From 7cdc3a522fc2a72265265669f89a7f0f6c8ac8b3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 14 Jan 2022 14:10:37 +0300 Subject: [PATCH] support version mode cli options in send-message subcommand (#1284) --- .../bin-substrate/src/cli/encode_call.rs | 5 +- bridges/relays/bin-substrate/src/cli/mod.rs | 85 +++++++++++++------ .../bin-substrate/src/cli/send_message.rs | 38 ++++++--- 3 files changed, 85 insertions(+), 43 deletions(-) diff --git a/bridges/relays/bin-substrate/src/cli/encode_call.rs b/bridges/relays/bin-substrate/src/cli/encode_call.rs index 8be04a88ff75..b409cf383ed7 100644 --- a/bridges/relays/bin-substrate/src/cli/encode_call.rs +++ b/bridges/relays/bin-substrate/src/cli/encode_call.rs @@ -308,8 +308,8 @@ mod tests { ); } - #[test] - fn should_encode_bridge_send_message_call() { + #[async_std::test] + async fn should_encode_bridge_send_message_call() { // given let encode_message = SendMessage::from_iter(vec![ "send-message", @@ -325,6 +325,7 @@ mod tests { "remark", ]) .encode_payload() + .await .unwrap(); let mut encode_call = EncodeCall::from_iter(vec![ diff --git a/bridges/relays/bin-substrate/src/cli/mod.rs b/bridges/relays/bin-substrate/src/cli/mod.rs index 1ff46fdbb846..ae169f773eff 100644 --- a/bridges/relays/bin-substrate/src/cli/mod.rs +++ b/bridges/relays/bin-substrate/src/cli/mod.rs @@ -240,7 +240,7 @@ impl AccountId { /// /// Used to abstract away CLI commands. pub trait CliChain: relay_substrate_client::Chain { - /// Chain's current version of the runtime. + /// Current version of the chain runtime, known to relay. const RUNTIME_VERSION: sp_version::RuntimeVersion; /// Crypto KeyPair type used to send messages. @@ -368,7 +368,7 @@ where } #[doc = "Runtime version params."] -#[derive(StructOpt, Debug, PartialEq, Eq, Clone, EnumString, EnumVariantNames)] +#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, EnumVariantNames)] pub enum RuntimeVersionType { /// Auto query version from chain Auto, @@ -391,7 +391,7 @@ macro_rules! declare_chain_options { #[structopt(long, default_value = "127.0.0.1")] pub [<$chain_prefix _host>]: String, #[doc = "Connect to " $chain " node websocket server at given port."] - #[structopt(long)] + #[structopt(long, default_value = "9944")] pub [<$chain_prefix _port>]: u16, #[doc = "Use secure websocket connection."] #[structopt(long)] @@ -402,7 +402,7 @@ macro_rules! declare_chain_options { } #[doc = $chain " runtime version params."] - #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy)] pub struct [<$chain RuntimeVersionParams>] { #[doc = "The type of runtime version for chain " $chain] #[structopt(long, default_value = "Bundle")] @@ -543,29 +543,9 @@ macro_rules! declare_chain_options { &self, bundle_runtime_version: Option ) -> anyhow::Result> { - let runtime_version_params = &self.[<$chain_prefix _runtime_version>]; - let chain_runtime_version = match runtime_version_params.[<$chain_prefix _version_mode>] { - RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, - RuntimeVersionType::Custom => { - let except_spec_version = runtime_version_params.[<$chain_prefix _spec_version>] - .ok_or(anyhow::Error::msg(format!("The {}-spec-version is required when choose custom mode", stringify!($chain_prefix))))?; - let except_transaction_version = runtime_version_params.[<$chain_prefix _transaction_version>] - .ok_or(anyhow::Error::msg(format!("The {}-transaction-version is required when choose custom mode", stringify!($chain_prefix))))?; - ChainRuntimeVersion::Custom( - except_spec_version, - except_transaction_version - ) - } - RuntimeVersionType::Bundle => { - match bundle_runtime_version { - Some(runtime_version) => ChainRuntimeVersion::Custom( - runtime_version.spec_version, - runtime_version.transaction_version - ), - None => ChainRuntimeVersion::Auto - } - } - }; + let chain_runtime_version = self + .[<$chain_prefix _runtime_version>] + .into_runtime_version(bundle_runtime_version)?; Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { host: self.[<$chain_prefix _host>].clone(), port: self.[<$chain_prefix _port>], @@ -575,6 +555,57 @@ macro_rules! declare_chain_options { .await ) } + + /// Return selected `chain_spec` version. + /// + /// This function only connects to the node if version mode is set to `Auto`. + #[allow(dead_code)] + pub async fn selected_chain_spec_version( + &self, + bundle_runtime_version: Option, + ) -> anyhow::Result { + let chain_runtime_version = self + .[<$chain_prefix _runtime_version>] + .into_runtime_version(bundle_runtime_version.clone())?; + Ok(match chain_runtime_version { + ChainRuntimeVersion::Auto => self + .to_client::(bundle_runtime_version) + .await? + .simple_runtime_version() + .await? + .0, + ChainRuntimeVersion::Custom(spec_version, _) => spec_version, + }) + } + } + + impl [<$chain RuntimeVersionParams>] { + /// Converts self into `ChainRuntimeVersion`. + pub fn into_runtime_version( + self, + bundle_runtime_version: Option, + ) -> anyhow::Result { + Ok(match self.[<$chain_prefix _version_mode>] { + RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, + RuntimeVersionType::Custom => { + let except_spec_version = self.[<$chain_prefix _spec_version>] + .ok_or_else(|| anyhow::Error::msg(format!("The {}-spec-version is required when choose custom mode", stringify!($chain_prefix))))?; + let except_transaction_version = self.[<$chain_prefix _transaction_version>] + .ok_or_else(|| anyhow::Error::msg(format!("The {}-transaction-version is required when choose custom mode", stringify!($chain_prefix))))?; + ChainRuntimeVersion::Custom( + except_spec_version, + except_transaction_version + ) + }, + RuntimeVersionType::Bundle => match bundle_runtime_version { + Some(runtime_version) => ChainRuntimeVersion::Custom( + runtime_version.spec_version, + runtime_version.transaction_version + ), + None => ChainRuntimeVersion::Auto + }, + }) + } } } }; diff --git a/bridges/relays/bin-substrate/src/cli/send_message.rs b/bridges/relays/bin-substrate/src/cli/send_message.rs index 52eab9c64ec9..2d81576de3dd 100644 --- a/bridges/relays/bin-substrate/src/cli/send_message.rs +++ b/bridges/relays/bin-substrate/src/cli/send_message.rs @@ -19,7 +19,7 @@ use crate::cli::{ encode_call::{self, CliEncodeCall}, estimate_fee::estimate_message_delivery_and_dispatch_fee, Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, - SourceSigningParams, TargetSigningParams, + SourceSigningParams, TargetConnectionParams, TargetSigningParams, }; use bp_message_dispatch::{CallOrigin, MessagePayload}; use bp_runtime::{BalanceOf, Chain as _}; @@ -88,10 +88,16 @@ pub struct SendMessage { /// `SourceAccount`. #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] origin: Origins, + + // Normally we don't need to connect to the target chain to send message. But for testing + // we may want to use **actual** `spec_version` of the target chain when composing a message. + // Then we'll need to read version from the target chain node. + #[structopt(flatten)] + target: TargetConnectionParams, } impl SendMessage { - pub fn encode_payload( + pub async fn encode_payload( &mut self, ) -> anyhow::Result>> { crate::select_full_bridge!(self.bridge, { @@ -110,6 +116,10 @@ impl SendMessage { encode_call::preprocess_call::(message, bridge.bridge_instance_index()); let target_call = Target::encode_call(message)?; + let target_spec_version = self + .target + .selected_chain_spec_version::(Some(Target::RUNTIME_VERSION)) + .await?; let payload = { let target_call_weight = prepare_call_dispatch_weight( @@ -121,7 +131,7 @@ impl SendMessage { let source_account_id = source_sender_public.into_account(); message_payload( - Target::RUNTIME_VERSION.spec_version, + target_spec_version, target_call_weight, match origin { Origins::Source => CallOrigin::SourceAccount(source_account_id), @@ -130,7 +140,7 @@ impl SendMessage { let digest = account_ownership_digest( &target_call, source_account_id.clone(), - Target::RUNTIME_VERSION.spec_version, + target_spec_version, ); let target_origin_public = target_sign.public(); let digest_signature = target_sign.sign(&digest); @@ -152,7 +162,7 @@ impl SendMessage { /// Run the command. pub async fn run(mut self) -> anyhow::Result<()> { crate::select_full_bridge!(self.bridge, { - let payload = self.encode_payload()?; + let payload = self.encode_payload().await?; let source_client = self.source.to_client::(SOURCE_RUNTIME_VERSION).await?; let source_sign = self.source_sign.to_keypair::()?; @@ -291,8 +301,8 @@ mod tests { use super::*; use hex_literal::hex; - #[test] - fn send_remark_rialto_to_millau() { + #[async_std::test] + async fn send_remark_rialto_to_millau() { // given let mut send_message = SendMessage::from_iter(vec![ "send-message", @@ -307,7 +317,7 @@ mod tests { ]); // when - let payload = send_message.encode_payload().unwrap(); + let payload = send_message.encode_payload().await.unwrap(); // then assert_eq!( @@ -324,8 +334,8 @@ mod tests { ); } - #[test] - fn send_remark_millau_to_rialto() { + #[async_std::test] + async fn send_remark_millau_to_rialto() { // given let mut send_message = SendMessage::from_iter(vec![ "send-message", @@ -344,7 +354,7 @@ mod tests { ]); // when - let payload = send_message.encode_payload().unwrap(); + let payload = send_message.encode_payload().await.unwrap(); // then // Since signatures are randomized we extract it from here and only check the rest. @@ -388,8 +398,8 @@ mod tests { assert!(send_message.is_ok()); } - #[test] - fn accepts_non_default_dispatch_fee_payment() { + #[async_std::test] + async fn accepts_non_default_dispatch_fee_payment() { // given let mut send_message = SendMessage::from_iter(vec![ "send-message", @@ -404,7 +414,7 @@ mod tests { ]); // when - let payload = send_message.encode_payload().unwrap(); + let payload = send_message.encode_payload().await.unwrap(); // then assert_eq!(