[CLI] remove select_full_bridge!() macro

Signed-off-by: Serban Iorga <serban@parity.io>
This commit is contained in:
Serban Iorga
2022-07-06 15:45:30 +03:00
committed by Bastian Köcher
parent 88e95388bb
commit f89eeb920a
5 changed files with 323 additions and 259 deletions
+81 -95
View File
@@ -15,9 +15,12 @@
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use crate::cli::CliChain; use crate::cli::CliChain;
use bp_runtime::{AccountIdOf, SourceAccount};
use relay_substrate_client::{AccountKeyPairOf, Chain, TransactionSignScheme}; use relay_substrate_client::{AccountKeyPairOf, Chain, TransactionSignScheme};
use strum::{EnumString, EnumVariantNames}; 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)] #[derive(Debug, PartialEq, Eq, EnumString, EnumVariantNames)]
#[strum(serialize_all = "kebab_case")] #[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 MILLAU_TO_RIALTO_PARACHAIN_INDEX: u8 = 1;
pub const RIALTO_PARACHAIN_TO_MILLAU_INDEX: u8 = 0; 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. /// Minimal bridge representation that can be used from the CLI.
/// It connects a source chain to a target chain. /// It connects a source chain to a target chain.
pub trait CliBridgeBase: Sized { pub trait CliBridgeBase: Sized {
@@ -145,8 +60,8 @@ pub trait CliBridgeBase: Sized {
+ CliChain<KeyPair = AccountKeyPairOf<Self::Target>>; + CliChain<KeyPair = AccountKeyPairOf<Self::Target>>;
} }
/// Bridge representation that can be used from the CLI. /// Bridge representation that can be used from the CLI for relaying headers.
pub trait CliBridge: CliBridgeBase { pub trait HeadersCliBridge: CliBridgeBase {
/// Finality proofs synchronization pipeline. /// Finality proofs synchronization pipeline.
type Finality: SubstrateFinalitySyncPipeline< type Finality: SubstrateFinalitySyncPipeline<
SourceChain = Self::Source, 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<Self::Source>>,
) -> AccountIdOf<Self::Target>;
}
//// `Millau` to `Rialto` bridge definition. //// `Millau` to `Rialto` bridge definition.
pub struct MillauToRialtoCliBridge {} pub struct MillauToRialtoCliBridge {}
@@ -163,10 +97,22 @@ impl CliBridgeBase for MillauToRialtoCliBridge {
type Target = relay_rialto_client::Rialto; type Target = relay_rialto_client::Rialto;
} }
impl CliBridge for MillauToRialtoCliBridge { impl HeadersCliBridge for MillauToRialtoCliBridge {
type Finality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; 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<Self::Source>>,
) -> AccountIdOf<Self::Target> {
bp_rialto::derive_account_from_millau_id(id)
}
}
//// `Rialto` to `Millau` bridge definition. //// `Rialto` to `Millau` bridge definition.
pub struct RialtoToMillauCliBridge {} pub struct RialtoToMillauCliBridge {}
@@ -175,10 +121,24 @@ impl CliBridgeBase for RialtoToMillauCliBridge {
type Target = relay_millau_client::Millau; type Target = relay_millau_client::Millau;
} }
impl CliBridge for RialtoToMillauCliBridge { impl HeadersCliBridge for RialtoToMillauCliBridge {
type Finality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; 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<Self::Source>>,
) -> AccountIdOf<Self::Target> {
bp_millau::derive_account_from_rialto_id(id)
}
}
//// `Westend` to `Millau` bridge definition. //// `Westend` to `Millau` bridge definition.
pub struct WestendToMillauCliBridge {} pub struct WestendToMillauCliBridge {}
@@ -187,7 +147,7 @@ impl CliBridgeBase for WestendToMillauCliBridge {
type Target = relay_millau_client::Millau; type Target = relay_millau_client::Millau;
} }
impl CliBridge for WestendToMillauCliBridge { impl HeadersCliBridge for WestendToMillauCliBridge {
type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau;
} }
@@ -199,11 +159,24 @@ impl CliBridgeBase for MillauToRialtoParachainCliBridge {
type Target = relay_rialto_parachain_client::RialtoParachain; type Target = relay_rialto_parachain_client::RialtoParachain;
} }
impl CliBridge for MillauToRialtoParachainCliBridge { impl HeadersCliBridge for MillauToRialtoParachainCliBridge {
type Finality = type Finality =
crate::chains::millau_headers_to_rialto_parachain::MillauFinalityToRialtoParachain; 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<Self::Source>>,
) -> AccountIdOf<Self::Target> {
bp_rialto_parachain::derive_account_from_millau_id(id)
}
}
//// `RialtoParachain` to `Millau` bridge definition. //// `RialtoParachain` to `Millau` bridge definition.
pub struct RialtoParachainToMillauCliBridge {} pub struct RialtoParachainToMillauCliBridge {}
@@ -212,6 +185,19 @@ impl CliBridgeBase for RialtoParachainToMillauCliBridge {
type Target = relay_millau_client::Millau; 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<Self::Source>>,
) -> AccountIdOf<Self::Target> {
bp_millau::derive_account_from_rialto_parachain_id(id)
}
}
//// `WestendParachain` to `Millau` bridge definition. //// `WestendParachain` to `Millau` bridge definition.
pub struct WestmintToMillauCliBridge {} pub struct WestmintToMillauCliBridge {}
@@ -14,17 +14,17 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use crate::{ use crate::cli::{
cli::{ bridge::{FullBridge, MessagesCliBridge, *},
bridge::FullBridge, relay_headers_and_messages::CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, relay_headers_and_messages::CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO,
Balance, HexBytes, HexLaneId, SourceConnectionParams, Balance, HexBytes, HexLaneId, SourceConnectionParams,
},
select_full_bridge,
}; };
use async_trait::async_trait;
use bp_runtime::BalanceOf; use bp_runtime::BalanceOf;
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use relay_substrate_client::Chain; use relay_substrate_client::{Chain, ChainBase};
use sp_runtime::FixedU128; use sp_runtime::FixedU128;
use std::fmt::Display;
use structopt::StructOpt; use structopt::StructOpt;
use strum::VariantNames; use strum::VariantNames;
use substrate_relay_helper::helpers::tokens_conversion_rate_from_metrics; 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
<Self::Source as ChainBase>::Balance: Display + Into<u128>,
{
async fn estimate_fee(data: EstimateFee) -> anyhow::Result<()> {
let source_client = data.source.to_client::<Self::Source>().await?;
let lane = data.lane.into();
let payload =
crate::cli::encode_message::encode_message::<Self::Source, Self::Target>(&data.payload)
.map_err(|e| anyhow::format_err!("{:?}", e))?;
let fee = estimate_message_delivery_and_dispatch_fee::<Self::Source, Self::Target, _>(
&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 { impl EstimateFee {
/// Run the command. /// Run the command.
pub async fn run(self) -> anyhow::Result<()> { pub async fn run(self) -> anyhow::Result<()> {
let Self { source, bridge, lane, conversion_rate_override, payload } = self; match self.bridge {
FullBridge::MillauToRialto => MillauToRialtoCliBridge::estimate_fee(self),
select_full_bridge!(bridge, { FullBridge::RialtoToMillau => RialtoToMillauCliBridge::estimate_fee(self),
let source_client = source.to_client::<Source>().await?; FullBridge::MillauToRialtoParachain =>
let lane = lane.into(); MillauToRialtoParachainCliBridge::estimate_fee(self),
let payload = crate::cli::encode_message::encode_message::<Source, Target>(&payload) FullBridge::RialtoParachainToMillau =>
.map_err(|e| anyhow::format_err!("{:?}", e))?; RialtoParachainToMillauCliBridge::estimate_fee(self),
}
let fee = estimate_message_delivery_and_dispatch_fee::<Source, Target, _>( .await
&source_client,
conversion_rate_override,
ESTIMATE_MESSAGE_FEE_METHOD,
lane,
payload,
)
.await?;
log::info!(target: "bridge", "Fee: {:?}", Balance(fee as _));
println!("{}", fee);
Ok(())
})
} }
} }
@@ -24,11 +24,8 @@ use relay_utils::metrics::{GlobalMetrics, StandaloneMetric};
use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline;
use crate::cli::{ use crate::cli::{
bridge::{ bridge::*, PrometheusParams, SourceConnectionParams, TargetConnectionParams,
CliBridge, MillauToRialtoCliBridge, MillauToRialtoParachainCliBridge, TargetSigningParams,
RialtoToMillauCliBridge, WestendToMillauCliBridge,
},
PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams,
}; };
/// Start headers relayer process. /// Start headers relayer process.
@@ -62,7 +59,7 @@ pub enum RelayHeadersBridge {
} }
#[async_trait] #[async_trait]
trait HeadersRelayer: CliBridge trait HeadersRelayer: HeadersCliBridge
where where
<Self::Target as ChainBase>::AccountId: From<<AccountKeyPairOf<Self::Target> as Pair>::Public>, <Self::Target as ChainBase>::AccountId: From<<AccountKeyPairOf<Self::Target> as Pair>::Public>,
{ {
@@ -14,18 +14,21 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use async_trait::async_trait;
use sp_core::Pair;
use structopt::StructOpt; use structopt::StructOpt;
use strum::{EnumString, EnumVariantNames, VariantNames}; use strum::{EnumString, EnumVariantNames, VariantNames};
use messages_relay::relay_strategy::MixStrategy; 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::{ use crate::cli::{
cli::{ bridge::*, CliChain, HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams,
bridge::FullBridge, HexLaneId, PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams,
SourceSigningParams, TargetConnectionParams, TargetSigningParams,
},
select_full_bridge,
}; };
/// Relayer operating mode. /// Relayer operating mode.
@@ -71,40 +74,66 @@ pub struct RelayMessages {
prometheus_params: PrometheusParams, prometheus_params: PrometheusParams,
} }
#[async_trait]
trait MessagesRelayer: MessagesCliBridge
where
Self::Source: TransactionSignScheme<Chain = Self::Source>
+ CliChain<KeyPair = AccountKeyPairOf<Self::Source>>,
<Self::Source as ChainBase>::AccountId: From<<AccountKeyPairOf<Self::Source> as Pair>::Public>,
<Self::Target as ChainBase>::AccountId: From<<AccountKeyPairOf<Self::Target> as Pair>::Public>,
<Self::Source as ChainBase>::Balance: TryFrom<<Self::Target as ChainBase>::Balance>,
Self::MessagesLane: SubstrateMessageLane<RelayStrategy = MixStrategy>,
{
async fn relay_messages(data: RelayMessages) -> anyhow::Result<()> {
let source_client = data.source.to_client::<Self::Source>().await?;
let source_sign = data.source_sign.to_keypair::<Self::Source>()?;
let source_transactions_mortality = data.source_sign.transactions_mortality()?;
let target_client = data.target.to_client::<Self::Target>().await?;
let target_sign = data.target_sign.to_keypair::<Self::Target>()?;
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::<Self::MessagesLane>(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 { impl RelayMessages {
/// Run the command. /// Run the command.
pub async fn run(self) -> anyhow::Result<()> { pub async fn run(self) -> anyhow::Result<()> {
select_full_bridge!(self.bridge, { match self.bridge {
let source_client = self.source.to_client::<Source>().await?; FullBridge::MillauToRialto => MillauToRialtoCliBridge::relay_messages(self),
let source_sign = self.source_sign.to_keypair::<Source>()?; FullBridge::RialtoToMillau => RialtoToMillauCliBridge::relay_messages(self),
let source_transactions_mortality = self.source_sign.transactions_mortality()?; FullBridge::MillauToRialtoParachain =>
let target_client = self.target.to_client::<Target>().await?; MillauToRialtoParachainCliBridge::relay_messages(self),
let target_sign = self.target_sign.to_keypair::<Target>()?; FullBridge::RialtoParachainToMillau =>
let target_transactions_mortality = self.target_sign.transactions_mortality()?; RialtoParachainToMillauCliBridge::relay_messages(self),
let relayer_mode = self.relayer_mode.into(); }
let relay_strategy = MixStrategy::new(relayer_mode); .await
substrate_relay_helper::messages_lane::run::<MessagesLane>(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))
})
} }
} }
@@ -15,16 +15,20 @@
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use crate::cli::{ use crate::cli::{
bridge::FullBridge, bridge::{FullBridge, MessagesCliBridge, *},
encode_message::{self, CliEncodeMessage}, encode_message::{self, CliEncodeMessage},
estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride}, 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 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_core::{Bytes, Pair};
use sp_runtime::AccountId32; use sp_runtime::AccountId32;
use std::fmt::Debug; use std::fmt::{Debug, Display};
use structopt::StructOpt; use structopt::StructOpt;
use strum::{EnumString, EnumVariantNames, VariantNames}; use strum::{EnumString, EnumVariantNames, VariantNames};
@@ -75,97 +79,125 @@ pub struct SendMessage {
message: crate::cli::encode_message::Message, message: crate::cli::encode_message::Message,
} }
#[async_trait]
trait MessageSender: MessagesCliBridge
where
Self::Source: ChainBase<Index = u32>
+ TransactionSignScheme<Chain = Self::Source>
+ CliChain<KeyPair = AccountKeyPairOf<Self::Source>>
+ CliEncodeMessage,
<Self::Source as ChainBase>::Balance: Display + From<u64> + Into<u128>,
<Self::Source as Chain>::Call: Sync,
<Self::Source as TransactionSignScheme>::SignedTransaction: Sync,
AccountIdOf<Self::Source>: From<<AccountKeyPairOf<Self::Source> as Pair>::Public>,
AccountId32: From<<AccountKeyPairOf<Self::Source> as Pair>::Public>,
{
async fn send_message(data: SendMessage) -> anyhow::Result<()> {
let payload = encode_message::encode_message::<Self::Source, Self::Target>(&data.message)?;
let source_client = data.source.to_client::<Self::Source>().await?;
let source_sign = data.source_sign.to_keypair::<Self::Source>()?;
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::<Self::Source, Self::Target, _>(
&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 { impl SendMessage {
/// Run the command. /// Run the command.
pub async fn run(self) -> anyhow::Result<()> { pub async fn run(self) -> anyhow::Result<()> {
crate::select_full_bridge!(self.bridge, { match self.bridge {
let payload = encode_message::encode_message::<Source, Target>(&self.message)?; FullBridge::MillauToRialto => MillauToRialtoCliBridge::send_message(self),
FullBridge::RialtoToMillau => RialtoToMillauCliBridge::send_message(self),
let source_client = self.source.to_client::<Source>().await?; FullBridge::MillauToRialtoParachain =>
let source_sign = self.source_sign.to_keypair::<Source>()?; MillauToRialtoParachainCliBridge::send_message(self),
FullBridge::RialtoParachainToMillau =>
let lane = self.lane.clone().into(); RialtoParachainToMillauCliBridge::send_message(self),
let conversion_rate_override = self.conversion_rate_override; }
let fee = match self.fee { .await
Some(fee) => fee,
None => Balance(
estimate_message_delivery_and_dispatch_fee::<Source, Target, _>(
&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(())
} }
} }