From 165730a2c20624ab0696e4fad89b51648fcd61f2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 25 Jun 2021 11:06:14 +0300 Subject: [PATCH] Rococo <> Wococo messages relay (#1030) * MessagesInstance -> BridgedMessagesInstance * Chain::ID -> Bridge::THIS_CHAIN_ID+Bridge::BRIDGED_CHAIN_ID * FromBridgedChainEncodedMessageCall -> FromBridgedChainEncodedMessageCall * impl Parameter for () * copypaste storage_map_final_key to avoid different runtime references/dummy runtimes * moved dummy runtime from primitives to relay client * Rococo <> Wococo messages relays * send R<>W messages using relay * fmt * return Result from get_dispatch_info * fix benchmarks compilation * clippy --- .../bin/millau/runtime/src/rialto_messages.rs | 13 +- bridges/bin/rialto/runtime/src/lib.rs | 19 +- .../bin/rialto/runtime/src/millau_messages.rs | 13 +- bridges/bin/runtime-common/src/messages.rs | 79 +++--- bridges/modules/messages/src/lib.rs | 34 ++- bridges/primitives/chain-rococo/Cargo.toml | 2 - bridges/primitives/chain-rococo/src/lib.rs | 51 +--- bridges/primitives/chain-wococo/Cargo.toml | 2 - bridges/primitives/chain-wococo/src/lib.rs | 45 +--- bridges/primitives/messages/src/lib.rs | 4 + .../relays/bin-substrate/src/chains/millau.rs | 6 +- .../src/chains/millau_messages_to_rialto.rs | 16 +- .../relays/bin-substrate/src/chains/mod.rs | 7 +- .../relays/bin-substrate/src/chains/rialto.rs | 6 +- .../src/chains/rialto_messages_to_millau.rs | 16 +- .../relays/bin-substrate/src/chains/rococo.rs | 65 ++++- .../src/chains/rococo_headers_to_wococo.rs | 7 +- .../src/chains/rococo_messages_to_wococo.rs | 227 ++++++++++++++++++ .../relays/bin-substrate/src/chains/wococo.rs | 59 ++++- .../src/chains/wococo_headers_to_rococo.rs | 7 +- .../src/chains/wococo_messages_to_rococo.rs | 227 ++++++++++++++++++ .../relays/bin-substrate/src/cli/bridge.rs | 50 ++++ .../bin-substrate/src/cli/encode_call.rs | 7 +- .../bin-substrate/src/cli/init_bridge.rs | 8 +- .../src/cli/relay_headers_and_messages.rs | 24 ++ .../bin-substrate/src/cli/send_message.rs | 4 +- .../bin-substrate/src/messages_source.rs | 17 +- .../bin-substrate/src/messages_target.rs | 17 +- bridges/relays/client-rococo/Cargo.toml | 9 + bridges/relays/client-rococo/src/lib.rs | 6 +- bridges/relays/client-rococo/src/runtime.rs | 135 +++++++++++ bridges/relays/client-wococo/Cargo.toml | 9 + bridges/relays/client-wococo/src/lib.rs | 6 +- bridges/relays/client-wococo/src/runtime.rs | 135 +++++++++++ 34 files changed, 1090 insertions(+), 242 deletions(-) create mode 100644 bridges/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs create mode 100644 bridges/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs create mode 100644 bridges/relays/client-rococo/src/runtime.rs create mode 100644 bridges/relays/client-wococo/src/runtime.rs diff --git a/bridges/bin/millau/runtime/src/rialto_messages.rs b/bridges/bin/millau/runtime/src/rialto_messages.rs index 644ddc6421..12af2c3285 100644 --- a/bridges/bin/millau/runtime/src/rialto_messages.rs +++ b/bridges/bin/millau/runtime/src/rialto_messages.rs @@ -52,7 +52,7 @@ pub type ToRialtoMessageVerifier = messages::source::FromThisChainMessageVerifie pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Encoded Millau Call as it comes from Rialto. -pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; +pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; /// Messages proof for Rialto -> Millau messages. type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; @@ -74,9 +74,12 @@ pub struct WithRialtoMessageBridge; impl MessageBridge for WithRialtoMessageBridge { const RELAYER_FEE_PERCENT: u32 = 10; + const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; + const BRIDGED_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; type ThisChain = Millau; type BridgedChain = Rialto; + type BridgedMessagesInstance = crate::WithRialtoMessagesInstance; fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance { bp_millau::Balance::try_from(RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance)) @@ -89,16 +92,12 @@ impl MessageBridge for WithRialtoMessageBridge { pub struct Millau; impl messages::ChainWithMessages for Millau { - const ID: ChainId = MILLAU_CHAIN_ID; - type Hash = bp_millau::Hash; type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; type Signature = bp_millau::Signature; type Weight = Weight; type Balance = bp_millau::Balance; - - type MessagesInstance = crate::WithRialtoMessagesInstance; } impl messages::ThisChainWithMessages for Millau { @@ -145,16 +144,12 @@ impl messages::ThisChainWithMessages for Millau { pub struct Rialto; impl messages::ChainWithMessages for Rialto { - const ID: ChainId = RIALTO_CHAIN_ID; - type Hash = bp_rialto::Hash; type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; type Signature = bp_rialto::Signature; type Weight = Weight; type Balance = bp_rialto::Balance; - - type MessagesInstance = pallet_bridge_messages::DefaultInstance; } impl messages::BridgedChainWithMessages for Rialto { diff --git a/bridges/bin/rialto/runtime/src/lib.rs b/bridges/bin/rialto/runtime/src/lib.rs index 40eb7326a3..219feda646 100644 --- a/bridges/bin/rialto/runtime/src/lib.rs +++ b/bridges/bin/rialto/runtime/src/lib.rs @@ -915,10 +915,10 @@ impl_runtime_apis! { fn prepare_message_proof( params: MessageProofParams, ) -> (millau_messages::FromMillauMessagesProof, Weight) { - use crate::millau_messages::{Millau, WithMillauMessageBridge}; + use crate::millau_messages::WithMillauMessageBridge; use bp_messages::MessageKey; use bridge_runtime_common::{ - messages::ChainWithMessages, + messages::MessageBridge, messages_benchmarking::{ed25519_sign, prepare_message_proof}, }; use codec::Encode; @@ -951,13 +951,12 @@ impl_runtime_apis! { } let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key::< - Runtime, - ::MessagesInstance, + ::BridgedMessagesInstance, >( &message_key.lane_id, message_key.nonce, ).0; let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key::< - ::MessagesInstance, + ::BridgedMessagesInstance, >( &lane_id, ).0; @@ -998,18 +997,14 @@ impl_runtime_apis! { fn prepare_message_delivery_proof( params: MessageDeliveryProofParams, ) -> millau_messages::ToMillauMessagesDeliveryProof { - use crate::millau_messages::{Millau, WithMillauMessageBridge}; - use bridge_runtime_common::{ - messages::ChainWithMessages, - messages_benchmarking::prepare_message_delivery_proof, - }; + use crate::millau_messages::WithMillauMessageBridge; + use bridge_runtime_common::{messages_benchmarking::prepare_message_delivery_proof}; use sp_runtime::traits::Header; prepare_message_delivery_proof::( params, |lane_id| pallet_bridge_messages::storage_keys::inbound_lane_data_key::< - Runtime, - ::MessagesInstance, + ::BridgedMessagesInstance, >( &lane_id, ).0, diff --git a/bridges/bin/rialto/runtime/src/millau_messages.rs b/bridges/bin/rialto/runtime/src/millau_messages.rs index edcef4447f..bf97478a0a 100644 --- a/bridges/bin/rialto/runtime/src/millau_messages.rs +++ b/bridges/bin/rialto/runtime/src/millau_messages.rs @@ -52,7 +52,7 @@ pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifie pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Encoded Rialto Call as it comes from Millau. -pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; +pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; /// Call-dispatch based message dispatch for Millau -> Rialto messages. pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< @@ -74,9 +74,12 @@ pub struct WithMillauMessageBridge; impl MessageBridge for WithMillauMessageBridge { const RELAYER_FEE_PERCENT: u32 = 10; + const THIS_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; + const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; type ThisChain = Rialto; type BridgedChain = Millau; + type BridgedMessagesInstance = crate::WithMillauMessagesInstance; fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance { bp_rialto::Balance::try_from(MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance)) @@ -89,16 +92,12 @@ impl MessageBridge for WithMillauMessageBridge { pub struct Rialto; impl messages::ChainWithMessages for Rialto { - const ID: ChainId = RIALTO_CHAIN_ID; - type Hash = bp_rialto::Hash; type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; type Signature = bp_rialto::Signature; type Weight = Weight; type Balance = bp_rialto::Balance; - - type MessagesInstance = crate::WithMillauMessagesInstance; } impl messages::ThisChainWithMessages for Rialto { @@ -145,16 +144,12 @@ impl messages::ThisChainWithMessages for Rialto { pub struct Millau; impl messages::ChainWithMessages for Millau { - const ID: ChainId = MILLAU_CHAIN_ID; - type Hash = bp_millau::Hash; type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; type Signature = bp_millau::Signature; type Weight = Weight; type Balance = bp_millau::Balance; - - type MessagesInstance = pallet_bridge_messages::DefaultInstance; } impl messages::BridgedChainWithMessages for Millau { diff --git a/bridges/bin/runtime-common/src/messages.rs b/bridges/bin/runtime-common/src/messages.rs index 5628977480..72249e4f4e 100644 --- a/bridges/bin/runtime-common/src/messages.rs +++ b/bridges/bin/runtime-common/src/messages.rs @@ -49,10 +49,17 @@ pub trait MessageBridge { /// Relayer interest (in percents). const RELAYER_FEE_PERCENT: u32; + /// Identifier of this chain. + const THIS_CHAIN_ID: ChainId; + /// Identifier of the Bridged chain. + const BRIDGED_CHAIN_ID: ChainId; + /// This chain in context of message bridge. type ThisChain: ThisChainWithMessages; /// Bridged chain in context of message bridge. type BridgedChain: BridgedChainWithMessages; + /// Instance of the `pallet-bridge-messages` pallet at the Bridged chain. + type BridgedMessagesInstance: Instance; /// Convert Bridged chain balance into This chain balance. fn bridged_balance_to_this_balance(bridged_balance: BalanceOf>) -> BalanceOf>; @@ -60,9 +67,6 @@ pub trait MessageBridge { /// Chain that has `pallet-bridge-messages` and `dispatch` modules. pub trait ChainWithMessages { - /// Identifier of this chain. - const ID: ChainId; - /// Hash used in the chain. type Hash: Decode; /// Accound id on the chain. @@ -78,9 +82,6 @@ pub trait ChainWithMessages { type Weight: From + PartialOrd; /// Type of balances that is used on the chain. type Balance: Encode + Decode + CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From + Copy; - - /// Instance of the `pallet-bridge-messages` pallet. - type MessagesInstance: Instance; } /// Message related transaction parameters estimation. @@ -147,7 +148,6 @@ pub(crate) type SignerOf = ::Signer; pub(crate) type SignatureOf = ::Signature; pub(crate) type WeightOf = ::Weight; pub(crate) type BalanceOf = ::Balance; -pub(crate) type MessagesInstanceOf = ::MessagesInstance; pub(crate) type CallOf = ::Call; @@ -376,7 +376,6 @@ pub mod source { ) -> Result, &'static str> where ThisRuntime: pallet_bridge_grandpa::Config, - ThisRuntime: pallet_bridge_messages::Config>>, HashOf>: Into>::BridgedChain>>, { @@ -391,10 +390,8 @@ pub mod source { |storage| { // Messages delivery proof is just proof of single storage key read => any error // is fatal. - let storage_inbound_lane_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::< - ThisRuntime, - MessagesInstanceOf>, - >(&lane); + let storage_inbound_lane_data_key = + pallet_bridge_messages::storage_keys::inbound_lane_data_key::(&lane); let raw_inbound_lane_data = storage .read_value(storage_inbound_lane_data_key.0.as_ref()) .map_err(|_| "Failed to read inbound lane state from storage proof")? @@ -425,7 +422,7 @@ pub mod target { AccountIdOf>, SignerOf>, SignatureOf>, - FromBridgedChainEncodedMessageCall, + FromBridgedChainEncodedMessageCall>>, >; /// Messages proof from bridged chain: @@ -463,12 +460,12 @@ pub mod target { /// Our Call is opaque (`Vec`) for Bridged chain. So it is encoded, prefixed with /// vector length. Custom decode implementation here is exactly to deal with this. #[derive(Decode, Encode, RuntimeDebug, PartialEq)] - pub struct FromBridgedChainEncodedMessageCall { + pub struct FromBridgedChainEncodedMessageCall { encoded_call: Vec, - _marker: PhantomData, + _marker: PhantomData, } - impl FromBridgedChainEncodedMessageCall { + impl FromBridgedChainEncodedMessageCall { /// Create encoded call. pub fn new(encoded_call: Vec) -> Self { FromBridgedChainEncodedMessageCall { @@ -478,9 +475,9 @@ pub mod target { } } - impl From> for Result>, ()> { - fn from(encoded_call: FromBridgedChainEncodedMessageCall) -> Self { - CallOf::>::decode(&mut &encoded_call.encoded_call[..]).map_err(drop) + impl From> for Result { + fn from(encoded_call: FromBridgedChainEncodedMessageCall) -> Self { + DecodedCall::decode(&mut &encoded_call.encoded_call[..]).map_err(drop) } } @@ -523,8 +520,8 @@ pub mod target { ) -> MessageDispatchResult { let message_id = (message.key.lane_id, message.key.nonce); pallet_bridge_dispatch::Pallet::::dispatch( - B::BridgedChain::ID, - B::ThisChain::ID, + B::BRIDGED_CHAIN_ID, + B::THIS_CHAIN_ID, message_id, message.data.payload.map_err(drop), |dispatch_origin, dispatch_weight| { @@ -561,7 +558,7 @@ pub mod target { ) -> Result>>>, &'static str> where ThisRuntime: pallet_bridge_grandpa::Config, - ThisRuntime: pallet_bridge_messages::Config>>, + ThisRuntime: pallet_bridge_messages::Config, HashOf>: Into>::BridgedChain>>, { @@ -574,7 +571,7 @@ pub mod target { StorageProof::new(bridged_storage_proof), |storage_adapter| storage_adapter, ) - .map(|storage| StorageProofCheckerAdapter::<_, B, ThisRuntime> { + .map(|storage| StorageProofCheckerAdapter::<_, B> { storage, _dummy: Default::default(), }) @@ -614,31 +611,29 @@ pub mod target { fn read_raw_message(&self, message_key: &MessageKey) -> Option>; } - struct StorageProofCheckerAdapter { + struct StorageProofCheckerAdapter { storage: StorageProofChecker, - _dummy: sp_std::marker::PhantomData<(B, ThisRuntime)>, + _dummy: sp_std::marker::PhantomData, } - impl MessageProofParser for StorageProofCheckerAdapter + impl MessageProofParser for StorageProofCheckerAdapter where H: Hasher, B: MessageBridge, - ThisRuntime: pallet_bridge_messages::Config>>, { fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option> { - let storage_outbound_lane_data_key = pallet_bridge_messages::storage_keys::outbound_lane_data_key::< - MessagesInstanceOf>, - >(lane_id); + let storage_outbound_lane_data_key = + pallet_bridge_messages::storage_keys::outbound_lane_data_key::(lane_id); self.storage .read_value(storage_outbound_lane_data_key.0.as_ref()) .ok()? } fn read_raw_message(&self, message_key: &MessageKey) -> Option> { - let storage_message_key = pallet_bridge_messages::storage_keys::message_key::< - ThisRuntime, - MessagesInstanceOf>, - >(&message_key.lane_id, message_key.nonce); + let storage_message_key = pallet_bridge_messages::storage_keys::message_key::( + &message_key.lane_id, + message_key.nonce, + ); self.storage.read_value(storage_message_key.0.as_ref()).ok()? } } @@ -743,9 +738,12 @@ mod tests { impl MessageBridge for OnThisChainBridge { const RELAYER_FEE_PERCENT: u32 = 10; + const THIS_CHAIN_ID: ChainId = *b"this"; + const BRIDGED_CHAIN_ID: ChainId = *b"brdg"; type ThisChain = ThisChain; type BridgedChain = BridgedChain; + type BridgedMessagesInstance = pallet_bridge_messages::DefaultInstance; fn bridged_balance_to_this_balance(bridged_balance: BridgedChainBalance) -> ThisChainBalance { ThisChainBalance(bridged_balance.0 * BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE as u32) @@ -758,9 +756,12 @@ mod tests { impl MessageBridge for OnBridgedChainBridge { const RELAYER_FEE_PERCENT: u32 = 20; + const THIS_CHAIN_ID: ChainId = *b"brdg"; + const BRIDGED_CHAIN_ID: ChainId = *b"this"; type ThisChain = BridgedChain; type BridgedChain = ThisChain; + type BridgedMessagesInstance = pallet_bridge_messages::DefaultInstance; fn bridged_balance_to_this_balance(_this_balance: ThisChainBalance) -> BridgedChainBalance { unreachable!() @@ -857,16 +858,12 @@ mod tests { struct ThisChain; impl ChainWithMessages for ThisChain { - const ID: ChainId = *b"this"; - type Hash = (); type AccountId = ThisChainAccountId; type Signer = ThisChainSigner; type Signature = ThisChainSignature; type Weight = frame_support::weights::Weight; type Balance = ThisChainBalance; - - type MessagesInstance = pallet_bridge_messages::DefaultInstance; } impl ThisChainWithMessages for ThisChain { @@ -917,16 +914,12 @@ mod tests { struct BridgedChain; impl ChainWithMessages for BridgedChain { - const ID: ChainId = *b"brdg"; - type Hash = (); type AccountId = BridgedChainAccountId; type Signer = BridgedChainSigner; type Signature = BridgedChainSignature; type Weight = frame_support::weights::Weight; type Balance = BridgedChainBalance; - - type MessagesInstance = pallet_bridge_messages::DefaultInstance; } impl ThisChainWithMessages for BridgedChain { @@ -1002,7 +995,7 @@ mod tests { weight: 100, origin: bp_message_dispatch::CallOrigin::SourceRoot, dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - call: target::FromBridgedChainEncodedMessageCall::::new( + call: target::FromBridgedChainEncodedMessageCall::::new( ThisChainCall::Transfer.encode(), ), } diff --git a/bridges/modules/messages/src/lib.rs b/bridges/modules/messages/src/lib.rs index 054c0e2a02..a5f94c1eda 100644 --- a/bridges/modules/messages/src/lib.rs +++ b/bridges/modules/messages/src/lib.rs @@ -755,24 +755,38 @@ impl, I: Instance> Pallet { /// trying to avoid here) - by using strings like "Instance2", "OutboundMessages", etc. pub mod storage_keys { use super::*; - use frame_support::storage::generator::StorageMap; + use frame_support::{traits::Instance, StorageHasher}; use sp_core::storage::StorageKey; /// Storage key of the outbound message in the runtime storage. - pub fn message_key, I: Instance>(lane: &LaneId, nonce: MessageNonce) -> StorageKey { - let message_key = MessageKey { lane_id: *lane, nonce }; - let raw_storage_key = OutboundMessages::::storage_map_final_key(message_key); - StorageKey(raw_storage_key) + pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { + storage_map_final_key::("OutboundMessages", &MessageKey { lane_id: *lane, nonce }.encode()) } /// Storage key of the outbound message lane state in the runtime storage. pub fn outbound_lane_data_key(lane: &LaneId) -> StorageKey { - StorageKey(OutboundLanes::::storage_map_final_key(*lane)) + storage_map_final_key::("OutboundLanes", lane) } /// Storage key of the inbound message lane state in the runtime storage. - pub fn inbound_lane_data_key, I: Instance>(lane: &LaneId) -> StorageKey { - StorageKey(InboundLanes::::storage_map_final_key(*lane)) + pub fn inbound_lane_data_key(lane: &LaneId) -> StorageKey { + storage_map_final_key::("InboundLanes", lane) + } + + /// This is a copypaste of the `frame_support::storage::generator::StorageMap::storage_map_final_key`. + fn storage_map_final_key(map_name: &str, key: &[u8]) -> StorageKey { + let module_prefix_hashed = frame_support::Twox128::hash(I::PREFIX.as_bytes()); + let storage_prefix_hashed = frame_support::Twox128::hash(map_name.as_bytes()); + let key_hashed = frame_support::Blake2_128Concat::hash(key); + + let mut final_key = + Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len()); + + final_key.extend_from_slice(&module_prefix_hashed[..]); + final_key.extend_from_slice(&storage_prefix_hashed[..]); + final_key.extend_from_slice(key_hashed.as_ref()); + + StorageKey(final_key) } } @@ -1685,7 +1699,7 @@ mod tests { fn storage_message_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking all // previously crafted messages proofs. - let storage_key = storage_keys::message_key::(&*b"test", 42).0; + let storage_key = storage_keys::message_key::(&*b"test", 42).0; assert_eq!( storage_key, hex!("dd16c784ebd3390a9bc0357c7511ed018a395e6242c6813b196ca31ed0547ea79446af0e09063bd4a7874aef8a997cec746573742a00000000000000").to_vec(), @@ -1711,7 +1725,7 @@ mod tests { fn inbound_lane_data_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking all // previously crafted inbound lane state proofs. - let storage_key = storage_keys::inbound_lane_data_key::(&*b"test").0; + let storage_key = storage_keys::inbound_lane_data_key::(&*b"test").0; assert_eq!( storage_key, hex!("dd16c784ebd3390a9bc0357c7511ed01e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(), diff --git a/bridges/primitives/chain-rococo/Cargo.toml b/bridges/primitives/chain-rococo/Cargo.toml index 2f806b3632..33772c7890 100644 --- a/bridges/primitives/chain-rococo/Cargo.toml +++ b/bridges/primitives/chain-rococo/Cargo.toml @@ -11,7 +11,6 @@ parity-scale-codec = { version = "2.0.0", default-features = false, features = [ smallvec = "1.6" # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } @@ -26,7 +25,6 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master [features] default = ["std"] std = [ - "bp-header-chain/std", "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", diff --git a/bridges/primitives/chain-rococo/src/lib.rs b/bridges/primitives/chain-rococo/src/lib.rs index 7940b40d43..8df064e891 100644 --- a/bridges/primitives/chain-rococo/src/lib.rs +++ b/bridges/primitives/chain-rococo/src/lib.rs @@ -21,7 +21,6 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; -use bp_runtime::Chain; use frame_support::weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -31,7 +30,12 @@ pub use bp_polkadot_core::*; /// Rococo Chain pub type Rococo = PolkadotLike; -pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; +/// The target length of a session (how often authorities change) on Westend measured in of number of +/// blocks. +/// +/// Note that since this is a target sessions may change before/after this time depending on network +/// conditions. +pub const SESSION_LENGTH: BlockNumber = 10 * time_units::MINUTES; // NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. pub const VERSION: RuntimeVersion = RuntimeVersion { @@ -61,44 +65,11 @@ impl WeightToFeePolynomial for WeightToFee { } } -/// Rococo Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to Rococo chain. -/// Ideally this code would be auto-generated from Metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo -/// `construct_runtime`, so that we maintain SCALE-compatibility. -/// -/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs -#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] -pub enum Call { - /// Wococo bridge pallet. - #[codec(index = 41)] - BridgeGrandpaWococo(BridgeGrandpaWococoCall), -} - -#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] -#[allow(non_camel_case_types)] -pub enum BridgeGrandpaWococoCall { - #[codec(index = 0)] - submit_finality_proof( - ::Header, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), -} - -impl sp_runtime::traits::Dispatchable for Call { - type Origin = (); - type Config = (); - type Info = (); - type PostInfo = (); - - fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } +// We use this to get the account on Rococo (target) which is derived from Wococo's (source) +// account. +pub fn derive_account_from_wococo_id(id: bp_runtime::SourceAccount) -> AccountId { + let encoded_id = bp_runtime::derive_account_id(bp_runtime::WOCOCO_CHAIN_ID, id); + AccountIdConverter::convert(encoded_id) } /// Name of the `RococoFinalityApi::best_finalized` runtime method. diff --git a/bridges/primitives/chain-wococo/Cargo.toml b/bridges/primitives/chain-wococo/Cargo.toml index ffa75b5a45..88201dde9a 100644 --- a/bridges/primitives/chain-wococo/Cargo.toml +++ b/bridges/primitives/chain-wococo/Cargo.toml @@ -10,7 +10,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-rococo = { path = "../chain-rococo", default-features = false } @@ -24,7 +23,6 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [features] default = ["std"] std = [ - "bp-header-chain/std", "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", diff --git a/bridges/primitives/chain-wococo/src/lib.rs b/bridges/primitives/chain-wococo/src/lib.rs index 3aaa5a730a..24572e141b 100644 --- a/bridges/primitives/chain-wococo/src/lib.rs +++ b/bridges/primitives/chain-wococo/src/lib.rs @@ -21,58 +21,15 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; -use bp_runtime::Chain; use sp_std::prelude::*; pub use bp_polkadot_core::*; // Rococo runtime = Wococo runtime -pub use bp_rococo::{WeightToFee, VERSION}; +pub use bp_rococo::{WeightToFee, SESSION_LENGTH, VERSION}; /// Wococo Chain pub type Wococo = PolkadotLike; -pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; - -/// Wococo Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to Rococo chain. -/// Ideally this code would be auto-generated from Metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo -/// `construct_runtime`, so that we maintain SCALE-compatibility. -/// -/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs -#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] -pub enum Call { - /// Rococo bridge pallet. - #[codec(index = 40)] - BridgeGrandpaRococo(BridgeGrandpaRococoCall), -} - -#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] -#[allow(non_camel_case_types)] -pub enum BridgeGrandpaRococoCall { - #[codec(index = 0)] - submit_finality_proof( - ::Header, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), -} - -impl sp_runtime::traits::Dispatchable for Call { - type Origin = (); - type Config = (); - type Info = (); - type PostInfo = (); - - fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } -} - // We use this to get the account on Wococo (target) which is derived from Rococo's (source) // account. pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) -> AccountId { diff --git a/bridges/primitives/messages/src/lib.rs b/bridges/primitives/messages/src/lib.rs index eb44fbea94..963543ec32 100644 --- a/bridges/primitives/messages/src/lib.rs +++ b/bridges/primitives/messages/src/lib.rs @@ -64,6 +64,10 @@ pub trait Parameter: frame_support::Parameter { fn save(&self); } +impl Parameter for () { + fn save(&self) {} +} + /// Lane identifier. pub type LaneId = [u8; 4]; diff --git a/bridges/relays/bin-substrate/src/chains/millau.rs b/bridges/relays/bin-substrate/src/chains/millau.rs index 41ac760828..3cba16ea32 100644 --- a/bridges/relays/bin-substrate/src/chains/millau.rs +++ b/bridges/relays/bin-substrate/src/chains/millau.rs @@ -23,7 +23,7 @@ use crate::cli::{ }; use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; -use frame_support::weights::{GetDispatchInfo, Weight}; +use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; use relay_millau_client::Millau; use sp_version::RuntimeVersion; @@ -62,6 +62,10 @@ impl CliEncodeCall for Millau { }, }) } + + fn get_dispatch_info(call: &millau_runtime::Call) -> anyhow::Result { + Ok(call.get_dispatch_info()) + } } impl CliChain for Millau { diff --git a/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index f132088f54..31dc51e9c2 100644 --- a/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -126,20 +126,12 @@ impl SubstrateMessageLane for MillauMessagesToRialto { } /// Millau node as messages source. -type MillauSourceClient = SubstrateMessagesSource< - Millau, - MillauMessagesToRialto, - millau_runtime::Runtime, - millau_runtime::WithRialtoMessagesInstance, ->; +type MillauSourceClient = + SubstrateMessagesSource; /// Rialto node as messages target. -type RialtoTargetClient = SubstrateMessagesTarget< - Rialto, - MillauMessagesToRialto, - rialto_runtime::Runtime, - rialto_runtime::WithMillauMessagesInstance, ->; +type RialtoTargetClient = + SubstrateMessagesTarget; /// Run Millau-to-Rialto messages sync. pub async fn run( diff --git a/bridges/relays/bin-substrate/src/chains/mod.rs b/bridges/relays/bin-substrate/src/chains/mod.rs index 7b7b768635..09d3c3e9c0 100644 --- a/bridges/relays/bin-substrate/src/chains/mod.rs +++ b/bridges/relays/bin-substrate/src/chains/mod.rs @@ -21,8 +21,10 @@ pub mod millau_messages_to_rialto; pub mod rialto_headers_to_millau; pub mod rialto_messages_to_millau; pub mod rococo_headers_to_wococo; +pub mod rococo_messages_to_wococo; pub mod westend_headers_to_millau; pub mod wococo_headers_to_rococo; +pub mod wococo_messages_to_rococo; mod millau; mod rialto; @@ -271,7 +273,10 @@ mod rococo_tests { votes_ancestries: vec![], }; - let actual = bp_rococo::BridgeGrandpaWococoCall::submit_finality_proof(header.clone(), justification.clone()); + let actual = relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof( + header.clone(), + justification.clone(), + ); let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( header, justification, diff --git a/bridges/relays/bin-substrate/src/chains/rialto.rs b/bridges/relays/bin-substrate/src/chains/rialto.rs index 77eeb06da0..9a6185b4fc 100644 --- a/bridges/relays/bin-substrate/src/chains/rialto.rs +++ b/bridges/relays/bin-substrate/src/chains/rialto.rs @@ -23,7 +23,7 @@ use crate::cli::{ }; use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; -use frame_support::weights::{GetDispatchInfo, Weight}; +use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; use relay_rialto_client::Rialto; use sp_version::RuntimeVersion; @@ -60,6 +60,10 @@ impl CliEncodeCall for Rialto { }, }) } + + fn get_dispatch_info(call: &rialto_runtime::Call) -> anyhow::Result { + Ok(call.get_dispatch_info()) + } } impl CliChain for Rialto { diff --git a/bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 02c6010f74..89f9dd7e99 100644 --- a/bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -126,20 +126,12 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { } /// Rialto node as messages source. -type RialtoSourceClient = SubstrateMessagesSource< - Rialto, - RialtoMessagesToMillau, - rialto_runtime::Runtime, - rialto_runtime::WithMillauMessagesInstance, ->; +type RialtoSourceClient = + SubstrateMessagesSource; /// Millau node as messages target. -type MillauTargetClient = SubstrateMessagesTarget< - Millau, - RialtoMessagesToMillau, - millau_runtime::Runtime, - millau_runtime::WithRialtoMessagesInstance, ->; +type MillauTargetClient = + SubstrateMessagesTarget; /// Run Rialto-to-Millau messages sync. pub async fn run( diff --git a/bridges/relays/bin-substrate/src/chains/rococo.rs b/bridges/relays/bin-substrate/src/chains/rococo.rs index 0bcf388c34..ec94450a63 100644 --- a/bridges/relays/bin-substrate/src/chains/rococo.rs +++ b/bridges/relays/bin-substrate/src/chains/rococo.rs @@ -14,11 +14,70 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{encode_message, CliChain}; -use frame_support::weights::Weight; +use codec::Decode; +use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_rococo_client::Rococo; use sp_version::RuntimeVersion; +use crate::cli::{ + bridge, + encode_call::{Call, CliEncodeCall}, + encode_message, CliChain, +}; + +/// Weight of the `system::remark` call at Rococo. +/// +/// This weight is larger (x2) than actual weight at current Rooco runtime to avoid unsuccessful +/// calls in the future. But since it is used only in tests (and on test chains), this is ok. +pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; + +impl CliEncodeCall for Rococo { + fn max_extrinsic_size() -> u32 { + bp_rococo::max_extrinsic_size() + } + + fn encode_call(call: &Call) -> anyhow::Result { + Ok(match call { + Call::Remark { remark_payload, .. } => { + relay_rococo_client::runtime::Call::System(relay_rococo_client::runtime::SystemCall::remark( + remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + )) + } + Call::BridgeSendMessage { + lane, + payload, + fee, + bridge_instance_index, + } => match *bridge_instance_index { + bridge::ROCOCO_TO_WOCOCO_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + relay_rococo_client::runtime::Call::BridgeMessagesWococo( + relay_rococo_client::runtime::BridgeMessagesWococoCall::send_message(lane.0, payload, fee.0), + ) + } + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, + _ => anyhow::bail!("The call is not supported"), + }) + } + + fn get_dispatch_info(call: &relay_rococo_client::runtime::Call) -> anyhow::Result { + match *call { + relay_rococo_client::runtime::Call::System(relay_rococo_client::runtime::SystemCall::remark(_)) => { + Ok(DispatchInfo { + weight: SYSTEM_REMARK_CALL_WEIGHT, + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + }) + } + _ => anyhow::bail!("Unsupported Rococo call: {:?}", call), + } + } +} + impl CliChain for Rococo { const RUNTIME_VERSION: RuntimeVersion = bp_rococo::VERSION; @@ -30,7 +89,7 @@ impl CliChain for Rococo { } fn max_extrinsic_weight() -> Weight { - 0 + bp_wococo::max_extrinsic_weight() } fn encode_message(_message: encode_message::MessagePayload) -> Result { diff --git a/bridges/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/bridges/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index 4e641aec74..c7f60100f1 100644 --- a/bridges/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/bridges/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -61,10 +61,9 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { header: RococoSyncHeader, proof: GrandpaJustification, ) -> Bytes { - let call = bp_wococo::Call::BridgeGrandpaRococo(bp_wococo::BridgeGrandpaRococoCall::submit_finality_proof( - header.into_inner(), - proof, - )); + let call = relay_wococo_client::runtime::Call::BridgeGrandpaRococo( + relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof(header.into_inner(), proof), + ); let genesis_hash = *self.target_client.genesis_hash(); let transaction = Wococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); diff --git a/bridges/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/bridges/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs new file mode 100644 index 0000000000..be5f91116e --- /dev/null +++ b/bridges/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -0,0 +1,227 @@ +// Copyright 2019-2021 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 . + +//! Rococo-to-Wococo messages sync entrypoint. + +use crate::messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, +}; +use crate::messages_source::SubstrateMessagesSource; +use crate::messages_target::SubstrateMessagesTarget; + +use bp_messages::MessageNonce; +use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID}; +use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; +use codec::Encode; +use messages_relay::message_lane::MessageLane; +use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; +use relay_substrate_client::{metrics::StorageProofOverheadMetric, Chain, TransactionSignScheme}; +use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; +use sp_core::{Bytes, Pair}; +use std::{ops::RangeInclusive, time::Duration}; + +/// Rococo-to-Wococo message lane. +pub type RococoMessagesToWococo = + SubstrateMessageLaneToSubstrate; + +impl SubstrateMessageLane for RococoMessagesToWococo { + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; + const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_wococo::TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; + + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rococo::FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_rococo::FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_rococo::FROM_ROCOCO_UNREWARDED_RELAYERS_STATE; + + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; + + type SourceChain = Rococo; + type TargetChain = Wococo; + + fn source_transactions_author(&self) -> bp_rococo::AccountId { + (*self.source_sign.public().as_array_ref()).into() + } + + fn make_messages_receiving_proof_transaction( + &self, + transaction_nonce: ::Index, + _generated_at_block: WococoHeaderId, + proof: ::MessagesReceivingProof, + ) -> Bytes { + let (relayers_state, proof) = proof; + let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo( + relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_delivery_proof( + proof, + relayers_state, + ), + ); + let genesis_hash = *self.source_client.genesis_hash(); + let transaction = Rococo::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); + log::trace!( + target: "bridge", + "Prepared Wococo -> Rococo confirmation transaction. Weight: /{}, size: {}/{}", + bp_rococo::max_extrinsic_weight(), + transaction.encode().len(), + bp_rococo::max_extrinsic_size(), + ); + Bytes(transaction.encode()) + } + + fn target_transactions_author(&self) -> bp_wococo::AccountId { + (*self.target_sign.public().as_array_ref()).into() + } + + fn make_messages_delivery_transaction( + &self, + transaction_nonce: ::Index, + _generated_at_header: RococoHeaderId, + _nonces: RangeInclusive, + proof: ::MessagesProof, + ) -> Bytes { + let (dispatch_weight, proof) = proof; + let FromBridgedChainMessagesProof { + ref nonces_start, + ref nonces_end, + .. + } = proof; + let messages_count = nonces_end - nonces_start + 1; + + let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo( + relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_proof( + self.relayer_id_at_source.clone(), + proof, + messages_count as _, + dispatch_weight, + ), + ); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Wococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + log::trace!( + target: "bridge", + "Prepared Rococo -> Wococo delivery transaction. Weight: /{}, size: {}/{}", + bp_wococo::max_extrinsic_weight(), + transaction.encode().len(), + bp_wococo::max_extrinsic_size(), + ); + Bytes(transaction.encode()) + } +} + +/// Rococo node as messages source. +type RococoSourceClient = + SubstrateMessagesSource; + +/// Wococo node as messages target. +type WococoTargetClient = + SubstrateMessagesTarget; + +/// Run Rococo-to-Wococo messages sync. +pub async fn run( + params: MessagesRelayParams, +) -> Result<(), String> { + let stall_timeout = Duration::from_secs(5 * 60); + let relayer_id_at_rococo = (*params.source_sign.public().as_array_ref()).into(); + + let lane_id = params.lane_id; + let source_client = params.source_client; + let lane = RococoMessagesToWococo { + source_client: source_client.clone(), + source_sign: params.source_sign, + target_client: params.target_client.clone(), + target_sign: params.target_sign, + relayer_id_at_source: relayer_id_at_rococo, + }; + + // 2/3 is reserved for proofs and tx overhead + let max_messages_size_in_single_batch = bp_wococo::max_extrinsic_size() / 3; + // we don't know exact weights of the Wococo runtime. So to guess weights we'll be using + // weights from Rialto and then simply dividing it by x2. + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + select_delivery_transaction_limits::>( + bp_wococo::max_extrinsic_weight(), + bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + ); + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = ( + max_messages_in_single_batch / 2, + max_messages_weight_in_single_batch / 2, + ); + + log::info!( + target: "bridge", + "Starting Rococo -> Wococo messages relay.\n\t\ + Rococo relayer account id: {:?}\n\t\ + Max messages in single transaction: {}\n\t\ + Max messages size in single transaction: {}\n\t\ + Max messages weight in single transaction: {}", + lane.relayer_id_at_source, + max_messages_in_single_batch, + max_messages_size_in_single_batch, + max_messages_weight_in_single_batch, + ); + + messages_relay::message_lane_loop::run( + messages_relay::message_lane_loop::Params { + lane: lane_id, + source_tick: Rococo::AVERAGE_BLOCK_INTERVAL, + target_tick: Wococo::AVERAGE_BLOCK_INTERVAL, + reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, + stall_timeout, + delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { + max_unrewarded_relayer_entries_at_target: bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + max_unconfirmed_nonces_at_target: bp_wococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_messages_in_single_batch, + max_messages_weight_in_single_batch, + max_messages_size_in_single_batch, + relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic, + }, + }, + RococoSourceClient::new( + source_client.clone(), + lane.clone(), + lane_id, + WOCOCO_CHAIN_ID, + params.target_to_source_headers_relay, + ), + WococoTargetClient::new( + params.target_client, + lane, + lane_id, + ROCOCO_CHAIN_ID, + params.source_to_target_headers_relay, + ), + relay_utils::relay_metrics( + Some(messages_relay::message_lane_loop::metrics_prefix::< + RococoMessagesToWococo, + >(&lane_id)), + params.metrics_params, + ) + .standalone_metric(|registry, prefix| { + StorageProofOverheadMetric::new( + registry, + prefix, + source_client.clone(), + "rococo_storage_proof_overhead".into(), + "Rococo storage proof overhead".into(), + ) + })? + .into_params(), + futures::future::pending(), + ) + .await +} diff --git a/bridges/relays/bin-substrate/src/chains/wococo.rs b/bridges/relays/bin-substrate/src/chains/wococo.rs index 549aa8a882..9b944d7816 100644 --- a/bridges/relays/bin-substrate/src/chains/wococo.rs +++ b/bridges/relays/bin-substrate/src/chains/wococo.rs @@ -14,11 +14,64 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{encode_message, CliChain}; -use frame_support::weights::Weight; +use codec::Decode; +use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_wococo_client::Wococo; use sp_version::RuntimeVersion; +use crate::cli::{ + bridge, + encode_call::{Call, CliEncodeCall}, + encode_message, CliChain, +}; + +impl CliEncodeCall for Wococo { + fn max_extrinsic_size() -> u32 { + bp_wococo::max_extrinsic_size() + } + + fn encode_call(call: &Call) -> anyhow::Result { + Ok(match call { + Call::Remark { remark_payload, .. } => { + relay_wococo_client::runtime::Call::System(relay_wococo_client::runtime::SystemCall::remark( + remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + )) + } + Call::BridgeSendMessage { + lane, + payload, + fee, + bridge_instance_index, + } => match *bridge_instance_index { + bridge::WOCOCO_TO_ROCOCO_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + relay_wococo_client::runtime::Call::BridgeMessagesRococo( + relay_wococo_client::runtime::BridgeMessagesRococoCall::send_message(lane.0, payload, fee.0), + ) + } + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, + _ => anyhow::bail!("The call is not supported"), + }) + } + + fn get_dispatch_info(call: &relay_wococo_client::runtime::Call) -> anyhow::Result { + match *call { + relay_wococo_client::runtime::Call::System(relay_wococo_client::runtime::SystemCall::remark(_)) => { + Ok(DispatchInfo { + weight: crate::chains::rococo::SYSTEM_REMARK_CALL_WEIGHT, + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + }) + } + _ => anyhow::bail!("Unsupported Rococo call: {:?}", call), + } + } +} + impl CliChain for Wococo { const RUNTIME_VERSION: RuntimeVersion = bp_wococo::VERSION; @@ -30,7 +83,7 @@ impl CliChain for Wococo { } fn max_extrinsic_weight() -> Weight { - 0 + bp_wococo::max_extrinsic_weight() } fn encode_message(_message: encode_message::MessagePayload) -> Result { diff --git a/bridges/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/bridges/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index 4cae33db31..8ee30d3ff4 100644 --- a/bridges/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/bridges/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -67,10 +67,9 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { header: WococoSyncHeader, proof: GrandpaJustification, ) -> Bytes { - let call = bp_rococo::Call::BridgeGrandpaWococo(bp_rococo::BridgeGrandpaWococoCall::submit_finality_proof( - header.into_inner(), - proof, - )); + let call = relay_rococo_client::runtime::Call::BridgeGrandpaWococo( + relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof(header.into_inner(), proof), + ); let genesis_hash = *self.target_client.genesis_hash(); let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); diff --git a/bridges/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/bridges/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs new file mode 100644 index 0000000000..b696801569 --- /dev/null +++ b/bridges/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -0,0 +1,227 @@ +// Copyright 2019-2021 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 . + +//! Wococo-to-Rococo messages sync entrypoint. + +use crate::messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, +}; +use crate::messages_source::SubstrateMessagesSource; +use crate::messages_target::SubstrateMessagesTarget; + +use bp_messages::MessageNonce; +use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID}; +use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; +use codec::Encode; +use messages_relay::message_lane::MessageLane; +use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; +use relay_substrate_client::{metrics::StorageProofOverheadMetric, Chain, TransactionSignScheme}; +use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; +use sp_core::{Bytes, Pair}; +use std::{ops::RangeInclusive, time::Duration}; + +/// Wococo-to-Rococo message lane. +pub type WococoMessagesToRococo = + SubstrateMessageLaneToSubstrate; + +impl SubstrateMessageLane for WococoMessagesToRococo { + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; + const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rococo::TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; + + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_wococo::FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_wococo::FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_wococo::FROM_WOCOCO_UNREWARDED_RELAYERS_STATE; + + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; + + type SourceChain = Wococo; + type TargetChain = Rococo; + + fn source_transactions_author(&self) -> bp_wococo::AccountId { + (*self.source_sign.public().as_array_ref()).into() + } + + fn make_messages_receiving_proof_transaction( + &self, + transaction_nonce: ::Index, + _generated_at_block: RococoHeaderId, + proof: ::MessagesReceivingProof, + ) -> Bytes { + let (relayers_state, proof) = proof; + let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo( + relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_delivery_proof( + proof, + relayers_state, + ), + ); + let genesis_hash = *self.source_client.genesis_hash(); + let transaction = Wococo::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); + log::trace!( + target: "bridge", + "Prepared Rococo -> Wococo confirmation transaction. Weight: /{}, size: {}/{}", + bp_wococo::max_extrinsic_weight(), + transaction.encode().len(), + bp_wococo::max_extrinsic_size(), + ); + Bytes(transaction.encode()) + } + + fn target_transactions_author(&self) -> bp_rococo::AccountId { + (*self.target_sign.public().as_array_ref()).into() + } + + fn make_messages_delivery_transaction( + &self, + transaction_nonce: ::Index, + _generated_at_header: WococoHeaderId, + _nonces: RangeInclusive, + proof: ::MessagesProof, + ) -> Bytes { + let (dispatch_weight, proof) = proof; + let FromBridgedChainMessagesProof { + ref nonces_start, + ref nonces_end, + .. + } = proof; + let messages_count = nonces_end - nonces_start + 1; + + let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo( + relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_proof( + self.relayer_id_at_source.clone(), + proof, + messages_count as _, + dispatch_weight, + ), + ); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + log::trace!( + target: "bridge", + "Prepared Wococo -> Rococo delivery transaction. Weight: /{}, size: {}/{}", + bp_rococo::max_extrinsic_weight(), + transaction.encode().len(), + bp_rococo::max_extrinsic_size(), + ); + Bytes(transaction.encode()) + } +} + +/// Wococo node as messages source. +type WococoSourceClient = + SubstrateMessagesSource; + +/// Rococo node as messages target. +type RococoTargetClient = + SubstrateMessagesTarget; + +/// Run Wococo-to-Rococo messages sync. +pub async fn run( + params: MessagesRelayParams, +) -> Result<(), String> { + let stall_timeout = Duration::from_secs(5 * 60); + let relayer_id_at_wococo = (*params.source_sign.public().as_array_ref()).into(); + + let lane_id = params.lane_id; + let source_client = params.source_client; + let lane = WococoMessagesToRococo { + source_client: source_client.clone(), + source_sign: params.source_sign, + target_client: params.target_client.clone(), + target_sign: params.target_sign, + relayer_id_at_source: relayer_id_at_wococo, + }; + + // 2/3 is reserved for proofs and tx overhead + let max_messages_size_in_single_batch = bp_rococo::max_extrinsic_size() / 3; + // we don't know exact weights of the Rococo runtime. So to guess weights we'll be using + // weights from Rialto and then simply dividing it by x2. + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + select_delivery_transaction_limits::>( + bp_rococo::max_extrinsic_weight(), + bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + ); + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = ( + max_messages_in_single_batch / 2, + max_messages_weight_in_single_batch / 2, + ); + + log::info!( + target: "bridge", + "Starting Wococo -> Rococo messages relay.\n\t\ + Wococo relayer account id: {:?}\n\t\ + Max messages in single transaction: {}\n\t\ + Max messages size in single transaction: {}\n\t\ + Max messages weight in single transaction: {}", + lane.relayer_id_at_source, + max_messages_in_single_batch, + max_messages_size_in_single_batch, + max_messages_weight_in_single_batch, + ); + + messages_relay::message_lane_loop::run( + messages_relay::message_lane_loop::Params { + lane: lane_id, + source_tick: Wococo::AVERAGE_BLOCK_INTERVAL, + target_tick: Rococo::AVERAGE_BLOCK_INTERVAL, + reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, + stall_timeout, + delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { + max_unrewarded_relayer_entries_at_target: bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + max_unconfirmed_nonces_at_target: bp_rococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_messages_in_single_batch, + max_messages_weight_in_single_batch, + max_messages_size_in_single_batch, + relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic, + }, + }, + WococoSourceClient::new( + source_client.clone(), + lane.clone(), + lane_id, + ROCOCO_CHAIN_ID, + params.target_to_source_headers_relay, + ), + RococoTargetClient::new( + params.target_client, + lane, + lane_id, + WOCOCO_CHAIN_ID, + params.source_to_target_headers_relay, + ), + relay_utils::relay_metrics( + Some(messages_relay::message_lane_loop::metrics_prefix::< + WococoMessagesToRococo, + >(&lane_id)), + params.metrics_params, + ) + .standalone_metric(|registry, prefix| { + StorageProofOverheadMetric::new( + registry, + prefix, + source_client.clone(), + "wococo_storage_proof_overhead".into(), + "Wococo storage proof overhead".into(), + ) + })? + .into_params(), + futures::future::pending(), + ) + .await +} diff --git a/bridges/relays/bin-substrate/src/cli/bridge.rs b/bridges/relays/bin-substrate/src/cli/bridge.rs index b54d3a72ad..1feb3dcb1a 100644 --- a/bridges/relays/bin-substrate/src/cli/bridge.rs +++ b/bridges/relays/bin-substrate/src/cli/bridge.rs @@ -22,6 +22,8 @@ arg_enum! { pub enum FullBridge { MillauToRialto, RialtoToMillau, + RococoToWococo, + WococoToRococo, } } @@ -31,12 +33,16 @@ impl FullBridge { match self { Self::MillauToRialto => MILLAU_TO_RIALTO_INDEX, Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX, + Self::RococoToWococo => ROCOCO_TO_WOCOCO_INDEX, + Self::WococoToRococo => WOCOCO_TO_ROCOCO_INDEX, } } } pub const RIALTO_TO_MILLAU_INDEX: u8 = 0; pub const MILLAU_TO_RIALTO_INDEX: u8 = 0; +pub const ROCOCO_TO_WOCOCO_INDEX: u8 = 0; +pub const WOCOCO_TO_ROCOCO_INDEX: u8 = 0; /// The macro allows executing bridge-specific code without going fully generic. /// @@ -89,6 +95,50 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use rialto_runtime::rialto_to_millau_account_ownership_digest as account_ownership_digest; + $generic + } + FullBridge::RococoToWococo => { + type Source = relay_rococo_client::Rococo; + #[allow(dead_code)] + type Target = relay_wococo_client::Wococo; + + // Derive-account + #[allow(unused_imports)] + use bp_wococo::derive_account_from_rococo_id as derive_account; + + // Relay-messages + #[allow(unused_imports)] + use crate::chains::rococo_messages_to_wococo::run as relay_messages; + + // Send-message / Estimate-fee + #[allow(unused_imports)] + use bp_wococo::TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; + // Send-message + #[allow(unused_imports)] + use relay_rococo_client::runtime::rococo_to_wococo_account_ownership_digest as account_ownership_digest; + + $generic + } + FullBridge::WococoToRococo => { + type Source = relay_wococo_client::Wococo; + #[allow(dead_code)] + type Target = relay_rococo_client::Rococo; + + // Derive-account + #[allow(unused_imports)] + use bp_rococo::derive_account_from_wococo_id as derive_account; + + // Relay-messages + #[allow(unused_imports)] + use crate::chains::wococo_messages_to_rococo::run as relay_messages; + + // Send-message / Estimate-fee + #[allow(unused_imports)] + use bp_rococo::TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; + // Send-message + #[allow(unused_imports)] + use relay_wococo_client::runtime::wococo_to_rococo_account_ownership_digest as account_ownership_digest; + $generic } } diff --git a/bridges/relays/bin-substrate/src/cli/encode_call.rs b/bridges/relays/bin-substrate/src/cli/encode_call.rs index 390d8f6ae6..cfe6d99a4e 100644 --- a/bridges/relays/bin-substrate/src/cli/encode_call.rs +++ b/bridges/relays/bin-substrate/src/cli/encode_call.rs @@ -17,7 +17,7 @@ use crate::cli::bridge::FullBridge; use crate::cli::{AccountId, Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId}; use crate::select_full_bridge; -use frame_support::dispatch::GetDispatchInfo; +use frame_support::weights::DispatchInfo; use relay_substrate_client::Chain; use structopt::StructOpt; @@ -85,6 +85,9 @@ pub trait CliEncodeCall: Chain { /// Encode a CLI call. fn encode_call(call: &Call) -> anyhow::Result; + + /// Get dispatch info for the call. + fn get_dispatch_info(call: &Self::Call) -> anyhow::Result; } impl EncodeCall { @@ -96,7 +99,7 @@ impl EncodeCall { let encoded = HexBytes::encode(&call); log::info!(target: "bridge", "Generated {} call: {:#?}", Source::NAME, call); - log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, call.get_dispatch_info().weight); + log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, Source::get_dispatch_info(&call)?.weight); log::info!(target: "bridge", "Encoded {} call: {:?}", Source::NAME, encoded); Ok(encoded) diff --git a/bridges/relays/bin-substrate/src/cli/init_bridge.rs b/bridges/relays/bin-substrate/src/cli/init_bridge.rs index b5590b9e5a..20e6daa500 100644 --- a/bridges/relays/bin-substrate/src/cli/init_bridge.rs +++ b/bridges/relays/bin-substrate/src/cli/init_bridge.rs @@ -109,7 +109,9 @@ macro_rules! select_bridge { fn encode_init_bridge( init_data: InitializationData<::Header>, ) -> ::Call { - bp_wococo::Call::BridgeGrandpaRococo(bp_wococo::BridgeGrandpaRococoCall::initialize(init_data)) + relay_wococo_client::runtime::Call::BridgeGrandpaRococo( + relay_wococo_client::runtime::BridgeGrandpaRococoCall::initialize(init_data), + ) } $generic @@ -121,7 +123,9 @@ macro_rules! select_bridge { fn encode_init_bridge( init_data: InitializationData<::Header>, ) -> ::Call { - bp_rococo::Call::BridgeGrandpaWococo(bp_rococo::BridgeGrandpaWococoCall::initialize(init_data)) + relay_rococo_client::runtime::Call::BridgeGrandpaWococo( + relay_rococo_client::runtime::BridgeGrandpaWococoCall::initialize(init_data), + ) } $generic diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 4955e8bbef..e71ea6aeaa 100644 --- a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -35,6 +35,7 @@ use structopt::StructOpt; #[derive(StructOpt)] pub enum RelayHeadersAndMessages { MillauRialto(MillauRialtoHeadersAndMessages), + RococoWococo(RococoWococoHeadersAndMessages), } /// Parameters that have the same names across all bridges. @@ -102,6 +103,26 @@ macro_rules! select_bridge { use crate::chains::millau_messages_to_rialto::run as left_to_right_messages; use crate::chains::rialto_messages_to_millau::run as right_to_left_messages; + $generic + } + RelayHeadersAndMessages::RococoWococo(_) => { + type Params = RococoWococoHeadersAndMessages; + + type Left = relay_rococo_client::Rococo; + type Right = relay_wococo_client::Wococo; + + type LeftToRightFinality = crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo; + type RightToLeftFinality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; + + type LeftToRightMessages = crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo; + type RightToLeftMessages = crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo; + + const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_rococo::BlockNumber = bp_rococo::SESSION_LENGTH; + const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_wococo::BlockNumber = bp_wococo::SESSION_LENGTH; + + use crate::chains::rococo_messages_to_wococo::run as left_to_right_messages; + use crate::chains::wococo_messages_to_rococo::run as right_to_left_messages; + $generic } } @@ -111,8 +132,11 @@ macro_rules! select_bridge { // All supported chains. declare_chain_options!(Millau, millau); declare_chain_options!(Rialto, rialto); +declare_chain_options!(Rococo, rococo); +declare_chain_options!(Wococo, wococo); // All supported bridges. declare_bridge_options!(Millau, Rialto); +declare_bridge_options!(Rococo, Wococo); impl RelayHeadersAndMessages { /// Run the command. diff --git a/bridges/relays/bin-substrate/src/cli/send_message.rs b/bridges/relays/bin-substrate/src/cli/send_message.rs index 508a354ee9..f710f814e4 100644 --- a/bridges/relays/bin-substrate/src/cli/send_message.rs +++ b/bridges/relays/bin-substrate/src/cli/send_message.rs @@ -24,7 +24,7 @@ use crate::cli::{ use bp_message_dispatch::{CallOrigin, MessagePayload}; use bp_runtime::messages::DispatchFeePayment; use codec::Encode; -use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; +use frame_support::weights::Weight; use relay_substrate_client::{Chain, TransactionSignScheme}; use sp_core::{Bytes, Pair}; use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner}; @@ -89,7 +89,7 @@ impl SendMessage { let payload = { let target_call_weight = prepare_call_dispatch_weight( dispatch_weight, - ExplicitOrMaximal::Explicit(target_call.get_dispatch_info().weight), + ExplicitOrMaximal::Explicit(Target::get_dispatch_info(&target_call)?.weight), compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()), ); let source_sender_public: MultiSigner = source_sign.public().into(); diff --git a/bridges/relays/bin-substrate/src/messages_source.rs b/bridges/relays/bin-substrate/src/messages_source.rs index 35c5b8da19..88c8b529dc 100644 --- a/bridges/relays/bin-substrate/src/messages_source.rs +++ b/bridges/relays/bin-substrate/src/messages_source.rs @@ -33,7 +33,6 @@ use messages_relay::{ ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, SourceClient, SourceClientState, }, }; -use pallet_bridge_messages::Config as MessagesConfig; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf}; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; @@ -46,16 +45,16 @@ use std::{marker::PhantomData, ops::RangeInclusive}; pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof>); /// Substrate client as Substrate messages source. -pub struct SubstrateMessagesSource { +pub struct SubstrateMessagesSource { client: Client, lane: P, lane_id: LaneId, instance: ChainId, target_to_source_headers_relay: Option>, - _phantom: PhantomData<(R, I)>, + _phantom: PhantomData, } -impl SubstrateMessagesSource { +impl SubstrateMessagesSource { /// Create new Substrate headers source. pub fn new( client: Client, @@ -75,7 +74,7 @@ impl SubstrateMessagesSource Clone for SubstrateMessagesSource { +impl Clone for SubstrateMessagesSource { fn clone(&self) -> Self { Self { client: self.client.clone(), @@ -89,11 +88,10 @@ impl Clone for SubstrateMessagesSource< } #[async_trait] -impl RelayClient for SubstrateMessagesSource +impl RelayClient for SubstrateMessagesSource where C: Chain, P: SubstrateMessageLane, - R: 'static + Send + Sync, I: Send + Sync + Instance, { type Error = SubstrateError; @@ -104,7 +102,7 @@ where } #[async_trait] -impl SourceClient

for SubstrateMessagesSource +impl SourceClient

for SubstrateMessagesSource where C: Chain, C::Header: DeserializeOwned, @@ -120,7 +118,6 @@ where P::TargetChain: Chain, P::TargetHeaderNumber: Decode, P::TargetHeaderHash: Decode, - R: Send + Sync + MessagesConfig, I: Send + Sync + Instance, { async fn state(&self) -> Result, SubstrateError> { @@ -198,7 +195,7 @@ where let mut storage_keys = Vec::with_capacity(nonces.end().saturating_sub(*nonces.start()) as usize + 1); let mut message_nonce = *nonces.start(); while message_nonce <= *nonces.end() { - let message_key = pallet_bridge_messages::storage_keys::message_key::(&self.lane_id, message_nonce); + let message_key = pallet_bridge_messages::storage_keys::message_key::(&self.lane_id, message_nonce); storage_keys.push(message_key); message_nonce += 1; } diff --git a/bridges/relays/bin-substrate/src/messages_target.rs b/bridges/relays/bin-substrate/src/messages_target.rs index f9ffb922db..f74efbe61b 100644 --- a/bridges/relays/bin-substrate/src/messages_target.rs +++ b/bridges/relays/bin-substrate/src/messages_target.rs @@ -32,7 +32,6 @@ use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{TargetClient, TargetClientState}, }; -use pallet_bridge_messages::Config as MessagesConfig; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf}; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase}; use sp_core::Bytes; @@ -46,16 +45,16 @@ pub type SubstrateMessagesReceivingProof = ( ); /// Substrate client as Substrate messages target. -pub struct SubstrateMessagesTarget { +pub struct SubstrateMessagesTarget { client: Client, lane: P, lane_id: LaneId, instance: ChainId, source_to_target_headers_relay: Option>, - _phantom: PhantomData<(R, I)>, + _phantom: PhantomData, } -impl SubstrateMessagesTarget { +impl SubstrateMessagesTarget { /// Create new Substrate headers target. pub fn new( client: Client, @@ -75,7 +74,7 @@ impl SubstrateMessagesTarget Clone for SubstrateMessagesTarget { +impl Clone for SubstrateMessagesTarget { fn clone(&self) -> Self { Self { client: self.client.clone(), @@ -89,11 +88,10 @@ impl Clone for SubstrateMessagesTarget< } #[async_trait] -impl RelayClient for SubstrateMessagesTarget +impl RelayClient for SubstrateMessagesTarget where C: Chain, P: SubstrateMessageLane, - R: 'static + Send + Sync, I: Send + Sync + Instance, { type Error = SubstrateError; @@ -104,7 +102,7 @@ where } #[async_trait] -impl TargetClient

for SubstrateMessagesTarget +impl TargetClient

for SubstrateMessagesTarget where C: Chain, C::Header: DeserializeOwned, @@ -119,7 +117,6 @@ where P::SourceChain: Chain, P::SourceHeaderNumber: Decode, P::SourceHeaderHash: Decode, - R: Send + Sync + MessagesConfig, I: Send + Sync + Instance, { async fn state(&self) -> Result, SubstrateError> { @@ -190,7 +187,7 @@ where id: TargetHeaderIdOf

, ) -> Result<(TargetHeaderIdOf

, P::MessagesReceivingProof), SubstrateError> { let (id, relayers_state) = self.unrewarded_relayers_state(id).await?; - let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::(&self.lane_id); + let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::(&self.lane_id); let proof = self .client .prove_storage(vec![inbound_data_key], id.1) diff --git a/bridges/relays/client-rococo/Cargo.toml b/bridges/relays/client-rococo/Cargo.toml index 095f365374..5611ac27b1 100644 --- a/bridges/relays/client-rococo/Cargo.toml +++ b/bridges/relays/client-rococo/Cargo.toml @@ -12,7 +12,16 @@ relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } # Bridge dependencies +bridge-runtime-common = { path = "../../bin/runtime-common" } +bp-header-chain = { path = "../../primitives/header-chain" } +bp-message-dispatch = { path = "../../primitives/message-dispatch" } +bp-messages = { path = "../../primitives/messages" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rococo = { path = "../../primitives/chain-rococo" } +bp-runtime = { path = "../../primitives/runtime" } +bp-wococo = { path = "../../primitives/chain-wococo" } +pallet-bridge-dispatch = { path = "../../modules/dispatch" } +pallet-bridge-messages = { path = "../../modules/messages" } # Substrate Dependencies frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bridges/relays/client-rococo/src/lib.rs b/bridges/relays/client-rococo/src/lib.rs index fe9448d19c..5a7d8999f7 100644 --- a/bridges/relays/client-rococo/src/lib.rs +++ b/bridges/relays/client-rococo/src/lib.rs @@ -22,6 +22,8 @@ use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; +pub mod runtime; + /// Rococo header id. pub type HeaderId = relay_utils::HeaderId; @@ -46,7 +48,7 @@ impl Chain for Rococo { type AccountId = bp_rococo::AccountId; type Index = bp_rococo::Index; type SignedBlock = bp_rococo::SignedBlock; - type Call = bp_rococo::Call; + type Call = crate::runtime::Call; type Balance = bp_rococo::Balance; } @@ -59,7 +61,7 @@ impl ChainWithBalances for Rococo { impl TransactionSignScheme for Rococo { type Chain = Rococo; type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = bp_rococo::UncheckedExtrinsic; + type SignedTransaction = crate::runtime::UncheckedExtrinsic; fn sign_transaction( genesis_hash: ::Hash, diff --git a/bridges/relays/client-rococo/src/runtime.rs b/bridges/relays/client-rococo/src/runtime.rs new file mode 100644 index 0000000000..6dbd40bee5 --- /dev/null +++ b/bridges/relays/client-rococo/src/runtime.rs @@ -0,0 +1,135 @@ +// Copyright 2019-2021 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 . + +//! Types that are specific to the Rococo runtime. + +use bp_messages::{LaneId, UnrewardedRelayersState}; +use bp_polkadot_core::PolkadotLike; +use bp_runtime::Chain; +use codec::{Decode, Encode}; +use frame_support::weights::Weight; + +/// Instance of messages pallet that is used to bridge with Wococo chain. +pub type WithWococoMessagesInstance = pallet_bridge_messages::Instance1; + +/// Unchecked Rococo extrinsic. +pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; + +/// Wococo account ownership digest from Rococo. +/// +/// The byte vector returned by this function should be signed with a Wococo account private key. +/// This way, the owner of `rococo_account_id` on Rococo proves that the Wococo account private key +/// is also under his control. +pub fn rococo_to_wococo_account_ownership_digest( + wococo_call: &Call, + rococo_account_id: AccountId, + wococo_spec_version: SpecVersion, +) -> Vec +where + Call: codec::Encode, + AccountId: codec::Encode, + SpecVersion: codec::Encode, +{ + pallet_bridge_dispatch::account_ownership_digest( + wococo_call, + rococo_account_id, + wococo_spec_version, + bp_runtime::ROCOCO_CHAIN_ID, + bp_runtime::WOCOCO_CHAIN_ID, + ) +} + +/// Rococo Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to Rococo chain. +/// Ideally this code would be auto-generated from Metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo +/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +pub enum Call { + /// System pallet. + #[codec(index = 0)] + System(SystemCall), + /// Wococo bridge pallet. + #[codec(index = 41)] + BridgeGrandpaWococo(BridgeGrandpaWococoCall), + /// Wococo messages pallet. + #[codec(index = 44)] + BridgeMessagesWococo(BridgeMessagesWococoCall), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum SystemCall { + #[codec(index = 1)] + remark(Vec), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeGrandpaWococoCall { + #[codec(index = 0)] + submit_finality_proof( + ::Header, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeMessagesWococoCall { + #[codec(index = 3)] + send_message( + LaneId, + bp_message_dispatch::MessagePayload< + bp_rococo::AccountId, + bp_wococo::AccountId, + bp_wococo::AccountPublic, + Vec, + >, + bp_rococo::Balance, + ), + #[codec(index = 5)] + receive_messages_proof( + bp_wococo::AccountId, + bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, + u32, + Weight, + ), + #[codec(index = 6)] + receive_messages_delivery_proof( + bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof, + UnrewardedRelayersState, + ), +} + +impl sp_runtime::traits::Dispatchable for Call { + type Origin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { + unimplemented!("The Call is not expected to be dispatched.") + } +} diff --git a/bridges/relays/client-wococo/Cargo.toml b/bridges/relays/client-wococo/Cargo.toml index 22d710ca3d..c1b9aafd95 100644 --- a/bridges/relays/client-wococo/Cargo.toml +++ b/bridges/relays/client-wococo/Cargo.toml @@ -12,7 +12,16 @@ relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } # Bridge dependencies +bridge-runtime-common = { path = "../../bin/runtime-common" } +bp-header-chain = { path = "../../primitives/header-chain" } +bp-message-dispatch = { path = "../../primitives/message-dispatch" } +bp-messages = { path = "../../primitives/messages" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } +bp-rococo = { path = "../../primitives/chain-rococo" } +bp-runtime = { path = "../../primitives/runtime" } bp-wococo = { path = "../../primitives/chain-wococo" } +pallet-bridge-dispatch = { path = "../../modules/dispatch" } +pallet-bridge-messages = { path = "../../modules/messages" } # Substrate Dependencies frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bridges/relays/client-wococo/src/lib.rs b/bridges/relays/client-wococo/src/lib.rs index 76ecf5b0a5..8ceba7c7c4 100644 --- a/bridges/relays/client-wococo/src/lib.rs +++ b/bridges/relays/client-wococo/src/lib.rs @@ -22,6 +22,8 @@ use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; +pub mod runtime; + /// Wococo header id. pub type HeaderId = relay_utils::HeaderId; @@ -46,7 +48,7 @@ impl Chain for Wococo { type AccountId = bp_wococo::AccountId; type Index = bp_wococo::Index; type SignedBlock = bp_wococo::SignedBlock; - type Call = bp_wococo::Call; + type Call = crate::runtime::Call; type Balance = bp_wococo::Balance; } @@ -59,7 +61,7 @@ impl ChainWithBalances for Wococo { impl TransactionSignScheme for Wococo { type Chain = Wococo; type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = bp_wococo::UncheckedExtrinsic; + type SignedTransaction = crate::runtime::UncheckedExtrinsic; fn sign_transaction( genesis_hash: ::Hash, diff --git a/bridges/relays/client-wococo/src/runtime.rs b/bridges/relays/client-wococo/src/runtime.rs new file mode 100644 index 0000000000..e973c3a6d0 --- /dev/null +++ b/bridges/relays/client-wococo/src/runtime.rs @@ -0,0 +1,135 @@ +// Copyright 2019-2021 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 . + +//! Types that are specific to the Wococo runtime. + +use bp_messages::{LaneId, UnrewardedRelayersState}; +use bp_polkadot_core::PolkadotLike; +use bp_runtime::Chain; +use codec::{Decode, Encode}; +use frame_support::weights::Weight; + +/// Instance of messages pallet that is used to bridge with Rococo chain. +pub type WithRococoMessagesInstance = pallet_bridge_messages::DefaultInstance; + +/// Unchecked Wococo extrinsic. +pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; + +/// Rococo account ownership digest from Wococo. +/// +/// The byte vector returned by this function should be signed with a Rococo account private key. +/// This way, the owner of `wococo_account_id` on Rococo proves that the Rococo account private key +/// is also under his control. +pub fn wococo_to_rococo_account_ownership_digest( + rococo_call: &Call, + wococo_account_id: AccountId, + rococo_spec_version: SpecVersion, +) -> Vec +where + Call: codec::Encode, + AccountId: codec::Encode, + SpecVersion: codec::Encode, +{ + pallet_bridge_dispatch::account_ownership_digest( + rococo_call, + wococo_account_id, + rococo_spec_version, + bp_runtime::WOCOCO_CHAIN_ID, + bp_runtime::ROCOCO_CHAIN_ID, + ) +} + +/// Wococo Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to Rococo chain. +/// Ideally this code would be auto-generated from Metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo +/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +pub enum Call { + /// System pallet. + #[codec(index = 0)] + System(SystemCall), + /// Rococo bridge pallet. + #[codec(index = 40)] + BridgeGrandpaRococo(BridgeGrandpaRococoCall), + /// Rococo messages pallet. + #[codec(index = 43)] + BridgeMessagesRococo(BridgeMessagesRococoCall), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum SystemCall { + #[codec(index = 1)] + remark(Vec), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeGrandpaRococoCall { + #[codec(index = 0)] + submit_finality_proof( + ::Header, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeMessagesRococoCall { + #[codec(index = 3)] + send_message( + LaneId, + bp_message_dispatch::MessagePayload< + bp_rococo::AccountId, + bp_wococo::AccountId, + bp_wococo::AccountPublic, + Vec, + >, + bp_rococo::Balance, + ), + #[codec(index = 5)] + receive_messages_proof( + bp_rococo::AccountId, + bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, + u32, + Weight, + ), + #[codec(index = 6)] + receive_messages_delivery_proof( + bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof, + UnrewardedRelayersState, + ), +} + +impl sp_runtime::traits::Dispatchable for Call { + type Origin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { + unimplemented!("The Call is not expected to be dispatched.") + } +}