mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 00:31:02 +00:00
migrate eth PoA pallet to frame v2 (#1091)
This commit is contained in:
committed by
Bastian Köcher
parent
239790fc72
commit
92b3a69126
@@ -128,7 +128,7 @@ impl MaybeLockFundsTransaction for EthTransaction {
|
|||||||
|
|
||||||
/// Prepares everything required to bench claim of funds locked by given transaction.
|
/// Prepares everything required to bench claim of funds locked by given transaction.
|
||||||
#[cfg(feature = "runtime-benchmarks")]
|
#[cfg(feature = "runtime-benchmarks")]
|
||||||
pub(crate) fn prepare_environment_for_claim<T: pallet_bridge_eth_poa::Config<I>, I: frame_support::traits::Instance>(
|
pub(crate) fn prepare_environment_for_claim<T: pallet_bridge_eth_poa::Config<I>, I: 'static>(
|
||||||
transactions: &[(RawTransaction, RawTransactionReceipt)],
|
transactions: &[(RawTransaction, RawTransactionReceipt)],
|
||||||
) -> bp_eth_poa::H256 {
|
) -> bp_eth_poa::H256 {
|
||||||
use bp_eth_poa::compute_merkle_root;
|
use bp_eth_poa::compute_merkle_root;
|
||||||
|
|||||||
@@ -1102,6 +1102,7 @@ impl_runtime_apis! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_benchmark!(params, batches, pallet_bridge_eth_poa, BridgeRialtoPoa);
|
||||||
add_benchmark!(
|
add_benchmark!(
|
||||||
params,
|
params,
|
||||||
batches,
|
batches,
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ use crate::test_utils::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use bp_eth_poa::{compute_merkle_root, U256};
|
use bp_eth_poa::{compute_merkle_root, U256};
|
||||||
use frame_benchmarking::benchmarks_instance;
|
use frame_benchmarking::benchmarks_instance_pallet;
|
||||||
use frame_system::RawOrigin;
|
use frame_system::RawOrigin;
|
||||||
|
|
||||||
benchmarks_instance! {
|
benchmarks_instance_pallet! {
|
||||||
// Benchmark `import_unsigned_header` extrinsic with the best possible conditions:
|
// Benchmark `import_unsigned_header` extrinsic with the best possible conditions:
|
||||||
// * Parent header is finalized.
|
// * Parent header is finalized.
|
||||||
// * New header doesn't require receipts.
|
// * New header doesn't require receipts.
|
||||||
@@ -153,7 +153,7 @@ benchmarks_instance! {
|
|||||||
let validators = validators(num_validators);
|
let validators = validators(num_validators);
|
||||||
|
|
||||||
// Want to prune eligible blocks between [0, n)
|
// Want to prune eligible blocks between [0, n)
|
||||||
BlocksToPrune::<I>::put(PruningRange {
|
BlocksToPrune::<T, I>::put(PruningRange {
|
||||||
oldest_unpruned_block: 0,
|
oldest_unpruned_block: 0,
|
||||||
oldest_block_to_keep: n as u64,
|
oldest_block_to_keep: n as u64,
|
||||||
});
|
});
|
||||||
@@ -172,8 +172,8 @@ benchmarks_instance! {
|
|||||||
let storage = BridgeStorage::<T, I>::new();
|
let storage = BridgeStorage::<T, I>::new();
|
||||||
let max_pruned: u64 = (n - 1) as _;
|
let max_pruned: u64 = (n - 1) as _;
|
||||||
assert_eq!(storage.best_block().0.number, (n + 1) as u64);
|
assert_eq!(storage.best_block().0.number, (n + 1) as u64);
|
||||||
assert!(HeadersByNumber::<I>::get(&0).is_none());
|
assert!(HeadersByNumber::<T, I>::get(&0).is_none());
|
||||||
assert!(HeadersByNumber::<I>::get(&max_pruned).is_none());
|
assert!(HeadersByNumber::<T, I>::get(&max_pruned).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The goal of this bench is to import a block which contains a transaction receipt. The receipt
|
// The goal of this bench is to import a block which contains a transaction receipt. The receipt
|
||||||
@@ -216,7 +216,7 @@ benchmarks_instance! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_bench<T: Config<I>, I: Instance>(num_validators: usize) -> AuraHeader {
|
fn initialize_bench<T: Config<I>, I: 'static>(num_validators: usize) -> AuraHeader {
|
||||||
// Initialize storage with some initial header
|
// Initialize storage with some initial header
|
||||||
let initial_header = build_genesis_header(&validator(0));
|
let initial_header = build_genesis_header(&validator(0));
|
||||||
let initial_difficulty = initial_header.difficulty;
|
let initial_difficulty = initial_header.difficulty;
|
||||||
|
|||||||
@@ -284,7 +284,6 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::mock::{insert_header, run_test, validator, validators_addresses, HeaderBuilder, TestRuntime};
|
use crate::mock::{insert_header, run_test, validator, validators_addresses, HeaderBuilder, TestRuntime};
|
||||||
use crate::{BridgeStorage, FinalityCache, HeaderToImport};
|
use crate::{BridgeStorage, FinalityCache, HeaderToImport};
|
||||||
use frame_support::StorageMap;
|
|
||||||
|
|
||||||
const TOTAL_VALIDATORS: usize = 5;
|
const TOTAL_VALIDATORS: usize = 5;
|
||||||
|
|
||||||
|
|||||||
@@ -176,9 +176,7 @@ mod tests {
|
|||||||
validators_change_receipt, HeaderBuilder, KeepSomeHeadersBehindBest, TestRuntime, GAS_LIMIT,
|
validators_change_receipt, HeaderBuilder, KeepSomeHeadersBehindBest, TestRuntime, GAS_LIMIT,
|
||||||
};
|
};
|
||||||
use crate::validators::ValidatorsSource;
|
use crate::validators::ValidatorsSource;
|
||||||
use crate::DefaultInstance;
|
|
||||||
use crate::{BlocksToPrune, BridgeStorage, Headers, PruningRange};
|
use crate::{BlocksToPrune, BridgeStorage, Headers, PruningRange};
|
||||||
use frame_support::{StorageMap, StorageValue};
|
|
||||||
use secp256k1::SecretKey;
|
use secp256k1::SecretKey;
|
||||||
|
|
||||||
const TOTAL_VALIDATORS: usize = 3;
|
const TOTAL_VALIDATORS: usize = 3;
|
||||||
@@ -367,7 +365,7 @@ mod tests {
|
|||||||
step += 3;
|
step += 3;
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
BlocksToPrune::<DefaultInstance>::get(),
|
BlocksToPrune::<TestRuntime, ()>::get(),
|
||||||
PruningRange {
|
PruningRange {
|
||||||
oldest_unpruned_block: 11,
|
oldest_unpruned_block: 11,
|
||||||
oldest_block_to_keep: 14,
|
oldest_block_to_keep: 14,
|
||||||
@@ -394,7 +392,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(finalized_blocks, expected_blocks);
|
assert_eq!(finalized_blocks, expected_blocks);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
BlocksToPrune::<DefaultInstance>::get(),
|
BlocksToPrune::<TestRuntime, ()>::get(),
|
||||||
PruningRange {
|
PruningRange {
|
||||||
oldest_unpruned_block: 15,
|
oldest_unpruned_block: 15,
|
||||||
oldest_block_to_keep: 15,
|
oldest_block_to_keep: 15,
|
||||||
|
|||||||
+204
-153
@@ -21,14 +21,8 @@
|
|||||||
use crate::finality::{CachedFinalityVotes, FinalityVotes};
|
use crate::finality::{CachedFinalityVotes, FinalityVotes};
|
||||||
use bp_eth_poa::{Address, AuraHeader, HeaderId, RawTransaction, RawTransactionReceipt, Receipt, H256, U256};
|
use bp_eth_poa::{Address, AuraHeader, HeaderId, RawTransaction, RawTransactionReceipt, Receipt, H256, U256};
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_support::{decl_module, decl_storage, traits::Get};
|
use frame_support::traits::Get;
|
||||||
use sp_runtime::{
|
use sp_runtime::RuntimeDebug;
|
||||||
transaction_validity::{
|
|
||||||
InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource, TransactionValidity,
|
|
||||||
UnknownTransaction, ValidTransaction,
|
|
||||||
},
|
|
||||||
RuntimeDebug,
|
|
||||||
};
|
|
||||||
use sp_std::{cmp::Ord, collections::btree_map::BTreeMap, prelude::*};
|
use sp_std::{cmp::Ord, collections::btree_map::BTreeMap, prelude::*};
|
||||||
|
|
||||||
pub use validators::{ValidatorsConfiguration, ValidatorsSource};
|
pub use validators::{ValidatorsConfiguration, ValidatorsSource};
|
||||||
@@ -369,8 +363,16 @@ impl<AccountId> OnHeadersSubmitted<AccountId> for () {
|
|||||||
fn on_valid_headers_finalized(_submitter: AccountId, _finalized: u64) {}
|
fn on_valid_headers_finalized(_submitter: AccountId, _finalized: u64) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The module configuration trait.
|
pub use pallet::*;
|
||||||
pub trait Config<I = DefaultInstance>: frame_system::Config {
|
|
||||||
|
#[frame_support::pallet]
|
||||||
|
pub mod pallet {
|
||||||
|
use super::*;
|
||||||
|
use frame_support::pallet_prelude::*;
|
||||||
|
use frame_system::pallet_prelude::*;
|
||||||
|
|
||||||
|
#[pallet::config]
|
||||||
|
pub trait Config<I: 'static = ()>: frame_system::Config {
|
||||||
/// Aura configuration.
|
/// Aura configuration.
|
||||||
type AuraConfiguration: Get<AuraConfiguration>;
|
type AuraConfiguration: Get<AuraConfiguration>;
|
||||||
/// Validators configuration.
|
/// Validators configuration.
|
||||||
@@ -390,13 +392,24 @@ pub trait Config<I = DefaultInstance>: frame_system::Config {
|
|||||||
|
|
||||||
/// Handler for headers submission result.
|
/// Handler for headers submission result.
|
||||||
type OnHeadersSubmitted: OnHeadersSubmitted<Self::AccountId>;
|
type OnHeadersSubmitted: OnHeadersSubmitted<Self::AccountId>;
|
||||||
}
|
}
|
||||||
|
|
||||||
decl_module! {
|
#[pallet::pallet]
|
||||||
pub struct Module<T: Config<I>, I: Instance = DefaultInstance> for enum Call where origin: T::Origin {
|
#[pallet::generate_store(pub(super) trait Store)]
|
||||||
|
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
|
||||||
|
|
||||||
|
#[pallet::hooks]
|
||||||
|
impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> {}
|
||||||
|
|
||||||
|
#[pallet::call]
|
||||||
|
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||||
/// Import single Aura header. Requires transaction to be **UNSIGNED**.
|
/// Import single Aura header. Requires transaction to be **UNSIGNED**.
|
||||||
#[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
|
#[pallet::weight(0)] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
|
||||||
pub fn import_unsigned_header(origin, header: AuraHeader, receipts: Option<Vec<Receipt>>) {
|
pub fn import_unsigned_header(
|
||||||
|
origin: OriginFor<T>,
|
||||||
|
header: AuraHeader,
|
||||||
|
receipts: Option<Vec<Receipt>>,
|
||||||
|
) -> DispatchResult {
|
||||||
frame_system::ensure_none(origin)?;
|
frame_system::ensure_none(origin)?;
|
||||||
|
|
||||||
import::import_header(
|
import::import_header(
|
||||||
@@ -408,7 +421,10 @@ decl_module! {
|
|||||||
header,
|
header,
|
||||||
&T::ChainTime::default(),
|
&T::ChainTime::default(),
|
||||||
receipts,
|
receipts,
|
||||||
).map_err(|e| e.msg())?;
|
)
|
||||||
|
.map_err(|e| e.msg())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Import Aura chain headers in a single **SIGNED** transaction.
|
/// Import Aura chain headers in a single **SIGNED** transaction.
|
||||||
@@ -417,8 +433,11 @@ decl_module! {
|
|||||||
///
|
///
|
||||||
/// This should be used with caution - passing too many headers could lead to
|
/// This should be used with caution - passing too many headers could lead to
|
||||||
/// enormous block production/import time.
|
/// enormous block production/import time.
|
||||||
#[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
|
#[pallet::weight(0)] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
|
||||||
pub fn import_signed_headers(origin, headers_with_receipts: Vec<(AuraHeader, Option<Vec<Receipt>>)>) {
|
pub fn import_signed_headers(
|
||||||
|
origin: OriginFor<T>,
|
||||||
|
headers_with_receipts: Vec<(AuraHeader, Option<Vec<Receipt>>)>,
|
||||||
|
) -> DispatchResult {
|
||||||
let submitter = frame_system::ensure_signed(origin)?;
|
let submitter = frame_system::ensure_signed(origin)?;
|
||||||
let mut finalized_headers = BTreeMap::new();
|
let mut finalized_headers = BTreeMap::new();
|
||||||
let import_result = import::import_headers(
|
let import_result = import::import_headers(
|
||||||
@@ -435,77 +454,147 @@ decl_module! {
|
|||||||
// if we have finalized some headers, we will reward their submitters even
|
// if we have finalized some headers, we will reward their submitters even
|
||||||
// if current submitter has provided some invalid headers
|
// if current submitter has provided some invalid headers
|
||||||
for (f_submitter, f_count) in finalized_headers {
|
for (f_submitter, f_count) in finalized_headers {
|
||||||
T::OnHeadersSubmitted::on_valid_headers_finalized(
|
T::OnHeadersSubmitted::on_valid_headers_finalized(f_submitter, f_count);
|
||||||
f_submitter,
|
|
||||||
f_count,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// now track/penalize current submitter for providing new headers
|
// now track/penalize current submitter for providing new headers
|
||||||
match import_result {
|
match import_result {
|
||||||
Ok((useful, useless)) =>
|
Ok((useful, useless)) => T::OnHeadersSubmitted::on_valid_headers_submitted(submitter, useful, useless),
|
||||||
T::OnHeadersSubmitted::on_valid_headers_submitted(submitter, useful, useless),
|
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
// even though we may have accept some headers, we do not want to reward someone
|
// even though we may have accept some headers, we do not want to reward someone
|
||||||
// who provides invalid headers
|
// who provides invalid headers
|
||||||
T::OnHeadersSubmitted::on_invalid_headers_submitted(submitter);
|
T::OnHeadersSubmitted::on_invalid_headers_submitted(submitter);
|
||||||
return Err(error.msg().into());
|
return Err(error.msg().into());
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decl_storage! {
|
Ok(())
|
||||||
trait Store for Pallet<T: Config<I>, I: Instance = DefaultInstance> as Bridge {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pallet::validate_unsigned]
|
||||||
|
impl<T: Config<I>, I: 'static> ValidateUnsigned for Pallet<T, I> {
|
||||||
|
type Call = Call<T, I>;
|
||||||
|
|
||||||
|
fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity {
|
||||||
|
match *call {
|
||||||
|
Self::Call::import_unsigned_header(ref header, ref receipts) => {
|
||||||
|
let accept_result = verification::accept_aura_header_into_pool(
|
||||||
|
&BridgeStorage::<T, I>::new(),
|
||||||
|
&T::AuraConfiguration::get(),
|
||||||
|
&T::ValidatorsConfiguration::get(),
|
||||||
|
&pool_configuration(),
|
||||||
|
header,
|
||||||
|
&T::ChainTime::default(),
|
||||||
|
receipts.as_ref(),
|
||||||
|
);
|
||||||
|
|
||||||
|
match accept_result {
|
||||||
|
Ok((requires, provides)) => Ok(ValidTransaction {
|
||||||
|
priority: TransactionPriority::max_value(),
|
||||||
|
requires,
|
||||||
|
provides,
|
||||||
|
longevity: TransactionLongevity::max_value(),
|
||||||
|
propagate: true,
|
||||||
|
}),
|
||||||
|
// UnsignedTooFarInTheFuture is the special error code used to limit
|
||||||
|
// number of transactions in the pool - we do not want to ban transaction
|
||||||
|
// in this case (see verification.rs for details)
|
||||||
|
Err(error::Error::UnsignedTooFarInTheFuture) => {
|
||||||
|
UnknownTransaction::Custom(error::Error::UnsignedTooFarInTheFuture.code()).into()
|
||||||
|
}
|
||||||
|
Err(error) => InvalidTransaction::Custom(error.code()).into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => InvalidTransaction::Call.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Best known block.
|
/// Best known block.
|
||||||
BestBlock: (HeaderId, U256);
|
#[pallet::storage]
|
||||||
|
pub(super) type BestBlock<T: Config<I>, I: 'static = ()> = StorageValue<_, (HeaderId, U256), ValueQuery>;
|
||||||
|
|
||||||
/// Best finalized block.
|
/// Best finalized block.
|
||||||
FinalizedBlock: HeaderId;
|
#[pallet::storage]
|
||||||
|
pub(super) type FinalizedBlock<T: Config<I>, I: 'static = ()> = StorageValue<_, HeaderId, ValueQuery>;
|
||||||
|
|
||||||
/// Range of blocks that we want to prune.
|
/// Range of blocks that we want to prune.
|
||||||
BlocksToPrune: PruningRange;
|
#[pallet::storage]
|
||||||
|
pub(super) type BlocksToPrune<T: Config<I>, I: 'static = ()> = StorageValue<_, PruningRange, ValueQuery>;
|
||||||
|
|
||||||
/// Map of imported headers by hash.
|
/// Map of imported headers by hash.
|
||||||
Headers: map hasher(identity) H256 => Option<StoredHeader<T::AccountId>>;
|
#[pallet::storage]
|
||||||
|
pub(super) type Headers<T: Config<I>, I: 'static = ()> = StorageMap<_, Identity, H256, StoredHeader<T::AccountId>>;
|
||||||
|
|
||||||
/// Map of imported header hashes by number.
|
/// Map of imported header hashes by number.
|
||||||
HeadersByNumber: map hasher(blake2_128_concat) u64 => Option<Vec<H256>>;
|
#[pallet::storage]
|
||||||
|
pub(super) type HeadersByNumber<T: Config<I>, I: 'static = ()> = StorageMap<_, Blake2_128Concat, u64, Vec<H256>>;
|
||||||
|
|
||||||
/// Map of cached finality data by header hash.
|
/// Map of cached finality data by header hash.
|
||||||
FinalityCache: map hasher(identity) H256 => Option<FinalityVotes<T::AccountId>>;
|
#[pallet::storage]
|
||||||
|
pub(super) type FinalityCache<T: Config<I>, I: 'static = ()> =
|
||||||
|
StorageMap<_, Identity, H256, FinalityVotes<T::AccountId>>;
|
||||||
|
|
||||||
/// The ID of next validator set.
|
/// The ID of next validator set.
|
||||||
NextValidatorsSetId: u64;
|
#[pallet::storage]
|
||||||
|
pub(super) type NextValidatorsSetId<T: Config<I>, I: 'static = ()> = StorageValue<_, u64, ValueQuery>;
|
||||||
|
|
||||||
/// Map of validators sets by their id.
|
/// Map of validators sets by their id.
|
||||||
ValidatorsSets: map hasher(twox_64_concat) u64 => Option<ValidatorsSet>;
|
#[pallet::storage]
|
||||||
|
pub(super) type ValidatorsSets<T: Config<I>, I: 'static = ()> = StorageMap<_, Twox64Concat, u64, ValidatorsSet>;
|
||||||
|
|
||||||
/// Validators sets reference count. Each header that is authored by this set increases
|
/// Validators sets reference count. Each header that is authored by this set increases
|
||||||
/// the reference count. When we prune this header, we decrease the reference count.
|
/// the reference count. When we prune this header, we decrease the reference count.
|
||||||
/// When it reaches zero, we are free to prune validator set as well.
|
/// When it reaches zero, we are free to prune validator set as well.
|
||||||
ValidatorsSetsRc: map hasher(twox_64_concat) u64 => Option<u64>;
|
#[pallet::storage]
|
||||||
|
pub(super) type ValidatorsSetsRc<T: Config<I>, I: 'static = ()> = StorageMap<_, Twox64Concat, u64, u64>;
|
||||||
|
|
||||||
/// Map of validators set changes scheduled by given header.
|
/// Map of validators set changes scheduled by given header.
|
||||||
ScheduledChanges: map hasher(identity) H256 => Option<AuraScheduledChange>;
|
#[pallet::storage]
|
||||||
|
pub(super) type ScheduledChanges<T: Config<I>, I: 'static = ()> =
|
||||||
|
StorageMap<_, Identity, H256, AuraScheduledChange>;
|
||||||
|
|
||||||
|
#[pallet::genesis_config]
|
||||||
|
pub struct GenesisConfig {
|
||||||
|
/// PoA header to start with.
|
||||||
|
pub initial_header: AuraHeader,
|
||||||
|
/// Initial PoA chain difficulty.
|
||||||
|
pub initial_difficulty: U256,
|
||||||
|
/// Initial PoA validators set.
|
||||||
|
pub initial_validators: Vec<Address>,
|
||||||
}
|
}
|
||||||
add_extra_genesis {
|
|
||||||
config(initial_header): AuraHeader;
|
#[cfg(feature = "std")]
|
||||||
config(initial_difficulty): U256;
|
impl Default for GenesisConfig {
|
||||||
config(initial_validators): Vec<Address>;
|
fn default() -> Self {
|
||||||
build(|config| {
|
Self {
|
||||||
|
initial_header: Default::default(),
|
||||||
|
initial_difficulty: Default::default(),
|
||||||
|
initial_validators: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pallet::genesis_build]
|
||||||
|
impl<T: Config<I>, I: 'static> GenesisBuild<T, I> for GenesisConfig {
|
||||||
|
fn build(&self) {
|
||||||
// the initial blocks should be selected so that:
|
// the initial blocks should be selected so that:
|
||||||
// 1) it doesn't signal validators changes;
|
// 1) it doesn't signal validators changes;
|
||||||
// 2) there are no scheduled validators changes from previous blocks;
|
// 2) there are no scheduled validators changes from previous blocks;
|
||||||
// 3) (implied) all direct children of initial block are authored by the same validators set.
|
// 3) (implied) all direct children of initial block are authored by the same validators set.
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!config.initial_validators.is_empty(),
|
!self.initial_validators.is_empty(),
|
||||||
"Initial validators set can't be empty",
|
"Initial validators set can't be empty",
|
||||||
);
|
);
|
||||||
|
|
||||||
initialize_storage::<T, I>(
|
initialize_storage::<T, I>(&self.initial_header, self.initial_difficulty, &self.initial_validators);
|
||||||
&config.initial_header,
|
}
|
||||||
config.initial_difficulty,
|
|
||||||
&config.initial_validators,
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config<I>, I: Instance> Pallet<T, I> {
|
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||||
/// Returns number and hash of the best block known to the bridge module.
|
/// Returns number and hash of the best block known to the bridge module.
|
||||||
/// The caller should only submit `import_header` transaction that makes
|
/// The caller should only submit `import_header` transaction that makes
|
||||||
/// (or leads to making) other header the best one.
|
/// (or leads to making) other header the best one.
|
||||||
@@ -542,49 +631,11 @@ impl<T: Config<I>, I: Instance> Pallet<T, I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config<I>, I: Instance> frame_support::unsigned::ValidateUnsigned for Pallet<T, I> {
|
|
||||||
type Call = Call<T, I>;
|
|
||||||
|
|
||||||
fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity {
|
|
||||||
match *call {
|
|
||||||
Self::Call::import_unsigned_header(ref header, ref receipts) => {
|
|
||||||
let accept_result = verification::accept_aura_header_into_pool(
|
|
||||||
&BridgeStorage::<T, I>::new(),
|
|
||||||
&T::AuraConfiguration::get(),
|
|
||||||
&T::ValidatorsConfiguration::get(),
|
|
||||||
&pool_configuration(),
|
|
||||||
header,
|
|
||||||
&T::ChainTime::default(),
|
|
||||||
receipts.as_ref(),
|
|
||||||
);
|
|
||||||
|
|
||||||
match accept_result {
|
|
||||||
Ok((requires, provides)) => Ok(ValidTransaction {
|
|
||||||
priority: TransactionPriority::max_value(),
|
|
||||||
requires,
|
|
||||||
provides,
|
|
||||||
longevity: TransactionLongevity::max_value(),
|
|
||||||
propagate: true,
|
|
||||||
}),
|
|
||||||
// UnsignedTooFarInTheFuture is the special error code used to limit
|
|
||||||
// number of transactions in the pool - we do not want to ban transaction
|
|
||||||
// in this case (see verification.rs for details)
|
|
||||||
Err(error::Error::UnsignedTooFarInTheFuture) => {
|
|
||||||
UnknownTransaction::Custom(error::Error::UnsignedTooFarInTheFuture.code()).into()
|
|
||||||
}
|
|
||||||
Err(error) => InvalidTransaction::Custom(error.code()).into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => InvalidTransaction::Call.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Runtime bridge storage.
|
/// Runtime bridge storage.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct BridgeStorage<T, I = DefaultInstance>(sp_std::marker::PhantomData<(T, I)>);
|
pub struct BridgeStorage<T, I: 'static = ()>(sp_std::marker::PhantomData<(T, I)>);
|
||||||
|
|
||||||
impl<T: Config<I>, I: Instance> BridgeStorage<T, I> {
|
impl<T: Config<I>, I: 'static> BridgeStorage<T, I> {
|
||||||
/// Create new BridgeStorage.
|
/// Create new BridgeStorage.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
BridgeStorage(sp_std::marker::PhantomData::<(T, I)>::default())
|
BridgeStorage(sp_std::marker::PhantomData::<(T, I)>::default())
|
||||||
@@ -592,7 +643,7 @@ impl<T: Config<I>, I: Instance> BridgeStorage<T, I> {
|
|||||||
|
|
||||||
/// Prune old blocks.
|
/// Prune old blocks.
|
||||||
fn prune_blocks(&self, mut max_blocks_to_prune: u64, finalized_number: u64, prune_end: u64) {
|
fn prune_blocks(&self, mut max_blocks_to_prune: u64, finalized_number: u64, prune_end: u64) {
|
||||||
let pruning_range = BlocksToPrune::<I>::get();
|
let pruning_range = BlocksToPrune::<T, I>::get();
|
||||||
let mut new_pruning_range = pruning_range.clone();
|
let mut new_pruning_range = pruning_range.clone();
|
||||||
|
|
||||||
// update oldest block we want to keep
|
// update oldest block we want to keep
|
||||||
@@ -611,7 +662,7 @@ impl<T: Config<I>, I: Instance> BridgeStorage<T, I> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read hashes of blocks with given number and try to prune these blocks
|
// read hashes of blocks with given number and try to prune these blocks
|
||||||
let blocks_at_number = HeadersByNumber::<I>::take(number);
|
let blocks_at_number = HeadersByNumber::<T, I>::take(number);
|
||||||
if let Some(mut blocks_at_number) = blocks_at_number {
|
if let Some(mut blocks_at_number) = blocks_at_number {
|
||||||
self.prune_blocks_by_hashes(
|
self.prune_blocks_by_hashes(
|
||||||
&mut max_blocks_to_prune,
|
&mut max_blocks_to_prune,
|
||||||
@@ -622,7 +673,7 @@ impl<T: Config<I>, I: Instance> BridgeStorage<T, I> {
|
|||||||
|
|
||||||
// if we haven't pruned all blocks, remember unpruned
|
// if we haven't pruned all blocks, remember unpruned
|
||||||
if !blocks_at_number.is_empty() {
|
if !blocks_at_number.is_empty() {
|
||||||
HeadersByNumber::<I>::insert(number, blocks_at_number);
|
HeadersByNumber::<T, I>::insert(number, blocks_at_number);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -638,7 +689,7 @@ impl<T: Config<I>, I: Instance> BridgeStorage<T, I> {
|
|||||||
|
|
||||||
// update pruning range in storage
|
// update pruning range in storage
|
||||||
if pruning_range != new_pruning_range {
|
if pruning_range != new_pruning_range {
|
||||||
BlocksToPrune::<I>::put(new_pruning_range);
|
BlocksToPrune::<T, I>::put(new_pruning_range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,7 +702,7 @@ impl<T: Config<I>, I: Instance> BridgeStorage<T, I> {
|
|||||||
blocks_at_number: &mut Vec<H256>,
|
blocks_at_number: &mut Vec<H256>,
|
||||||
) {
|
) {
|
||||||
// ensure that unfinalized headers we want to prune do not have scheduled changes
|
// ensure that unfinalized headers we want to prune do not have scheduled changes
|
||||||
if number > finalized_number && blocks_at_number.iter().any(ScheduledChanges::<I>::contains_key) {
|
if number > finalized_number && blocks_at_number.iter().any(ScheduledChanges::<T, I>::contains_key) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -665,10 +716,10 @@ impl<T: Config<I>, I: Instance> BridgeStorage<T, I> {
|
|||||||
hash,
|
hash,
|
||||||
);
|
);
|
||||||
|
|
||||||
ScheduledChanges::<I>::remove(hash);
|
ScheduledChanges::<T, I>::remove(hash);
|
||||||
FinalityCache::<T, I>::remove(hash);
|
FinalityCache::<T, I>::remove(hash);
|
||||||
if let Some(header) = header {
|
if let Some(header) = header {
|
||||||
ValidatorsSetsRc::<I>::mutate(header.next_validators_set_id, |rc| match *rc {
|
ValidatorsSetsRc::<T, I>::mutate(header.next_validators_set_id, |rc| match *rc {
|
||||||
Some(rc) if rc > 1 => Some(rc - 1),
|
Some(rc) if rc > 1 => Some(rc - 1),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
@@ -683,15 +734,15 @@ impl<T: Config<I>, I: Instance> BridgeStorage<T, I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config<I>, I: Instance> Storage for BridgeStorage<T, I> {
|
impl<T: Config<I>, I: 'static> Storage for BridgeStorage<T, I> {
|
||||||
type Submitter = T::AccountId;
|
type Submitter = T::AccountId;
|
||||||
|
|
||||||
fn best_block(&self) -> (HeaderId, U256) {
|
fn best_block(&self) -> (HeaderId, U256) {
|
||||||
BestBlock::<I>::get()
|
BestBlock::<T, I>::get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalized_block(&self) -> HeaderId {
|
fn finalized_block(&self) -> HeaderId {
|
||||||
FinalizedBlock::<I>::get()
|
FinalizedBlock::<T, I>::get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header(&self, hash: &H256) -> Option<(AuraHeader, Option<Self::Submitter>)> {
|
fn header(&self, hash: &H256) -> Option<(AuraHeader, Option<Self::Submitter>)> {
|
||||||
@@ -750,9 +801,9 @@ impl<T: Config<I>, I: Instance> Storage for BridgeStorage<T, I> {
|
|||||||
parent_hash: &H256,
|
parent_hash: &H256,
|
||||||
) -> Option<ImportContext<Self::Submitter>> {
|
) -> Option<ImportContext<Self::Submitter>> {
|
||||||
Headers::<T, I>::get(parent_hash).map(|parent_header| {
|
Headers::<T, I>::get(parent_hash).map(|parent_header| {
|
||||||
let validators_set = ValidatorsSets::<I>::get(parent_header.next_validators_set_id)
|
let validators_set = ValidatorsSets::<T, I>::get(parent_header.next_validators_set_id)
|
||||||
.expect("validators set is only pruned when last ref is pruned; there is a ref; qed");
|
.expect("validators set is only pruned when last ref is pruned; there is a ref; qed");
|
||||||
let parent_scheduled_change = ScheduledChanges::<I>::get(parent_hash);
|
let parent_scheduled_change = ScheduledChanges::<T, I>::get(parent_hash);
|
||||||
ImportContext {
|
ImportContext {
|
||||||
submitter,
|
submitter,
|
||||||
parent_hash: *parent_hash,
|
parent_hash: *parent_hash,
|
||||||
@@ -767,15 +818,15 @@ impl<T: Config<I>, I: Instance> Storage for BridgeStorage<T, I> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn scheduled_change(&self, hash: &H256) -> Option<AuraScheduledChange> {
|
fn scheduled_change(&self, hash: &H256) -> Option<AuraScheduledChange> {
|
||||||
ScheduledChanges::<I>::get(hash)
|
ScheduledChanges::<T, I>::get(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_header(&mut self, header: HeaderToImport<Self::Submitter>) {
|
fn insert_header(&mut self, header: HeaderToImport<Self::Submitter>) {
|
||||||
if header.is_best {
|
if header.is_best {
|
||||||
BestBlock::<I>::put((header.id, header.total_difficulty));
|
BestBlock::<T, I>::put((header.id, header.total_difficulty));
|
||||||
}
|
}
|
||||||
if let Some(scheduled_change) = header.scheduled_change {
|
if let Some(scheduled_change) = header.scheduled_change {
|
||||||
ScheduledChanges::<I>::insert(
|
ScheduledChanges::<T, I>::insert(
|
||||||
&header.id.hash,
|
&header.id.hash,
|
||||||
AuraScheduledChange {
|
AuraScheduledChange {
|
||||||
validators: scheduled_change,
|
validators: scheduled_change,
|
||||||
@@ -785,12 +836,12 @@ impl<T: Config<I>, I: Instance> Storage for BridgeStorage<T, I> {
|
|||||||
}
|
}
|
||||||
let next_validators_set_id = match header.enacted_change {
|
let next_validators_set_id = match header.enacted_change {
|
||||||
Some(enacted_change) => {
|
Some(enacted_change) => {
|
||||||
let next_validators_set_id = NextValidatorsSetId::<I>::mutate(|set_id| {
|
let next_validators_set_id = NextValidatorsSetId::<T, I>::mutate(|set_id| {
|
||||||
let next_set_id = *set_id;
|
let next_set_id = *set_id;
|
||||||
*set_id += 1;
|
*set_id += 1;
|
||||||
next_set_id
|
next_set_id
|
||||||
});
|
});
|
||||||
ValidatorsSets::<I>::insert(
|
ValidatorsSets::<T, I>::insert(
|
||||||
next_validators_set_id,
|
next_validators_set_id,
|
||||||
ValidatorsSet {
|
ValidatorsSet {
|
||||||
validators: enacted_change.validators,
|
validators: enacted_change.validators,
|
||||||
@@ -798,11 +849,11 @@ impl<T: Config<I>, I: Instance> Storage for BridgeStorage<T, I> {
|
|||||||
signal_block: enacted_change.signal_block,
|
signal_block: enacted_change.signal_block,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
ValidatorsSetsRc::<I>::insert(next_validators_set_id, 1);
|
ValidatorsSetsRc::<T, I>::insert(next_validators_set_id, 1);
|
||||||
next_validators_set_id
|
next_validators_set_id
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
ValidatorsSetsRc::<I>::mutate(header.context.validators_set_id, |rc| {
|
ValidatorsSetsRc::<T, I>::mutate(header.context.validators_set_id, |rc| {
|
||||||
*rc = Some(rc.map(|rc| rc + 1).unwrap_or(1));
|
*rc = Some(rc.map(|rc| rc + 1).unwrap_or(1));
|
||||||
*rc
|
*rc
|
||||||
});
|
});
|
||||||
@@ -826,7 +877,7 @@ impl<T: Config<I>, I: Instance> Storage for BridgeStorage<T, I> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let last_signal_block = header.context.last_signal_block();
|
let last_signal_block = header.context.last_signal_block();
|
||||||
HeadersByNumber::<I>::append(header.id.number, header.id.hash);
|
HeadersByNumber::<T, I>::append(header.id.number, header.id.hash);
|
||||||
Headers::<T, I>::insert(
|
Headers::<T, I>::insert(
|
||||||
&header.id.hash,
|
&header.id.hash,
|
||||||
StoredHeader {
|
StoredHeader {
|
||||||
@@ -844,7 +895,7 @@ impl<T: Config<I>, I: Instance> Storage for BridgeStorage<T, I> {
|
|||||||
let finalized_number = finalized
|
let finalized_number = finalized
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|f| f.number)
|
.map(|f| f.number)
|
||||||
.unwrap_or_else(|| FinalizedBlock::<I>::get().number);
|
.unwrap_or_else(|| FinalizedBlock::<T, I>::get().number);
|
||||||
if let Some(finalized) = finalized {
|
if let Some(finalized) = finalized {
|
||||||
log::trace!(
|
log::trace!(
|
||||||
target: "runtime",
|
target: "runtime",
|
||||||
@@ -853,7 +904,7 @@ impl<T: Config<I>, I: Instance> Storage for BridgeStorage<T, I> {
|
|||||||
finalized.hash,
|
finalized.hash,
|
||||||
);
|
);
|
||||||
|
|
||||||
FinalizedBlock::<I>::put(finalized);
|
FinalizedBlock::<T, I>::put(finalized);
|
||||||
}
|
}
|
||||||
|
|
||||||
// and now prune headers if we need to
|
// and now prune headers if we need to
|
||||||
@@ -863,7 +914,7 @@ impl<T: Config<I>, I: Instance> Storage for BridgeStorage<T, I> {
|
|||||||
|
|
||||||
/// Initialize storage.
|
/// Initialize storage.
|
||||||
#[cfg(any(feature = "std", feature = "runtime-benchmarks"))]
|
#[cfg(any(feature = "std", feature = "runtime-benchmarks"))]
|
||||||
pub(crate) fn initialize_storage<T: Config<I>, I: Instance>(
|
pub(crate) fn initialize_storage<T: Config<I>, I: 'static>(
|
||||||
initial_header: &AuraHeader,
|
initial_header: &AuraHeader,
|
||||||
initial_difficulty: U256,
|
initial_difficulty: U256,
|
||||||
initial_validators: &[Address],
|
initial_validators: &[Address],
|
||||||
@@ -880,13 +931,13 @@ pub(crate) fn initialize_storage<T: Config<I>, I: Instance>(
|
|||||||
number: initial_header.number,
|
number: initial_header.number,
|
||||||
hash: initial_hash,
|
hash: initial_hash,
|
||||||
};
|
};
|
||||||
BestBlock::<I>::put((initial_id, initial_difficulty));
|
BestBlock::<T, I>::put((initial_id, initial_difficulty));
|
||||||
FinalizedBlock::<I>::put(initial_id);
|
FinalizedBlock::<T, I>::put(initial_id);
|
||||||
BlocksToPrune::<I>::put(PruningRange {
|
BlocksToPrune::<T, I>::put(PruningRange {
|
||||||
oldest_unpruned_block: initial_header.number,
|
oldest_unpruned_block: initial_header.number,
|
||||||
oldest_block_to_keep: initial_header.number,
|
oldest_block_to_keep: initial_header.number,
|
||||||
});
|
});
|
||||||
HeadersByNumber::<I>::insert(initial_header.number, vec![initial_hash]);
|
HeadersByNumber::<T, I>::insert(initial_header.number, vec![initial_hash]);
|
||||||
Headers::<T, I>::insert(
|
Headers::<T, I>::insert(
|
||||||
initial_hash,
|
initial_hash,
|
||||||
StoredHeader {
|
StoredHeader {
|
||||||
@@ -897,8 +948,8 @@ pub(crate) fn initialize_storage<T: Config<I>, I: Instance>(
|
|||||||
last_signal_block: None,
|
last_signal_block: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
NextValidatorsSetId::<I>::put(1);
|
NextValidatorsSetId::<T, I>::put(1);
|
||||||
ValidatorsSets::<I>::insert(
|
ValidatorsSets::<T, I>::insert(
|
||||||
0,
|
0,
|
||||||
ValidatorsSet {
|
ValidatorsSet {
|
||||||
validators: initial_validators.to_vec(),
|
validators: initial_validators.to_vec(),
|
||||||
@@ -906,7 +957,7 @@ pub(crate) fn initialize_storage<T: Config<I>, I: Instance>(
|
|||||||
enact_block: initial_id,
|
enact_block: initial_id,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
ValidatorsSetsRc::<I>::insert(0, 1);
|
ValidatorsSetsRc::<T, I>::insert(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verify that transaction is included into given finalized block.
|
/// Verify that transaction is included into given finalized block.
|
||||||
@@ -1112,7 +1163,7 @@ pub(crate) mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if i == 7 && j == 1 {
|
if i == 7 && j == 1 {
|
||||||
ScheduledChanges::<DefaultInstance>::insert(
|
ScheduledChanges::<TestRuntime, ()>::insert(
|
||||||
hash,
|
hash,
|
||||||
AuraScheduledChange {
|
AuraScheduledChange {
|
||||||
validators: validators_addresses(5),
|
validators: validators_addresses(5),
|
||||||
@@ -1121,7 +1172,7 @@ pub(crate) mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HeadersByNumber::<DefaultInstance>::insert(i, headers_by_number);
|
HeadersByNumber::<TestRuntime, ()>::insert(i, headers_by_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
f(BridgeStorage::new())
|
f(BridgeStorage::new())
|
||||||
@@ -1131,16 +1182,16 @@ pub(crate) mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn blocks_are_not_pruned_if_range_is_empty() {
|
fn blocks_are_not_pruned_if_range_is_empty() {
|
||||||
with_headers_to_prune(|storage| {
|
with_headers_to_prune(|storage| {
|
||||||
BlocksToPrune::<DefaultInstance>::put(PruningRange {
|
BlocksToPrune::<TestRuntime, ()>::put(PruningRange {
|
||||||
oldest_unpruned_block: 5,
|
oldest_unpruned_block: 5,
|
||||||
oldest_block_to_keep: 5,
|
oldest_block_to_keep: 5,
|
||||||
});
|
});
|
||||||
|
|
||||||
// try to prune blocks [5; 10)
|
// try to prune blocks [5; 10)
|
||||||
storage.prune_blocks(0xFFFF, 10, 5);
|
storage.prune_blocks(0xFFFF, 10, 5);
|
||||||
assert_eq!(HeadersByNumber::<DefaultInstance>::get(&5).unwrap().len(), 5);
|
assert_eq!(HeadersByNumber::<TestRuntime, ()>::get(&5).unwrap().len(), 5);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
BlocksToPrune::<DefaultInstance>::get(),
|
BlocksToPrune::<TestRuntime, ()>::get(),
|
||||||
PruningRange {
|
PruningRange {
|
||||||
oldest_unpruned_block: 5,
|
oldest_unpruned_block: 5,
|
||||||
oldest_block_to_keep: 5,
|
oldest_block_to_keep: 5,
|
||||||
@@ -1152,7 +1203,7 @@ pub(crate) mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn blocks_to_prune_never_shrinks_from_the_end() {
|
fn blocks_to_prune_never_shrinks_from_the_end() {
|
||||||
with_headers_to_prune(|storage| {
|
with_headers_to_prune(|storage| {
|
||||||
BlocksToPrune::<DefaultInstance>::put(PruningRange {
|
BlocksToPrune::<TestRuntime, ()>::put(PruningRange {
|
||||||
oldest_unpruned_block: 0,
|
oldest_unpruned_block: 0,
|
||||||
oldest_block_to_keep: 5,
|
oldest_block_to_keep: 5,
|
||||||
});
|
});
|
||||||
@@ -1160,7 +1211,7 @@ pub(crate) mod tests {
|
|||||||
// try to prune blocks [5; 10)
|
// try to prune blocks [5; 10)
|
||||||
storage.prune_blocks(0xFFFF, 10, 3);
|
storage.prune_blocks(0xFFFF, 10, 3);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
BlocksToPrune::<DefaultInstance>::get(),
|
BlocksToPrune::<TestRuntime, ()>::get(),
|
||||||
PruningRange {
|
PruningRange {
|
||||||
oldest_unpruned_block: 5,
|
oldest_unpruned_block: 5,
|
||||||
oldest_block_to_keep: 5,
|
oldest_block_to_keep: 5,
|
||||||
@@ -1174,12 +1225,12 @@ pub(crate) mod tests {
|
|||||||
with_headers_to_prune(|storage| {
|
with_headers_to_prune(|storage| {
|
||||||
// try to prune blocks [0; 10)
|
// try to prune blocks [0; 10)
|
||||||
storage.prune_blocks(0, 10, 10);
|
storage.prune_blocks(0, 10, 10);
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&0).is_some());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&0).is_some());
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&1).is_some());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&1).is_some());
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&2).is_some());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&2).is_some());
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&3).is_some());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&3).is_some());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
BlocksToPrune::<DefaultInstance>::get(),
|
BlocksToPrune::<TestRuntime, ()>::get(),
|
||||||
PruningRange {
|
PruningRange {
|
||||||
oldest_unpruned_block: 0,
|
oldest_unpruned_block: 0,
|
||||||
oldest_block_to_keep: 10,
|
oldest_block_to_keep: 10,
|
||||||
@@ -1194,13 +1245,13 @@ pub(crate) mod tests {
|
|||||||
// try to prune blocks [0; 10)
|
// try to prune blocks [0; 10)
|
||||||
storage.prune_blocks(7, 10, 10);
|
storage.prune_blocks(7, 10, 10);
|
||||||
// 1 headers with number = 0 is pruned (1 total)
|
// 1 headers with number = 0 is pruned (1 total)
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&0).is_none());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&0).is_none());
|
||||||
// 5 headers with number = 1 are pruned (6 total)
|
// 5 headers with number = 1 are pruned (6 total)
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&1).is_none());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&1).is_none());
|
||||||
// 1 header with number = 2 are pruned (7 total)
|
// 1 header with number = 2 are pruned (7 total)
|
||||||
assert_eq!(HeadersByNumber::<DefaultInstance>::get(&2).unwrap().len(), 4);
|
assert_eq!(HeadersByNumber::<TestRuntime, ()>::get(&2).unwrap().len(), 4);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
BlocksToPrune::<DefaultInstance>::get(),
|
BlocksToPrune::<TestRuntime, ()>::get(),
|
||||||
PruningRange {
|
PruningRange {
|
||||||
oldest_unpruned_block: 2,
|
oldest_unpruned_block: 2,
|
||||||
oldest_block_to_keep: 10,
|
oldest_block_to_keep: 10,
|
||||||
@@ -1210,13 +1261,13 @@ pub(crate) mod tests {
|
|||||||
// try to prune blocks [2; 10)
|
// try to prune blocks [2; 10)
|
||||||
storage.prune_blocks(11, 10, 10);
|
storage.prune_blocks(11, 10, 10);
|
||||||
// 4 headers with number = 2 are pruned (4 total)
|
// 4 headers with number = 2 are pruned (4 total)
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&2).is_none());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&2).is_none());
|
||||||
// 5 headers with number = 3 are pruned (9 total)
|
// 5 headers with number = 3 are pruned (9 total)
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&3).is_none());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&3).is_none());
|
||||||
// 2 headers with number = 4 are pruned (11 total)
|
// 2 headers with number = 4 are pruned (11 total)
|
||||||
assert_eq!(HeadersByNumber::<DefaultInstance>::get(&4).unwrap().len(), 3);
|
assert_eq!(HeadersByNumber::<TestRuntime, ()>::get(&4).unwrap().len(), 3);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
BlocksToPrune::<DefaultInstance>::get(),
|
BlocksToPrune::<TestRuntime, ()>::get(),
|
||||||
PruningRange {
|
PruningRange {
|
||||||
oldest_unpruned_block: 4,
|
oldest_unpruned_block: 4,
|
||||||
oldest_block_to_keep: 10,
|
oldest_block_to_keep: 10,
|
||||||
@@ -1233,16 +1284,16 @@ pub(crate) mod tests {
|
|||||||
// and one of blocks#7 has scheduled change
|
// and one of blocks#7 has scheduled change
|
||||||
// => we won't prune any block#7 at all
|
// => we won't prune any block#7 at all
|
||||||
storage.prune_blocks(0xFFFF, 5, 10);
|
storage.prune_blocks(0xFFFF, 5, 10);
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&0).is_none());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&0).is_none());
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&1).is_none());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&1).is_none());
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&2).is_none());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&2).is_none());
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&3).is_none());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&3).is_none());
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&4).is_none());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&4).is_none());
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&5).is_none());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&5).is_none());
|
||||||
assert!(HeadersByNumber::<DefaultInstance>::get(&6).is_none());
|
assert!(HeadersByNumber::<TestRuntime, ()>::get(&6).is_none());
|
||||||
assert_eq!(HeadersByNumber::<DefaultInstance>::get(&7).unwrap().len(), 5);
|
assert_eq!(HeadersByNumber::<TestRuntime, ()>::get(&7).unwrap().len(), 5);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
BlocksToPrune::<DefaultInstance>::get(),
|
BlocksToPrune::<TestRuntime, ()>::get(),
|
||||||
PruningRange {
|
PruningRange {
|
||||||
oldest_unpruned_block: 7,
|
oldest_unpruned_block: 7,
|
||||||
oldest_block_to_keep: 10,
|
oldest_block_to_keep: 10,
|
||||||
@@ -1272,7 +1323,7 @@ pub(crate) mod tests {
|
|||||||
assert!(FinalityCache::<TestRuntime>::get(&header_with_entry_hash).is_some());
|
assert!(FinalityCache::<TestRuntime>::get(&header_with_entry_hash).is_some());
|
||||||
|
|
||||||
// when we later prune this header, cache entry is removed
|
// when we later prune this header, cache entry is removed
|
||||||
BlocksToPrune::<DefaultInstance>::put(PruningRange {
|
BlocksToPrune::<TestRuntime, ()>::put(PruningRange {
|
||||||
oldest_unpruned_block: interval - 1,
|
oldest_unpruned_block: interval - 1,
|
||||||
oldest_block_to_keep: interval - 1,
|
oldest_block_to_keep: interval - 1,
|
||||||
});
|
});
|
||||||
@@ -1359,7 +1410,7 @@ pub(crate) mod tests {
|
|||||||
insert_header(&mut storage, header1s);
|
insert_header(&mut storage, header1s);
|
||||||
|
|
||||||
// header1 is finalized
|
// header1 is finalized
|
||||||
FinalizedBlock::<DefaultInstance>::put(header1_id);
|
FinalizedBlock::<TestRuntime, ()>::put(header1_id);
|
||||||
|
|
||||||
// trying to get finality votes when importing header2 -> header1 succeeds
|
// trying to get finality votes when importing header2 -> header1 succeeds
|
||||||
assert!(
|
assert!(
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ pub use bp_eth_poa::signatures::secret_to_address;
|
|||||||
use crate::validators::{ValidatorsConfiguration, ValidatorsSource};
|
use crate::validators::{ValidatorsConfiguration, ValidatorsSource};
|
||||||
use crate::{AuraConfiguration, ChainTime, Config, GenesisConfig as CrateGenesisConfig, PruningStrategy};
|
use crate::{AuraConfiguration, ChainTime, Config, GenesisConfig as CrateGenesisConfig, PruningStrategy};
|
||||||
use bp_eth_poa::{Address, AuraHeader, H256, U256};
|
use bp_eth_poa::{Address, AuraHeader, H256, U256};
|
||||||
use frame_support::{parameter_types, weights::Weight};
|
use frame_support::{parameter_types, traits::GenesisBuild, weights::Weight};
|
||||||
use secp256k1::SecretKey;
|
use secp256k1::SecretKey;
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
testing::Header as SubstrateHeader,
|
testing::Header as SubstrateHeader,
|
||||||
@@ -146,13 +146,12 @@ pub fn run_test_with_genesis<T>(
|
|||||||
) -> T {
|
) -> T {
|
||||||
let validators = validators(total_validators);
|
let validators = validators(total_validators);
|
||||||
let addresses = validators_addresses(total_validators);
|
let addresses = validators_addresses(total_validators);
|
||||||
sp_io::TestExternalities::new(
|
sp_io::TestExternalities::from(
|
||||||
CrateGenesisConfig {
|
GenesisBuild::<TestRuntime>::build_storage(&CrateGenesisConfig {
|
||||||
initial_header: genesis.clone(),
|
initial_header: genesis.clone(),
|
||||||
initial_difficulty: 0.into(),
|
initial_difficulty: 0.into(),
|
||||||
initial_validators: addresses.clone(),
|
initial_validators: addresses.clone(),
|
||||||
}
|
})
|
||||||
.build_storage::<TestRuntime, crate::DefaultInstance>()
|
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.execute_with(|| {
|
.execute_with(|| {
|
||||||
|
|||||||
@@ -63,30 +63,28 @@ impl HeaderBuilder {
|
|||||||
/// Creates default header on top of test parent with given hash.
|
/// Creates default header on top of test parent with given hash.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn with_parent_hash(parent_hash: H256) -> Self {
|
pub fn with_parent_hash(parent_hash: H256) -> Self {
|
||||||
Self::with_parent_hash_on_runtime::<crate::mock::TestRuntime, crate::DefaultInstance>(parent_hash)
|
Self::with_parent_hash_on_runtime::<crate::mock::TestRuntime, ()>(parent_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates default header on top of test parent with given number. First parent is selected.
|
/// Creates default header on top of test parent with given number. First parent is selected.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn with_parent_number(parent_number: u64) -> Self {
|
pub fn with_parent_number(parent_number: u64) -> Self {
|
||||||
Self::with_parent_number_on_runtime::<crate::mock::TestRuntime, crate::DefaultInstance>(parent_number)
|
Self::with_parent_number_on_runtime::<crate::mock::TestRuntime, ()>(parent_number)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates default header on top of parent with given hash.
|
/// Creates default header on top of parent with given hash.
|
||||||
pub fn with_parent_hash_on_runtime<T: Config<I>, I: crate::Instance>(parent_hash: H256) -> Self {
|
pub fn with_parent_hash_on_runtime<T: Config<I>, I: 'static>(parent_hash: H256) -> Self {
|
||||||
use crate::Headers;
|
use crate::Headers;
|
||||||
use frame_support::StorageMap;
|
|
||||||
|
|
||||||
let parent_header = Headers::<T, I>::get(&parent_hash).unwrap().header;
|
let parent_header = Headers::<T, I>::get(&parent_hash).unwrap().header;
|
||||||
Self::with_parent(&parent_header)
|
Self::with_parent(&parent_header)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates default header on top of parent with given number. First parent is selected.
|
/// Creates default header on top of parent with given number. First parent is selected.
|
||||||
pub fn with_parent_number_on_runtime<T: Config<I>, I: crate::Instance>(parent_number: u64) -> Self {
|
pub fn with_parent_number_on_runtime<T: Config<I>, I: 'static>(parent_number: u64) -> Self {
|
||||||
use crate::HeadersByNumber;
|
use crate::HeadersByNumber;
|
||||||
use frame_support::StorageMap;
|
|
||||||
|
|
||||||
let parent_hash = HeadersByNumber::<I>::get(parent_number).unwrap()[0];
|
let parent_hash = HeadersByNumber::<T, I>::get(parent_number).unwrap()[0];
|
||||||
Self::with_parent_hash_on_runtime::<T, I>(parent_hash)
|
Self::with_parent_hash_on_runtime::<T, I>(parent_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -276,10 +276,8 @@ impl ValidatorsSource {
|
|||||||
pub(crate) mod tests {
|
pub(crate) mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::mock::{run_test, validators_addresses, validators_change_receipt, TestRuntime};
|
use crate::mock::{run_test, validators_addresses, validators_change_receipt, TestRuntime};
|
||||||
use crate::DefaultInstance;
|
|
||||||
use crate::{AuraScheduledChange, BridgeStorage, Headers, ScheduledChanges, StoredHeader};
|
use crate::{AuraScheduledChange, BridgeStorage, Headers, ScheduledChanges, StoredHeader};
|
||||||
use bp_eth_poa::compute_merkle_root;
|
use bp_eth_poa::compute_merkle_root;
|
||||||
use frame_support::StorageMap;
|
|
||||||
|
|
||||||
const TOTAL_VALIDATORS: usize = 3;
|
const TOTAL_VALIDATORS: usize = 3;
|
||||||
|
|
||||||
@@ -438,7 +436,7 @@ pub(crate) mod tests {
|
|||||||
};
|
};
|
||||||
Headers::<TestRuntime>::insert(id100.hash, header100);
|
Headers::<TestRuntime>::insert(id100.hash, header100);
|
||||||
if let Some(scheduled_at) = scheduled_at {
|
if let Some(scheduled_at) = scheduled_at {
|
||||||
ScheduledChanges::<DefaultInstance>::insert(scheduled_at.hash, scheduled_change);
|
ScheduledChanges::<TestRuntime, ()>::insert(scheduled_at.hash, scheduled_change);
|
||||||
}
|
}
|
||||||
|
|
||||||
validators.finalize_validators_change(&storage, &finalized_blocks)
|
validators.finalize_validators_change(&storage, &finalized_blocks)
|
||||||
|
|||||||
@@ -375,13 +375,11 @@ mod tests {
|
|||||||
validators_change_receipt, AccountId, ConstChainTime, HeaderBuilder, TestRuntime, GAS_LIMIT,
|
validators_change_receipt, AccountId, ConstChainTime, HeaderBuilder, TestRuntime, GAS_LIMIT,
|
||||||
};
|
};
|
||||||
use crate::validators::ValidatorsSource;
|
use crate::validators::ValidatorsSource;
|
||||||
use crate::DefaultInstance;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
pool_configuration, BridgeStorage, FinalizedBlock, Headers, HeadersByNumber, NextValidatorsSetId,
|
pool_configuration, BridgeStorage, FinalizedBlock, Headers, HeadersByNumber, NextValidatorsSetId,
|
||||||
ScheduledChanges, ValidatorsSet, ValidatorsSets,
|
ScheduledChanges, ValidatorsSet, ValidatorsSets,
|
||||||
};
|
};
|
||||||
use bp_eth_poa::{compute_merkle_root, rlp_encode, TransactionOutcome, H520, U256};
|
use bp_eth_poa::{compute_merkle_root, rlp_encode, TransactionOutcome, H520, U256};
|
||||||
use frame_support::{StorageMap, StorageValue};
|
|
||||||
use hex_literal::hex;
|
use hex_literal::hex;
|
||||||
use secp256k1::SecretKey;
|
use secp256k1::SecretKey;
|
||||||
use sp_runtime::transaction_validity::TransactionTag;
|
use sp_runtime::transaction_validity::TransactionTag;
|
||||||
@@ -418,7 +416,7 @@ mod tests {
|
|||||||
let block3 = HeaderBuilder::with_parent_number(2).sign_by_set(&validators);
|
let block3 = HeaderBuilder::with_parent_number(2).sign_by_set(&validators);
|
||||||
insert_header(&mut storage, block3);
|
insert_header(&mut storage, block3);
|
||||||
|
|
||||||
FinalizedBlock::<DefaultInstance>::put(block2_id);
|
FinalizedBlock::<TestRuntime, ()>::put(block2_id);
|
||||||
|
|
||||||
let validators_config =
|
let validators_config =
|
||||||
ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new()));
|
ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new()));
|
||||||
@@ -436,21 +434,21 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn change_validators_set_at(number: u64, finalized_set: Vec<Address>, signalled_set: Option<Vec<Address>>) {
|
fn change_validators_set_at(number: u64, finalized_set: Vec<Address>, signalled_set: Option<Vec<Address>>) {
|
||||||
let set_id = NextValidatorsSetId::<DefaultInstance>::get();
|
let set_id = NextValidatorsSetId::<TestRuntime, ()>::get();
|
||||||
NextValidatorsSetId::<DefaultInstance>::put(set_id + 1);
|
NextValidatorsSetId::<TestRuntime, ()>::put(set_id + 1);
|
||||||
ValidatorsSets::<DefaultInstance>::insert(
|
ValidatorsSets::<TestRuntime, ()>::insert(
|
||||||
set_id,
|
set_id,
|
||||||
ValidatorsSet {
|
ValidatorsSet {
|
||||||
validators: finalized_set,
|
validators: finalized_set,
|
||||||
signal_block: None,
|
signal_block: None,
|
||||||
enact_block: HeaderId {
|
enact_block: HeaderId {
|
||||||
number: 0,
|
number: 0,
|
||||||
hash: HeadersByNumber::<DefaultInstance>::get(&0).unwrap()[0],
|
hash: HeadersByNumber::<TestRuntime, ()>::get(&0).unwrap()[0],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let header_hash = HeadersByNumber::<DefaultInstance>::get(&number).unwrap()[0];
|
let header_hash = HeadersByNumber::<TestRuntime, ()>::get(&number).unwrap()[0];
|
||||||
let mut header = Headers::<TestRuntime>::get(&header_hash).unwrap();
|
let mut header = Headers::<TestRuntime>::get(&header_hash).unwrap();
|
||||||
header.next_validators_set_id = set_id;
|
header.next_validators_set_id = set_id;
|
||||||
if let Some(signalled_set) = signalled_set {
|
if let Some(signalled_set) = signalled_set {
|
||||||
@@ -458,7 +456,7 @@ mod tests {
|
|||||||
number: header.header.number - 1,
|
number: header.header.number - 1,
|
||||||
hash: header.header.parent_hash,
|
hash: header.header.parent_hash,
|
||||||
});
|
});
|
||||||
ScheduledChanges::<DefaultInstance>::insert(
|
ScheduledChanges::<TestRuntime, ()>::insert(
|
||||||
header.header.parent_hash,
|
header.header.parent_hash,
|
||||||
AuraScheduledChange {
|
AuraScheduledChange {
|
||||||
validators: signalled_set,
|
validators: signalled_set,
|
||||||
|
|||||||
Reference in New Issue
Block a user