mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 21:01:02 +00:00
CLI: Estimate Fee (#888)
* Move estimate-fee * Add parsing test. * Address review comments. * Fix compilation. * Move things around. Co-authored-by: Svyatoslav Nikolsky <svyatonik@gmail.com>
This commit is contained in:
committed by
Bastian Köcher
parent
9f01c459bd
commit
a2566970eb
@@ -17,7 +17,7 @@
|
|||||||
use structopt::clap::arg_enum;
|
use structopt::clap::arg_enum;
|
||||||
|
|
||||||
arg_enum! {
|
arg_enum! {
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
/// Supported full bridges (headers + messages).
|
/// Supported full bridges (headers + messages).
|
||||||
pub enum FullBridge {
|
pub enum FullBridge {
|
||||||
MillauToRialto,
|
MillauToRialto,
|
||||||
@@ -59,9 +59,9 @@ macro_rules! select_full_bridge {
|
|||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use crate::rialto_millau::millau_messages_to_rialto::run as relay_messages;
|
use crate::rialto_millau::millau_messages_to_rialto::run as relay_messages;
|
||||||
|
|
||||||
// Send-message
|
// Send-message / Estimate-fee
|
||||||
#[allow(unused_imports)]
|
#[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
|
// Send-message
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use millau_runtime::rialto_account_ownership_digest as account_ownership_digest;
|
use millau_runtime::rialto_account_ownership_digest as account_ownership_digest;
|
||||||
@@ -81,9 +81,10 @@ macro_rules! select_full_bridge {
|
|||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use crate::rialto_millau::rialto_messages_to_millau::run as relay_messages;
|
use crate::rialto_millau::rialto_messages_to_millau::run as relay_messages;
|
||||||
|
|
||||||
// Send-message
|
// Send-message / Estimate-fee
|
||||||
#[allow(unused_imports)]
|
#[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
|
// Send-message
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use rialto_runtime::millau_account_ownership_digest as account_ownership_digest;
|
use rialto_runtime::millau_account_ownership_digest as account_ownership_digest;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ pub struct EncodeCall {
|
|||||||
///
|
///
|
||||||
/// Note this enum may be used in the context of both Source (as part of `encode-call`)
|
/// 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`).
|
/// and Target chain (as part of `encode-message/send-message`).
|
||||||
#[derive(StructOpt, Debug)]
|
#[derive(StructOpt, Debug, PartialEq, Eq)]
|
||||||
pub enum Call {
|
pub enum Call {
|
||||||
/// Raw bytes for the message
|
/// Raw bytes for the message
|
||||||
Raw {
|
Raw {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use crate::select_full_bridge;
|
|||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
/// Generic message payload.
|
/// Generic message payload.
|
||||||
#[derive(StructOpt, Debug)]
|
#[derive(StructOpt, Debug, PartialEq, Eq)]
|
||||||
pub enum MessagePayload {
|
pub enum MessagePayload {
|
||||||
/// Raw, SCALE-encoded `MessagePayload`.
|
/// Raw, SCALE-encoded `MessagePayload`.
|
||||||
Raw {
|
Raw {
|
||||||
|
|||||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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::<Source>().await?;
|
||||||
|
let lane = lane.into();
|
||||||
|
let payload = Source::encode_message(payload).map_err(|e| anyhow::format_err!("{:?}", e))?;
|
||||||
|
|
||||||
|
let fee: <Source as ChainWithBalances>::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<Fee: Decode, C: Chain, P: Encode>(
|
||||||
|
client: &relay_substrate_client::Client<C>,
|
||||||
|
estimate_fee_method: &str,
|
||||||
|
lane: bp_messages::LaneId,
|
||||||
|
payload: P,
|
||||||
|
) -> anyhow::Result<Fee> {
|
||||||
|
let encoded_response = client
|
||||||
|
.state_call(estimate_fee_method.into(), (lane, payload).encode().into(), None)
|
||||||
|
.await?;
|
||||||
|
let decoded_response: Option<Fee> =
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
use crate::rialto_millau::cli as rialto_millau;
|
|
||||||
use bp_messages::LaneId;
|
use bp_messages::LaneId;
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_support::weights::Weight;
|
use frame_support::weights::Weight;
|
||||||
@@ -28,12 +27,13 @@ use structopt::{clap::arg_enum, StructOpt};
|
|||||||
pub(crate) mod bridge;
|
pub(crate) mod bridge;
|
||||||
pub(crate) mod encode_call;
|
pub(crate) mod encode_call;
|
||||||
pub(crate) mod encode_message;
|
pub(crate) mod encode_message;
|
||||||
|
pub(crate) mod estimate_fee;
|
||||||
|
pub(crate) mod send_message;
|
||||||
|
|
||||||
mod derive_account;
|
mod derive_account;
|
||||||
mod init_bridge;
|
mod init_bridge;
|
||||||
mod relay_headers;
|
mod relay_headers;
|
||||||
mod relay_messages;
|
mod relay_messages;
|
||||||
mod send_message;
|
|
||||||
|
|
||||||
/// Parse relay CLI args.
|
/// Parse relay CLI args.
|
||||||
pub fn parse_args() -> Command {
|
pub fn parse_args() -> Command {
|
||||||
@@ -75,7 +75,7 @@ pub enum Command {
|
|||||||
/// the bridge.
|
/// the bridge.
|
||||||
EncodeMessage(encode_message::EncodeMessage),
|
EncodeMessage(encode_message::EncodeMessage),
|
||||||
/// Estimate Delivery and Dispatch Fee required for message submission to messages pallet.
|
/// 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.
|
/// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain.
|
||||||
DeriveAccount(derive_account::DeriveAccount),
|
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! {
|
arg_enum! {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// The origin to use when dispatching the message on the target chain.
|
/// The origin to use when dispatching the message on the target chain.
|
||||||
@@ -127,7 +110,7 @@ arg_enum! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generic balance type.
|
/// Generic balance type.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct Balance(pub u128);
|
pub struct Balance(pub u128);
|
||||||
|
|
||||||
impl std::fmt::Display for Balance {
|
impl std::fmt::Display for Balance {
|
||||||
@@ -242,7 +225,7 @@ pub trait CliChain: relay_substrate_client::Chain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Lane id.
|
/// Lane id.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct HexLaneId(pub LaneId);
|
pub struct HexLaneId(pub LaneId);
|
||||||
|
|
||||||
impl From<HexLaneId> for LaneId {
|
impl From<HexLaneId> for LaneId {
|
||||||
@@ -262,7 +245,7 @@ impl std::str::FromStr for HexLaneId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Nicer formatting for raw bytes vectors.
|
/// Nicer formatting for raw bytes vectors.
|
||||||
#[derive(Default, Encode, Decode)]
|
#[derive(Default, Encode, Decode, PartialEq, Eq)]
|
||||||
pub struct HexBytes(pub Vec<u8>);
|
pub struct HexBytes(pub Vec<u8>);
|
||||||
|
|
||||||
impl std::str::FromStr for HexBytes {
|
impl std::str::FromStr for HexBytes {
|
||||||
@@ -321,7 +304,7 @@ impl From<PrometheusParams> for relay_utils::metrics::MetricsParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Either explicit or maximal allowed value.
|
/// Either explicit or maximal allowed value.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum ExplicitOrMaximal<V> {
|
pub enum ExplicitOrMaximal<V> {
|
||||||
/// User has explicitly specified argument value.
|
/// User has explicitly specified argument value.
|
||||||
Explicit(V),
|
Explicit(V),
|
||||||
@@ -353,7 +336,7 @@ macro_rules! declare_chain_options {
|
|||||||
($chain:ident, $chain_prefix:ident) => {
|
($chain:ident, $chain_prefix:ident) => {
|
||||||
paste::item! {
|
paste::item! {
|
||||||
#[doc = $chain " connection params."]
|
#[doc = $chain " connection params."]
|
||||||
#[derive(StructOpt)]
|
#[derive(StructOpt, Debug, PartialEq, Eq)]
|
||||||
pub struct [<$chain ConnectionParams>] {
|
pub struct [<$chain ConnectionParams>] {
|
||||||
#[doc = "Connect to " $chain " node at given host."]
|
#[doc = "Connect to " $chain " node at given host."]
|
||||||
#[structopt(long, default_value = "127.0.0.1")]
|
#[structopt(long, default_value = "127.0.0.1")]
|
||||||
@@ -367,7 +350,7 @@ macro_rules! declare_chain_options {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[doc = $chain " signing params."]
|
#[doc = $chain " signing params."]
|
||||||
#[derive(StructOpt)]
|
#[derive(StructOpt, Debug, PartialEq, Eq)]
|
||||||
pub struct [<$chain SigningParams>] {
|
pub struct [<$chain SigningParams>] {
|
||||||
#[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."]
|
#[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."]
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
use crate::cli::bridge::FullBridge;
|
use crate::cli::bridge::FullBridge;
|
||||||
use crate::cli::encode_call::{self, CliEncodeCall};
|
use crate::cli::encode_call::{self, CliEncodeCall};
|
||||||
|
use crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee;
|
||||||
use crate::cli::{
|
use crate::cli::{
|
||||||
Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams,
|
Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams,
|
||||||
TargetSigningParams,
|
TargetSigningParams,
|
||||||
@@ -26,6 +27,7 @@ use pallet_bridge_dispatch::{CallOrigin, MessagePayload};
|
|||||||
use relay_substrate_client::{Chain, TransactionSignScheme};
|
use relay_substrate_client::{Chain, TransactionSignScheme};
|
||||||
use sp_core::{Bytes, Pair};
|
use sp_core::{Bytes, Pair};
|
||||||
use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner};
|
use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner};
|
||||||
|
use std::fmt::Debug;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
/// Send bridge message.
|
/// Send bridge message.
|
||||||
@@ -84,12 +86,12 @@ impl SendMessage {
|
|||||||
let target_call_weight = prepare_call_dispatch_weight(
|
let target_call_weight = prepare_call_dispatch_weight(
|
||||||
dispatch_weight,
|
dispatch_weight,
|
||||||
ExplicitOrMaximal::Explicit(target_call.get_dispatch_info().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_sender_public: MultiSigner = source_sign.public().into();
|
||||||
let source_account_id = source_sender_public.into_account();
|
let source_account_id = source_sender_public.into_account();
|
||||||
|
|
||||||
crate::rialto_millau::message_payload(
|
message_payload(
|
||||||
Target::RUNTIME_VERSION.spec_version,
|
Target::RUNTIME_VERSION.spec_version,
|
||||||
target_call_weight,
|
target_call_weight,
|
||||||
match origin {
|
match origin {
|
||||||
@@ -127,14 +129,14 @@ impl SendMessage {
|
|||||||
let lane = self.lane.clone().into();
|
let lane = self.lane.clone().into();
|
||||||
let fee = match self.fee {
|
let fee = match self.fee {
|
||||||
Some(fee) => fee,
|
Some(fee) => fee,
|
||||||
None => crate::rialto_millau::estimate_message_delivery_and_dispatch_fee::<
|
None => Balance(
|
||||||
<Source as relay_substrate_client::ChainWithBalances>::NativeBalance,
|
estimate_message_delivery_and_dispatch_fee::<
|
||||||
_,
|
<Source as relay_substrate_client::ChainWithBalances>::NativeBalance,
|
||||||
_,
|
_,
|
||||||
>(&source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone())
|
_,
|
||||||
.await?
|
>(&source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone())
|
||||||
.map(|v| Balance(v as _))
|
.await? as _,
|
||||||
.ok_or_else(|| anyhow::format_err!("Failed to estimate message fee. Message is too heavy?"))?,
|
),
|
||||||
};
|
};
|
||||||
let dispatch_weight = payload.weight;
|
let dispatch_weight = payload.weight;
|
||||||
let send_message_call = Source::encode_call(&encode_call::Call::BridgeSendMessage {
|
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<SAccountId, TPublic, TSignature>(
|
||||||
|
spec_version: u32,
|
||||||
|
weight: Weight,
|
||||||
|
origin: CallOrigin<SAccountId, TPublic, TSignature>,
|
||||||
|
call: &impl Encode,
|
||||||
|
) -> MessagePayload<SAccountId, TPublic, TSignature, Vec<u8>>
|
||||||
|
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<u8>`
|
||||||
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
//! 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)
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
//! Rialto <> Millau Bridge commands.
|
//! Rialto <> Millau Bridge commands.
|
||||||
|
|
||||||
pub mod cli;
|
|
||||||
pub mod millau_headers_to_rialto;
|
pub mod millau_headers_to_rialto;
|
||||||
pub mod millau_messages_to_rialto;
|
pub mod millau_messages_to_rialto;
|
||||||
pub mod rialto_headers_to_millau;
|
pub mod rialto_headers_to_millau;
|
||||||
@@ -31,111 +30,15 @@ pub type RialtoClient = relay_substrate_client::Client<Rialto>;
|
|||||||
use crate::cli::{
|
use crate::cli::{
|
||||||
bridge,
|
bridge,
|
||||||
encode_call::{self, Call, CliEncodeCall},
|
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 frame_support::weights::{GetDispatchInfo, Weight};
|
||||||
use pallet_bridge_dispatch::{CallOrigin, MessagePayload};
|
use pallet_bridge_dispatch::{CallOrigin, MessagePayload};
|
||||||
use relay_millau_client::Millau;
|
use relay_millau_client::Millau;
|
||||||
use relay_rialto_client::Rialto;
|
use relay_rialto_client::Rialto;
|
||||||
use relay_substrate_client::Chain;
|
|
||||||
use relay_westend_client::Westend;
|
use relay_westend_client::Westend;
|
||||||
use sp_version::RuntimeVersion;
|
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::<Source>().await.map_err(format_err)?;
|
|
||||||
let lane = lane.into();
|
|
||||||
let payload = Source::encode_message(payload)?;
|
|
||||||
|
|
||||||
let fee: Option<SourceBalance> =
|
|
||||||
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::<Source>().await.map_err(format_err)?;
|
|
||||||
let lane = lane.into();
|
|
||||||
let payload = Source::encode_message(payload)?;
|
|
||||||
|
|
||||||
let fee: Option<SourceBalance> =
|
|
||||||
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<Fee: Decode, C: Chain, P: Encode>(
|
|
||||||
client: &relay_substrate_client::Client<C>,
|
|
||||||
estimate_fee_method: &str,
|
|
||||||
lane: bp_messages::LaneId,
|
|
||||||
payload: P,
|
|
||||||
) -> Result<Option<Fee>, relay_substrate_client::Error> {
|
|
||||||
let encoded_response = client
|
|
||||||
.state_call(estimate_fee_method.into(), (lane, payload).encode().into(), None)
|
|
||||||
.await?;
|
|
||||||
let decoded_response: Option<Fee> =
|
|
||||||
Decode::decode(&mut &encoded_response.0[..]).map_err(relay_substrate_client::Error::ResponseParseFailed)?;
|
|
||||||
Ok(decoded_response)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn message_payload<SAccountId, TPublic, TSignature>(
|
|
||||||
spec_version: u32,
|
|
||||||
weight: Weight,
|
|
||||||
origin: CallOrigin<SAccountId, TPublic, TSignature>,
|
|
||||||
call: &impl Encode,
|
|
||||||
) -> MessagePayload<SAccountId, TPublic, TSignature, Vec<u8>>
|
|
||||||
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<u8>`
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CliEncodeCall for Millau {
|
impl CliEncodeCall for Millau {
|
||||||
fn max_extrinsic_size() -> u32 {
|
fn max_extrinsic_size() -> u32 {
|
||||||
@@ -204,7 +107,7 @@ impl CliChain for Millau {
|
|||||||
let call = Target::encode_call(&call).map_err(|e| e.to_string())?;
|
let call = Target::encode_call(&call).map_err(|e| e.to_string())?;
|
||||||
let weight = call.get_dispatch_info().weight;
|
let weight = call.get_dispatch_info().weight;
|
||||||
|
|
||||||
Ok(message_payload(spec_version, weight, origin, &call))
|
Ok(send_message::message_payload(spec_version, weight, origin, &call))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -274,7 +177,7 @@ impl CliChain for Rialto {
|
|||||||
let call = Target::encode_call(&call).map_err(|e| e.to_string())?;
|
let call = Target::encode_call(&call).map_err(|e| e.to_string())?;
|
||||||
let weight = call.get_dispatch_info().weight;
|
let weight = call.get_dispatch_info().weight;
|
||||||
|
|
||||||
Ok(message_payload(spec_version, weight, origin, &call))
|
Ok(send_message::message_payload(spec_version, weight, origin, &call))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -299,14 +202,11 @@ impl CliChain for Westend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_err(e: anyhow::Error) -> String {
|
|
||||||
e.to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use bp_messages::source_chain::TargetHeaderChain;
|
use bp_messages::source_chain::TargetHeaderChain;
|
||||||
|
use codec::Encode;
|
||||||
use relay_substrate_client::TransactionSignScheme;
|
use relay_substrate_client::TransactionSignScheme;
|
||||||
use sp_core::Pair;
|
use sp_core::Pair;
|
||||||
use sp_runtime::traits::{IdentifyAccount, Verify};
|
use sp_runtime::traits::{IdentifyAccount, Verify};
|
||||||
@@ -363,7 +263,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let call: millau_runtime::Call = millau_runtime::SystemCall::remark(vec![42; maximal_remark_size as _]).into();
|
let call: millau_runtime::Call = millau_runtime::SystemCall::remark(vec![42; maximal_remark_size as _]).into();
|
||||||
let payload = message_payload(
|
let payload = send_message::message_payload(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
call.get_dispatch_info().weight,
|
call.get_dispatch_info().weight,
|
||||||
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
||||||
@@ -373,7 +273,7 @@ mod tests {
|
|||||||
|
|
||||||
let call: millau_runtime::Call =
|
let call: millau_runtime::Call =
|
||||||
millau_runtime::SystemCall::remark(vec![42; (maximal_remark_size + 1) as _]).into();
|
millau_runtime::SystemCall::remark(vec![42; (maximal_remark_size + 1) as _]).into();
|
||||||
let payload = message_payload(
|
let payload = send_message::message_payload(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
call.get_dispatch_info().weight,
|
call.get_dispatch_info().weight,
|
||||||
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
||||||
@@ -396,10 +296,11 @@ mod tests {
|
|||||||
fn maximal_rialto_to_millau_message_dispatch_weight_is_computed_correctly() {
|
fn maximal_rialto_to_millau_message_dispatch_weight_is_computed_correctly() {
|
||||||
use rialto_runtime::millau_messages::Millau;
|
use rialto_runtime::millau_messages::Millau;
|
||||||
|
|
||||||
let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight());
|
let maximal_dispatch_weight =
|
||||||
|
send_message::compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight());
|
||||||
let call: millau_runtime::Call = rialto_runtime::SystemCall::remark(vec![]).into();
|
let call: millau_runtime::Call = rialto_runtime::SystemCall::remark(vec![]).into();
|
||||||
|
|
||||||
let payload = message_payload(
|
let payload = send_message::message_payload(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
maximal_dispatch_weight,
|
maximal_dispatch_weight,
|
||||||
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
||||||
@@ -407,7 +308,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(Millau::verify_message(&payload), Ok(()));
|
assert_eq!(Millau::verify_message(&payload), Ok(()));
|
||||||
|
|
||||||
let payload = message_payload(
|
let payload = send_message::message_payload(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
maximal_dispatch_weight + 1,
|
maximal_dispatch_weight + 1,
|
||||||
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
||||||
@@ -420,10 +321,11 @@ mod tests {
|
|||||||
fn maximal_weight_fill_block_to_rialto_is_generated_correctly() {
|
fn maximal_weight_fill_block_to_rialto_is_generated_correctly() {
|
||||||
use millau_runtime::rialto_messages::Rialto;
|
use millau_runtime::rialto_messages::Rialto;
|
||||||
|
|
||||||
let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight());
|
let maximal_dispatch_weight =
|
||||||
|
send_message::compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight());
|
||||||
let call: rialto_runtime::Call = millau_runtime::SystemCall::remark(vec![]).into();
|
let call: rialto_runtime::Call = millau_runtime::SystemCall::remark(vec![]).into();
|
||||||
|
|
||||||
let payload = message_payload(
|
let payload = send_message::message_payload(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
maximal_dispatch_weight,
|
maximal_dispatch_weight,
|
||||||
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
||||||
@@ -431,7 +333,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(Rialto::verify_message(&payload), Ok(()));
|
assert_eq!(Rialto::verify_message(&payload), Ok(()));
|
||||||
|
|
||||||
let payload = message_payload(
|
let payload = send_message::message_payload(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
maximal_dispatch_weight + 1,
|
maximal_dispatch_weight + 1,
|
||||||
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
pallet_bridge_dispatch::CallOrigin::SourceRoot,
|
||||||
|
|||||||
Reference in New Issue
Block a user