From 3e45356aad95c25410690b0e6eb541ab40d6d3ac Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 3 Nov 2020 11:15:17 +0300 Subject: [PATCH] Rialto -> Millau headers relay (#477) * Rialto -> Millau headers relay * removed more constraints * removed file from other PR * Update primitives/rialto/src/lib.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bridges/bin/millau/runtime/src/lib.rs | 2 +- bridges/primitives/rialto/src/lib.rs | 13 +- bridges/primitives/runtime/src/chain.rs | 2 +- .../relays/ethereum/src/ethereum_exchange.rs | 8 +- .../relays/ethereum/src/ethereum_sync_loop.rs | 8 +- .../ethereum/src/substrate_sync_loop.rs | 7 +- .../relays/headers-relay/src/sync_types.rs | 4 +- bridges/relays/millau-client/src/lib.rs | 2 + bridges/relays/rialto-client/src/lib.rs | 6 + bridges/relays/substrate-client/src/chain.rs | 13 +- bridges/relays/substrate-client/src/client.rs | 5 +- .../substrate-client/src/headers_source.rs | 4 +- bridges/relays/substrate/Cargo.toml | 1 + bridges/relays/substrate/src/cli.rs | 11 ++ .../relays/substrate/src/headers_maintain.rs | 9 +- .../relays/substrate/src/headers_pipeline.rs | 140 ++++++++++++++++++ .../relays/substrate/src/headers_target.rs | 4 +- bridges/relays/substrate/src/main.rs | 25 ++++ .../substrate/src/millau_headers_to_rialto.rs | 113 +++----------- .../substrate/src/rialto_headers_to_millau.rs | 88 +++++++++++ 20 files changed, 337 insertions(+), 128 deletions(-) create mode 100644 bridges/relays/substrate/src/headers_pipeline.rs create mode 100644 bridges/relays/substrate/src/rialto_headers_to_millau.rs diff --git a/bridges/bin/millau/runtime/src/lib.rs b/bridges/bin/millau/runtime/src/lib.rs index 1e5a8feddeaf..faad5153d822 100644 --- a/bridges/bin/millau/runtime/src/lib.rs +++ b/bridges/bin/millau/runtime/src/lib.rs @@ -57,7 +57,7 @@ pub use frame_support::{ pub use pallet_balances::Call as BalancesCall; pub use pallet_message_lane::Call as MessageLaneCall; -pub use pallet_substrate_bridge::Call as BridgeSubstrateCall; +pub use pallet_substrate_bridge::Call as BridgeRialtoCall; pub use pallet_timestamp::Call as TimestampCall; #[cfg(any(feature = "std", test))] diff --git a/bridges/primitives/rialto/src/lib.rs b/bridges/primitives/rialto/src/lib.rs index 426c5c4f1f89..b024dc66c3a9 100644 --- a/bridges/primitives/rialto/src/lib.rs +++ b/bridges/primitives/rialto/src/lib.rs @@ -29,11 +29,11 @@ use sp_runtime::{ }; use sp_std::prelude::*; -/// Maximal weight of single Millau block. +/// Maximal weight of single Rialto block. pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2_000_000_000_000; /// Portion of block reserved for regular transactions. pub const AVAILABLE_BLOCK_RATIO: u32 = 75; -/// Maximal weight of single Millau extrinsic (65% of maximum block weight = 75% for regular +/// Maximal weight of single Rialto extrinsic (65% of maximum block weight = 75% for regular /// transactions minus 10% for initialization). pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10); @@ -60,6 +60,15 @@ impl Chain for Rialto { type Header = Header; } +/// Name of the `RialtoHeaderApi::best_blocks` runtime method. +pub const BEST_RIALTO_BLOCKS_METHOD: &str = "RialtoHeaderApi_best_blocks"; +/// Name of the `RialtoHeaderApi::finalized_block` runtime method. +pub const FINALIZED_RIALTO_BLOCK_METHOD: &str = "RialtoHeaderApi_finalized_block"; +/// Name of the `RialtoHeaderApi::is_known_block` runtime method. +pub const IS_KNOWN_RIALTO_BLOCK_METHOD: &str = "RialtoHeaderApi_is_known_block"; +/// Name of the `RialtoHeaderApi::incomplete_headers` runtime method. +pub const INCOMPLETE_RIALTO_HEADERS_METHOD: &str = "RialtoHeaderApi_incomplete_headers"; + /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = MultiSignature; diff --git a/bridges/primitives/runtime/src/chain.rs b/bridges/primitives/runtime/src/chain.rs index a63d5688d905..706e56f667ec 100644 --- a/bridges/primitives/runtime/src/chain.rs +++ b/bridges/primitives/runtime/src/chain.rs @@ -70,7 +70,7 @@ pub trait Chain: Send + Sync + 'static { /// A type that fulfills the abstract idea of what a Substrate header is. // See here for more info: // https://crates.parity.io/sp_runtime/traits/trait.Header.html - type Header: Parameter + HeaderT; + type Header: Parameter + HeaderT + MaybeSerializeDeserialize; } /// Block number used by the chain. diff --git a/bridges/relays/ethereum/src/ethereum_exchange.rs b/bridges/relays/ethereum/src/ethereum_exchange.rs index c8b8a7a7e8eb..870de74f7835 100644 --- a/bridges/relays/ethereum/src/ethereum_exchange.rs +++ b/bridges/relays/ethereum/src/ethereum_exchange.rs @@ -36,15 +36,15 @@ use relay_ethereum_client::{ Client as EthereumClient, ConnectionParams as EthereumConnectionParams, }; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams}; +use relay_substrate_client::{ + Chain as SubstrateChain, Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, +}; use relay_utils::{metrics::MetricsParams, HeaderId}; use rialto_runtime::exchange::EthereumTransactionInclusionProof; use std::{sync::Arc, time::Duration}; /// Interval at which we ask Ethereum node for updates. const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10); -/// Interval at which we ask Substrate node for updates. -const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(5); /// Exchange relay mode. #[derive(Debug)] @@ -210,7 +210,7 @@ impl TargetClient for SubstrateTransactionsTarget { type Error = RpcError; async fn tick(&self) { - async_std::task::sleep(SUBSTRATE_TICK_INTERVAL).await; + async_std::task::sleep(Rialto::AVERAGE_BLOCK_INTERVAL).await; } async fn is_header_known(&self, id: &EthereumHeaderId) -> Result { diff --git a/bridges/relays/ethereum/src/ethereum_sync_loop.rs b/bridges/relays/ethereum/src/ethereum_sync_loop.rs index c2dd0b2d1e19..ec0c95c70ca7 100644 --- a/bridges/relays/ethereum/src/ethereum_sync_loop.rs +++ b/bridges/relays/ethereum/src/ethereum_sync_loop.rs @@ -34,7 +34,9 @@ use relay_ethereum_client::{ Client as EthereumClient, ConnectionParams as EthereumConnectionParams, }; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams}; +use relay_substrate_client::{ + Chain as SubstrateChain, Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, +}; use relay_utils::metrics::MetricsParams; use std::fmt::Debug; @@ -45,8 +47,6 @@ pub mod consts { /// Interval at which we check new Ethereum headers when we are synced/almost synced. pub const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10); - /// Interval at which we check new Substrate blocks. - pub const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(5); /// Max number of headers in single submit transaction. pub const MAX_HEADERS_IN_SINGLE_SUBMIT: usize = 32; /// Max total size of headers in single submit transaction. This only affects signed @@ -253,7 +253,7 @@ pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { source, consts::ETHEREUM_TICK_INTERVAL, target, - consts::SUBSTRATE_TICK_INTERVAL, + Rialto::AVERAGE_BLOCK_INTERVAL, (), sync_params, metrics_params, diff --git a/bridges/relays/ethereum/src/substrate_sync_loop.rs b/bridges/relays/ethereum/src/substrate_sync_loop.rs index fcc6e2786b56..7ca9d797dfe5 100644 --- a/bridges/relays/ethereum/src/substrate_sync_loop.rs +++ b/bridges/relays/ethereum/src/substrate_sync_loop.rs @@ -32,7 +32,8 @@ use relay_ethereum_client::{ }; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SyncHeader as RialtoSyncHeader}; use relay_substrate_client::{ - headers_source::HeadersSource, Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, + headers_source::HeadersSource, Chain as SubstrateChain, Client as SubstrateClient, + ConnectionParams as SubstrateConnectionParams, }; use relay_utils::metrics::MetricsParams; use sp_runtime::Justification; @@ -43,8 +44,6 @@ use std::{collections::HashSet, time::Duration}; pub mod consts { use super::*; - /// Interval at which we check new Substrate headers when we are synced/almost synced. - pub const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(10); /// Interval at which we check new Ethereum blocks. pub const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(5); /// Max Ethereum headers we want to have in all 'before-submitted' states. @@ -174,7 +173,7 @@ pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { headers_relay::sync_loop::run( source, - consts::SUBSTRATE_TICK_INTERVAL, + Rialto::AVERAGE_BLOCK_INTERVAL, target, consts::ETHEREUM_TICK_INTERVAL, (), diff --git a/bridges/relays/headers-relay/src/sync_types.rs b/bridges/relays/headers-relay/src/sync_types.rs index 54a41a8aaa57..958c81dd911e 100644 --- a/bridges/relays/headers-relay/src/sync_types.rs +++ b/bridges/relays/headers-relay/src/sync_types.rs @@ -68,7 +68,7 @@ pub trait HeadersSyncPipeline: Clone + Send + Sync { + num_traits::One + Into; /// Type of header that we're syncing. - type Header: Clone + std::fmt::Debug + PartialEq + SourceHeader + Send + Sync; + type Header: SourceHeader; /// Type of extra data for the header that we're receiving from the source node: /// 1) extra data is required for some headers; /// 2) target node may answer if it'll require extra data before header is submitted; @@ -94,7 +94,7 @@ pub trait HeadersSyncPipeline: Clone + Send + Sync { pub type HeaderIdOf

= HeaderId<

::Hash,

::Number>; /// Header that we're receiving from source node. -pub trait SourceHeader { +pub trait SourceHeader: Clone + std::fmt::Debug + PartialEq + Send + Sync { /// Returns ID of header. fn id(&self) -> HeaderId; /// Returns ID of parent header. diff --git a/bridges/relays/millau-client/src/lib.rs b/bridges/relays/millau-client/src/lib.rs index e2ab00e4b7b8..9c018a8419a4 100644 --- a/bridges/relays/millau-client/src/lib.rs +++ b/bridges/relays/millau-client/src/lib.rs @@ -26,6 +26,8 @@ use sp_runtime::{ }; use std::time::Duration; +pub use millau_runtime::BridgeRialtoCall; + /// Millau header id. pub type HeaderId = relay_utils::HeaderId; diff --git a/bridges/relays/rialto-client/src/lib.rs b/bridges/relays/rialto-client/src/lib.rs index 8ab542680395..f45408d1538a 100644 --- a/bridges/relays/rialto-client/src/lib.rs +++ b/bridges/relays/rialto-client/src/lib.rs @@ -151,6 +151,12 @@ impl From for SyncHeader { } } +impl From for rialto_runtime::Header { + fn from(header: SyncHeader) -> Self { + header.0 + } +} + impl SourceHeader for SyncHeader { fn id(&self) -> HeaderId { relay_utils::HeaderId(*self.number(), self.hash()) diff --git a/bridges/relays/substrate-client/src/chain.rs b/bridges/relays/substrate-client/src/chain.rs index d82845b25e41..1de2bf401f13 100644 --- a/bridges/relays/substrate-client/src/chain.rs +++ b/bridges/relays/substrate-client/src/chain.rs @@ -34,14 +34,23 @@ pub trait Chain: ChainBase { const NAME: &'static str; /// Average block interval. /// - /// How often blocks are produced on that chain. It's suggested to set this value to match the block time of the chain. + /// How often blocks are produced on that chain. It's suggested to set this value + /// to match the block time of the chain. const AVERAGE_BLOCK_INTERVAL: Duration; /// The user account identifier type for the runtime. type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; /// Account index (aka nonce) type. This stores the number of previous transactions associated /// with a sender account. - type Index: Parameter + Member + MaybeSerialize + Debug + Default + MaybeDisplay + AtLeast32Bit + Copy; + type Index: Parameter + + Member + + MaybeSerialize + + Debug + + Default + + MaybeDisplay + + DeserializeOwned + + AtLeast32Bit + + Copy; /// Block type. type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. diff --git a/bridges/relays/substrate-client/src/client.rs b/bridges/relays/substrate-client/src/client.rs index 05a0da47ebe8..9ff54c4b3ab2 100644 --- a/bridges/relays/substrate-client/src/client.rs +++ b/bridges/relays/substrate-client/src/client.rs @@ -138,10 +138,7 @@ impl Client { /// Get the nonce of the given Substrate account. /// /// Note: It's the caller's responsibility to make sure `account` is a valid ss58 address. - pub async fn next_account_index(&self, account: C::AccountId) -> Result - where - C::Index: DeserializeOwned, - { + pub async fn next_account_index(&self, account: C::AccountId) -> Result { Ok(Substrate::::system_account_next_index(&self.client, account).await?) } diff --git a/bridges/relays/substrate-client/src/headers_source.rs b/bridges/relays/substrate-client/src/headers_source.rs index 14be6e0e65cb..b9b46774ce58 100644 --- a/bridges/relays/substrate-client/src/headers_source.rs +++ b/bridges/relays/substrate-client/src/headers_source.rs @@ -25,7 +25,6 @@ use headers_relay::{ sync_loop::SourceClient, sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SourceHeader}, }; -use jsonrpsee::common::DeserializeOwned; use num_traits::Saturating; use sp_runtime::{traits::Header as HeaderT, Justification}; use std::marker::PhantomData; @@ -51,8 +50,7 @@ impl SourceClient

for HeadersSource where C: Chain, C::BlockNumber: Into + Saturating, - C::Header: DeserializeOwned + Into, - C::Index: DeserializeOwned, + C::Header: Into, P: HeadersSyncPipeline, P::Header: SourceHeader, { diff --git a/bridges/relays/substrate/Cargo.toml b/bridges/relays/substrate/Cargo.toml index 3a760ffde86b..c5dca17c9fab 100644 --- a/bridges/relays/substrate/Cargo.toml +++ b/bridges/relays/substrate/Cargo.toml @@ -12,6 +12,7 @@ codec = { package = "parity-scale-codec", version = "1.3.4" } futures = "0.3.7" hex = "0.4" log = "0.4.11" +num-traits = "0.2" paste = "1.0" structopt = "0.3" diff --git a/bridges/relays/substrate/src/cli.rs b/bridges/relays/substrate/src/cli.rs index ec081cd1d278..cff2d3621110 100644 --- a/bridges/relays/substrate/src/cli.rs +++ b/bridges/relays/substrate/src/cli.rs @@ -39,6 +39,17 @@ pub enum Command { #[structopt(flatten)] prometheus_params: PrometheusParams, }, + /// Relay Rialto headers to Millau. + RialtoHeadersToMillau { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, + }, /// Submit message to given Rialto -> Millau lane. SubmitMillauToRialtoMessage { #[structopt(flatten)] diff --git a/bridges/relays/substrate/src/headers_maintain.rs b/bridges/relays/substrate/src/headers_maintain.rs index e5e7c7023cda..af3196b375b2 100644 --- a/bridges/relays/substrate/src/headers_maintain.rs +++ b/bridges/relays/substrate/src/headers_maintain.rs @@ -43,7 +43,7 @@ use headers_relay::{ use relay_substrate_client::{Chain, Client, Error as SubstrateError, JustificationsSubscription}; use relay_utils::HeaderId; use sp_core::Bytes; -use sp_runtime::{traits::Header as HeaderT, DeserializeOwned, Justification}; +use sp_runtime::{traits::Header as HeaderT, Justification}; use std::{collections::VecDeque, task::Poll}; /// Substrate-to-Substrate headers synchronization maintain procedure. @@ -80,8 +80,6 @@ impl SubstrateHeadersToSubstrateMaint impl SyncMaintain

for SubstrateHeadersToSubstrateMaintain where C: Chain, - C::Header: DeserializeOwned, - C::Index: DeserializeOwned, P::Number: Decode + From, P::Hash: Decode + From, P: SubstrateHeadersSyncPipeline, @@ -271,8 +269,6 @@ where P::Number: Decode + From, P::Hash: Decode + From, C: Chain, - C::Header: DeserializeOwned, - C::Index: DeserializeOwned, { let call = P::FINALIZED_BLOCK_METHOD.into(); let data = Bytes(Vec::new()); @@ -288,7 +284,8 @@ where #[cfg(test)] mod tests { use super::*; - use crate::millau_headers_to_rialto::{sync_params, MillauHeadersToRialto}; + use crate::headers_pipeline::sync_params; + use crate::millau_headers_to_rialto::MillauHeadersToRialto; fn parent_hash(index: u8) -> bp_millau::Hash { if index == 1 { diff --git a/bridges/relays/substrate/src/headers_pipeline.rs b/bridges/relays/substrate/src/headers_pipeline.rs new file mode 100644 index 000000000000..3a6348961fb7 --- /dev/null +++ b/bridges/relays/substrate/src/headers_pipeline.rs @@ -0,0 +1,140 @@ +// 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 . + +//! Substrate-to-Substrate headers sync entrypoint. + +use crate::{ + headers_maintain::SubstrateHeadersToSubstrateMaintain, + headers_target::{SubstrateHeadersSyncPipeline, SubstrateHeadersTarget}, +}; + +use codec::Encode; +use headers_relay::{ + sync::{HeadersSyncParams, TargetTransactionMode}, + sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}, +}; +use num_traits::Saturating; +use relay_substrate_client::{headers_source::HeadersSource, BlockNumberOf, Chain, Client, HashOf}; +use sp_runtime::Justification; +use std::marker::PhantomData; + +/// Substrate-to-Substrate headers pipeline. +#[derive(Debug, Clone)] +pub struct SubstrateHeadersToSubstrate { + /// Client for the target chain. + pub(crate) target_client: Client, + /// Data required to sign target chain transactions. + pub(crate) target_sign: TargetSign, + /// Unused generic arguments dump. + _marker: PhantomData<(SourceChain, SourceSyncHeader)>, +} + +impl + SubstrateHeadersToSubstrate +{ + /// Create new Substrate-to-Substrate headers pipeline. + pub fn new(target_client: Client, target_sign: TargetSign) -> Self { + SubstrateHeadersToSubstrate { + target_client, + target_sign, + _marker: Default::default(), + } + } +} + +impl HeadersSyncPipeline + for SubstrateHeadersToSubstrate +where + SourceChain: Clone + Chain, + BlockNumberOf: Saturating + Into, + SourceSyncHeader: + SourceHeader, BlockNumberOf> + std::ops::Deref, + TargetChain: Clone + Chain, + TargetSign: Clone + Send + Sync, +{ + const SOURCE_NAME: &'static str = SourceChain::NAME; + const TARGET_NAME: &'static str = TargetChain::NAME; + + type Hash = HashOf; + type Number = BlockNumberOf; + type Header = SourceSyncHeader; + type Extra = (); + type Completion = Justification; + + fn estimate_size(source: &QueuedHeader) -> usize { + source.header().encode().len() + } +} + +/// Return sync parameters for Substrate-to-Substrate headers sync. +pub fn sync_params() -> HeadersSyncParams { + HeadersSyncParams { + max_future_headers_to_download: 32, + max_headers_in_submitted_status: 8, + max_headers_in_single_submit: 1, + max_headers_size_in_single_submit: 1024 * 1024, + prune_depth: 256, + target_tx_mode: TargetTransactionMode::Signed, + } +} + +/// Run Substrate-to-Substrate headers sync. +pub async fn run( + pipeline: P, + source_client: Client, + target_client: Client, + metrics_params: Option, +) where + P: SubstrateHeadersSyncPipeline< + Hash = HashOf, + Number = BlockNumberOf, + Completion = Justification, + Extra = (), + >, + P::Header: SourceHeader, BlockNumberOf>, + SourceChain: Clone + Chain, + SourceChain::Header: Into, + BlockNumberOf: Into + Saturating, + TargetChain: Clone + Chain, +{ + let source_justifications = match source_client.clone().subscribe_justifications().await { + Ok(source_justifications) => source_justifications, + Err(error) => { + log::warn!( + target: "bridge", + "Failed to subscribe to {} justifications: {:?}", + SourceChain::NAME, + error, + ); + + return; + } + }; + + let sync_maintain = + SubstrateHeadersToSubstrateMaintain::new(pipeline.clone(), source_client.clone(), source_justifications); + + headers_relay::sync_loop::run( + HeadersSource::new(source_client), + SourceChain::AVERAGE_BLOCK_INTERVAL, + SubstrateHeadersTarget::new(target_client, pipeline), + TargetChain::AVERAGE_BLOCK_INTERVAL, + sync_maintain, + sync_params(), + metrics_params, + futures::future::pending(), + ); +} diff --git a/bridges/relays/substrate/src/headers_target.rs b/bridges/relays/substrate/src/headers_target.rs index a6502f407fa4..6f23706d171c 100644 --- a/bridges/relays/substrate/src/headers_target.rs +++ b/bridges/relays/substrate/src/headers_target.rs @@ -28,7 +28,7 @@ use headers_relay::{ use relay_substrate_client::{Chain, Client, Error as SubstrateError}; use relay_utils::HeaderId; use sp_core::Bytes; -use sp_runtime::{DeserializeOwned, Justification}; +use sp_runtime::Justification; use std::collections::HashSet; /// Headers sync pipeline for Substrate <-> Substrate relays. @@ -77,8 +77,6 @@ impl SubstrateHeadersTarget { impl TargetClient

for SubstrateHeadersTarget where C: Chain, - C::Header: DeserializeOwned, - C::Index: DeserializeOwned, P::Number: Decode, P::Hash: Decode + Encode, P: SubstrateHeadersSyncPipeline, diff --git a/bridges/relays/substrate/src/main.rs b/bridges/relays/substrate/src/main.rs index 76b2aa9189dd..6d36e7606159 100644 --- a/bridges/relays/substrate/src/main.rs +++ b/bridges/relays/substrate/src/main.rs @@ -34,8 +34,10 @@ pub type RialtoClient = relay_substrate_client::Client; mod cli; mod headers_maintain; +mod headers_pipeline; mod headers_target; mod millau_headers_to_rialto; +mod rialto_headers_to_millau; fn main() { initialize_relay(); @@ -71,6 +73,29 @@ async fn run_command(command: cli::Command) -> Result<(), String> { .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await; } + cli::Command::RialtoHeadersToMillau { + rialto, + millau, + millau_sign, + prometheus_params, + } => { + let rialto_client = RialtoClient::new(ConnectionParams { + host: rialto.rialto_host, + port: rialto.rialto_port, + }) + .await?; + let millau_client = MillauClient::new(ConnectionParams { + host: millau.millau_host, + port: millau.millau_port, + }) + .await?; + let millau_sign = MillauSigningParams::from_suri( + &millau_sign.millau_signer, + millau_sign.millau_signer_password.as_deref(), + ) + .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; + rialto_headers_to_millau::run(rialto_client, millau_client, millau_sign, prometheus_params.into()).await; + } cli::Command::SubmitMillauToRialtoMessage { millau, millau_sign, diff --git a/bridges/relays/substrate/src/millau_headers_to_rialto.rs b/bridges/relays/substrate/src/millau_headers_to_rialto.rs index 7bf504bcfe96..a07138e01936 100644 --- a/bridges/relays/substrate/src/millau_headers_to_rialto.rs +++ b/bridges/relays/substrate/src/millau_headers_to_rialto.rs @@ -17,9 +17,8 @@ //! Millau-to-Rialto headers sync entrypoint. use crate::{ - headers_maintain::SubstrateHeadersToSubstrateMaintain, - headers_target::{SubstrateHeadersSyncPipeline, SubstrateHeadersTarget}, - MillauClient, RialtoClient, + headers_pipeline::SubstrateHeadersToSubstrate, headers_target::SubstrateHeadersSyncPipeline, MillauClient, + RialtoClient, }; use async_trait::async_trait; @@ -27,41 +26,18 @@ use bp_millau::{ BEST_MILLAU_BLOCKS_METHOD, FINALIZED_MILLAU_BLOCK_METHOD, INCOMPLETE_MILLAU_HEADERS_METHOD, IS_KNOWN_MILLAU_BLOCK_METHOD, }; -use codec::Encode; -use headers_relay::{ - sync::{HeadersSyncParams, TargetTransactionMode}, - sync_types::{HeadersSyncPipeline, QueuedHeader}, -}; +use headers_relay::sync_types::QueuedHeader; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SyncHeader as MillauSyncHeader}; use relay_rialto_client::{BridgeMillauCall, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{ - headers_source::HeadersSource, BlockNumberOf, Error as SubstrateError, HashOf, TransactionSignScheme, -}; +use relay_substrate_client::{Error as SubstrateError, TransactionSignScheme}; use sp_core::Pair; use sp_runtime::Justification; -use std::time::Duration; - -/// Millau-to-Rialto headers pipeline. -#[derive(Debug, Clone)] -pub struct MillauHeadersToRialto { - client: RialtoClient, - sign: RialtoSigningParams, -} - -impl HeadersSyncPipeline for MillauHeadersToRialto { - const SOURCE_NAME: &'static str = "Millau"; - const TARGET_NAME: &'static str = "Rialto"; - - type Hash = HashOf; - type Number = BlockNumberOf; - type Header = MillauSyncHeader; - type Extra = (); - type Completion = Justification; - fn estimate_size(source: &QueuedHeader) -> usize { - source.header().encode().len() - } -} +/// Millau-to-Rialto headers sync pipeline. +pub(crate) type MillauHeadersToRialto = + SubstrateHeadersToSubstrate; +/// Millau header in-the-queue. +type QueuedMillauHeader = QueuedHeader; #[async_trait] impl SubstrateHeadersSyncPipeline for MillauHeadersToRialto { @@ -76,10 +52,10 @@ impl SubstrateHeadersSyncPipeline for MillauHeadersToRialto { &self, header: QueuedMillauHeader, ) -> Result { - let account_id = self.sign.signer.public().as_array_ref().clone().into(); - let nonce = self.client.next_account_index(account_id).await?; + let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.target_client.next_account_index(account_id).await?; let call = BridgeMillauCall::import_signed_header(header.header().clone().into()).into(); - let transaction = Rialto::sign_transaction(&self.client, &self.sign.signer, nonce, call); + let transaction = Rialto::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); Ok(transaction) } @@ -88,35 +64,14 @@ impl SubstrateHeadersSyncPipeline for MillauHeadersToRialto { id: MillauHeaderId, completion: Justification, ) -> Result { - let account_id = self.sign.signer.public().as_array_ref().clone().into(); - let nonce = self.client.next_account_index(account_id).await?; + let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.target_client.next_account_index(account_id).await?; let call = BridgeMillauCall::finalize_header(id.1, completion).into(); - let transaction = Rialto::sign_transaction(&self.client, &self.sign.signer, nonce, call); + let transaction = Rialto::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); Ok(transaction) } } -/// Millau header in-the-queue. -type QueuedMillauHeader = QueuedHeader; - -/// Millau node as headers source. -type MillauSourceClient = HeadersSource; - -/// Rialto node as headers target. -type RialtoTargetClient = SubstrateHeadersTarget; - -/// Return sync parameters for Millau-to-Rialto headers sync. -pub fn sync_params() -> HeadersSyncParams { - HeadersSyncParams { - max_future_headers_to_download: 32, - max_headers_in_submitted_status: 8, - max_headers_in_single_submit: 1, - max_headers_size_in_single_submit: 1024 * 1024, - prune_depth: 256, - target_tx_mode: TargetTransactionMode::Signed, - } -} - /// Run Millau-to-Rialto headers sync. pub async fn run( millau_client: MillauClient, @@ -124,37 +79,11 @@ pub async fn run( rialto_sign: RialtoSigningParams, metrics_params: Option, ) { - let millau_tick = Duration::from_secs(5); - let rialto_tick = Duration::from_secs(5); - - let millau_justifications = match millau_client.clone().subscribe_justifications().await { - Ok(millau_justifications) => millau_justifications, - Err(error) => { - log::warn!( - target: "bridge", - "Failed to subscribe to Millau justifications: {:?}", - error, - ); - - return; - } - }; - - let pipeline = MillauHeadersToRialto { - client: rialto_client.clone(), - sign: rialto_sign, - }; - let sync_maintain = - SubstrateHeadersToSubstrateMaintain::new(pipeline.clone(), rialto_client.clone(), millau_justifications); - - headers_relay::sync_loop::run( - MillauSourceClient::new(millau_client), - millau_tick, - RialtoTargetClient::new(rialto_client, pipeline), - rialto_tick, - sync_maintain, - sync_params(), + crate::headers_pipeline::run( + MillauHeadersToRialto::new(rialto_client.clone(), rialto_sign), + millau_client, + rialto_client, metrics_params, - futures::future::pending(), - ); + ) + .await; } diff --git a/bridges/relays/substrate/src/rialto_headers_to_millau.rs b/bridges/relays/substrate/src/rialto_headers_to_millau.rs new file mode 100644 index 000000000000..f458e291244d --- /dev/null +++ b/bridges/relays/substrate/src/rialto_headers_to_millau.rs @@ -0,0 +1,88 @@ +// 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 . + +//! Rialto-to-Millau headers sync entrypoint. + +use crate::{ + headers_pipeline::SubstrateHeadersToSubstrate, headers_target::SubstrateHeadersSyncPipeline, MillauClient, + RialtoClient, +}; + +use async_trait::async_trait; +use bp_rialto::{ + BEST_RIALTO_BLOCKS_METHOD, FINALIZED_RIALTO_BLOCK_METHOD, INCOMPLETE_RIALTO_HEADERS_METHOD, + IS_KNOWN_RIALTO_BLOCK_METHOD, +}; +use headers_relay::sync_types::QueuedHeader; +use relay_millau_client::{BridgeRialtoCall, Millau, SigningParams as MillauSigningParams}; +use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SyncHeader as RialtoSyncHeader}; +use relay_substrate_client::{Error as SubstrateError, TransactionSignScheme}; +use sp_core::Pair; +use sp_runtime::Justification; + +/// Rialto-to-Millau headers sync pipeline. +type RialtoHeadersToMillau = SubstrateHeadersToSubstrate; +/// Rialto header in-the-queue. +type QueuedRialtoHeader = QueuedHeader; + +#[async_trait] +impl SubstrateHeadersSyncPipeline for RialtoHeadersToMillau { + const BEST_BLOCK_METHOD: &'static str = BEST_RIALTO_BLOCKS_METHOD; + const FINALIZED_BLOCK_METHOD: &'static str = FINALIZED_RIALTO_BLOCK_METHOD; + const IS_KNOWN_BLOCK_METHOD: &'static str = IS_KNOWN_RIALTO_BLOCK_METHOD; + const INCOMPLETE_HEADERS_METHOD: &'static str = INCOMPLETE_RIALTO_HEADERS_METHOD; + + type SignedTransaction = ::SignedTransaction; + + async fn make_submit_header_transaction( + &self, + header: QueuedRialtoHeader, + ) -> Result { + let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.target_client.next_account_index(account_id).await?; + let call = BridgeRialtoCall::import_signed_header(header.header().clone().into()).into(); + let transaction = Millau::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); + Ok(transaction) + } + + async fn make_complete_header_transaction( + &self, + id: RialtoHeaderId, + completion: Justification, + ) -> Result { + let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.target_client.next_account_index(account_id).await?; + let call = BridgeRialtoCall::finalize_header(id.1, completion).into(); + let transaction = Millau::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); + Ok(transaction) + } +} + +/// Run Rialto-to-Millau headers sync. +pub async fn run( + rialto_client: RialtoClient, + millau_client: MillauClient, + millau_sign: MillauSigningParams, + metrics_params: Option, +) { + crate::headers_pipeline::run( + RialtoHeadersToMillau::new(millau_client.clone(), millau_sign), + rialto_client, + millau_client, + metrics_params, + ) + .await; +}