diff --git a/bridges/bin/node/node/Cargo.toml b/bridges/bin/node/node/Cargo.toml index 84edf0183e35..f60ad3ac0c82 100644 --- a/bridges/bin/node/node/Cargo.toml +++ b/bridges/bin/node/node/Cargo.toml @@ -146,9 +146,7 @@ tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [features] -default = ["bridge-rialto"] -bridge-kovan = ["bridge-node-runtime/bridge-kovan"] -bridge-rialto = ["bridge-node-runtime/bridge-rialto"] +default = [] runtime-benchmarks = [ "bridge-node-runtime/runtime-benchmarks", ] diff --git a/bridges/bin/node/node/src/chain_spec.rs b/bridges/bin/node/node/src/chain_spec.rs index 425448b921c2..12c97f140e9d 100644 --- a/bridges/bin/node/node/src/chain_spec.rs +++ b/bridges/bin/node/node/src/chain_spec.rs @@ -15,8 +15,8 @@ // along with Parity Bridges Common. If not, see . use bridge_node_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeEthPoAConfig, GenesisConfig, GrandpaConfig, SessionConfig, - SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, + AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoConfig, GenesisConfig, GrandpaConfig, + SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use grandpa_primitives::AuthorityId as GrandpaId; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -152,7 +152,8 @@ fn testnet_genesis( pallet_aura: Some(AuraConfig { authorities: Vec::new(), }), - pallet_bridge_eth_poa: load_bridge_config(), + pallet_bridge_eth_poa_Instance1: load_rialto_bridge_config(), + pallet_bridge_eth_poa_Instance2: load_kovan_bridge_config(), pallet_grandpa: Some(GrandpaConfig { authorities: Vec::new(), }), @@ -166,10 +167,18 @@ fn testnet_genesis( } } -fn load_bridge_config() -> Option { - Some(BridgeEthPoAConfig { - initial_header: bridge_node_runtime::bridge::genesis_header(), +fn load_rialto_bridge_config() -> Option { + Some(BridgeRialtoConfig { + initial_header: bridge_node_runtime::rialto::genesis_header(), initial_difficulty: 0.into(), - initial_validators: bridge_node_runtime::bridge::genesis_validators(), + initial_validators: bridge_node_runtime::rialto::genesis_validators(), + }) +} + +fn load_kovan_bridge_config() -> Option { + Some(BridgeKovanConfig { + initial_header: bridge_node_runtime::kovan::genesis_header(), + initial_difficulty: 0.into(), + initial_validators: bridge_node_runtime::kovan::genesis_validators(), }) } diff --git a/bridges/bin/node/runtime/Cargo.toml b/bridges/bin/node/runtime/Cargo.toml index c1437ae4d511..755dc99b343f 100644 --- a/bridges/bin/node/runtime/Cargo.toml +++ b/bridges/bin/node/runtime/Cargo.toml @@ -224,9 +224,7 @@ package = "substrate-wasm-builder-runner" git = "https://github.com/paritytech/substrate/" [features] -default = ["std", "bridge-rialto"] -bridge-kovan = [] -bridge-rialto = [] +default = ["std"] std = [ "pallet-aura/std", "pallet-balances/std", @@ -268,5 +266,4 @@ runtime-benchmarks = [ "pallet-bridge-eth-poa/runtime-benchmarks", "sp-bridge-eth-poa/test-helpers", "sp-runtime/runtime-benchmarks", - "bridge-kovan", ] diff --git a/bridges/bin/node/runtime/src/exchange.rs b/bridges/bin/node/runtime/src/exchange.rs index 75b2007bff28..e41ec9ac4049 100644 --- a/bridges/bin/node/runtime/src/exchange.rs +++ b/bridges/bin/node/runtime/src/exchange.rs @@ -30,7 +30,6 @@ use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use hex_literal::hex; -use pallet_bridge_currency_exchange::Blockchain; use sp_bridge_eth_poa::{transaction_decode, RawTransaction}; use sp_currency_exchange::{ Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, Result as ExchangeResult, @@ -65,25 +64,6 @@ pub struct EthereumTransactionTag { pub nonce: sp_core::U256, } -/// Eth blockchain from runtime perspective. -pub struct EthBlockchain; - -impl Blockchain for EthBlockchain { - type Transaction = RawTransaction; - type TransactionInclusionProof = EthereumTransactionInclusionProof; - - fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { - let is_transaction_finalized = - crate::BridgeEthPoA::verify_transaction_finalized(proof.block, proof.index, &proof.proof); - - if !is_transaction_finalized { - return None; - } - - proof.proof.get(proof.index as usize).cloned() - } -} - /// Eth transaction from runtime perspective. pub struct EthTransaction; @@ -147,7 +127,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( +pub(crate) fn prepare_environment_for_claim, I: pallet_bridge_eth_poa::Instance>( transactions: &[RawTransaction], ) -> sp_bridge_eth_poa::H256 { use pallet_bridge_eth_poa::{ @@ -156,8 +136,8 @@ pub(crate) fn prepare_environment_for_claim( }; use sp_bridge_eth_poa::compute_merkle_root; - let mut storage = BridgeStorage::::new(); - let header = HeaderBuilder::with_parent_number_on_runtime::(0) + let mut storage = BridgeStorage::::new(); + let header = HeaderBuilder::with_parent_number_on_runtime::(0) .with_transactions_root(compute_merkle_root(transactions.iter())) .sign_by(&validator(0)); let header_id = header.compute_id(); diff --git a/bridges/bin/node/runtime/src/kovan.rs b/bridges/bin/node/runtime/src/kovan.rs index fe62fce163b1..ad641aa728a6 100644 --- a/bridges/bin/node/runtime/src/kovan.rs +++ b/bridges/bin/node/runtime/src/kovan.rs @@ -14,12 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::exchange::EthereumTransactionInclusionProof; + use frame_support::RuntimeDebug; use hex_literal::hex; +use pallet_bridge_currency_exchange::PeerBlockchain; use pallet_bridge_eth_poa::{ AuraConfiguration, PruningStrategy as BridgePruningStrategy, ValidatorsConfiguration, ValidatorsSource, }; -use sp_bridge_eth_poa::{Address, Header, U256}; +use sp_bridge_eth_poa::{Address, Header, RawTransaction, U256}; use sp_std::prelude::*; frame_support::parameter_types! { @@ -131,6 +134,25 @@ impl BridgePruningStrategy for PruningStrategy { } } +/// The Kovan Blockchain as seen by the runtime. +pub struct KovanBlockchain; + +impl PeerBlockchain for KovanBlockchain { + type Transaction = RawTransaction; + type TransactionInclusionProof = EthereumTransactionInclusionProof; + + fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { + let is_transaction_finalized = + crate::BridgeKovan::verify_transaction_finalized(proof.block, proof.index, &proof.proof); + + if !is_transaction_finalized { + return None; + } + + proof.proof.get(proof.index as usize).cloned() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/bridges/bin/node/runtime/src/lib.rs b/bridges/bin/node/runtime/src/lib.rs index 9f473fee9d8b..6c4ad00692e4 100644 --- a/bridges/bin/node/runtime/src/lib.rs +++ b/bridges/bin/node/runtime/src/lib.rs @@ -32,17 +32,11 @@ pub mod exchange; #[cfg(feature = "runtime-benchmarks")] pub mod benches; -#[cfg(feature = "bridge-kovan")] pub mod kovan; -#[cfg(feature = "bridge-rialto")] pub mod rialto; #[cfg(feature = "runtime-benchmarks")] pub use benches as bridge; -#[cfg(all(feature = "bridge-kovan", not(feature = "runtime-benchmarks")))] -pub use kovan as bridge; -#[cfg(all(feature = "bridge-rialto", not(feature = "runtime-benchmarks")))] -pub use rialto as bridge; use codec::{Decode, Encode}; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; @@ -69,10 +63,12 @@ pub use frame_support::{ weights::{IdentityFee, RuntimeDbWeight, Weight}, StorageValue, }; + pub use pallet_balances::Call as BalancesCall; pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall; pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; pub use pallet_timestamp::Call as TimestampCall; + #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; pub use sp_runtime::{Perbill, Permill}; @@ -233,17 +229,39 @@ impl pallet_aura::Trait for Runtime { type AuthorityId = AuraId; } -impl pallet_bridge_eth_poa::Trait for Runtime { - type AuraConfiguration = bridge::BridgeAuraConfiguration; - type FinalityVotesCachingInterval = bridge::FinalityVotesCachingInterval; - type ValidatorsConfiguration = bridge::BridgeValidatorsConfiguration; - type PruningStrategy = bridge::PruningStrategy; +type Rialto = pallet_bridge_eth_poa::Instance1; +impl pallet_bridge_eth_poa::Trait for Runtime { + type AuraConfiguration = rialto::BridgeAuraConfiguration; + type FinalityVotesCachingInterval = rialto::FinalityVotesCachingInterval; + type ValidatorsConfiguration = rialto::BridgeValidatorsConfiguration; + type PruningStrategy = rialto::PruningStrategy; + type OnHeadersSubmitted = (); +} + +type Kovan = pallet_bridge_eth_poa::Instance2; +impl pallet_bridge_eth_poa::Trait for Runtime { + type AuraConfiguration = kovan::BridgeAuraConfiguration; + type FinalityVotesCachingInterval = kovan::FinalityVotesCachingInterval; + type ValidatorsConfiguration = kovan::BridgeValidatorsConfiguration; + type PruningStrategy = kovan::PruningStrategy; type OnHeadersSubmitted = (); } -impl pallet_bridge_currency_exchange::Trait for Runtime { +type RialtoCurrencyExchange = pallet_bridge_currency_exchange::Instance1; +impl pallet_bridge_currency_exchange::Trait for Runtime { type OnTransactionSubmitted = (); - type PeerBlockchain = exchange::EthBlockchain; + type PeerBlockchain = rialto::RialtoBlockchain; + type PeerMaybeLockFundsTransaction = exchange::EthTransaction; + type RecipientsMap = sp_currency_exchange::IdentityRecipients; + type Amount = Balance; + type CurrencyConverter = sp_currency_exchange::IdentityCurrencyConverter; + type DepositInto = DepositInto; +} + +type KovanCurrencyExchange = pallet_bridge_currency_exchange::Instance2; +impl pallet_bridge_currency_exchange::Trait for Runtime { + type OnTransactionSubmitted = (); + type PeerBlockchain = kovan::KovanBlockchain; type PeerMaybeLockFundsTransaction = exchange::EthTransaction; type RecipientsMap = sp_currency_exchange::IdentityRecipients; type Amount = Balance; @@ -439,6 +457,10 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { + BridgeRialto: pallet_bridge_eth_poa::::{Module, Call, Config, Storage, ValidateUnsigned}, + BridgeKovan: pallet_bridge_eth_poa::::{Module, Call, Config, Storage, ValidateUnsigned}, + BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, + BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, @@ -448,8 +470,6 @@ construct_runtime!( TransactionPayment: pallet_transaction_payment::{Module, Storage}, Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, Session: pallet_session::{Module, Call, Storage, Event, Config}, - BridgeEthPoA: pallet_bridge_eth_poa::{Module, Call, Config, Storage, ValidateUnsigned}, - BridgeCurrencyExchange: pallet_bridge_currency_exchange::{Module, Call}, } ); @@ -535,32 +555,59 @@ impl_runtime_apis! { } } - impl sp_bridge_eth_poa::EthereumHeadersApi for Runtime { + impl sp_bridge_eth_poa::RialtoHeaderApi for Runtime { fn best_block() -> (u64, sp_bridge_eth_poa::H256) { - let best_block = BridgeEthPoA::best_block(); + let best_block = BridgeRialto::best_block(); (best_block.number, best_block.hash) } fn finalized_block() -> (u64, sp_bridge_eth_poa::H256) { - let finalized_block = BridgeEthPoA::finalized_block(); + let finalized_block = BridgeRialto::finalized_block(); (finalized_block.number, finalized_block.hash) } fn is_import_requires_receipts(header: sp_bridge_eth_poa::Header) -> bool { - BridgeEthPoA::is_import_requires_receipts(header) + BridgeRialto::is_import_requires_receipts(header) } fn is_known_block(hash: sp_bridge_eth_poa::H256) -> bool { - BridgeEthPoA::is_known_block(hash) + BridgeRialto::is_known_block(hash) } } - impl sp_currency_exchange::CurrencyExchangeApi for Runtime { + impl sp_bridge_eth_poa::KovanHeaderApi for Runtime { + fn best_block() -> (u64, sp_bridge_eth_poa::H256) { + let best_block = BridgeKovan::best_block(); + (best_block.number, best_block.hash) + } + + fn finalized_block() -> (u64, sp_bridge_eth_poa::H256) { + let finalized_block = BridgeKovan::finalized_block(); + (finalized_block.number, finalized_block.hash) + } + + fn is_import_requires_receipts(header: sp_bridge_eth_poa::Header) -> bool { + BridgeKovan::is_import_requires_receipts(header) + } + + fn is_known_block(hash: sp_bridge_eth_poa::H256) -> bool { + BridgeKovan::is_known_block(hash) + } + } + + impl sp_currency_exchange::RialtoCurrencyExchangeApi for Runtime { + fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { + BridgeRialtoCurrencyExchange::filter_transaction_proof(&proof) + } + } + + impl sp_currency_exchange::KovanCurrencyExchangeApi for Runtime { fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { - BridgeCurrencyExchange::filter_transaction_proof(&proof) + BridgeKovanCurrencyExchange::filter_transaction_proof(&proof) } } + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction( source: TransactionSource, @@ -656,14 +703,14 @@ impl_runtime_apis! { ProofParams as BridgeCurrencyExchangeProofParams, }; - impl BridgeCurrencyExchangeTrait for Runtime { + impl BridgeCurrencyExchangeTrait for Runtime { fn make_proof( proof_params: BridgeCurrencyExchangeProofParams, ) -> crate::exchange::EthereumTransactionInclusionProof { use sp_currency_exchange::DepositInto; if proof_params.recipient_exists { - ::DepositInto::deposit_into( + >::DepositInto::deposit_into( proof_params.recipient.clone(), ExistentialDeposit::get(), ).unwrap(); @@ -681,7 +728,7 @@ impl_runtime_apis! { let transactions = sp_std::iter::repeat(transaction.clone()) .take(1 + proof_params.proof_size_factor as usize) .collect::>(); - let block_hash = crate::exchange::prepare_environment_for_claim::(&transactions); + let block_hash = crate::exchange::prepare_environment_for_claim::(&transactions); crate::exchange::EthereumTransactionInclusionProof { block: block_hash, index: 0, @@ -690,8 +737,8 @@ impl_runtime_apis! { } } - add_benchmark!(params, batches, b"bridge-eth-poa", BridgeEthPoA); - add_benchmark!(params, batches, b"bridge-currency-exchange", BridgeCurrencyExchangeBench::); + add_benchmark!(params, batches, b"bridge-eth-poa", BridgeKovan); + add_benchmark!(params, batches, b"bridge-currency-exchange", BridgeCurrencyExchangeBench::); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) @@ -785,7 +832,7 @@ mod tests { let initial_amount = as Currency>::free_balance(&existing_account); let additional_amount = 10_000; - ::DepositInto::deposit_into( + >::DepositInto::deposit_into( existing_account.clone(), additional_amount, ) @@ -804,7 +851,7 @@ mod tests { let initial_amount = 0; let additional_amount = ExistentialDeposit::get() + 10_000; let new_account: AccountId = [42u8; 32].into(); - ::DepositInto::deposit_into( + >::DepositInto::deposit_into( new_account.clone(), additional_amount, ) diff --git a/bridges/bin/node/runtime/src/rialto.rs b/bridges/bin/node/runtime/src/rialto.rs index cdc314fb480c..6560dbb39809 100644 --- a/bridges/bin/node/runtime/src/rialto.rs +++ b/bridges/bin/node/runtime/src/rialto.rs @@ -14,12 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::exchange::EthereumTransactionInclusionProof; + use frame_support::RuntimeDebug; use hex_literal::hex; +use pallet_bridge_currency_exchange::PeerBlockchain; use pallet_bridge_eth_poa::{ AuraConfiguration, PruningStrategy as TPruningStrategy, ValidatorsConfiguration, ValidatorsSource, }; -use sp_bridge_eth_poa::{Address, Header, U256}; +use sp_bridge_eth_poa::{Address, Header, RawTransaction, U256}; use sp_std::prelude::*; frame_support::parameter_types! { @@ -104,6 +107,25 @@ impl TPruningStrategy for PruningStrategy { } } +/// The Rialto Blockchain as seen by the runtime. +pub struct RialtoBlockchain; + +impl PeerBlockchain for RialtoBlockchain { + type Transaction = RawTransaction; + type TransactionInclusionProof = EthereumTransactionInclusionProof; + + fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { + let is_transaction_finalized = + crate::BridgeRialto::verify_transaction_finalized(proof.block, proof.index, &proof.proof); + + if !is_transaction_finalized { + return None; + } + + proof.proof.get(proof.index as usize).cloned() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/bridges/modules/currency-exchange/src/benchmarking.rs b/bridges/modules/currency-exchange/src/benchmarking.rs index dc032720ce3c..30fb7e63f007 100644 --- a/bridges/modules/currency-exchange/src/benchmarking.rs +++ b/bridges/modules/currency-exchange/src/benchmarking.rs @@ -18,10 +18,10 @@ //! So we are giving runtime opportunity to prepare environment and construct proof //! before invoking module calls. -use super::{Blockchain, Call, Module as CurrencyExchangeModule, Trait as CurrencyExchangeTrait}; +use super::{Call, Instance, Module as CurrencyExchangeModule, PeerBlockchain, Trait as CurrencyExchangeTrait}; use sp_std::prelude::*; -use frame_benchmarking::{account, benchmarks}; +use frame_benchmarking::{account, benchmarks_instance}; use frame_system::RawOrigin; const SEED: u32 = 0; @@ -29,7 +29,7 @@ const WORST_TX_SIZE_FACTOR: u32 = 1000; const WORST_PROOF_SIZE_FACTOR: u32 = 1000; /// Module we're benchmarking here. -pub struct Module(CurrencyExchangeModule); +pub struct Module, I: Instance>(CurrencyExchangeModule); /// Proof benchmarking parameters. pub struct ProofParams { @@ -46,14 +46,14 @@ pub struct ProofParams { } /// Trait that must be implemented by runtime. -pub trait Trait: CurrencyExchangeTrait { +pub trait Trait: CurrencyExchangeTrait { /// Prepare proof for importing exchange transaction. fn make_proof( proof_params: ProofParams, - ) -> <::PeerBlockchain as Blockchain>::TransactionInclusionProof; + ) -> <>::PeerBlockchain as PeerBlockchain>::TransactionInclusionProof; } -benchmarks! { +benchmarks_instance! { _ { } // Benchmark `import_peer_transaction` extrinsic with the best possible conditions: diff --git a/bridges/modules/currency-exchange/src/lib.rs b/bridges/modules/currency-exchange/src/lib.rs index 1c39e1aea932..cf03239c8a66 100644 --- a/bridges/modules/currency-exchange/src/lib.rs +++ b/bridges/modules/currency-exchange/src/lib.rs @@ -33,8 +33,8 @@ pub trait OnTransactionSubmitted { fn on_valid_transaction_submitted(submitter: AccountId); } -/// Peer blockhain interface. -pub trait Blockchain { +/// Peer blockchain interface. +pub trait PeerBlockchain { /// Transaction type. type Transaction: Parameter; /// Transaction inclusion proof type. @@ -47,14 +47,14 @@ pub trait Blockchain { } /// The module configuration trait -pub trait Trait: frame_system::Trait { +pub trait Trait: frame_system::Trait { /// Handler for transaction submission result. type OnTransactionSubmitted: OnTransactionSubmitted; - /// Peer blockchain type. - type PeerBlockchain: Blockchain; + /// Represents the blockchain that we'll be exchanging currency with. + type PeerBlockchain: PeerBlockchain; /// Peer blockchain transaction parser. type PeerMaybeLockFundsTransaction: MaybeLockFundsTransaction< - Transaction = ::Transaction, + Transaction = ::Transaction, >; /// Map between blockchains recipients. type RecipientsMap: RecipientsMap< @@ -73,7 +73,7 @@ pub trait Trait: frame_system::Trait { } decl_error! { - pub enum Error for Module { + pub enum Error for Module, I: Instance> { /// Invalid peer blockchain transaction provided. InvalidTransaction, /// Peer transaction has invalid amount. @@ -96,17 +96,17 @@ decl_error! { } decl_module! { - pub struct Module for enum Call where origin: T::Origin { + pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { /// Imports lock fund transaction of the peer blockchain. #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn import_peer_transaction( origin, - proof: <::PeerBlockchain as Blockchain>::TransactionInclusionProof, + proof: <>::PeerBlockchain as PeerBlockchain>::TransactionInclusionProof, ) -> DispatchResult { let submitter = frame_system::ensure_signed(origin)?; // verify and parse transaction proof - let deposit = prepare_deposit_details::(&proof)?; + let deposit = prepare_deposit_details::(&proof)?; // make sure to update the mapping if we deposit successfully to avoid double spending, // i.e. whenever `deposit_into` is successful we MUST update `Transfers`. @@ -117,9 +117,9 @@ decl_module! { match deposit_result { Ok(_) => (), Err(ExchangeError::DepositPartiallyFailed) => (), - Err(error) => return Err(Error::::from(error).into()), + Err(error) => return Err(Error::::from(error).into()), } - Transfers::::insert(&deposit.transfer_id, ()) + Transfers::::insert(&deposit.transfer_id, ()) } // reward submitter for providing valid message @@ -137,17 +137,17 @@ decl_module! { } decl_storage! { - trait Store for Module as Bridge { + trait Store for Module, I: Instance = DefaultInstance> as Bridge { /// All transfers that have already been claimed. Transfers: map hasher(blake2_128_concat) ::Id => (); } } -impl Module { +impl, I: Instance> Module { /// Returns true if currency exchange module is able to import given transaction proof in /// its current state. - pub fn filter_transaction_proof(proof: &::TransactionInclusionProof) -> bool { - if prepare_deposit_details::(proof).is_err() { + pub fn filter_transaction_proof(proof: &::TransactionInclusionProof) -> bool { + if prepare_deposit_details::(proof).is_err() { return false; } @@ -155,7 +155,7 @@ impl Module { } } -impl From for Error { +impl, I: Instance> From for Error { fn from(error: ExchangeError) -> Self { match error { ExchangeError::InvalidTransaction => Error::InvalidTransaction, @@ -174,7 +174,7 @@ impl OnTransactionSubmitted for () { } /// Exchange deposit details. -struct DepositDetails { +struct DepositDetails, I: Instance> { /// Transfer id. pub transfer_id: ::Id, /// Transfer recipient. @@ -185,21 +185,25 @@ struct DepositDetails { /// Verify and parse transaction proof, preparing everything required for importing /// this transaction proof. -fn prepare_deposit_details( - proof: &<::PeerBlockchain as Blockchain>::TransactionInclusionProof, -) -> Result, Error> { +fn prepare_deposit_details, I: Instance>( + proof: &<>::PeerBlockchain as PeerBlockchain>::TransactionInclusionProof, +) -> Result, Error> { // ensure that transaction is included in finalized block that we know of - let transaction = ::PeerBlockchain::verify_transaction_inclusion_proof(proof) - .ok_or_else(|| Error::::UnfinalizedTransaction)?; + let transaction = >::PeerBlockchain::verify_transaction_inclusion_proof(proof) + .ok_or_else(|| Error::::UnfinalizedTransaction)?; // parse transaction - let transaction = ::PeerMaybeLockFundsTransaction::parse(&transaction).map_err(Error::::from)?; + let transaction = + >::PeerMaybeLockFundsTransaction::parse(&transaction).map_err(Error::::from)?; let transfer_id = transaction.id; - ensure!(!Transfers::::contains_key(&transfer_id), Error::::AlreadyClaimed); + ensure!( + !Transfers::::contains_key(&transfer_id), + Error::::AlreadyClaimed + ); // grant recipient - let recipient = T::RecipientsMap::map(transaction.recipient).map_err(Error::::from)?; - let amount = T::CurrencyConverter::convert(transaction.amount).map_err(Error::::from)?; + let recipient = T::RecipientsMap::map(transaction.recipient).map_err(Error::::from)?; + let amount = T::CurrencyConverter::convert(transaction.amount).map_err(Error::::from)?; Ok(DepositDetails { transfer_id, @@ -235,13 +239,13 @@ mod tests { impl OnTransactionSubmitted for DummyTransactionSubmissionHandler { fn on_valid_transaction_submitted(submitter: AccountId) { - Transfers::::insert(submitter, ()); + Transfers::::insert(submitter, ()); } } pub struct DummyBlockchain; - impl Blockchain for DummyBlockchain { + impl PeerBlockchain for DummyBlockchain { type Transaction = RawTransaction; type TransactionInclusionProof = (bool, RawTransaction); @@ -386,7 +390,7 @@ mod tests { new_test_ext().execute_with(|| { assert_noop!( Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (false, transaction(0))), - Error::::UnfinalizedTransaction, + Error::::UnfinalizedTransaction, ); }); } @@ -399,7 +403,7 @@ mod tests { Origin::signed(SUBMITTER), (true, transaction(INVALID_TRANSACTION_ID)), ), - Error::::InvalidTransaction, + Error::::InvalidTransaction, ); }); } @@ -413,7 +417,7 @@ mod tests { Origin::signed(SUBMITTER), (true, transaction(ALREADY_CLAIMED_TRANSACTION_ID)), ), - Error::::AlreadyClaimed, + Error::::AlreadyClaimed, ); }); } @@ -425,7 +429,7 @@ mod tests { transaction.recipient = UNKNOWN_RECIPIENT_ID; assert_noop!( Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), - Error::::FailedToMapRecipients, + Error::::FailedToMapRecipients, ); }); } @@ -437,7 +441,7 @@ mod tests { transaction.amount = INVALID_AMOUNT; assert_noop!( Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), - Error::::FailedToConvertCurrency, + Error::::FailedToConvertCurrency, ); }); } @@ -449,7 +453,7 @@ mod tests { transaction.amount = MAX_DEPOSIT_AMOUNT + 1; assert_noop!( Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), - Error::::DepositFailed, + Error::::DepositFailed, ); }); } diff --git a/bridges/modules/ethereum/src/benchmarking.rs b/bridges/modules/ethereum/src/benchmarking.rs index 1f0a7fbe96f2..1da7019c6408 100644 --- a/bridges/modules/ethereum/src/benchmarking.rs +++ b/bridges/modules/ethereum/src/benchmarking.rs @@ -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::(num_validators); + let initial_header = initialize_bench::(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::::new(); + let storage = BridgeStorage::::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::::new(); + let mut storage = BridgeStorage::::new(); let num_validators: u32 = 2; - let initial_header = initialize_bench::(num_validators as usize); + let initial_header = initialize_bench::(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::::new(); + let storage = BridgeStorage::::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::::new(); + let mut storage = BridgeStorage::::new(); let num_validators: u32 = 2; - let initial_header = initialize_bench::(num_validators as usize); + let initial_header = initialize_bench::(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::::new(); + let storage = BridgeStorage::::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::::new(); + let mut storage = BridgeStorage::::new(); let num_validators = 3; - let initial_header = initialize_bench::(num_validators as usize); + let initial_header = initialize_bench::(num_validators as usize); let validators = validators(num_validators); // Want to prune eligible blocks between [0, n) - BlocksToPrune::put(PruningRange { + BlocksToPrune::::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::::new(); + let storage = BridgeStorage::::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::::get(&0).is_none()); + assert!(HeadersByNumber::::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::::new(); + let mut storage = BridgeStorage::::new(); let num_validators = 1; - let initial_header = initialize_bench::(num_validators as usize); + let initial_header = initialize_bench::(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::::new(); + let storage = BridgeStorage::::new(); assert_eq!(storage.best_block().0.number, 2); } } -fn initialize_bench(num_validators: usize) -> Header { +fn initialize_bench, 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::(&initial_header, initial_difficulty, &initial_validators); + initialize_storage::(&initial_header, initial_difficulty, &initial_validators); initial_header } diff --git a/bridges/modules/ethereum/src/import.rs b/bridges/modules/ethereum/src/import.rs index 490c164e47b5..20c86cf6eb8b 100644 --- a/bridges/modules/ethereum/src/import.rs +++ b/bridges/modules/ethereum/src/import.rs @@ -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::::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::::get(), PruningRange { oldest_unpruned_block: 15, oldest_block_to_keep: 15, diff --git a/bridges/modules/ethereum/src/lib.rs b/bridges/modules/ethereum/src/lib.rs index bfae5d4b260c..de25c5aaa218 100644 --- a/bridges/modules/ethereum/src/lib.rs +++ b/bridges/modules/ethereum/src/lib.rs @@ -351,7 +351,7 @@ impl OnHeadersSubmitted for () { } /// The module configuration trait. -pub trait Trait: frame_system::Trait { +pub trait Trait: frame_system::Trait { /// Aura configuration. type AuraConfiguration: Get; /// Validators configuration. @@ -372,14 +372,14 @@ pub trait Trait: frame_system::Trait { } decl_module! { - pub struct Module for enum Call where origin: T::Origin { + pub struct Module, 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>) { frame_system::ensure_none(origin)?; import::import_header( - &mut BridgeStorage::::new(), + &mut BridgeStorage::::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::::new(), + &mut BridgeStorage::::new(), &mut T::PruningStrategy::default(), &T::AuraConfiguration::get(), &T::ValidatorsConfiguration::get(), @@ -434,7 +434,7 @@ decl_module! { } decl_storage! { - trait Store for Module as Bridge { + trait Store for Module, 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::( + initialize_storage::( &config.initial_header, config.initial_difficulty, &config.initial_validators, @@ -482,43 +482,47 @@ decl_storage! { } } -impl Module { +impl, I: Instance> Module { /// 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::::new().best_block().0 + BridgeStorage::::new().best_block().0 } /// Returns number and hash of the best finalized block known to the bridge module. pub fn finalized_block() -> HeaderId { - BridgeStorage::::new().finalized_block() + BridgeStorage::::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::::new(), &T::ValidatorsConfiguration::get(), &header) + import::header_import_requires_receipts( + &BridgeStorage::::new(), + &T::ValidatorsConfiguration::get(), + &header, + ) } /// Returns true if header is known to the runtime. pub fn is_known_block(hash: H256) -> bool { - BridgeStorage::::new().header(&hash).is_some() + BridgeStorage::::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::::new(), block, tx_index, proof) + crate::verify_transaction_finalized(&BridgeStorage::::new(), block, tx_index, proof) } } -impl frame_support::unsigned::ValidateUnsigned for Module { - type Call = Call; +impl, I: Instance> frame_support::unsigned::ValidateUnsigned for Module { + type Call = Call; 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::::new(), + &BridgeStorage::::new(), &T::AuraConfiguration::get(), &T::ValidatorsConfiguration::get(), &pool_configuration(), @@ -550,17 +554,17 @@ impl frame_support::unsigned::ValidateUnsigned for Module { /// Runtime bridge storage. #[derive(Default)] -pub struct BridgeStorage(sp_std::marker::PhantomData); +pub struct BridgeStorage(sp_std::marker::PhantomData<(T, I)>); -impl BridgeStorage { +impl, I: Instance> BridgeStorage { /// Create new BridgeStorage. pub fn new() -> Self { - BridgeStorage(sp_std::marker::PhantomData::::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::::get(); let mut new_pruning_range = pruning_range.clone(); // update oldest block we want to keep @@ -579,7 +583,7 @@ impl BridgeStorage { } // 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::::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 BridgeStorage { // if we haven't pruned all blocks, remember unpruned if !blocks_at_number.is_empty() { - HeadersByNumber::insert(number, blocks_at_number); + HeadersByNumber::::insert(number, blocks_at_number); break; } } @@ -606,7 +610,7 @@ impl BridgeStorage { // update pruning range in storage if pruning_range != new_pruning_range { - BlocksToPrune::put(new_pruning_range); + BlocksToPrune::::put(new_pruning_range); } } @@ -619,13 +623,13 @@ impl BridgeStorage { blocks_at_number: &mut Vec, ) { // 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::::contains_key) { return; } // physically remove headers and (probably) obsolete validators sets while let Some(hash) = blocks_at_number.pop() { - let header = Headers::::take(&hash); + let header = Headers::::take(&hash); frame_support::debug::trace!( target: "runtime", "Pruning PoA header: ({}, {})", @@ -633,10 +637,10 @@ impl BridgeStorage { hash, ); - ScheduledChanges::remove(hash); - FinalityCache::::remove(hash); + ScheduledChanges::::remove(hash); + FinalityCache::::remove(hash); if let Some(header) = header { - ValidatorsSetsRc::mutate(header.next_validators_set_id, |rc| match *rc { + ValidatorsSetsRc::::mutate(header.next_validators_set_id, |rc| match *rc { Some(rc) if rc > 1 => Some(rc - 1), _ => None, }); @@ -651,19 +655,19 @@ impl BridgeStorage { } } -impl Storage for BridgeStorage { +impl, I: Instance> Storage for BridgeStorage { type Submitter = T::AccountId; fn best_block(&self) -> (HeaderId, U256) { - BestBlock::get() + BestBlock::::get() } fn finalized_block(&self) -> HeaderId { - FinalizedBlock::get() + FinalizedBlock::::get() } fn header(&self, hash: &H256) -> Option<(Header, Option)> { - Headers::::get(hash).map(|header| (header.header, header.submitter)) + Headers::::get(hash).map(|header| (header.header, header.submitter)) } fn cached_finality_votes( @@ -675,7 +679,7 @@ impl Storage for BridgeStorage { 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 Storage for BridgeStorage { } // if we have found cached votes => stop - let cached_votes = FinalityCache::::get(¤t_id.hash); + let cached_votes = FinalityCache::::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::::get(¤t_id.hash) { + let header = match Headers::::get(¤t_id.hash) { Some(header) if header.header.number != 0 => header, _ => return votes, }; @@ -717,10 +721,10 @@ impl Storage for BridgeStorage { submitter: Option, parent_hash: &H256, ) -> Option> { - Headers::::get(parent_hash).map(|parent_header| { - let validators_set = ValidatorsSets::get(parent_header.next_validators_set_id) + Headers::::get(parent_hash).map(|parent_header| { + let validators_set = ValidatorsSets::::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::::get(parent_hash); ImportContext { submitter, parent_hash: *parent_hash, @@ -735,15 +739,15 @@ impl Storage for BridgeStorage { } fn scheduled_change(&self, hash: &H256) -> Option { - ScheduledChanges::get(hash) + ScheduledChanges::::get(hash) } fn insert_header(&mut self, header: HeaderToImport) { if header.is_best { - BestBlock::put((header.id, header.total_difficulty)); + BestBlock::::put((header.id, header.total_difficulty)); } if let Some(scheduled_change) = header.scheduled_change { - ScheduledChanges::insert( + ScheduledChanges::::insert( &header.id.hash, ScheduledChange { validators: scheduled_change, @@ -753,12 +757,12 @@ impl Storage for BridgeStorage { } 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::::mutate(|set_id| { let next_set_id = *set_id; *set_id += 1; next_set_id }); - ValidatorsSets::insert( + ValidatorsSets::::insert( next_validators_set_id, ValidatorsSet { validators: enacted_change.validators, @@ -766,11 +770,11 @@ impl Storage for BridgeStorage { signal_block: enacted_change.signal_block, }, ); - ValidatorsSetsRc::insert(next_validators_set_id, 1); + ValidatorsSetsRc::::insert(next_validators_set_id, 1); next_validators_set_id } None => { - ValidatorsSetsRc::mutate(header.context.validators_set_id, |rc| { + ValidatorsSetsRc::::mutate(header.context.validators_set_id, |rc| { *rc = Some(rc.map(|rc| rc + 1).unwrap_or(1)); *rc }); @@ -782,7 +786,7 @@ impl Storage for BridgeStorage { 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::::insert(header.id.hash, header.finality_votes); + FinalityCache::::insert(header.id.hash, header.finality_votes); } } @@ -794,8 +798,8 @@ impl Storage for BridgeStorage { ); let last_signal_block = header.context.last_signal_block(); - HeadersByNumber::append(header.id.number, header.id.hash); - Headers::::insert( + HeadersByNumber::::append(header.id.number, header.id.hash); + Headers::::insert( &header.id.hash, StoredHeader { submitter: header.context.submitter, @@ -812,7 +816,7 @@ impl Storage for BridgeStorage { let finalized_number = finalized .as_ref() .map(|f| f.number) - .unwrap_or_else(|| FinalizedBlock::get().number); + .unwrap_or_else(|| FinalizedBlock::::get().number); if let Some(finalized) = finalized { frame_support::debug::trace!( target: "runtime", @@ -821,7 +825,7 @@ impl Storage for BridgeStorage { finalized.hash, ); - FinalizedBlock::put(finalized); + FinalizedBlock::::put(finalized); } // and now prune headers if we need to @@ -831,7 +835,7 @@ impl Storage for BridgeStorage { /// Initialize storage. #[cfg(any(feature = "std", feature = "runtime-benchmarks"))] -pub(crate) fn initialize_storage( +pub(crate) fn initialize_storage, I: Instance>( initial_header: &Header, initial_difficulty: U256, initial_validators: &[Address], @@ -848,14 +852,14 @@ pub(crate) fn initialize_storage( number: initial_header.number, hash: initial_hash, }; - BestBlock::put((initial_id, initial_difficulty)); - FinalizedBlock::put(initial_id); - BlocksToPrune::put(PruningRange { + BestBlock::::put((initial_id, initial_difficulty)); + FinalizedBlock::::put(initial_id); + BlocksToPrune::::put(PruningRange { oldest_unpruned_block: initial_header.number, oldest_block_to_keep: initial_header.number, }); - HeadersByNumber::insert(initial_header.number, vec![initial_hash]); - Headers::::insert( + HeadersByNumber::::insert(initial_header.number, vec![initial_hash]); + Headers::::insert( initial_hash, StoredHeader { submitter: None, @@ -865,8 +869,8 @@ pub(crate) fn initialize_storage( last_signal_block: None, }, ); - NextValidatorsSetId::put(1); - ValidatorsSets::insert( + NextValidatorsSetId::::put(1); + ValidatorsSets::::insert( 0, ValidatorsSet { validators: initial_validators.to_vec(), @@ -874,7 +878,7 @@ pub(crate) fn initialize_storage( enact_block: initial_id, }, ); - ValidatorsSetsRc::insert(0, 1); + ValidatorsSetsRc::::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::::insert( hash, ScheduledChange { validators: validators_addresses(5), @@ -997,7 +1001,7 @@ pub(crate) mod tests { ); } } - HeadersByNumber::insert(i, headers_by_number); + HeadersByNumber::::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::::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::::get(&5).unwrap().len(), 5); assert_eq!( - BlocksToPrune::get(), + BlocksToPrune::::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::::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::::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::::get(&0).is_some()); + assert!(HeadersByNumber::::get(&1).is_some()); + assert!(HeadersByNumber::::get(&2).is_some()); + assert!(HeadersByNumber::::get(&3).is_some()); assert_eq!( - BlocksToPrune::get(), + BlocksToPrune::::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::::get(&0).is_none()); // 5 headers with number = 1 are pruned (6 total) - assert!(HeadersByNumber::get(&1).is_none()); + assert!(HeadersByNumber::::get(&1).is_none()); // 1 header with number = 2 are pruned (7 total) - assert_eq!(HeadersByNumber::get(&2).unwrap().len(), 4); + assert_eq!(HeadersByNumber::::get(&2).unwrap().len(), 4); assert_eq!( - BlocksToPrune::get(), + BlocksToPrune::::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::::get(&2).is_none()); // 5 headers with number = 3 are pruned (9 total) - assert!(HeadersByNumber::get(&3).is_none()); + assert!(HeadersByNumber::::get(&3).is_none()); // 2 headers with number = 4 are pruned (11 total) - assert_eq!(HeadersByNumber::get(&4).unwrap().len(), 3); + assert_eq!(HeadersByNumber::::get(&4).unwrap().len(), 3); assert_eq!( - BlocksToPrune::get(), + BlocksToPrune::::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::::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_eq!( - BlocksToPrune::get(), + BlocksToPrune::::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::::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::::put(header1_id); // trying to get finality votes when importing header2 -> header1 succeeds assert!( diff --git a/bridges/modules/ethereum/src/mock.rs b/bridges/modules/ethereum/src/mock.rs index 0dde85bd93c5..31717d53cc44 100644 --- a/bridges/modules/ethereum/src/mock.rs +++ b/bridges/modules/ethereum/src/mock.rs @@ -136,7 +136,7 @@ pub fn run_test_with_genesis(genesis: Header, total_validators: usize, test: initial_difficulty: 0.into(), initial_validators: addresses.clone(), } - .build_storage::() + .build_storage::() .unwrap(), ) .execute_with(|| { diff --git a/bridges/modules/ethereum/src/test_utils.rs b/bridges/modules/ethereum/src/test_utils.rs index eacdb680e0ba..e6e3ac4681c2 100644 --- a/bridges/modules/ethereum/src/test_utils.rs +++ b/bridges/modules/ethereum/src/test_utils.rs @@ -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::(parent_hash) + Self::with_parent_hash_on_runtime::(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::(parent_number) + Self::with_parent_number_on_runtime::(parent_number) } /// Creates default header on top of parent with given hash. - pub fn with_parent_hash_on_runtime(parent_hash: H256) -> Self { + pub fn with_parent_hash_on_runtime, I: crate::Instance>(parent_hash: H256) -> Self { use crate::Headers; use frame_support::StorageMap; - let parent_header = Headers::::get(&parent_hash).unwrap().header; + let parent_header = Headers::::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(parent_number: u64) -> Self { + pub fn with_parent_number_on_runtime, 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::(parent_hash) + let parent_hash = HeadersByNumber::::get(parent_number).unwrap()[0]; + Self::with_parent_hash_on_runtime::(parent_hash) } /// Creates default header on top of non-existent parent. diff --git a/bridges/modules/ethereum/src/validators.rs b/bridges/modules/ethereum/src/validators.rs index 7aa2dd8cb1ee..9695e9a11be6 100644 --- a/bridges/modules/ethereum/src/validators.rs +++ b/bridges/modules/ethereum/src/validators.rs @@ -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::::insert(id100.hash, header100); if let Some(scheduled_at) = scheduled_at { - ScheduledChanges::insert(scheduled_at.hash, scheduled_change); + ScheduledChanges::::insert(scheduled_at.hash, scheduled_change); } validators.finalize_validators_change(&storage, &finalized_blocks) diff --git a/bridges/modules/ethereum/src/verification.rs b/bridges/modules/ethereum/src/verification.rs index 3b1c1865929e..31f9c2e5531d 100644 --- a/bridges/modules/ethereum/src/verification.rs +++ b/bridges/modules/ethereum/src/verification.rs @@ -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::::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
, signalled_set: Option>) { - let set_id = NextValidatorsSetId::get(); - NextValidatorsSetId::put(set_id + 1); - ValidatorsSets::insert( + let set_id = NextValidatorsSetId::::get(); + NextValidatorsSetId::::put(set_id + 1); + ValidatorsSets::::insert( set_id, ValidatorsSet { validators: finalized_set, signal_block: None, enact_block: HeaderId { number: 0, - hash: HeadersByNumber::get(&0).unwrap()[0], + hash: HeadersByNumber::::get(&0).unwrap()[0], }, }, ); - let header_hash = HeadersByNumber::get(&number).unwrap()[0]; + let header_hash = HeadersByNumber::::get(&number).unwrap()[0]; let mut header = Headers::::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::::insert( header.header.parent_hash, ScheduledChange { validators: signalled_set, diff --git a/bridges/primitives/currency-exchange/src/lib.rs b/bridges/primitives/currency-exchange/src/lib.rs index 28a3afd08080..131daf66eda5 100644 --- a/bridges/primitives/currency-exchange/src/lib.rs +++ b/bridges/primitives/currency-exchange/src/lib.rs @@ -134,8 +134,15 @@ impl CurrencyConverter for IdentityCurrencyConverter { } decl_runtime_apis! { - /// API for exchange transactions submitters. - pub trait CurrencyExchangeApi { + /// API for Rialto exchange transactions submitters. + pub trait RialtoCurrencyExchangeApi { + /// Returns true if currency exchange module is able to import transaction proof in + /// its current state. + fn filter_transaction_proof(proof: Proof) -> bool; + } + + /// API for Kovan exchange transactions submitters. + pub trait KovanCurrencyExchangeApi { /// Returns true if currency exchange module is able to import transaction proof in /// its current state. fn filter_transaction_proof(proof: Proof) -> bool; diff --git a/bridges/primitives/ethereum-poa/src/lib.rs b/bridges/primitives/ethereum-poa/src/lib.rs index 6515f901feff..444af8cfa363 100644 --- a/bridges/primitives/ethereum-poa/src/lib.rs +++ b/bridges/primitives/ethereum-poa/src/lib.rs @@ -505,19 +505,32 @@ pub fn step_validator(header_validators: &[T], header_step: u64) -> &T { } sp_api::decl_runtime_apis! { - /// API for headers submitters. - pub trait EthereumHeadersApi { + /// API for querying information about headers from the Rialto Bridge Pallet + pub trait RialtoHeaderApi { /// 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 an `import_header` transaction that makes /// (or leads to making) other header the best one. fn best_block() -> (u64, H256); - /// Returns number and hash of the best finalized block known to the bridge module. fn finalized_block() -> (u64, H256); - /// Returns true if the import of given block requires transactions receipts. fn is_import_requires_receipts(header: Header) -> bool; + /// Returns true if header is known to the runtime. + fn is_known_block(hash: H256) -> bool; + } + /// API for querying information about headers from the Kovan Bridge Pallet + pub trait KovanHeaderApi { + /// Returns number and hash of the best block known to the bridge module. + /// + /// The caller should only submit an `import_header` transaction that makes + /// (or leads to making) other header the best one. + fn best_block() -> (u64, H256); + /// Returns number and hash of the best finalized block known to the bridge module. + fn finalized_block() -> (u64, H256); + /// Returns true if the import of given block requires transactions receipts. + fn is_import_requires_receipts(header: Header) -> bool; /// Returns true if header is known to the runtime. fn is_known_block(hash: H256) -> bool; } diff --git a/bridges/relays/ethereum/src/substrate_client.rs b/bridges/relays/ethereum/src/substrate_client.rs index 32f219d4ea33..3865566d9183 100644 --- a/bridges/relays/ethereum/src/substrate_client.rs +++ b/bridges/relays/ethereum/src/substrate_client.rs @@ -34,10 +34,10 @@ use sp_core::crypto::Pair; use sp_runtime::traits::IdentifyAccount; use std::collections::VecDeque; -const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "EthereumHeadersApi_is_import_requires_receipts"; -const ETH_API_IS_KNOWN_BLOCK: &str = "EthereumHeadersApi_is_known_block"; -const ETH_API_BEST_BLOCK: &str = "EthereumHeadersApi_best_block"; -const ETH_API_BEST_FINALIZED_BLOCK: &str = "EthereumHeadersApi_finalized_block"; +const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "RialtoHeaderApi_is_import_requires_receipts"; +const ETH_API_IS_KNOWN_BLOCK: &str = "RialtoHeaderApi_is_known_block"; +const ETH_API_BEST_BLOCK: &str = "RialtoHeaderApi_best_block"; +const ETH_API_BEST_FINALIZED_BLOCK: &str = "RialtoHeaderApi_finalized_block"; const EXCH_API_FILTER_TRANSACTION_PROOF: &str = "CurrencyExchangeApi_filter_transaction_proof"; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; @@ -336,7 +336,8 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient { let nonce = self.next_account_index(account_id).await?; let transaction = create_signed_transaction( - bridge_node_runtime::Call::BridgeCurrencyExchange( + // TODO [#209]: Change so that that it's dynamic + bridge_node_runtime::Call::BridgeRialtoCurrencyExchange( bridge_node_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof), ), ¶ms.signer, @@ -356,7 +357,8 @@ fn create_signed_submit_transaction( genesis_hash: H256, ) -> bridge_node_runtime::UncheckedExtrinsic { create_signed_transaction( - bridge_node_runtime::Call::BridgeEthPoA(bridge_node_runtime::BridgeEthPoACall::import_signed_headers( + // TODO [#209]: Change so that that it's dynamic + bridge_node_runtime::Call::BridgeRialto(bridge_node_runtime::BridgeEthPoACall::import_signed_headers( headers .into_iter() .map(|header| { @@ -376,7 +378,8 @@ fn create_signed_submit_transaction( /// Create unsigned Substrate transaction for submitting Ethereum header. fn create_unsigned_submit_transaction(header: QueuedEthereumHeader) -> bridge_node_runtime::UncheckedExtrinsic { let function = - bridge_node_runtime::Call::BridgeEthPoA(bridge_node_runtime::BridgeEthPoACall::import_unsigned_header( + // TODO [#209]: Change so that that it's dynamic + bridge_node_runtime::Call::BridgeRialto(bridge_node_runtime::BridgeEthPoACall::import_unsigned_header( into_substrate_ethereum_header(header.header()), into_substrate_ethereum_receipts(header.extra()), ));