mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-23 23:35:44 +00:00
Allow Multiple Bridge Pallet Instances (#226)
* Add Instance type parameter to pallet * Sketch out what the runtime could look like * Allow runtime to compile with multiple bridge pallets * Cargo Fmt * Allow an instance of a PoA chain to be used with currency-exchange I specify that it's only _an instance_ instead of _instances_ since the currency-exchange pallet does not support multiple instances itself. What this commit does is make it so that the different instances of the PoA chains we currently have are compatible with the currency-exchange pallet through the implementation of the PeerBlockchain trait. * Add Instance type parameter to Currency Exchange pallet * Wire up currency exchange intances in runtime * Rust Fmt * Show sccache * Allow Eth pallet to use a default instance * Use a default instance in Eth pallet tests * Remove Rialto and Kovan feature flags Through some discussions it has been decided that the `bridge-node` should, like Substrate's `node-template`, be a showcase of the different pallets available in a project. Because of this I've removed the feature flags for the Rialto and Kovan networks in favour of having both of them included in the runtime. * Update the chain_spec to use both Rialto and Kovan configs * Update pallet level calls used by Substrate client Allows the project to compile. However, it should be noted that in reality we shouldn't be hardcoding the pallet we're calling. * Allow currency-exchange pallet to use a default instance * Support benchmarking an instance of the Eth pallet * Update currency exchange benchmarks to work with instances * Fix test helpers which now need a PoA instance * Remove Actions for checking Rialto and Kovan features * Add missing comments * Update Runtime API string constants * Add issue number for generic chain support in relay * Add Runtime APIs for instances of the currency-exchange pallet * Rust Fmt Co-authored-by: Denis S. Soldatov aka General-Beck <general.beck@gmail.com>
This commit is contained in:
committed by
Bastian Köcher
parent
c4424e5b73
commit
30844b1e9c
@@ -21,11 +21,11 @@ use crate::test_utils::{
|
||||
HeaderBuilder,
|
||||
};
|
||||
|
||||
use frame_benchmarking::benchmarks;
|
||||
use frame_benchmarking::benchmarks_instance;
|
||||
use frame_system::RawOrigin;
|
||||
use primitives::{compute_merkle_root, U256};
|
||||
|
||||
benchmarks! {
|
||||
benchmarks_instance! {
|
||||
_ { }
|
||||
|
||||
// Benchmark `import_unsigned_header` extrinsic with the best possible conditions:
|
||||
@@ -37,7 +37,7 @@ benchmarks! {
|
||||
let n in 1..1000;
|
||||
|
||||
let num_validators = 2;
|
||||
let initial_header = initialize_bench::<T>(num_validators);
|
||||
let initial_header = initialize_bench::<T, I>(num_validators);
|
||||
|
||||
// prepare header to be inserted
|
||||
let header = build_custom_header(
|
||||
@@ -50,7 +50,7 @@ benchmarks! {
|
||||
);
|
||||
}: import_unsigned_header(RawOrigin::None, header, None)
|
||||
verify {
|
||||
let storage = BridgeStorage::<T>::new();
|
||||
let storage = BridgeStorage::<T, I>::new();
|
||||
assert_eq!(storage.best_block().0.number, 1);
|
||||
assert_eq!(storage.finalized_block().number, 0);
|
||||
}
|
||||
@@ -67,9 +67,9 @@ benchmarks! {
|
||||
// finalization.
|
||||
let n in 1..7;
|
||||
|
||||
let mut storage = BridgeStorage::<T>::new();
|
||||
let mut storage = BridgeStorage::<T, I>::new();
|
||||
let num_validators: u32 = 2;
|
||||
let initial_header = initialize_bench::<T>(num_validators as usize);
|
||||
let initial_header = initialize_bench::<T, I>(num_validators as usize);
|
||||
|
||||
// Since we only have two validators we need to make sure the number of blocks is even to
|
||||
// make sure the right validator signs the final block
|
||||
@@ -95,7 +95,7 @@ benchmarks! {
|
||||
let header = HeaderBuilder::with_parent(&last_header).sign_by(&last_authority);
|
||||
}: import_unsigned_header(RawOrigin::None, header, None)
|
||||
verify {
|
||||
let storage = BridgeStorage::<T>::new();
|
||||
let storage = BridgeStorage::<T, I>::new();
|
||||
assert_eq!(storage.best_block().0.number, (num_blocks + 1) as u64);
|
||||
assert_eq!(storage.finalized_block().number, num_blocks as u64);
|
||||
}
|
||||
@@ -108,9 +108,9 @@ benchmarks! {
|
||||
// finalization.
|
||||
let n in 7..100;
|
||||
|
||||
let mut storage = BridgeStorage::<T>::new();
|
||||
let mut storage = BridgeStorage::<T, I>::new();
|
||||
let num_validators: u32 = 2;
|
||||
let initial_header = initialize_bench::<T>(num_validators as usize);
|
||||
let initial_header = initialize_bench::<T, I>(num_validators as usize);
|
||||
|
||||
// Since we only have two validators we need to make sure the number of blocks is even to
|
||||
// make sure the right validator signs the final block
|
||||
@@ -136,7 +136,7 @@ benchmarks! {
|
||||
let header = HeaderBuilder::with_parent(&last_header).sign_by(&last_authority);
|
||||
}: import_unsigned_header(RawOrigin::None, header, None)
|
||||
verify {
|
||||
let storage = BridgeStorage::<T>::new();
|
||||
let storage = BridgeStorage::<T, I>::new();
|
||||
assert_eq!(storage.best_block().0.number, (num_blocks + 1) as u64);
|
||||
assert_eq!(storage.finalized_block().number, num_blocks as u64);
|
||||
}
|
||||
@@ -148,14 +148,14 @@ benchmarks! {
|
||||
import_unsigned_pruning {
|
||||
let n in 1..MAX_BLOCKS_TO_PRUNE_IN_SINGLE_IMPORT as u32;
|
||||
|
||||
let mut storage = BridgeStorage::<T>::new();
|
||||
let mut storage = BridgeStorage::<T, I>::new();
|
||||
|
||||
let num_validators = 3;
|
||||
let initial_header = initialize_bench::<T>(num_validators as usize);
|
||||
let initial_header = initialize_bench::<T, I>(num_validators as usize);
|
||||
let validators = validators(num_validators);
|
||||
|
||||
// Want to prune eligible blocks between [0, n)
|
||||
BlocksToPrune::put(PruningRange {
|
||||
BlocksToPrune::<I>::put(PruningRange {
|
||||
oldest_unpruned_block: 0,
|
||||
oldest_block_to_keep: n as u64,
|
||||
});
|
||||
@@ -171,11 +171,11 @@ benchmarks! {
|
||||
let header = HeaderBuilder::with_parent(&parent).sign_by_set(&validators);
|
||||
}: import_unsigned_header(RawOrigin::None, header, None)
|
||||
verify {
|
||||
let storage = BridgeStorage::<T>::new();
|
||||
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::get(&0).is_none());
|
||||
assert!(HeadersByNumber::get(&max_pruned).is_none());
|
||||
assert!(HeadersByNumber::<I>::get(&0).is_none());
|
||||
assert!(HeadersByNumber::<I>::get(&max_pruned).is_none());
|
||||
}
|
||||
|
||||
// The goal of this bench is to import a block which contains a transaction receipt. The receipt
|
||||
@@ -184,10 +184,10 @@ benchmarks! {
|
||||
import_unsigned_with_receipts {
|
||||
let n in 1..100;
|
||||
|
||||
let mut storage = BridgeStorage::<T>::new();
|
||||
let mut storage = BridgeStorage::<T, I>::new();
|
||||
|
||||
let num_validators = 1;
|
||||
let initial_header = initialize_bench::<T>(num_validators as usize);
|
||||
let initial_header = initialize_bench::<T, I>(num_validators as usize);
|
||||
|
||||
let mut receipts = vec![];
|
||||
for i in 1..=n {
|
||||
@@ -213,18 +213,18 @@ benchmarks! {
|
||||
);
|
||||
}: import_unsigned_header(RawOrigin::None, header, Some(receipts))
|
||||
verify {
|
||||
let storage = BridgeStorage::<T>::new();
|
||||
let storage = BridgeStorage::<T, I>::new();
|
||||
assert_eq!(storage.best_block().0.number, 2);
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_bench<T: Trait>(num_validators: usize) -> Header {
|
||||
fn initialize_bench<T: Trait<I>, I: Instance>(num_validators: usize) -> Header {
|
||||
// Initialize storage with some initial header
|
||||
let initial_header = build_genesis_header(&validator(0));
|
||||
let initial_difficulty = initial_header.difficulty;
|
||||
let initial_validators = validators_addresses(num_validators as usize);
|
||||
|
||||
initialize_storage::<T>(&initial_header, initial_difficulty, &initial_validators);
|
||||
initialize_storage::<T, I>(&initial_header, initial_difficulty, &initial_validators);
|
||||
|
||||
initial_header
|
||||
}
|
||||
|
||||
@@ -169,6 +169,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;
|
||||
@@ -352,7 +353,7 @@ mod tests {
|
||||
step += 3;
|
||||
}
|
||||
assert_eq!(
|
||||
BlocksToPrune::get(),
|
||||
BlocksToPrune::<DefaultInstance>::get(),
|
||||
PruningRange {
|
||||
oldest_unpruned_block: 11,
|
||||
oldest_block_to_keep: 14,
|
||||
@@ -378,7 +379,7 @@ mod tests {
|
||||
.unwrap();
|
||||
assert_eq!(finalized_blocks, expected_blocks);
|
||||
assert_eq!(
|
||||
BlocksToPrune::get(),
|
||||
BlocksToPrune::<DefaultInstance>::get(),
|
||||
PruningRange {
|
||||
oldest_unpruned_block: 15,
|
||||
oldest_block_to_keep: 15,
|
||||
|
||||
@@ -351,7 +351,7 @@ impl<AccountId> OnHeadersSubmitted<AccountId> for () {
|
||||
}
|
||||
|
||||
/// The module configuration trait.
|
||||
pub trait Trait: frame_system::Trait {
|
||||
pub trait Trait<I = DefaultInstance>: frame_system::Trait {
|
||||
/// Aura configuration.
|
||||
type AuraConfiguration: Get<AuraConfiguration>;
|
||||
/// Validators configuration.
|
||||
@@ -372,14 +372,14 @@ pub trait Trait: frame_system::Trait {
|
||||
}
|
||||
|
||||
decl_module! {
|
||||
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
||||
pub struct Module<T: Trait<I>, I: Instance = DefaultInstance> for enum Call where origin: T::Origin {
|
||||
/// 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: Header, receipts: Option<Vec<Receipt>>) {
|
||||
frame_system::ensure_none(origin)?;
|
||||
|
||||
import::import_header(
|
||||
&mut BridgeStorage::<T>::new(),
|
||||
&mut BridgeStorage::<T, I>::new(),
|
||||
&mut T::PruningStrategy::default(),
|
||||
&T::AuraConfiguration::get(),
|
||||
&T::ValidatorsConfiguration::get(),
|
||||
@@ -400,7 +400,7 @@ decl_module! {
|
||||
let submitter = frame_system::ensure_signed(origin)?;
|
||||
let mut finalized_headers = BTreeMap::new();
|
||||
let import_result = import::import_headers(
|
||||
&mut BridgeStorage::<T>::new(),
|
||||
&mut BridgeStorage::<T, I>::new(),
|
||||
&mut T::PruningStrategy::default(),
|
||||
&T::AuraConfiguration::get(),
|
||||
&T::ValidatorsConfiguration::get(),
|
||||
@@ -434,7 +434,7 @@ decl_module! {
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Bridge {
|
||||
trait Store for Module<T: Trait<I>, I: Instance = DefaultInstance> as Bridge {
|
||||
/// Best known block.
|
||||
BestBlock: (HeaderId, U256);
|
||||
/// Best finalized block.
|
||||
@@ -473,7 +473,7 @@ decl_storage! {
|
||||
"Initial validators set can't be empty",
|
||||
);
|
||||
|
||||
initialize_storage::<T>(
|
||||
initialize_storage::<T, I>(
|
||||
&config.initial_header,
|
||||
config.initial_difficulty,
|
||||
&config.initial_validators,
|
||||
@@ -482,43 +482,47 @@ decl_storage! {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Module<T> {
|
||||
impl<T: Trait<I>, I: Instance> Module<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.
|
||||
pub fn best_block() -> HeaderId {
|
||||
BridgeStorage::<T>::new().best_block().0
|
||||
BridgeStorage::<T, I>::new().best_block().0
|
||||
}
|
||||
|
||||
/// Returns number and hash of the best finalized block known to the bridge module.
|
||||
pub fn finalized_block() -> HeaderId {
|
||||
BridgeStorage::<T>::new().finalized_block()
|
||||
BridgeStorage::<T, I>::new().finalized_block()
|
||||
}
|
||||
|
||||
/// Returns true if the import of given block requires transactions receipts.
|
||||
pub fn is_import_requires_receipts(header: Header) -> bool {
|
||||
import::header_import_requires_receipts(&BridgeStorage::<T>::new(), &T::ValidatorsConfiguration::get(), &header)
|
||||
import::header_import_requires_receipts(
|
||||
&BridgeStorage::<T, I>::new(),
|
||||
&T::ValidatorsConfiguration::get(),
|
||||
&header,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns true if header is known to the runtime.
|
||||
pub fn is_known_block(hash: H256) -> bool {
|
||||
BridgeStorage::<T>::new().header(&hash).is_some()
|
||||
BridgeStorage::<T, I>::new().header(&hash).is_some()
|
||||
}
|
||||
|
||||
/// Verify that transaction is included into given finalized block.
|
||||
pub fn verify_transaction_finalized(block: H256, tx_index: u64, proof: &[RawTransaction]) -> bool {
|
||||
crate::verify_transaction_finalized(&BridgeStorage::<T>::new(), block, tx_index, proof)
|
||||
crate::verify_transaction_finalized(&BridgeStorage::<T, I>::new(), block, tx_index, proof)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> frame_support::unsigned::ValidateUnsigned for Module<T> {
|
||||
type Call = Call<T>;
|
||||
impl<T: Trait<I>, I: Instance> frame_support::unsigned::ValidateUnsigned for Module<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>::new(),
|
||||
&BridgeStorage::<T, I>::new(),
|
||||
&T::AuraConfiguration::get(),
|
||||
&T::ValidatorsConfiguration::get(),
|
||||
&pool_configuration(),
|
||||
@@ -550,17 +554,17 @@ impl<T: Trait> frame_support::unsigned::ValidateUnsigned for Module<T> {
|
||||
|
||||
/// Runtime bridge storage.
|
||||
#[derive(Default)]
|
||||
pub struct BridgeStorage<T>(sp_std::marker::PhantomData<T>);
|
||||
pub struct BridgeStorage<T, I = DefaultInstance>(sp_std::marker::PhantomData<(T, I)>);
|
||||
|
||||
impl<T: Trait> BridgeStorage<T> {
|
||||
impl<T: Trait<I>, I: Instance> BridgeStorage<T, I> {
|
||||
/// Create new BridgeStorage.
|
||||
pub fn new() -> Self {
|
||||
BridgeStorage(sp_std::marker::PhantomData::<T>::default())
|
||||
BridgeStorage(sp_std::marker::PhantomData::<(T, I)>::default())
|
||||
}
|
||||
|
||||
/// Prune old blocks.
|
||||
fn prune_blocks(&self, mut max_blocks_to_prune: u64, finalized_number: u64, prune_end: u64) {
|
||||
let pruning_range = BlocksToPrune::get();
|
||||
let pruning_range = BlocksToPrune::<I>::get();
|
||||
let mut new_pruning_range = pruning_range.clone();
|
||||
|
||||
// update oldest block we want to keep
|
||||
@@ -579,7 +583,7 @@ impl<T: Trait> BridgeStorage<T> {
|
||||
}
|
||||
|
||||
// read hashes of blocks with given number and try to prune these blocks
|
||||
let blocks_at_number = HeadersByNumber::take(number);
|
||||
let blocks_at_number = HeadersByNumber::<I>::take(number);
|
||||
if let Some(mut blocks_at_number) = blocks_at_number {
|
||||
self.prune_blocks_by_hashes(
|
||||
&mut max_blocks_to_prune,
|
||||
@@ -590,7 +594,7 @@ impl<T: Trait> BridgeStorage<T> {
|
||||
|
||||
// if we haven't pruned all blocks, remember unpruned
|
||||
if !blocks_at_number.is_empty() {
|
||||
HeadersByNumber::insert(number, blocks_at_number);
|
||||
HeadersByNumber::<I>::insert(number, blocks_at_number);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -606,7 +610,7 @@ impl<T: Trait> BridgeStorage<T> {
|
||||
|
||||
// update pruning range in storage
|
||||
if pruning_range != new_pruning_range {
|
||||
BlocksToPrune::put(new_pruning_range);
|
||||
BlocksToPrune::<I>::put(new_pruning_range);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -619,13 +623,13 @@ impl<T: Trait> BridgeStorage<T> {
|
||||
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::contains_key) {
|
||||
if number > finalized_number && blocks_at_number.iter().any(ScheduledChanges::<I>::contains_key) {
|
||||
return;
|
||||
}
|
||||
|
||||
// physically remove headers and (probably) obsolete validators sets
|
||||
while let Some(hash) = blocks_at_number.pop() {
|
||||
let header = Headers::<T>::take(&hash);
|
||||
let header = Headers::<T, I>::take(&hash);
|
||||
frame_support::debug::trace!(
|
||||
target: "runtime",
|
||||
"Pruning PoA header: ({}, {})",
|
||||
@@ -633,10 +637,10 @@ impl<T: Trait> BridgeStorage<T> {
|
||||
hash,
|
||||
);
|
||||
|
||||
ScheduledChanges::remove(hash);
|
||||
FinalityCache::<T>::remove(hash);
|
||||
ScheduledChanges::<I>::remove(hash);
|
||||
FinalityCache::<T, I>::remove(hash);
|
||||
if let Some(header) = header {
|
||||
ValidatorsSetsRc::mutate(header.next_validators_set_id, |rc| match *rc {
|
||||
ValidatorsSetsRc::<I>::mutate(header.next_validators_set_id, |rc| match *rc {
|
||||
Some(rc) if rc > 1 => Some(rc - 1),
|
||||
_ => None,
|
||||
});
|
||||
@@ -651,19 +655,19 @@ impl<T: Trait> BridgeStorage<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Storage for BridgeStorage<T> {
|
||||
impl<T: Trait<I>, I: Instance> Storage for BridgeStorage<T, I> {
|
||||
type Submitter = T::AccountId;
|
||||
|
||||
fn best_block(&self) -> (HeaderId, U256) {
|
||||
BestBlock::get()
|
||||
BestBlock::<I>::get()
|
||||
}
|
||||
|
||||
fn finalized_block(&self) -> HeaderId {
|
||||
FinalizedBlock::get()
|
||||
FinalizedBlock::<I>::get()
|
||||
}
|
||||
|
||||
fn header(&self, hash: &H256) -> Option<(Header, Option<Self::Submitter>)> {
|
||||
Headers::<T>::get(hash).map(|header| (header.header, header.submitter))
|
||||
Headers::<T, I>::get(hash).map(|header| (header.header, header.submitter))
|
||||
}
|
||||
|
||||
fn cached_finality_votes(
|
||||
@@ -675,7 +679,7 @@ impl<T: Trait> Storage for BridgeStorage<T> {
|
||||
let mut votes = CachedFinalityVotes::default();
|
||||
let mut current_id = *parent;
|
||||
loop {
|
||||
// if we have reached finalized block' sibling => stop with special signal
|
||||
// if we have reached finalized block's sibling => stop with special signal
|
||||
if current_id.number == best_finalized.number && current_id.hash != best_finalized.hash {
|
||||
votes.stopped_at_finalized_sibling = true;
|
||||
return votes;
|
||||
@@ -687,14 +691,14 @@ impl<T: Trait> Storage for BridgeStorage<T> {
|
||||
}
|
||||
|
||||
// if we have found cached votes => stop
|
||||
let cached_votes = FinalityCache::<T>::get(¤t_id.hash);
|
||||
let cached_votes = FinalityCache::<T, I>::get(¤t_id.hash);
|
||||
if let Some(cached_votes) = cached_votes {
|
||||
votes.votes = Some(cached_votes);
|
||||
return votes;
|
||||
}
|
||||
|
||||
// read next parent header id
|
||||
let header = match Headers::<T>::get(¤t_id.hash) {
|
||||
let header = match Headers::<T, I>::get(¤t_id.hash) {
|
||||
Some(header) if header.header.number != 0 => header,
|
||||
_ => return votes,
|
||||
};
|
||||
@@ -717,10 +721,10 @@ impl<T: Trait> Storage for BridgeStorage<T> {
|
||||
submitter: Option<Self::Submitter>,
|
||||
parent_hash: &H256,
|
||||
) -> Option<ImportContext<Self::Submitter>> {
|
||||
Headers::<T>::get(parent_hash).map(|parent_header| {
|
||||
let validators_set = ValidatorsSets::get(parent_header.next_validators_set_id)
|
||||
Headers::<T, I>::get(parent_hash).map(|parent_header| {
|
||||
let validators_set = ValidatorsSets::<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::get(parent_hash);
|
||||
let parent_scheduled_change = ScheduledChanges::<I>::get(parent_hash);
|
||||
ImportContext {
|
||||
submitter,
|
||||
parent_hash: *parent_hash,
|
||||
@@ -735,15 +739,15 @@ impl<T: Trait> Storage for BridgeStorage<T> {
|
||||
}
|
||||
|
||||
fn scheduled_change(&self, hash: &H256) -> Option<ScheduledChange> {
|
||||
ScheduledChanges::get(hash)
|
||||
ScheduledChanges::<I>::get(hash)
|
||||
}
|
||||
|
||||
fn insert_header(&mut self, header: HeaderToImport<Self::Submitter>) {
|
||||
if header.is_best {
|
||||
BestBlock::put((header.id, header.total_difficulty));
|
||||
BestBlock::<I>::put((header.id, header.total_difficulty));
|
||||
}
|
||||
if let Some(scheduled_change) = header.scheduled_change {
|
||||
ScheduledChanges::insert(
|
||||
ScheduledChanges::<I>::insert(
|
||||
&header.id.hash,
|
||||
ScheduledChange {
|
||||
validators: scheduled_change,
|
||||
@@ -753,12 +757,12 @@ impl<T: Trait> Storage for BridgeStorage<T> {
|
||||
}
|
||||
let next_validators_set_id = match header.enacted_change {
|
||||
Some(enacted_change) => {
|
||||
let next_validators_set_id = NextValidatorsSetId::mutate(|set_id| {
|
||||
let next_validators_set_id = NextValidatorsSetId::<I>::mutate(|set_id| {
|
||||
let next_set_id = *set_id;
|
||||
*set_id += 1;
|
||||
next_set_id
|
||||
});
|
||||
ValidatorsSets::insert(
|
||||
ValidatorsSets::<I>::insert(
|
||||
next_validators_set_id,
|
||||
ValidatorsSet {
|
||||
validators: enacted_change.validators,
|
||||
@@ -766,11 +770,11 @@ impl<T: Trait> Storage for BridgeStorage<T> {
|
||||
signal_block: enacted_change.signal_block,
|
||||
},
|
||||
);
|
||||
ValidatorsSetsRc::insert(next_validators_set_id, 1);
|
||||
ValidatorsSetsRc::<I>::insert(next_validators_set_id, 1);
|
||||
next_validators_set_id
|
||||
}
|
||||
None => {
|
||||
ValidatorsSetsRc::mutate(header.context.validators_set_id, |rc| {
|
||||
ValidatorsSetsRc::<I>::mutate(header.context.validators_set_id, |rc| {
|
||||
*rc = Some(rc.map(|rc| rc + 1).unwrap_or(1));
|
||||
*rc
|
||||
});
|
||||
@@ -782,7 +786,7 @@ impl<T: Trait> Storage for BridgeStorage<T> {
|
||||
if let Some(finality_votes_caching_interval) = finality_votes_caching_interval {
|
||||
let cache_entry_required = header.id.number != 0 && header.id.number % finality_votes_caching_interval == 0;
|
||||
if cache_entry_required {
|
||||
FinalityCache::<T>::insert(header.id.hash, header.finality_votes);
|
||||
FinalityCache::<T, I>::insert(header.id.hash, header.finality_votes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -794,8 +798,8 @@ impl<T: Trait> Storage for BridgeStorage<T> {
|
||||
);
|
||||
|
||||
let last_signal_block = header.context.last_signal_block();
|
||||
HeadersByNumber::append(header.id.number, header.id.hash);
|
||||
Headers::<T>::insert(
|
||||
HeadersByNumber::<I>::append(header.id.number, header.id.hash);
|
||||
Headers::<T, I>::insert(
|
||||
&header.id.hash,
|
||||
StoredHeader {
|
||||
submitter: header.context.submitter,
|
||||
@@ -812,7 +816,7 @@ impl<T: Trait> Storage for BridgeStorage<T> {
|
||||
let finalized_number = finalized
|
||||
.as_ref()
|
||||
.map(|f| f.number)
|
||||
.unwrap_or_else(|| FinalizedBlock::get().number);
|
||||
.unwrap_or_else(|| FinalizedBlock::<I>::get().number);
|
||||
if let Some(finalized) = finalized {
|
||||
frame_support::debug::trace!(
|
||||
target: "runtime",
|
||||
@@ -821,7 +825,7 @@ impl<T: Trait> Storage for BridgeStorage<T> {
|
||||
finalized.hash,
|
||||
);
|
||||
|
||||
FinalizedBlock::put(finalized);
|
||||
FinalizedBlock::<I>::put(finalized);
|
||||
}
|
||||
|
||||
// and now prune headers if we need to
|
||||
@@ -831,7 +835,7 @@ impl<T: Trait> Storage for BridgeStorage<T> {
|
||||
|
||||
/// Initialize storage.
|
||||
#[cfg(any(feature = "std", feature = "runtime-benchmarks"))]
|
||||
pub(crate) fn initialize_storage<T: Trait>(
|
||||
pub(crate) fn initialize_storage<T: Trait<I>, I: Instance>(
|
||||
initial_header: &Header,
|
||||
initial_difficulty: U256,
|
||||
initial_validators: &[Address],
|
||||
@@ -848,14 +852,14 @@ pub(crate) fn initialize_storage<T: Trait>(
|
||||
number: initial_header.number,
|
||||
hash: initial_hash,
|
||||
};
|
||||
BestBlock::put((initial_id, initial_difficulty));
|
||||
FinalizedBlock::put(initial_id);
|
||||
BlocksToPrune::put(PruningRange {
|
||||
BestBlock::<I>::put((initial_id, initial_difficulty));
|
||||
FinalizedBlock::<I>::put(initial_id);
|
||||
BlocksToPrune::<I>::put(PruningRange {
|
||||
oldest_unpruned_block: initial_header.number,
|
||||
oldest_block_to_keep: initial_header.number,
|
||||
});
|
||||
HeadersByNumber::insert(initial_header.number, vec![initial_hash]);
|
||||
Headers::<T>::insert(
|
||||
HeadersByNumber::<I>::insert(initial_header.number, vec![initial_hash]);
|
||||
Headers::<T, I>::insert(
|
||||
initial_hash,
|
||||
StoredHeader {
|
||||
submitter: None,
|
||||
@@ -865,8 +869,8 @@ pub(crate) fn initialize_storage<T: Trait>(
|
||||
last_signal_block: None,
|
||||
},
|
||||
);
|
||||
NextValidatorsSetId::put(1);
|
||||
ValidatorsSets::insert(
|
||||
NextValidatorsSetId::<I>::put(1);
|
||||
ValidatorsSets::<I>::insert(
|
||||
0,
|
||||
ValidatorsSet {
|
||||
validators: initial_validators.to_vec(),
|
||||
@@ -874,7 +878,7 @@ pub(crate) fn initialize_storage<T: Trait>(
|
||||
enact_block: initial_id,
|
||||
},
|
||||
);
|
||||
ValidatorsSetsRc::insert(0, 1);
|
||||
ValidatorsSetsRc::<I>::insert(0, 1);
|
||||
}
|
||||
|
||||
/// Verify that transaction is included into given finalized block.
|
||||
@@ -988,7 +992,7 @@ pub(crate) mod tests {
|
||||
);
|
||||
|
||||
if i == 7 && j == 1 {
|
||||
ScheduledChanges::insert(
|
||||
ScheduledChanges::<DefaultInstance>::insert(
|
||||
hash,
|
||||
ScheduledChange {
|
||||
validators: validators_addresses(5),
|
||||
@@ -997,7 +1001,7 @@ pub(crate) mod tests {
|
||||
);
|
||||
}
|
||||
}
|
||||
HeadersByNumber::insert(i, headers_by_number);
|
||||
HeadersByNumber::<DefaultInstance>::insert(i, headers_by_number);
|
||||
}
|
||||
|
||||
f(BridgeStorage::new())
|
||||
@@ -1007,16 +1011,16 @@ pub(crate) mod tests {
|
||||
#[test]
|
||||
fn blocks_are_not_pruned_if_range_is_empty() {
|
||||
with_headers_to_prune(|storage| {
|
||||
BlocksToPrune::put(PruningRange {
|
||||
BlocksToPrune::<DefaultInstance>::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::get(&5).unwrap().len(), 5);
|
||||
assert_eq!(HeadersByNumber::<DefaultInstance>::get(&5).unwrap().len(), 5);
|
||||
assert_eq!(
|
||||
BlocksToPrune::get(),
|
||||
BlocksToPrune::<DefaultInstance>::get(),
|
||||
PruningRange {
|
||||
oldest_unpruned_block: 5,
|
||||
oldest_block_to_keep: 5,
|
||||
@@ -1028,7 +1032,7 @@ pub(crate) mod tests {
|
||||
#[test]
|
||||
fn blocks_to_prune_never_shrinks_from_the_end() {
|
||||
with_headers_to_prune(|storage| {
|
||||
BlocksToPrune::put(PruningRange {
|
||||
BlocksToPrune::<DefaultInstance>::put(PruningRange {
|
||||
oldest_unpruned_block: 0,
|
||||
oldest_block_to_keep: 5,
|
||||
});
|
||||
@@ -1036,7 +1040,7 @@ pub(crate) mod tests {
|
||||
// try to prune blocks [5; 10)
|
||||
storage.prune_blocks(0xFFFF, 10, 3);
|
||||
assert_eq!(
|
||||
BlocksToPrune::get(),
|
||||
BlocksToPrune::<DefaultInstance>::get(),
|
||||
PruningRange {
|
||||
oldest_unpruned_block: 5,
|
||||
oldest_block_to_keep: 5,
|
||||
@@ -1050,12 +1054,12 @@ pub(crate) mod tests {
|
||||
with_headers_to_prune(|storage| {
|
||||
// try to prune blocks [0; 10)
|
||||
storage.prune_blocks(0, 10, 10);
|
||||
assert!(HeadersByNumber::get(&0).is_some());
|
||||
assert!(HeadersByNumber::get(&1).is_some());
|
||||
assert!(HeadersByNumber::get(&2).is_some());
|
||||
assert!(HeadersByNumber::get(&3).is_some());
|
||||
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_eq!(
|
||||
BlocksToPrune::get(),
|
||||
BlocksToPrune::<DefaultInstance>::get(),
|
||||
PruningRange {
|
||||
oldest_unpruned_block: 0,
|
||||
oldest_block_to_keep: 10,
|
||||
@@ -1070,13 +1074,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::get(&0).is_none());
|
||||
assert!(HeadersByNumber::<DefaultInstance>::get(&0).is_none());
|
||||
// 5 headers with number = 1 are pruned (6 total)
|
||||
assert!(HeadersByNumber::get(&1).is_none());
|
||||
assert!(HeadersByNumber::<DefaultInstance>::get(&1).is_none());
|
||||
// 1 header with number = 2 are pruned (7 total)
|
||||
assert_eq!(HeadersByNumber::get(&2).unwrap().len(), 4);
|
||||
assert_eq!(HeadersByNumber::<DefaultInstance>::get(&2).unwrap().len(), 4);
|
||||
assert_eq!(
|
||||
BlocksToPrune::get(),
|
||||
BlocksToPrune::<DefaultInstance>::get(),
|
||||
PruningRange {
|
||||
oldest_unpruned_block: 2,
|
||||
oldest_block_to_keep: 10,
|
||||
@@ -1086,13 +1090,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::get(&2).is_none());
|
||||
assert!(HeadersByNumber::<DefaultInstance>::get(&2).is_none());
|
||||
// 5 headers with number = 3 are pruned (9 total)
|
||||
assert!(HeadersByNumber::get(&3).is_none());
|
||||
assert!(HeadersByNumber::<DefaultInstance>::get(&3).is_none());
|
||||
// 2 headers with number = 4 are pruned (11 total)
|
||||
assert_eq!(HeadersByNumber::get(&4).unwrap().len(), 3);
|
||||
assert_eq!(HeadersByNumber::<DefaultInstance>::get(&4).unwrap().len(), 3);
|
||||
assert_eq!(
|
||||
BlocksToPrune::get(),
|
||||
BlocksToPrune::<DefaultInstance>::get(),
|
||||
PruningRange {
|
||||
oldest_unpruned_block: 4,
|
||||
oldest_block_to_keep: 10,
|
||||
@@ -1109,16 +1113,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::get(&0).is_none());
|
||||
assert!(HeadersByNumber::get(&1).is_none());
|
||||
assert!(HeadersByNumber::get(&2).is_none());
|
||||
assert!(HeadersByNumber::get(&3).is_none());
|
||||
assert!(HeadersByNumber::get(&4).is_none());
|
||||
assert!(HeadersByNumber::get(&5).is_none());
|
||||
assert!(HeadersByNumber::get(&6).is_none());
|
||||
assert_eq!(HeadersByNumber::get(&7).unwrap().len(), 5);
|
||||
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_eq!(
|
||||
BlocksToPrune::get(),
|
||||
BlocksToPrune::<DefaultInstance>::get(),
|
||||
PruningRange {
|
||||
oldest_unpruned_block: 7,
|
||||
oldest_block_to_keep: 10,
|
||||
@@ -1151,7 +1155,7 @@ pub(crate) mod tests {
|
||||
);
|
||||
|
||||
// when we later prune this header, cache entry is removed
|
||||
BlocksToPrune::put(PruningRange {
|
||||
BlocksToPrune::<DefaultInstance>::put(PruningRange {
|
||||
oldest_unpruned_block: interval - 1,
|
||||
oldest_block_to_keep: interval - 1,
|
||||
});
|
||||
@@ -1238,7 +1242,7 @@ pub(crate) mod tests {
|
||||
insert_header(&mut storage, header1s);
|
||||
|
||||
// header1 is finalized
|
||||
FinalizedBlock::put(header1_id);
|
||||
FinalizedBlock::<DefaultInstance>::put(header1_id);
|
||||
|
||||
// trying to get finality votes when importing header2 -> header1 succeeds
|
||||
assert!(
|
||||
|
||||
@@ -136,7 +136,7 @@ pub fn run_test_with_genesis<T>(genesis: Header, total_validators: usize, test:
|
||||
initial_difficulty: 0.into(),
|
||||
initial_validators: addresses.clone(),
|
||||
}
|
||||
.build_storage::<TestRuntime>()
|
||||
.build_storage::<TestRuntime, crate::DefaultInstance>()
|
||||
.unwrap(),
|
||||
)
|
||||
.execute_with(|| {
|
||||
|
||||
@@ -63,31 +63,31 @@ 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>(parent_hash)
|
||||
Self::with_parent_hash_on_runtime::<crate::mock::TestRuntime, crate::DefaultInstance>(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>(parent_number)
|
||||
Self::with_parent_number_on_runtime::<crate::mock::TestRuntime, crate::DefaultInstance>(parent_number)
|
||||
}
|
||||
|
||||
/// Creates default header on top of parent with given hash.
|
||||
pub fn with_parent_hash_on_runtime<T: Trait>(parent_hash: H256) -> Self {
|
||||
pub fn with_parent_hash_on_runtime<T: Trait<I>, I: crate::Instance>(parent_hash: H256) -> Self {
|
||||
use crate::Headers;
|
||||
use frame_support::StorageMap;
|
||||
|
||||
let parent_header = Headers::<T>::get(&parent_hash).unwrap().header;
|
||||
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: Trait>(parent_number: u64) -> Self {
|
||||
pub fn with_parent_number_on_runtime<T: Trait<I>, I: crate::Instance>(parent_number: u64) -> Self {
|
||||
use crate::HeadersByNumber;
|
||||
use frame_support::StorageMap;
|
||||
|
||||
let parent_hash = HeadersByNumber::get(parent_number).unwrap()[0];
|
||||
Self::with_parent_hash_on_runtime::<T>(parent_hash)
|
||||
let parent_hash = HeadersByNumber::<I>::get(parent_number).unwrap()[0];
|
||||
Self::with_parent_hash_on_runtime::<T, I>(parent_hash)
|
||||
}
|
||||
|
||||
/// Creates default header on top of non-existent parent.
|
||||
|
||||
@@ -276,6 +276,7 @@ impl ValidatorsSource {
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
use crate::mock::{run_test, validators_addresses, validators_change_receipt, TestRuntime};
|
||||
use crate::DefaultInstance;
|
||||
use crate::{BridgeStorage, Headers, ScheduledChange, ScheduledChanges, StoredHeader};
|
||||
use frame_support::StorageMap;
|
||||
use primitives::compute_merkle_root;
|
||||
@@ -433,7 +434,7 @@ pub(crate) mod tests {
|
||||
};
|
||||
Headers::<TestRuntime>::insert(id100.hash, header100);
|
||||
if let Some(scheduled_at) = scheduled_at {
|
||||
ScheduledChanges::insert(scheduled_at.hash, scheduled_change);
|
||||
ScheduledChanges::<DefaultInstance>::insert(scheduled_at.hash, scheduled_change);
|
||||
}
|
||||
|
||||
validators.finalize_validators_change(&storage, &finalized_blocks)
|
||||
|
||||
@@ -361,6 +361,7 @@ mod tests {
|
||||
validators_change_receipt, AccountId, HeaderBuilder, TestRuntime, GAS_LIMIT,
|
||||
};
|
||||
use crate::validators::ValidatorsSource;
|
||||
use crate::DefaultInstance;
|
||||
use crate::{
|
||||
pool_configuration, BridgeStorage, FinalizedBlock, Headers, HeadersByNumber, NextValidatorsSetId,
|
||||
ScheduledChanges, ValidatorsSet, ValidatorsSets,
|
||||
@@ -402,7 +403,7 @@ mod tests {
|
||||
let block3 = HeaderBuilder::with_parent_number(2).sign_by_set(&validators);
|
||||
insert_header(&mut storage, block3);
|
||||
|
||||
FinalizedBlock::put(block2_id);
|
||||
FinalizedBlock::<DefaultInstance>::put(block2_id);
|
||||
|
||||
let validators_config =
|
||||
ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new()));
|
||||
@@ -419,21 +420,21 @@ mod tests {
|
||||
}
|
||||
|
||||
fn change_validators_set_at(number: u64, finalized_set: Vec<Address>, signalled_set: Option<Vec<Address>>) {
|
||||
let set_id = NextValidatorsSetId::get();
|
||||
NextValidatorsSetId::put(set_id + 1);
|
||||
ValidatorsSets::insert(
|
||||
let set_id = NextValidatorsSetId::<DefaultInstance>::get();
|
||||
NextValidatorsSetId::<DefaultInstance>::put(set_id + 1);
|
||||
ValidatorsSets::<DefaultInstance>::insert(
|
||||
set_id,
|
||||
ValidatorsSet {
|
||||
validators: finalized_set,
|
||||
signal_block: None,
|
||||
enact_block: HeaderId {
|
||||
number: 0,
|
||||
hash: HeadersByNumber::get(&0).unwrap()[0],
|
||||
hash: HeadersByNumber::<DefaultInstance>::get(&0).unwrap()[0],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
let header_hash = HeadersByNumber::get(&number).unwrap()[0];
|
||||
let header_hash = HeadersByNumber::<DefaultInstance>::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 {
|
||||
@@ -441,7 +442,7 @@ mod tests {
|
||||
number: header.header.number - 1,
|
||||
hash: header.header.parent_hash,
|
||||
});
|
||||
ScheduledChanges::insert(
|
||||
ScheduledChanges::<DefaultInstance>::insert(
|
||||
header.header.parent_hash,
|
||||
ScheduledChange {
|
||||
validators: signalled_set,
|
||||
|
||||
Reference in New Issue
Block a user