From 544698734c943965077db4d8c220e65dde739902 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 13 Nov 2020 16:09:29 +0300 Subject: [PATCH 1/4] replace generic message lane APIs with chain-specific --- Cargo.lock | 1 - bin/millau/runtime/src/lib.rs | 6 ++-- bin/rialto/runtime/src/lib.rs | 6 ++-- primitives/message-lane/Cargo.toml | 2 -- primitives/message-lane/src/lib.rs | 28 ------------------- primitives/millau/src/lib.rs | 45 +++++++++++++++++++++++++++++- primitives/rialto/src/lib.rs | 45 +++++++++++++++++++++++++++++- 7 files changed, 92 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 47d7c47c7b..813987bbf5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -726,7 +726,6 @@ version = "0.1.0" dependencies = [ "frame-support", "parity-scale-codec", - "sp-api", "sp-std", ] diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 7435788acc..639ab027c3 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -540,8 +540,7 @@ impl_runtime_apis! { } } - // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) - impl bp_message_lane::OutboundLaneApi for Runtime { + impl bp_rialto::ToRialtoOutboundLaneApi for Runtime { fn messages_dispatch_weight( lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, @@ -566,8 +565,7 @@ impl_runtime_apis! { } } - // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) - impl bp_message_lane::InboundLaneApi for Runtime { + impl bp_rialto::FromRialtoInboundLaneApi for Runtime { fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { BridgeRialtoMessageLane::inbound_latest_received_nonce(lane) } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 4a3855f69e..f7e96ab6a8 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -704,8 +704,7 @@ impl_runtime_apis! { } } - // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) - impl bp_message_lane::OutboundLaneApi for Runtime { + impl bp_millau::ToMillauOutboundLaneApi for Runtime { fn messages_dispatch_weight( lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, @@ -730,8 +729,7 @@ impl_runtime_apis! { } } - // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) - impl bp_message_lane::InboundLaneApi for Runtime { + impl bp_millau::FromMillauInboundLaneApi for Runtime { fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { BridgeMillauMessageLane::inbound_latest_received_nonce(lane) } diff --git a/primitives/message-lane/Cargo.toml b/primitives/message-lane/Cargo.toml index d705c119fe..ecd20d611e 100644 --- a/primitives/message-lane/Cargo.toml +++ b/primitives/message-lane/Cargo.toml @@ -12,7 +12,6 @@ codec = { package = "parity-scale-codec", version = "1.3.1", default-features = # Substrate Dependencies frame-support = { version = "2.0", default-features = false } -sp-api = { version = "2.0", default-features = false } sp-std = { version = "2.0", default-features = false } [features] @@ -20,6 +19,5 @@ default = ["std"] std = [ "codec/std", "frame-support/std", - "sp-api/std", "sp-std/std" ] diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index 760333a8cf..848acb31b2 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -24,7 +24,6 @@ use codec::{Decode, Encode}; use frame_support::RuntimeDebug; -use sp_api::decl_runtime_apis; use sp_std::{collections::vec_deque::VecDeque, prelude::*}; pub mod source_chain; @@ -125,30 +124,3 @@ impl Default for OutboundLaneData { } } } - -decl_runtime_apis! { - /// Outbound message lane API. - pub trait OutboundLaneApi { - /// Returns dispatch weight of all messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn messages_dispatch_weight( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec<(MessageNonce, Weight)>; - /// Returns nonce of the latest message, received by bridged chain. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, generated by given lane. - fn latest_generated_nonce(lane: LaneId) -> MessageNonce; - } - - /// Inbound message lane API. - pub trait InboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of latest message that has been confirmed to the bridged chain. - fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; - } -} diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index d8c6f5c300..41d7e92739 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_message_lane::MessageNonce; +use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::Chain; use frame_support::{weights::Weight, RuntimeDebug}; use sp_core::Hasher as HasherT; @@ -73,6 +73,18 @@ pub const IS_KNOWN_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_is_known_block"; /// Name of the `MillauHeaderApi::incomplete_headers` runtime method. pub const INCOMPLETE_MILLAU_HEADERS_METHOD: &str = "MillauHeaderApi_incomplete_headers"; +/// Name of the `ToMillauOutboundLaneApi::messages_dispatch_weight` runtime method. +pub const TO_MILLAU_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToMillauOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToMillauOutboundLaneApi::latest_received_nonce` runtime method. +pub const TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = "ToMillauOutboundLaneApi_latest_received_nonce"; +/// Name of the `ToMillauOutboundLaneApi::latest_generated_nonce` runtime method. +pub const TO_MILLAU_LATEST_GENERATED_NONCE_METHOD: &str = "ToMillauOutboundLaneApi_latest_generated_nonce"; + +/// Name of the `FromMillauInboundLaneApi::latest_received_nonce` runtime method. +pub const FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = "FromMillauInboundLaneApi_latest_received_nonce"; +/// Name of the `FromMillauInboundLaneApi::latest_onfirmed_nonce` runtime method. +pub const FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromMillauInboundLaneApi_latest_confirmed_nonce"; + /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = MultiSignature; @@ -111,4 +123,35 @@ sp_api::decl_runtime_apis! { /// Returns true if the header is considered finalized by the runtime. fn is_finalized_block(hash: Hash) -> bool; } + + /// Outbound message lane API for messages that are sent to Millau chain. + /// + /// This API is implemented by runtimes that are sending messages to Millau chain, not the + /// Millau runtime itself. + pub trait ToMillauOutboundLaneApi { + /// Returns dispatch weight of all messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn messages_dispatch_weight( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec<(MessageNonce, Weight)>; + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API for messages sent by Millau chain. + /// + /// This API is implemented by runtimes that are receiving messages from Millau chain, not the + /// Millau runtime itself. + pub trait FromMillauInboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + } } diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 389bd869f1..8b43961c73 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_message_lane::MessageNonce; +use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::Chain; use frame_support::{weights::Weight, RuntimeDebug}; use sp_core::Hasher as HasherT; @@ -73,6 +73,18 @@ 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"; +/// Name of the `ToRialtoOutboundLaneApi::messages_dispatch_weight` runtime method. +pub const TO_RIALTO_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToRialtoOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToRialtoOutboundLaneApi::latest_received_nonce` runtime method. +pub const TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_received_nonce"; +/// Name of the `ToRialtoOutboundLaneApi::latest_generated_nonce` runtime method. +pub const TO_RIALTO_LATEST_GENERATED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_generated_nonce"; + +/// Name of the `FromRialtoInboundLaneApi::latest_received_nonce` runtime method. +pub const FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_received_nonce"; +/// Name of the `FromRialtoInboundLaneApi::latest_onfirmed_nonce` runtime method. +pub const FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_confirmed_nonce"; + /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = MultiSignature; @@ -111,4 +123,35 @@ sp_api::decl_runtime_apis! { /// Returns true if the header is considered finalized by the runtime. fn is_finalized_block(hash: Hash) -> bool; } + + /// Outbound message lane API for messages that are sent to Rialto chain. + /// + /// This API is implemented by runtimes that are sending messages to Rialto chain, not the + /// Rialto runtime itself. + pub trait ToRialtoOutboundLaneApi { + /// Returns dispatch weight of all messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn messages_dispatch_weight( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec<(MessageNonce, Weight)>; + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API for messages sent by Rialto chain. + /// + /// This API is implemented by runtimes that are receiving messages from Rialto chain, not the + /// Rialto runtime itself. + pub trait FromRialtoInboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + } } From c96f527fc51e51d5c88163e403d495caa509a357 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 13 Nov 2020 16:15:15 +0300 Subject: [PATCH 2/4] moved SubstrateHeadersSyncPipeline to headers_pipeline.rs --- relays/substrate/src/headers_maintain.rs | 2 +- relays/substrate/src/headers_pipeline.rs | 36 +++++++++++++++++-- relays/substrate/src/headers_target.rs | 33 ++--------------- .../substrate/src/millau_headers_to_rialto.rs | 4 +-- .../substrate/src/rialto_headers_to_millau.rs | 4 +-- 5 files changed, 41 insertions(+), 38 deletions(-) diff --git a/relays/substrate/src/headers_maintain.rs b/relays/substrate/src/headers_maintain.rs index fc91494c7b..0dac3cafb4 100644 --- a/relays/substrate/src/headers_maintain.rs +++ b/relays/substrate/src/headers_maintain.rs @@ -29,7 +29,7 @@ //! best finalized header on the target chain, we submit this justification to the target //! node. -use crate::headers_target::SubstrateHeadersSyncPipeline; +use crate::headers_pipeline::SubstrateHeadersSyncPipeline; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; diff --git a/relays/substrate/src/headers_pipeline.rs b/relays/substrate/src/headers_pipeline.rs index b00417da39..506f05b0f4 100644 --- a/relays/substrate/src/headers_pipeline.rs +++ b/relays/substrate/src/headers_pipeline.rs @@ -18,19 +18,49 @@ use crate::{ headers_maintain::SubstrateHeadersToSubstrateMaintain, - headers_target::{SubstrateHeadersSyncPipeline, SubstrateHeadersTarget}, + headers_target::SubstrateHeadersTarget, }; +use async_trait::async_trait; use codec::Encode; use headers_relay::{ sync::{HeadersSyncParams, TargetTransactionMode}, - sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}, + sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SourceHeader}, }; use num_traits::Saturating; -use relay_substrate_client::{headers_source::HeadersSource, BlockNumberOf, Chain, Client, HashOf}; +use relay_substrate_client::{headers_source::HeadersSource, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf}; use sp_runtime::Justification; use std::marker::PhantomData; +/// Headers sync pipeline for Substrate <-> Substrate relays. +#[async_trait] +pub trait SubstrateHeadersSyncPipeline: HeadersSyncPipeline { + /// Name of the `best_block` runtime method. + const BEST_BLOCK_METHOD: &'static str; + /// Name of the `finalized_block` runtime method. + const FINALIZED_BLOCK_METHOD: &'static str; + /// Name of the `is_known_block` runtime method. + const IS_KNOWN_BLOCK_METHOD: &'static str; + /// Name of the `incomplete_headers` runtime method. + const INCOMPLETE_HEADERS_METHOD: &'static str; + + /// Signed transaction type. + type SignedTransaction: Send + Sync + Encode; + + /// Make submit header transaction. + async fn make_submit_header_transaction( + &self, + header: QueuedHeader, + ) -> Result; + + /// Make completion transaction for the header. + async fn make_complete_header_transaction( + &self, + id: HeaderIdOf, + completion: Justification, + ) -> Result; +} + /// Substrate-to-Substrate headers pipeline. #[derive(Debug, Clone)] pub struct SubstrateHeadersToSubstrate { diff --git a/relays/substrate/src/headers_target.rs b/relays/substrate/src/headers_target.rs index 6fb4a1500a..314bbc352f 100644 --- a/relays/substrate/src/headers_target.rs +++ b/relays/substrate/src/headers_target.rs @@ -18,12 +18,14 @@ //! runtime that implements `HeaderApi` to allow bridging with //! chain. +use crate::headers_pipeline::SubstrateHeadersSyncPipeline; + use async_trait::async_trait; use codec::{Decode, Encode}; use futures::TryFutureExt; use headers_relay::{ sync_loop::TargetClient, - sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SubmittedHeaders}, + sync_types::{HeaderIdOf, QueuedHeader, SubmittedHeaders}, }; use relay_substrate_client::{Chain, Client, Error as SubstrateError}; use relay_utils::HeaderId; @@ -31,35 +33,6 @@ use sp_core::Bytes; use sp_runtime::Justification; use std::collections::HashSet; -/// Headers sync pipeline for Substrate <-> Substrate relays. -#[async_trait] -pub trait SubstrateHeadersSyncPipeline: HeadersSyncPipeline { - /// Name of the `best_block` runtime method. - const BEST_BLOCK_METHOD: &'static str; - /// Name of the `finalized_block` runtime method. - const FINALIZED_BLOCK_METHOD: &'static str; - /// Name of the `is_known_block` runtime method. - const IS_KNOWN_BLOCK_METHOD: &'static str; - /// Name of the `incomplete_headers` runtime method. - const INCOMPLETE_HEADERS_METHOD: &'static str; - - /// Signed transaction type. - type SignedTransaction: Send + Sync + Encode; - - /// Make submit header transaction. - async fn make_submit_header_transaction( - &self, - header: QueuedHeader, - ) -> Result; - - /// Make completion transaction for the header. - async fn make_complete_header_transaction( - &self, - id: HeaderIdOf, - completion: Justification, - ) -> Result; -} - /// Substrate client as Substrate headers target. pub struct SubstrateHeadersTarget { client: Client, diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/millau_headers_to_rialto.rs index a07138e019..714a6c22f5 100644 --- a/relays/substrate/src/millau_headers_to_rialto.rs +++ b/relays/substrate/src/millau_headers_to_rialto.rs @@ -17,8 +17,8 @@ //! Millau-to-Rialto headers sync entrypoint. use crate::{ - headers_pipeline::SubstrateHeadersToSubstrate, headers_target::SubstrateHeadersSyncPipeline, MillauClient, - RialtoClient, + headers_pipeline::{SubstrateHeadersSyncPipeline, SubstrateHeadersToSubstrate}, + MillauClient, RialtoClient, }; use async_trait::async_trait; diff --git a/relays/substrate/src/rialto_headers_to_millau.rs b/relays/substrate/src/rialto_headers_to_millau.rs index f458e29124..92a141654c 100644 --- a/relays/substrate/src/rialto_headers_to_millau.rs +++ b/relays/substrate/src/rialto_headers_to_millau.rs @@ -17,8 +17,8 @@ //! Rialto-to-Millau headers sync entrypoint. use crate::{ - headers_pipeline::SubstrateHeadersToSubstrate, headers_target::SubstrateHeadersSyncPipeline, MillauClient, - RialtoClient, + headers_pipeline::{SubstrateHeadersSyncPipeline, SubstrateHeadersToSubstrate}, + MillauClient, RialtoClient, }; use async_trait::async_trait; From c099b832d9efde68ec410d7e1dee1b8533ec30f1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 13 Nov 2020 17:18:35 +0300 Subject: [PATCH 3/4] substrate-specific message lane trait --- primitives/rialto/src/lib.rs | 4 +- relays/substrate/src/headers_pipeline.rs | 9 +- relays/substrate/src/main.rs | 1 + relays/substrate/src/messages_lane.rs | 63 ++++++++++ relays/substrate/src/messages_source.rs | 78 +++++------- relays/substrate/src/messages_target.rs | 68 ++++------- .../src/millau_messages_to_rialto.rs | 112 ++++++++---------- 7 files changed, 179 insertions(+), 156 deletions(-) create mode 100644 relays/substrate/src/messages_lane.rs diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 8b43961c73..a9a1342a68 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -75,10 +75,10 @@ pub const INCOMPLETE_RIALTO_HEADERS_METHOD: &str = "RialtoHeaderApi_incomplete_h /// Name of the `ToRialtoOutboundLaneApi::messages_dispatch_weight` runtime method. pub const TO_RIALTO_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToRialtoOutboundLaneApi_messages_dispatch_weight"; -/// Name of the `ToRialtoOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_received_nonce"; /// Name of the `ToRialtoOutboundLaneApi::latest_generated_nonce` runtime method. pub const TO_RIALTO_LATEST_GENERATED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_generated_nonce"; +/// Name of the `ToRialtoOutboundLaneApi::latest_received_nonce` runtime method. +pub const TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_received_nonce"; /// Name of the `FromRialtoInboundLaneApi::latest_received_nonce` runtime method. pub const FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_received_nonce"; diff --git a/relays/substrate/src/headers_pipeline.rs b/relays/substrate/src/headers_pipeline.rs index 506f05b0f4..b5900b5015 100644 --- a/relays/substrate/src/headers_pipeline.rs +++ b/relays/substrate/src/headers_pipeline.rs @@ -16,10 +16,7 @@ //! Substrate-to-Substrate headers sync entrypoint. -use crate::{ - headers_maintain::SubstrateHeadersToSubstrateMaintain, - headers_target::SubstrateHeadersTarget, -}; +use crate::{headers_maintain::SubstrateHeadersToSubstrateMaintain, headers_target::SubstrateHeadersTarget}; use async_trait::async_trait; use codec::Encode; @@ -28,7 +25,9 @@ use headers_relay::{ sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SourceHeader}, }; use num_traits::Saturating; -use relay_substrate_client::{headers_source::HeadersSource, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf}; +use relay_substrate_client::{ + headers_source::HeadersSource, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, +}; use sp_runtime::Justification; use std::marker::PhantomData; diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 727e4eb243..5202be898b 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -37,6 +37,7 @@ mod headers_initialize; mod headers_maintain; mod headers_pipeline; mod headers_target; +mod messages_lane; mod messages_source; mod messages_target; mod millau_headers_to_rialto; diff --git a/relays/substrate/src/messages_lane.rs b/relays/substrate/src/messages_lane.rs new file mode 100644 index 0000000000..35fd294965 --- /dev/null +++ b/relays/substrate/src/messages_lane.rs @@ -0,0 +1,63 @@ +// 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 . + +use async_trait::async_trait; +use bp_message_lane::MessageNonce; +use codec::Encode; +use messages_relay::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; +use relay_substrate_client::Error as SubstrateError; +use std::ops::RangeInclusive; + +/// Headers sync pipeline for Substrate <-> Substrate relays. +#[async_trait] +pub trait SubstrateMessageLane: MessageLane { + /// Name of the runtime method that returns dispatch weight of outbound messages at the source chain. + const OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD: &'static str; + /// Name of the runtime method that returns latest generated nonce at the source chain. + const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str; + /// Name of the runtime method that returns latest received (confirmed) nonce at the the source chain. + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; + + /// Name of the runtime method that returns latest received nonce at the source chain. + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; + /// Name of the runtime method that returns latest confirmed (reward-paid) nonce at the source chain. + const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str; + + /// Name of the runtime method that returns id of best finalized source header at target chain. + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str; + /// Name of the runtime method that returns id of best finalized target header at source chain. + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str; + + /// Signed transaction type of the source chain. + type SourceSignedTransaction: Send + Sync + Encode; + /// Signed transaction type of the target chain. + type TargetSignedTransaction: Send + Sync + Encode; + + /// Make messages delivery transaction. + async fn make_messages_delivery_transaction( + &self, + generated_at_header: SourceHeaderIdOf, + nonces: RangeInclusive, + proof: Self::MessagesProof, + ) -> Result; + + /// Make messages receiving proof transaction. + async fn make_messages_receiving_proof_transaction( + &self, + generated_at_header: TargetHeaderIdOf, + proof: Self::MessagesReceivingProof, + ) -> Result; +} diff --git a/relays/substrate/src/messages_source.rs b/relays/substrate/src/messages_source.rs index c648289fee..ff2a6ae968 100644 --- a/relays/substrate/src/messages_source.rs +++ b/relays/substrate/src/messages_source.rs @@ -18,13 +18,15 @@ //! runtime that implements `HeaderApi` to allow bridging with //! chain. +use crate::messages_lane::SubstrateMessageLane; + use async_trait::async_trait; use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::InstanceId; use codec::{Decode, Encode}; use frame_support::weights::Weight; use messages_relay::{ - message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, + message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{ClientState, MessageProofParameters, MessageWeightsMap, SourceClient, SourceClientState}, }; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf}; @@ -32,7 +34,7 @@ use relay_utils::HeaderId; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; use sp_trie::StorageProof; -use std::{marker::PhantomData, ops::RangeInclusive}; +use std::ops::RangeInclusive; /// Intermediate message proof returned by the source Substrate node. Includes everything /// required to submit to the target node: cumulative dispatch weight of bundled messages and @@ -40,68 +42,50 @@ use std::{marker::PhantomData, ops::RangeInclusive}; pub type SubstrateMessagesProof = (Weight, (HashOf, StorageProof, LaneId, MessageNonce, MessageNonce)); /// Substrate client as Substrate messages source. -pub struct SubstrateMessagesSource { +pub struct SubstrateMessagesSource { client: Client, - tx_maker: M, - lane: LaneId, + lane: P, + lane_id: LaneId, instance: InstanceId, - _marker: PhantomData

, } -/// Substrate transactions maker. -#[async_trait] -pub trait SubstrateTransactionMaker: Clone + Send + Sync { - /// Signed transaction type. - type SignedTransaction: Send + Sync + Encode; - - /// Make messages receiving proof transaction. - async fn make_messages_receiving_proof_transaction( - &self, - generated_at_block: TargetHeaderIdOf

, - proof: P::MessagesReceivingProof, - ) -> Result; -} - -impl SubstrateMessagesSource { +impl SubstrateMessagesSource { /// Create new Substrate headers source. - pub fn new(client: Client, tx_maker: M, lane: LaneId, instance: InstanceId) -> Self { + pub fn new(client: Client, lane: P, lane_id: LaneId, instance: InstanceId) -> Self { SubstrateMessagesSource { client, - tx_maker, lane, + lane_id, instance, - _marker: Default::default(), } } } -impl Clone for SubstrateMessagesSource { +impl Clone for SubstrateMessagesSource { fn clone(&self) -> Self { Self { client: self.client.clone(), - tx_maker: self.tx_maker.clone(), - lane: self.lane, + lane: self.lane.clone(), + lane_id: self.lane_id, instance: self.instance, - _marker: Default::default(), } } } #[async_trait] -impl SourceClient

for SubstrateMessagesSource +impl SourceClient

for SubstrateMessagesSource where C: Chain, C::Header: DeserializeOwned, C::Index: DeserializeOwned, ::Number: Into, - P: MessageLane< + P: SubstrateMessageLane< MessagesProof = SubstrateMessagesProof, SourceHeaderNumber = ::Number, SourceHeaderHash = ::Hash, >, P::TargetHeaderNumber: Decode, P::TargetHeaderHash: Decode, - M: SubstrateTransactionMaker, { type Error = SubstrateError; @@ -112,7 +96,11 @@ where } async fn state(&self) -> Result, Self::Error> { - read_client_state::<_, P::TargetHeaderHash, P::TargetHeaderNumber>(&self.client, P::TARGET_NAME).await + read_client_state::<_, P::TargetHeaderHash, P::TargetHeaderNumber>( + &self.client, + P::BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE, + ) + .await } async fn latest_generated_nonce( @@ -122,9 +110,8 @@ where let encoded_response = self .client .state_call( - // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 - "OutboundLaneApi_latest_generated_nonce".into(), - Bytes(self.lane.encode()), + P::OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD.into(), + Bytes(self.lane_id.encode()), Some(id.1), ) .await?; @@ -140,9 +127,8 @@ where let encoded_response = self .client .state_call( - // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 - "OutboundLaneApi_latest_received_nonce".into(), - Bytes(self.lane.encode()), + P::OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD.into(), + Bytes(self.lane_id.encode()), Some(id.1), ) .await?; @@ -159,9 +145,8 @@ where let encoded_response = self .client .state_call( - // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 - "OutboundLaneApi_messages_dispatch_weight".into(), - Bytes((self.lane, nonces.start(), nonces.end()).encode()), + P::OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD.into(), + Bytes((self.lane_id, nonces.start(), nonces.end()).encode()), Some(id.1), ) .await?; @@ -194,13 +179,13 @@ where .client .prove_messages( self.instance, - self.lane, + self.lane_id, nonces.clone(), proof_parameters.outbound_state_proof_required, id.1, ) .await?; - let proof = (id.1, proof, self.lane, *nonces.start(), *nonces.end()); + let proof = (id.1, proof, self.lane_id, *nonces.start(), *nonces.end()); Ok((id, nonces, (proof_parameters.dispatch_weight, proof))) } @@ -210,7 +195,7 @@ where proof: P::MessagesReceivingProof, ) -> Result<(), Self::Error> { let tx = self - .tx_maker + .lane .make_messages_receiving_proof_transaction(generated_at_block, proof) .await?; self.client.submit_extrinsic(Bytes(tx.encode())).await?; @@ -220,7 +205,7 @@ where pub async fn read_client_state( self_client: &Client, - bridged_chain_name: &str, + best_finalized_header_id_method_name: &str, ) -> Result, HeaderId>, SubstrateError> where SelfChain: Chain, @@ -235,10 +220,9 @@ where let self_best_finalized_id = HeaderId(*self_best_finalized_header.number(), self_best_finalized_header_hash); // now let's read id of best finalized peer header at our best finalized block - let best_finalized_peer_on_self_method = format!("{}HeaderApi_finalized_block", bridged_chain_name); let encoded_best_finalized_peer_on_self = self_client .state_call( - best_finalized_peer_on_self_method, + best_finalized_header_id_method_name.into(), Bytes(Vec::new()), Some(self_best_finalized_header_hash), ) diff --git a/relays/substrate/src/messages_target.rs b/relays/substrate/src/messages_target.rs index 2569b5e2c9..36a2366e49 100644 --- a/relays/substrate/src/messages_target.rs +++ b/relays/substrate/src/messages_target.rs @@ -18,6 +18,7 @@ //! runtime that implements `HeaderApi` to allow bridging with //! chain. +use crate::messages_lane::SubstrateMessageLane; use crate::messages_source::read_client_state; use async_trait::async_trait; @@ -25,79 +26,60 @@ use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::InstanceId; use codec::{Decode, Encode}; use messages_relay::{ - message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, + message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{TargetClient, TargetClientState}, }; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf}; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; use sp_trie::StorageProof; -use std::{marker::PhantomData, ops::RangeInclusive}; +use std::ops::RangeInclusive; /// Substrate client as Substrate messages target. -pub struct SubstrateMessagesTarget { +pub struct SubstrateMessagesTarget { client: Client, - tx_maker: M, - lane: LaneId, + lane: P, + lane_id: LaneId, instance: InstanceId, - _marker: PhantomData

, } -/// Substrate transactions maker. -#[async_trait] -pub trait SubstrateTransactionMaker: Clone + Send + Sync { - /// Signed transaction type. - type SignedTransaction: Send + Sync + Encode; - - /// Make messages delivery transaction. - async fn make_messages_delivery_transaction( - &self, - generated_at_header: SourceHeaderIdOf

, - nonces: RangeInclusive, - proof: P::MessagesProof, - ) -> Result; -} - -impl SubstrateMessagesTarget { +impl SubstrateMessagesTarget { /// Create new Substrate headers target. - pub fn new(client: Client, tx_maker: M, lane: LaneId, instance: InstanceId) -> Self { + pub fn new(client: Client, lane: P, lane_id: LaneId, instance: InstanceId) -> Self { SubstrateMessagesTarget { client, - tx_maker, lane, + lane_id, instance, - _marker: Default::default(), } } } -impl Clone for SubstrateMessagesTarget { +impl Clone for SubstrateMessagesTarget { fn clone(&self) -> Self { Self { client: self.client.clone(), - tx_maker: self.tx_maker.clone(), - lane: self.lane, + lane: self.lane.clone(), + lane_id: self.lane_id, instance: self.instance, - _marker: Default::default(), } } } #[async_trait] -impl TargetClient

for SubstrateMessagesTarget +impl TargetClient

for SubstrateMessagesTarget where C: Chain, C::Header: DeserializeOwned, C::Index: DeserializeOwned, ::Number: Into, - P: MessageLane< + P: SubstrateMessageLane< MessagesReceivingProof = (HashOf, StorageProof, LaneId), TargetHeaderNumber = ::Number, TargetHeaderHash = ::Hash, >, P::SourceHeaderNumber: Decode, P::SourceHeaderHash: Decode, - M: SubstrateTransactionMaker, { type Error = SubstrateError; @@ -108,7 +90,11 @@ where } async fn state(&self) -> Result, Self::Error> { - read_client_state::<_, P::SourceHeaderHash, P::SourceHeaderNumber>(&self.client, P::SOURCE_NAME).await + read_client_state::<_, P::SourceHeaderHash, P::SourceHeaderNumber>( + &self.client, + P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET, + ) + .await } async fn latest_received_nonce( @@ -118,9 +104,8 @@ where let encoded_response = self .client .state_call( - // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 - "InboundLaneApi_latest_received_nonce".into(), - Bytes(self.lane.encode()), + P::INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD.into(), + Bytes(self.lane_id.encode()), Some(id.1), ) .await?; @@ -136,9 +121,8 @@ where let encoded_response = self .client .state_call( - // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 - "OutboundLaneApi_latest_received_nonce".into(), - Bytes(self.lane.encode()), + P::INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD.into(), + Bytes(self.lane_id.encode()), Some(id.1), ) .await?; @@ -153,9 +137,9 @@ where ) -> Result<(TargetHeaderIdOf

, P::MessagesReceivingProof), Self::Error> { let proof = self .client - .prove_messages_delivery(self.instance, self.lane, id.1) + .prove_messages_delivery(self.instance, self.lane_id, id.1) .await?; - let proof = (id.1, proof, self.lane); + let proof = (id.1, proof, self.lane_id); Ok((id, proof)) } @@ -166,7 +150,7 @@ where proof: P::MessagesProof, ) -> Result, Self::Error> { let tx = self - .tx_maker + .lane .make_messages_delivery_transaction(generated_at_header, nonces.clone(), proof) .await?; self.client.submit_extrinsic(Bytes(tx.encode())).await?; diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index 81017f6745..17d7b10189 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -16,8 +16,9 @@ //! Millau-to-Rialto messages sync entrypoint. -use crate::messages_source::{SubstrateMessagesSource, SubstrateTransactionMaker as SubstrateSourceTransactionMaker}; -use crate::messages_target::{SubstrateMessagesTarget, SubstrateTransactionMaker as SubstrateTargetTransactionMaker}; +use crate::messages_lane::SubstrateMessageLane; +use crate::messages_source::SubstrateMessagesSource; +use crate::messages_target::SubstrateMessagesTarget; use crate::{MillauClient, RialtoClient}; use async_trait::async_trait; @@ -45,8 +46,14 @@ type FromMillauMessagesProof = ( type FromRialtoMessagesReceivingProof = (HashOf, StorageProof, LaneId); /// Millau-to-Rialto messages pipeline. -#[derive(Debug, Clone, Copy)] -struct MillauMessagesToRialto; +#[derive(Debug, Clone)] +struct MillauMessagesToRialto { + millau_client: MillauClient, + millau_sign: MillauSigningParams, + rialto_client: RialtoClient, + rialto_sign: RialtoSigningParams, + relayer_id: bp_millau::AccountId, +} impl MessageLane for MillauMessagesToRialto { const SOURCE_NAME: &'static str = "Millau"; @@ -62,72 +69,66 @@ impl MessageLane for MillauMessagesToRialto { type TargetHeaderHash = HashOf; } -/// Millau node as messages source. -type MillauSourceClient = SubstrateMessagesSource; +#[async_trait] +impl SubstrateMessageLane for MillauMessagesToRialto { + const OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD: &'static str = + bp_rialto::TO_RIALTO_MESSAGES_DISPATCH_WEIGHT_METHOD; + const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD; -/// Millau transaction maker. -#[derive(Clone)] -struct MillauTransactionMaker { - client: MillauClient, - sign: MillauSigningParams, -} + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD; -#[async_trait] -impl SubstrateSourceTransactionMaker for MillauTransactionMaker { - type SignedTransaction = ::SignedTransaction; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::FINALIZED_MILLAU_BLOCK_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rialto::FINALIZED_RIALTO_BLOCK_METHOD; + + type SourceSignedTransaction = ::SignedTransaction; + type TargetSignedTransaction = ::SignedTransaction; async fn make_messages_receiving_proof_transaction( &self, _generated_at_block: RialtoHeaderId, proof: FromRialtoMessagesReceivingProof, - ) -> Result { - let account_id = self.sign.signer.public().as_array_ref().clone().into(); - let nonce = self.client.next_account_index(account_id).await?; + ) -> Result { + let account_id = self.millau_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.millau_client.next_account_index(account_id).await?; let call = millau_runtime::MessageLaneCall::receive_messages_delivery_proof(proof).into(); - let transaction = Millau::sign_transaction(&self.client, &self.sign.signer, nonce, call); + let transaction = Millau::sign_transaction(&self.millau_client, &self.millau_sign.signer, nonce, call); Ok(transaction) } -} - -/// Rialto node as messages target. -type RialtoTargetClient = SubstrateMessagesTarget; - -/// Rialto transaction maker. -#[derive(Clone)] -struct RialtoTransactionMaker { - client: RialtoClient, - relayer_id: bp_millau::AccountId, - sign: RialtoSigningParams, -} - -#[async_trait] -impl SubstrateTargetTransactionMaker for RialtoTransactionMaker { - type SignedTransaction = ::SignedTransaction; async fn make_messages_delivery_transaction( &self, _generated_at_header: MillauHeaderId, _nonces: RangeInclusive, proof: FromMillauMessagesProof, - ) -> Result { + ) -> Result { let (dispatch_weight, proof) = proof; - 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.rialto_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.rialto_client.next_account_index(account_id).await?; let call = rialto_runtime::MessageLaneCall::receive_messages_proof(self.relayer_id.clone(), proof, dispatch_weight) .into(); - let transaction = Rialto::sign_transaction(&self.client, &self.sign.signer, nonce, call); + let transaction = Rialto::sign_transaction(&self.rialto_client, &self.rialto_sign.signer, nonce, call); Ok(transaction) } } +/// Millau node as messages source. +type MillauSourceClient = SubstrateMessagesSource; + +/// Rialto node as messages target. +type RialtoTargetClient = SubstrateMessagesTarget; + /// Run Millau-to-Rialto messages sync. pub fn run( millau_client: MillauClient, millau_sign: MillauSigningParams, rialto_client: RialtoClient, rialto_sign: RialtoSigningParams, - lane: LaneId, + lane_id: LaneId, metrics_params: Option, ) { let millau_tick = Duration::from_secs(5); @@ -136,9 +137,17 @@ pub fn run( let stall_timeout = Duration::from_secs(5 * 60); let relayer_id = millau_sign.signer.public().as_array_ref().clone().into(); + let lane = MillauMessagesToRialto { + millau_client: millau_client.clone(), + millau_sign, + rialto_client: rialto_client.clone(), + rialto_sign, + relayer_id, + }; + messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { - lane, + lane: lane_id, source_tick: millau_tick, target_tick: rialto_tick, reconnect_delay, @@ -150,25 +159,8 @@ pub fn run( max_messages_weight_in_single_batch: bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT, }, }, - MillauSourceClient::new( - millau_client.clone(), - MillauTransactionMaker { - client: millau_client, - sign: millau_sign, - }, - lane, - RIALTO_BRIDGE_INSTANCE, - ), - RialtoTargetClient::new( - rialto_client.clone(), - RialtoTransactionMaker { - client: rialto_client, - relayer_id, - sign: rialto_sign, - }, - lane, - MILLAU_BRIDGE_INSTANCE, - ), + MillauSourceClient::new(millau_client, lane.clone(), lane_id, RIALTO_BRIDGE_INSTANCE), + RialtoTargetClient::new(rialto_client, lane, lane_id, MILLAU_BRIDGE_INSTANCE), metrics_params, futures::future::pending(), ); From 8614d6439b358dde83e23a656f01c97e003c1731 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 18 Nov 2020 11:46:28 +0300 Subject: [PATCH 4/4] Update relays/substrate/src/messages_lane.rs Co-authored-by: Hernando Castano --- relays/substrate/src/messages_lane.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/substrate/src/messages_lane.rs b/relays/substrate/src/messages_lane.rs index 35fd294965..3d1e12323c 100644 --- a/relays/substrate/src/messages_lane.rs +++ b/relays/substrate/src/messages_lane.rs @@ -21,7 +21,7 @@ use messages_relay::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderId use relay_substrate_client::Error as SubstrateError; use std::ops::RangeInclusive; -/// Headers sync pipeline for Substrate <-> Substrate relays. +/// Message sync pipeline for Substrate <-> Substrate relays. #[async_trait] pub trait SubstrateMessageLane: MessageLane { /// Name of the runtime method that returns dispatch weight of outbound messages at the source chain.