diff --git a/bridges/relays/ethereum/Cargo.toml b/bridges/relays/ethereum/Cargo.toml index 16deabd7179516c06dde64c3132aaa9a8ccbcc26..1bedea7aedaa0278bdccb17f3ee733fe3f37ce27 100644 --- a/bridges/relays/ethereum/Cargo.toml +++ b/bridges/relays/ethereum/Cargo.toml @@ -8,9 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" async-std = "1.6.2" -async-stream = "0.3.0" async-trait = "0.1.40" -backoff = "0.2" bp-currency-exchange = { path = "../../primitives/currency-exchange" } bp-eth-poa = { path = "../../primitives/ethereum-poa" } clap = { version = "2.33.3", features = ["yaml"] } @@ -20,18 +18,18 @@ ethabi = "12.0" ethabi-contract = "11.0" ethabi-derive = "12.0" ethereum-tx-sign = "3.0" +exchange-relay = { path = "../exchange-relay" } futures = "0.3.5" +headers-relay = { path = "../headers-relay" } hex = "0.4" hex-literal = "0.3" -linked-hash-map = "0.5.3" log = "0.4.11" +messages-relay = { path = "../messages-relay" } num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } -parking_lot = "0.11.0" -rustc-hex = "2.0.1" +relay-utils = { path = "../utils" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.57" -sysinfo = "0.15" time = "0.2" web3 = "0.13" diff --git a/bridges/relays/ethereum/src/ethereum_client.rs b/bridges/relays/ethereum/src/ethereum_client.rs index bfcb7d9cb2c9eb80187e50a52919101802d3ec3e..5635197d6404ad33648fbc6f12ba55704065801b 100644 --- a/bridges/relays/ethereum/src/ethereum_client.rs +++ b/bridges/relays/ethereum/src/ethereum_client.rs @@ -21,17 +21,16 @@ use crate::ethereum_types::{ use crate::rpc::{Ethereum, EthereumRpc}; use crate::rpc_errors::{EthereumNodeError, RpcError}; use crate::substrate_types::{GrandpaJustification, Hash as SubstrateHash, QueuedSubstrateHeader, SubstrateHeaderId}; -use crate::sync_types::SubmittedHeaders; -use crate::utils::{HeaderId, MaybeConnectionError}; use async_trait::async_trait; use codec::{Decode, Encode}; use ethabi::FunctionOutputDecoder; +use headers_relay::sync_types::SubmittedHeaders; use jsonrpsee::raw::RawClient; use jsonrpsee::transport::http::HttpTransportClient; use jsonrpsee::Client; use parity_crypto::publickey::KeyPair; - +use relay_utils::{HeaderId, MaybeConnectionError}; use std::collections::HashSet; // to encode/decode contract calls @@ -693,17 +692,20 @@ mod tests { } fn header(number: SubstrateBlockNumber) -> QueuedSubstrateHeader { - QueuedSubstrateHeader::new(SubstrateHeader::new( - number, - Default::default(), - Default::default(), - if number == 0 { - Default::default() - } else { - header(number - 1).id().1 - }, - Default::default(), - )) + QueuedSubstrateHeader::new( + SubstrateHeader::new( + number, + Default::default(), + Default::default(), + if number == 0 { + Default::default() + } else { + header(number - 1).id().1 + }, + Default::default(), + ) + .into(), + ) } #[test] diff --git a/bridges/relays/ethereum/src/ethereum_deploy_contract.rs b/bridges/relays/ethereum/src/ethereum_deploy_contract.rs index 94ce80706773f7985f0a4b2a277a4ad51bb210fd..b04632fc7eae0a2fa875aaa68bbe41cee9b43b05 100644 --- a/bridges/relays/ethereum/src/ethereum_deploy_contract.rs +++ b/bridges/relays/ethereum/src/ethereum_deploy_contract.rs @@ -21,10 +21,10 @@ use crate::instances::BridgeInstance; use crate::rpc::SubstrateRpc; use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; use crate::substrate_types::{Hash as SubstrateHash, Header as SubstrateHeader, SubstrateHeaderId}; -use crate::utils::HeaderId; use codec::{Decode, Encode}; use num_traits::Zero; +use relay_utils::HeaderId; /// Ethereum synchronization parameters. #[derive(Debug)] diff --git a/bridges/relays/ethereum/src/ethereum_exchange.rs b/bridges/relays/ethereum/src/ethereum_exchange.rs index 666b71fa3b4e7d180f71117a09f36ce99bd20f7c..e5a821bf3a098f50f12855ef549b79b1eebf4366 100644 --- a/bridges/relays/ethereum/src/ethereum_exchange.rs +++ b/bridges/relays/ethereum/src/ethereum_exchange.rs @@ -21,23 +21,22 @@ use crate::ethereum_types::{ EthereumHeaderId, HeaderWithTransactions as EthereumHeaderWithTransactions, Transaction as EthereumTransaction, TransactionHash as EthereumTransactionHash, H256, }; -use crate::exchange::{ - relay_single_transaction_proof, SourceBlock, SourceClient, SourceTransaction, TargetClient, - TransactionProofPipeline, -}; -use crate::exchange_loop::{run as run_loop, InMemoryStorage}; use crate::instances::BridgeInstance; -use crate::metrics::MetricsParams; use crate::rpc::{EthereumRpc, SubstrateRpc}; use crate::rpc_errors::RpcError; use crate::substrate_client::{ SubmitEthereumExchangeTransactionProof, SubstrateConnectionParams, SubstrateRpcClient, SubstrateSigningParams, }; use crate::substrate_types::into_substrate_ethereum_receipt; -use crate::utils::HeaderId; use async_trait::async_trait; use bp_currency_exchange::MaybeLockFundsTransaction; +use exchange_relay::exchange::{ + relay_single_transaction_proof, SourceBlock, SourceClient, SourceTransaction, TargetClient, + TransactionProofPipeline, +}; +use exchange_relay::exchange_loop::{run as run_loop, InMemoryStorage}; +use relay_utils::{metrics::MetricsParams, HeaderId}; use rialto_runtime::exchange::EthereumTransactionInclusionProof; use std::time::Duration; diff --git a/bridges/relays/ethereum/src/ethereum_sync_loop.rs b/bridges/relays/ethereum/src/ethereum_sync_loop.rs index 939cad5666da211ca17aa94da4d66f0e2aedf303..10779845cbf24300ba574652e36f574384f98211 100644 --- a/bridges/relays/ethereum/src/ethereum_sync_loop.rs +++ b/bridges/relays/ethereum/src/ethereum_sync_loop.rs @@ -17,20 +17,24 @@ //! Ethereum PoA -> Substrate synchronization. use crate::ethereum_client::{EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient}; -use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, QueuedEthereumHeader, Receipt}; +use crate::ethereum_types::{ + EthereumHeaderId, EthereumHeadersSyncPipeline, EthereumSyncHeader as Header, QueuedEthereumHeader, Receipt, +}; use crate::instances::BridgeInstance; -use crate::metrics::MetricsParams; use crate::rpc::{EthereumRpc, SubstrateRpc}; use crate::rpc_errors::RpcError; use crate::substrate_client::{ SubmitEthereumHeaders, SubstrateConnectionParams, SubstrateRpcClient, SubstrateSigningParams, }; use crate::substrate_types::into_substrate_ethereum_header; -use crate::sync::{HeadersSyncParams, TargetTransactionMode}; -use crate::sync_loop::{SourceClient, TargetClient}; -use crate::sync_types::{SourceHeader, SubmittedHeaders}; use async_trait::async_trait; +use headers_relay::{ + sync::{HeadersSyncParams, TargetTransactionMode}, + sync_loop::{SourceClient, TargetClient}, + sync_types::{SourceHeader, SubmittedHeaders}, +}; +use relay_utils::metrics::MetricsParams; use web3::types::H256; use std::fmt::Debug; @@ -95,11 +99,11 @@ impl SourceClient<EthereumHeadersSyncPipeline> for EthereumHeadersSource { } async fn header_by_hash(&self, hash: H256) -> Result<Header, Self::Error> { - self.client.header_by_hash(hash).await + self.client.header_by_hash(hash).await.map(Into::into) } async fn header_by_number(&self, number: u64) -> Result<Header, Self::Error> { - self.client.header_by_number(number).await + self.client.header_by_number(number).await.map(Into::into) } async fn header_completion(&self, id: EthereumHeaderId) -> Result<(EthereumHeaderId, Option<()>), Self::Error> { @@ -199,7 +203,7 @@ pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { let source = EthereumHeadersSource::new(eth_client); let target = SubstrateHeadersTarget::new(sub_client, sign_sub_transactions, sub_sign); - crate::sync_loop::run( + headers_relay::sync_loop::run( source, consts::ETHEREUM_TICK_INTERVAL, target, diff --git a/bridges/relays/ethereum/src/ethereum_types.rs b/bridges/relays/ethereum/src/ethereum_types.rs index bdb960c8cd8164b48abe8ed5164141938050920f..bb780d69680192e3bbe2cbae7f2ccf0471e9c5db 100644 --- a/bridges/relays/ethereum/src/ethereum_types.rs +++ b/bridges/relays/ethereum/src/ethereum_types.rs @@ -15,9 +15,10 @@ // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; -use crate::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}; -use crate::utils::HeaderId; + use codec::Encode; +use headers_relay::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use relay_utils::HeaderId; pub use web3::types::{Address, Bytes, CallRequest, H256, U128, U256, U64}; @@ -34,6 +35,17 @@ pub type Transaction = web3::types::Transaction; /// Ethereum header type. pub type Header = web3::types::Block<H256>; +/// Ethereum header type used in headers sync. +#[derive(Clone, Debug, PartialEq)] +pub struct EthereumSyncHeader(Header); + +impl std::ops::Deref for EthereumSyncHeader { + type Target = Header; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + /// Ethereum header with transactions type. pub type HeaderWithTransactions = web3::types::Block<Transaction>; @@ -60,7 +72,7 @@ impl HeadersSyncPipeline for EthereumHeadersSyncPipeline { type Hash = H256; type Number = u64; - type Header = Header; + type Header = EthereumSyncHeader; type Extra = Vec<Receipt>; type Completion = (); @@ -72,7 +84,13 @@ impl HeadersSyncPipeline for EthereumHeadersSyncPipeline { } } -impl SourceHeader<H256, u64> for Header { +impl From<Header> for EthereumSyncHeader { + fn from(header: Header) -> Self { + Self(header) + } +} + +impl SourceHeader<H256, u64> for EthereumSyncHeader { fn id(&self) -> EthereumHeaderId { HeaderId( self.number.expect(HEADER_ID_PROOF).as_u64(), diff --git a/bridges/relays/ethereum/src/instances.rs b/bridges/relays/ethereum/src/instances.rs index 4d17bcbec9b8d1dc8d5395b3fd13edf0d2e3d2f1..6fa44740e89c7f3036fa9dca946a3bd29332da12 100644 --- a/bridges/relays/ethereum/src/instances.rs +++ b/bridges/relays/ethereum/src/instances.rs @@ -53,7 +53,7 @@ impl BridgeInstance for Rialto { .into_iter() .map(|header| { ( - into_substrate_ethereum_header(header.header()), + into_substrate_ethereum_header(&header.header()), into_substrate_ethereum_receipts(header.extra()), ) }) @@ -65,7 +65,7 @@ impl BridgeInstance for Rialto { fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { let pallet_call = rialto_runtime::BridgeEthPoACall::import_unsigned_header( - into_substrate_ethereum_header(header.header()), + into_substrate_ethereum_header(&header.header()), into_substrate_ethereum_receipts(header.extra()), ); diff --git a/bridges/relays/ethereum/src/main.rs b/bridges/relays/ethereum/src/main.rs index 16f9d3e79c2f04217c51640271d9b1dab045a788..85deab4f1ad4bc27244c80641a7fb26a2172d936 100644 --- a/bridges/relays/ethereum/src/main.rs +++ b/bridges/relays/ethereum/src/main.rs @@ -22,42 +22,28 @@ mod ethereum_exchange; mod ethereum_exchange_submit; mod ethereum_sync_loop; mod ethereum_types; -mod exchange; -mod exchange_loop; -mod exchange_loop_metrics; -mod headers; mod instances; -mod message_lane; -mod message_lane_loop; -mod message_race_delivery; -mod message_race_loop; -mod message_race_receiving; -mod metrics; mod rpc; mod rpc_errors; mod substrate_client; mod substrate_sync_loop; mod substrate_types; -mod sync; -mod sync_loop; -mod sync_loop_metrics; -mod sync_loop_tests; -mod sync_types; -mod utils; use ethereum_client::{EthereumConnectionParams, EthereumSigningParams}; use ethereum_deploy_contract::EthereumDeployContractParams; use ethereum_exchange::EthereumExchangeParams; use ethereum_exchange_submit::EthereumExchangeSubmitParams; use ethereum_sync_loop::EthereumSyncParams; +use headers_relay::sync::TargetTransactionMode; use hex_literal::hex; use instances::{BridgeInstance, Kovan, Rialto}; use parity_crypto::publickey::{KeyPair, Secret}; +use relay_utils::metrics::MetricsParams; use sp_core::crypto::Pair; use substrate_client::{SubstrateConnectionParams, SubstrateSigningParams}; use substrate_sync_loop::SubstrateSyncParams; -use sync::HeadersSyncParams; +use headers_relay::sync::HeadersSyncParams; use std::io::Write; fn main() { @@ -223,19 +209,28 @@ fn substrate_signing_params(matches: &clap::ArgMatches) -> Result<SubstrateSigni } fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result<EthereumSyncParams, String> { - let mut sync_params = HeadersSyncParams::ethereum_sync_default(); + use crate::ethereum_sync_loop::consts::*; + + let mut sync_params = HeadersSyncParams { + max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, + max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, + max_headers_in_single_submit: MAX_HEADERS_IN_SINGLE_SUBMIT, + max_headers_size_in_single_submit: MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT, + prune_depth: PRUNE_DEPTH, + target_tx_mode: TargetTransactionMode::Signed, + }; match matches.value_of("sub-tx-mode") { - Some("signed") => sync_params.target_tx_mode = sync::TargetTransactionMode::Signed, + Some("signed") => sync_params.target_tx_mode = TargetTransactionMode::Signed, Some("unsigned") => { - sync_params.target_tx_mode = sync::TargetTransactionMode::Unsigned; + sync_params.target_tx_mode = TargetTransactionMode::Unsigned; // tx pool won't accept too much unsigned transactions sync_params.max_headers_in_submitted_status = 10; } - Some("backup") => sync_params.target_tx_mode = sync::TargetTransactionMode::Backup, + Some("backup") => sync_params.target_tx_mode = TargetTransactionMode::Backup, Some(mode) => return Err(format!("Invalid sub-tx-mode: {}", mode)), - None => sync_params.target_tx_mode = sync::TargetTransactionMode::Signed, + None => sync_params.target_tx_mode = TargetTransactionMode::Signed, } let params = EthereumSyncParams { @@ -253,6 +248,8 @@ fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result<EthereumSyncParams } fn substrate_sync_params(matches: &clap::ArgMatches) -> Result<SubstrateSyncParams, String> { + use crate::substrate_sync_loop::consts::*; + let eth_contract_address: ethereum_types::Address = if let Some(eth_contract) = matches.value_of("eth-contract") { eth_contract.parse().map_err(|e| format!("{}", e))? } else { @@ -267,7 +264,14 @@ fn substrate_sync_params(matches: &clap::ArgMatches) -> Result<SubstrateSyncPara eth_sign: ethereum_signing_params(matches)?, metrics_params: metrics_params(matches)?, instance: instance_params(matches)?, - sync_params: HeadersSyncParams::substrate_sync_default(), + sync_params: HeadersSyncParams { + max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, + max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, + max_headers_in_single_submit: 4, + max_headers_size_in_single_submit: std::usize::MAX, + prune_depth: PRUNE_DEPTH, + target_tx_mode: TargetTransactionMode::Signed, + }, eth_contract_address, }; @@ -388,12 +392,12 @@ fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result<EthereumExchan Ok(params) } -fn metrics_params(matches: &clap::ArgMatches) -> Result<Option<metrics::MetricsParams>, String> { +fn metrics_params(matches: &clap::ArgMatches) -> Result<Option<MetricsParams>, String> { if matches.is_present("no-prometheus") { return Ok(None); } - let mut metrics_params = metrics::MetricsParams::default(); + let mut metrics_params = MetricsParams::default(); if let Some(prometheus_host) = matches.value_of("prometheus-host") { metrics_params.host = prometheus_host.into(); diff --git a/bridges/relays/ethereum/src/rpc_errors.rs b/bridges/relays/ethereum/src/rpc_errors.rs index 26206bdc1d6dc58216fe517fb90fdfc0efd80243..747ec151f1e43c4094f51d0a3c7c0a2127d3ac05 100644 --- a/bridges/relays/ethereum/src/rpc_errors.rs +++ b/bridges/relays/ethereum/src/rpc_errors.rs @@ -14,9 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. -use crate::utils::MaybeConnectionError; - use jsonrpsee::client::RequestError; +use relay_utils::MaybeConnectionError; /// Contains common errors that can occur when /// interacting with a Substrate or Ethereum node diff --git a/bridges/relays/ethereum/src/substrate_client.rs b/bridges/relays/ethereum/src/substrate_client.rs index e6004be1f7e7788d6c6d794d8978e59ee20de7dc..aadde0ec14f204a15450ee9016e8cd68f9cc631f 100644 --- a/bridges/relays/ethereum/src/substrate_client.rs +++ b/bridges/relays/ethereum/src/substrate_client.rs @@ -19,16 +19,16 @@ use crate::instances::BridgeInstance; use crate::rpc::{Substrate, SubstrateRpc}; use crate::rpc_errors::RpcError; use crate::substrate_types::{Hash, Header as SubstrateHeader, Number, SignedBlock as SignedSubstrateBlock}; -use crate::sync_types::SubmittedHeaders; -use crate::utils::HeaderId; use async_trait::async_trait; use bp_eth_poa::AuraHeader as SubstrateEthereumHeader; use codec::{Decode, Encode}; +use headers_relay::sync_types::SubmittedHeaders; use jsonrpsee::raw::RawClient; use jsonrpsee::transport::http::HttpTransportClient; use jsonrpsee::Client; use num_traits::Zero; +use relay_utils::HeaderId; use sp_core::crypto::Pair; use sp_runtime::traits::IdentifyAccount; use std::collections::VecDeque; diff --git a/bridges/relays/ethereum/src/substrate_sync_loop.rs b/bridges/relays/ethereum/src/substrate_sync_loop.rs index 4f796029a83adb0ef09d7be1844c34ce613abaee..ce3a5ae4d31411fa72858973e88528c272bb73fe 100644 --- a/bridges/relays/ethereum/src/substrate_sync_loop.rs +++ b/bridges/relays/ethereum/src/substrate_sync_loop.rs @@ -21,18 +21,21 @@ use crate::ethereum_client::{ }; use crate::ethereum_types::Address; use crate::instances::BridgeInstance; -use crate::metrics::MetricsParams; use crate::rpc::SubstrateRpc; use crate::rpc_errors::RpcError; use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; use crate::substrate_types::{ - GrandpaJustification, Hash, Header, Number, QueuedSubstrateHeader, SubstrateHeaderId, SubstrateHeadersSyncPipeline, + GrandpaJustification, Hash, Number, QueuedSubstrateHeader, SubstrateHeaderId, SubstrateHeadersSyncPipeline, + SubstrateSyncHeader as Header, }; -use crate::sync::HeadersSyncParams; -use crate::sync_loop::{SourceClient, TargetClient}; -use crate::sync_types::{SourceHeader, SubmittedHeaders}; use async_trait::async_trait; +use headers_relay::{ + sync::HeadersSyncParams, + sync_loop::{SourceClient, TargetClient}, + sync_types::{SourceHeader, SubmittedHeaders}, +}; +use relay_utils::metrics::MetricsParams; use std::fmt::Debug; use std::{collections::HashSet, time::Duration}; @@ -92,11 +95,11 @@ impl SourceClient<SubstrateHeadersSyncPipeline> for SubstrateHeadersSource { } async fn header_by_hash(&self, hash: Hash) -> Result<Header, Self::Error> { - self.client.header_by_hash(hash).await + self.client.header_by_hash(hash).await.map(Into::into) } async fn header_by_number(&self, number: Number) -> Result<Header, Self::Error> { - self.client.header_by_number(number).await + self.client.header_by_number(number).await.map(Into::into) } async fn header_completion( @@ -197,7 +200,7 @@ pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { let target = EthereumHeadersTarget::new(eth_client, eth_contract_address, eth_sign); let source = SubstrateHeadersSource::new(sub_client); - crate::sync_loop::run( + headers_relay::sync_loop::run( source, consts::SUBSTRATE_TICK_INTERVAL, target, diff --git a/bridges/relays/ethereum/src/substrate_types.rs b/bridges/relays/ethereum/src/substrate_types.rs index 05b96c037ff1eda79343bc7497d158603ad6b698..4f5328b778763fbbec8107b070ca83ad1adadf3e 100644 --- a/bridges/relays/ethereum/src/substrate_types.rs +++ b/bridges/relays/ethereum/src/substrate_types.rs @@ -17,10 +17,10 @@ use crate::ethereum_types::{ Header as EthereumHeader, Receipt as EthereumReceipt, HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, }; -use crate::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}; -use crate::utils::HeaderId; use codec::Encode; +use headers_relay::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use relay_utils::HeaderId; pub use bp_eth_poa::{ Address, AuraHeader as SubstrateEthereumHeader, Bloom, Bytes, LogEntry as SubstrateEthereumLogEntry, @@ -36,6 +36,17 @@ pub type Number = rialto_runtime::BlockNumber; /// Substrate header type. pub type Header = rialto_runtime::Header; +/// Substrate header type used in headers sync. +#[derive(Clone, Debug, PartialEq)] +pub struct SubstrateSyncHeader(Header); + +impl std::ops::Deref for SubstrateSyncHeader { + type Target = Header; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + /// Substrate signed block type. pub type SignedBlock = rialto_runtime::SignedBlock; @@ -59,7 +70,7 @@ impl HeadersSyncPipeline for SubstrateHeadersSyncPipeline { type Hash = rialto_runtime::Hash; type Number = rialto_runtime::BlockNumber; - type Header = Header; + type Header = SubstrateSyncHeader; type Extra = (); type Completion = GrandpaJustification; @@ -68,7 +79,13 @@ impl HeadersSyncPipeline for SubstrateHeadersSyncPipeline { } } -impl SourceHeader<rialto_runtime::Hash, rialto_runtime::BlockNumber> for Header { +impl From<Header> for SubstrateSyncHeader { + fn from(header: Header) -> Self { + Self(header) + } +} + +impl SourceHeader<rialto_runtime::Hash, rialto_runtime::BlockNumber> for SubstrateSyncHeader { fn id(&self) -> SubstrateHeaderId { HeaderId(self.number, self.hash()) } diff --git a/bridges/relays/exchange-relay/Cargo.toml b/bridges/relays/exchange-relay/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..87502fe6a6e5f026ba2e3d9e3e17ff316afe2b7a --- /dev/null +++ b/bridges/relays/exchange-relay/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "exchange-relay" +version = "0.1.0" +authors = ["Parity Technologies <admin@parity.io>"] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +async-std = "1.6.2" +async-trait = "0.1.40" +backoff = "0.2" +futures = "0.3.5" +log = "0.4.11" +num-traits = "0.2" +parking_lot = "0.11.0" +relay-utils = { path = "../utils" } diff --git a/bridges/relays/ethereum/src/exchange.rs b/bridges/relays/exchange-relay/src/exchange.rs similarity index 99% rename from bridges/relays/ethereum/src/exchange.rs rename to bridges/relays/exchange-relay/src/exchange.rs index e236b9d3cf56ef3f8f463c155c3e6040a0944f7a..0df2927d56c6ed623248f64aafa7069dd98dfacc 100644 --- a/bridges/relays/ethereum/src/exchange.rs +++ b/bridges/relays/exchange-relay/src/exchange.rs @@ -16,9 +16,8 @@ //! Relaying proofs of exchange transaction. -use crate::utils::{MaybeConnectionError, StringifiedMaybeConnectionError}; - use async_trait::async_trait; +use relay_utils::{MaybeConnectionError, StringifiedMaybeConnectionError}; use std::{ fmt::{Debug, Display}, string::ToString, @@ -54,7 +53,7 @@ pub trait SourceBlock { type Transaction: SourceTransaction; /// Return hash of the block. - fn id(&self) -> crate::utils::HeaderId<Self::Hash, Self::Number>; + fn id(&self) -> relay_utils::HeaderId<Self::Hash, Self::Number>; /// Return block transactions iterator. fn transactions(&self) -> Vec<Self::Transaction>; } @@ -81,7 +80,7 @@ pub type TransactionOf<P> = <<P as TransactionProofPipeline>::Block as SourceBlo pub type TransactionHashOf<P> = <TransactionOf<P> as SourceTransaction>::Hash; /// Header id. -pub type HeaderId<P> = crate::utils::HeaderId<BlockHashOf<P>, BlockNumberOf<P>>; +pub type HeaderId<P> = relay_utils::HeaderId<BlockHashOf<P>, BlockNumberOf<P>>; /// Source client API. #[async_trait] @@ -443,9 +442,9 @@ async fn wait_header_finalized<P: TransactionProofPipeline>( #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::utils::HeaderId; use parking_lot::Mutex; + use relay_utils::HeaderId; use std::{ collections::{HashMap, HashSet}, sync::Arc, diff --git a/bridges/relays/ethereum/src/exchange_loop.rs b/bridges/relays/exchange-relay/src/exchange_loop.rs similarity index 97% rename from bridges/relays/ethereum/src/exchange_loop.rs rename to bridges/relays/exchange-relay/src/exchange_loop.rs index 0da29d2324ed431fb5114603a5c465044f67227a..645672ba3f403756c06e75db1a35e80789619dfa 100644 --- a/bridges/relays/ethereum/src/exchange_loop.rs +++ b/bridges/relays/exchange-relay/src/exchange_loop.rs @@ -21,12 +21,14 @@ use crate::exchange::{ TransactionProofPipeline, }; use crate::exchange_loop_metrics::ExchangeLoopMetrics; -use crate::metrics::{start as metrics_start, GlobalMetrics, MetricsParams}; -use crate::utils::retry_backoff; use backoff::backoff::Backoff; use futures::{future::FutureExt, select}; use num_traits::One; +use relay_utils::{ + metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, + retry_backoff, +}; use std::{future::Future, time::Duration}; /// Delay after connection-related error happened before we'll try @@ -95,8 +97,8 @@ pub fn run<P: TransactionProofPipeline>( let mut state = storage.state(); let mut current_finalized_block = None; - let mut metrics_global = GlobalMetrics::new(); - let mut metrics_exch = ExchangeLoopMetrics::new(); + let mut metrics_global = GlobalMetrics::default(); + let mut metrics_exch = ExchangeLoopMetrics::default(); let metrics_enabled = metrics_params.is_some(); metrics_start( format!("{}_to_{}_Exchange", P::SOURCE_NAME, P::TARGET_NAME), diff --git a/bridges/relays/ethereum/src/exchange_loop_metrics.rs b/bridges/relays/exchange-relay/src/exchange_loop_metrics.rs similarity index 93% rename from bridges/relays/ethereum/src/exchange_loop_metrics.rs rename to bridges/relays/exchange-relay/src/exchange_loop_metrics.rs index 438360e22435ba3c9ab54d08ac9640e8f64b273c..325bfd2c9dfcd60951d5ba3babbb2b9d156c6105 100644 --- a/bridges/relays/ethereum/src/exchange_loop_metrics.rs +++ b/bridges/relays/exchange-relay/src/exchange_loop_metrics.rs @@ -14,8 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. +//! Metrics for currency-exchange relay loop. + use crate::exchange::{BlockNumberOf, RelayedBlockTransactions, TransactionProofPipeline}; -use crate::metrics::{register, Counter, CounterVec, GaugeVec, Metrics, Opts, Registry, U64}; +use relay_utils::metrics::{register, Counter, CounterVec, GaugeVec, Metrics, Opts, Registry, U64}; /// Exchange transactions relay metrics. pub struct ExchangeLoopMetrics { @@ -36,9 +38,8 @@ impl Metrics for ExchangeLoopMetrics { } } -impl ExchangeLoopMetrics { - /// Creates sync loop metrics. - pub fn new() -> Self { +impl Default for ExchangeLoopMetrics { + fn default() -> Self { ExchangeLoopMetrics { best_block_numbers: GaugeVec::new( Opts::new("best_block_numbers", "Best finalized block numbers"), @@ -54,7 +55,9 @@ impl ExchangeLoopMetrics { .expect("metric is static and thus valid; qed"), } } +} +impl ExchangeLoopMetrics { /// Update metrics when single block is relayed. pub fn update<P: TransactionProofPipeline>( &mut self, diff --git a/bridges/relays/exchange-relay/src/lib.rs b/bridges/relays/exchange-relay/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..f975ef2aa0ff4240172b86a07c6b5dfac803d501 --- /dev/null +++ b/bridges/relays/exchange-relay/src/lib.rs @@ -0,0 +1,26 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Parity Bridges Common. + +// Parity Bridges Common is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity Bridges Common is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. + +//! Relaying [`currency-exchange`](../pallet_bridge_currency_exchange/index.html) application +//! specific data. Currency exchange application allows exchanging tokens between bridged chains. +//! This module provides entrypoints for crafting and submitting (single and multiple) +//! proof-of-exchange-at-source-chain transaction(s) to target chain. + +#![warn(missing_docs)] + +pub mod exchange; +pub mod exchange_loop; +pub mod exchange_loop_metrics; diff --git a/bridges/relays/headers-relay/Cargo.toml b/bridges/relays/headers-relay/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..e289ac984fb86c8c6f9a730fdb6002b3195e0336 --- /dev/null +++ b/bridges/relays/headers-relay/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "headers-relay" +version = "0.1.0" +authors = ["Parity Technologies <admin@parity.io>"] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +async-std = "1.6.2" +async-trait = "0.1.40" +backoff = "0.2" +futures = "0.3.5" +linked-hash-map = "0.5.3" +log = "0.4.11" +num-traits = "0.2" +parking_lot = "0.11.0" +relay-utils = { path = "../utils" } diff --git a/bridges/relays/ethereum/src/headers.rs b/bridges/relays/headers-relay/src/headers.rs similarity index 92% rename from bridges/relays/ethereum/src/headers.rs rename to bridges/relays/headers-relay/src/headers.rs index 991d935548adf5b9e9ddd3383305a4e7ed635a9e..5800d370fba0a3f723a811cb0d8337c9e588319a 100644 --- a/bridges/relays/ethereum/src/headers.rs +++ b/bridges/relays/headers-relay/src/headers.rs @@ -14,11 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. +//! Headers queue - the intermediate buffer that is filled when headers are read +//! from the source chain. Headers are removed from the queue once they become +//! known to the target chain. Inside, there are several sub-queues, where headers +//! may stay until source/target chain state isn't updated. When a header reaches the +//! `ready` sub-queue, it may be submitted to the target chain. + use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SourceHeader}; -use crate::utils::HeaderId; use linked_hash_map::LinkedHashMap; use num_traits::{One, Zero}; +use relay_utils::HeaderId; use std::{ collections::{btree_map::Entry as BTreeMapEntry, hash_map::Entry as HashMapEntry, BTreeMap, HashMap, HashSet}, time::{Duration, Instant}, @@ -32,7 +38,7 @@ type KnownHeaders<P> = /// We're trying to fetch completion data for single header at this interval. const RETRY_FETCH_COMPLETION_INTERVAL: Duration = Duration::from_secs(20); -/// Ethereum headers queue. +/// Headers queue. #[derive(Debug)] pub struct QueuedHeaders<P: HeadersSyncPipeline> { /// Headers that are received from source node, but we (native sync code) have @@ -80,9 +86,8 @@ struct HeaderCompletion<Completion> { pub completion: Completion, } -impl<P: HeadersSyncPipeline> QueuedHeaders<P> { - /// Returns new QueuedHeaders. - pub fn new() -> Self { +impl<P: HeadersSyncPipeline> Default for QueuedHeaders<P> { + fn default() -> Self { QueuedHeaders { maybe_orphan: HeadersQueue::new(), orphan: HeadersQueue::new(), @@ -98,7 +103,9 @@ impl<P: HeadersSyncPipeline> QueuedHeaders<P> { prune_border: Zero::zero(), } } +} +impl<P: HeadersSyncPipeline> QueuedHeaders<P> { /// Returns prune border. #[cfg(test)] pub fn prune_border(&self) -> P::Number { @@ -778,57 +785,56 @@ fn queued_incomplete_header<Id: Clone + Eq + std::hash::Hash, T>( #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, H256}; + use crate::sync_loop_tests::{TestHash, TestHeader, TestHeaderId, TestHeadersSyncPipeline, TestNumber}; use crate::sync_types::QueuedHeader; - pub(crate) fn header(number: u64) -> QueuedHeader<EthereumHeadersSyncPipeline> { - QueuedHeader::new(Header { - number: Some(number.into()), - hash: Some(hash(number)), + pub(crate) fn header(number: TestNumber) -> QueuedHeader<TestHeadersSyncPipeline> { + QueuedHeader::new(TestHeader { + number, + hash: hash(number), parent_hash: hash(number - 1), - ..Default::default() }) } - pub(crate) fn hash(number: u64) -> H256 { - H256::from_low_u64_le(number) + pub(crate) fn hash(number: TestNumber) -> TestHash { + number } - pub(crate) fn id(number: u64) -> EthereumHeaderId { + pub(crate) fn id(number: TestNumber) -> TestHeaderId { HeaderId(number, hash(number)) } #[test] fn total_headers_works() { // total headers just sums up number of headers in every queue - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue.maybe_orphan.entry(1).or_default().insert( hash(1), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(Default::default()), ); queue.maybe_orphan.entry(1).or_default().insert( hash(2), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(Default::default()), ); queue.maybe_orphan.entry(2).or_default().insert( hash(3), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(Default::default()), ); queue.orphan.entry(3).or_default().insert( hash(4), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(Default::default()), ); queue.maybe_extra.entry(4).or_default().insert( hash(5), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(Default::default()), ); queue.ready.entry(5).or_default().insert( hash(6), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(Default::default()), ); queue.incomplete.entry(6).or_default().insert( hash(7), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(Default::default()), ); assert_eq!(queue.total_headers(), 7); } @@ -836,48 +842,48 @@ pub(crate) mod tests { #[test] fn best_queued_number_works() { // initially there are headers in MaybeOrphan queue only - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue.maybe_orphan.entry(1).or_default().insert( hash(1), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(Default::default()), ); queue.maybe_orphan.entry(1).or_default().insert( hash(2), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(Default::default()), ); queue.maybe_orphan.entry(3).or_default().insert( hash(3), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(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), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(Default::default()), ); assert_eq!(queue.best_queued_number(), 10); // and then there's better header in MaybeExtra queue.maybe_extra.entry(20).or_default().insert( hash(20), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(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), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(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), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(Default::default()), ); assert_eq!(queue.best_queued_number(), 40); // and then there's some header in Incomplete queue.incomplete.entry(50).or_default().insert( hash(50), - QueuedHeader::<EthereumHeadersSyncPipeline>::new(Default::default()), + QueuedHeader::<TestHeadersSyncPipeline>::new(Default::default()), ); assert_eq!(queue.best_queued_number(), 50); } @@ -885,7 +891,7 @@ pub(crate) mod tests { #[test] fn status_works() { // all headers are unknown initially - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); assert_eq!(queue.status(&id(10)), HeaderStatus::Unknown); // and status is read from the KnownHeaders queue @@ -899,22 +905,22 @@ pub(crate) mod tests { #[test] fn header_works() { // initially we have oldest header #10 - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue.maybe_orphan.entry(10).or_default().insert(hash(1), header(100)); assert_eq!( - queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), + queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, 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(), + queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, 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(), + queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, hash(102) ); } @@ -922,7 +928,7 @@ pub(crate) mod tests { #[test] fn header_response_works() { // when parent is Synced, we insert to MaybeExtra - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(100) @@ -932,7 +938,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); // when parent is Ready, we insert to MaybeExtra - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(100) @@ -942,7 +948,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); // when parent is Receipts, we insert to MaybeExtra - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(100) @@ -952,7 +958,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); // when parent is MaybeExtra, we insert to MaybeExtra - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(100) @@ -962,7 +968,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); // when parent is Orphan, we insert to Orphan - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(100) @@ -972,7 +978,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::Orphan); // when parent is MaybeOrphan, we insert to MaybeOrphan - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(100) @@ -982,7 +988,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeOrphan); // when parent is unknown, we insert to MaybeOrphan - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeOrphan); } @@ -996,7 +1002,7 @@ pub(crate) mod tests { // #98 in MaybeExtra // #97 in Receipts // #96 in Ready - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(100) @@ -1053,7 +1059,7 @@ pub(crate) mod tests { // #101 in Orphan // #102 in MaybeOrphan // #103 in Orphan - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(101) @@ -1095,7 +1101,7 @@ pub(crate) mod tests { // #102 in MaybeOrphan // 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::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(100) @@ -1140,7 +1146,7 @@ pub(crate) mod tests { // #101 in MaybeOrphan // 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::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(100) @@ -1172,7 +1178,7 @@ pub(crate) mod tests { #[test] fn positive_maybe_extra_response_works() { - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(100) @@ -1188,7 +1194,7 @@ pub(crate) mod tests { #[test] fn negative_maybe_extra_response_works() { // when parent header is complete - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(100) @@ -1217,14 +1223,14 @@ pub(crate) mod tests { #[test] fn receipts_response_works() { // when parent header is complete - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(100) .or_default() .insert(hash(100), HeaderStatus::Extra); queue.extra.entry(100).or_default().insert(hash(100), header(100)); - queue.extra_response(&id(100), Vec::new()); + queue.extra_response(&id(100), 100_100); assert!(queue.extra.is_empty()); assert_eq!(queue.ready.len(), 1); assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Ready); @@ -1237,7 +1243,7 @@ pub(crate) mod tests { .or_default() .insert(hash(201), HeaderStatus::Extra); queue.extra.entry(201).or_default().insert(hash(201), header(201)); - queue.extra_response(&id(201), Vec::new()); + queue.extra_response(&id(201), 201_201); assert!(queue.extra.is_empty()); assert_eq!(queue.incomplete.len(), 1); assert_eq!(queue.known_headers[&201][&hash(201)], HeaderStatus::Incomplete); @@ -1245,7 +1251,7 @@ pub(crate) mod tests { #[test] fn header_submitted_works() { - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(100) @@ -1259,7 +1265,7 @@ pub(crate) mod tests { #[test] fn incomplete_header_works() { - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); // nothing to complete if queue is empty assert_eq!(queue.incomplete_header(), None); @@ -1282,7 +1288,7 @@ pub(crate) mod tests { #[test] fn completion_response_works() { - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue.incomplete_headers.insert(id(100), None); queue.incomplete_headers.insert(id(200), Some(Instant::now())); @@ -1299,18 +1305,18 @@ pub(crate) mod tests { assert_eq!(queue.header_to_complete(), None); // when response is Some, we're scheduling completion - queue.completion_response(&id(200), Some(())); + queue.completion_response(&id(200), Some(200_200)); assert_eq!(queue.incomplete_headers.len(), 2); assert_eq!(queue.completion_data.len(), 1); assert!(queue.incomplete_headers.contains_key(&id(100))); assert!(queue.completion_data.contains_key(&id(200))); - assert_eq!(queue.header_to_complete(), Some((id(200), &()))); + assert_eq!(queue.header_to_complete(), Some((id(200), &200_200))); } #[test] fn header_completed_works() { - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); - queue.completion_data.insert(id(100), ()); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); + queue.completion_data.insert(id(100), 100_100); // when unknown header is completed queue.header_completed(&id(200)); @@ -1323,7 +1329,7 @@ pub(crate) mod tests { #[test] fn incomplete_headers_response_works() { - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); // when we have already submitted #101 and #102 is ready queue @@ -1370,7 +1376,7 @@ pub(crate) mod tests { #[test] fn is_parent_incomplete_works() { - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); // when we do not know header itself assert_eq!(queue.is_parent_incomplete(&id(50)), false); @@ -1404,7 +1410,7 @@ pub(crate) mod tests { assert_eq!(queue.is_parent_incomplete(&id(200)), true); // when parent is the incomplete header and we have completion data - queue.completion_data.insert(id(299), ()); + queue.completion_data.insert(id(299), 299_299); queue .known_headers .entry(300) @@ -1416,7 +1422,7 @@ pub(crate) mod tests { #[test] fn prune_works() { - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); queue .known_headers .entry(105) @@ -1487,7 +1493,7 @@ pub(crate) mod tests { #[test] fn incomplete_headers_are_still_incomplete_after_advance() { - let mut queue = QueuedHeaders::<EthereumHeadersSyncPipeline>::new(); + let mut queue = QueuedHeaders::<TestHeadersSyncPipeline>::default(); // relay#1 knows that header#100 is incomplete && it has headers 101..104 in incomplete queue queue.incomplete_headers.insert(id(100), None); diff --git a/bridges/relays/headers-relay/src/lib.rs b/bridges/relays/headers-relay/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..d91fe94d9d50b0b0783a674839425c8cfe6fc1d8 --- /dev/null +++ b/bridges/relays/headers-relay/src/lib.rs @@ -0,0 +1,33 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Parity Bridges Common. + +// Parity Bridges Common is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity Bridges Common is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. + +//! Relaying source chain headers to target chain. This module provides entrypoint +//! that starts reading new headers from source chain and submit these headers as +//! module/contract transactions to the target chain. Module/contract on the target +//! chain is a light-client of the source chain. All other trustless bridge +//! applications are built using this light-client, so running headers-relay is +//! essential for running all other bridge applications. + +// required for futures::select! +#![recursion_limit = "1024"] +#![warn(missing_docs)] + +pub mod headers; +pub mod sync; +pub mod sync_loop; +pub mod sync_loop_metrics; +pub mod sync_loop_tests; +pub mod sync_types; diff --git a/bridges/relays/ethereum/src/sync.rs b/bridges/relays/headers-relay/src/sync.rs similarity index 91% rename from bridges/relays/ethereum/src/sync.rs rename to bridges/relays/headers-relay/src/sync.rs index e86e9be4ae3399ca1bb5511c62d5dd8d9bac9f94..8e4c671dbaa9ed648d780c7112e6182d0897dcd7 100644 --- a/bridges/relays/ethereum/src/sync.rs +++ b/bridges/relays/headers-relay/src/sync.rs @@ -14,6 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. +//! Headers synchronization context. This structure wraps headers queue and is +//! able to choose: which headers to read from the source chain? Which headers +//! to submit to the target chain? The context makes decisions basing on parameters +//! passed using `HeadersSyncParams` structure. + use crate::headers::QueuedHeaders; use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader}; use num_traits::{One, Saturating, Zero}; @@ -36,38 +41,6 @@ pub struct HeadersSyncParams { pub target_tx_mode: TargetTransactionMode, } -impl HeadersSyncParams { - /// Default parameters for syncing Ethereum headers. - pub fn ethereum_sync_default() -> Self { - use crate::ethereum_sync_loop::consts::*; - - Self { - max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, - max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, - max_headers_in_single_submit: MAX_HEADERS_IN_SINGLE_SUBMIT, - max_headers_size_in_single_submit: MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT, - prune_depth: PRUNE_DEPTH, - target_tx_mode: TargetTransactionMode::Signed, - } - } - - /// Default parameters for syncing Substrate headers. - pub fn substrate_sync_default() -> Self { - use crate::substrate_sync_loop::consts::*; - - Self { - max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, - max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, - // since we always have single Substrate header in separate Ethereum transaction, - // all max_**_in_single_submit aren't important here - max_headers_in_single_submit: 4, - max_headers_size_in_single_submit: std::usize::MAX, - prune_depth: PRUNE_DEPTH, - target_tx_mode: TargetTransactionMode::Signed, - } - } -} - /// Target transaction mode. #[derive(Debug, PartialEq, Clone)] pub enum TargetTransactionMode { @@ -99,7 +72,7 @@ impl<P: HeadersSyncPipeline> HeadersSync<P> { /// Creates new headers synchronizer. pub fn new(params: HeadersSyncParams) -> Self { HeadersSync { - headers: QueuedHeaders::new(), + headers: QueuedHeaders::default(), params, source_best_number: None, target_best_header: None, @@ -308,13 +281,13 @@ impl<P: HeadersSyncPipeline> HeadersSync<P> { #[cfg(test)] pub mod tests { use super::*; - use crate::ethereum_types::{EthereumHeadersSyncPipeline, H256}; use crate::headers::tests::{header, id}; + use crate::sync_loop_tests::{TestHash, TestHeadersSyncPipeline, TestNumber}; use crate::sync_types::HeaderStatus; - use crate::utils::HeaderId; + use relay_utils::HeaderId; - fn side_hash(number: u64) -> H256 { - H256::from_low_u64_le(1000 + number) + fn side_hash(number: TestNumber) -> TestHash { + 1000 + number } pub fn default_sync_params() -> HeadersSyncParams { @@ -330,7 +303,7 @@ pub mod tests { #[test] fn select_new_header_to_download_works() { - let mut eth_sync = HeadersSync::<EthereumHeadersSyncPipeline>::new(default_sync_params()); + let mut eth_sync = HeadersSync::<TestHeadersSyncPipeline>::new(default_sync_params()); // both best && target headers are unknown assert_eq!(eth_sync.select_new_header_to_download(), None); @@ -366,7 +339,7 @@ pub mod tests { #[test] fn select_new_header_to_download_works_with_empty_queue() { - let mut eth_sync = HeadersSync::<EthereumHeadersSyncPipeline>::new(default_sync_params()); + let mut eth_sync = HeadersSync::<TestHeadersSyncPipeline>::new(default_sync_params()); eth_sync.source_best_header_number_response(100); // when queue is not empty => everything goes as usually @@ -489,7 +462,7 @@ pub mod tests { #[test] fn pruning_happens_on_target_best_header_response() { - let mut eth_sync = HeadersSync::<EthereumHeadersSyncPipeline>::new(default_sync_params()); + let mut eth_sync = HeadersSync::<TestHeadersSyncPipeline>::new(default_sync_params()); eth_sync.params.prune_depth = 50; eth_sync.target_best_header_response(id(100)); assert_eq!(eth_sync.headers.prune_border(), 50); diff --git a/bridges/relays/ethereum/src/sync_loop.rs b/bridges/relays/headers-relay/src/sync_loop.rs similarity index 98% rename from bridges/relays/ethereum/src/sync_loop.rs rename to bridges/relays/headers-relay/src/sync_loop.rs index 62a9b06a83de4fb66fdbec1fc18cb61c51baa53e..14eb7e2a4140e52d863d462328c7ef9269be2f46 100644 --- a/bridges/relays/ethereum/src/sync_loop.rs +++ b/bridges/relays/headers-relay/src/sync_loop.rs @@ -14,17 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. -use crate::metrics::{start as metrics_start, GlobalMetrics, MetricsParams}; +//! Entrypoint for running headers synchronization loop. + use crate::sync::HeadersSyncParams; use crate::sync_loop_metrics::SyncLoopMetrics; use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SubmittedHeaders}; -use crate::utils::{ - format_ids, interval, process_future_result, retry_backoff, MaybeConnectionError, StringifiedMaybeConnectionError, -}; use async_trait::async_trait; use futures::{future::FutureExt, stream::StreamExt}; use num_traits::{Saturating, Zero}; +use relay_utils::{ + format_ids, interval, + metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, + process_future_result, retry_backoff, MaybeConnectionError, StringifiedMaybeConnectionError, +}; use std::{ collections::HashSet, future::Future, @@ -117,8 +120,8 @@ pub fn run<P: HeadersSyncPipeline, TC: TargetClient<P>>( let mut stall_countdown = None; let mut last_update_time = Instant::now(); - let mut metrics_global = GlobalMetrics::new(); - let mut metrics_sync = SyncLoopMetrics::new(); + let mut metrics_global = GlobalMetrics::default(); + let mut metrics_sync = SyncLoopMetrics::default(); let metrics_enabled = metrics_params.is_some(); metrics_start( format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME), diff --git a/bridges/relays/ethereum/src/sync_loop_metrics.rs b/bridges/relays/headers-relay/src/sync_loop_metrics.rs similarity index 94% rename from bridges/relays/ethereum/src/sync_loop_metrics.rs rename to bridges/relays/headers-relay/src/sync_loop_metrics.rs index dc512a46e48f65110a2904fac38494739c50663b..26939ee372cb7e2ebca294bab780f62517f45264 100644 --- a/bridges/relays/ethereum/src/sync_loop_metrics.rs +++ b/bridges/relays/headers-relay/src/sync_loop_metrics.rs @@ -14,11 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. -use crate::metrics::{register, GaugeVec, Metrics, Opts, Registry, U64}; +//! Metrics for headers synchronization relay loop. + use crate::sync::HeadersSync; use crate::sync_types::{HeaderStatus, HeadersSyncPipeline}; use num_traits::Zero; +use relay_utils::metrics::{register, GaugeVec, Metrics, Opts, Registry, U64}; /// Headers sync metrics. pub struct SyncLoopMetrics { @@ -36,9 +38,8 @@ impl Metrics for SyncLoopMetrics { } } -impl SyncLoopMetrics { - /// Creates sync loop metrics. - pub fn new() -> Self { +impl Default for SyncLoopMetrics { + fn default() -> Self { SyncLoopMetrics { best_block_numbers: GaugeVec::new( Opts::new("best_block_numbers", "Best block numbers on source and target nodes"), @@ -52,7 +53,9 @@ impl SyncLoopMetrics { .expect("metric is static and thus valid; qed"), } } +} +impl SyncLoopMetrics { /// Update metrics. pub fn update<P: HeadersSyncPipeline>(&mut self, sync: &HeadersSync<P>) { let headers = sync.headers(); diff --git a/bridges/relays/ethereum/src/sync_loop_tests.rs b/bridges/relays/headers-relay/src/sync_loop_tests.rs similarity index 96% rename from bridges/relays/ethereum/src/sync_loop_tests.rs rename to bridges/relays/headers-relay/src/sync_loop_tests.rs index 8e2a4380ebbf7dd09967502c9625fc28fe539a49..84b2082ce91d402fb3d167fa6b4eb4839a1dfe1e 100644 --- a/bridges/relays/ethereum/src/sync_loop_tests.rs +++ b/bridges/relays/headers-relay/src/sync_loop_tests.rs @@ -18,30 +18,30 @@ use crate::sync_loop::{run, SourceClient, TargetClient}; use crate::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader, SubmittedHeaders}; -use crate::utils::{process_future_result, retry_backoff, HeaderId, MaybeConnectionError}; use async_trait::async_trait; use backoff::backoff::Backoff; use futures::{future::FutureExt, stream::StreamExt}; use parking_lot::Mutex; +use relay_utils::{process_future_result, retry_backoff, HeaderId, MaybeConnectionError}; use std::{ collections::{HashMap, HashSet}, sync::Arc, time::Duration, }; -type TestNumber = u64; -type TestHash = u64; -type TestExtra = u64; -type TestCompletion = u64; -type TestHeaderId = HeaderId<TestHash, TestNumber>; -type TestQueuedHeader = QueuedHeader<TestHeadersSyncPipeline>; +pub type TestNumber = u64; +pub type TestHash = u64; +pub type TestHeaderId = HeaderId<TestHash, TestNumber>; +pub type TestExtra = u64; +pub type TestCompletion = u64; +pub type TestQueuedHeader = QueuedHeader<TestHeadersSyncPipeline>; -#[derive(Debug, Clone, PartialEq)] -struct TestHeader { - hash: TestHash, - number: TestNumber, - parent_hash: TestHash, +#[derive(Default, Debug, Clone, PartialEq)] +pub struct TestHeader { + pub hash: TestHash, + pub number: TestNumber, + pub parent_hash: TestHash, } impl SourceHeader<TestHash, TestNumber> for TestHeader { @@ -63,8 +63,8 @@ impl MaybeConnectionError for TestError { } } -#[derive(Debug, Clone, Copy)] -struct TestHeadersSyncPipeline; +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct TestHeadersSyncPipeline; impl HeadersSyncPipeline for TestHeadersSyncPipeline { const SOURCE_NAME: &'static str = "Source"; diff --git a/bridges/relays/ethereum/src/sync_types.rs b/bridges/relays/headers-relay/src/sync_types.rs similarity index 97% rename from bridges/relays/ethereum/src/sync_types.rs rename to bridges/relays/headers-relay/src/sync_types.rs index 3970fb56291dbdcbf3f5a458509d22f1791d6ae1..21eec10c1e0d36f2acadf830d26d1db69e9ab7f8 100644 --- a/bridges/relays/ethereum/src/sync_types.rs +++ b/bridges/relays/headers-relay/src/sync_types.rs @@ -14,8 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. -use crate::utils::{format_ids, HeaderId}; +//! Types that are used by headers synchronization components. +use relay_utils::{format_ids, HeaderId}; use std::{ops::Deref, sync::Arc}; /// Ethereum header synchronization status. @@ -99,8 +100,7 @@ pub trait SourceHeader<Hash, Number> { } /// Header how it's stored in the synchronization queue. -#[derive(Clone, Debug)] -#[cfg_attr(test, derive(PartialEq))] +#[derive(Clone, Debug, PartialEq)] pub struct QueuedHeader<P: HeadersSyncPipeline>(Arc<QueuedHeaderData<P>>); impl<P: HeadersSyncPipeline> QueuedHeader<P> { @@ -129,8 +129,7 @@ impl<P: HeadersSyncPipeline> Deref for QueuedHeader<P> { } /// Header how it's stored in the synchronization queue. -#[derive(Clone, Debug, Default)] -#[cfg_attr(test, derive(PartialEq))] +#[derive(Clone, Debug, Default, PartialEq)] pub struct QueuedHeaderData<P: HeadersSyncPipeline> { header: P::Header, extra: Option<P::Extra>, diff --git a/bridges/relays/messages-relay/Cargo.toml b/bridges/relays/messages-relay/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..0af7eddc551fc4b6cbc585b3b7a69337b6df4509 --- /dev/null +++ b/bridges/relays/messages-relay/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "messages-relay" +version = "0.1.0" +authors = ["Parity Technologies <admin@parity.io>"] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +async-std = "1.6.2" +async-trait = "0.1.40" +futures = "0.3.5" +log = "0.4.11" +num-traits = "0.2" +parking_lot = "0.11.0" +relay-utils = { path = "../utils" } diff --git a/bridges/relays/messages-relay/src/lib.rs b/bridges/relays/messages-relay/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..fe764071cfb6f6ffe82834a353040de13e2c7eb2 --- /dev/null +++ b/bridges/relays/messages-relay/src/lib.rs @@ -0,0 +1,32 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Parity Bridges Common. + +// Parity Bridges Common is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity Bridges Common is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. + +//! Relaying [`message-lane`](../pallet_message_lane/index.html) application specific +//! data. Message lane allows sending arbitrary messages between bridged chains. This +//! module provides entrypoint that starts reading messages from given message lane +//! of source chain and submits proof-of-message-at-source-chain transactions to the +//! target chain. Additionaly, proofs-of-messages-delivery are sent back from the +//! target chain to the source chain. + +// required for futures::select! +#![recursion_limit = "1024"] +#![warn(missing_docs)] + +pub mod message_lane; +pub mod message_lane_loop; +pub mod message_race_delivery; +pub mod message_race_loop; +pub mod message_race_receiving; diff --git a/bridges/relays/ethereum/src/message_lane.rs b/bridges/relays/messages-relay/src/message_lane.rs similarity index 98% rename from bridges/relays/ethereum/src/message_lane.rs rename to bridges/relays/messages-relay/src/message_lane.rs index 0635456c40641e2f78b13cc9fb6120c52c03e6bd..8671451394eb19ec5e8260644bd44bb2bba46c33 100644 --- a/bridges/relays/ethereum/src/message_lane.rs +++ b/bridges/relays/messages-relay/src/message_lane.rs @@ -19,7 +19,7 @@ //! 1) relay new messages from source to target node; //! 2) relay proof-of-receiving from target to source node. -use crate::utils::HeaderId; +use relay_utils::HeaderId; use num_traits::{One, Zero}; use std::fmt::Debug; diff --git a/bridges/relays/ethereum/src/message_lane_loop.rs b/bridges/relays/messages-relay/src/message_lane_loop.rs similarity index 99% rename from bridges/relays/ethereum/src/message_lane_loop.rs rename to bridges/relays/messages-relay/src/message_lane_loop.rs index 0618382b83954d8c47dc33a8c4a2fa21e3f2c315..91d3017e93eae25d3270c415c067a328d3eaba25 100644 --- a/bridges/relays/ethereum/src/message_lane_loop.rs +++ b/bridges/relays/messages-relay/src/message_lane_loop.rs @@ -30,10 +30,10 @@ use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use crate::message_race_delivery::run as run_message_delivery_race; use crate::message_race_receiving::run as run_message_receiving_race; -use crate::utils::{interval, process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; use async_trait::async_trait; use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; +use relay_utils::{interval, process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; use std::{fmt::Debug, future::Future, ops::RangeInclusive, time::Duration}; /// Source client trait. @@ -334,9 +334,9 @@ async fn run_until_connection_lost<P: MessageLane, SC: SourceClient<P>, TC: Targ #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::utils::HeaderId; use futures::stream::StreamExt; use parking_lot::Mutex; + use relay_utils::HeaderId; use std::sync::Arc; pub fn header_id(number: TestSourceHeaderNumber) -> HeaderId<TestSourceHeaderNumber, TestSourceHeaderHash> { diff --git a/bridges/relays/ethereum/src/message_race_delivery.rs b/bridges/relays/messages-relay/src/message_race_delivery.rs similarity index 99% rename from bridges/relays/ethereum/src/message_race_delivery.rs rename to bridges/relays/messages-relay/src/message_race_delivery.rs index d55b8353ee4dcaadcac3346d1e4aab04d50f92be..7cac96c01b488a9774df93c787bff50d60530a79 100644 --- a/bridges/relays/ethereum/src/message_race_delivery.rs +++ b/bridges/relays/messages-relay/src/message_race_delivery.rs @@ -19,11 +19,11 @@ use crate::message_lane_loop::{ TargetClientState, }; use crate::message_race_loop::{MessageRace, RaceState, RaceStrategy, SourceClient, TargetClient}; -use crate::utils::{FailedClient, HeaderId}; use async_trait::async_trait; use futures::stream::FusedStream; use num_traits::{One, Zero}; +use relay_utils::{FailedClient, HeaderId}; use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive, time::Duration}; /// Maximal number of messages to relay in single transaction. diff --git a/bridges/relays/ethereum/src/message_race_loop.rs b/bridges/relays/messages-relay/src/message_race_loop.rs similarity index 99% rename from bridges/relays/ethereum/src/message_race_loop.rs rename to bridges/relays/messages-relay/src/message_race_loop.rs index 9d1657edb451e83545e7200cc7b4ad4b28c65a4e..30401cd0baaa9a66798366bcc3076f2ad09cc29a 100644 --- a/bridges/relays/ethereum/src/message_race_loop.rs +++ b/bridges/relays/messages-relay/src/message_race_loop.rs @@ -24,13 +24,13 @@ #![allow(dead_code)] use crate::message_lane_loop::ClientState; -use crate::utils::{process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; use async_trait::async_trait; use futures::{ future::FutureExt, stream::{FusedStream, StreamExt}, }; +use relay_utils::{process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; use std::{ fmt::Debug, ops::RangeInclusive, diff --git a/bridges/relays/ethereum/src/message_race_receiving.rs b/bridges/relays/messages-relay/src/message_race_receiving.rs similarity index 97% rename from bridges/relays/ethereum/src/message_race_receiving.rs rename to bridges/relays/messages-relay/src/message_race_receiving.rs index a50b713f0bd7c060bf764b3d6359e3b9c9608f6f..4eeea7adbd374828176301e56cbee7b4160d655f 100644 --- a/bridges/relays/ethereum/src/message_race_receiving.rs +++ b/bridges/relays/messages-relay/src/message_race_receiving.rs @@ -11,6 +11,8 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. +//! Message receiving race delivers proof-of-messages-delivery from lane.target to lane.source. + use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use crate::message_lane_loop::{ SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, @@ -18,10 +20,10 @@ use crate::message_lane_loop::{ }; use crate::message_race_delivery::DeliveryStrategy; use crate::message_race_loop::{MessageRace, SourceClient, TargetClient}; -use crate::utils::FailedClient; use async_trait::async_trait; use futures::stream::FusedStream; +use relay_utils::FailedClient; use std::{marker::PhantomData, ops::RangeInclusive, time::Duration}; /// Message receiving confirmations delivery strategy. diff --git a/bridges/relays/utils/Cargo.toml b/bridges/relays/utils/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..ffebd82a51aeedffd0f5b2dce13dcd3e8f7f615c --- /dev/null +++ b/bridges/relays/utils/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "relay-utils" +version = "0.1.0" +authors = ["Parity Technologies <admin@parity.io>"] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +async-std = "1.6.2" +backoff = "0.2" +futures = "0.3.5" +log = "0.4.11" +sysinfo = "0.15" + +# Substrate dependencies +substrate-prometheus-endpoint = { version = "0.8.0-rc6", git = "https://github.com/paritytech/substrate.git", tag = "v2.0.0-rc6" } diff --git a/bridges/relays/ethereum/src/utils.rs b/bridges/relays/utils/src/lib.rs similarity index 96% rename from bridges/relays/ethereum/src/utils.rs rename to bridges/relays/utils/src/lib.rs index e149f1884b2298218d6a286b7d097b4a3859fe3a..0b4d682c1cd41087e90be2d072b73ac3dce84452 100644 --- a/bridges/relays/ethereum/src/utils.rs +++ b/bridges/relays/utils/src/lib.rs @@ -14,16 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. +//! Utilities used by different relays. + use backoff::{backoff::Backoff, ExponentialBackoff}; use futures::future::FutureExt; use std::time::Duration; /// Max delay after connection-unrelated error happened before we'll try the /// same request again. -const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60); +pub const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60); /// Delay after connection-related error happened before we'll try /// reconnection again. -const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); +pub const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); + +pub mod metrics; /// Macro that returns (client, Err(error)) tuple from function if result is Err(error). #[macro_export] @@ -176,7 +180,7 @@ impl ProcessFutureResult { } /// Process result of the future from a client. -pub(crate) fn process_future_result<TResult, TError, TGoOfflineFuture>( +pub fn process_future_result<TResult, TError, TGoOfflineFuture>( result: Result<TResult, TError>, retry_backoff: &mut ExponentialBackoff, on_success: impl FnOnce(TResult), diff --git a/bridges/relays/ethereum/src/metrics.rs b/bridges/relays/utils/src/metrics.rs similarity index 98% rename from bridges/relays/ethereum/src/metrics.rs rename to bridges/relays/utils/src/metrics.rs index c94ecf6f02c85f869f6b5d76fef8fbcffa83015c..0667bdb922a00cdd11db6c5982315d941ff87799 100644 --- a/bridges/relays/ethereum/src/metrics.rs +++ b/bridges/relays/utils/src/metrics.rs @@ -107,9 +107,8 @@ impl Metrics for GlobalMetrics { } } -impl GlobalMetrics { - /// Creates global metrics. - pub fn new() -> Self { +impl Default for GlobalMetrics { + fn default() -> Self { GlobalMetrics { system: System::new_with_specifics(RefreshKind::everything()), system_average_load: GaugeVec::new(Opts::new("system_average_load", "System load average"), &["over"]) @@ -123,7 +122,9 @@ impl GlobalMetrics { .expect("metric is static and thus valid; qed"), } } +} +impl GlobalMetrics { /// Update metrics. pub fn update(&mut self) { // update system-wide metrics