From f89eeb920a713a78a93f04151b6d238012265893 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 6 Jul 2022 15:45:30 +0300 Subject: [PATCH] [CLI] remove select_full_bridge!() macro Signed-off-by: Serban Iorga --- .../relays/bin-substrate/src/cli/bridge.rs | 176 +++++++------- .../bin-substrate/src/cli/estimate_fee.rs | 76 +++--- .../bin-substrate/src/cli/relay_headers.rs | 9 +- .../bin-substrate/src/cli/relay_messages.rs | 105 ++++++--- .../bin-substrate/src/cli/send_message.rs | 216 ++++++++++-------- 5 files changed, 323 insertions(+), 259 deletions(-) diff --git a/bridges/relays/bin-substrate/src/cli/bridge.rs b/bridges/relays/bin-substrate/src/cli/bridge.rs index 242c22647c..103c9cb391 100644 --- a/bridges/relays/bin-substrate/src/cli/bridge.rs +++ b/bridges/relays/bin-substrate/src/cli/bridge.rs @@ -15,9 +15,12 @@ // along with Parity Bridges Common. If not, see . use crate::cli::CliChain; +use bp_runtime::{AccountIdOf, SourceAccount}; use relay_substrate_client::{AccountKeyPairOf, Chain, TransactionSignScheme}; use strum::{EnumString, EnumVariantNames}; -use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; +use substrate_relay_helper::{ + finality::SubstrateFinalitySyncPipeline, messages_lane::SubstrateMessageLane, +}; #[derive(Debug, PartialEq, Eq, EnumString, EnumVariantNames)] #[strum(serialize_all = "kebab_case")] @@ -46,94 +49,6 @@ pub const MILLAU_TO_RIALTO_INDEX: u8 = 0; pub const MILLAU_TO_RIALTO_PARACHAIN_INDEX: u8 = 1; pub const RIALTO_PARACHAIN_TO_MILLAU_INDEX: u8 = 0; -/// The macro allows executing bridge-specific code without going fully generic. -/// -/// It matches on the [`FullBridge`] enum, sets bridge-specific types or imports and injects -/// the `$generic` code at every variant. -#[macro_export] -macro_rules! select_full_bridge { - ($bridge: expr, $generic: tt) => { - match $bridge { - FullBridge::MillauToRialto => { - type Source = relay_millau_client::Millau; - #[allow(dead_code)] - type Target = relay_rialto_client::Rialto; - - // Derive-account - #[allow(unused_imports)] - use bp_rialto::derive_account_from_millau_id as derive_account; - - // Relay-messages - #[allow(unused_imports)] - use $crate::chains::millau_messages_to_rialto::MillauMessagesToRialto as MessagesLane; - - // Send-message / Estimate-fee - #[allow(unused_imports)] - use bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - - $generic - }, - FullBridge::RialtoToMillau => { - type Source = relay_rialto_client::Rialto; - #[allow(dead_code)] - type Target = relay_millau_client::Millau; - - // Derive-account - #[allow(unused_imports)] - use bp_millau::derive_account_from_rialto_id as derive_account; - - // Relay-messages - #[allow(unused_imports)] - use $crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau as MessagesLane; - - // Send-message / Estimate-fee - #[allow(unused_imports)] - use bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - - $generic - }, - FullBridge::MillauToRialtoParachain => { - type Source = relay_millau_client::Millau; - #[allow(dead_code)] - type Target = relay_rialto_parachain_client::RialtoParachain; - - // Derive-account - #[allow(unused_imports)] - use bp_rialto_parachain::derive_account_from_millau_id as derive_account; - - // Relay-messages - #[allow(unused_imports)] - use $crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain as MessagesLane; - - // Send-message / Estimate-fee - #[allow(unused_imports)] - use bp_rialto_parachain::TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - - $generic - } - FullBridge::RialtoParachainToMillau => { - type Source = relay_rialto_parachain_client::RialtoParachain; - #[allow(dead_code)] - type Target = relay_millau_client::Millau; - - // Derive-account - #[allow(unused_imports)] - use bp_millau::derive_account_from_rialto_parachain_id as derive_account; - - // Relay-messages - #[allow(unused_imports)] - use $crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau as MessagesLane; - - // Send-message / Estimate-fee - #[allow(unused_imports)] - use bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - - $generic - } - } - }; -} - /// Minimal bridge representation that can be used from the CLI. /// It connects a source chain to a target chain. pub trait CliBridgeBase: Sized { @@ -145,8 +60,8 @@ pub trait CliBridgeBase: Sized { + CliChain>; } -/// Bridge representation that can be used from the CLI. -pub trait CliBridge: CliBridgeBase { +/// Bridge representation that can be used from the CLI for relaying headers. +pub trait HeadersCliBridge: CliBridgeBase { /// Finality proofs synchronization pipeline. type Finality: SubstrateFinalitySyncPipeline< SourceChain = Self::Source, @@ -155,6 +70,25 @@ pub trait CliBridge: CliBridgeBase { >; } +/// Bridge representation that can be used from the CLI for relaying messages. +pub trait MessagesCliBridge: CliBridgeBase { + /// Name of the runtime method used to estimate the message dispatch and delivery fee for the + /// defined bridge. + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str; + /// The Source -> Destination messages synchronization pipeline. + type MessagesLane: SubstrateMessageLane< + SourceChain = Self::Source, + TargetChain = Self::Target, + SourceTransactionSignScheme = Self::Source, + TargetTransactionSignScheme = Self::Target, + >; + + /// We use this to get the account on the target which is derived from the source account. + fn derive_account_from_id( + id: SourceAccount>, + ) -> AccountIdOf; +} + //// `Millau` to `Rialto` bridge definition. pub struct MillauToRialtoCliBridge {} @@ -163,10 +97,22 @@ impl CliBridgeBase for MillauToRialtoCliBridge { type Target = relay_rialto_client::Rialto; } -impl CliBridge for MillauToRialtoCliBridge { +impl HeadersCliBridge for MillauToRialtoCliBridge { type Finality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; } +impl MessagesCliBridge for MillauToRialtoCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto; + + fn derive_account_from_id( + id: SourceAccount>, + ) -> AccountIdOf { + bp_rialto::derive_account_from_millau_id(id) + } +} + //// `Rialto` to `Millau` bridge definition. pub struct RialtoToMillauCliBridge {} @@ -175,10 +121,24 @@ impl CliBridgeBase for RialtoToMillauCliBridge { type Target = relay_millau_client::Millau; } -impl CliBridge for RialtoToMillauCliBridge { +impl HeadersCliBridge for RialtoToMillauCliBridge { type Finality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; } +impl MessagesCliBridge for RialtoToMillauCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau; + + /// We use this to get the account on the target chain which is derived from + /// the source chain account. + fn derive_account_from_id( + id: SourceAccount>, + ) -> AccountIdOf { + bp_millau::derive_account_from_rialto_id(id) + } +} + //// `Westend` to `Millau` bridge definition. pub struct WestendToMillauCliBridge {} @@ -187,7 +147,7 @@ impl CliBridgeBase for WestendToMillauCliBridge { type Target = relay_millau_client::Millau; } -impl CliBridge for WestendToMillauCliBridge { +impl HeadersCliBridge for WestendToMillauCliBridge { type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; } @@ -199,11 +159,24 @@ impl CliBridgeBase for MillauToRialtoParachainCliBridge { type Target = relay_rialto_parachain_client::RialtoParachain; } -impl CliBridge for MillauToRialtoParachainCliBridge { +impl HeadersCliBridge for MillauToRialtoParachainCliBridge { type Finality = crate::chains::millau_headers_to_rialto_parachain::MillauFinalityToRialtoParachain; } +impl MessagesCliBridge for MillauToRialtoParachainCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_rialto_parachain::TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = + crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain; + + fn derive_account_from_id( + id: SourceAccount>, + ) -> AccountIdOf { + bp_rialto_parachain::derive_account_from_millau_id(id) + } +} + //// `RialtoParachain` to `Millau` bridge definition. pub struct RialtoParachainToMillauCliBridge {} @@ -212,6 +185,19 @@ impl CliBridgeBase for RialtoParachainToMillauCliBridge { type Target = relay_millau_client::Millau; } +impl MessagesCliBridge for RialtoParachainToMillauCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = + crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau; + + fn derive_account_from_id( + id: SourceAccount>, + ) -> AccountIdOf { + bp_millau::derive_account_from_rialto_parachain_id(id) + } +} + //// `WestendParachain` to `Millau` bridge definition. pub struct WestmintToMillauCliBridge {} diff --git a/bridges/relays/bin-substrate/src/cli/estimate_fee.rs b/bridges/relays/bin-substrate/src/cli/estimate_fee.rs index bf13996ec5..30f20b681d 100644 --- a/bridges/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/bridges/relays/bin-substrate/src/cli/estimate_fee.rs @@ -14,17 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::{ - cli::{ - bridge::FullBridge, relay_headers_and_messages::CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - Balance, HexBytes, HexLaneId, SourceConnectionParams, - }, - select_full_bridge, +use crate::cli::{ + bridge::{FullBridge, MessagesCliBridge, *}, + relay_headers_and_messages::CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, + Balance, HexBytes, HexLaneId, SourceConnectionParams, }; +use async_trait::async_trait; use bp_runtime::BalanceOf; use codec::{Decode, Encode}; -use relay_substrate_client::Chain; +use relay_substrate_client::{Chain, ChainBase}; use sp_runtime::FixedU128; +use std::fmt::Display; use structopt::StructOpt; use strum::VariantNames; use substrate_relay_helper::helpers::tokens_conversion_rate_from_metrics; @@ -74,30 +74,50 @@ impl std::str::FromStr for ConversionRateOverride { } } +#[async_trait] +trait FeeEstimator: MessagesCliBridge +where + ::Balance: Display + Into, +{ + async fn estimate_fee(data: EstimateFee) -> anyhow::Result<()> { + let source_client = data.source.to_client::().await?; + let lane = data.lane.into(); + let payload = + crate::cli::encode_message::encode_message::(&data.payload) + .map_err(|e| anyhow::format_err!("{:?}", e))?; + + let fee = estimate_message_delivery_and_dispatch_fee::( + &source_client, + data.conversion_rate_override, + Self::ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload, + ) + .await?; + + log::info!(target: "bridge", "Fee: {:?}", Balance(fee.into())); + println!("{}", fee); + Ok(()) + } +} + +impl FeeEstimator for MillauToRialtoCliBridge {} +impl FeeEstimator for RialtoToMillauCliBridge {} +impl FeeEstimator for MillauToRialtoParachainCliBridge {} +impl FeeEstimator for RialtoParachainToMillauCliBridge {} + impl EstimateFee { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { - let Self { source, bridge, lane, conversion_rate_override, payload } = self; - - select_full_bridge!(bridge, { - let source_client = source.to_client::().await?; - let lane = lane.into(); - let payload = crate::cli::encode_message::encode_message::(&payload) - .map_err(|e| anyhow::format_err!("{:?}", e))?; - - let fee = estimate_message_delivery_and_dispatch_fee::( - &source_client, - conversion_rate_override, - ESTIMATE_MESSAGE_FEE_METHOD, - lane, - payload, - ) - .await?; - - log::info!(target: "bridge", "Fee: {:?}", Balance(fee as _)); - println!("{}", fee); - Ok(()) - }) + match self.bridge { + FullBridge::MillauToRialto => MillauToRialtoCliBridge::estimate_fee(self), + FullBridge::RialtoToMillau => RialtoToMillauCliBridge::estimate_fee(self), + FullBridge::MillauToRialtoParachain => + MillauToRialtoParachainCliBridge::estimate_fee(self), + FullBridge::RialtoParachainToMillau => + RialtoParachainToMillauCliBridge::estimate_fee(self), + } + .await } } diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers.rs b/bridges/relays/bin-substrate/src/cli/relay_headers.rs index 25bb3440c6..f8d7eeb541 100644 --- a/bridges/relays/bin-substrate/src/cli/relay_headers.rs +++ b/bridges/relays/bin-substrate/src/cli/relay_headers.rs @@ -24,11 +24,8 @@ use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; use crate::cli::{ - bridge::{ - CliBridge, MillauToRialtoCliBridge, MillauToRialtoParachainCliBridge, - RialtoToMillauCliBridge, WestendToMillauCliBridge, - }, - PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams, + bridge::*, PrometheusParams, SourceConnectionParams, TargetConnectionParams, + TargetSigningParams, }; /// Start headers relayer process. @@ -62,7 +59,7 @@ pub enum RelayHeadersBridge { } #[async_trait] -trait HeadersRelayer: CliBridge +trait HeadersRelayer: HeadersCliBridge where ::AccountId: From< as Pair>::Public>, { diff --git a/bridges/relays/bin-substrate/src/cli/relay_messages.rs b/bridges/relays/bin-substrate/src/cli/relay_messages.rs index 820a71748d..7242d13185 100644 --- a/bridges/relays/bin-substrate/src/cli/relay_messages.rs +++ b/bridges/relays/bin-substrate/src/cli/relay_messages.rs @@ -14,18 +14,21 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use async_trait::async_trait; +use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use messages_relay::relay_strategy::MixStrategy; -use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams}; +use relay_substrate_client::{AccountKeyPairOf, ChainBase, TransactionSignScheme}; +use substrate_relay_helper::{ + messages_lane::{MessagesRelayParams, SubstrateMessageLane}, + TransactionParams, +}; -use crate::{ - cli::{ - bridge::FullBridge, HexLaneId, PrometheusParams, SourceConnectionParams, - SourceSigningParams, TargetConnectionParams, TargetSigningParams, - }, - select_full_bridge, +use crate::cli::{ + bridge::*, CliChain, HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams, + TargetConnectionParams, TargetSigningParams, }; /// Relayer operating mode. @@ -71,40 +74,66 @@ pub struct RelayMessages { prometheus_params: PrometheusParams, } +#[async_trait] +trait MessagesRelayer: MessagesCliBridge +where + Self::Source: TransactionSignScheme + + CliChain>, + ::AccountId: From< as Pair>::Public>, + ::AccountId: From< as Pair>::Public>, + ::Balance: TryFrom<::Balance>, + Self::MessagesLane: SubstrateMessageLane, +{ + async fn relay_messages(data: RelayMessages) -> anyhow::Result<()> { + let source_client = data.source.to_client::().await?; + let source_sign = data.source_sign.to_keypair::()?; + let source_transactions_mortality = data.source_sign.transactions_mortality()?; + let target_client = data.target.to_client::().await?; + let target_sign = data.target_sign.to_keypair::()?; + let target_transactions_mortality = data.target_sign.transactions_mortality()?; + let relayer_mode = data.relayer_mode.into(); + let relay_strategy = MixStrategy::new(relayer_mode); + + substrate_relay_helper::messages_lane::run::(MessagesRelayParams { + source_client, + source_transaction_params: TransactionParams { + signer: source_sign, + mortality: source_transactions_mortality, + }, + target_client, + 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: data.lane.into(), + metrics_params: data.prometheus_params.into(), + standalone_metrics: None, + relay_strategy, + }) + .await + .map_err(|e| anyhow::format_err!("{}", e)) + } +} + +impl MessagesRelayer for MillauToRialtoCliBridge {} +impl MessagesRelayer for RialtoToMillauCliBridge {} +impl MessagesRelayer for MillauToRialtoParachainCliBridge {} +impl MessagesRelayer for RialtoParachainToMillauCliBridge {} + impl RelayMessages { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { - select_full_bridge!(self.bridge, { - let source_client = self.source.to_client::().await?; - let source_sign = self.source_sign.to_keypair::()?; - let source_transactions_mortality = self.source_sign.transactions_mortality()?; - let target_client = self.target.to_client::().await?; - let target_sign = self.target_sign.to_keypair::()?; - let target_transactions_mortality = self.target_sign.transactions_mortality()?; - let relayer_mode = self.relayer_mode.into(); - let relay_strategy = MixStrategy::new(relayer_mode); - - substrate_relay_helper::messages_lane::run::(MessagesRelayParams { - source_client, - source_transaction_params: TransactionParams { - signer: source_sign, - mortality: source_transactions_mortality, - }, - target_client, - 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(), - metrics_params: self.prometheus_params.into(), - standalone_metrics: None, - relay_strategy, - }) - .await - .map_err(|e| anyhow::format_err!("{}", e)) - }) + match self.bridge { + FullBridge::MillauToRialto => MillauToRialtoCliBridge::relay_messages(self), + FullBridge::RialtoToMillau => RialtoToMillauCliBridge::relay_messages(self), + FullBridge::MillauToRialtoParachain => + MillauToRialtoParachainCliBridge::relay_messages(self), + FullBridge::RialtoParachainToMillau => + RialtoParachainToMillauCliBridge::relay_messages(self), + } + .await } } diff --git a/bridges/relays/bin-substrate/src/cli/send_message.rs b/bridges/relays/bin-substrate/src/cli/send_message.rs index 959fbbd7fc..ee17fb3f31 100644 --- a/bridges/relays/bin-substrate/src/cli/send_message.rs +++ b/bridges/relays/bin-substrate/src/cli/send_message.rs @@ -15,16 +15,20 @@ // along with Parity Bridges Common. If not, see . use crate::cli::{ - bridge::FullBridge, + bridge::{FullBridge, MessagesCliBridge, *}, encode_message::{self, CliEncodeMessage}, estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride}, - Balance, HexBytes, HexLaneId, SourceConnectionParams, SourceSigningParams, + Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams, SourceSigningParams, }; +use async_trait::async_trait; +use bp_runtime::AccountIdOf; use codec::Encode; -use relay_substrate_client::{Chain, SignParam, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{ + AccountKeyPairOf, Chain, ChainBase, SignParam, TransactionSignScheme, UnsignedTransaction, +}; use sp_core::{Bytes, Pair}; use sp_runtime::AccountId32; -use std::fmt::Debug; +use std::fmt::{Debug, Display}; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; @@ -75,97 +79,125 @@ pub struct SendMessage { message: crate::cli::encode_message::Message, } +#[async_trait] +trait MessageSender: MessagesCliBridge +where + Self::Source: ChainBase + + TransactionSignScheme + + CliChain> + + CliEncodeMessage, + ::Balance: Display + From + Into, + ::Call: Sync, + ::SignedTransaction: Sync, + AccountIdOf: From< as Pair>::Public>, + AccountId32: From< as Pair>::Public>, +{ + async fn send_message(data: SendMessage) -> anyhow::Result<()> { + let payload = encode_message::encode_message::(&data.message)?; + + let source_client = data.source.to_client::().await?; + let source_sign = data.source_sign.to_keypair::()?; + + let lane = data.lane.clone().into(); + let conversion_rate_override = data.conversion_rate_override; + let fee = match data.fee { + Some(fee) => fee, + None => Balance( + estimate_message_delivery_and_dispatch_fee::( + &source_client, + conversion_rate_override, + Self::ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload.clone(), + ) + .await? + .into(), + ), + }; + let payload_len = payload.encode().len(); + let send_message_call = Self::Source::encode_send_message_call( + data.lane.0, + payload, + fee.cast().into(), + data.bridge.bridge_instance_index(), + )?; + + let source_genesis_hash = *source_client.genesis_hash(); + let (spec_version, transaction_version) = source_client.simple_runtime_version().await?; + let estimated_transaction_fee = source_client + .estimate_extrinsic_fee(Bytes( + Self::Source::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: source_genesis_hash, + signer: source_sign.clone(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(send_message_call.clone(), 0), + })? + .encode(), + )) + .await?; + source_client + .submit_signed_extrinsic(source_sign.public().into(), move |_, transaction_nonce| { + let signed_source_call = Self::Source::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: source_genesis_hash, + signer: source_sign.clone(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(send_message_call, transaction_nonce), + })? + .encode(); + + log::info!( + target: "bridge", + "Sending message to {}. Lane: {:?}. Size: {}. Fee: {}", + Self::Target::NAME, + lane, + payload_len, + fee, + ); + log::info!( + target: "bridge", + "The source account ({:?}) balance will be reduced by (at most) {} (message fee) + + {} (tx fee ) = {} {} tokens", AccountId32::from(source_sign.public()), + fee.0, + estimated_transaction_fee.inclusion_fee(), + fee.0.saturating_add(estimated_transaction_fee.inclusion_fee().into()), + Self::Source::NAME, + ); + log::info!( + target: "bridge", + "Signed {} Call: {:?}", + Self::Source::NAME, + HexBytes::encode(&signed_source_call) + ); + + Ok(Bytes(signed_source_call)) + }) + .await?; + + Ok(()) + } +} + +impl MessageSender for MillauToRialtoCliBridge {} +impl MessageSender for RialtoToMillauCliBridge {} +impl MessageSender for MillauToRialtoParachainCliBridge {} +impl MessageSender for RialtoParachainToMillauCliBridge {} + impl SendMessage { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { - crate::select_full_bridge!(self.bridge, { - let payload = encode_message::encode_message::(&self.message)?; - - let source_client = self.source.to_client::().await?; - let source_sign = self.source_sign.to_keypair::()?; - - let lane = self.lane.clone().into(); - let conversion_rate_override = self.conversion_rate_override; - let fee = match self.fee { - Some(fee) => fee, - None => Balance( - estimate_message_delivery_and_dispatch_fee::( - &source_client, - conversion_rate_override, - ESTIMATE_MESSAGE_FEE_METHOD, - lane, - payload.clone(), - ) - .await? as _, - ), - }; - let payload_len = payload.encode().len(); - #[allow(clippy::useless_conversion)] - let send_message_call = Source::encode_send_message_call( - self.lane.0, - payload, - fee.cast().into(), - self.bridge.bridge_instance_index(), - )?; - - let source_genesis_hash = *source_client.genesis_hash(); - let (spec_version, transaction_version) = - source_client.simple_runtime_version().await?; - let estimated_transaction_fee = source_client - .estimate_extrinsic_fee(Bytes( - Source::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: source_genesis_hash, - signer: source_sign.clone(), - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(send_message_call.clone(), 0), - })? - .encode(), - )) - .await?; - source_client - .submit_signed_extrinsic(source_sign.public().into(), move |_, transaction_nonce| { - let signed_source_call = Source::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: source_genesis_hash, - signer: source_sign.clone(), - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(send_message_call, transaction_nonce), - })? - .encode(); - - log::info!( - target: "bridge", - "Sending message to {}. Lane: {:?}. Size: {}. Fee: {}", - Target::NAME, - lane, - payload_len, - fee, - ); - log::info!( - target: "bridge", - "The source account ({:?}) balance will be reduced by (at most) {} (message fee) + {} (tx fee ) = {} {} tokens", - AccountId32::from(source_sign.public()), - fee.0, - estimated_transaction_fee.inclusion_fee(), - fee.0.saturating_add(estimated_transaction_fee.inclusion_fee() as _), - Source::NAME, - ); - log::info!( - target: "bridge", - "Signed {} Call: {:?}", - Source::NAME, - HexBytes::encode(&signed_source_call) - ); - - Ok(Bytes(signed_source_call)) - }) - .await?; - }); - - Ok(()) + match self.bridge { + FullBridge::MillauToRialto => MillauToRialtoCliBridge::send_message(self), + FullBridge::RialtoToMillau => RialtoToMillauCliBridge::send_message(self), + FullBridge::MillauToRialtoParachain => + MillauToRialtoParachainCliBridge::send_message(self), + FullBridge::RialtoParachainToMillau => + RialtoParachainToMillauCliBridge::send_message(self), + } + .await } }