diff --git a/bridges/bin/node/node/build.rs b/bridges/bin/node/node/build.rs index 0232226348..e9a10ff8ad 100644 --- a/bridges/bin/node/node/build.rs +++ b/bridges/bin/node/node/build.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use vergen::{ConstantsFlags, generate_cargo_keys}; +use vergen::{generate_cargo_keys, ConstantsFlags}; const ERROR_MSG: &str = "Failed to generate metadata files"; diff --git a/bridges/bin/node/node/src/chain_spec.rs b/bridges/bin/node/node/src/chain_spec.rs index 6301e342ee..0e81f7f167 100644 --- a/bridges/bin/node/node/src/chain_spec.rs +++ b/bridges/bin/node/node/src/chain_spec.rs @@ -14,16 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use sp_core::{Pair, Public, sr25519}; use bridge_node_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeEthPoAConfig, - GenesisConfig, GrandpaConfig, SudoConfig, SystemConfig, - WASM_BINARY, Signature + AccountId, AuraConfig, BalancesConfig, BridgeEthPoAConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig, + SystemConfig, WASM_BINARY, }; -use sp_consensus_aura::sr25519::{AuthorityId as AuraId}; -use grandpa_primitives::{AuthorityId as GrandpaId}; +use grandpa_primitives::AuthorityId as GrandpaId; use sc_service; -use sp_runtime::traits::{Verify, IdentifyAccount}; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_core::{sr25519, Pair, Public}; +use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. pub type ChainSpec = sc_service::ChainSpec; @@ -47,18 +46,16 @@ pub fn get_from_seed(seed: &str) -> ::Pu type AccountPublic = ::Signer; /// Helper function to generate an account ID from seed -pub fn get_account_id_from_seed(seed: &str) -> AccountId where - AccountPublic: From<::Public> +pub fn get_account_id_from_seed(seed: &str) -> AccountId +where + AccountPublic: From<::Public>, { AccountPublic::from(get_from_seed::(seed)).into_account() } /// Helper function to generate an authority key for Aura pub fn get_authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { - ( - get_from_seed::(s), - get_from_seed::(s), - ) + (get_from_seed::(s), get_from_seed::(s)) } impl Alternative { @@ -68,24 +65,24 @@ impl Alternative { Alternative::Development => ChainSpec::from_genesis( "Development", "dev", - || testnet_genesis( - vec![ - get_authority_keys_from_seed("Alice"), - ], - get_account_id_from_seed::("Alice"), - vec![ + || { + testnet_genesis( + vec![get_authority_keys_from_seed("Alice")], get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - ], - true, - ), + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + ], + true, + ) + }, vec![], None, None, None, - None + None, ), }) } @@ -98,17 +95,19 @@ impl Alternative { } } -fn testnet_genesis(initial_authorities: Vec<(AuraId, GrandpaId)>, +fn testnet_genesis( + initial_authorities: Vec<(AuraId, GrandpaId)>, root_key: AccountId, endowed_accounts: Vec, - _enable_println: bool) -> GenesisConfig { + _enable_println: bool, +) -> GenesisConfig { GenesisConfig { frame_system: Some(SystemConfig { code: WASM_BINARY.to_vec(), changes_trie_config: Default::default(), }), pallet_balances: Some(BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(), + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), }), pallet_aura: Some(AuraConfig { authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), @@ -117,9 +116,7 @@ fn testnet_genesis(initial_authorities: Vec<(AuraId, GrandpaId)>, pallet_grandpa: Some(GrandpaConfig { authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), }), - pallet_sudo: Some(SudoConfig { - key: root_key, - }), + pallet_sudo: Some(SudoConfig { key: root_key }), } } @@ -132,45 +129,85 @@ pub fn load_spec(id: &str) -> Result, String> { fn load_kovan_config() -> Option { Some(BridgeEthPoAConfig { - initial_header: sp_bridge_eth_poa::Header { - parent_hash: Default::default(), - timestamp: 0, - number: 0, - author: Default::default(), - transactions_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), - uncles_hash: "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".parse().unwrap(), - extra_data: vec![], - state_root: "2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2".parse().unwrap(), - receipts_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), - log_bloom: Default::default(), - gas_used: Default::default(), - gas_limit: 6000000.into(), - difficulty: 131072.into(), - seal: vec![ - vec![128].into(), - vec![184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0].into(), - ], - }, - initial_difficulty: 0.into(), - initial_validators: vec![ - [0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, - 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, 0xAd, 0xc0, 0xED].into(), - [0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, - 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, 0x0a, 0x4d, 0x3d].into(), - [0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, - 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, 0x42, 0x4d, 0x6c].into(), - [0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, - 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, 0xbA, 0x81, 0xA1].into(), - [0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, - 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, 0xfd, 0x03, 0x2d].into(), - [0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, - 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, 0x93, 0x38, 0x7A].into(), - [0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, - 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, 0x89, 0x78, 0x79].into(), - [0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, - 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, 0xa1, 0x64, 0x5c].into(), - [0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, - 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, 0x31, 0x94, 0xde].into(), + initial_header: sp_bridge_eth_poa::Header { + parent_hash: Default::default(), + timestamp: 0, + number: 0, + author: Default::default(), + transactions_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + .parse() + .unwrap(), + uncles_hash: "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + .parse() + .unwrap(), + extra_data: vec![], + state_root: "2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2" + .parse() + .unwrap(), + receipts_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + .parse() + .unwrap(), + log_bloom: Default::default(), + gas_used: Default::default(), + gas_limit: 6000000.into(), + difficulty: 131072.into(), + seal: vec![ + vec![128].into(), + vec![ + 184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + ] + .into(), ], - }) + }, + initial_difficulty: 0.into(), + initial_validators: vec![ + [ + 0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, + 0xAd, 0xc0, 0xED, + ] + .into(), + [ + 0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, + 0x0a, 0x4d, 0x3d, + ] + .into(), + [ + 0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, + 0x42, 0x4d, 0x6c, + ] + .into(), + [ + 0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, + 0xbA, 0x81, 0xA1, + ] + .into(), + [ + 0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, + 0xfd, 0x03, 0x2d, + ] + .into(), + [ + 0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, + 0x93, 0x38, 0x7A, + ] + .into(), + [ + 0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, + 0x89, 0x78, 0x79, + ] + .into(), + [ + 0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, + 0xa1, 0x64, 0x5c, + ] + .into(), + [ + 0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, + 0x31, 0x94, 0xde, + ] + .into(), + ], + }) } diff --git a/bridges/bin/node/node/src/command.rs b/bridges/bin/node/node/src/command.rs index c17ea03dd3..cdae1c8e3a 100644 --- a/bridges/bin/node/node/src/command.rs +++ b/bridges/bin/node/node/src/command.rs @@ -30,11 +30,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; -use sc_cli::VersionInfo; -use crate::service; use crate::chain_spec; use crate::cli::Cli; +use crate::service; +use sc_cli::VersionInfo; +use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; /// Parse and run command line arguments pub fn run(version: VersionInfo) -> sc_cli::Result<()> { @@ -46,20 +46,12 @@ pub fn run(version: VersionInfo) -> sc_cli::Result<()> { Some(subcommand) => { subcommand.init(&version)?; subcommand.update_config(&mut config, chain_spec::load_spec, &version)?; - subcommand.run( - config, - |config: _| Ok(new_full_start!(config).0), - ) - }, + subcommand.run(config, |config: _| Ok(new_full_start!(config).0)) + } None => { opt.run.init(&version)?; opt.run.update_config(&mut config, chain_spec::load_spec, &version)?; - opt.run.run( - config, - service::new_light, - service::new_full, - &version, - ) - }, + opt.run.run(config, service::new_light, service::new_full, &version) + } } } diff --git a/bridges/bin/node/node/src/service.rs b/bridges/bin/node/node/src/service.rs index f268a5dbbb..6d629f5708 100644 --- a/bridges/bin/node/node/src/service.rs +++ b/bridges/bin/node/node/src/service.rs @@ -16,16 +16,16 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. -use std::sync::Arc; -use std::time::Duration; +use bridge_node_runtime::{self, opaque::Block, GenesisConfig, RuntimeApi}; +use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; use sc_client::LongestChain; -use bridge_node_runtime::{self, GenesisConfig, opaque::Block, RuntimeApi}; -use sc_service::{error::{Error as ServiceError}, AbstractService, Configuration, ServiceBuilder}; -use sp_inherents::InherentDataProviders; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; -use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; -use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; +use sc_service::{error::Error as ServiceError, AbstractService, Configuration, ServiceBuilder}; +use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; +use sp_inherents::InherentDataProviders; +use std::sync::Arc; +use std::time::Duration; // Our native executor instance. native_executor_instance!( @@ -44,48 +44,50 @@ macro_rules! new_full_start { let inherent_data_providers = sp_inherents::InherentDataProviders::new(); let builder = sc_service::ServiceBuilder::new_full::< - bridge_node_runtime::opaque::Block, bridge_node_runtime::RuntimeApi, crate::service::Executor + bridge_node_runtime::opaque::Block, + bridge_node_runtime::RuntimeApi, + crate::service::Executor, >($config)? - .with_select_chain(|_config, backend| { - Ok(sc_client::LongestChain::new(backend.clone())) - })? - .with_transaction_pool(|config, client, _fetcher| { - let pool_api = sc_transaction_pool::FullChainApi::new(client.clone()); - Ok(sc_transaction_pool::BasicPool::new(config, std::sync::Arc::new(pool_api))) - })? - .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { - let select_chain = select_chain.take() - .ok_or_else(|| sc_service::Error::SelectChainRequired)?; + .with_select_chain(|_config, backend| Ok(sc_client::LongestChain::new(backend.clone())))? + .with_transaction_pool(|config, client, _fetcher| { + let pool_api = sc_transaction_pool::FullChainApi::new(client.clone()); + Ok(sc_transaction_pool::BasicPool::new( + config, + std::sync::Arc::new(pool_api), + )) + })? + .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { + let select_chain = select_chain + .take() + .ok_or_else(|| sc_service::Error::SelectChainRequired)?; - let (grandpa_block_import, grandpa_link) = - grandpa::block_import(client.clone(), &*client, select_chain)?; + let (grandpa_block_import, grandpa_link) = grandpa::block_import(client.clone(), &*client, select_chain)?; - let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( - grandpa_block_import.clone(), client.clone(), - ); + let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( + grandpa_block_import.clone(), + client.clone(), + ); - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>( - sc_consensus_aura::slot_duration(&*client)?, - aura_block_import, - Some(Box::new(grandpa_block_import.clone())), - None, - client, - inherent_data_providers.clone(), - )?; + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>( + sc_consensus_aura::slot_duration(&*client)?, + aura_block_import, + Some(Box::new(grandpa_block_import.clone())), + None, + client, + inherent_data_providers.clone(), + )?; - import_setup = Some((grandpa_block_import, grandpa_link)); + import_setup = Some((grandpa_block_import, grandpa_link)); - Ok(import_queue) - })?; + Ok(import_queue) + })?; (builder, import_setup, inherent_data_providers) - }} + }}; } /// Builds a new service for a full client. -pub fn new_full(config: Configuration) - -> Result -{ +pub fn new_full(config: Configuration) -> Result { let is_authority = config.roles.is_authority(); let force_authoring = config.force_authoring; let name = config.name.clone(); @@ -98,14 +100,14 @@ pub fn new_full(config: Configuration) let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config); - let (block_import, grandpa_link) = - import_setup.take() - .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); + let (block_import, grandpa_link) = import_setup + .take() + .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); let service = builder - .with_finality_proof_provider(|client, backend| + .with_finality_proof_provider(|client, backend| { Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) - )? + })? .build()?; if participates_in_consensus { @@ -115,11 +117,9 @@ pub fn new_full(config: Configuration) }; let client = service.client(); - let select_chain = service.select_chain() - .ok_or(ServiceError::SelectChainRequired)?; + let select_chain = service.select_chain().ok_or(ServiceError::SelectChainRequired)?; - let can_author_with = - sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); + let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>( sc_consensus_aura::slot_duration(&*client)?, @@ -177,38 +177,28 @@ pub fn new_full(config: Configuration) // the GRANDPA voter task is considered infallible, i.e. // if it fails we take down the service with it. - service.spawn_essential_task( - "grandpa-voter", - grandpa::run_grandpa_voter(grandpa_config)? - ); + service.spawn_essential_task("grandpa-voter", grandpa::run_grandpa_voter(grandpa_config)?); } else { - grandpa::setup_disabled_grandpa( - service.client(), - &inherent_data_providers, - service.network(), - )?; + grandpa::setup_disabled_grandpa(service.client(), &inherent_data_providers, service.network())?; } Ok(service) } /// Builds a new service for a light client. -pub fn new_light(config: Configuration) - -> Result -{ +pub fn new_light(config: Configuration) -> Result { let inherent_data_providers = InherentDataProviders::new(); ServiceBuilder::new_light::(config)? - .with_select_chain(|_config, backend| { - Ok(LongestChain::new(backend.clone())) - })? + .with_select_chain(|_config, backend| Ok(LongestChain::new(backend.clone())))? .with_transaction_pool(|config, client, fetcher| { - let fetcher = fetcher - .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; + let fetcher = fetcher.ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone()); let pool = sc_transaction_pool::BasicPool::with_revalidation_type( - config, Arc::new(pool_api), sc_transaction_pool::RevalidationType::Light, + config, + Arc::new(pool_api), + sc_transaction_pool::RevalidationType::Light, ); Ok(pool) })? @@ -216,12 +206,10 @@ pub fn new_light(config: Configuration) let fetch_checker = fetcher .map(|fetcher| fetcher.checker().clone()) .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; - let grandpa_block_import = grandpa::light_block_import( - client.clone(), backend, &*client.clone(), Arc::new(fetch_checker), - )?; + let grandpa_block_import = + grandpa::light_block_import(client.clone(), backend, &*client.clone(), Arc::new(fetch_checker))?; let finality_proof_import = grandpa_block_import.clone(); - let finality_proof_request_builder = - finality_proof_import.create_finality_proof_request_builder(); + let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>( sc_consensus_aura::slot_duration(&*client)?, @@ -234,8 +222,8 @@ pub fn new_light(config: Configuration) Ok((import_queue, finality_proof_request_builder)) })? - .with_finality_proof_provider(|client, backend| + .with_finality_proof_provider(|client, backend| { Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) - )? + })? .build() } diff --git a/bridges/bin/node/runtime/src/lib.rs b/bridges/bin/node/runtime/src/lib.rs index d5b1c0dd14..dff29f9dff 100644 --- a/bridges/bin/node/runtime/src/lib.rs +++ b/bridges/bin/node/runtime/src/lib.rs @@ -18,41 +18,35 @@ #![cfg_attr(not(feature = "std"), no_std)] // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit="256"] +#![recursion_limit = "256"] // Make the WASM binary available. #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -use sp_std::prelude::*; -use sp_core::OpaqueMetadata; -use sp_runtime::{ - ApplyExtrinsicResult, transaction_validity::TransactionValidity, generic, create_runtime_str, - impl_opaque_keys, MultiSignature, -}; -use sp_runtime::traits::{ - BlakeTwo256, Block as BlockT, IdentityLookup, Verify, ConvertInto, IdentifyAccount -}; +use pallet_grandpa::fg_primitives; +use pallet_grandpa::AuthorityList as GrandpaAuthorityList; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use pallet_grandpa::AuthorityList as GrandpaAuthorityList; -use pallet_grandpa::fg_primitives; -use sp_version::RuntimeVersion; +use sp_core::OpaqueMetadata; +use sp_runtime::traits::{BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, IdentityLookup, Verify}; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, transaction_validity::TransactionValidity, ApplyExtrinsicResult, + MultiSignature, +}; +use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; +use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. +pub use frame_support::{construct_runtime, parameter_types, traits::Randomness, weights::Weight, StorageValue}; +pub use pallet_balances::Call as BalancesCall; +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 pallet_timestamp::Call as TimestampCall; -pub use pallet_balances::Call as BalancesCall; -pub use sp_runtime::{Permill, Perbill}; -pub use frame_support::{ - StorageValue, construct_runtime, parameter_types, - traits::Randomness, - weights::Weight, -}; -pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; +pub use sp_runtime::{Perbill, Permill}; /// An index to a block. pub type BlockNumber = u32; @@ -274,7 +268,7 @@ pub type SignedExtra = ( frame_system::CheckEra, frame_system::CheckNonce, frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment + pallet_transaction_payment::ChargeTransactionPayment, ); /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; @@ -283,7 +277,8 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive, Runtime, AllModules>; +pub type Executive = + frame_executive::Executive, Runtime, AllModules>; impl_runtime_apis! { impl sp_api::Core for Runtime { diff --git a/bridges/modules/ethereum/src/finality.rs b/bridges/modules/ethereum/src/finality.rs index f41fd712e6..e2ea253172 100644 --- a/bridges/modules/ethereum/src/finality.rs +++ b/bridges/modules/ethereum/src/finality.rs @@ -100,7 +100,13 @@ fn prepare_votes( header: &Header, submitter: Option<&S::Submitter>, two_thirds_majority_transition: u64, -) -> Result<(BTreeMap, VecDeque<(H256, u64, Option, BTreeSet
)>), Error> { +) -> Result< + ( + BTreeMap, + VecDeque<(H256, u64, Option, BTreeSet
)>, + ), + Error, +> { // this fn can only work with single validators set if !validators.contains(&header.author) { return Err(Error::NotValidator); diff --git a/bridges/modules/ethereum/src/import.rs b/bridges/modules/ethereum/src/import.rs index 14cb8f26a7..9b9f3e613c 100644 --- a/bridges/modules/ethereum/src/import.rs +++ b/bridges/modules/ethereum/src/import.rs @@ -36,10 +36,7 @@ use crate::validators::{Validators, ValidatorsConfiguration}; use crate::verification::verify_aura_header; use crate::{AuraConfiguration, Storage}; use primitives::{Header, Receipt, H256}; -use sp_std::{ - collections::btree_map::BTreeMap, - prelude::*, -}; +use sp_std::{collections::btree_map::BTreeMap, prelude::*}; /// Maximal number of headers behind best blocks that we are aiming to store. When there /// are too many unfinalized headers, it slows down finalization tracking significantly. @@ -89,7 +86,7 @@ pub fn import_headers( } } useful += 1; - }, + } Err(Error::AncientHeader) | Err(Error::KnownHeader) => useless += 1, Err(error) => return Err(error), } @@ -143,16 +140,14 @@ pub fn import_header( let total_difficulty = import_context.total_difficulty() + header.difficulty; let is_best = total_difficulty > best_total_difficulty; let header_number = header.number; - storage.insert_header( - import_context.into_import_header( - is_best, - hash, - header, - total_difficulty, - enacted_change, - scheduled_change, - ), - ); + storage.insert_header(import_context.into_import_header( + is_best, + hash, + header, + total_difficulty, + enacted_change, + scheduled_change, + )); // now mark finalized headers && prune old headers storage.finalize_headers( @@ -300,18 +295,18 @@ mod tests { let mut latest_block_hash = Default::default(); for i in 1..11 { let header = block_i(&storage, i, &validators); - let (rolling_last_block_hash, finalized_blocks) = - import_header( - &mut storage, - &kovan_aura_config(), - &validators_config, - 10, - Some(100), - header, - None, - ).unwrap(); + let (rolling_last_block_hash, finalized_blocks) = import_header( + &mut storage, + &kovan_aura_config(), + &validators_config, + 10, + Some(100), + header, + None, + ) + .unwrap(); match i { - 2 ..= 10 => assert_eq!( + 2..=10 => assert_eq!( finalized_blocks, vec![(i - 1, block_i(&storage, i - 1, &validators).hash(), Some(100))], "At {}", @@ -341,7 +336,8 @@ mod tests { Some(vec![crate::validators::tests::validators_change_recept( latest_block_hash, )]), - ).unwrap(); + ) + .unwrap(); assert_eq!( finalized_blocks, vec![(10, block_i(&storage, 10, &validators).hash(), Some(100))], @@ -366,20 +362,17 @@ mod tests { }; let header = signed_header(&validators, header, step as _); expected_blocks.push((i, header.hash(), Some(102))); - let (rolling_last_block_hash, finalized_blocks) = - import_header( - &mut storage, - &kovan_aura_config(), - &validators_config, - 10, - Some(102), - header, - None, - ).unwrap(); - assert_eq!( - finalized_blocks, - vec![], - ); + let (rolling_last_block_hash, finalized_blocks) = import_header( + &mut storage, + &kovan_aura_config(), + &validators_config, + 10, + Some(102), + header, + None, + ) + .unwrap(); + assert_eq!(finalized_blocks, vec![],); latest_block_hash = rolling_last_block_hash; step += 3; } @@ -406,7 +399,8 @@ mod tests { Some(103), header, None, - ).unwrap(); + ) + .unwrap(); assert_eq!(finalized_blocks, expected_blocks); assert_eq!(storage.oldest_unpruned_block(), 15); } diff --git a/bridges/modules/ethereum/src/lib.rs b/bridges/modules/ethereum/src/lib.rs index 5d28bfd074..9a3317c973 100644 --- a/bridges/modules/ethereum/src/lib.rs +++ b/bridges/modules/ethereum/src/lib.rs @@ -36,12 +36,7 @@ use codec::{Decode, Encode}; use frame_support::{decl_module, decl_storage}; use primitives::{Address, Header, Receipt, H256, U256}; use sp_runtime::RuntimeDebug; -use sp_std::{ - prelude::*, - cmp::Ord, - collections::btree_map::BTreeMap, - iter::from_fn, -}; +use sp_std::{cmp::Ord, collections::btree_map::BTreeMap, iter::from_fn, prelude::*}; use validators::{ValidatorsConfiguration, ValidatorsSource}; pub use import::{header_import_requires_receipts, import_header}; @@ -481,7 +476,10 @@ impl Storage for BridgeStorage { // ensure that unfinalized headers we want to prune do not have scheduled changes if number > finalized_number { if let Some(ref blocks_at_number) = blocks_at_number { - if blocks_at_number.iter().any(|block| ScheduledChanges::contains_key(block)) { + if blocks_at_number + .iter() + .any(|block| ScheduledChanges::contains_key(block)) + { HeadersByNumber::insert(number, blocks_at_number); OldestUnprunedBlock::put(number); return; @@ -776,7 +774,9 @@ pub(crate) mod tests { } fn header(&self, hash: &H256) -> Option<(Header, Option)> { - self.headers.get(hash).map(|header| (header.header.clone(), header.submitter.clone())) + self.headers + .get(hash) + .map(|header| (header.header.clone(), header.submitter.clone())) } fn import_context( diff --git a/bridges/modules/ethereum/src/verification.rs b/bridges/modules/ethereum/src/verification.rs index c0edd5e56d..2104d7f21c 100644 --- a/bridges/modules/ethereum/src/verification.rs +++ b/bridges/modules/ethereum/src/verification.rs @@ -198,10 +198,7 @@ mod tests { empty_step } - fn verify_with_config( - config: &AuraConfiguration, - header: &Header, - ) -> Result, Error> { + fn verify_with_config(config: &AuraConfiguration, header: &Header) -> Result, Error> { let storage = InMemoryStorage::new(genesis(), validators_addresses(3)); verify_aura_header(&storage, &config, None, header) } diff --git a/bridges/relays/ethereum/src/ethereum_client.rs b/bridges/relays/ethereum/src/ethereum_client.rs index 2147922dc7..2efa99598c 100644 --- a/bridges/relays/ethereum/src/ethereum_client.rs +++ b/bridges/relays/ethereum/src/ethereum_client.rs @@ -30,18 +30,13 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . +use crate::ethereum_sync_loop::MaybeConnectionError; +use crate::ethereum_types::{Header, HeaderId, Receipt, H256, U64}; use jsonrpsee::common::Params; -use jsonrpsee::raw::{ - RawClient, - RawClientError, -}; -use jsonrpsee::transport::http::{ - HttpTransportClient, RequestError -}; +use jsonrpsee::raw::{RawClient, RawClientError}; +use jsonrpsee::transport::http::{HttpTransportClient, RequestError}; use serde::de::DeserializeOwned; use serde_json::{from_value, to_value}; -use crate::ethereum_sync_loop::MaybeConnectionError; -use crate::ethereum_types::{H256, Header, HeaderId, Receipt, U64}; /// Proof of hash serialization success. const HASH_SERIALIZATION_PROOF: &'static str = "hash serialization never fails; qed"; @@ -87,11 +82,7 @@ pub fn client(uri: &str) -> Client { /// Retrieve best known block number from Ethereum node. pub async fn best_block_number(client: Client) -> (Client, Result) { - let (client, result) = call_rpc::( - client, - "eth_blockNumber", - Params::None, - ).await; + let (client, result) = call_rpc::(client, "eth_blockNumber", Params::None).await; (client, result.map(|x| x.as_u64())) } @@ -104,11 +95,17 @@ pub async fn header_by_number(client: Client, number: u64) -> (Client, Result Ok(header), - false => Err(Error::IncompleteHeader), - })) + ) + .await; + ( + client, + header.and_then( + |header: Header| match header.number.is_some() && header.hash.is_some() { + true => Ok(header), + false => Err(Error::IncompleteHeader), + }, + ), + ) } /// Retrieve block header by its hash from Ethereum node. @@ -120,11 +117,17 @@ pub async fn header_by_hash(client: Client, hash: H256) -> (Client, Result Ok(header), - false => Err(Error::IncompleteHeader), - })) + ) + .await; + ( + client, + header.and_then( + |header: Header| match header.number.is_none() && header.hash.is_none() { + true => Ok(header), + false => Err(Error::IncompleteHeader), + }, + ), + ) } /// Retrieve transactions receipts for given block. @@ -151,16 +154,16 @@ async fn transaction_receipt(client: Client, hash: H256) -> (Client, Result( client, "eth_getTransactionReceipt", - Params::Array(vec![ - to_value(hash).expect(HASH_SERIALIZATION_PROOF), - ]), - ).await; - (client, receipt.and_then(|receipt| { - match receipt.gas_used.is_some() { + Params::Array(vec![to_value(hash).expect(HASH_SERIALIZATION_PROOF)]), + ) + .await; + ( + client, + receipt.and_then(|receipt| match receipt.gas_used.is_some() { true => Ok(receipt), false => Err(Error::IncompleteReceipt), - } - })) + }), + ) } /// Calls RPC on Ethereum node. diff --git a/bridges/relays/ethereum/src/ethereum_headers.rs b/bridges/relays/ethereum/src/ethereum_headers.rs index 1a3c110ad3..0fbc73f839 100644 --- a/bridges/relays/ethereum/src/ethereum_headers.rs +++ b/bridges/relays/ethereum/src/ethereum_headers.rs @@ -30,12 +30,10 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . +use crate::ethereum_types::{Header, HeaderId, HeaderStatus, QueuedHeader, Receipt, H256}; use std::collections::{ - BTreeMap, HashMap, HashSet, - btree_map::Entry as BTreeMapEntry, - hash_map::Entry as HashMapEntry, + btree_map::Entry as BTreeMapEntry, hash_map::Entry as HashMapEntry, BTreeMap, HashMap, HashSet, }; -use crate::ethereum_types::{H256, Header, HeaderId, HeaderStatus, QueuedHeader, Receipt}; type HeadersQueue = BTreeMap>; type KnownHeaders = BTreeMap>; @@ -79,9 +77,15 @@ impl QueuedHeaders { pub fn headers_in_status(&self, status: HeaderStatus) -> usize { match status { HeaderStatus::Unknown | HeaderStatus::Synced => return 0, - HeaderStatus::MaybeOrphan => self.maybe_orphan.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::MaybeOrphan => self + .maybe_orphan + .values() + .fold(0, |total, headers| total + headers.len()), HeaderStatus::Orphan => self.orphan.values().fold(0, |total, headers| total + headers.len()), - HeaderStatus::MaybeReceipts => self.maybe_receipts.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::MaybeReceipts => self + .maybe_receipts + .values() + .fold(0, |total, headers| total + headers.len()), HeaderStatus::Receipts => self.receipts.values().fold(0, |total, headers| total + headers.len()), HeaderStatus::Ready => self.ready.values().fold(0, |total, headers| total + headers.len()), HeaderStatus::Submitted => self.submitted.values().fold(0, |total, headers| total + headers.len()), @@ -90,9 +94,14 @@ impl QueuedHeaders { /// Returns number of headers that are currently in the queue. pub fn total_headers(&self) -> usize { - self.maybe_orphan.values().fold(0, |total, headers| total + headers.len()) + self.maybe_orphan + .values() + .fold(0, |total, headers| total + headers.len()) + self.orphan.values().fold(0, |total, headers| total + headers.len()) - + self.maybe_receipts.values().fold(0, |total, headers| total + headers.len()) + + self + .maybe_receipts + .values() + .fold(0, |total, headers| total + headers.len()) + self.receipts.values().fold(0, |total, headers| total + headers.len()) + self.ready.values().fold(0, |total, headers| total + headers.len()) } @@ -171,16 +180,19 @@ impl QueuedHeaders { HeaderStatus::Unknown | HeaderStatus::MaybeOrphan => { insert_header(&mut self.maybe_orphan, id, header); HeaderStatus::MaybeOrphan - }, + } HeaderStatus::Orphan => { insert_header(&mut self.orphan, id, header); HeaderStatus::Orphan } - HeaderStatus::MaybeReceipts | HeaderStatus::Receipts | HeaderStatus::Ready - | HeaderStatus::Submitted | HeaderStatus::Synced => { + HeaderStatus::MaybeReceipts + | HeaderStatus::Receipts + | HeaderStatus::Ready + | HeaderStatus::Submitted + | HeaderStatus::Synced => { insert_header(&mut self.maybe_receipts, id, header); HeaderStatus::MaybeReceipts - }, + } }; self.known_headers.entry(id.0).or_default().insert(id.1, status); @@ -202,10 +214,12 @@ impl QueuedHeaders { HeaderStatus::Ready => remove_header(&mut self.ready, ¤t), HeaderStatus::Submitted => remove_header(&mut self.submitted, ¤t), HeaderStatus::Synced => break, - }.expect("header has a given status; given queue has the header; qed"); + } + .expect("header has a given status; given queue has the header; qed"); log::debug!(target: "bridge", "Ethereum header {:?} is now {:?}", current, HeaderStatus::Synced); - *self.known_headers + *self + .known_headers .entry(current.0) .or_default() .entry(current.1) @@ -215,7 +229,8 @@ impl QueuedHeaders { // remember that the header is synced log::debug!(target: "bridge", "Ethereum header {:?} is now {:?}", id, HeaderStatus::Synced); - *self.known_headers + *self + .known_headers .entry(id.0) .or_default() .entry(id.1) @@ -303,7 +318,7 @@ impl QueuedHeaders { if prune_border <= self.prune_border { return; } - + prune_queue(&mut self.maybe_orphan, prune_border); prune_queue(&mut self.orphan, prune_border); prune_queue(&mut self.maybe_receipts, prune_border); @@ -402,7 +417,10 @@ fn move_header_descendants( if current_parents.contains(&entry.get().header().parent_hash) { let header_to_move = entry.remove(); let header_to_move_id = header_to_move.id(); - known_headers.entry(header_to_move_id.0).or_default().insert(header_to_move_id.1, destination_status); + known_headers + .entry(header_to_move_id.0) + .or_default() + .insert(header_to_move_id.1, destination_status); headers_to_move.push((header_to_move_id, header_to_move)); log::debug!( @@ -438,7 +456,8 @@ fn oldest_header(queue: &HeadersQueue) -> Option<&QueuedHeader> { /// Return oldest headers from the queue until functor will return false. fn oldest_headers(queue: &HeadersQueue, mut f: impl FnMut(&QueuedHeader) -> bool) -> Option> { - let result = queue.values() + let result = queue + .values() .flat_map(|h| h.values()) .take_while(|h| f(h)) .collect::>(); @@ -490,11 +509,27 @@ pub(crate) mod tests { fn total_headers_works() { // total headers just sums up number of headers in every queue let mut queue = QueuedHeaders::default(); - queue.maybe_orphan.entry(1).or_default().insert(hash(1), Default::default()); - queue.maybe_orphan.entry(1).or_default().insert(hash(2), Default::default()); - queue.maybe_orphan.entry(2).or_default().insert(hash(3), Default::default()); + queue + .maybe_orphan + .entry(1) + .or_default() + .insert(hash(1), Default::default()); + queue + .maybe_orphan + .entry(1) + .or_default() + .insert(hash(2), Default::default()); + queue + .maybe_orphan + .entry(2) + .or_default() + .insert(hash(3), Default::default()); queue.orphan.entry(3).or_default().insert(hash(4), Default::default()); - queue.maybe_receipts.entry(4).or_default().insert(hash(5), Default::default()); + queue + .maybe_receipts + .entry(4) + .or_default() + .insert(hash(5), Default::default()); queue.ready.entry(5).or_default().insert(hash(6), Default::default()); assert_eq!(queue.total_headers(), 6); } @@ -503,21 +538,41 @@ pub(crate) mod tests { fn best_queued_number_works() { // initially there are headers in MaybeOrphan queue only let mut queue = QueuedHeaders::default(); - queue.maybe_orphan.entry(1).or_default().insert(hash(1), Default::default()); - queue.maybe_orphan.entry(1).or_default().insert(hash(2), Default::default()); - queue.maybe_orphan.entry(3).or_default().insert(hash(3), Default::default()); + queue + .maybe_orphan + .entry(1) + .or_default() + .insert(hash(1), Default::default()); + queue + .maybe_orphan + .entry(1) + .or_default() + .insert(hash(2), Default::default()); + queue + .maybe_orphan + .entry(3) + .or_default() + .insert(hash(3), Default::default()); assert_eq!(queue.best_queued_number(), 3); // and then there's better header in Orphan queue.orphan.entry(10).or_default().insert(hash(10), Default::default()); assert_eq!(queue.best_queued_number(), 10); // and then there's better header in MaybeReceipts - queue.maybe_receipts.entry(20).or_default().insert(hash(20), Default::default()); + queue + .maybe_receipts + .entry(20) + .or_default() + .insert(hash(20), Default::default()); assert_eq!(queue.best_queued_number(), 20); // and then there's better header in Ready queue.ready.entry(30).or_default().insert(hash(30), Default::default()); assert_eq!(queue.best_queued_number(), 30); // and then there's better header in MaybeOrphan again - queue.maybe_orphan.entry(40).or_default().insert(hash(40), Default::default()); + queue + .maybe_orphan + .entry(40) + .or_default() + .insert(hash(40), Default::default()); assert_eq!(queue.best_queued_number(), 40); } @@ -527,7 +582,11 @@ pub(crate) mod tests { let mut queue = QueuedHeaders::default(); assert_eq!(queue.status(&id(10)), HeaderStatus::Unknown); // and status is read from the KnownHeaders - queue.known_headers.entry(10).or_default().insert(hash(10), HeaderStatus::Ready); + queue + .known_headers + .entry(10) + .or_default() + .insert(hash(10), HeaderStatus::Ready); assert_eq!(queue.status(&id(10)), HeaderStatus::Ready); } @@ -536,50 +595,83 @@ pub(crate) mod tests { // initially we have oldest header #10 let mut queue = QueuedHeaders::default(); queue.maybe_orphan.entry(10).or_default().insert(hash(1), header(100)); - assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), hash(100)); + assert_eq!( + queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), + hash(100) + ); // inserting #20 changes nothing queue.maybe_orphan.entry(20).or_default().insert(hash(1), header(101)); - assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), hash(100)); + assert_eq!( + queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), + hash(100) + ); // inserting #5 makes it oldest queue.maybe_orphan.entry(5).or_default().insert(hash(1), header(102)); - assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), hash(102)); + assert_eq!( + queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), + hash(102) + ); } #[test] fn header_response_works() { // when parent is Synced, we insert to MaybeReceipts let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Synced); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Synced); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); // when parent is Ready, we insert to MaybeReceipts let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Ready); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Ready); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); // when parent is Receipts, we insert to MaybeReceipts let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Receipts); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Receipts); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); // when parent is MaybeReceipts, we insert to MaybeReceipts let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeReceipts); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeReceipts); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); // when parent is Orphan, we insert to Orphan let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Orphan); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Orphan); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::Orphan); // when parent is MaybeOrphan, we insert to MaybeOrphan let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeOrphan); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeOrphan); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeOrphan); @@ -599,15 +691,39 @@ pub(crate) mod tests { // #97 in Receipts // #96 in Ready let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); - queue.known_headers.entry(99).or_default().insert(hash(99), HeaderStatus::Orphan); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(100) + .or_default() + .insert(hash(100), header(100)); + queue + .known_headers + .entry(99) + .or_default() + .insert(hash(99), HeaderStatus::Orphan); queue.orphan.entry(99).or_default().insert(hash(99), header(99)); - queue.known_headers.entry(98).or_default().insert(hash(98), HeaderStatus::MaybeReceipts); + queue + .known_headers + .entry(98) + .or_default() + .insert(hash(98), HeaderStatus::MaybeReceipts); queue.maybe_receipts.entry(98).or_default().insert(hash(98), header(98)); - queue.known_headers.entry(97).or_default().insert(hash(97), HeaderStatus::Receipts); + queue + .known_headers + .entry(97) + .or_default() + .insert(hash(97), HeaderStatus::Receipts); queue.receipts.entry(97).or_default().insert(hash(97), header(97)); - queue.known_headers.entry(96).or_default().insert(hash(96), HeaderStatus::Ready); + queue + .known_headers + .entry(96) + .or_default() + .insert(hash(96), HeaderStatus::Ready); queue.ready.entry(96).or_default().insert(hash(96), header(96)); queue.substrate_best_header_response(&id(100)); @@ -618,7 +734,10 @@ pub(crate) mod tests { assert!(queue.receipts.is_empty()); assert!(queue.ready.is_empty()); assert_eq!(queue.known_headers.len(), 5); - assert!(queue.known_headers.values().all(|s| s.values().all(|s| *s == HeaderStatus::Synced))); + assert!(queue + .known_headers + .values() + .all(|s| s.values().all(|s| *s == HeaderStatus::Synced))); } #[test] @@ -629,11 +748,27 @@ pub(crate) mod tests { // #102 in MaybeOrphan // #103 in Orphan let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(101).or_default().insert(hash(101), HeaderStatus::Orphan); + queue + .known_headers + .entry(101) + .or_default() + .insert(hash(101), HeaderStatus::Orphan); queue.orphan.entry(101).or_default().insert(hash(101), header(101)); - queue.known_headers.entry(102).or_default().insert(hash(102), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(102).or_default().insert(hash(102), header(102)); - queue.known_headers.entry(103).or_default().insert(hash(103), HeaderStatus::Orphan); + queue + .known_headers + .entry(102) + .or_default() + .insert(hash(102), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(102) + .or_default() + .insert(hash(102), header(102)); + queue + .known_headers + .entry(103) + .or_default() + .insert(hash(103), HeaderStatus::Orphan); queue.orphan.entry(103).or_default().insert(hash(103), header(103)); queue.substrate_best_header_response(&id(100)); @@ -655,12 +790,32 @@ pub(crate) mod tests { // and we have asked for MaybeOrphan status of #100.parent (i.e. #99) // and the response is: YES, #99 is known to the Substrate runtime let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); - queue.known_headers.entry(101).or_default().insert(hash(101), HeaderStatus::Orphan); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(100) + .or_default() + .insert(hash(100), header(100)); + queue + .known_headers + .entry(101) + .or_default() + .insert(hash(101), HeaderStatus::Orphan); queue.orphan.entry(101).or_default().insert(hash(101), header(101)); - queue.known_headers.entry(102).or_default().insert(hash(102), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(102).or_default().insert(hash(102), header(102)); + queue + .known_headers + .entry(102) + .or_default() + .insert(hash(102), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(102) + .or_default() + .insert(hash(102), header(102)); queue.maybe_orphan_response(&id(99), true); // then all headers (#100..#103) are moved to the MaybeReceipts queue @@ -680,10 +835,26 @@ pub(crate) mod tests { // and we have asked for MaybeOrphan status of #100.parent (i.e. #99) // and the response is: NO, #99 is NOT known to the Substrate runtime let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); - queue.known_headers.entry(101).or_default().insert(hash(101), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(101).or_default().insert(hash(101), header(101)); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(100) + .or_default() + .insert(hash(100), header(100)); + queue + .known_headers + .entry(101) + .or_default() + .insert(hash(101), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(101) + .or_default() + .insert(hash(101), header(101)); queue.maybe_orphan_response(&id(99), false); // then all headers (#100..#101) are moved to the Orphan queue @@ -696,8 +867,16 @@ pub(crate) mod tests { #[test] fn positive_maybe_receipts_response_works() { let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeReceipts); - queue.maybe_receipts.entry(100).or_default().insert(hash(100), header(100)); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeReceipts); + queue + .maybe_receipts + .entry(100) + .or_default() + .insert(hash(100), header(100)); queue.maybe_receipts_response(&id(100), true); assert!(queue.maybe_receipts.is_empty()); assert_eq!(queue.receipts.len(), 1); @@ -707,8 +886,16 @@ pub(crate) mod tests { #[test] fn negative_maybe_receipts_response_works() { let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeReceipts); - queue.maybe_receipts.entry(100).or_default().insert(hash(100), header(100)); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeReceipts); + queue + .maybe_receipts + .entry(100) + .or_default() + .insert(hash(100), header(100)); queue.maybe_receipts_response(&id(100), false); assert!(queue.maybe_receipts.is_empty()); assert_eq!(queue.ready.len(), 1); @@ -718,7 +905,11 @@ pub(crate) mod tests { #[test] fn receipts_response_works() { let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Receipts); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Receipts); queue.receipts.entry(100).or_default().insert(hash(100), header(100)); queue.receipts_response(&id(100), Vec::new()); assert!(queue.receipts.is_empty()); @@ -729,7 +920,11 @@ pub(crate) mod tests { #[test] fn header_submitted_works() { let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Ready); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Ready); queue.ready.entry(100).or_default().insert(hash(100), header(100)); queue.headers_submitted(vec![id(100)]); assert!(queue.ready.is_empty()); @@ -739,15 +934,43 @@ pub(crate) mod tests { #[test] fn prune_works() { let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(104).or_default().insert(hash(104), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(104).or_default().insert(hash(104), header(104)); - queue.known_headers.entry(103).or_default().insert(hash(103), HeaderStatus::Orphan); + queue + .known_headers + .entry(104) + .or_default() + .insert(hash(104), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(104) + .or_default() + .insert(hash(104), header(104)); + queue + .known_headers + .entry(103) + .or_default() + .insert(hash(103), HeaderStatus::Orphan); queue.orphan.entry(103).or_default().insert(hash(103), header(103)); - queue.known_headers.entry(102).or_default().insert(hash(102), HeaderStatus::MaybeReceipts); - queue.maybe_receipts.entry(102).or_default().insert(hash(102), header(102)); - queue.known_headers.entry(101).or_default().insert(hash(101), HeaderStatus::Receipts); + queue + .known_headers + .entry(102) + .or_default() + .insert(hash(102), HeaderStatus::MaybeReceipts); + queue + .maybe_receipts + .entry(102) + .or_default() + .insert(hash(102), header(102)); + queue + .known_headers + .entry(101) + .or_default() + .insert(hash(101), HeaderStatus::Receipts); queue.receipts.entry(101).or_default().insert(hash(101), header(101)); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Ready); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Ready); queue.ready.entry(100).or_default().insert(hash(100), header(100)); queue.prune(102); diff --git a/bridges/relays/ethereum/src/ethereum_sync.rs b/bridges/relays/ethereum/src/ethereum_sync.rs index 5819c5f0bb..9c2834c1ae 100644 --- a/bridges/relays/ethereum/src/ethereum_sync.rs +++ b/bridges/relays/ethereum/src/ethereum_sync.rs @@ -30,11 +30,11 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . -use codec::Encode; use crate::ethereum_headers::QueuedHeaders; -use crate::ethereum_types::{HeaderId, HeaderStatus, QueuedHeader}; use crate::ethereum_sync_loop::EthereumSyncParams; +use crate::ethereum_types::{HeaderId, HeaderStatus, QueuedHeader}; use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; +use codec::Encode; /// Ethereum headers synchronization context. #[derive(Debug)] @@ -63,7 +63,8 @@ impl HeadersSync { /// Returns true if we have synced almost all known headers. pub fn is_almost_synced(&self) -> bool { match self.target_header_number { - Some(target_header_number) => self.best_header + Some(target_header_number) => self + .best_header .map(|best| target_header_number.saturating_sub(best.0) < 4) .unwrap_or(false), None => true, @@ -100,10 +101,7 @@ impl HeadersSync { } // we assume that there were no reorgs if we have already downloaded best header - let best_downloaded_number = std::cmp::max( - self.headers.best_queued_number(), - best_header.0, - ); + let best_downloaded_number = std::cmp::max(self.headers.best_queued_number(), best_header.0); if best_downloaded_number == target_header_number { return None; } @@ -115,7 +113,9 @@ impl HeadersSync { /// Select headers that need to be submitted to the Substrate node. pub fn select_headers_to_submit(&self) -> Option> { let headers_in_submit_status = self.headers.headers_in_status(HeaderStatus::Submitted); - let headers_to_submit_count = self.params.max_headers_in_submitted_status + let headers_to_submit_count = self + .params + .max_headers_in_submitted_status .checked_sub(headers_in_submit_status)?; let mut total_size = 0; @@ -129,7 +129,8 @@ impl HeadersSync { } let encoded_size = into_substrate_ethereum_header(header.header()).encode().len() - + into_substrate_ethereum_receipts(header.receipts()).map(|receipts| receipts.encode().len()) + + into_substrate_ethereum_receipts(header.receipts()) + .map(|receipts| receipts.encode().len()) .unwrap_or(0); if total_headers != 0 && total_size + encoded_size > self.params.max_headers_size_in_single_submit { return false; @@ -162,7 +163,8 @@ impl HeadersSync { self.headers.substrate_best_header_response(&best_header); // prune ancient headers - self.headers.prune(best_header.0.saturating_sub(self.params.prune_depth)); + self.headers + .prune(best_header.0.saturating_sub(self.params.prune_depth)); // finally remember the best header itself self.best_header = Some(best_header); @@ -180,9 +182,9 @@ impl HeadersSync { #[cfg(test)] mod tests { - use crate::ethereum_headers::tests::{header, id}; - use crate::ethereum_types::{H256, HeaderStatus}; use super::*; + use crate::ethereum_headers::tests::{header, id}; + use crate::ethereum_types::{HeaderStatus, H256}; fn side_hash(number: u64) -> H256 { H256::from_low_u64_le(1000 + number) diff --git a/bridges/relays/ethereum/src/ethereum_sync_loop.rs b/bridges/relays/ethereum/src/ethereum_sync_loop.rs index 1540edd78f..6f61b423d2 100644 --- a/bridges/relays/ethereum/src/ethereum_sync_loop.rs +++ b/bridges/relays/ethereum/src/ethereum_sync_loop.rs @@ -30,10 +30,10 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . -use futures::{future::FutureExt, stream::StreamExt}; use crate::ethereum_client; use crate::ethereum_types::HeaderStatus as EthereumHeaderStatus; use crate::substrate_client; +use futures::{future::FutureExt, stream::StreamExt}; // TODO: when SharedClient will be available, switch to Substrate headers subscription // (because we do not need old Substrate headers) @@ -98,7 +98,10 @@ impl std::fmt::Debug for EthereumSyncParams { .field("max_future_headers_to_download", &self.max_future_headers_to_download) .field("max_headers_in_submitted_status", &self.max_headers_in_submitted_status) .field("max_headers_in_single_submit", &self.max_headers_in_single_submit) - .field("max_headers_size_in_single_submit", &self.max_headers_size_in_single_submit) + .field( + "max_headers_size_in_single_submit", + &self.max_headers_size_in_single_submit, + ) .field("prune_depth", &self.prune_depth) .finish() } @@ -136,9 +139,7 @@ pub fn run(params: EthereumSyncParams) { let mut eth_maybe_client = None; let mut eth_best_block_number_required = false; - let eth_best_block_number_future = ethereum_client::best_block_number( - ethereum_client::client(ð_uri) - ).fuse(); + let eth_best_block_number_future = ethereum_client::best_block_number(ethereum_client::client(ð_uri)).fuse(); let eth_new_header_future = futures::future::Fuse::terminated(); let eth_orphan_header_future = futures::future::Fuse::terminated(); let eth_receipts_future = futures::future::Fuse::terminated(); @@ -147,9 +148,8 @@ pub fn run(params: EthereumSyncParams) { let mut sub_maybe_client = None; let mut sub_best_block_required = false; - let sub_best_block_future = substrate_client::best_ethereum_block( - substrate_client::client(&sub_uri, sub_signer), - ).fuse(); + let sub_best_block_future = + substrate_client::best_ethereum_block(substrate_client::client(&sub_uri, sub_signer)).fuse(); let sub_receipts_check_future = futures::future::Fuse::terminated(); let sub_existence_status_future = futures::future::Fuse::terminated(); let sub_submit_header_future = futures::future::Fuse::terminated(); @@ -326,7 +326,7 @@ pub fn run(params: EthereumSyncParams) { // 2) check transactions receipts - it stops us from downloading/submitting new blocks; // 3) check existence - it stops us from submitting new blocks; // 4) submit header - + if sub_best_block_required { log::debug!(target: "bridge", "Asking Substrate about best block"); sub_best_block_future.set(substrate_client::best_ethereum_block(sub_client).fuse()); @@ -338,9 +338,8 @@ pub fn run(params: EthereumSyncParams) { ); let header = header.clone(); - sub_receipts_check_future.set( - substrate_client::ethereum_receipts_required(sub_client, header).fuse() - ); + sub_receipts_check_future + .set(substrate_client::ethereum_receipts_required(sub_client, header).fuse()); } else if let Some(header) = eth_sync.headers().header(EthereumHeaderStatus::MaybeOrphan) { // for MaybeOrphan we actually ask for parent' header existence let parent_id = header.parent_id(); @@ -351,9 +350,8 @@ pub fn run(params: EthereumSyncParams) { parent_id, ); - sub_existence_status_future.set( - substrate_client::ethereum_header_known(sub_client, parent_id).fuse(), - ); + sub_existence_status_future + .set(substrate_client::ethereum_header_known(sub_client, parent_id).fuse()); } else if let Some(headers) = eth_sync.select_headers_to_submit() { let ids = match headers.len() { 1 => format!("{:?}", headers[0].id()), @@ -368,9 +366,7 @@ pub fn run(params: EthereumSyncParams) { ); let headers = headers.into_iter().cloned().collect(); - sub_submit_header_future.set( - substrate_client::submit_ethereum_headers(sub_client, headers).fuse(), - ); + sub_submit_header_future.set(substrate_client::submit_ethereum_headers(sub_client, headers).fuse()); // remember that we have submitted some headers if stall_countdown.is_none() { @@ -400,11 +396,8 @@ pub fn run(params: EthereumSyncParams) { id, ); eth_receipts_future.set( - ethereum_client::transactions_receipts( - eth_client, - id, - header.header().transactions.clone(), - ).fuse() + ethereum_client::transactions_receipts(eth_client, id, header.header().transactions.clone()) + .fuse(), ); } else if let Some(header) = eth_sync.headers().header(EthereumHeaderStatus::Orphan) { // for Orphan we actually ask for parent' header @@ -416,9 +409,7 @@ pub fn run(params: EthereumSyncParams) { parent_id, ); - eth_orphan_header_future.set( - ethereum_client::header_by_hash(eth_client, parent_id.1).fuse(), - ); + eth_orphan_header_future.set(ethereum_client::header_by_hash(eth_client, parent_id.1).fuse()); } else if let Some(id) = eth_sync.select_new_header_to_download() { log::debug!( target: "bridge", @@ -426,9 +417,7 @@ pub fn run(params: EthereumSyncParams) { id, ); - eth_new_header_future.set( - ethereum_client::header_by_number(eth_client, id).fuse(), - ); + eth_new_header_future.set(ethereum_client::header_by_number(eth_client, id).fuse()); } else { eth_maybe_client = Some(eth_client); } @@ -469,7 +458,10 @@ async fn delay(timeout_ms: u64, retval: T) -> T { } fn interval(timeout_ms: u64) -> impl futures::Stream { - futures::stream::unfold((), move |_| async move { delay(timeout_ms, ()).await; Some(((), ())) }) + futures::stream::unfold((), move |_| async move { + delay(timeout_ms, ()).await; + Some(((), ())) + }) } fn process_future_result( @@ -488,7 +480,7 @@ fn process_future_result( Ok(result) => { *maybe_client = Some(client); on_success(result); - }, + } Err(error) => { if error.is_connection_error() { go_offline_future.set(go_offline(client).fuse()); @@ -497,6 +489,6 @@ fn process_future_result( } log::error!(target: "bridge", "{}: {:?}", error_pattern, error); - }, + } } } diff --git a/bridges/relays/ethereum/src/ethereum_types.rs b/bridges/relays/ethereum/src/ethereum_types.rs index cd61ac01b3..a83c4b666b 100644 --- a/bridges/relays/ethereum/src/ethereum_types.rs +++ b/bridges/relays/ethereum/src/ethereum_types.rs @@ -52,7 +52,10 @@ pub struct HeaderId(pub u64, pub H256); impl From<&Header> for HeaderId { fn from(header: &Header) -> HeaderId { - HeaderId(header.number.expect(HEADER_ID_PROOF).as_u64(), header.hash.expect(HEADER_ID_PROOF)) + HeaderId( + header.number.expect(HEADER_ID_PROOF).as_u64(), + header.hash.expect(HEADER_ID_PROOF), + ) } } diff --git a/bridges/relays/ethereum/src/main.rs b/bridges/relays/ethereum/src/main.rs index eee802a004..583faf08c9 100644 --- a/bridges/relays/ethereum/src/main.rs +++ b/bridges/relays/ethereum/src/main.rs @@ -30,7 +30,7 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . -#![recursion_limit="1024"] +#![recursion_limit = "1024"] mod ethereum_client; mod ethereum_headers; @@ -40,8 +40,8 @@ mod ethereum_types; mod substrate_client; mod substrate_types; -use std::io::Write; use sp_core::crypto::Pair; +use std::io::Write; fn main() { initialize(); @@ -51,7 +51,7 @@ fn main() { Err(err) => { log::error!(target: "bridge", "Error parsing parameters: {}", err); return; - }, + } }); } @@ -66,8 +66,8 @@ fn initialize() { builder.parse_filters(&filters); builder.format(move |buf, record| { writeln!(buf, "{}", { - let timestamp = time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()) - .expect("Time is incorrectly formatted"); + let timestamp = + time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()).expect("Time is incorrectly formatted"); if cfg!(windows) { format!("{} {} {} {}", timestamp, record.level(), record.target(), record.args()) } else { @@ -79,11 +79,13 @@ fn initialize() { log::Level::Debug => Color::Fixed(14).paint(record.level().to_string()), log::Level::Trace => Color::Fixed(12).paint(record.level().to_string()), }; - format!("{} {} {} {}" - , Color::Fixed(8).bold().paint(timestamp) - , log_level - , Color::Fixed(8).paint(record.target()) - , record.args()) + format!( + "{} {} {} {}", + Color::Fixed(8).bold().paint(timestamp), + log_level, + Color::Fixed(8).paint(record.target()), + record.args() + ) } }) }); @@ -110,8 +112,8 @@ fn ethereum_sync_params() -> Result. -use codec::{Encode, Decode}; +use crate::ethereum_sync_loop::MaybeConnectionError; +use crate::ethereum_types::{Bytes, HeaderId as EthereumHeaderId, QueuedHeader as QueuedEthereumHeader, H256}; +use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts, TransactionHash}; +use codec::{Decode, Encode}; use jsonrpsee::common::Params; -use jsonrpsee::raw::{ - RawClient, RawClientError -}; -use jsonrpsee::transport::http::{ - HttpTransportClient, RequestError -}; +use jsonrpsee::raw::{RawClient, RawClientError}; +use jsonrpsee::transport::http::{HttpTransportClient, RequestError}; use serde_json::{from_value, to_value}; use sp_core::crypto::Pair; use sp_runtime::traits::IdentifyAccount; -use crate::ethereum_sync_loop::MaybeConnectionError; -use crate::ethereum_types::{ - Bytes, - H256, - HeaderId as EthereumHeaderId, - QueuedHeader as QueuedEthereumHeader, -}; -use crate::substrate_types::{ - TransactionHash, - into_substrate_ethereum_header, - into_substrate_ethereum_receipts, -}; /// Substrate client type. pub struct Client { @@ -105,7 +92,8 @@ pub async fn best_ethereum_block(client: Client) -> (Client, Result nonce, Err(err) => return (client, Err(err)), }; - let transaction = create_submit_transaction( - headers, - &client.signer, - nonce, - genesis_hash, - ); + let transaction = create_submit_transaction(headers, &client.signer, nonce, genesis_hash); let encoded_transaction = transaction.encode(); let (client, transaction_hash) = call_rpc( client, "author_submitExtrinsic", - Params::Array(vec![ - to_value(Bytes(encoded_transaction)).unwrap(), - ]), - ).await; + Params::Array(vec![to_value(Bytes(encoded_transaction)).unwrap()]), + ) + .await; (client, transaction_hash.map(|transaction_hash| (transaction_hash, ids))) } @@ -197,10 +184,9 @@ async fn block_hash_by_number(client: Client, number: u64) -> (Client, Result

( - mut client: Client, - method: &'static str, - params: Params, -) -> (Client, Result) { - async fn do_call_rpc( - client: &mut Client, - method: &'static str, - params: Params, - ) -> Result { +async fn call_rpc(mut client: Client, method: &'static str, params: Params) -> (Client, Result) { + async fn do_call_rpc(client: &mut Client, method: &'static str, params: Params) -> Result { let request_id = client .rpc_client .start_request(method, params) @@ -253,16 +230,8 @@ async fn call_rpc( } /// Calls RPC on Substrate node that returns u64. -async fn call_rpc_u64( - mut client: Client, - method: &'static str, - params: Params, -) -> (Client, Result) { - async fn do_call_rpc( - client: &mut Client, - method: &'static str, - params: Params, - ) -> Result { +async fn call_rpc_u64(mut client: Client, method: &'static str, params: Params) -> (Client, Result) { + async fn do_call_rpc(client: &mut Client, method: &'static str, params: Params) -> Result { let request_id = client .rpc_client .start_request(method, params) @@ -290,20 +259,18 @@ fn create_submit_transaction( index: node_primitives::Index, genesis_hash: H256, ) -> bridge_node_runtime::UncheckedExtrinsic { - let function = bridge_node_runtime::Call::BridgeEthPoA( - bridge_node_runtime::BridgeEthPoACall::import_headers( - headers - .into_iter() - .map(|header| { - let (header, receipts) = header.extract(); - ( - into_substrate_ethereum_header(&header), - into_substrate_ethereum_receipts(&receipts), - ) - }) - .collect(), - ), - ); + let function = bridge_node_runtime::Call::BridgeEthPoA(bridge_node_runtime::BridgeEthPoACall::import_headers( + headers + .into_iter() + .map(|header| { + let (header, receipts) = header.extract(); + ( + into_substrate_ethereum_header(&header), + into_substrate_ethereum_receipts(&receipts), + ) + }) + .collect(), + )); let extra = |i: node_primitives::Index, f: node_primitives::Balance| { ( @@ -331,10 +298,5 @@ fn create_submit_transaction( let signer: sp_runtime::MultiSigner = signer.public().into(); let (function, extra, _) = raw_payload.deconstruct(); - bridge_node_runtime::UncheckedExtrinsic::new_signed( - function, - signer.into_account().into(), - signature.into(), - extra, - ) + bridge_node_runtime::UncheckedExtrinsic::new_signed(function, signer.into_account().into(), signature.into(), extra) } diff --git a/bridges/relays/ethereum/src/substrate_types.rs b/bridges/relays/ethereum/src/substrate_types.rs index 62b28e4735..fd1f07e693 100644 --- a/bridges/relays/ethereum/src/substrate_types.rs +++ b/bridges/relays/ethereum/src/substrate_types.rs @@ -30,17 +30,14 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . -pub use sp_bridge_eth_poa::{ - Address, Bloom, Bytes, H256, Header as SubstrateEthereumHeader, - LogEntry as SubstrateEthereumLogEntry, Receipt as SubstrateEthereumReceipt, - TransactionOutcome as SubstrateEthereumTransactionOutcome, U256, -}; pub use crate::ethereum_types::H256 as TransactionHash; use crate::ethereum_types::{ - HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, + Header as EthereumHeader, Receipt as EthereumReceipt, HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, RECEIPT_GAS_USED_PROOF as ETHEREUM_RECEIPT_GAS_USED_PROOF, - Header as EthereumHeader, - Receipt as EthereumReceipt, +}; +pub use sp_bridge_eth_poa::{ + Address, Bloom, Bytes, Header as SubstrateEthereumHeader, LogEntry as SubstrateEthereumLogEntry, + Receipt as SubstrateEthereumReceipt, TransactionOutcome as SubstrateEthereumTransactionOutcome, H256, U256, }; /// Convert Ethereum header into Ethereum header for Substrate. @@ -67,18 +64,27 @@ pub fn into_substrate_ethereum_header(header: &EthereumHeader) -> SubstrateEther pub fn into_substrate_ethereum_receipts( receipts: &Option>, ) -> Option> { - receipts.as_ref().map(|receipts| receipts.iter().map(|receipt| SubstrateEthereumReceipt { - gas_used: receipt.gas_used.expect(ETHEREUM_RECEIPT_GAS_USED_PROOF), - log_bloom: receipt.logs_bloom.data().into(), - logs: receipt.logs.iter().map(|log_entry| SubstrateEthereumLogEntry { - address: log_entry.address, - topics: log_entry.topics.clone(), - data: log_entry.data.0.clone(), - }).collect(), - outcome: match (receipt.status, receipt.root) { - (Some(status), None) => SubstrateEthereumTransactionOutcome::StatusCode(status.as_u64() as u8), - (None, Some(root)) => SubstrateEthereumTransactionOutcome::StateRoot(root), - _ => SubstrateEthereumTransactionOutcome::Unknown, - }, - }).collect()) + receipts.as_ref().map(|receipts| { + receipts + .iter() + .map(|receipt| SubstrateEthereumReceipt { + gas_used: receipt.gas_used.expect(ETHEREUM_RECEIPT_GAS_USED_PROOF), + log_bloom: receipt.logs_bloom.data().into(), + logs: receipt + .logs + .iter() + .map(|log_entry| SubstrateEthereumLogEntry { + address: log_entry.address, + topics: log_entry.topics.clone(), + data: log_entry.data.0.clone(), + }) + .collect(), + outcome: match (receipt.status, receipt.root) { + (Some(status), None) => SubstrateEthereumTransactionOutcome::StatusCode(status.as_u64() as u8), + (None, Some(root)) => SubstrateEthereumTransactionOutcome::StateRoot(root), + _ => SubstrateEthereumTransactionOutcome::Unknown, + }, + }) + .collect() + }) } diff --git a/bridges/relays/substrate/src/bridge.rs b/bridges/relays/substrate/src/bridge.rs index 044f4606d8..c203e85a2e 100644 --- a/bridges/relays/substrate/src/bridge.rs +++ b/bridges/relays/substrate/src/bridge.rs @@ -15,22 +15,27 @@ // along with Parity Bridges Common. If not, see . use crate::error::Error; +use crate::params::{Params, RPCUrlParam}; use crate::rpc::{self, SubstrateRPC}; -use crate::params::{RPCUrlParam, Params}; -use futures::{prelude::*, channel::{mpsc, oneshot}, future, select}; +use futures::{ + channel::{mpsc, oneshot}, + future, + prelude::*, + select, +}; use jsonrpsee::{ raw::client::{RawClient, RawClientError, RawClientEvent, RawClientRequestId, RawClientSubscription}, transport::{ + ws::{WsConnecError, WsTransportClient}, TransportClient, - ws::{WsTransportClient, WsConnecError}, }, }; use node_primitives::{Hash, Header}; +use sp_core::Bytes; use std::cell::RefCell; use std::collections::HashMap; use std::pin::Pin; -use sp_core::Bytes; type ChainId = Hash; @@ -71,24 +76,25 @@ async fn init_rpc_connection(url: &RPCUrlParam) -> Result { let genesis_hash = rpc::genesis_block_hash(&mut client) .await .map_err(|e| Error::RPCError(e.to_string()))? - .ok_or_else(|| Error::InvalidChainState(format!( - "chain with RPC URL {} is missing a genesis block hash", - url_str, - )))?; + .ok_or_else(|| { + Error::InvalidChainState(format!( + "chain with RPC URL {} is missing a genesis block hash", + url_str, + )) + })?; let latest_finalized_hash = SubstrateRPC::chain_finalized_head(&mut client) .await .map_err(|e| Error::RPCError(e.to_string()))?; - let latest_finalized_header = SubstrateRPC::chain_header( - &mut client, - Some(latest_finalized_hash) - ) + let latest_finalized_header = SubstrateRPC::chain_header(&mut client, Some(latest_finalized_hash)) .await .map_err(|e| Error::RPCError(e.to_string()))? - .ok_or_else(|| Error::InvalidChainState(format!( - "chain {} is missing header for finalized block hash {}", - genesis_hash, latest_finalized_hash - )))?; + .ok_or_else(|| { + Error::InvalidChainState(format!( + "chain {} is missing header for finalized block hash {}", + genesis_hash, latest_finalized_hash + )) + })?; let (sender, receiver) = mpsc::channel(0); @@ -101,41 +107,35 @@ async fn init_rpc_connection(url: &RPCUrlParam) -> Result { state: ChainState { current_finalized_head: latest_finalized_header, bridges: HashMap::new(), - } + }, }) } /// Returns IDs of the bridged chains. -async fn read_bridges(chain: &mut Chain, chain_ids: &[Hash]) - -> Result, Error> -{ +async fn read_bridges(chain: &mut Chain, chain_ids: &[Hash]) -> Result, Error> { // This should make an RPC call to read this information from the bridge pallet state. // For now, just pretend every chain is bridged to every other chain. // // TODO: The correct thing. - Ok( - chain_ids - .iter() - .cloned() - .filter(|&chain_id| chain_id != chain.genesis_hash) - .collect() - ) + Ok(chain_ids + .iter() + .cloned() + .filter(|&chain_id| chain_id != chain.genesis_hash) + .collect()) } -pub async fn run_async( - params: Params, - exit: Box + Unpin + Send> -) -> Result<(), Error> -{ +pub async fn run_async(params: Params, exit: Box + Unpin + Send>) -> Result<(), Error> { let chains = init_chains(¶ms).await?; - let (chain_tasks, exit_signals) = chains.into_iter() + let (chain_tasks, exit_signals) = chains + .into_iter() .map(|(chain_id, chain_cell)| { let chain = chain_cell.into_inner(); let (task_exit_signal, task_exit_receiver) = oneshot::channel(); - let task_exit = Box::new(task_exit_receiver.map(|result| { - result.expect("task_exit_signal is not dropped before send() is called") - })); + let task_exit = Box::new( + task_exit_receiver + .map(|result| result.expect("task_exit_signal is not dropped before send() is called")), + ); let chain_task = async_std::task::spawn(async move { if let Err(err) = chain_task(chain_id, chain, task_exit).await { log::error!("Error in task for chain {}: {}", chain_id, err); @@ -156,39 +156,43 @@ pub async fn run_async( Ok(()) } -fn initial_next_events<'a>(chains: &'a HashMap>) - -> Vec> + 'a>>> -{ - chains.values() +fn initial_next_events<'a>( + chains: &'a HashMap>, +) -> Vec> + 'a>>> { + chains + .values() .map(|chain_cell| async move { let mut chain = chain_cell.borrow_mut(); - let event = chain.client.next_event() + let event = chain + .client + .next_event() .await .map_err(|err| Error::RPCError(err.to_string()))?; Ok((chain.genesis_hash, event)) }) - .map(|fut| Box::pin(fut) as Pin>>) + .map(|fut| Box::pin(fut) as Pin>>) .collect() } async fn next_event<'a>( - next_events: Vec> + 'a>>>, + next_events: Vec> + 'a>>>, chains: &'a HashMap>, -) - -> ( - Result<(Hash, RawClientEvent), Error>, - Vec> +'a>>> - ) -{ +) -> ( + Result<(Hash, RawClientEvent), Error>, + Vec> + 'a>>>, +) { let (result, _, mut rest) = future::select_all(next_events).await; match result { Ok((chain_id, _)) => { let fut = async move { - let chain_cell = chains.get(&chain_id) + let chain_cell = chains + .get(&chain_id) .expect("chain must be in the map as a function precondition; qed"); let mut chain = chain_cell.borrow_mut(); - let event = chain.client.next_event() + let event = chain + .client + .next_event() .await .map_err(|err| Error::RPCError(err.to_string()))?; Ok((chain_id, event)) @@ -209,9 +213,7 @@ async fn init_chains(params: &Params) -> Result> .collect::, _>>()?; // TODO: Remove when read_bridges is implemented correctly. - let chain_ids = chains.keys() - .cloned() - .collect::>(); + let chain_ids = chains.keys().cloned().collect::>(); // let chain_ids_slice = chain_ids.as_slice(); for (&chain_id, chain_cell) in chains.iter() { @@ -229,15 +231,18 @@ async fn init_chains(params: &Params) -> Result> let genesis_head = SubstrateRPC::chain_header(&mut chain.client, chain_id) .await .map_err(|e| Error::RPCError(e.to_string()))? - .ok_or_else(|| Error::InvalidChainState(format!( - "chain {} is missing a genesis block header", chain_id - )))?; + .ok_or_else(|| { + Error::InvalidChainState(format!("chain {} is missing a genesis block header", chain_id)) + })?; let channel = chain.sender.clone(); - chain.state.bridges.insert(bridged_chain_id, BridgeState { - channel, - locally_finalized_head_on_bridged_chain: genesis_head, - }); + chain.state.bridges.insert( + bridged_chain_id, + BridgeState { + channel, + locally_finalized_head_on_bridged_chain: genesis_head, + }, + ); // The conditional ensures that we don't log twice per pair of chains. if chain_id.as_ref() < bridged_chain_id.as_ref() { @@ -250,28 +255,25 @@ async fn init_chains(params: &Params) -> Result> Ok(chains) } -async fn setup_subscriptions(chain: &mut Chain) - -> Result<(RawClientRequestId, RawClientRequestId), RawClientError> -{ - let new_heads_subscription_id = chain.client - .start_subscription( - "chain_subscribeNewHeads", - jsonrpsee::common::Params::None, - ) +async fn setup_subscriptions( + chain: &mut Chain, +) -> Result<(RawClientRequestId, RawClientRequestId), RawClientError> { + let new_heads_subscription_id = chain + .client + .start_subscription("chain_subscribeNewHeads", jsonrpsee::common::Params::None) .await .map_err(RawClientError::Inner)?; - let finalized_heads_subscription_id = chain.client - .start_subscription( - "chain_subscribeFinalizedHeads", - jsonrpsee::common::Params::None, - ) + let finalized_heads_subscription_id = chain + .client + .start_subscription("chain_subscribeFinalizedHeads", jsonrpsee::common::Params::None) .await .map_err(RawClientError::Inner)?; - let new_heads_subscription = - chain.client.subscription_by_id(new_heads_subscription_id) - .expect("subscription_id was returned from start_subscription above; qed"); + let new_heads_subscription = chain + .client + .subscription_by_id(new_heads_subscription_id) + .expect("subscription_id was returned from start_subscription above; qed"); let new_heads_subscription = match new_heads_subscription { RawClientSubscription::Active(_) => {} RawClientSubscription::Pending(subscription) => { @@ -279,9 +281,10 @@ async fn setup_subscriptions(chain: &mut Chain) } }; - let finalized_heads_subscription = - chain.client.subscription_by_id(finalized_heads_subscription_id) - .expect("subscription_id was returned from start_subscription above; qed"); + let finalized_heads_subscription = chain + .client + .subscription_by_id(finalized_heads_subscription_id) + .expect("subscription_id was returned from start_subscription above; qed"); let finalized_heads_subscription = match finalized_heads_subscription { RawClientSubscription::Active(subscription) => {} RawClientSubscription::Pending(subscription) => { @@ -298,27 +301,26 @@ async fn handle_rpc_event( event: RawClientEvent, new_heads_subscription_id: RawClientRequestId, finalized_heads_subscription_id: RawClientRequestId, -) -> Result<(), Error> -{ +) -> Result<(), Error> { match event { - RawClientEvent::SubscriptionNotif { request_id, result } => + RawClientEvent::SubscriptionNotif { request_id, result } => { if request_id == new_heads_subscription_id { - let header: Header = serde_json::from_value(result) - .map_err(Error::SerializationError)?; + let header: Header = serde_json::from_value(result).map_err(Error::SerializationError)?; log::info!("Received new head {:?} on chain {}", header, chain_id); } else if request_id == finalized_heads_subscription_id { - let header: Header = serde_json::from_value(result) - .map_err(Error::SerializationError)?; + let header: Header = serde_json::from_value(result).map_err(Error::SerializationError)?; log::info!("Received finalized head {:?} on chain {}", header, chain_id); // let old_finalized_head = chain_state.current_finalized_head; chain.state.current_finalized_head = header; for (bridged_chain_id, bridged_chain) in chain.state.bridges.iter_mut() { - if bridged_chain.locally_finalized_head_on_bridged_chain.number < - chain.state.current_finalized_head.number { + if bridged_chain.locally_finalized_head_on_bridged_chain.number + < chain.state.current_finalized_head.number + { // Craft and submit an extrinsic over RPC log::info!("Sending command to submit extrinsic to chain {}", chain_id); - let mut send_event = bridged_chain.channel + let mut send_event = bridged_chain + .channel .send(Event::SubmitExtrinsic(Bytes(Vec::new()))) .fuse(); @@ -343,12 +345,17 @@ async fn handle_rpc_event( } } else { return Err(Error::RPCError(format!( - "unexpected subscription response with request ID {:?}", request_id + "unexpected subscription response with request ID {:?}", + request_id ))); - }, - _ => return Err(Error::RPCError(format!( - "unexpected RPC event from chain {}: {:?}", chain_id, event - ))), + } + } + _ => { + return Err(Error::RPCError(format!( + "unexpected RPC event from chain {}: {:?}", + chain_id, event + ))) + } } Ok(()) } @@ -358,8 +365,7 @@ async fn handle_bridge_event( chain_id: ChainId, rpc_client: &mut RawClient, event: Event, -) -> Result<(), Error> -{ +) -> Result<(), Error> { match event { Event::SubmitExtrinsic(data) => { log::info!("Submitting extrinsic to chain {}", chain_id); @@ -374,13 +380,11 @@ async fn handle_bridge_event( async fn chain_task( chain_id: ChainId, mut chain: Chain, - exit: impl Future + Unpin + Send -) -> Result<(), Error> -{ - let (new_heads_subscription_id, finalized_heads_subscription_id) = - setup_subscriptions(&mut chain) - .await - .map_err(|e| Error::RPCError(e.to_string()))?; + exit: impl Future + Unpin + Send, +) -> Result<(), Error> { + let (new_heads_subscription_id, finalized_heads_subscription_id) = setup_subscriptions(&mut chain) + .await + .map_err(|e| Error::RPCError(e.to_string()))?; let mut exit = exit.fuse(); loop { diff --git a/bridges/relays/substrate/src/main.rs b/bridges/relays/substrate/src/main.rs index 7443c6bebc..7185313a57 100644 --- a/bridges/relays/substrate/src/main.rs +++ b/bridges/relays/substrate/src/main.rs @@ -22,8 +22,8 @@ mod rpc; use bridge::run_async; use params::{Params, RPCUrlParam}; -use clap::{App, Arg, value_t, values_t}; -use futures::{prelude::*, channel}; +use clap::{value_t, values_t, App, Arg}; +use futures::{channel, prelude::*}; use std::cell::Cell; use std::process; @@ -32,9 +32,7 @@ fn main() { env_logger::init(); let exit = setup_exit_handler(); - let result = async_std::task::block_on(async move { - run_async(params, exit).await - }); + let result = async_std::task::block_on(async move { run_async(params, exit).await }); if let Err(err) = result { log::error!("{}", err); process::exit(1); @@ -60,22 +58,17 @@ fn parse_args() -> Params { .value_name("HOST[:PORT]") .help("The URL of a bridged Substrate node") .takes_value(true) - .multiple(true) + .multiple(true), ) .get_matches(); - let base_path = value_t!(matches, "base-path", String) - .unwrap_or_else(|e| e.exit()); - let rpc_urls = values_t!(matches, "rpc-url", RPCUrlParam) - .unwrap_or_else(|e| e.exit()); + let base_path = value_t!(matches, "base-path", String).unwrap_or_else(|e| e.exit()); + let rpc_urls = values_t!(matches, "rpc-url", RPCUrlParam).unwrap_or_else(|e| e.exit()); - Params { - base_path, - rpc_urls, - } + Params { base_path, rpc_urls } } -fn setup_exit_handler() -> Box + Unpin + Send> { +fn setup_exit_handler() -> Box + Unpin + Send> { let (exit_sender, exit_receiver) = channel::oneshot::channel(); let exit_sender = Cell::new(Some(exit_sender)); @@ -86,11 +79,11 @@ fn setup_exit_handler() -> Box + Unpin + Send> { } } }) - .expect("must be able to set Ctrl-C handler"); + .expect("must be able to set Ctrl-C handler"); - Box::new(exit_receiver.map(|result| { - result.expect( - "exit_sender cannot be dropped as it is moved into a globally-referenced closure" - ) - })) + Box::new( + exit_receiver.map(|result| { + result.expect("exit_sender cannot be dropped as it is moved into a globally-referenced closure") + }), + ) } diff --git a/bridges/relays/substrate/src/params.rs b/bridges/relays/substrate/src/params.rs index 2b2e81321d..3129c920e8 100644 --- a/bridges/relays/substrate/src/params.rs +++ b/bridges/relays/substrate/src/params.rs @@ -16,8 +16,8 @@ use crate::error::Error; -use url::Url; use std::str::FromStr; +use url::Url; const DEFAULT_WS_PORT: u16 = 9944; @@ -42,8 +42,8 @@ impl FromStr for RPCUrlParam { type Err = Error; fn from_str(url_str: &str) -> Result { - let mut url = Url::parse(url_str) - .map_err(|e| Error::UrlError(format!("could not parse {}: {}", url_str, e)))?; + let mut url = + Url::parse(url_str).map_err(|e| Error::UrlError(format!("could not parse {}: {}", url_str, e)))?; if url.scheme() != "ws" { return Err(Error::UrlError(format!("must have scheme ws, found {}", url.scheme()))); diff --git a/bridges/relays/substrate/src/rpc.rs b/bridges/relays/substrate/src/rpc.rs index 38e751ce89..10e41907f7 100644 --- a/bridges/relays/substrate/src/rpc.rs +++ b/bridges/relays/substrate/src/rpc.rs @@ -41,8 +41,8 @@ jsonrpsee::rpc_api! { } } -pub async fn genesis_block_hash(client: &mut RawClient) - -> Result, RawClientError> -{ +pub async fn genesis_block_hash( + client: &mut RawClient, +) -> Result, RawClientError> { SubstrateRPC::chain_block_hash(client, Some(NumberOrHex::Number(0))).await }