diff --git a/bridges/relays/bin-substrate/src/cli/bridge.rs b/bridges/relays/bin-substrate/src/cli/bridge.rs
index 2184903e01..5a5715699c 100644
--- a/bridges/relays/bin-substrate/src/cli/bridge.rs
+++ b/bridges/relays/bin-substrate/src/cli/bridge.rs
@@ -17,7 +17,7 @@
use structopt::clap::arg_enum;
arg_enum! {
- #[derive(Debug)]
+ #[derive(Debug, PartialEq, Eq)]
/// Supported full bridges (headers + messages).
pub enum FullBridge {
MillauToRialto,
@@ -59,9 +59,9 @@ macro_rules! select_full_bridge {
#[allow(unused_imports)]
use crate::rialto_millau::millau_messages_to_rialto::run as relay_messages;
- // Send-message
+ // Send-message / Estimate-fee
#[allow(unused_imports)]
- use bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD;
+ use bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD;
// Send-message
#[allow(unused_imports)]
use millau_runtime::rialto_account_ownership_digest as account_ownership_digest;
@@ -81,9 +81,10 @@ macro_rules! select_full_bridge {
#[allow(unused_imports)]
use crate::rialto_millau::rialto_messages_to_millau::run as relay_messages;
- // Send-message
+ // Send-message / Estimate-fee
#[allow(unused_imports)]
- use bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD;
+ use bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD;
+
// Send-message
#[allow(unused_imports)]
use rialto_runtime::millau_account_ownership_digest as account_ownership_digest;
diff --git a/bridges/relays/bin-substrate/src/cli/encode_call.rs b/bridges/relays/bin-substrate/src/cli/encode_call.rs
index b5cdaaa1d3..6e1130cffc 100644
--- a/bridges/relays/bin-substrate/src/cli/encode_call.rs
+++ b/bridges/relays/bin-substrate/src/cli/encode_call.rs
@@ -35,7 +35,7 @@ pub struct EncodeCall {
///
/// Note this enum may be used in the context of both Source (as part of `encode-call`)
/// and Target chain (as part of `encode-message/send-message`).
-#[derive(StructOpt, Debug)]
+#[derive(StructOpt, Debug, PartialEq, Eq)]
pub enum Call {
/// Raw bytes for the message
Raw {
diff --git a/bridges/relays/bin-substrate/src/cli/encode_message.rs b/bridges/relays/bin-substrate/src/cli/encode_message.rs
index 5ef668864e..a29aa8597d 100644
--- a/bridges/relays/bin-substrate/src/cli/encode_message.rs
+++ b/bridges/relays/bin-substrate/src/cli/encode_message.rs
@@ -19,7 +19,7 @@ use crate::select_full_bridge;
use structopt::StructOpt;
/// Generic message payload.
-#[derive(StructOpt, Debug)]
+#[derive(StructOpt, Debug, PartialEq, Eq)]
pub enum MessagePayload {
/// Raw, SCALE-encoded `MessagePayload`.
Raw {
diff --git a/bridges/relays/bin-substrate/src/cli/estimate_fee.rs b/bridges/relays/bin-substrate/src/cli/estimate_fee.rs
new file mode 100644
index 0000000000..4e39ad351e
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/cli/estimate_fee.rs
@@ -0,0 +1,128 @@
+// 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 .
+
+use crate::cli::bridge::FullBridge;
+use crate::cli::{Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams};
+use crate::select_full_bridge;
+use codec::{Decode, Encode};
+use relay_substrate_client::{Chain, ChainWithBalances};
+use structopt::StructOpt;
+
+/// Estimate Delivery & Dispatch Fee command.
+#[derive(StructOpt, Debug, PartialEq, Eq)]
+pub struct EstimateFee {
+ /// A bridge instance to encode call for.
+ #[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)]
+ bridge: FullBridge,
+ #[structopt(flatten)]
+ source: SourceConnectionParams,
+ /// Hex-encoded id of lane that will be delivering the message.
+ #[structopt(long, default_value = "00000000")]
+ lane: HexLaneId,
+ /// Payload to send over the bridge.
+ #[structopt(flatten)]
+ payload: crate::cli::encode_message::MessagePayload,
+}
+
+impl EstimateFee {
+ /// Run the command.
+ pub async fn run(self) -> anyhow::Result<()> {
+ let Self {
+ source,
+ bridge,
+ lane,
+ payload,
+ } = self;
+
+ select_full_bridge!(bridge, {
+ let source_client = source.to_client::().await?;
+ let lane = lane.into();
+ let payload = Source::encode_message(payload).map_err(|e| anyhow::format_err!("{:?}", e))?;
+
+ let fee: ::NativeBalance =
+ estimate_message_delivery_and_dispatch_fee(&source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload)
+ .await?;
+
+ log::info!(target: "bridge", "Fee: {:?}", Balance(fee as _));
+ println!("{}", fee);
+ Ok(())
+ })
+ }
+}
+
+pub(crate) async fn estimate_message_delivery_and_dispatch_fee(
+ client: &relay_substrate_client::Client,
+ estimate_fee_method: &str,
+ lane: bp_messages::LaneId,
+ payload: P,
+) -> anyhow::Result {
+ let encoded_response = client
+ .state_call(estimate_fee_method.into(), (lane, payload).encode().into(), None)
+ .await?;
+ let decoded_response: Option =
+ Decode::decode(&mut &encoded_response.0[..]).map_err(relay_substrate_client::Error::ResponseParseFailed)?;
+ let fee = decoded_response
+ .ok_or_else(|| anyhow::format_err!("Unable to decode fee from: {:?}", HexBytes(encoded_response.to_vec())))?;
+ Ok(fee)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::cli::encode_call;
+ use sp_core::crypto::Ss58Codec;
+
+ #[test]
+ fn should_parse_cli_options() {
+ // given
+ let alice = sp_keyring::AccountKeyring::Alice.to_account_id().to_ss58check();
+
+ // when
+ let res = EstimateFee::from_iter(vec![
+ "estimate_fee",
+ "RialtoToMillau",
+ "--source-port",
+ "1234",
+ "call",
+ "--sender",
+ &alice,
+ "remark",
+ "--remark-payload",
+ "1234",
+ ]);
+
+ // then
+ assert_eq!(
+ res,
+ EstimateFee {
+ bridge: FullBridge::RialtoToMillau,
+ lane: HexLaneId([0, 0, 0, 0]),
+ source: SourceConnectionParams {
+ source_host: "127.0.0.1".into(),
+ source_port: 1234,
+ source_secure: false,
+ },
+ payload: crate::cli::encode_message::MessagePayload::Call {
+ sender: alice.parse().unwrap(),
+ call: encode_call::Call::Remark {
+ remark_payload: Some(HexBytes(vec![0x12, 0x34])),
+ remark_size: None,
+ }
+ }
+ }
+ );
+ }
+}
diff --git a/bridges/relays/bin-substrate/src/cli/mod.rs b/bridges/relays/bin-substrate/src/cli/mod.rs
index 960e85ea92..c77d5071db 100644
--- a/bridges/relays/bin-substrate/src/cli/mod.rs
+++ b/bridges/relays/bin-substrate/src/cli/mod.rs
@@ -18,7 +18,6 @@
use std::convert::TryInto;
-use crate::rialto_millau::cli as rialto_millau;
use bp_messages::LaneId;
use codec::{Decode, Encode};
use frame_support::weights::Weight;
@@ -28,12 +27,13 @@ use structopt::{clap::arg_enum, StructOpt};
pub(crate) mod bridge;
pub(crate) mod encode_call;
pub(crate) mod encode_message;
+pub(crate) mod estimate_fee;
+pub(crate) mod send_message;
mod derive_account;
mod init_bridge;
mod relay_headers;
mod relay_messages;
-mod send_message;
/// Parse relay CLI args.
pub fn parse_args() -> Command {
@@ -75,7 +75,7 @@ pub enum Command {
/// the bridge.
EncodeMessage(encode_message::EncodeMessage),
/// Estimate Delivery and Dispatch Fee required for message submission to messages pallet.
- EstimateFee(EstimateFee),
+ EstimateFee(estimate_fee::EstimateFee),
/// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain.
DeriveAccount(derive_account::DeriveAccount),
}
@@ -97,23 +97,6 @@ impl Command {
}
}
-/// Estimate Delivery & Dispatch Fee command.
-#[derive(StructOpt)]
-pub enum EstimateFee {
- #[structopt(flatten)]
- RialtoMillau(rialto_millau::EstimateFee),
-}
-
-impl EstimateFee {
- /// Run the command.
- pub async fn run(self) -> anyhow::Result<()> {
- match self {
- Self::RialtoMillau(arg) => arg.run().await?,
- }
- Ok(())
- }
-}
-
arg_enum! {
#[derive(Debug)]
/// The origin to use when dispatching the message on the target chain.
@@ -127,7 +110,7 @@ arg_enum! {
}
/// Generic balance type.
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Balance(pub u128);
impl std::fmt::Display for Balance {
@@ -242,7 +225,7 @@ pub trait CliChain: relay_substrate_client::Chain {
}
/// Lane id.
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HexLaneId(pub LaneId);
impl From for LaneId {
@@ -262,7 +245,7 @@ impl std::str::FromStr for HexLaneId {
}
/// Nicer formatting for raw bytes vectors.
-#[derive(Default, Encode, Decode)]
+#[derive(Default, Encode, Decode, PartialEq, Eq)]
pub struct HexBytes(pub Vec);
impl std::str::FromStr for HexBytes {
@@ -321,7 +304,7 @@ impl From for relay_utils::metrics::MetricsParams {
}
/// Either explicit or maximal allowed value.
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ExplicitOrMaximal {
/// User has explicitly specified argument value.
Explicit(V),
@@ -353,7 +336,7 @@ macro_rules! declare_chain_options {
($chain:ident, $chain_prefix:ident) => {
paste::item! {
#[doc = $chain " connection params."]
- #[derive(StructOpt)]
+ #[derive(StructOpt, Debug, PartialEq, Eq)]
pub struct [<$chain ConnectionParams>] {
#[doc = "Connect to " $chain " node at given host."]
#[structopt(long, default_value = "127.0.0.1")]
@@ -367,7 +350,7 @@ macro_rules! declare_chain_options {
}
#[doc = $chain " signing params."]
- #[derive(StructOpt)]
+ #[derive(StructOpt, Debug, PartialEq, Eq)]
pub struct [<$chain SigningParams>] {
#[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."]
#[structopt(long)]
diff --git a/bridges/relays/bin-substrate/src/cli/send_message.rs b/bridges/relays/bin-substrate/src/cli/send_message.rs
index e6ab7dcfa7..64448f0f1d 100644
--- a/bridges/relays/bin-substrate/src/cli/send_message.rs
+++ b/bridges/relays/bin-substrate/src/cli/send_message.rs
@@ -16,6 +16,7 @@
use crate::cli::bridge::FullBridge;
use crate::cli::encode_call::{self, CliEncodeCall};
+use crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee;
use crate::cli::{
Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams,
TargetSigningParams,
@@ -26,6 +27,7 @@ use pallet_bridge_dispatch::{CallOrigin, MessagePayload};
use relay_substrate_client::{Chain, TransactionSignScheme};
use sp_core::{Bytes, Pair};
use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner};
+use std::fmt::Debug;
use structopt::StructOpt;
/// Send bridge message.
@@ -84,12 +86,12 @@ impl SendMessage {
let target_call_weight = prepare_call_dispatch_weight(
dispatch_weight,
ExplicitOrMaximal::Explicit(target_call.get_dispatch_info().weight),
- crate::rialto_millau::compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()),
+ compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()),
);
let source_sender_public: MultiSigner = source_sign.public().into();
let source_account_id = source_sender_public.into_account();
- crate::rialto_millau::message_payload(
+ message_payload(
Target::RUNTIME_VERSION.spec_version,
target_call_weight,
match origin {
@@ -127,14 +129,14 @@ impl SendMessage {
let lane = self.lane.clone().into();
let fee = match self.fee {
Some(fee) => fee,
- None => crate::rialto_millau::estimate_message_delivery_and_dispatch_fee::<
- ::NativeBalance,
- _,
- _,
- >(&source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone())
- .await?
- .map(|v| Balance(v as _))
- .ok_or_else(|| anyhow::format_err!("Failed to estimate message fee. Message is too heavy?"))?,
+ None => Balance(
+ estimate_message_delivery_and_dispatch_fee::<
+ ::NativeBalance,
+ _,
+ _,
+ >(&source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone())
+ .await? as _,
+ ),
};
let dispatch_weight = payload.weight;
let send_message_call = Source::encode_call(&encode_call::Call::BridgeSendMessage {
@@ -192,6 +194,47 @@ fn prepare_call_dispatch_weight(
}
}
+pub(crate) fn message_payload(
+ spec_version: u32,
+ weight: Weight,
+ origin: CallOrigin,
+ call: &impl Encode,
+) -> MessagePayload>
+where
+ SAccountId: Encode + Debug,
+ TPublic: Encode + Debug,
+ TSignature: Encode + Debug,
+{
+ // Display nicely formatted call.
+ let payload = MessagePayload {
+ spec_version,
+ weight,
+ origin,
+ call: HexBytes::encode(call),
+ };
+
+ log::info!(target: "bridge", "Created Message Payload: {:#?}", payload);
+ log::info!(target: "bridge", "Encoded Message Payload: {:?}", HexBytes::encode(&payload));
+
+ // re-pack to return `Vec`
+ let MessagePayload {
+ spec_version,
+ weight,
+ origin,
+ call,
+ } = payload;
+ MessagePayload {
+ spec_version,
+ weight,
+ origin,
+ call: call.0,
+ }
+}
+
+pub(crate) fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight {
+ bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight)
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/bridges/relays/bin-substrate/src/rialto_millau/cli.rs b/bridges/relays/bin-substrate/src/rialto_millau/cli.rs
deleted file mode 100644
index 841f5427ba..0000000000
--- a/bridges/relays/bin-substrate/src/rialto_millau/cli.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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 .
-
-//! Deal with CLI args of Rialto <> Millau relay.
-
-use structopt::StructOpt;
-
-use crate::cli::{HexLaneId, SourceConnectionParams};
-
-/// Estimate Delivery & Dispatch Fee command.
-///
-/// TODO [#855] Move to separate module.
-#[derive(StructOpt)]
-pub enum EstimateFee {
- /// Estimate fee of Rialto to Millau message.
- RialtoToMillau {
- #[structopt(flatten)]
- source: SourceConnectionParams,
- /// Hex-encoded id of lane that will be delivering the message.
- #[structopt(long)]
- lane: HexLaneId,
- /// Payload to send over the bridge.
- #[structopt(flatten)]
- payload: crate::cli::encode_message::MessagePayload,
- },
- /// Estimate fee of Rialto to Millau message.
- MillauToRialto {
- #[structopt(flatten)]
- source: SourceConnectionParams,
- /// Hex-encoded id of lane that will be delivering the message.
- #[structopt(long)]
- lane: HexLaneId,
- /// Payload to send over the bridge.
- #[structopt(flatten)]
- payload: crate::cli::encode_message::MessagePayload,
- },
-}
-
-impl EstimateFee {
- /// Run the command.
- pub async fn run(self) -> anyhow::Result<()> {
- super::run_estimate_fee(self).await.map_err(format_err)?;
- Ok(())
- }
-}
-
-fn format_err(err: String) -> anyhow::Error {
- anyhow::anyhow!(err)
-}
diff --git a/bridges/relays/bin-substrate/src/rialto_millau/mod.rs b/bridges/relays/bin-substrate/src/rialto_millau/mod.rs
index 6b61653ae3..a04cd55f7d 100644
--- a/bridges/relays/bin-substrate/src/rialto_millau/mod.rs
+++ b/bridges/relays/bin-substrate/src/rialto_millau/mod.rs
@@ -16,7 +16,6 @@
//! Rialto <> Millau Bridge commands.
-pub mod cli;
pub mod millau_headers_to_rialto;
pub mod millau_messages_to_rialto;
pub mod rialto_headers_to_millau;
@@ -31,111 +30,15 @@ pub type RialtoClient = relay_substrate_client::Client;
use crate::cli::{
bridge,
encode_call::{self, Call, CliEncodeCall},
- encode_message, CliChain, HexBytes,
+ encode_message, send_message, CliChain,
};
-use codec::{Decode, Encode};
+use codec::Decode;
use frame_support::weights::{GetDispatchInfo, Weight};
use pallet_bridge_dispatch::{CallOrigin, MessagePayload};
use relay_millau_client::Millau;
use relay_rialto_client::Rialto;
-use relay_substrate_client::Chain;
use relay_westend_client::Westend;
use sp_version::RuntimeVersion;
-use std::fmt::Debug;
-
-async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> {
- match cmd {
- cli::EstimateFee::RialtoToMillau { source, lane, payload } => {
- type Source = Rialto;
- type SourceBalance = bp_rialto::Balance;
-
- let estimate_message_fee_method = bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD;
-
- let source_client = source.to_client::().await.map_err(format_err)?;
- let lane = lane.into();
- let payload = Source::encode_message(payload)?;
-
- let fee: Option =
- estimate_message_delivery_and_dispatch_fee(&source_client, estimate_message_fee_method, lane, payload)
- .await?;
-
- println!("Fee: {:?}", fee);
- }
- cli::EstimateFee::MillauToRialto { source, lane, payload } => {
- type Source = Millau;
- type SourceBalance = bp_millau::Balance;
-
- let estimate_message_fee_method = bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD;
-
- let source_client = source.to_client::().await.map_err(format_err)?;
- let lane = lane.into();
- let payload = Source::encode_message(payload)?;
-
- let fee: Option =
- estimate_message_delivery_and_dispatch_fee(&source_client, estimate_message_fee_method, lane, payload)
- .await?;
-
- println!("Fee: {:?}", fee);
- }
- }
-
- Ok(())
-}
-
-pub(crate) async fn estimate_message_delivery_and_dispatch_fee(
- client: &relay_substrate_client::Client,
- estimate_fee_method: &str,
- lane: bp_messages::LaneId,
- payload: P,
-) -> Result