From 0f781b9f8156a4380aeaf607542323775a8849c0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 6 Dec 2021 16:46:25 +0300 Subject: [PATCH] Refactor message relay helpers (#1234) * refactor message relay helpers * single standalone_metrics function * fixed tests * clippy + fmt * removed commented code * add calls tracing * fix spelling * cargo fmt * -commented code * fix build again * post-merge build fix * clippy + fmt --- bridges/bin/millau/node/src/service.rs | 7 +- bridges/bin/millau/runtime/src/lib.rs | 25 +- .../bin/millau/runtime/src/rialto_messages.rs | 8 +- bridges/bin/rialto/runtime/src/lib.rs | 25 +- .../bin/rialto/runtime/src/millau_messages.rs | 8 +- bridges/modules/grandpa/src/mock.rs | 7 + bridges/modules/token-swap/src/mock.rs | 7 + bridges/primitives/chain-kusama/src/lib.rs | 4 +- bridges/primitives/chain-millau/src/lib.rs | 36 +- bridges/primitives/chain-polkadot/src/lib.rs | 4 +- .../chain-rialto-parachain/src/lib.rs | 24 +- bridges/primitives/chain-rialto/src/lib.rs | 37 +- bridges/primitives/chain-rococo/src/lib.rs | 4 +- bridges/primitives/chain-wococo/src/lib.rs | 4 +- bridges/primitives/polkadot-core/src/lib.rs | 29 +- bridges/primitives/runtime/src/chain.rs | 7 +- .../relays/bin-substrate/src/chains/kusama.rs | 24 - .../src/chains/kusama_headers_to_polkadot.rs | 4 +- .../src/chains/kusama_messages_to_polkadot.rs | 297 +------- .../relays/bin-substrate/src/chains/millau.rs | 27 +- .../src/chains/millau_messages_to_rialto.rs | 291 +------- .../relays/bin-substrate/src/chains/mod.rs | 13 +- .../bin-substrate/src/chains/polkadot.rs | 24 - .../src/chains/polkadot_headers_to_kusama.rs | 4 +- .../src/chains/polkadot_messages_to_kusama.rs | 296 +------- .../relays/bin-substrate/src/chains/rialto.rs | 27 +- .../src/chains/rialto_messages_to_millau.rs | 290 +------- .../src/chains/rialto_parachain.rs | 10 +- .../relays/bin-substrate/src/chains/rococo.rs | 12 +- .../src/chains/rococo_headers_to_wococo.rs | 4 +- .../src/chains/rococo_messages_to_wococo.rs | 295 +------- .../bin-substrate/src/chains/westend.rs | 5 - .../relays/bin-substrate/src/chains/wococo.rs | 14 +- .../src/chains/wococo_headers_to_rococo.rs | 4 +- .../src/chains/wococo_messages_to_rococo.rs | 293 +------- .../relays/bin-substrate/src/cli/bridge.rs | 12 +- .../bin-substrate/src/cli/encode_call.rs | 3 - bridges/relays/bin-substrate/src/cli/mod.rs | 4 - .../bin-substrate/src/cli/relay_headers.rs | 9 +- .../src/cli/relay_headers_and_messages.rs | 73 +- .../bin-substrate/src/cli/relay_messages.rs | 16 +- .../bin-substrate/src/cli/send_message.rs | 2 +- bridges/relays/client-kusama/src/lib.rs | 39 +- bridges/relays/client-millau/Cargo.toml | 1 + bridges/relays/client-millau/src/lib.rs | 38 +- bridges/relays/client-polkadot/src/lib.rs | 39 +- .../relays/client-rialto-parachain/src/lib.rs | 10 + bridges/relays/client-rialto/Cargo.toml | 1 + bridges/relays/client-rialto/src/lib.rs | 38 +- bridges/relays/client-rococo/src/lib.rs | 39 +- bridges/relays/client-rococo/src/runtime.rs | 4 +- bridges/relays/client-substrate/Cargo.toml | 2 + bridges/relays/client-substrate/src/chain.rs | 54 +- bridges/relays/client-substrate/src/guard.rs | 10 +- bridges/relays/client-substrate/src/lib.rs | 3 +- bridges/relays/client-westend/Cargo.toml | 1 + bridges/relays/client-westend/src/lib.rs | 10 + bridges/relays/client-wococo/src/lib.rs | 39 +- bridges/relays/client-wococo/src/runtime.rs | 4 +- bridges/relays/lib-substrate-relay/Cargo.toml | 1 + .../src/finality_pipeline.rs | 18 +- .../src/finality_target.rs | 15 +- bridges/relays/lib-substrate-relay/src/lib.rs | 10 + .../lib-substrate-relay/src/messages_lane.rs | 673 ++++++++++-------- .../src/messages_metrics.rs | 199 ++++++ .../src/messages_source.rs | 151 ++-- .../src/messages_target.rs | 243 +++---- .../src/on_demand_headers.rs | 8 +- 68 files changed, 1484 insertions(+), 2455 deletions(-) create mode 100644 bridges/relays/lib-substrate-relay/src/messages_metrics.rs diff --git a/bridges/bin/millau/node/src/service.rs b/bridges/bin/millau/node/src/service.rs index b01c0bfca906..36e1b948752a 100644 --- a/bridges/bin/millau/node/src/service.rs +++ b/bridges/bin/millau/node/src/service.rs @@ -66,6 +66,7 @@ type FullClient = type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; +#[allow(clippy::type_complexity)] pub fn new_partial( config: &Configuration, ) -> Result< @@ -89,7 +90,7 @@ pub fn new_partial( ServiceError, > { if config.keystore_remote.is_some() { - return Err(ServiceError::Other(format!("Remote Keystores are not supported."))) + return Err(ServiceError::Other("Remote Keystores are not supported.".into())) } let telemetry = config @@ -111,7 +112,7 @@ pub fn new_partial( let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( - &config, + config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, )?; @@ -178,7 +179,7 @@ pub fn new_partial( }) } -fn remote_keystore(_url: &String) -> Result, &'static str> { +fn remote_keystore(_url: &str) -> Result, &'static str> { // FIXME: here would the concrete keystore be built, // must return a concrete type (NOT `LocalKeystore`) that // implements `CryptoStore` and `SyncCryptoStore` diff --git a/bridges/bin/millau/runtime/src/lib.rs b/bridges/bin/millau/runtime/src/lib.rs index 25cf48b6f707..be186569961d 100644 --- a/bridges/bin/millau/runtime/src/lib.rs +++ b/bridges/bin/millau/runtime/src/lib.rs @@ -407,9 +407,9 @@ impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = - bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; // `IdentityFee` is used by Millau => we may use weight directly pub const GetDeliveryConfirmationTransactionFee: Balance = bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; @@ -875,6 +875,7 @@ where #[cfg(test)] mod tests { use super::*; + use bp_runtime::Chain; use bridge_runtime_common::messages; #[test] @@ -891,30 +892,30 @@ mod tests { ); let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( - messages::target::maximal_incoming_message_size(bp_millau::max_extrinsic_size()), + messages::target::maximal_incoming_message_size(bp_millau::Millau::max_extrinsic_size()), ); pallet_bridge_messages::ensure_able_to_receive_message::( - bp_millau::max_extrinsic_size(), - bp_millau::max_extrinsic_weight(), + bp_millau::Millau::max_extrinsic_size(), + bp_millau::Millau::max_extrinsic_weight(), max_incoming_message_proof_size, messages::target::maximal_incoming_message_dispatch_weight( - bp_millau::max_extrinsic_weight(), + bp_millau::Millau::max_extrinsic_weight(), ), ); let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, - bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, ) .unwrap_or(u32::MAX); pallet_bridge_messages::ensure_able_to_receive_confirmation::( - bp_millau::max_extrinsic_size(), - bp_millau::max_extrinsic_weight(), + bp_millau::Millau::max_extrinsic_size(), + bp_millau::Millau::max_extrinsic_weight(), max_incoming_inbound_lane_data_proof_size, - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, DbWeight::get(), ); } diff --git a/bridges/bin/millau/runtime/src/rialto_messages.rs b/bridges/bin/millau/runtime/src/rialto_messages.rs index 6d9677c45cf9..d46ab4ca042a 100644 --- a/bridges/bin/millau/runtime/src/rialto_messages.rs +++ b/bridges/bin/millau/runtime/src/rialto_messages.rs @@ -23,7 +23,7 @@ use bp_messages::{ target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; +use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; use codec::{Decode, Encode}; use frame_support::{ @@ -86,7 +86,7 @@ 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; - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; type ThisChain = Millau; type BridgedChain = Rialto; @@ -172,13 +172,13 @@ impl messages::ChainWithMessages for Rialto { impl messages::BridgedChainWithMessages for Rialto { fn maximal_extrinsic_size() -> u32 { - bp_rialto::max_extrinsic_size() + bp_rialto::Rialto::max_extrinsic_size() } fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades let upper_limit = messages::target::maximal_incoming_message_dispatch_weight( - bp_rialto::max_extrinsic_weight(), + bp_rialto::Rialto::max_extrinsic_weight(), ); // we're charging for payload bytes in `WithRialtoMessageBridge::transaction_payment` diff --git a/bridges/bin/rialto/runtime/src/lib.rs b/bridges/bin/rialto/runtime/src/lib.rs index 7b9de28aa914..59be1186b409 100644 --- a/bridges/bin/rialto/runtime/src/lib.rs +++ b/bridges/bin/rialto/runtime/src/lib.rs @@ -434,9 +434,9 @@ impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = - bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; // `IdentityFee` is used by Rialto => we may use weight directly pub const GetDeliveryConfirmationTransactionFee: Balance = bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; @@ -1183,6 +1183,7 @@ where #[cfg(test)] mod tests { use super::*; + use bp_runtime::Chain; use bridge_runtime_common::messages; #[test] @@ -1198,30 +1199,30 @@ mod tests { ); let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( - messages::target::maximal_incoming_message_size(bp_rialto::max_extrinsic_size()), + messages::target::maximal_incoming_message_size(bp_rialto::Rialto::max_extrinsic_size()), ); pallet_bridge_messages::ensure_able_to_receive_message::( - bp_rialto::max_extrinsic_size(), - bp_rialto::max_extrinsic_weight(), + bp_rialto::Rialto::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_weight(), max_incoming_message_proof_size, messages::target::maximal_incoming_message_dispatch_weight( - bp_rialto::max_extrinsic_weight(), + bp_rialto::Rialto::max_extrinsic_weight(), ), ); let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, - bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, ) .unwrap_or(u32::MAX); pallet_bridge_messages::ensure_able_to_receive_confirmation::( - bp_rialto::max_extrinsic_size(), - bp_rialto::max_extrinsic_weight(), + bp_rialto::Rialto::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_weight(), max_incoming_inbound_lane_data_proof_size, - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, DbWeight::get(), ); } diff --git a/bridges/bin/rialto/runtime/src/millau_messages.rs b/bridges/bin/rialto/runtime/src/millau_messages.rs index 13a1c6b06ec2..05935c90ea10 100644 --- a/bridges/bin/rialto/runtime/src/millau_messages.rs +++ b/bridges/bin/rialto/runtime/src/millau_messages.rs @@ -23,7 +23,7 @@ use bp_messages::{ target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; +use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; use codec::{Decode, Encode}; use frame_support::{ @@ -86,7 +86,7 @@ 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; - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; type ThisChain = Rialto; type BridgedChain = Millau; @@ -170,13 +170,13 @@ impl messages::ChainWithMessages for Millau { impl messages::BridgedChainWithMessages for Millau { fn maximal_extrinsic_size() -> u32 { - bp_millau::max_extrinsic_size() + bp_millau::Millau::max_extrinsic_size() } fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades let upper_limit = messages::target::maximal_incoming_message_dispatch_weight( - bp_millau::max_extrinsic_weight(), + bp_millau::Millau::max_extrinsic_weight(), ); // we're charging for payload bytes in `WithMillauMessageBridge::transaction_payment` diff --git a/bridges/modules/grandpa/src/mock.rs b/bridges/modules/grandpa/src/mock.rs index f8b5e269323f..37d93df779bf 100644 --- a/bridges/modules/grandpa/src/mock.rs +++ b/bridges/modules/grandpa/src/mock.rs @@ -106,6 +106,13 @@ impl Chain for TestBridgedChain { type Balance = u64; type Index = u64; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + unreachable!() + } + fn max_extrinsic_weight() -> Weight { + unreachable!() + } } pub fn run_test(test: impl FnOnce() -> T) -> T { diff --git a/bridges/modules/token-swap/src/mock.rs b/bridges/modules/token-swap/src/mock.rs index 63edb323e1a4..2c24e282af62 100644 --- a/bridges/modules/token-swap/src/mock.rs +++ b/bridges/modules/token-swap/src/mock.rs @@ -142,6 +142,13 @@ impl bp_runtime::Chain for BridgedChain { type Balance = BridgedBalance; type Index = u64; type Signature = BridgedAccountSignature; + + fn max_extrinsic_size() -> u32 { + unreachable!() + } + fn max_extrinsic_weight() -> Weight { + unreachable!() + } } pub struct TestMessagesBridge; diff --git a/bridges/primitives/chain-kusama/src/lib.rs b/bridges/primitives/chain-kusama/src/lib.rs index f52d03f9f2be..046323aa7009 100644 --- a/bridges/primitives/chain-kusama/src/lib.rs +++ b/bridges/primitives/chain-kusama/src/lib.rs @@ -81,8 +81,8 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 30_000; /// conditions. pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; -/// Name of the With-Polkadot messages pallet instance in the Kusama runtime. -pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; +/// Name of the With-Kusama messages pallet instance that is deployed at bridged chains. +pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; /// Name of the DOT->KSM conversion rate stored in the Kusama runtime. pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str = diff --git a/bridges/primitives/chain-millau/src/lib.rs b/bridges/primitives/chain-millau/src/lib.rs index ba6846702134..4b2b043ed122 100644 --- a/bridges/primitives/chain-millau/src/lib.rs +++ b/bridges/primitives/chain-millau/src/lib.rs @@ -68,11 +68,11 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); -/// Maximal number of unrewarded relayer entries at inbound lane. -pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 1024; +/// Maximal number of unrewarded relayer entries in Millau confirmation transaction. +pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 128; -/// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; +/// Maximal number of unconfirmed messages in Millau confirmation transaction. +pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 128; /// Weight of single regular message delivery transaction on Millau chain. /// @@ -172,6 +172,17 @@ impl Chain for Millau { type Balance = Balance; type Index = Index; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } } /// Millau Hasher (Blake2-256 ++ Keccak-256) implementation. @@ -246,21 +257,12 @@ frame_support::parameter_types! { .build_or_panic(); } -/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. -pub fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) -} +/// Name of the With-Millau messages pallet instance that is deployed at bridged chains. +pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; -/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. -pub fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) -} +/// Name of the Rialto->Millau (actually DOT->KSM) conversion rate stored in the Millau runtime. +pub const RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = "RialtoToMillauConversionRate"; -/// Name of the With-Rialto messages pallet instance in the Millau runtime. -pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages"; /// Name of the With-Rialto token swap pallet instance in the Millau runtime. pub const WITH_RIALTO_TOKEN_SWAP_PALLET_NAME: &str = "BridgeRialtoTokenSwap"; diff --git a/bridges/primitives/chain-polkadot/src/lib.rs b/bridges/primitives/chain-polkadot/src/lib.rs index 36d15ea6e426..6989e6d2b641 100644 --- a/bridges/primitives/chain-polkadot/src/lib.rs +++ b/bridges/primitives/chain-polkadot/src/lib.rs @@ -81,8 +81,8 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 10_000_000_000; /// conditions. pub const SESSION_LENGTH: BlockNumber = 4 * time_units::HOURS; -/// Name of the With-Kusama messages pallet instance in the Polkadot runtime. -pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; +/// Name of the With-Polkadot messages pallet instance that is deployed at bridged chains. +pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; /// Name of the KSM->DOT conversion rate stored in the Polkadot runtime. pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str = diff --git a/bridges/primitives/chain-rialto-parachain/src/lib.rs b/bridges/primitives/chain-rialto-parachain/src/lib.rs index 826f6d39bd7f..786226cf93c9 100644 --- a/bridges/primitives/chain-rialto-parachain/src/lib.rs +++ b/bridges/primitives/chain-rialto-parachain/src/lib.rs @@ -92,6 +92,17 @@ impl Chain for RialtoParachain { type Balance = Balance; type Index = Index; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } } frame_support::parameter_types! { @@ -113,16 +124,3 @@ frame_support::parameter_types! { .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) .build_or_panic(); } - -/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. -pub fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) -} - -/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. -pub fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) -} diff --git a/bridges/primitives/chain-rialto/src/lib.rs b/bridges/primitives/chain-rialto/src/lib.rs index 3a0f7045c088..d994b2f03f63 100644 --- a/bridges/primitives/chain-rialto/src/lib.rs +++ b/bridges/primitives/chain-rialto/src/lib.rs @@ -59,11 +59,11 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); -/// Maximal number of unrewarded relayer entries at inbound lane. -pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; +/// Maximal number of unrewarded relayer entries in Rialto confirmation transaction. +pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; -/// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; +/// Maximal number of unconfirmed messages in Rialto confirmation transaction. +pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 1024; /// Weight of single regular message delivery transaction on Rialto chain. /// @@ -171,6 +171,17 @@ impl Chain for Rialto { type Balance = Balance; type Index = Index; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } } /// Convert a 256-bit hash into an AccountId. @@ -215,21 +226,11 @@ frame_support::parameter_types! { .build_or_panic(); } -/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. -pub fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) -} - -/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. -pub fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) -} +/// Name of the With-Rialto messages pallet instance that is deployed at bridged chains. +pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages"; -/// Name of the With-Millau messages pallet instance in the Rialto runtime. -pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; +/// Name of the Millau->Rialto (actually KSM->DOT) conversion rate stored in the Rialto runtime. +pub const MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME: &str = "MillauToRialtoConversionRate"; /// Name of the parachain registrar pallet in the Rialto runtime. pub const PARAS_REGISTRAR_PALLET_NAME: &str = "Registrar"; diff --git a/bridges/primitives/chain-rococo/src/lib.rs b/bridges/primitives/chain-rococo/src/lib.rs index e5b3647f32bc..aca238358e18 100644 --- a/bridges/primitives/chain-rococo/src/lib.rs +++ b/bridges/primitives/chain-rococo/src/lib.rs @@ -74,8 +74,8 @@ pub fn derive_account_from_wococo_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } -/// Name of the With-Wococo messages pallet instance in the Rococo runtime. -pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; +/// Name of the With-Rococo messages pallet instance that is deployed at bridged chains. +pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; /// Name of the `RococoFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_best_finalized"; diff --git a/bridges/primitives/chain-wococo/src/lib.rs b/bridges/primitives/chain-wococo/src/lib.rs index b16dff388c24..20541d99a6ae 100644 --- a/bridges/primitives/chain-wococo/src/lib.rs +++ b/bridges/primitives/chain-wococo/src/lib.rs @@ -39,8 +39,8 @@ pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } -/// Name of the With-Rococo messages pallet instance in the Wococo runtime. -pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; +/// Name of the With-Wococo messages pallet instance that is deployed at bridged chains. +pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; /// Name of the `WococoFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_best_finalized"; diff --git a/bridges/primitives/polkadot-core/src/lib.rs b/bridges/primitives/polkadot-core/src/lib.rs index 38e43d312b5d..0dc7c54835b9 100644 --- a/bridges/primitives/polkadot-core/src/lib.rs +++ b/bridges/primitives/polkadot-core/src/lib.rs @@ -115,31 +115,17 @@ parameter_types! { .build_or_panic(); } -/// Get the maximum weight (compute time) that a Normal extrinsic on the Polkadot-like chain can -/// use. -pub fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) -} - -/// Get the maximum length in bytes that a Normal extrinsic on the Polkadot-like chain requires. -pub fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) -} - // TODO [#78] may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 /// Maximal number of messages in single delivery transaction. pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; /// Maximal number of unrewarded relayer entries at inbound lane. -pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; +pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 128; // TODO [#438] should be selected keeping in mind: // finality delay on both chains + reward payout cost + messages throughput. /// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; +pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 8192; // One important thing about weight-related constants here is that actually we may have // different weights on different Polkadot-like chains. But now all deployments are @@ -361,6 +347,17 @@ impl Chain for PolkadotLike { type Balance = Balance; type Index = Index; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } } /// Convert a 256-bit hash into an AccountId. diff --git a/bridges/primitives/runtime/src/chain.rs b/bridges/primitives/runtime/src/chain.rs index e963b633b7f5..9dfe6216a7ca 100644 --- a/bridges/primitives/runtime/src/chain.rs +++ b/bridges/primitives/runtime/src/chain.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use frame_support::Parameter; +use frame_support::{weights::Weight, Parameter}; use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero}; use sp_runtime::{ traits::{ @@ -120,6 +120,11 @@ pub trait Chain: Send + Sync + 'static { + Copy; /// Signature type, used on this chain. type Signature: Parameter + Verify; + + /// Get the maximum size (in bytes) of a Normal extrinsic at this chain. + fn max_extrinsic_size() -> u32; + /// Get the maximum weight (compute time) that a Normal extrinsic at this chain can use. + fn max_extrinsic_weight() -> Weight; } /// Block number used by the chain. diff --git a/bridges/relays/bin-substrate/src/chains/kusama.rs b/bridges/relays/bin-substrate/src/chains/kusama.rs index b12d23f2a56d..10afbdd8a5a4 100644 --- a/bridges/relays/bin-substrate/src/chains/kusama.rs +++ b/bridges/relays/bin-substrate/src/chains/kusama.rs @@ -17,8 +17,6 @@ use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_kusama_client::Kusama; -use sp_core::storage::StorageKey; -use sp_runtime::{FixedPointNumber, FixedU128}; use sp_version::RuntimeVersion; use crate::cli::{ @@ -33,14 +31,7 @@ use crate::cli::{ /// 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; -/// Id of Kusama token that is used to fetch token price. -pub(crate) const TOKEN_ID: &str = "kusama"; - impl CliEncodeCall for Kusama { - fn max_extrinsic_size() -> u32 { - bp_kusama::max_extrinsic_size() - } - fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Remark { remark_payload, .. } => relay_kusama_client::runtime::Call::System( @@ -93,24 +84,9 @@ impl CliChain for Kusama { 42 } - fn max_extrinsic_weight() -> Weight { - bp_kusama::max_extrinsic_weight() - } - fn encode_message( _message: encode_message::MessagePayload, ) -> anyhow::Result { anyhow::bail!("Sending messages from Kusama is not yet supported.") } } - -/// Storage key and initial value of Polkadot -> Kusama conversion rate. -pub(crate) fn polkadot_to_kusama_conversion_rate_params() -> (StorageKey, FixedU128) { - ( - bp_runtime::storage_parameter_key( - bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME, - ), - // starting relay before this parameter will be set to some value may cause troubles - FixedU128::from_inner(FixedU128::DIV), - ) -} diff --git a/bridges/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/bridges/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs index afa22aec9e47..c36c336718c0 100644 --- a/bridges/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs +++ b/bridges/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs @@ -17,7 +17,7 @@ //! Kusama-to-Polkadot headers sync entrypoint. use sp_core::Pair; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; +use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -53,7 +53,7 @@ impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot { ); relay_substrate_client::guard::abort_when_account_balance_decreased( target_client.clone(), - transaction_params.transactions_signer.public().into(), + transaction_params.signer.public().into(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } diff --git a/bridges/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/bridges/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs index 32133adc3e54..6a8780a34aad 100644 --- a/bridges/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ b/bridges/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -16,284 +16,49 @@ //! Kusama-to-Polkadot messages sync entrypoint. -use std::ops::RangeInclusive; - use codec::Encode; use frame_support::weights::Weight; use sp_core::{Bytes, Pair}; -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_kusama_client::{ - HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams, -}; -use relay_polkadot_client::{ - HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams, -}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; - -/// Kusama-to-Polkadot message lane. -pub type MessageLaneKusamaMessagesToPolkadot = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct KusamaMessagesToPolkadot { - message_lane: MessageLaneKusamaMessagesToPolkadot, -} +use messages_relay::relay_strategy::MixStrategy; +use relay_kusama_client::Kusama; +use relay_polkadot_client::Polkadot; +use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +/// Description of Kusama -> Polkadot messages bridge. +#[derive(Clone, Debug)] +pub struct KusamaMessagesToPolkadot; +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + KusamaMessagesToPolkadot, + KusamaMessagesToPolkadotReceiveMessagesProofCallBuilder, + relay_polkadot_client::runtime::Call::BridgeKusamaMessages, + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_proof +); +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + KusamaMessagesToPolkadot, + KusamaMessagesToPolkadotReceiveMessagesDeliveryProofCallBuilder, + relay_kusama_client::runtime::Call::BridgePolkadotMessages, + relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof +); impl SubstrateMessageLane for KusamaMessagesToPolkadot { - type MessageLane = MessageLaneKusamaMessagesToPolkadot; - - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_polkadot::TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_polkadot::TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_kusama::FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_kusama::FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_kusama::FROM_KUSAMA_UNREWARDED_RELAYERS_STATE; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = - bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = - bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME); type SourceChain = Kusama; type TargetChain = Polkadot; - fn source_transactions_author(&self) -> bp_kusama::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: KusamaHeaderId, - transaction_nonce: bp_runtime::IndexOf, - _generated_at_block: PolkadotHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call = relay_kusama_client::runtime::Call::BridgePolkadotMessages( - relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof( - proof, - relayers_state, - ), - ); - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Kusama::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Polkadot -> Kusama confirmation transaction. Weight: /{}, size: {}/{}", - bp_kusama::max_extrinsic_weight(), - transaction.encode().len(), - bp_kusama::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } - - fn target_transactions_author(&self) -> bp_polkadot::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } + type SourceTransactionSignScheme = Kusama; + type TargetTransactionSignScheme = Polkadot; - fn make_messages_delivery_transaction( - &self, - best_block_id: PolkadotHeaderId, - transaction_nonce: bp_runtime::IndexOf, - _generated_at_header: KusamaHeaderId, - _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_polkadot_client::runtime::Call::BridgeKusamaMessages( - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_proof( - self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count as _, - dispatch_weight, - ), - ); - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Polkadot::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Kusama -> Polkadot delivery transaction. Weight: /{}, size: {}/{}", - bp_polkadot::max_extrinsic_weight(), - transaction.encode().len(), - bp_polkadot::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Kusama node as messages source. -type KusamaSourceClient = SubstrateMessagesSource; - -/// Polkadot node as messages target. -type PolkadotTargetClient = SubstrateMessagesTarget; - -/// Run Kusama-to-Polkadot messages sync. -pub async fn run( - params: MessagesRelayParams< - Kusama, - KusamaSigningParams, - Polkadot, - PolkadotSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Kusama::AVERAGE_BLOCK_INTERVAL, - Polkadot::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_kusama = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = KusamaMessagesToPolkadot { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_kusama, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_polkadot::max_extrinsic_size() / 3; - // we don't know exact weights of the Polkadot 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::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_polkadot::max_extrinsic_weight(), - bp_polkadot::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 Kusama -> Polkadot messages relay.\n\t\ - Kusama 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: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Kusama::AVERAGE_BLOCK_INTERVAL, - target_tick: Polkadot::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_polkadot::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_polkadot::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - KusamaSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - PolkadotTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} + type ReceiveMessagesProofCallBuilder = KusamaMessagesToPolkadotReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + KusamaMessagesToPolkadotReceiveMessagesDeliveryProofCallBuilder; -/// Create standalone metrics for the Kusama -> Polkadot messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - Some(crate::chains::kusama::TOKEN_ID), - Some(crate::chains::polkadot::TOKEN_ID), - Some(crate::chains::polkadot::kusama_to_polkadot_conversion_rate_params()), - Some(crate::chains::kusama::polkadot_to_kusama_conversion_rate_params()), - ) + type RelayStrategy = MixStrategy; } /// Update Polkadot -> Kusama conversion rate, stored in Kusama runtime storage. diff --git a/bridges/relays/bin-substrate/src/chains/millau.rs b/bridges/relays/bin-substrate/src/chains/millau.rs index 755d7cc4430a..3d599c2e5451 100644 --- a/bridges/relays/bin-substrate/src/chains/millau.rs +++ b/bridges/relays/bin-substrate/src/chains/millau.rs @@ -26,24 +26,11 @@ use crate::cli::{ use anyhow::anyhow; use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; -use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; +use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_millau_client::Millau; -use sp_core::storage::StorageKey; -use sp_runtime::FixedU128; use sp_version::RuntimeVersion; -// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we -// want to test our code that is intended to work with real-value chains. So to keep it close to -// 1:1, we'll be treating Rialto as BTC and Millau as wBTC (only in relayer). - -/// The identifier of token, which value is associated with Millau token value by relayer. -pub(crate) const ASSOCIATED_TOKEN_ID: &str = crate::chains::kusama::TOKEN_ID; - impl CliEncodeCall for Millau { - fn max_extrinsic_size() -> u32 { - bp_millau::max_extrinsic_size() - } - fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Raw { data } => Decode::decode(&mut &*data.0)?, @@ -96,10 +83,6 @@ impl CliChain for Millau { millau_runtime::SS58Prefix::get() as u16 } - fn max_extrinsic_weight() -> Weight { - bp_millau::max_extrinsic_weight() - } - // TODO [#854|#843] support multiple bridges? fn encode_message( message: encode_message::MessagePayload, @@ -132,11 +115,3 @@ impl CliChain for Millau { } } } - -/// Storage key and initial value of Rialto -> Millau conversion rate. -pub(crate) fn rialto_to_millau_conversion_rate_params() -> (StorageKey, FixedU128) { - ( - StorageKey(millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec()), - millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE, - ) -} 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 c4179eea330f..4acc7fdd2ff8 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 @@ -16,279 +16,46 @@ //! Millau-to-Rialto messages sync entrypoint. -use std::ops::RangeInclusive; - use codec::Encode; -use frame_support::dispatch::GetDispatchInfo; use sp_core::{Bytes, Pair}; -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_millau_client::{ - HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams, -}; -use relay_rialto_client::{ - HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams, -}; -use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, +use messages_relay::relay_strategy::MixStrategy; +use relay_millau_client::Millau; +use relay_rialto_client::Rialto; +use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use substrate_relay_helper::messages_lane::{ + DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, + SubstrateMessageLane, }; -/// Millau-to-Rialto message lane. -pub type MessageLaneMillauMessagesToRialto = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct MillauMessagesToRialto { - message_lane: MessageLaneMillauMessagesToRialto, -} +/// Description of Millau -> Rialto messages bridge. +#[derive(Clone, Debug)] +pub struct MillauMessagesToRialto; impl SubstrateMessageLane for MillauMessagesToRialto { - type MessageLane = MessageLaneMillauMessagesToRialto; - - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_rialto::TO_RIALTO_MESSAGE_DETAILS_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; - - 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; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); type SourceChain = Millau; type TargetChain = Rialto; - fn source_transactions_author(&self) -> bp_millau::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: MillauHeaderId, - transaction_nonce: IndexOf, - _generated_at_block: RialtoHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call: millau_runtime::Call = - millau_runtime::MessagesCall::receive_messages_delivery_proof { proof, relayers_state } - .into(); - let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Millau::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Rialto -> Millau confirmation transaction. Weight: {}/{}, size: {}/{}", - call_weight, - bp_millau::max_extrinsic_weight(), - transaction.encode().len(), - bp_millau::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } - - fn target_transactions_author(&self) -> bp_rialto::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } - - fn make_messages_delivery_transaction( - &self, - best_block_id: RialtoHeaderId, - transaction_nonce: IndexOf, - _generated_at_header: MillauHeaderId, - _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: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_proof { - relayer_id_at_bridged_chain: self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count: messages_count as _, - dispatch_weight, - } - .into(); - let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Rialto::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Millau -> Rialto delivery transaction. Weight: {}/{}, size: {}/{}", - call_weight, - bp_rialto::max_extrinsic_weight(), - transaction.encode().len(), - bp_rialto::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Millau node as messages source. -type MillauSourceClient = SubstrateMessagesSource; - -/// Rialto node as messages target. -type RialtoTargetClient = SubstrateMessagesTarget; - -/// Run Millau-to-Rialto messages sync. -pub async fn run( - params: MessagesRelayParams< - Millau, - MillauSigningParams, - Rialto, - RialtoSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Millau::AVERAGE_BLOCK_INTERVAL, - Rialto::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_millau = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = MillauMessagesToRialto { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_millau, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_rialto::max_extrinsic_size() / 3; - // TODO: use Millau weights after https://github.com/paritytech/parity-bridges-common/issues/390 - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_rialto::max_extrinsic_weight(), - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - - log::info!( - target: "bridge", - "Starting Millau -> Rialto messages relay.\n\t\ - Millau 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: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Millau::AVERAGE_BLOCK_INTERVAL, - target_tick: Rialto::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_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - MillauSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - RialtoTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} - -/// Create standalone metrics for the Millau -> Rialto messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - Some(crate::chains::millau::ASSOCIATED_TOKEN_ID), - Some(crate::chains::rialto::ASSOCIATED_TOKEN_ID), - Some(crate::chains::rialto::millau_to_rialto_conversion_rate_params()), - Some(crate::chains::millau::rialto_to_millau_conversion_rate_params()), - ) + type SourceTransactionSignScheme = Millau; + type TargetTransactionSignScheme = Rialto; + + type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< + Self, + rialto_runtime::Runtime, + rialto_runtime::WithMillauMessagesInstance, + >; + type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder< + Self, + millau_runtime::Runtime, + millau_runtime::WithRialtoMessagesInstance, + >; + + type RelayStrategy = MixStrategy; } /// Update Rialto -> Millau conversion rate, stored in Millau runtime storage. diff --git a/bridges/relays/bin-substrate/src/chains/mod.rs b/bridges/relays/bin-substrate/src/chains/mod.rs index 1bc0115b5b05..3f2f5633a03b 100644 --- a/bridges/relays/bin-substrate/src/chains/mod.rs +++ b/bridges/relays/bin-substrate/src/chains/mod.rs @@ -43,6 +43,7 @@ mod wococo; mod tests { use crate::cli::{encode_call, send_message}; use bp_messages::source_chain::TargetHeaderChain; + use bp_runtime::Chain as _; use codec::Encode; use frame_support::dispatch::GetDispatchInfo; use relay_millau_client::Millau; @@ -102,8 +103,8 @@ mod tests { use rialto_runtime::millau_messages::Millau; let maximal_remark_size = encode_call::compute_maximal_message_arguments_size( - bp_rialto::max_extrinsic_size(), - bp_millau::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_size(), + bp_millau::Millau::max_extrinsic_size(), ); let call: millau_runtime::Call = @@ -135,8 +136,8 @@ mod tests { fn maximal_size_remark_to_rialto_is_generated_correctly() { assert!( bridge_runtime_common::messages::target::maximal_incoming_message_size( - bp_rialto::max_extrinsic_size() - ) > bp_millau::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_size() + ) > bp_millau::Millau::max_extrinsic_size(), "We can't actually send maximal messages to Rialto from Millau, because Millau extrinsics can't be that large", ) } @@ -146,7 +147,7 @@ mod tests { use rialto_runtime::millau_messages::Millau; let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( - bp_millau::max_extrinsic_weight(), + bp_millau::Millau::max_extrinsic_weight(), ); let call: millau_runtime::Call = rialto_runtime::SystemCall::remark { remark: vec![] }.into(); @@ -175,7 +176,7 @@ mod tests { use millau_runtime::rialto_messages::Rialto; let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( - bp_rialto::max_extrinsic_weight(), + bp_rialto::Rialto::max_extrinsic_weight(), ); let call: rialto_runtime::Call = millau_runtime::SystemCall::remark { remark: vec![] }.into(); diff --git a/bridges/relays/bin-substrate/src/chains/polkadot.rs b/bridges/relays/bin-substrate/src/chains/polkadot.rs index 7b6256d1749f..8c31792a5430 100644 --- a/bridges/relays/bin-substrate/src/chains/polkadot.rs +++ b/bridges/relays/bin-substrate/src/chains/polkadot.rs @@ -17,8 +17,6 @@ use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_polkadot_client::Polkadot; -use sp_core::storage::StorageKey; -use sp_runtime::{FixedPointNumber, FixedU128}; use sp_version::RuntimeVersion; use crate::cli::{ @@ -33,14 +31,7 @@ use crate::cli::{ /// 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; -/// Id of Polkadot token that is used to fetch token price. -pub(crate) const TOKEN_ID: &str = "polkadot"; - impl CliEncodeCall for Polkadot { - fn max_extrinsic_size() -> u32 { - bp_polkadot::max_extrinsic_size() - } - fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Remark { remark_payload, .. } => relay_polkadot_client::runtime::Call::System( @@ -93,24 +84,9 @@ impl CliChain for Polkadot { 42 } - fn max_extrinsic_weight() -> Weight { - bp_polkadot::max_extrinsic_weight() - } - fn encode_message( _message: encode_message::MessagePayload, ) -> anyhow::Result { anyhow::bail!("Sending messages from Polkadot is not yet supported.") } } - -/// Storage key and initial value of Kusama -> Polkadot conversion rate. -pub(crate) fn kusama_to_polkadot_conversion_rate_params() -> (StorageKey, FixedU128) { - ( - bp_runtime::storage_parameter_key( - bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME, - ), - // starting relay before this parameter will be set to some value may cause troubles - FixedU128::from_inner(FixedU128::DIV), - ) -} diff --git a/bridges/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs b/bridges/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs index 695e0ec3ee6b..5f65d658b90c 100644 --- a/bridges/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs +++ b/bridges/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs @@ -17,7 +17,7 @@ //! Polkadot-to-Kusama headers sync entrypoint. use sp_core::Pair; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; +use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -53,7 +53,7 @@ impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama { ); relay_substrate_client::guard::abort_when_account_balance_decreased( target_client.clone(), - transaction_params.transactions_signer.public().into(), + transaction_params.signer.public().into(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } diff --git a/bridges/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/bridges/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs index bc7f22243092..12ebdde15cb5 100644 --- a/bridges/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ b/bridges/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -16,283 +16,49 @@ //! Polkadot-to-Kusama messages sync entrypoint. -use std::ops::RangeInclusive; - use codec::Encode; use sp_core::{Bytes, Pair}; -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_kusama_client::{ - HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams, -}; -use relay_polkadot_client::{ - HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams, -}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; - -/// Polkadot-to-Kusama message lane. -pub type MessageLanePolkadotMessagesToKusama = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct PolkadotMessagesToKusama { - message_lane: MessageLanePolkadotMessagesToKusama, -} +use messages_relay::relay_strategy::MixStrategy; +use relay_kusama_client::Kusama; +use relay_polkadot_client::Polkadot; +use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +/// Description of Polkadot -> Kusama messages bridge. +#[derive(Clone, Debug)] +pub struct PolkadotMessagesToKusama; +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + PolkadotMessagesToKusama, + PolkadotMessagesToKusamaReceiveMessagesProofCallBuilder, + relay_kusama_client::runtime::Call::BridgePolkadotMessages, + relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_proof +); +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + PolkadotMessagesToKusama, + PolkadotMessagesToKusamaReceiveMessagesDeliveryProofCallBuilder, + relay_polkadot_client::runtime::Call::BridgeKusamaMessages, + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof +); impl SubstrateMessageLane for PolkadotMessagesToKusama { - type MessageLane = MessageLanePolkadotMessagesToKusama; - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_kusama::TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_kusama::TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_polkadot::FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_polkadot::FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_polkadot::FROM_POLKADOT_UNREWARDED_RELAYERS_STATE; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = - bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = - bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME); type SourceChain = Polkadot; type TargetChain = Kusama; - fn source_transactions_author(&self) -> bp_polkadot::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: PolkadotHeaderId, - transaction_nonce: bp_runtime::IndexOf, - _generated_at_block: KusamaHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call = relay_polkadot_client::runtime::Call::BridgeKusamaMessages( - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof( - proof, - relayers_state, - ), - ); - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Polkadot::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Kusama -> Polkadot confirmation transaction. Weight: /{}, size: {}/{}", - bp_polkadot::max_extrinsic_weight(), - transaction.encode().len(), - bp_polkadot::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } - - fn target_transactions_author(&self) -> bp_kusama::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } - - fn make_messages_delivery_transaction( - &self, - best_block_id: KusamaHeaderId, - transaction_nonce: bp_runtime::IndexOf, - _generated_at_header: PolkadotHeaderId, - _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; + type SourceTransactionSignScheme = Polkadot; + type TargetTransactionSignScheme = Kusama; - let call = relay_kusama_client::runtime::Call::BridgePolkadotMessages( - relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_proof( - self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count as _, - dispatch_weight, - ), - ); - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Kusama::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Polkadot -> Kusama delivery transaction. Weight: /{}, size: {}/{}", - bp_kusama::max_extrinsic_weight(), - transaction.encode().len(), - bp_kusama::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Polkadot node as messages source. -type PolkadotSourceClient = SubstrateMessagesSource; - -/// Kusama node as messages target. -type KusamaTargetClient = SubstrateMessagesTarget; - -/// Run Polkadot-to-Kusama messages sync. -pub async fn run( - params: MessagesRelayParams< - Polkadot, - PolkadotSigningParams, - Kusama, - KusamaSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Polkadot::AVERAGE_BLOCK_INTERVAL, - Kusama::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_polkadot = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = PolkadotMessagesToKusama { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_polkadot, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_kusama::max_extrinsic_size() / 3; - // we don't know exact weights of the Kusama 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::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_kusama::max_extrinsic_weight(), - bp_kusama::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 Polkadot -> Kusama messages relay.\n\t\ - Polkadot 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: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Polkadot::AVERAGE_BLOCK_INTERVAL, - target_tick: Kusama::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_kusama::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_kusama::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - PolkadotSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - KusamaTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} + type ReceiveMessagesProofCallBuilder = PolkadotMessagesToKusamaReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + PolkadotMessagesToKusamaReceiveMessagesDeliveryProofCallBuilder; -/// Create standalone metrics for the Polkadot -> Kusama messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - Some(crate::chains::polkadot::TOKEN_ID), - Some(crate::chains::kusama::TOKEN_ID), - Some(crate::chains::kusama::polkadot_to_kusama_conversion_rate_params()), - Some(crate::chains::polkadot::kusama_to_polkadot_conversion_rate_params()), - ) + type RelayStrategy = MixStrategy; } /// Update Kusama -> Polkadot conversion rate, stored in Polkadot runtime storage. diff --git a/bridges/relays/bin-substrate/src/chains/rialto.rs b/bridges/relays/bin-substrate/src/chains/rialto.rs index 2d873a24ba7a..8931c5112da8 100644 --- a/bridges/relays/bin-substrate/src/chains/rialto.rs +++ b/bridges/relays/bin-substrate/src/chains/rialto.rs @@ -26,24 +26,11 @@ use crate::cli::{ use anyhow::anyhow; use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; -use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; +use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_rialto_client::Rialto; -use sp_core::storage::StorageKey; -use sp_runtime::FixedU128; use sp_version::RuntimeVersion; -// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we -// want to test our code that is intended to work with real-value chains. So to keep it close to -// 1:1, we'll be treating Rialto as BTC and Millau as wBTC (only in relayer). - -/// The identifier of token, which value is associated with Rialto token value by relayer. -pub(crate) const ASSOCIATED_TOKEN_ID: &str = crate::chains::polkadot::TOKEN_ID; - impl CliEncodeCall for Rialto { - fn max_extrinsic_size() -> u32 { - bp_rialto::max_extrinsic_size() - } - fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Raw { data } => Decode::decode(&mut &*data.0)?, @@ -96,10 +83,6 @@ impl CliChain for Rialto { rialto_runtime::SS58Prefix::get() as u16 } - fn max_extrinsic_weight() -> Weight { - bp_rialto::max_extrinsic_weight() - } - fn encode_message( message: encode_message::MessagePayload, ) -> anyhow::Result { @@ -131,11 +114,3 @@ impl CliChain for Rialto { } } } - -/// Storage key and initial value of Millau -> Rialto conversion rate. -pub(crate) fn millau_to_rialto_conversion_rate_params() -> (StorageKey, FixedU128) { - ( - StorageKey(rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec()), - rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE, - ) -} 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 774da017df0c..b6e85a7dec79 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 @@ -16,278 +16,46 @@ //! Rialto-to-Millau messages sync entrypoint. -use std::ops::RangeInclusive; - use codec::Encode; -use frame_support::dispatch::GetDispatchInfo; use sp_core::{Bytes, Pair}; -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_millau_client::{ - HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams, -}; -use relay_rialto_client::{ - HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams, -}; -use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, +use messages_relay::relay_strategy::MixStrategy; +use relay_millau_client::Millau; +use relay_rialto_client::Rialto; +use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use substrate_relay_helper::messages_lane::{ + DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, + SubstrateMessageLane, }; -/// Rialto-to-Millau message lane. -pub type MessageLaneRialtoMessagesToMillau = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct RialtoMessagesToMillau { - message_lane: MessageLaneRialtoMessagesToMillau, -} +/// Description of Rialto -> Millau messages bridge. +#[derive(Clone, Debug)] +pub struct RialtoMessagesToMillau; impl SubstrateMessageLane for RialtoMessagesToMillau { - type MessageLane = MessageLaneRialtoMessagesToMillau; - - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME); type SourceChain = Rialto; type TargetChain = Millau; - fn source_transactions_author(&self) -> bp_rialto::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: RialtoHeaderId, - transaction_nonce: IndexOf, - _generated_at_block: MillauHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call: rialto_runtime::Call = - rialto_runtime::MessagesCall::receive_messages_delivery_proof { proof, relayers_state } - .into(); - let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Rialto::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Millau -> Rialto confirmation transaction. Weight: {}/{}, size: {}/{}", - call_weight, - bp_rialto::max_extrinsic_weight(), - transaction.encode().len(), - bp_rialto::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } - - fn target_transactions_author(&self) -> bp_millau::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } - - fn make_messages_delivery_transaction( - &self, - best_block_id: MillauHeaderId, - transaction_nonce: IndexOf, - _generated_at_header: RialtoHeaderId, - _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: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_proof { - relayer_id_at_bridged_chain: self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count: messages_count as _, - dispatch_weight, - } - .into(); - let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Millau::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Rialto -> Millau delivery transaction. Weight: {}/{}, size: {}/{}", - call_weight, - bp_millau::max_extrinsic_weight(), - transaction.encode().len(), - bp_millau::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Rialto node as messages source. -type RialtoSourceClient = SubstrateMessagesSource; - -/// Millau node as messages target. -type MillauTargetClient = SubstrateMessagesTarget; - -/// Run Rialto-to-Millau messages sync. -pub async fn run( - params: MessagesRelayParams< - Rialto, - RialtoSigningParams, - Millau, - MillauSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Rialto::AVERAGE_BLOCK_INTERVAL, - Millau::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_rialto = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = RialtoMessagesToMillau { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_rialto, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_millau::max_extrinsic_size() / 3; - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_millau::max_extrinsic_weight(), - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - - log::info!( - target: "bridge", - "Starting Rialto -> Millau messages relay.\n\t\ - Rialto 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: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Rialto::AVERAGE_BLOCK_INTERVAL, - target_tick: Millau::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_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - RialtoSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - MillauTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} - -/// Create standalone metrics for the Rialto -> Millau messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - Some(crate::chains::rialto::ASSOCIATED_TOKEN_ID), - Some(crate::chains::millau::ASSOCIATED_TOKEN_ID), - Some(crate::chains::millau::rialto_to_millau_conversion_rate_params()), - Some(crate::chains::rialto::millau_to_rialto_conversion_rate_params()), - ) + type SourceTransactionSignScheme = Rialto; + type TargetTransactionSignScheme = Millau; + + type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< + Self, + millau_runtime::Runtime, + millau_runtime::WithRialtoMessagesInstance, + >; + type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder< + Self, + rialto_runtime::Runtime, + rialto_runtime::WithMillauMessagesInstance, + >; + + type RelayStrategy = MixStrategy; } /// Update Millau -> Rialto conversion rate, stored in Rialto runtime storage. diff --git a/bridges/relays/bin-substrate/src/chains/rialto_parachain.rs b/bridges/relays/bin-substrate/src/chains/rialto_parachain.rs index 9adcad223196..da400a4dafd8 100644 --- a/bridges/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/bridges/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -22,15 +22,11 @@ use crate::cli::{ }; use bp_message_dispatch::MessagePayload; use codec::Decode; -use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; +use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_rialto_parachain_client::RialtoParachain; use sp_version::RuntimeVersion; impl CliEncodeCall for RialtoParachain { - fn max_extrinsic_size() -> u32 { - bp_rialto_parachain::max_extrinsic_size() - } - fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Raw { data } => Decode::decode(&mut &*data.0)?, @@ -71,10 +67,6 @@ impl CliChain for RialtoParachain { rialto_parachain_runtime::SS58Prefix::get() as u16 } - fn max_extrinsic_weight() -> Weight { - bp_rialto_parachain::max_extrinsic_weight() - } - fn encode_message( _message: encode_message::MessagePayload, ) -> anyhow::Result { diff --git a/bridges/relays/bin-substrate/src/chains/rococo.rs b/bridges/relays/bin-substrate/src/chains/rococo.rs index 4df60f89faa2..ef49899ec791 100644 --- a/bridges/relays/bin-substrate/src/chains/rococo.rs +++ b/bridges/relays/bin-substrate/src/chains/rococo.rs @@ -33,10 +33,6 @@ use crate::cli::{ 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( @@ -48,8 +44,8 @@ impl CliEncodeCall for Rococo { 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( + relay_rococo_client::runtime::Call::BridgeWococoMessages( + relay_rococo_client::runtime::BridgeWococoMessagesCall::send_message( lane.0, payload, fee.0, ), ) @@ -89,10 +85,6 @@ impl CliChain for Rococo { 42 } - fn max_extrinsic_weight() -> Weight { - bp_wococo::max_extrinsic_weight() - } - fn encode_message( _message: encode_message::MessagePayload, ) -> anyhow::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 0b6608b99bec..d0f1896db89f 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 @@ -19,7 +19,7 @@ use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY; use sp_core::Pair; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; +use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Description of Rococo -> Wococo finalized headers bridge. #[derive(Clone, Debug)] @@ -48,7 +48,7 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { ); relay_substrate_client::guard::abort_when_account_balance_decreased( target_client.clone(), - transaction_params.transactions_signer.public().into(), + transaction_params.signer.public().into(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } 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 index d6c9040e1277..a85789bb1bed 100644 --- a/bridges/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/bridges/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -16,280 +16,41 @@ //! Rococo-to-Wococo messages sync entrypoint. -use std::ops::RangeInclusive; - -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_rococo_client::{ - HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams, -}; -use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_wococo_client::{ - HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo, -}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; - -/// Rococo-to-Wococo message lane. -pub type MessageLaneRococoMessagesToWococo = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct RococoMessagesToWococo { - message_lane: MessageLaneRococoMessagesToWococo, -} +use messages_relay::relay_strategy::MixStrategy; +use relay_rococo_client::Rococo; +use relay_wococo_client::Wococo; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +/// Description of Rococo -> Wococo messages bridge. +#[derive(Clone, Debug)] +pub struct RococoMessagesToWococo; +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + RococoMessagesToWococo, + RococoMessagesToWococoReceiveMessagesProofCallBuilder, + relay_wococo_client::runtime::Call::BridgeRococoMessages, + relay_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_proof +); +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + RococoMessagesToWococo, + RococoMessagesToWococoReceiveMessagesDeliveryProofCallBuilder, + relay_rococo_client::runtime::Call::BridgeWococoMessages, + relay_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_delivery_proof +); impl SubstrateMessageLane for RococoMessagesToWococo { - type MessageLane = MessageLaneRococoMessagesToWococo; - - 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; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; type SourceChain = Rococo; type TargetChain = Wococo; - fn source_transactions_author(&self) -> bp_rococo::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: RococoHeaderId, - transaction_nonce: IndexOf, - _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.message_lane.source_client.genesis_hash(); - let transaction = Rococo::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - 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()) - } + type SourceTransactionSignScheme = Rococo; + type TargetTransactionSignScheme = Wococo; - fn target_transactions_author(&self) -> bp_wococo::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } - - fn make_messages_delivery_transaction( - &self, - best_block_id: WococoHeaderId, - transaction_nonce: IndexOf, - _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.message_lane.relayer_id_at_source.clone(), - proof, - messages_count as _, - dispatch_weight, - ), - ); - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Wococo::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - 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< - Rococo, - RococoSigningParams, - Wococo, - WococoSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Rococo::AVERAGE_BLOCK_INTERVAL, - Wococo::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - 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 target_client = params.target_client; - let lane = RococoMessagesToWococo { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - 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::< - pallet_bridge_messages::weights::RialtoWeight, - >( - 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: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - 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, - relay_strategy: params.relay_strategy, - }, - }, - RococoSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - WococoTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} + type ReceiveMessagesProofCallBuilder = RococoMessagesToWococoReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + RococoMessagesToWococoReceiveMessagesDeliveryProofCallBuilder; -/// Create standalone metrics for the Rococo -> Wococo messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - None, - None, - None, - None, - ) + type RelayStrategy = MixStrategy; } diff --git a/bridges/relays/bin-substrate/src/chains/westend.rs b/bridges/relays/bin-substrate/src/chains/westend.rs index a42e4805512c..5a3dd9956dc9 100644 --- a/bridges/relays/bin-substrate/src/chains/westend.rs +++ b/bridges/relays/bin-substrate/src/chains/westend.rs @@ -18,7 +18,6 @@ use crate::cli::{encode_message, CliChain}; use anyhow::anyhow; -use frame_support::weights::Weight; use relay_westend_client::Westend; use sp_version::RuntimeVersion; @@ -32,10 +31,6 @@ impl CliChain for Westend { 42 } - fn max_extrinsic_weight() -> Weight { - 0 - } - fn encode_message( _message: encode_message::MessagePayload, ) -> anyhow::Result { diff --git a/bridges/relays/bin-substrate/src/chains/wococo.rs b/bridges/relays/bin-substrate/src/chains/wococo.rs index 328397d14ba7..2acc8af48456 100644 --- a/bridges/relays/bin-substrate/src/chains/wococo.rs +++ b/bridges/relays/bin-substrate/src/chains/wococo.rs @@ -16,7 +16,7 @@ use anyhow::anyhow; use codec::Decode; -use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; +use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; use relay_wococo_client::Wococo; use sp_version::RuntimeVersion; @@ -27,10 +27,6 @@ use crate::cli::{ }; 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( @@ -42,8 +38,8 @@ impl CliEncodeCall for Wococo { 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( + relay_wococo_client::runtime::Call::BridgeRococoMessages( + relay_wococo_client::runtime::BridgeRococoMessagesCall::send_message( lane.0, payload, fee.0, ), ) @@ -83,10 +79,6 @@ impl CliChain for Wococo { 42 } - fn max_extrinsic_weight() -> Weight { - bp_wococo::max_extrinsic_weight() - } - fn encode_message( _message: encode_message::MessagePayload, ) -> anyhow::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 276a5b84da30..2d8795fc83dd 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 @@ -17,7 +17,7 @@ //! Wococo-to-Rococo headers sync entrypoint. use sp_core::Pair; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; +use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -53,7 +53,7 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { ); relay_substrate_client::guard::abort_when_account_balance_decreased( target_client.clone(), - transaction_params.transactions_signer.public().into(), + transaction_params.signer.public().into(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } 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 index dcba89e43f05..7c599e413946 100644 --- a/bridges/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/bridges/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -16,279 +16,42 @@ //! Wococo-to-Rococo messages sync entrypoint. -use std::ops::RangeInclusive; - -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_rococo_client::{ - HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams, -}; -use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_wococo_client::{ - HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo, -}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; -/// Wococo-to-Rococo message lane. -pub type MessageLaneWococoMessagesToRococo = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct WococoMessagesToRococo { - message_lane: MessageLaneWococoMessagesToRococo, -} +use messages_relay::relay_strategy::MixStrategy; +use relay_rococo_client::Rococo; +use relay_wococo_client::Wococo; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +/// Description of Wococo -> Rococo messages bridge. +#[derive(Clone, Debug)] +pub struct WococoMessagesToRococo; +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + WococoMessagesToRococo, + WococoMessagesToRococoReceiveMessagesProofCallBuilder, + relay_rococo_client::runtime::Call::BridgeWococoMessages, + relay_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_proof +); +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + WococoMessagesToRococo, + WococoMessagesToRococoReceiveMessagesDeliveryProofCallBuilder, + relay_wococo_client::runtime::Call::BridgeRococoMessages, + relay_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_delivery_proof +); impl SubstrateMessageLane for WococoMessagesToRococo { - type MessageLane = MessageLaneWococoMessagesToRococo; - 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; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; type SourceChain = Wococo; type TargetChain = Rococo; - fn source_transactions_author(&self) -> bp_wococo::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: WococoHeaderId, - transaction_nonce: IndexOf, - _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.message_lane.source_client.genesis_hash(); - let transaction = Wococo::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - 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.message_lane.target_sign.public().as_array_ref()).into() - } + type SourceTransactionSignScheme = Wococo; + type TargetTransactionSignScheme = Rococo; - fn make_messages_delivery_transaction( - &self, - best_block_id: WococoHeaderId, - transaction_nonce: IndexOf, - _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.message_lane.relayer_id_at_source.clone(), - proof, - messages_count as _, - dispatch_weight, - ), - ); - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Rococo::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - 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< - Wococo, - WococoSigningParams, - Rococo, - RococoSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Wococo::AVERAGE_BLOCK_INTERVAL, - Rococo::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - 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 target_client = params.target_client; - let lane = WococoMessagesToRococo { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - 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::< - pallet_bridge_messages::weights::RialtoWeight, - >( - 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: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - 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, - relay_strategy: params.relay_strategy, - }, - }, - WococoSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - RococoTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} + type ReceiveMessagesProofCallBuilder = WococoMessagesToRococoReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + WococoMessagesToRococoReceiveMessagesDeliveryProofCallBuilder; -/// Create standalone metrics for the Wococo -> Rococo messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - None, - None, - None, - None, - ) + type RelayStrategy = MixStrategy; } diff --git a/bridges/relays/bin-substrate/src/cli/bridge.rs b/bridges/relays/bin-substrate/src/cli/bridge.rs index 1af6142c53ec..2eb836a84a75 100644 --- a/bridges/relays/bin-substrate/src/cli/bridge.rs +++ b/bridges/relays/bin-substrate/src/cli/bridge.rs @@ -68,7 +68,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::millau_messages_to_rialto::run as relay_messages; + use crate::chains::millau_messages_to_rialto::MillauMessagesToRialto as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -90,7 +90,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::rialto_messages_to_millau::run as relay_messages; + use crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -113,7 +113,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::rococo_messages_to_wococo::run as relay_messages; + use crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -135,7 +135,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::wococo_messages_to_rococo::run as relay_messages; + use crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -157,7 +157,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::kusama_messages_to_polkadot::run as relay_messages; + use crate::chains::kusama_messages_to_polkadot::KusamaMessagesToPolkadot as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -179,7 +179,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::polkadot_messages_to_kusama::run as relay_messages; + use crate::chains::polkadot_messages_to_kusama::PolkadotMessagesToKusama as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] diff --git a/bridges/relays/bin-substrate/src/cli/encode_call.rs b/bridges/relays/bin-substrate/src/cli/encode_call.rs index e17854662e5c..8be04a88ff75 100644 --- a/bridges/relays/bin-substrate/src/cli/encode_call.rs +++ b/bridges/relays/bin-substrate/src/cli/encode_call.rs @@ -84,9 +84,6 @@ pub enum Call { } pub trait CliEncodeCall: Chain { - /// Maximal size (in bytes) of any extrinsic (from the runtime). - fn max_extrinsic_size() -> u32; - /// Encode a CLI call. fn encode_call(call: &Call) -> anyhow::Result; diff --git a/bridges/relays/bin-substrate/src/cli/mod.rs b/bridges/relays/bin-substrate/src/cli/mod.rs index f1180059b994..ae167334d829 100644 --- a/bridges/relays/bin-substrate/src/cli/mod.rs +++ b/bridges/relays/bin-substrate/src/cli/mod.rs @@ -20,7 +20,6 @@ use std::convert::TryInto; use bp_messages::LaneId; use codec::{Decode, Encode}; -use frame_support::weights::Weight; use sp_runtime::app_crypto::Ss58Codec; use structopt::{clap::arg_enum, StructOpt}; @@ -258,9 +257,6 @@ pub trait CliChain: relay_substrate_client::Chain { fn encode_message( message: crate::cli::encode_message::MessagePayload, ) -> anyhow::Result; - - /// Maximal extrinsic weight (from the runtime). - fn max_extrinsic_weight() -> Weight; } /// Lane id. diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers.rs b/bridges/relays/bin-substrate/src/cli/relay_headers.rs index a8179478f810..43def352a4d1 100644 --- a/bridges/relays/bin-substrate/src/cli/relay_headers.rs +++ b/bridges/relays/bin-substrate/src/cli/relay_headers.rs @@ -125,11 +125,10 @@ impl RelayHeaders { let metrics_params: relay_utils::metrics::MetricsParams = self.prometheus_params.into(); GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; - let target_transactions_params = - substrate_relay_helper::finality_pipeline::TransactionParams { - transactions_signer: target_sign, - transactions_mortality: target_transactions_mortality, - }; + let target_transactions_params = substrate_relay_helper::TransactionParams { + signer: target_sign, + mortality: target_transactions_mortality, + }; Finality::start_relay_guards(&target_client, &target_transactions_params); substrate_relay_helper::finality_pipeline::run::( 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 86b2fbfb4d1b..112d2f419bda 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,7 +35,7 @@ use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use substrate_relay_helper::{ finality_pipeline::SubstrateFinalitySyncPipeline, messages_lane::MessagesRelayParams, - on_demand_headers::OnDemandHeadersRelay, + on_demand_headers::OnDemandHeadersRelay, TransactionParams, }; use crate::{ @@ -139,13 +139,12 @@ macro_rules! select_bridge { use crate::chains::{ millau_messages_to_rialto::{ - run as left_to_right_messages, - standalone_metrics as left_to_right_standalone_metrics, update_rialto_to_millau_conversion_rate as update_right_to_left_conversion_rate, + MillauMessagesToRialto as LeftToRightMessageLane, }, rialto_messages_to_millau::{ - run as right_to_left_messages, update_millau_to_rialto_conversion_rate as update_left_to_right_conversion_rate, + RialtoMessagesToMillau as RightToLeftMessageLane, }, }; @@ -187,11 +186,8 @@ macro_rules! select_bridge { bp_wococo::SESSION_LENGTH; use crate::chains::{ - rococo_messages_to_wococo::{ - run as left_to_right_messages, - standalone_metrics as left_to_right_standalone_metrics, - }, - wococo_messages_to_rococo::run as right_to_left_messages, + rococo_messages_to_wococo::RococoMessagesToWococo as LeftToRightMessageLane, + wococo_messages_to_rococo::WococoMessagesToRococo as RightToLeftMessageLane, }; async fn update_right_to_left_conversion_rate( @@ -269,13 +265,12 @@ macro_rules! select_bridge { use crate::chains::{ kusama_messages_to_polkadot::{ - run as left_to_right_messages, - standalone_metrics as left_to_right_standalone_metrics, update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate, + KusamaMessagesToPolkadot as LeftToRightMessageLane, }, polkadot_messages_to_kusama::{ - run as right_to_left_messages, update_kusama_to_polkadot_conversion_rate as update_left_to_right_conversion_rate, + PolkadotMessagesToKusama as RightToLeftMessageLane, }, }; @@ -358,7 +353,9 @@ impl RelayHeadersAndMessages { let metrics_params: MetricsParams = params.shared.prometheus_params.into(); let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); let left_to_right_metrics = - left_to_right_standalone_metrics(left_client.clone(), right_client.clone())?; + substrate_relay_helper::messages_metrics::standalone_metrics::< + LeftToRightMessageLane, + >(left_client.clone(), right_client.clone())?; let right_to_left_metrics = left_to_right_metrics.clone().reverse(); // start conversion rate update loops for left/right chains @@ -489,16 +486,14 @@ impl RelayHeadersAndMessages { } // start on-demand header relays - let left_to_right_transaction_params = - substrate_relay_helper::finality_pipeline::TransactionParams { - transactions_mortality: right_transactions_mortality, - transactions_signer: right_sign.clone(), - }; - let right_to_left_transaction_params = - substrate_relay_helper::finality_pipeline::TransactionParams { - transactions_mortality: left_transactions_mortality, - transactions_signer: left_sign.clone(), - }; + let left_to_right_transaction_params = TransactionParams { + mortality: right_transactions_mortality, + signer: right_sign.clone(), + }; + let right_to_left_transaction_params = TransactionParams { + mortality: left_transactions_mortality, + signer: left_sign.clone(), + }; LeftToRightFinality::start_relay_guards( &right_client, &left_to_right_transaction_params, @@ -526,13 +521,19 @@ impl RelayHeadersAndMessages { let mut message_relays = Vec::with_capacity(lanes.len() * 2); for lane in lanes { let lane = lane.into(); - let left_to_right_messages = left_to_right_messages(MessagesRelayParams { + let left_to_right_messages = substrate_relay_helper::messages_lane::run::< + LeftToRightMessageLane, + >(MessagesRelayParams { source_client: left_client.clone(), - source_sign: left_sign.clone(), - source_transactions_mortality: left_transactions_mortality, + source_transaction_params: TransactionParams { + signer: left_sign.clone(), + mortality: left_transactions_mortality, + }, target_client: right_client.clone(), - target_sign: right_sign.clone(), - target_transactions_mortality: right_transactions_mortality, + target_transaction_params: TransactionParams { + signer: right_sign.clone(), + mortality: right_transactions_mortality, + }, source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), lane_id: lane, @@ -542,13 +543,19 @@ impl RelayHeadersAndMessages { }) .map_err(|e| anyhow::format_err!("{}", e)) .boxed(); - let right_to_left_messages = right_to_left_messages(MessagesRelayParams { + let right_to_left_messages = substrate_relay_helper::messages_lane::run::< + RightToLeftMessageLane, + >(MessagesRelayParams { source_client: right_client.clone(), - source_sign: right_sign.clone(), - source_transactions_mortality: right_transactions_mortality, + source_transaction_params: TransactionParams { + signer: right_sign.clone(), + mortality: right_transactions_mortality, + }, target_client: left_client.clone(), - target_sign: left_sign.clone(), - target_transactions_mortality: left_transactions_mortality, + target_transaction_params: TransactionParams { + signer: left_sign.clone(), + mortality: left_transactions_mortality, + }, source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), lane_id: lane, diff --git a/bridges/relays/bin-substrate/src/cli/relay_messages.rs b/bridges/relays/bin-substrate/src/cli/relay_messages.rs index e47abfc5d94e..45087fad5eb3 100644 --- a/bridges/relays/bin-substrate/src/cli/relay_messages.rs +++ b/bridges/relays/bin-substrate/src/cli/relay_messages.rs @@ -18,7 +18,7 @@ use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use messages_relay::relay_strategy::MixStrategy; -use substrate_relay_helper::messages_lane::MessagesRelayParams; +use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams}; use crate::{ cli::{ @@ -84,13 +84,17 @@ impl RelayMessages { let relayer_mode = self.relayer_mode.into(); let relay_strategy = MixStrategy::new(relayer_mode); - relay_messages(MessagesRelayParams { + substrate_relay_helper::messages_lane::run::(MessagesRelayParams { source_client, - source_sign, - source_transactions_mortality, + source_transaction_params: TransactionParams { + signer: source_sign, + mortality: source_transactions_mortality, + }, target_client, - target_sign, - target_transactions_mortality, + target_transaction_params: TransactionParams { + signer: target_sign, + mortality: target_transactions_mortality, + }, source_to_target_headers_relay: None, target_to_source_headers_relay: None, lane_id: self.lane.into(), diff --git a/bridges/relays/bin-substrate/src/cli/send_message.rs b/bridges/relays/bin-substrate/src/cli/send_message.rs index 3e77ad834292..5c403f6c23a9 100644 --- a/bridges/relays/bin-substrate/src/cli/send_message.rs +++ b/bridges/relays/bin-substrate/src/cli/send_message.rs @@ -22,7 +22,7 @@ use crate::cli::{ SourceSigningParams, TargetSigningParams, }; use bp_message_dispatch::{CallOrigin, MessagePayload}; -use bp_runtime::BalanceOf; +use bp_runtime::{BalanceOf, Chain as _}; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{Chain, TransactionSignScheme, UnsignedTransaction}; diff --git a/bridges/relays/client-kusama/src/lib.rs b/bridges/relays/client-kusama/src/lib.rs index b1ea0f5fefbf..861816bb6739 100644 --- a/bridges/relays/client-kusama/src/lib.rs +++ b/bridges/relays/client-kusama/src/lib.rs @@ -16,10 +16,12 @@ //! Types used to connect to the Kusama chain. +use bp_messages::MessageNonce; use codec::Encode; +use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -44,10 +46,19 @@ impl ChainBase for Kusama { type Balance = bp_kusama::Balance; type Index = bp_kusama::Nonce; type Signature = bp_kusama::Signature; + + fn max_extrinsic_size() -> u32 { + bp_kusama::Kusama::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_kusama::Kusama::max_extrinsic_weight() + } } impl Chain for Kusama { const NAME: &'static str = "Kusama"; + const TOKEN_ID: Option<&'static str> = Some("kusama"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); @@ -59,6 +70,30 @@ impl Chain for Kusama { type WeightToFee = bp_kusama::WeightToFee; } +impl ChainWithMessages for Kusama { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_kusama::WITH_KUSAMA_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_kusama::TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD; + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_kusama::TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_kusama::FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_kusama::FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD; + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = + bp_kusama::FROM_KUSAMA_UNREWARDED_RELAYERS_STATE; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Kusama { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_kusama::account_info_storage_key(account_id)) diff --git a/bridges/relays/client-millau/Cargo.toml b/bridges/relays/client-millau/Cargo.toml index 49d9dade154c..da3d4e7fe1d6 100644 --- a/bridges/relays/client-millau/Cargo.toml +++ b/bridges/relays/client-millau/Cargo.toml @@ -12,6 +12,7 @@ relay-utils = { path = "../utils" } # Supported Chains +bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } millau-runtime = { path = "../../bin/millau/runtime" } diff --git a/bridges/relays/client-millau/src/lib.rs b/bridges/relays/client-millau/src/lib.rs index e7ee54afb084..96a046ef5cdc 100644 --- a/bridges/relays/client-millau/src/lib.rs +++ b/bridges/relays/client-millau/src/lib.rs @@ -16,9 +16,11 @@ //! Types used to connect to the Millau-Substrate chain. +use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; +use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithMessages, IndexOf, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; @@ -42,10 +44,44 @@ impl ChainBase for Millau { type Balance = millau_runtime::Balance; type Index = millau_runtime::Index; type Signature = millau_runtime::Signature; + + fn max_extrinsic_size() -> u32 { + bp_millau::Millau::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_millau::Millau::max_extrinsic_weight() + } +} + +impl ChainWithMessages for Millau { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD; + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD; + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = + bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); } impl Chain for Millau { const NAME: &'static str = "Millau"; + // Rialto token has no value, but we associate it with KSM token + const TOKEN_ID: Option<&'static str> = Some("kusama"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); diff --git a/bridges/relays/client-polkadot/src/lib.rs b/bridges/relays/client-polkadot/src/lib.rs index e5c7f62fa172..d468206f9d5e 100644 --- a/bridges/relays/client-polkadot/src/lib.rs +++ b/bridges/relays/client-polkadot/src/lib.rs @@ -16,10 +16,12 @@ //! Types used to connect to the Polkadot chain. +use bp_messages::MessageNonce; use codec::Encode; +use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -44,10 +46,19 @@ impl ChainBase for Polkadot { type Balance = bp_polkadot::Balance; type Index = bp_polkadot::Nonce; type Signature = bp_polkadot::Signature; + + fn max_extrinsic_size() -> u32 { + bp_polkadot::Polkadot::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_polkadot::Polkadot::max_extrinsic_weight() + } } impl Chain for Polkadot { const NAME: &'static str = "Polkadot"; + const TOKEN_ID: Option<&'static str> = Some("polkadot"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); @@ -59,6 +70,30 @@ impl Chain for Polkadot { type WeightToFee = bp_polkadot::WeightToFee; } +impl ChainWithMessages for Polkadot { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_polkadot::WITH_POLKADOT_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_polkadot::TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD; + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_polkadot::TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_polkadot::FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_polkadot::FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD; + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = + bp_polkadot::FROM_POLKADOT_UNREWARDED_RELAYERS_STATE; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Polkadot { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_polkadot::account_info_storage_key(account_id)) diff --git a/bridges/relays/client-rialto-parachain/src/lib.rs b/bridges/relays/client-rialto-parachain/src/lib.rs index b34154393a1b..65bf46f660cc 100644 --- a/bridges/relays/client-rialto-parachain/src/lib.rs +++ b/bridges/relays/client-rialto-parachain/src/lib.rs @@ -16,6 +16,7 @@ //! Types used to connect to the Rialto-Substrate chain. +use frame_support::weights::Weight; use relay_substrate_client::{Chain, ChainBase}; use std::time::Duration; @@ -37,10 +38,19 @@ impl ChainBase for RialtoParachain { type Balance = rialto_parachain_runtime::Balance; type Index = rialto_parachain_runtime::Index; type Signature = rialto_parachain_runtime::Signature; + + fn max_extrinsic_size() -> u32 { + bp_rialto::Rialto::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_rialto::Rialto::max_extrinsic_weight() + } } impl Chain for RialtoParachain { const NAME: &'static str = "RialtoParachain"; + const TOKEN_ID: Option<&'static str> = None; // should be fixed/changed in https://github.com/paritytech/parity-bridges-common/pull/1199 const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = ""; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); diff --git a/bridges/relays/client-rialto/Cargo.toml b/bridges/relays/client-rialto/Cargo.toml index 3132b26d27fc..483812ca8088 100644 --- a/bridges/relays/client-rialto/Cargo.toml +++ b/bridges/relays/client-rialto/Cargo.toml @@ -12,6 +12,7 @@ relay-utils = { path = "../utils" } # Bridge dependencies +bp-messages = { path = "../../primitives/messages" } bp-rialto = { path = "../../primitives/chain-rialto" } rialto-runtime = { path = "../../bin/rialto/runtime" } diff --git a/bridges/relays/client-rialto/src/lib.rs b/bridges/relays/client-rialto/src/lib.rs index 60c6e9388b69..80e3c2c7ae74 100644 --- a/bridges/relays/client-rialto/src/lib.rs +++ b/bridges/relays/client-rialto/src/lib.rs @@ -16,9 +16,11 @@ //! Types used to connect to the Rialto-Substrate chain. +use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; +use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithMessages, IndexOf, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; @@ -42,10 +44,20 @@ impl ChainBase for Rialto { type Balance = rialto_runtime::Balance; type Index = rialto_runtime::Index; type Signature = rialto_runtime::Signature; + + fn max_extrinsic_size() -> u32 { + bp_rialto::Rialto::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_rialto::Rialto::max_extrinsic_weight() + } } impl Chain for Rialto { const NAME: &'static str = "Rialto"; + // Rialto token has no value, but we associate it with DOT token + const TOKEN_ID: Option<&'static str> = Some("polkadot"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); @@ -57,6 +69,30 @@ impl Chain for Rialto { type WeightToFee = bp_rialto::WeightToFee; } +impl ChainWithMessages for Rialto { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD; + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD; + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = + bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Rialto { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { use frame_support::storage::generator::StorageMap; diff --git a/bridges/relays/client-rococo/src/lib.rs b/bridges/relays/client-rococo/src/lib.rs index 7ee51730e996..ee17e62dcd71 100644 --- a/bridges/relays/client-rococo/src/lib.rs +++ b/bridges/relays/client-rococo/src/lib.rs @@ -16,10 +16,12 @@ //! Types used to connect to the Rococo-Substrate chain. +use bp_messages::MessageNonce; use codec::Encode; +use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -47,10 +49,19 @@ impl ChainBase for Rococo { type Balance = bp_rococo::Balance; type Index = bp_rococo::Nonce; type Signature = bp_rococo::Signature; + + fn max_extrinsic_size() -> u32 { + bp_rococo::Rococo::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_rococo::Rococo::max_extrinsic_weight() + } } impl Chain for Rococo { const NAME: &'static str = "Rococo"; + const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); @@ -62,6 +73,30 @@ impl Chain for Rococo { type WeightToFee = bp_rococo::WeightToFee; } +impl ChainWithMessages for Rococo { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD; + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_rococo::TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_rococo::FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_rococo::FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD; + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = + bp_rococo::FROM_ROCOCO_UNREWARDED_RELAYERS_STATE; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Rococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_rococo::account_info_storage_key(account_id)) diff --git a/bridges/relays/client-rococo/src/runtime.rs b/bridges/relays/client-rococo/src/runtime.rs index df69b0a6a9c3..b13808059964 100644 --- a/bridges/relays/client-rococo/src/runtime.rs +++ b/bridges/relays/client-rococo/src/runtime.rs @@ -74,7 +74,7 @@ pub enum Call { BridgeGrandpaWococo(BridgeGrandpaWococoCall), /// Wococo messages pallet. #[codec(index = 44)] - BridgeMessagesWococo(BridgeMessagesWococoCall), + BridgeWococoMessages(BridgeWococoMessagesCall), } #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] @@ -105,7 +105,7 @@ pub enum BridgeGrandpaWococoCall { #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] -pub enum BridgeMessagesWococoCall { +pub enum BridgeWococoMessagesCall { #[codec(index = 3)] send_message( LaneId, diff --git a/bridges/relays/client-substrate/Cargo.toml b/bridges/relays/client-substrate/Cargo.toml index 2eb07fdcde46..eacaa929a94d 100644 --- a/bridges/relays/client-substrate/Cargo.toml +++ b/bridges/relays/client-substrate/Cargo.toml @@ -20,7 +20,9 @@ thiserror = "1.0.26" # Bridge dependencies bp-header-chain = { path = "../../primitives/header-chain" } +bp-messages = { path = "../../primitives/messages" } bp-runtime = { path = "../../primitives/runtime" } +pallet-bridge-messages = { path = "../../modules/messages" } finality-relay = { path = "../finality" } relay-utils = { path = "../utils" } diff --git a/bridges/relays/client-substrate/src/chain.rs b/bridges/relays/client-substrate/src/chain.rs index 97063c15c860..6b62e699b7ef 100644 --- a/bridges/relays/client-substrate/src/chain.rs +++ b/bridges/relays/client-substrate/src/chain.rs @@ -14,9 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use bp_messages::MessageNonce; use bp_runtime::{Chain as ChainBase, HashOf, TransactionEraOf}; use codec::{Codec, Encode}; -use frame_support::weights::WeightToFeePolynomial; +use frame_support::weights::{Weight, WeightToFeePolynomial}; use jsonrpsee_ws_client::types::{DeserializeOwned, Serialize}; use num_traits::Zero; use sc_transaction_pool_api::TransactionStatus; @@ -32,6 +33,11 @@ use std::{fmt::Debug, time::Duration}; pub trait Chain: ChainBase + Clone { /// Chain name. const NAME: &'static str; + /// Identifier of the basic token of the chain (if applicable). + /// + /// This identifier is used to fetch token price. In case of testnets, you may either + /// set it to `None`, or associate testnet with one of the existing tokens. + const TOKEN_ID: Option<&'static str>; /// Name of the runtime API method that is returning best known finalized header number /// and hash (as tuple). /// @@ -52,12 +58,56 @@ pub trait Chain: ChainBase + Clone { /// Block type. type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. - type Call: Clone + Dispatchable + Debug + Send; + type Call: Clone + Codec + Dispatchable + Debug + Send; /// Type that is used by the chain, to convert from weight to fee. type WeightToFee: WeightToFeePolynomial; } +/// Substrate-based chain with messaging support from minimal relay-client point of view. +pub trait ChainWithMessages: Chain { + /// Name of the bridge messages pallet (used in `construct_runtime` macro call) that is deployed + /// at some other chain to bridge with this `ChainWithMessages`. + /// + /// We assume that all chains that are bridging with this `ChainWithMessages` are using + /// the same name. + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str; + + /// Name of the `ToOutboundLaneApi::message_details` runtime API method. + /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str; + /// Name of the `ToOutboundLaneApi::latest_generated_nonce` runtime API + /// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`. + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str; + /// Name of the `ToOutboundLaneApi::latest_received_nonce` runtime API + /// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`. + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str; + + /// Name of the `FromInboundLaneApi::latest_received_nonce` runtime method. + /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str; + /// Name of the `FromInboundLaneApi::latest_confirmed_nonce` runtime method. + /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str; + /// Name of the `FromInboundLaneApi::unrewarded_relayers_state` runtime + /// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`. + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str; + + /// Additional weight of the dispatch fee payment if dispatch is paid at the target chain + /// and this `ChainWithMessages` is the target chain. + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight; + + /// Maximal number of unrewarded relayers in a single confirmation transaction at this + /// `ChainWithMessages`. + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce; + /// Maximal number of unconfirmed messages in a single confirmation transaction at this + /// `ChainWithMessages`. + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce; + + /// Weights of message pallet calls. + type WeightInfo: pallet_bridge_messages::WeightInfoExt; +} + /// Call type used by the chain. pub type CallOf = ::Call; /// Weight-to-Fee type used by the chain. diff --git a/bridges/relays/client-substrate/src/guard.rs b/bridges/relays/client-substrate/src/guard.rs index 93b76bdf9f07..c31482eec396 100644 --- a/bridges/relays/client-substrate/src/guard.rs +++ b/bridges/relays/client-substrate/src/guard.rs @@ -181,7 +181,7 @@ impl Environment for Client { #[cfg(test)] mod tests { use super::*; - use frame_support::weights::IdentityFee; + use frame_support::weights::{IdentityFee, Weight}; use futures::{ channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, future::FutureExt, @@ -202,10 +202,18 @@ mod tests { type Balance = u32; type Index = u32; type Signature = sp_runtime::testing::TestSignature; + + fn max_extrinsic_size() -> u32 { + unreachable!() + } + fn max_extrinsic_weight() -> Weight { + unreachable!() + } } impl Chain for TestChain { const NAME: &'static str = "Test"; + const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "BestTestHeader"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1); const STORAGE_PROOF_OVERHEAD: u32 = 0; diff --git a/bridges/relays/client-substrate/src/lib.rs b/bridges/relays/client-substrate/src/lib.rs index f03b79228bf0..56a6c981fcb1 100644 --- a/bridges/relays/client-substrate/src/lib.rs +++ b/bridges/relays/client-substrate/src/lib.rs @@ -32,7 +32,8 @@ use std::time::Duration; pub use crate::{ chain::{ AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, - TransactionSignScheme, TransactionStatusOf, UnsignedTransaction, WeightToFeeOf, + ChainWithMessages, TransactionSignScheme, TransactionStatusOf, UnsignedTransaction, + WeightToFeeOf, }, client::{Client, OpaqueGrandpaAuthoritiesSet, Subscription}, error::{Error, Result}, diff --git a/bridges/relays/client-westend/Cargo.toml b/bridges/relays/client-westend/Cargo.toml index 24b05c4f4836..9bbb0b6fb13f 100644 --- a/bridges/relays/client-westend/Cargo.toml +++ b/bridges/relays/client-westend/Cargo.toml @@ -16,5 +16,6 @@ bp-westend = { path = "../../primitives/chain-westend" } # Substrate Dependencies +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bridges/relays/client-westend/src/lib.rs b/bridges/relays/client-westend/src/lib.rs index 6d43aa837b29..004cb5476be7 100644 --- a/bridges/relays/client-westend/src/lib.rs +++ b/bridges/relays/client-westend/src/lib.rs @@ -16,6 +16,7 @@ //! Types used to connect to the Westend chain. +use frame_support::weights::Weight; use relay_substrate_client::{Chain, ChainBase, ChainWithBalances}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -40,10 +41,19 @@ impl ChainBase for Westend { type Balance = bp_westend::Balance; type Index = bp_westend::Nonce; type Signature = bp_westend::Signature; + + fn max_extrinsic_size() -> u32 { + bp_westend::Westend::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_westend::Westend::max_extrinsic_weight() + } } impl Chain for Westend { const NAME: &'static str = "Westend"; + const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); diff --git a/bridges/relays/client-wococo/src/lib.rs b/bridges/relays/client-wococo/src/lib.rs index a15ff469991b..e9bdfd834a91 100644 --- a/bridges/relays/client-wococo/src/lib.rs +++ b/bridges/relays/client-wococo/src/lib.rs @@ -16,10 +16,12 @@ //! Types used to connect to the Wococo-Substrate chain. +use bp_messages::MessageNonce; use codec::Encode; +use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -47,10 +49,19 @@ impl ChainBase for Wococo { type Balance = bp_wococo::Balance; type Index = bp_wococo::Nonce; type Signature = bp_wococo::Signature; + + fn max_extrinsic_size() -> u32 { + bp_wococo::Wococo::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_wococo::Wococo::max_extrinsic_weight() + } } impl Chain for Wococo { const NAME: &'static str = "Wococo"; + const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); @@ -62,6 +73,30 @@ impl Chain for Wococo { type WeightToFee = bp_wococo::WeightToFee; } +impl ChainWithMessages for Wococo { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_wococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD; + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_wococo::TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_wococo::FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_wococo::FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD; + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = + bp_wococo::FROM_WOCOCO_UNREWARDED_RELAYERS_STATE; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_wococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_wococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Wococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_wococo::account_info_storage_key(account_id)) diff --git a/bridges/relays/client-wococo/src/runtime.rs b/bridges/relays/client-wococo/src/runtime.rs index 38a40abd2120..b28e053086b1 100644 --- a/bridges/relays/client-wococo/src/runtime.rs +++ b/bridges/relays/client-wococo/src/runtime.rs @@ -74,7 +74,7 @@ pub enum Call { BridgeGrandpaRococo(BridgeGrandpaRococoCall), /// Rococo messages pallet. #[codec(index = 43)] - BridgeMessagesRococo(BridgeMessagesRococoCall), + BridgeRococoMessages(BridgeRococoMessagesCall), } #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] @@ -105,7 +105,7 @@ pub enum BridgeGrandpaRococoCall { #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] -pub enum BridgeMessagesRococoCall { +pub enum BridgeRococoMessagesCall { #[codec(index = 3)] send_message( LaneId, diff --git a/bridges/relays/lib-substrate-relay/Cargo.toml b/bridges/relays/lib-substrate-relay/Cargo.toml index 89d03803b35f..1224d8143938 100644 --- a/bridges/relays/lib-substrate-relay/Cargo.toml +++ b/bridges/relays/lib-substrate-relay/Cargo.toml @@ -42,6 +42,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master [dev-dependencies] bp-millau = { path = "../../primitives/chain-millau" } +bp-rialto = { path = "../../primitives/chain-rialto" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-wococo = { path = "../../primitives/chain-wococo" } relay-rococo-client = { path = "../client-rococo" } diff --git a/bridges/relays/lib-substrate-relay/src/finality_pipeline.rs b/bridges/relays/lib-substrate-relay/src/finality_pipeline.rs index 1266ed59ed00..87e50be03932 100644 --- a/bridges/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/bridges/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -17,7 +17,10 @@ //! Types and functions intended to ease adding of new Substrate -> Substrate //! finality proofs synchronization pipelines. -use crate::{finality_source::SubstrateFinalitySource, finality_target::SubstrateFinalityTarget}; +use crate::{ + finality_source::SubstrateFinalitySource, finality_target::SubstrateFinalityTarget, + TransactionParams, +}; use bp_header_chain::justification::GrandpaJustification; use finality_relay::FinalitySyncPipeline; @@ -36,15 +39,6 @@ use std::{fmt::Debug, marker::PhantomData}; /// Substrate+GRANDPA based chains (good to know). pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; -/// Submit-finality-proofs transaction creation parameters. -#[derive(Clone, Debug)] -pub struct TransactionParams { - /// Transactions author. - pub transactions_signer: TS, - /// Transactions mortality. - pub transactions_mortality: Option, -} - /// Substrate -> Substrate finality proofs synchronization pipeline. pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { /// Headers of this chain are submitted to the `TargetChain`. @@ -67,7 +61,7 @@ pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { /// Adapter that allows all `SubstrateFinalitySyncPipeline` to act as `FinalitySyncPipeline`. #[derive(Clone, Debug)] -pub struct FinalitySyncPipelineAdapter { +pub(crate) struct FinalitySyncPipelineAdapter { _phantom: PhantomData

, } @@ -179,7 +173,7 @@ where ), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, stall_timeout: transaction_stall_timeout( - transaction_params.transactions_mortality, + transaction_params.mortality, P::TargetChain::AVERAGE_BLOCK_INTERVAL, crate::STALL_TIMEOUT, ), diff --git a/bridges/relays/lib-substrate-relay/src/finality_target.rs b/bridges/relays/lib-substrate-relay/src/finality_target.rs index adfe12ab35b8..5daf6c7538a3 100644 --- a/bridges/relays/lib-substrate-relay/src/finality_target.rs +++ b/bridges/relays/lib-substrate-relay/src/finality_target.rs @@ -18,8 +18,10 @@ //! bridge GRANDPA pallet deployed and provide `FinalityApi` to allow bridging //! with chain. -use crate::finality_pipeline::{ - FinalitySyncPipelineAdapter, SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, +use crate::{ + finality_pipeline::{ + FinalitySyncPipelineAdapter, SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, + }, TransactionParams, }; @@ -103,16 +105,13 @@ where P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); self.client .submit_signed_extrinsic( - self.transaction_params.transactions_signer.public().into(), + self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { Bytes( P::TransactionSignScheme::sign_transaction( genesis_hash, - &transaction_params.transactions_signer, - TransactionEra::new( - best_block_id, - transaction_params.transactions_mortality, - ), + &transaction_params.signer, + TransactionEra::new(best_block_id, transaction_params.mortality), UnsignedTransaction::new(call, transaction_nonce), ) .encode(), diff --git a/bridges/relays/lib-substrate-relay/src/lib.rs b/bridges/relays/lib-substrate-relay/src/lib.rs index 1c62ddaa9a7e..c27aa7b708fd 100644 --- a/bridges/relays/lib-substrate-relay/src/lib.rs +++ b/bridges/relays/lib-substrate-relay/src/lib.rs @@ -28,6 +28,7 @@ pub mod finality_target; pub mod headers_initialize; pub mod helpers; pub mod messages_lane; +pub mod messages_metrics; pub mod messages_source; pub mod messages_target; pub mod on_demand_headers; @@ -40,3 +41,12 @@ pub mod on_demand_headers; /// blockchains) blocks. So 1 hour seems to be a good guess for (even congested) chains to mine /// transaction, or remove it from the pool. pub const STALL_TIMEOUT: Duration = Duration::from_secs(60 * 60); + +/// Transaction creation parameters. +#[derive(Clone, Debug)] +pub struct TransactionParams { + /// Transactions author. + pub signer: TS, + /// Transactions mortality. + pub mortality: Option, +} diff --git a/bridges/relays/lib-substrate-relay/src/messages_lane.rs b/bridges/relays/lib-substrate-relay/src/messages_lane.rs index 6cadb64754a5..4742ce6e4829 100644 --- a/bridges/relays/lib-substrate-relay/src/messages_lane.rs +++ b/bridges/relays/lib-substrate-relay/src/messages_lane.rs @@ -17,194 +17,396 @@ //! Tools for supporting message lanes between two Substrate-based chains. use crate::{ - messages_source::SubstrateMessagesProof, messages_target::SubstrateMessagesReceivingProof, + messages_metrics::StandaloneMessagesMetrics, + messages_source::{SubstrateMessagesProof, SubstrateMessagesSource}, + messages_target::{SubstrateMessagesDeliveryProof, SubstrateMessagesTarget}, on_demand_headers::OnDemandHeadersRelay, + TransactionParams, STALL_TIMEOUT, }; -use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{AccountIdOf, IndexOf}; -use frame_support::weights::Weight; -use messages_relay::{ - message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, - relay_strategy::RelayStrategy, +use bp_runtime::{AccountIdOf, Chain as _}; +use bridge_runtime_common::messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; +use codec::Encode; +use frame_support::weights::{GetDispatchInfo, Weight}; +use messages_relay::{message_lane::MessageLane, relay_strategy::RelayStrategy}; +use pallet_bridge_messages::{Call as BridgeMessagesCall, Config as BridgeMessagesConfig}; use relay_substrate_client::{ - metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, - BlockNumberOf, Chain, Client, HashOf, + AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithMessages, Client, HashOf, + TransactionSignScheme, }; -use relay_utils::{ - metrics::{ - FloatJsonValueMetric, GlobalMetrics, MetricsParams, PrometheusError, StandaloneMetric, - }, - BlockNumberBase, -}; -use sp_core::{storage::StorageKey, Bytes}; -use sp_runtime::FixedU128; -use std::ops::RangeInclusive; +use relay_utils::metrics::MetricsParams; +use sp_core::Pair; +use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; + +/// Substrate -> Substrate messages synchronization pipeline. +pub trait SubstrateMessageLane: 'static + Clone + Debug + Send + Sync { + /// Name of the source -> target tokens conversion rate parameter name. + /// + /// The parameter is stored at the target chain and the storage key is computed using + /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed + /// to be 1. + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str>; + /// Name of the target -> source tokens conversion rate parameter name. + /// + /// The parameter is stored at the source chain and the storage key is computed using + /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed + /// to be 1. + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str>; + + /// Messages of this chain are relayed to the `TargetChain`. + type SourceChain: ChainWithMessages; + /// Messages from the `SourceChain` are dispatched on this chain. + type TargetChain: ChainWithMessages; + + /// Scheme used to sign source chain transactions. + type SourceTransactionSignScheme: TransactionSignScheme; + /// Scheme used to sign target chain transactions. + type TargetTransactionSignScheme: TransactionSignScheme; + + /// How receive messages proof call is built? + type ReceiveMessagesProofCallBuilder: ReceiveMessagesProofCallBuilder; + /// How receive messages delivery proof call is built? + type ReceiveMessagesDeliveryProofCallBuilder: ReceiveMessagesDeliveryProofCallBuilder; + + /// Message relay strategy. + type RelayStrategy: RelayStrategy; +} + +/// Adapter that allows all `SubstrateMessageLane` to act as `MessageLane`. +#[derive(Clone, Debug)] +pub(crate) struct MessageLaneAdapter { + _phantom: PhantomData

, +} + +impl MessageLane for MessageLaneAdapter

{ + const SOURCE_NAME: &'static str = P::SourceChain::NAME; + const TARGET_NAME: &'static str = P::TargetChain::NAME; + + type MessagesProof = SubstrateMessagesProof; + type MessagesReceivingProof = SubstrateMessagesDeliveryProof; + + type SourceChainBalance = BalanceOf; + type SourceHeaderNumber = BlockNumberOf; + type SourceHeaderHash = HashOf; + + type TargetHeaderNumber = BlockNumberOf; + type TargetHeaderHash = HashOf; +} /// Substrate <-> Substrate messages relay parameters. -pub struct MessagesRelayParams { +pub struct MessagesRelayParams { /// Messages source client. - pub source_client: Client, - /// Sign parameters for messages source chain. - pub source_sign: SS, - /// Mortality of source transactions. - pub source_transactions_mortality: Option, + pub source_client: Client, + /// Source transaction params. + pub source_transaction_params: + TransactionParams>, /// Messages target client. - pub target_client: Client, - /// Sign parameters for messages target chain. - pub target_sign: TS, - /// Mortality of target transactions. - pub target_transactions_mortality: Option, + pub target_client: Client, + /// Target transaction params. + pub target_transaction_params: + TransactionParams>, /// Optional on-demand source to target headers relay. - pub source_to_target_headers_relay: Option>, + pub source_to_target_headers_relay: Option>, /// Optional on-demand target to source headers relay. - pub target_to_source_headers_relay: Option>, + pub target_to_source_headers_relay: Option>, /// Identifier of lane that needs to be served. pub lane_id: LaneId, /// Metrics parameters. pub metrics_params: MetricsParams, /// Pre-registered standalone metrics. - pub standalone_metrics: Option>, - /// Relay strategy - pub relay_strategy: Strategy, + pub standalone_metrics: Option>, + /// Relay strategy. + pub relay_strategy: P::RelayStrategy, } -/// Message sync pipeline for Substrate <-> Substrate relays. -#[async_trait] -pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { - /// Underlying generic message lane. - type MessageLane: MessageLane; - - /// Name of the runtime method that returns dispatch weight of outbound messages at the source - /// chain. - const OUTBOUND_LANE_MESSAGE_DETAILS_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 target chain. - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; - /// Name of the runtime method that returns the latest confirmed (reward-paid) nonce at the - /// target chain. - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str; - /// Number of the runtime method that returns state of "unrewarded relayers" set at the target - /// chain. - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'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; - - /// Name of the messages pallet as it is declared in the `construct_runtime!()` at source chain. - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str; - /// Name of the messages pallet as it is declared in the `construct_runtime!()` at target chain. - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str; - - /// Extra weight of the delivery transaction at the target chain, that is paid to cover - /// dispatch fee payment. - /// - /// If dispatch fee is paid at the source chain, then this weight is refunded by the - /// delivery transaction. - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight; - - /// Source chain. - type SourceChain: Chain; - /// Target chain. - type TargetChain: Chain; - - /// Returns id of account that we're using to sign transactions at target chain (messages - /// proof). - fn target_transactions_author(&self) -> AccountIdOf; - - /// Make messages delivery transaction. - fn make_messages_delivery_transaction( - &self, - best_block_id: TargetHeaderIdOf, - transaction_nonce: IndexOf, - generated_at_header: SourceHeaderIdOf, - nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes; - - /// Returns id of account that we're using to sign transactions at source chain (delivery - /// proof). - fn source_transactions_author(&self) -> AccountIdOf; - - /// Make messages receiving proof transaction. - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: SourceHeaderIdOf, - transaction_nonce: IndexOf, - generated_at_header: TargetHeaderIdOf, - proof: ::MessagesReceivingProof, - ) -> Bytes; +/// Run Substrate-to-Substrate messages sync loop. +pub async fn run(params: MessagesRelayParams

) -> anyhow::Result<()> +where + AccountIdOf: + From< as Pair>::Public>, + AccountIdOf: + From< as Pair>::Public>, + BalanceOf: TryFrom>, + P::SourceTransactionSignScheme: TransactionSignScheme, + P::TargetTransactionSignScheme: TransactionSignScheme, +{ + let source_client = params.source_client; + let target_client = params.target_client; + let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( + params.source_transaction_params.mortality, + params.target_transaction_params.mortality, + P::SourceChain::AVERAGE_BLOCK_INTERVAL, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ); + let relayer_id_at_source: AccountIdOf = + params.source_transaction_params.signer.public().into(); + + // 2/3 is reserved for proofs and tx overhead + let max_messages_size_in_single_batch = P::TargetChain::max_extrinsic_size() / 3; + // we don't know exact weights of the Polkadot 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) = + crate::messages_lane::select_delivery_transaction_limits::< + ::WeightInfo, + >( + P::TargetChain::max_extrinsic_weight(), + P::SourceChain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + ); + 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); + + let standalone_metrics = params.standalone_metrics.map(Ok).unwrap_or_else(|| { + crate::messages_metrics::standalone_metrics::

( + source_client.clone(), + target_client.clone(), + ) + })?; + + log::info!( + target: "bridge", + "Starting {} -> {} messages relay.\n\t\ + {} 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: {}\n\t\ + Tx mortality: {:?}/{:?}\n\t\ + Stall timeout: {:?}", + P::SourceChain::NAME, + P::TargetChain::NAME, + P::SourceChain::NAME, + relayer_id_at_source, + max_messages_in_single_batch, + max_messages_size_in_single_batch, + max_messages_weight_in_single_batch, + params.source_transaction_params.mortality, + params.target_transaction_params.mortality, + stall_timeout, + ); + + messages_relay::message_lane_loop::run( + messages_relay::message_lane_loop::Params { + lane: params.lane_id, + source_tick: P::SourceChain::AVERAGE_BLOCK_INTERVAL, + target_tick: P::TargetChain::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: + P::SourceChain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + max_unconfirmed_nonces_at_target: + P::SourceChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + max_messages_in_single_batch, + max_messages_weight_in_single_batch, + max_messages_size_in_single_batch, + relay_strategy: params.relay_strategy, + }, + }, + SubstrateMessagesSource::

::new( + source_client, + params.lane_id, + params.source_transaction_params, + params.target_to_source_headers_relay, + ), + SubstrateMessagesTarget::

::new( + target_client, + params.lane_id, + relayer_id_at_source, + params.target_transaction_params, + standalone_metrics.clone(), + params.source_to_target_headers_relay, + ), + standalone_metrics.register_and_spawn(params.metrics_params)?, + futures::future::pending(), + ) + .await + .map_err(Into::into) +} + +/// Different ways of building `receive_messages_proof` calls. +pub trait ReceiveMessagesProofCallBuilder { + /// Given messages proof, build call of `receive_messages_proof` function of bridge + /// messages module at the target chain. + fn build_receive_messages_proof_call( + relayer_id_at_source: AccountIdOf, + proof: SubstrateMessagesProof, + messages_count: u32, + dispatch_weight: Weight, + trace_call: bool, + ) -> CallOf; } -/// Substrate-to-Substrate message lane. -#[derive(Debug)] -pub struct SubstrateMessageLaneToSubstrate< - Source: Chain, - SourceSignParams, - Target: Chain, - TargetSignParams, -> { - /// Client for the source Substrate chain. - pub source_client: Client, - /// Parameters required to sign transactions for source chain. - pub source_sign: SourceSignParams, - /// Source transactions mortality. - pub source_transactions_mortality: Option, - /// Client for the target Substrate chain. - pub target_client: Client, - /// Parameters required to sign transactions for target chain. - pub target_sign: TargetSignParams, - /// Target transactions mortality. - pub target_transactions_mortality: Option, - /// Account id of relayer at the source chain. - pub relayer_id_at_source: Source::AccountId, +/// Building `receive_messages_proof` call when you have direct access to the target +/// chain runtime. +pub struct DirectReceiveMessagesProofCallBuilder { + _phantom: PhantomData<(P, R, I)>, } -impl Clone - for SubstrateMessageLaneToSubstrate +impl ReceiveMessagesProofCallBuilder

for DirectReceiveMessagesProofCallBuilder +where + P: SubstrateMessageLane, + R: BridgeMessagesConfig>, + I: 'static, + R::SourceHeaderChain: bp_messages::target_chain::SourceHeaderChain< + R::InboundMessageFee, + MessagesProof = FromBridgedChainMessagesProof>, + >, + CallOf: From> + GetDispatchInfo, { - fn clone(&self) -> Self { - Self { - source_client: self.source_client.clone(), - source_sign: self.source_sign.clone(), - source_transactions_mortality: self.source_transactions_mortality, - target_client: self.target_client.clone(), - target_sign: self.target_sign.clone(), - target_transactions_mortality: self.target_transactions_mortality, - relayer_id_at_source: self.relayer_id_at_source.clone(), + fn build_receive_messages_proof_call( + relayer_id_at_source: AccountIdOf, + proof: SubstrateMessagesProof, + messages_count: u32, + dispatch_weight: Weight, + trace_call: bool, + ) -> CallOf { + let call: CallOf = BridgeMessagesCall::::receive_messages_proof { + relayer_id_at_bridged_chain: relayer_id_at_source, + proof: proof.1, + messages_count, + dispatch_weight, + } + .into(); + if trace_call { + // this trace isn't super-accurate, because limits are for transactions and we + // have a call here, but it provides required information + log::trace!( + target: "bridge", + "Prepared {} -> {} messages delivery call. Weight: {}/{}, size: {}/{}", + P::SourceChain::NAME, + P::TargetChain::NAME, + call.get_dispatch_info().weight, + P::TargetChain::max_extrinsic_weight(), + call.encode().len(), + P::TargetChain::max_extrinsic_size(), + ); } + call } } -impl MessageLane - for SubstrateMessageLaneToSubstrate -where - SourceSignParams: Clone + Send + Sync + 'static, - TargetSignParams: Clone + Send + Sync + 'static, - BlockNumberOf: BlockNumberBase, - BlockNumberOf: BlockNumberBase, -{ - const SOURCE_NAME: &'static str = Source::NAME; - const TARGET_NAME: &'static str = Target::NAME; +/// Macro that generates `ReceiveMessagesProofCallBuilder` implementation for the case when +/// you only have an access to the mocked version of target chain runtime. In this case you +/// should provide "name" of the call variant for the bridge messages calls and the "name" of +/// the variant for the `receive_messages_proof` call within that first option. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_mocked_receive_message_proof_call_builder { + ($pipeline:ident, $mocked_builder:ident, $bridge_messages:path, $receive_messages_proof:path) => { + pub struct $mocked_builder; + + impl $crate::messages_lane::ReceiveMessagesProofCallBuilder<$pipeline> + for $mocked_builder + { + fn build_receive_messages_proof_call( + relayer_id_at_source: relay_substrate_client::AccountIdOf< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain + >, + proof: $crate::messages_source::SubstrateMessagesProof< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain + >, + messages_count: u32, + dispatch_weight: Weight, + _trace_call: bool, + ) -> relay_substrate_client::CallOf< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::TargetChain + > { + $bridge_messages($receive_messages_proof( + relayer_id_at_source, + proof.1, + messages_count, + dispatch_weight, + )) + } + } + }; +} + +/// Different ways of building `receive_messages_delivery_proof` calls. +pub trait ReceiveMessagesDeliveryProofCallBuilder { + /// Given messages delivery proof, build call of `receive_messages_delivery_proof` function of + /// bridge messages module at the source chain. + fn build_receive_messages_delivery_proof_call( + proof: SubstrateMessagesDeliveryProof, + trace_call: bool, + ) -> CallOf; +} - type MessagesProof = SubstrateMessagesProof; - type MessagesReceivingProof = SubstrateMessagesReceivingProof; +/// Building `receive_messages_delivery_proof` call when you have direct access to the source +/// chain runtime. +pub struct DirectReceiveMessagesDeliveryProofCallBuilder { + _phantom: PhantomData<(P, R, I)>, +} - type SourceChainBalance = Source::Balance; - type SourceHeaderNumber = BlockNumberOf; - type SourceHeaderHash = HashOf; +impl ReceiveMessagesDeliveryProofCallBuilder

+ for DirectReceiveMessagesDeliveryProofCallBuilder +where + P: SubstrateMessageLane, + R: BridgeMessagesConfig, + I: 'static, + R::TargetHeaderChain: bp_messages::source_chain::TargetHeaderChain< + R::OutboundPayload, + R::AccountId, + MessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof>, + >, + CallOf: From> + GetDispatchInfo, +{ + fn build_receive_messages_delivery_proof_call( + proof: SubstrateMessagesDeliveryProof, + trace_call: bool, + ) -> CallOf { + let call: CallOf = + BridgeMessagesCall::::receive_messages_delivery_proof { + proof: proof.1, + relayers_state: proof.0, + } + .into(); + if trace_call { + // this trace isn't super-accurate, because limits are for transactions and we + // have a call here, but it provides required information + log::trace!( + target: "bridge", + "Prepared {} -> {} delivery confirmation transaction. Weight: {}/{}, size: {}/{}", + P::TargetChain::NAME, + P::SourceChain::NAME, + call.get_dispatch_info().weight, + P::SourceChain::max_extrinsic_weight(), + call.encode().len(), + P::SourceChain::max_extrinsic_size(), + ); + } + call + } +} - type TargetHeaderNumber = BlockNumberOf; - type TargetHeaderHash = HashOf; +/// Macro that generates `ReceiveMessagesDeliveryProofCallBuilder` implementation for the case when +/// you only have an access to the mocked version of source chain runtime. In this case you +/// should provide "name" of the call variant for the bridge messages calls and the "name" of +/// the variant for the `receive_messages_delivery_proof` call within that first option. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_mocked_receive_message_delivery_proof_call_builder { + ($pipeline:ident, $mocked_builder:ident, $bridge_messages:path, $receive_messages_delivery_proof:path) => { + pub struct $mocked_builder; + + impl $crate::messages_lane::ReceiveMessagesDeliveryProofCallBuilder<$pipeline> + for $mocked_builder + { + fn build_receive_messages_delivery_proof_call( + proof: $crate::messages_target::SubstrateMessagesDeliveryProof< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::TargetChain + >, + _trace_call: bool, + ) -> relay_substrate_client::CallOf< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain + > { + $bridge_messages($receive_messages_delivery_proof(proof.1, proof.0)) + } + } + }; } /// Returns maximal number of messages and their maximal cumulative dispatch weight, based @@ -245,155 +447,10 @@ pub fn select_delivery_transaction_limits { - /// Global metrics. - pub global: GlobalMetrics, - /// Storage chain proof overhead metric. - pub source_storage_proof_overhead: StorageProofOverheadMetric, - /// Target chain proof overhead metric. - pub target_storage_proof_overhead: StorageProofOverheadMetric, - /// Source tokens to base conversion rate metric. - pub source_to_base_conversion_rate: Option, - /// Target tokens to base conversion rate metric. - pub target_to_base_conversion_rate: Option, - /// Source tokens to target tokens conversion rate metric. This rate is stored by the target - /// chain. - pub source_to_target_conversion_rate: - Option>, - /// Target tokens to source tokens conversion rate metric. This rate is stored by the source - /// chain. - pub target_to_source_conversion_rate: - Option>, -} - -impl StandaloneMessagesMetrics { - /// Swap source and target sides. - pub fn reverse(self) -> StandaloneMessagesMetrics { - StandaloneMessagesMetrics { - global: self.global, - source_storage_proof_overhead: self.target_storage_proof_overhead, - target_storage_proof_overhead: self.source_storage_proof_overhead, - source_to_base_conversion_rate: self.target_to_base_conversion_rate, - target_to_base_conversion_rate: self.source_to_base_conversion_rate, - source_to_target_conversion_rate: self.target_to_source_conversion_rate, - target_to_source_conversion_rate: self.source_to_target_conversion_rate, - } - } - - /// Register all metrics in the registry. - pub fn register_and_spawn( - self, - metrics: MetricsParams, - ) -> Result { - self.global.register_and_spawn(&metrics.registry)?; - self.source_storage_proof_overhead.register_and_spawn(&metrics.registry)?; - self.target_storage_proof_overhead.register_and_spawn(&metrics.registry)?; - if let Some(m) = self.source_to_base_conversion_rate { - m.register_and_spawn(&metrics.registry)?; - } - if let Some(m) = self.target_to_base_conversion_rate { - m.register_and_spawn(&metrics.registry)?; - } - if let Some(m) = self.target_to_source_conversion_rate { - m.register_and_spawn(&metrics.registry)?; - } - Ok(metrics) - } - - /// Return conversion rate from target to source tokens. - pub async fn target_to_source_conversion_rate(&self) -> Option { - Self::compute_target_to_source_conversion_rate( - *self.target_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, - *self.source_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, - ) - } - - /// Return conversion rate from target to source tokens, given conversion rates from - /// target/source tokens to some base token. - fn compute_target_to_source_conversion_rate( - target_to_base_conversion_rate: Option, - source_to_base_conversion_rate: Option, - ) -> Option { - Some(source_to_base_conversion_rate? / target_to_base_conversion_rate?) - } -} - -/// Create standalone metrics for the message lane relay loop. -/// -/// All metrics returned by this function are exposed by loops that are serving given lane (`P`) -/// and by loops that are serving reverse lane (`P` with swapped `TargetChain` and `SourceChain`). -pub fn standalone_metrics( - source_client: Client, - target_client: Client, - source_chain_token_id: Option<&str>, - target_chain_token_id: Option<&str>, - source_to_target_conversion_rate_params: Option<(StorageKey, FixedU128)>, - target_to_source_conversion_rate_params: Option<(StorageKey, FixedU128)>, -) -> anyhow::Result> { - Ok(StandaloneMessagesMetrics { - global: GlobalMetrics::new()?, - source_storage_proof_overhead: StorageProofOverheadMetric::new( - source_client.clone(), - format!("{}_storage_proof_overhead", SC::NAME.to_lowercase()), - format!("{} storage proof overhead", SC::NAME), - )?, - target_storage_proof_overhead: StorageProofOverheadMetric::new( - target_client.clone(), - format!("{}_storage_proof_overhead", TC::NAME.to_lowercase()), - format!("{} storage proof overhead", TC::NAME), - )?, - source_to_base_conversion_rate: source_chain_token_id - .map(|source_chain_token_id| { - crate::helpers::token_price_metric(source_chain_token_id).map(Some) - }) - .unwrap_or(Ok(None))?, - target_to_base_conversion_rate: target_chain_token_id - .map(|target_chain_token_id| { - crate::helpers::token_price_metric(target_chain_token_id).map(Some) - }) - .unwrap_or(Ok(None))?, - source_to_target_conversion_rate: source_to_target_conversion_rate_params - .map(|(key, rate)| { - FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( - target_client, - key, - Some(rate), - format!("{}_{}_to_{}_conversion_rate", TC::NAME, SC::NAME, TC::NAME), - format!( - "{} to {} tokens conversion rate (used by {})", - SC::NAME, - TC::NAME, - TC::NAME - ), - ) - .map(Some) - }) - .unwrap_or(Ok(None))?, - target_to_source_conversion_rate: target_to_source_conversion_rate_params - .map(|(key, rate)| { - FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( - source_client, - key, - Some(rate), - format!("{}_{}_to_{}_conversion_rate", SC::NAME, TC::NAME, SC::NAME), - format!( - "{} to {} tokens conversion rate (used by {})", - TC::NAME, - SC::NAME, - SC::NAME - ), - ) - .map(Some) - }) - .unwrap_or(Ok(None))?, - }) -} - #[cfg(test)] mod tests { use super::*; + use bp_runtime::Chain; type RialtoToMillauMessagesWeights = pallet_bridge_messages::weights::RialtoWeight; @@ -402,8 +459,8 @@ mod tests { fn select_delivery_transaction_limits_works() { let (max_count, max_weight) = select_delivery_transaction_limits::( - bp_millau::max_extrinsic_weight(), - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + bp_millau::Millau::max_extrinsic_weight(), + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, ); assert_eq!( (max_count, max_weight), @@ -415,12 +472,4 @@ mod tests { (782, 216_583_333_334), ); } - - #[async_std::test] - async fn target_to_source_conversion_rate_works() { - assert_eq!( - StandaloneMessagesMetrics::::compute_target_to_source_conversion_rate(Some(183.15), Some(12.32)), - Some(12.32 / 183.15), - ); - } } diff --git a/bridges/relays/lib-substrate-relay/src/messages_metrics.rs b/bridges/relays/lib-substrate-relay/src/messages_metrics.rs new file mode 100644 index 000000000000..54eef6c0ae81 --- /dev/null +++ b/bridges/relays/lib-substrate-relay/src/messages_metrics.rs @@ -0,0 +1,199 @@ +// 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 . + +//! Tools for supporting message lanes between two Substrate-based chains. + +use crate::messages_lane::SubstrateMessageLane; + +use num_traits::One; +use relay_substrate_client::{ + metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, + Chain, Client, +}; +use relay_utils::metrics::{ + FloatJsonValueMetric, GlobalMetrics, MetricsParams, PrometheusError, StandaloneMetric, +}; +use sp_runtime::FixedU128; +use std::fmt::Debug; + +/// Shared references to the standalone metrics of the message lane relay loop. +#[derive(Debug, Clone)] +pub struct StandaloneMessagesMetrics { + /// Global metrics. + pub global: GlobalMetrics, + /// Storage chain proof overhead metric. + pub source_storage_proof_overhead: StorageProofOverheadMetric, + /// Target chain proof overhead metric. + pub target_storage_proof_overhead: StorageProofOverheadMetric, + /// Source tokens to base conversion rate metric. + pub source_to_base_conversion_rate: Option, + /// Target tokens to base conversion rate metric. + pub target_to_base_conversion_rate: Option, + /// Source tokens to target tokens conversion rate metric. This rate is stored by the target + /// chain. + pub source_to_target_conversion_rate: + Option>, + /// Target tokens to source tokens conversion rate metric. This rate is stored by the source + /// chain. + pub target_to_source_conversion_rate: + Option>, +} + +impl StandaloneMessagesMetrics { + /// Swap source and target sides. + pub fn reverse(self) -> StandaloneMessagesMetrics { + StandaloneMessagesMetrics { + global: self.global, + source_storage_proof_overhead: self.target_storage_proof_overhead, + target_storage_proof_overhead: self.source_storage_proof_overhead, + source_to_base_conversion_rate: self.target_to_base_conversion_rate, + target_to_base_conversion_rate: self.source_to_base_conversion_rate, + source_to_target_conversion_rate: self.target_to_source_conversion_rate, + target_to_source_conversion_rate: self.source_to_target_conversion_rate, + } + } + + /// Register all metrics in the registry. + pub fn register_and_spawn( + self, + metrics: MetricsParams, + ) -> Result { + self.global.register_and_spawn(&metrics.registry)?; + self.source_storage_proof_overhead.register_and_spawn(&metrics.registry)?; + self.target_storage_proof_overhead.register_and_spawn(&metrics.registry)?; + if let Some(m) = self.source_to_base_conversion_rate { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.target_to_base_conversion_rate { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.target_to_source_conversion_rate { + m.register_and_spawn(&metrics.registry)?; + } + Ok(metrics) + } + + /// Return conversion rate from target to source tokens. + pub async fn target_to_source_conversion_rate(&self) -> Option { + Self::compute_target_to_source_conversion_rate( + *self.target_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, + *self.source_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, + ) + } + + /// Return conversion rate from target to source tokens, given conversion rates from + /// target/source tokens to some base token. + fn compute_target_to_source_conversion_rate( + target_to_base_conversion_rate: Option, + source_to_base_conversion_rate: Option, + ) -> Option { + Some(source_to_base_conversion_rate? / target_to_base_conversion_rate?) + } +} + +/// Create standalone metrics for the message lane relay loop. +/// +/// All metrics returned by this function are exposed by loops that are serving given lane (`P`) +/// and by loops that are serving reverse lane (`P` with swapped `TargetChain` and `SourceChain`). +/// We assume that either conversion rate parameters have values in the storage, or they are +/// initialized with 1:1. +pub fn standalone_metrics( + source_client: Client, + target_client: Client, +) -> anyhow::Result> { + Ok(StandaloneMessagesMetrics { + global: GlobalMetrics::new()?, + source_storage_proof_overhead: StorageProofOverheadMetric::new( + source_client.clone(), + format!("{}_storage_proof_overhead", P::SourceChain::NAME.to_lowercase()), + format!("{} storage proof overhead", P::SourceChain::NAME), + )?, + target_storage_proof_overhead: StorageProofOverheadMetric::new( + target_client.clone(), + format!("{}_storage_proof_overhead", P::TargetChain::NAME.to_lowercase()), + format!("{} storage proof overhead", P::TargetChain::NAME), + )?, + source_to_base_conversion_rate: P::SourceChain::TOKEN_ID + .map(|source_chain_token_id| { + crate::helpers::token_price_metric(source_chain_token_id).map(Some) + }) + .unwrap_or(Ok(None))?, + target_to_base_conversion_rate: P::TargetChain::TOKEN_ID + .map(|target_chain_token_id| { + crate::helpers::token_price_metric(target_chain_token_id).map(Some) + }) + .unwrap_or(Ok(None))?, + source_to_target_conversion_rate: P::SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME + .map(bp_runtime::storage_parameter_key) + .map(|key| { + FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + target_client, + key, + Some(FixedU128::one()), + format!( + "{}_{}_to_{}_conversion_rate", + P::TargetChain::NAME, + P::SourceChain::NAME, + P::TargetChain::NAME + ), + format!( + "{} to {} tokens conversion rate (used by {})", + P::SourceChain::NAME, + P::TargetChain::NAME, + P::TargetChain::NAME + ), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + target_to_source_conversion_rate: P::TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME + .map(bp_runtime::storage_parameter_key) + .map(|key| { + FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + source_client, + key, + Some(FixedU128::one()), + format!( + "{}_{}_to_{}_conversion_rate", + P::SourceChain::NAME, + P::TargetChain::NAME, + P::SourceChain::NAME + ), + format!( + "{} to {} tokens conversion rate (used by {})", + P::TargetChain::NAME, + P::SourceChain::NAME, + P::SourceChain::NAME + ), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[async_std::test] + async fn target_to_source_conversion_rate_works() { + assert_eq!( + StandaloneMessagesMetrics::::compute_target_to_source_conversion_rate(Some(183.15), Some(12.32)), + Some(12.32 / 183.15), + ); + } +} diff --git a/bridges/relays/lib-substrate-relay/src/messages_source.rs b/bridges/relays/lib-substrate-relay/src/messages_source.rs index 5f066296e7e7..1947f526a01f 100644 --- a/bridges/relays/lib-substrate-relay/src/messages_source.rs +++ b/bridges/relays/lib-substrate-relay/src/messages_source.rs @@ -19,8 +19,12 @@ //! chain. use crate::{ - messages_lane::SubstrateMessageLane, messages_target::SubstrateMessagesReceivingProof, + messages_lane::{ + MessageLaneAdapter, ReceiveMessagesDeliveryProofCallBuilder, SubstrateMessageLane, + }, + messages_target::SubstrateMessagesDeliveryProof, on_demand_headers::OnDemandHeadersRelay, + TransactionParams, }; use async_trait::async_trait; @@ -39,15 +43,13 @@ use messages_relay::{ }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf, HeaderOf, - IndexOf, -}; -use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; -use sp_core::Bytes; -use sp_runtime::{ - traits::{AtLeast32BitUnsigned, Header as HeaderT}, - DeserializeOwned, + AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithMessages, Client, + Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, TransactionEra, TransactionSignScheme, + UnsignedTransaction, }; +use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; +use sp_core::{Bytes, Pair}; +use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; use std::ops::RangeInclusive; /// Intermediate message proof returned by the source Substrate node. Includes everything @@ -58,8 +60,8 @@ pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof { client: Client, - lane: P, lane_id: LaneId, + transaction_params: TransactionParams>, target_to_source_headers_relay: Option>, } @@ -67,11 +69,16 @@ impl SubstrateMessagesSource

{ /// Create new Substrate headers source. pub fn new( client: Client, - lane: P, lane_id: LaneId, + transaction_params: TransactionParams>, target_to_source_headers_relay: Option>, ) -> Self { - SubstrateMessagesSource { client, lane, lane_id, target_to_source_headers_relay } + SubstrateMessagesSource { + client, + lane_id, + transaction_params, + target_to_source_headers_relay, + } } } @@ -79,8 +86,8 @@ impl Clone for SubstrateMessagesSource

{ fn clone(&self) -> Self { Self { client: self.client.clone(), - lane: self.lane.clone(), lane_id: self.lane_id, + transaction_params: self.transaction_params.clone(), target_to_source_headers_relay: self.target_to_source_headers_relay.clone(), } } @@ -96,53 +103,33 @@ impl RelayClient for SubstrateMessagesSource

{ } #[async_trait] -impl

SourceClient for SubstrateMessagesSource

+impl SourceClient> for SubstrateMessagesSource

where - P: SubstrateMessageLane, - P::SourceChain: Chain< - Hash = ::SourceHeaderHash, - BlockNumber = ::SourceHeaderNumber, - Balance = ::SourceChainBalance, - >, - BalanceOf: Decode + Bounded, - IndexOf: DeserializeOwned, - HashOf: Copy, - BlockNumberOf: BlockNumberBase + Copy, - HeaderOf: DeserializeOwned, - P::TargetChain: Chain< - Hash = ::TargetHeaderHash, - BlockNumber = ::TargetHeaderNumber, - >, - - P::MessageLane: MessageLane< - MessagesProof = SubstrateMessagesProof, - MessagesReceivingProof = SubstrateMessagesReceivingProof, - >, - ::TargetHeaderNumber: Decode, - ::TargetHeaderHash: Decode, - ::SourceChainBalance: AtLeast32BitUnsigned, + AccountIdOf: + From< as Pair>::Public>, + P::SourceTransactionSignScheme: TransactionSignScheme, { - async fn state(&self) -> Result, SubstrateError> { + async fn state(&self) -> Result>, SubstrateError> { // we can't continue to deliver confirmations if source node is out of sync, because // it may have already received confirmations that we're going to deliver self.client.ensure_synced().await?; read_client_state::< _, - ::TargetHeaderHash, - ::TargetHeaderNumber, - >(&self.client, P::BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE) + as MessageLane>::TargetHeaderHash, + as MessageLane>::TargetHeaderNumber, + >(&self.client, P::TargetChain::BEST_FINALIZED_HEADER_ID_METHOD) .await } async fn latest_generated_nonce( &self, - id: SourceHeaderIdOf, - ) -> Result<(SourceHeaderIdOf, MessageNonce), SubstrateError> { + id: SourceHeaderIdOf>, + ) -> Result<(SourceHeaderIdOf>, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( - P::OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD.into(), + P::TargetChain::TO_CHAIN_LATEST_GENERATED_NONCE_METHOD.into(), Bytes(self.lane_id.encode()), Some(id.1), ) @@ -154,12 +141,12 @@ where async fn latest_confirmed_received_nonce( &self, - id: SourceHeaderIdOf, - ) -> Result<(SourceHeaderIdOf, MessageNonce), SubstrateError> { + id: SourceHeaderIdOf>, + ) -> Result<(SourceHeaderIdOf>, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( - P::OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD.into(), + P::TargetChain::TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD.into(), Bytes(self.lane_id.encode()), Some(id.1), ) @@ -171,16 +158,16 @@ where async fn generated_message_details( &self, - id: SourceHeaderIdOf, + id: SourceHeaderIdOf>, nonces: RangeInclusive, ) -> Result< - MessageDetailsMap<::SourceChainBalance>, + MessageDetailsMap< as MessageLane>::SourceChainBalance>, SubstrateError, > { let encoded_response = self .client .state_call( - P::OUTBOUND_LANE_MESSAGE_DETAILS_METHOD.into(), + P::TargetChain::TO_CHAIN_MESSAGE_DETAILS_METHOD.into(), Bytes((self.lane_id, nonces.start(), nonces.end()).encode()), Some(id.1), ) @@ -195,14 +182,14 @@ where async fn prove_messages( &self, - id: SourceHeaderIdOf, + id: SourceHeaderIdOf>, nonces: RangeInclusive, proof_parameters: MessageProofParameters, ) -> Result< ( - SourceHeaderIdOf, + SourceHeaderIdOf>, RangeInclusive, - ::MessagesProof, + as MessageLane>::MessagesProof, ), SubstrateError, > { @@ -211,7 +198,7 @@ where let mut message_nonce = *nonces.start(); while message_nonce <= *nonces.end() { let message_key = pallet_bridge_messages::storage_keys::message_key( - P::MESSAGE_PALLET_NAME_AT_SOURCE, + P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &self.lane_id, message_nonce, ); @@ -220,7 +207,7 @@ where } if proof_parameters.outbound_state_proof_required { storage_keys.push(pallet_bridge_messages::storage_keys::outbound_lane_data_key( - P::MESSAGE_PALLET_NAME_AT_SOURCE, + P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &self.lane_id, )); } @@ -238,19 +225,22 @@ where async fn submit_messages_receiving_proof( &self, - generated_at_block: TargetHeaderIdOf, - proof: ::MessagesReceivingProof, + _generated_at_block: TargetHeaderIdOf>, + proof: as MessageLane>::MessagesReceivingProof, ) -> Result<(), SubstrateError> { - let lane = self.lane.clone(); + let genesis_hash = *self.client.genesis_hash(); + let transaction_params = self.transaction_params.clone(); self.client .submit_signed_extrinsic( - self.lane.source_transactions_author(), + self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { - lane.make_messages_receiving_proof_transaction( + make_messages_delivery_proof_transaction::

( + &genesis_hash, + &transaction_params, best_block_id, transaction_nonce, - generated_at_block, proof, + true, ) }, ) @@ -258,7 +248,7 @@ where Ok(()) } - async fn require_target_header_on_source(&self, id: TargetHeaderIdOf) { + async fn require_target_header_on_source(&self, id: TargetHeaderIdOf>) { if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay { target_to_source_headers_relay.require_finalized_header(id).await; } @@ -266,13 +256,15 @@ where async fn estimate_confirmation_transaction( &self, - ) -> ::SourceChainBalance { + ) -> as MessageLane>::SourceChainBalance { self.client - .estimate_extrinsic_fee(self.lane.make_messages_receiving_proof_transaction( + .estimate_extrinsic_fee(make_messages_delivery_proof_transaction::

( + self.client.genesis_hash(), + &self.transaction_params, HeaderId(Default::default(), Default::default()), Zero::zero(), - HeaderId(Default::default(), Default::default()), prepare_dummy_messages_delivery_proof::(), + false, )) .await .map(|fee| fee.inclusion_fee()) @@ -280,12 +272,39 @@ where } } +/// Make messages delivery proof transaction from given proof. +fn make_messages_delivery_proof_transaction( + source_genesis_hash: &HashOf, + source_transaction_params: &TransactionParams>, + source_best_block_id: HeaderIdOf, + transaction_nonce: IndexOf, + proof: SubstrateMessagesDeliveryProof, + trace_call: bool, +) -> Bytes +where + P::SourceTransactionSignScheme: TransactionSignScheme, +{ + let call = + P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( + proof, trace_call, + ); + Bytes( + P::SourceTransactionSignScheme::sign_transaction( + *source_genesis_hash, + &source_transaction_params.signer, + TransactionEra::new(source_best_block_id, source_transaction_params.mortality), + UnsignedTransaction::new(call, transaction_nonce), + ) + .encode(), + ) +} + /// Prepare 'dummy' messages delivery proof that will compose the delivery confirmation transaction. /// /// We don't care about proof actually being the valid proof, because its validity doesn't /// affect the call weight - we only care about its size. fn prepare_dummy_messages_delivery_proof( -) -> SubstrateMessagesReceivingProof { +) -> SubstrateMessagesDeliveryProof { let single_message_confirmation_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( SC::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1, diff --git a/bridges/relays/lib-substrate-relay/src/messages_target.rs b/bridges/relays/lib-substrate-relay/src/messages_target.rs index eafc6bd3fc5f..3cbe0181d750 100644 --- a/bridges/relays/lib-substrate-relay/src/messages_target.rs +++ b/bridges/relays/lib-substrate-relay/src/messages_target.rs @@ -19,14 +19,15 @@ //! chain. use crate::{ - messages_lane::{StandaloneMessagesMetrics, SubstrateMessageLane}, + messages_lane::{MessageLaneAdapter, ReceiveMessagesProofCallBuilder, SubstrateMessageLane}, + messages_metrics::StandaloneMessagesMetrics, messages_source::{read_client_state, SubstrateMessagesProof}, on_demand_headers::OnDemandHeadersRelay, + TransactionParams, }; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; - use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; @@ -38,23 +39,25 @@ use messages_relay::{ }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderOf, IndexOf, - WeightToFeeOf, + AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithMessages, Client, + Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, TransactionEra, TransactionSignScheme, + UnsignedTransaction, WeightToFeeOf, }; -use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; -use sp_core::Bytes; -use sp_runtime::{traits::Saturating, DeserializeOwned, FixedPointNumber, FixedU128}; +use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; +use sp_core::{Bytes, Pair}; +use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use std::{convert::TryFrom, ops::RangeInclusive}; /// Message receiving proof returned by the target Substrate node. -pub type SubstrateMessagesReceivingProof = +pub type SubstrateMessagesDeliveryProof = (UnrewardedRelayersState, FromBridgedChainMessagesDeliveryProof>); /// Substrate client as Substrate messages target. pub struct SubstrateMessagesTarget { client: Client, - lane: P, lane_id: LaneId, + relayer_id_at_source: AccountIdOf, + transaction_params: TransactionParams>, metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option>, } @@ -63,15 +66,17 @@ impl SubstrateMessagesTarget

{ /// Create new Substrate headers target. pub fn new( client: Client, - lane: P, lane_id: LaneId, + relayer_id_at_source: AccountIdOf, + transaction_params: TransactionParams>, metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option>, ) -> Self { SubstrateMessagesTarget { client, - lane, lane_id, + relayer_id_at_source, + transaction_params, metric_values, source_to_target_headers_relay, } @@ -82,8 +87,9 @@ impl Clone for SubstrateMessagesTarget

{ fn clone(&self) -> Self { Self { client: self.client.clone(), - lane: self.lane.clone(), lane_id: self.lane_id, + relayer_id_at_source: self.relayer_id_at_source.clone(), + transaction_params: self.transaction_params.clone(), metric_values: self.metric_values.clone(), source_to_target_headers_relay: self.source_to_target_headers_relay.clone(), } @@ -100,52 +106,34 @@ impl RelayClient for SubstrateMessagesTarget

{ } #[async_trait] -impl

TargetClient for SubstrateMessagesTarget

+impl TargetClient> for SubstrateMessagesTarget

where - P: SubstrateMessageLane, - P::SourceChain: Chain< - Hash = ::SourceHeaderHash, - BlockNumber = ::SourceHeaderNumber, - Balance = ::SourceChainBalance, - >, - BalanceOf: TryFrom> + Bounded, - P::TargetChain: Chain< - Hash = ::TargetHeaderHash, - BlockNumber = ::TargetHeaderNumber, - >, - IndexOf: DeserializeOwned, - HashOf: Copy, - BlockNumberOf: Copy, - HeaderOf: DeserializeOwned, - BlockNumberOf: BlockNumberBase, - P::MessageLane: MessageLane< - MessagesProof = SubstrateMessagesProof, - MessagesReceivingProof = SubstrateMessagesReceivingProof, - >, - ::SourceHeaderNumber: Decode, - ::SourceHeaderHash: Decode, + AccountIdOf: + From< as Pair>::Public>, + P::TargetTransactionSignScheme: TransactionSignScheme, + BalanceOf: TryFrom>, { - async fn state(&self) -> Result, SubstrateError> { + async fn state(&self) -> Result>, SubstrateError> { // we can't continue to deliver messages if target node is out of sync, because // it may have already received (some of) messages that we're going to deliver self.client.ensure_synced().await?; read_client_state::< _, - ::SourceHeaderHash, - ::SourceHeaderNumber, - >(&self.client, P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET) + as MessageLane>::SourceHeaderHash, + as MessageLane>::SourceHeaderNumber, + >(&self.client, P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD) .await } async fn latest_received_nonce( &self, - id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, MessageNonce), SubstrateError> { + id: TargetHeaderIdOf>, + ) -> Result<(TargetHeaderIdOf>, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( - P::INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD.into(), + P::SourceChain::FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD.into(), Bytes(self.lane_id.encode()), Some(id.1), ) @@ -157,12 +145,12 @@ where async fn latest_confirmed_received_nonce( &self, - id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, MessageNonce), SubstrateError> { + id: TargetHeaderIdOf>, + ) -> Result<(TargetHeaderIdOf>, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( - P::INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD.into(), + P::SourceChain::FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD.into(), Bytes(self.lane_id.encode()), Some(id.1), ) @@ -174,12 +162,13 @@ where async fn unrewarded_relayers_state( &self, - id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, UnrewardedRelayersState), SubstrateError> { + id: TargetHeaderIdOf>, + ) -> Result<(TargetHeaderIdOf>, UnrewardedRelayersState), SubstrateError> + { let encoded_response = self .client .state_call( - P::INBOUND_LANE_UNREWARDED_RELAYERS_STATE.into(), + P::SourceChain::FROM_CHAIN_UNREWARDED_RELAYERS_STATE.into(), Bytes(self.lane_id.encode()), Some(id.1), ) @@ -192,14 +181,17 @@ where async fn prove_messages_receiving( &self, - id: TargetHeaderIdOf, + id: TargetHeaderIdOf>, ) -> Result< - (TargetHeaderIdOf, ::MessagesReceivingProof), + ( + TargetHeaderIdOf>, + as MessageLane>::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( - P::MESSAGE_PALLET_NAME_AT_TARGET, + P::SourceChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &self.lane_id, ); let proof = self @@ -218,22 +210,27 @@ where async fn submit_messages_proof( &self, - generated_at_header: SourceHeaderIdOf, + _generated_at_header: SourceHeaderIdOf>, nonces: RangeInclusive, - proof: ::MessagesProof, + proof: as MessageLane>::MessagesProof, ) -> Result, SubstrateError> { - let lane = self.lane.clone(); + let genesis_hash = *self.client.genesis_hash(); + let transaction_params = self.transaction_params.clone(); + let relayer_id_at_source = self.relayer_id_at_source.clone(); let nonces_clone = nonces.clone(); self.client .submit_signed_extrinsic( - self.lane.target_transactions_author(), + self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { - lane.make_messages_delivery_transaction( + make_messages_delivery_transaction::

( + &genesis_hash, + &transaction_params, best_block_id, transaction_nonce, - generated_at_header, + relayer_id_at_source, nonces_clone, proof, + true, ) }, ) @@ -241,7 +238,7 @@ where Ok(nonces) } - async fn require_source_header_on_target(&self, id: SourceHeaderIdOf) { + async fn require_source_header_on_target(&self, id: SourceHeaderIdOf>) { if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay { source_to_target_headers_relay.require_finalized_header(id).await; } @@ -253,7 +250,7 @@ where total_prepaid_nonces: MessageNonce, total_dispatch_weight: Weight, total_size: u32, - ) -> Result<::SourceChainBalance, SubstrateError> { + ) -> Result< as MessageLane>::SourceChainBalance, SubstrateError> { let conversion_rate = self.metric_values.target_to_source_conversion_rate().await.ok_or_else(|| { SubstrateError::Custom(format!( @@ -264,16 +261,19 @@ where })?; // Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight. - let delivery_tx = self.lane.make_messages_delivery_transaction( + let delivery_tx = make_messages_delivery_transaction::

( + self.client.genesis_hash(), + &self.transaction_params, HeaderId(Default::default(), Default::default()), Zero::zero(), - HeaderId(Default::default(), Default::default()), + Default::default(), nonces.clone(), prepare_dummy_messages_proof::( nonces.clone(), total_dispatch_weight, total_size, ), + false, ); let delivery_tx_fee = self.client.estimate_extrinsic_fee(delivery_tx).await?; let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee(); @@ -300,20 +300,23 @@ where let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE); let larger_delivery_tx_fee = self .client - .estimate_extrinsic_fee(self.lane.make_messages_delivery_transaction( + .estimate_extrinsic_fee(make_messages_delivery_transaction::

( + self.client.genesis_hash(), + &self.transaction_params, HeaderId(Default::default(), Default::default()), Zero::zero(), - HeaderId(Default::default(), Default::default()), + Default::default(), nonces.clone(), prepare_dummy_messages_proof::( nonces.clone(), larger_dispatch_weight, total_size, ), + false, )) .await?; - compute_prepaid_messages_refund::

( + compute_prepaid_messages_refund::( total_prepaid_nonces, compute_fee_multiplier::( delivery_tx_fee.adjusted_weight_fee, @@ -359,6 +362,41 @@ where } } +/// Make messages delivery transaction from given proof. +#[allow(clippy::too_many_arguments)] +fn make_messages_delivery_transaction( + target_genesis_hash: &HashOf, + target_transaction_params: &TransactionParams>, + target_best_block_id: HeaderIdOf, + transaction_nonce: IndexOf, + relayer_id_at_source: AccountIdOf, + nonces: RangeInclusive, + proof: SubstrateMessagesProof, + trace_call: bool, +) -> Bytes +where + P::TargetTransactionSignScheme: TransactionSignScheme, +{ + let messages_count = nonces.end() - nonces.start() + 1; + let dispatch_weight = proof.0; + let call = P::ReceiveMessagesProofCallBuilder::build_receive_messages_proof_call( + relayer_id_at_source, + proof, + messages_count as _, + dispatch_weight, + trace_call, + ); + Bytes( + P::TargetTransactionSignScheme::sign_transaction( + *target_genesis_hash, + &target_transaction_params.signer, + TransactionEra::new(target_best_block_id, target_transaction_params.mortality), + UnsignedTransaction::new(call, transaction_nonce), + ) + .encode(), + ) +} + /// Prepare 'dummy' messages proof that will compose the delivery transaction. /// /// We don't care about proof actually being the valid proof, because its validity doesn't @@ -425,80 +463,20 @@ fn compute_fee_multiplier( /// Compute fee that will be refunded to the relayer because dispatch of `total_prepaid_nonces` /// messages has been paid at the source chain. -fn compute_prepaid_messages_refund( +fn compute_prepaid_messages_refund( total_prepaid_nonces: MessageNonce, fee_multiplier: FixedU128, -) -> BalanceOf { - fee_multiplier.saturating_mul_int(WeightToFeeOf::::calc( - &P::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN.saturating_mul(total_prepaid_nonces), +) -> BalanceOf { + fee_multiplier.saturating_mul_int(WeightToFeeOf::::calc( + &C::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN.saturating_mul(total_prepaid_nonces), )) } #[cfg(test)] mod tests { use super::*; - use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; - use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; - - #[derive(Clone)] - struct TestSubstrateMessageLane; - - impl SubstrateMessageLane for TestSubstrateMessageLane { - type MessageLane = crate::messages_lane::SubstrateMessageLaneToSubstrate< - Rococo, - RococoSigningParams, - Wococo, - WococoSigningParams, - >; - - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = ""; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = ""; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = ""; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = ""; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = ""; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = ""; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = ""; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = ""; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = ""; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = ""; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = 100_000; - - type SourceChain = Rococo; - type TargetChain = Wococo; - - fn source_transactions_author(&self) -> bp_rococo::AccountId { - unreachable!() - } - - fn make_messages_receiving_proof_transaction( - &self, - _best_block_id: SourceHeaderIdOf, - _transaction_nonce: IndexOf, - _generated_at_block: TargetHeaderIdOf, - _proof: ::MessagesReceivingProof, - ) -> Bytes { - unreachable!() - } - - fn target_transactions_author(&self) -> bp_wococo::AccountId { - unreachable!() - } - - fn make_messages_delivery_transaction( - &self, - _best_block_id: TargetHeaderIdOf, - _transaction_nonce: IndexOf, - _generated_at_header: SourceHeaderIdOf, - _nonces: RangeInclusive, - _proof: ::MessagesProof, - ) -> Bytes { - unreachable!() - } - } + use relay_rococo_client::Rococo; + use relay_wococo_client::Wococo; #[test] fn prepare_dummy_messages_proof_works() { @@ -556,11 +534,10 @@ mod tests { #[test] fn compute_prepaid_messages_refund_returns_sane_results() { assert!( - compute_prepaid_messages_refund::( + compute_prepaid_messages_refund::( 10, FixedU128::saturating_from_rational(110, 100), - ) > (10 * TestSubstrateMessageLane::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN) - .into() + ) > (10 * Wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN).into() ); } } diff --git a/bridges/relays/lib-substrate-relay/src/on_demand_headers.rs b/bridges/relays/lib-substrate-relay/src/on_demand_headers.rs index 1bd0b0b729c4..d66aaba549e2 100644 --- a/bridges/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/bridges/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -30,12 +30,10 @@ use relay_utils::{ }; use crate::{ - finality_pipeline::{ - SubstrateFinalitySyncPipeline, TransactionParams, RECENT_FINALITY_PROOFS_LIMIT, - }, + finality_pipeline::{SubstrateFinalitySyncPipeline, RECENT_FINALITY_PROOFS_LIMIT}, finality_source::{RequiredHeaderNumberRef, SubstrateFinalitySource}, finality_target::SubstrateFinalityTarget, - STALL_TIMEOUT, + TransactionParams, STALL_TIMEOUT, }; /// On-demand Substrate <-> Substrate headers relay. @@ -116,7 +114,7 @@ async fn background_task( P::TransactionSignScheme: TransactionSignScheme, { let relay_task_name = on_demand_headers_relay_name::(); - let target_transactions_mortality = target_transaction_params.transactions_mortality; + let target_transactions_mortality = target_transaction_params.mortality; let mut finality_source = SubstrateFinalitySource::

::new( source_client.clone(), Some(required_header_number.clone()),