migrate eth PoA pallet to frame v2 (#1091)

This commit is contained in:
Svyatoslav Nikolsky
2021-08-12 16:59:12 +03:00
committed by Bastian Köcher
parent 239790fc72
commit 92b3a69126
10 changed files with 259 additions and 217 deletions
+1 -1
View File
@@ -128,7 +128,7 @@ impl MaybeLockFundsTransaction for EthTransaction {
/// Prepares everything required to bench claim of funds locked by given transaction.
#[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)],
) -> bp_eth_poa::H256 {
use bp_eth_poa::compute_merkle_root;
+1
View File
@@ -1102,6 +1102,7 @@ impl_runtime_apis! {
}
}
add_benchmark!(params, batches, pallet_bridge_eth_poa, BridgeRialtoPoa);
add_benchmark!(
params,
batches,
+6 -6
View File
@@ -22,10 +22,10 @@ use crate::test_utils::{
};
use bp_eth_poa::{compute_merkle_root, U256};
use frame_benchmarking::benchmarks_instance;
use frame_benchmarking::benchmarks_instance_pallet;
use frame_system::RawOrigin;
benchmarks_instance! {
benchmarks_instance_pallet! {
// Benchmark `import_unsigned_header` extrinsic with the best possible conditions:
// * Parent header is finalized.
// * New header doesn't require receipts.
@@ -153,7 +153,7 @@ benchmarks_instance! {
let validators = validators(num_validators);
// Want to prune eligible blocks between [0, n)
BlocksToPrune::<I>::put(PruningRange {
BlocksToPrune::<T, I>::put(PruningRange {
oldest_unpruned_block: 0,
oldest_block_to_keep: n as u64,
});
@@ -172,8 +172,8 @@ benchmarks_instance! {
let storage = BridgeStorage::<T, I>::new();
let max_pruned: u64 = (n - 1) as _;
assert_eq!(storage.best_block().0.number, (n + 1) as u64);
assert!(HeadersByNumber::<I>::get(&0).is_none());
assert!(HeadersByNumber::<I>::get(&max_pruned).is_none());
assert!(HeadersByNumber::<T, I>::get(&0).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
@@ -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
let initial_header = build_genesis_header(&validator(0));
let initial_difficulty = initial_header.difficulty;
-1
View File
@@ -284,7 +284,6 @@ mod tests {
use super::*;
use crate::mock::{insert_header, run_test, validator, validators_addresses, HeaderBuilder, TestRuntime};
use crate::{BridgeStorage, FinalityCache, HeaderToImport};
use frame_support::StorageMap;
const TOTAL_VALIDATORS: usize = 5;
+2 -4
View File
@@ -176,9 +176,7 @@ mod tests {
validators_change_receipt, HeaderBuilder, KeepSomeHeadersBehindBest, TestRuntime, GAS_LIMIT,
};
use crate::validators::ValidatorsSource;
use crate::DefaultInstance;
use crate::{BlocksToPrune, BridgeStorage, Headers, PruningRange};
use frame_support::{StorageMap, StorageValue};
use secp256k1::SecretKey;
const TOTAL_VALIDATORS: usize = 3;
@@ -367,7 +365,7 @@ mod tests {
step += 3;
}
assert_eq!(
BlocksToPrune::<DefaultInstance>::get(),
BlocksToPrune::<TestRuntime, ()>::get(),
PruningRange {
oldest_unpruned_block: 11,
oldest_block_to_keep: 14,
@@ -394,7 +392,7 @@ mod tests {
.unwrap();
assert_eq!(finalized_blocks, expected_blocks);
assert_eq!(
BlocksToPrune::<DefaultInstance>::get(),
BlocksToPrune::<TestRuntime, ()>::get(),
PruningRange {
oldest_unpruned_block: 15,
oldest_block_to_keep: 15,
+232 -181
View File
@@ -21,14 +21,8 @@
use crate::finality::{CachedFinalityVotes, FinalityVotes};
use bp_eth_poa::{Address, AuraHeader, HeaderId, RawTransaction, RawTransactionReceipt, Receipt, H256, U256};
use codec::{Decode, Encode};
use frame_support::{decl_module, decl_storage, traits::Get};
use sp_runtime::{
transaction_validity::{
InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource, TransactionValidity,
UnknownTransaction, ValidTransaction,
},
RuntimeDebug,
};
use frame_support::traits::Get;
use sp_runtime::RuntimeDebug;
use sp_std::{cmp::Ord, collections::btree_map::BTreeMap, prelude::*};
pub use validators::{ValidatorsConfiguration, ValidatorsSource};
@@ -369,34 +363,53 @@ impl<AccountId> OnHeadersSubmitted<AccountId> for () {
fn on_valid_headers_finalized(_submitter: AccountId, _finalized: u64) {}
}
/// The module configuration trait.
pub trait Config<I = DefaultInstance>: frame_system::Config {
/// Aura configuration.
type AuraConfiguration: Get<AuraConfiguration>;
/// Validators configuration.
type ValidatorsConfiguration: Get<validators::ValidatorsConfiguration>;
pub use pallet::*;
/// Interval (in blocks) for for finality votes caching.
/// If None, cache is disabled.
///
/// Ideally, this should either be None (when we are sure that there won't
/// be any significant finalization delays), or something that is bit larger
/// than average finalization delay.
type FinalityVotesCachingInterval: Get<Option<u64>>;
/// Headers pruning strategy.
type PruningStrategy: PruningStrategy;
/// Header timestamp verification against current on-chain time.
type ChainTime: ChainTime;
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
/// Handler for headers submission result.
type OnHeadersSubmitted: OnHeadersSubmitted<Self::AccountId>;
}
#[pallet::config]
pub trait Config<I: 'static = ()>: frame_system::Config {
/// Aura configuration.
type AuraConfiguration: Get<AuraConfiguration>;
/// Validators configuration.
type ValidatorsConfiguration: Get<validators::ValidatorsConfiguration>;
decl_module! {
pub struct Module<T: Config<I>, I: Instance = DefaultInstance> for enum Call where origin: T::Origin {
/// Interval (in blocks) for for finality votes caching.
/// If None, cache is disabled.
///
/// Ideally, this should either be None (when we are sure that there won't
/// be any significant finalization delays), or something that is bit larger
/// than average finalization delay.
type FinalityVotesCachingInterval: Get<Option<u64>>;
/// Headers pruning strategy.
type PruningStrategy: PruningStrategy;
/// Header timestamp verification against current on-chain time.
type ChainTime: ChainTime;
/// Handler for headers submission result.
type OnHeadersSubmitted: OnHeadersSubmitted<Self::AccountId>;
}
#[pallet::pallet]
#[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**.
#[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>>) {
#[pallet::weight(0)] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
pub fn import_unsigned_header(
origin: OriginFor<T>,
header: AuraHeader,
receipts: Option<Vec<Receipt>>,
) -> DispatchResult {
frame_system::ensure_none(origin)?;
import::import_header(
@@ -408,7 +421,10 @@ decl_module! {
header,
&T::ChainTime::default(),
receipts,
).map_err(|e| e.msg())?;
)
.map_err(|e| e.msg())?;
Ok(())
}
/// 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
/// enormous block production/import time.
#[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>>)>) {
#[pallet::weight(0)] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
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 mut finalized_headers = BTreeMap::new();
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 current submitter has provided some invalid headers
for (f_submitter, f_count) in finalized_headers {
T::OnHeadersSubmitted::on_valid_headers_finalized(
f_submitter,
f_count,
);
T::OnHeadersSubmitted::on_valid_headers_finalized(f_submitter, f_count);
}
// now track/penalize current submitter for providing new headers
match import_result {
Ok((useful, useless)) =>
T::OnHeadersSubmitted::on_valid_headers_submitted(submitter, useful, useless),
Ok((useful, useless)) => T::OnHeadersSubmitted::on_valid_headers_submitted(submitter, useful, useless),
Err(error) => {
// even though we may have accept some headers, we do not want to reward someone
// who provides invalid headers
T::OnHeadersSubmitted::on_invalid_headers_submitted(submitter);
return Err(error.msg().into());
},
}
}
Ok(())
}
}
#[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(),
}
}
}
}
decl_storage! {
trait Store for Pallet<T: Config<I>, I: Instance = DefaultInstance> as Bridge {
/// Best known block.
BestBlock: (HeaderId, U256);
/// Best finalized block.
FinalizedBlock: HeaderId;
/// Range of blocks that we want to prune.
BlocksToPrune: PruningRange;
/// Map of imported headers by hash.
Headers: map hasher(identity) H256 => Option<StoredHeader<T::AccountId>>;
/// Map of imported header hashes by number.
HeadersByNumber: map hasher(blake2_128_concat) u64 => Option<Vec<H256>>;
/// Map of cached finality data by header hash.
FinalityCache: map hasher(identity) H256 => Option<FinalityVotes<T::AccountId>>;
/// The ID of next validator set.
NextValidatorsSetId: u64;
/// Map of validators sets by their id.
ValidatorsSets: map hasher(twox_64_concat) u64 => Option<ValidatorsSet>;
/// 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.
/// When it reaches zero, we are free to prune validator set as well.
ValidatorsSetsRc: map hasher(twox_64_concat) u64 => Option<u64>;
/// Map of validators set changes scheduled by given header.
ScheduledChanges: map hasher(identity) H256 => Option<AuraScheduledChange>;
/// Best known block.
#[pallet::storage]
pub(super) type BestBlock<T: Config<I>, I: 'static = ()> = StorageValue<_, (HeaderId, U256), ValueQuery>;
/// Best finalized block.
#[pallet::storage]
pub(super) type FinalizedBlock<T: Config<I>, I: 'static = ()> = StorageValue<_, HeaderId, ValueQuery>;
/// Range of blocks that we want to prune.
#[pallet::storage]
pub(super) type BlocksToPrune<T: Config<I>, I: 'static = ()> = StorageValue<_, PruningRange, ValueQuery>;
/// Map of imported headers by hash.
#[pallet::storage]
pub(super) type Headers<T: Config<I>, I: 'static = ()> = StorageMap<_, Identity, H256, StoredHeader<T::AccountId>>;
/// Map of imported header hashes by number.
#[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.
#[pallet::storage]
pub(super) type FinalityCache<T: Config<I>, I: 'static = ()> =
StorageMap<_, Identity, H256, FinalityVotes<T::AccountId>>;
/// The ID of next validator set.
#[pallet::storage]
pub(super) type NextValidatorsSetId<T: Config<I>, I: 'static = ()> = StorageValue<_, u64, ValueQuery>;
/// Map of validators sets by their id.
#[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
/// 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.
#[pallet::storage]
pub(super) type ValidatorsSetsRc<T: Config<I>, I: 'static = ()> = StorageMap<_, Twox64Concat, u64, u64>;
/// Map of validators set changes scheduled by given header.
#[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;
config(initial_difficulty): U256;
config(initial_validators): Vec<Address>;
build(|config| {
#[cfg(feature = "std")]
impl Default for GenesisConfig {
fn default() -> Self {
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:
// 1) it doesn't signal validators changes;
// 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.
assert!(
!config.initial_validators.is_empty(),
!self.initial_validators.is_empty(),
"Initial validators set can't be empty",
);
initialize_storage::<T, I>(
&config.initial_header,
config.initial_difficulty,
&config.initial_validators,
);
})
initialize_storage::<T, I>(&self.initial_header, self.initial_difficulty, &self.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.
/// The caller should only submit `import_header` transaction that makes
/// (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.
#[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.
pub fn new() -> Self {
BridgeStorage(sp_std::marker::PhantomData::<(T, I)>::default())
@@ -592,7 +643,7 @@ impl<T: Config<I>, I: Instance> BridgeStorage<T, I> {
/// Prune old blocks.
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();
// 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
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 {
self.prune_blocks_by_hashes(
&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 !blocks_at_number.is_empty() {
HeadersByNumber::<I>::insert(number, blocks_at_number);
HeadersByNumber::<T, I>::insert(number, blocks_at_number);
break;
}
}
@@ -638,7 +689,7 @@ impl<T: Config<I>, I: Instance> BridgeStorage<T, I> {
// update pruning range in storage
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>,
) {
// 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;
}
@@ -665,10 +716,10 @@ impl<T: Config<I>, I: Instance> BridgeStorage<T, I> {
hash,
);
ScheduledChanges::<I>::remove(hash);
ScheduledChanges::<T, I>::remove(hash);
FinalityCache::<T, I>::remove(hash);
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),
_ => 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;
fn best_block(&self) -> (HeaderId, U256) {
BestBlock::<I>::get()
BestBlock::<T, I>::get()
}
fn finalized_block(&self) -> HeaderId {
FinalizedBlock::<I>::get()
FinalizedBlock::<T, I>::get()
}
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,
) -> Option<ImportContext<Self::Submitter>> {
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");
let parent_scheduled_change = ScheduledChanges::<I>::get(parent_hash);
let parent_scheduled_change = ScheduledChanges::<T, I>::get(parent_hash);
ImportContext {
submitter,
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> {
ScheduledChanges::<I>::get(hash)
ScheduledChanges::<T, I>::get(hash)
}
fn insert_header(&mut self, header: HeaderToImport<Self::Submitter>) {
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 {
ScheduledChanges::<I>::insert(
ScheduledChanges::<T, I>::insert(
&header.id.hash,
AuraScheduledChange {
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 {
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;
*set_id += 1;
next_set_id
});
ValidatorsSets::<I>::insert(
ValidatorsSets::<T, I>::insert(
next_validators_set_id,
ValidatorsSet {
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,
},
);
ValidatorsSetsRc::<I>::insert(next_validators_set_id, 1);
ValidatorsSetsRc::<T, I>::insert(next_validators_set_id, 1);
next_validators_set_id
}
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
});
@@ -826,7 +877,7 @@ impl<T: Config<I>, I: Instance> Storage for BridgeStorage<T, I> {
);
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(
&header.id.hash,
StoredHeader {
@@ -844,7 +895,7 @@ impl<T: Config<I>, I: Instance> Storage for BridgeStorage<T, I> {
let finalized_number = finalized
.as_ref()
.map(|f| f.number)
.unwrap_or_else(|| FinalizedBlock::<I>::get().number);
.unwrap_or_else(|| FinalizedBlock::<T, I>::get().number);
if let Some(finalized) = finalized {
log::trace!(
target: "runtime",
@@ -853,7 +904,7 @@ impl<T: Config<I>, I: Instance> Storage for BridgeStorage<T, I> {
finalized.hash,
);
FinalizedBlock::<I>::put(finalized);
FinalizedBlock::<T, I>::put(finalized);
}
// 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.
#[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_difficulty: U256,
initial_validators: &[Address],
@@ -880,13 +931,13 @@ pub(crate) fn initialize_storage<T: Config<I>, I: Instance>(
number: initial_header.number,
hash: initial_hash,
};
BestBlock::<I>::put((initial_id, initial_difficulty));
FinalizedBlock::<I>::put(initial_id);
BlocksToPrune::<I>::put(PruningRange {
BestBlock::<T, I>::put((initial_id, initial_difficulty));
FinalizedBlock::<T, I>::put(initial_id);
BlocksToPrune::<T, I>::put(PruningRange {
oldest_unpruned_block: 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(
initial_hash,
StoredHeader {
@@ -897,8 +948,8 @@ pub(crate) fn initialize_storage<T: Config<I>, I: Instance>(
last_signal_block: None,
},
);
NextValidatorsSetId::<I>::put(1);
ValidatorsSets::<I>::insert(
NextValidatorsSetId::<T, I>::put(1);
ValidatorsSets::<T, I>::insert(
0,
ValidatorsSet {
validators: initial_validators.to_vec(),
@@ -906,7 +957,7 @@ pub(crate) fn initialize_storage<T: Config<I>, I: Instance>(
enact_block: initial_id,
},
);
ValidatorsSetsRc::<I>::insert(0, 1);
ValidatorsSetsRc::<T, I>::insert(0, 1);
}
/// Verify that transaction is included into given finalized block.
@@ -1112,7 +1163,7 @@ pub(crate) mod tests {
);
if i == 7 && j == 1 {
ScheduledChanges::<DefaultInstance>::insert(
ScheduledChanges::<TestRuntime, ()>::insert(
hash,
AuraScheduledChange {
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())
@@ -1131,16 +1182,16 @@ pub(crate) mod tests {
#[test]
fn blocks_are_not_pruned_if_range_is_empty() {
with_headers_to_prune(|storage| {
BlocksToPrune::<DefaultInstance>::put(PruningRange {
BlocksToPrune::<TestRuntime, ()>::put(PruningRange {
oldest_unpruned_block: 5,
oldest_block_to_keep: 5,
});
// try to prune blocks [5; 10)
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!(
BlocksToPrune::<DefaultInstance>::get(),
BlocksToPrune::<TestRuntime, ()>::get(),
PruningRange {
oldest_unpruned_block: 5,
oldest_block_to_keep: 5,
@@ -1152,7 +1203,7 @@ pub(crate) mod tests {
#[test]
fn blocks_to_prune_never_shrinks_from_the_end() {
with_headers_to_prune(|storage| {
BlocksToPrune::<DefaultInstance>::put(PruningRange {
BlocksToPrune::<TestRuntime, ()>::put(PruningRange {
oldest_unpruned_block: 0,
oldest_block_to_keep: 5,
});
@@ -1160,7 +1211,7 @@ pub(crate) mod tests {
// try to prune blocks [5; 10)
storage.prune_blocks(0xFFFF, 10, 3);
assert_eq!(
BlocksToPrune::<DefaultInstance>::get(),
BlocksToPrune::<TestRuntime, ()>::get(),
PruningRange {
oldest_unpruned_block: 5,
oldest_block_to_keep: 5,
@@ -1174,12 +1225,12 @@ pub(crate) mod tests {
with_headers_to_prune(|storage| {
// try to prune blocks [0; 10)
storage.prune_blocks(0, 10, 10);
assert!(HeadersByNumber::<DefaultInstance>::get(&0).is_some());
assert!(HeadersByNumber::<DefaultInstance>::get(&1).is_some());
assert!(HeadersByNumber::<DefaultInstance>::get(&2).is_some());
assert!(HeadersByNumber::<DefaultInstance>::get(&3).is_some());
assert!(HeadersByNumber::<TestRuntime, ()>::get(&0).is_some());
assert!(HeadersByNumber::<TestRuntime, ()>::get(&1).is_some());
assert!(HeadersByNumber::<TestRuntime, ()>::get(&2).is_some());
assert!(HeadersByNumber::<TestRuntime, ()>::get(&3).is_some());
assert_eq!(
BlocksToPrune::<DefaultInstance>::get(),
BlocksToPrune::<TestRuntime, ()>::get(),
PruningRange {
oldest_unpruned_block: 0,
oldest_block_to_keep: 10,
@@ -1194,13 +1245,13 @@ pub(crate) mod tests {
// try to prune blocks [0; 10)
storage.prune_blocks(7, 10, 10);
// 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)
assert!(HeadersByNumber::<DefaultInstance>::get(&1).is_none());
assert!(HeadersByNumber::<TestRuntime, ()>::get(&1).is_none());
// 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!(
BlocksToPrune::<DefaultInstance>::get(),
BlocksToPrune::<TestRuntime, ()>::get(),
PruningRange {
oldest_unpruned_block: 2,
oldest_block_to_keep: 10,
@@ -1210,13 +1261,13 @@ pub(crate) mod tests {
// try to prune blocks [2; 10)
storage.prune_blocks(11, 10, 10);
// 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)
assert!(HeadersByNumber::<DefaultInstance>::get(&3).is_none());
assert!(HeadersByNumber::<TestRuntime, ()>::get(&3).is_none());
// 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!(
BlocksToPrune::<DefaultInstance>::get(),
BlocksToPrune::<TestRuntime, ()>::get(),
PruningRange {
oldest_unpruned_block: 4,
oldest_block_to_keep: 10,
@@ -1233,16 +1284,16 @@ pub(crate) mod tests {
// and one of blocks#7 has scheduled change
// => we won't prune any block#7 at all
storage.prune_blocks(0xFFFF, 5, 10);
assert!(HeadersByNumber::<DefaultInstance>::get(&0).is_none());
assert!(HeadersByNumber::<DefaultInstance>::get(&1).is_none());
assert!(HeadersByNumber::<DefaultInstance>::get(&2).is_none());
assert!(HeadersByNumber::<DefaultInstance>::get(&3).is_none());
assert!(HeadersByNumber::<DefaultInstance>::get(&4).is_none());
assert!(HeadersByNumber::<DefaultInstance>::get(&5).is_none());
assert!(HeadersByNumber::<DefaultInstance>::get(&6).is_none());
assert_eq!(HeadersByNumber::<DefaultInstance>::get(&7).unwrap().len(), 5);
assert!(HeadersByNumber::<TestRuntime, ()>::get(&0).is_none());
assert!(HeadersByNumber::<TestRuntime, ()>::get(&1).is_none());
assert!(HeadersByNumber::<TestRuntime, ()>::get(&2).is_none());
assert!(HeadersByNumber::<TestRuntime, ()>::get(&3).is_none());
assert!(HeadersByNumber::<TestRuntime, ()>::get(&4).is_none());
assert!(HeadersByNumber::<TestRuntime, ()>::get(&5).is_none());
assert!(HeadersByNumber::<TestRuntime, ()>::get(&6).is_none());
assert_eq!(HeadersByNumber::<TestRuntime, ()>::get(&7).unwrap().len(), 5);
assert_eq!(
BlocksToPrune::<DefaultInstance>::get(),
BlocksToPrune::<TestRuntime, ()>::get(),
PruningRange {
oldest_unpruned_block: 7,
oldest_block_to_keep: 10,
@@ -1272,7 +1323,7 @@ pub(crate) mod tests {
assert!(FinalityCache::<TestRuntime>::get(&header_with_entry_hash).is_some());
// when we later prune this header, cache entry is removed
BlocksToPrune::<DefaultInstance>::put(PruningRange {
BlocksToPrune::<TestRuntime, ()>::put(PruningRange {
oldest_unpruned_block: interval - 1,
oldest_block_to_keep: interval - 1,
});
@@ -1359,7 +1410,7 @@ pub(crate) mod tests {
insert_header(&mut storage, header1s);
// header1 is finalized
FinalizedBlock::<DefaultInstance>::put(header1_id);
FinalizedBlock::<TestRuntime, ()>::put(header1_id);
// trying to get finality votes when importing header2 -> header1 succeeds
assert!(
+4 -5
View File
@@ -23,7 +23,7 @@ pub use bp_eth_poa::signatures::secret_to_address;
use crate::validators::{ValidatorsConfiguration, ValidatorsSource};
use crate::{AuraConfiguration, ChainTime, Config, GenesisConfig as CrateGenesisConfig, PruningStrategy};
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 sp_runtime::{
testing::Header as SubstrateHeader,
@@ -146,13 +146,12 @@ pub fn run_test_with_genesis<T>(
) -> T {
let validators = validators(total_validators);
let addresses = validators_addresses(total_validators);
sp_io::TestExternalities::new(
CrateGenesisConfig {
sp_io::TestExternalities::from(
GenesisBuild::<TestRuntime>::build_storage(&CrateGenesisConfig {
initial_header: genesis.clone(),
initial_difficulty: 0.into(),
initial_validators: addresses.clone(),
}
.build_storage::<TestRuntime, crate::DefaultInstance>()
})
.unwrap(),
)
.execute_with(|| {
+5 -7
View File
@@ -63,30 +63,28 @@ impl HeaderBuilder {
/// Creates default header on top of test parent with given hash.
#[cfg(test)]
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.
#[cfg(test)]
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.
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 frame_support::StorageMap;
let parent_header = Headers::<T, I>::get(&parent_hash).unwrap().header;
Self::with_parent(&parent_header)
}
/// 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 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)
}
+1 -3
View File
@@ -276,10 +276,8 @@ impl ValidatorsSource {
pub(crate) mod tests {
use super::*;
use crate::mock::{run_test, validators_addresses, validators_change_receipt, TestRuntime};
use crate::DefaultInstance;
use crate::{AuraScheduledChange, BridgeStorage, Headers, ScheduledChanges, StoredHeader};
use bp_eth_poa::compute_merkle_root;
use frame_support::StorageMap;
const TOTAL_VALIDATORS: usize = 3;
@@ -438,7 +436,7 @@ pub(crate) mod tests {
};
Headers::<TestRuntime>::insert(id100.hash, header100);
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)
+7 -9
View File
@@ -375,13 +375,11 @@ mod tests {
validators_change_receipt, AccountId, ConstChainTime, HeaderBuilder, TestRuntime, GAS_LIMIT,
};
use crate::validators::ValidatorsSource;
use crate::DefaultInstance;
use crate::{
pool_configuration, BridgeStorage, FinalizedBlock, Headers, HeadersByNumber, NextValidatorsSetId,
ScheduledChanges, ValidatorsSet, ValidatorsSets,
};
use bp_eth_poa::{compute_merkle_root, rlp_encode, TransactionOutcome, H520, U256};
use frame_support::{StorageMap, StorageValue};
use hex_literal::hex;
use secp256k1::SecretKey;
use sp_runtime::transaction_validity::TransactionTag;
@@ -418,7 +416,7 @@ mod tests {
let block3 = HeaderBuilder::with_parent_number(2).sign_by_set(&validators);
insert_header(&mut storage, block3);
FinalizedBlock::<DefaultInstance>::put(block2_id);
FinalizedBlock::<TestRuntime, ()>::put(block2_id);
let validators_config =
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>>) {
let set_id = NextValidatorsSetId::<DefaultInstance>::get();
NextValidatorsSetId::<DefaultInstance>::put(set_id + 1);
ValidatorsSets::<DefaultInstance>::insert(
let set_id = NextValidatorsSetId::<TestRuntime, ()>::get();
NextValidatorsSetId::<TestRuntime, ()>::put(set_id + 1);
ValidatorsSets::<TestRuntime, ()>::insert(
set_id,
ValidatorsSet {
validators: finalized_set,
signal_block: None,
enact_block: HeaderId {
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();
header.next_validators_set_id = set_id;
if let Some(signalled_set) = signalled_set {
@@ -458,7 +456,7 @@ mod tests {
number: header.header.number - 1,
hash: header.header.parent_hash,
});
ScheduledChanges::<DefaultInstance>::insert(
ScheduledChanges::<TestRuntime, ()>::insert(
header.header.parent_hash,
AuraScheduledChange {
validators: signalled_set,