support version mode cli options in send-message subcommand (#1284)

This commit is contained in:
Svyatoslav Nikolsky
2022-01-14 14:10:37 +03:00
committed by Bastian Köcher
parent 1ec2edd357
commit a9334bb609
3 changed files with 85 additions and 43 deletions
@@ -308,8 +308,8 @@ mod tests {
); );
} }
#[test] #[async_std::test]
fn should_encode_bridge_send_message_call() { async fn should_encode_bridge_send_message_call() {
// given // given
let encode_message = SendMessage::from_iter(vec![ let encode_message = SendMessage::from_iter(vec![
"send-message", "send-message",
@@ -325,6 +325,7 @@ mod tests {
"remark", "remark",
]) ])
.encode_payload() .encode_payload()
.await
.unwrap(); .unwrap();
let mut encode_call = EncodeCall::from_iter(vec![ let mut encode_call = EncodeCall::from_iter(vec![
+58 -27
View File
@@ -240,7 +240,7 @@ impl AccountId {
/// ///
/// Used to abstract away CLI commands. /// Used to abstract away CLI commands.
pub trait CliChain: relay_substrate_client::Chain { 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; const RUNTIME_VERSION: sp_version::RuntimeVersion;
/// Crypto KeyPair type used to send messages. /// Crypto KeyPair type used to send messages.
@@ -368,7 +368,7 @@ where
} }
#[doc = "Runtime version params."] #[doc = "Runtime version params."]
#[derive(StructOpt, Debug, PartialEq, Eq, Clone, EnumString, EnumVariantNames)] #[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, EnumVariantNames)]
pub enum RuntimeVersionType { pub enum RuntimeVersionType {
/// Auto query version from chain /// Auto query version from chain
Auto, Auto,
@@ -391,7 +391,7 @@ macro_rules! declare_chain_options {
#[structopt(long, default_value = "127.0.0.1")] #[structopt(long, default_value = "127.0.0.1")]
pub [<$chain_prefix _host>]: String, pub [<$chain_prefix _host>]: String,
#[doc = "Connect to " $chain " node websocket server at given port."] #[doc = "Connect to " $chain " node websocket server at given port."]
#[structopt(long)] #[structopt(long, default_value = "9944")]
pub [<$chain_prefix _port>]: u16, pub [<$chain_prefix _port>]: u16,
#[doc = "Use secure websocket connection."] #[doc = "Use secure websocket connection."]
#[structopt(long)] #[structopt(long)]
@@ -402,7 +402,7 @@ macro_rules! declare_chain_options {
} }
#[doc = $chain " runtime version params."] #[doc = $chain " runtime version params."]
#[derive(StructOpt, Debug, PartialEq, Eq, Clone)] #[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy)]
pub struct [<$chain RuntimeVersionParams>] { pub struct [<$chain RuntimeVersionParams>] {
#[doc = "The type of runtime version for chain " $chain] #[doc = "The type of runtime version for chain " $chain]
#[structopt(long, default_value = "Bundle")] #[structopt(long, default_value = "Bundle")]
@@ -543,29 +543,9 @@ macro_rules! declare_chain_options {
&self, &self,
bundle_runtime_version: Option<sp_version::RuntimeVersion> bundle_runtime_version: Option<sp_version::RuntimeVersion>
) -> anyhow::Result<relay_substrate_client::Client<Chain>> { ) -> anyhow::Result<relay_substrate_client::Client<Chain>> {
let runtime_version_params = &self.[<$chain_prefix _runtime_version>]; let chain_runtime_version = self
let chain_runtime_version = match runtime_version_params.[<$chain_prefix _version_mode>] { .[<$chain_prefix _runtime_version>]
RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, .into_runtime_version(bundle_runtime_version)?;
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
}
}
};
Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams {
host: self.[<$chain_prefix _host>].clone(), host: self.[<$chain_prefix _host>].clone(),
port: self.[<$chain_prefix _port>], port: self.[<$chain_prefix _port>],
@@ -575,6 +555,57 @@ macro_rules! declare_chain_options {
.await .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<Chain: CliChain>(
&self,
bundle_runtime_version: Option<sp_version::RuntimeVersion>,
) -> anyhow::Result<u32> {
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::<Chain>(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<sp_version::RuntimeVersion>,
) -> anyhow::Result<ChainRuntimeVersion> {
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
},
})
}
} }
} }
}; };
@@ -19,7 +19,7 @@ use crate::cli::{
encode_call::{self, CliEncodeCall}, encode_call::{self, CliEncodeCall},
estimate_fee::estimate_message_delivery_and_dispatch_fee, estimate_fee::estimate_message_delivery_and_dispatch_fee,
Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams,
SourceSigningParams, TargetSigningParams, SourceSigningParams, TargetConnectionParams, TargetSigningParams,
}; };
use bp_message_dispatch::{CallOrigin, MessagePayload}; use bp_message_dispatch::{CallOrigin, MessagePayload};
use bp_runtime::{BalanceOf, Chain as _}; use bp_runtime::{BalanceOf, Chain as _};
@@ -88,10 +88,16 @@ pub struct SendMessage {
/// `SourceAccount`. /// `SourceAccount`.
#[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")]
origin: Origins, 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 { impl SendMessage {
pub fn encode_payload( pub async fn encode_payload(
&mut self, &mut self,
) -> anyhow::Result<MessagePayload<AccountId32, MultiSigner, MultiSignature, Vec<u8>>> { ) -> anyhow::Result<MessagePayload<AccountId32, MultiSigner, MultiSignature, Vec<u8>>> {
crate::select_full_bridge!(self.bridge, { crate::select_full_bridge!(self.bridge, {
@@ -110,6 +116,10 @@ impl SendMessage {
encode_call::preprocess_call::<Source, Target>(message, bridge.bridge_instance_index()); encode_call::preprocess_call::<Source, Target>(message, bridge.bridge_instance_index());
let target_call = Target::encode_call(message)?; let target_call = Target::encode_call(message)?;
let target_spec_version = self
.target
.selected_chain_spec_version::<Target>(Some(Target::RUNTIME_VERSION))
.await?;
let payload = { let payload = {
let target_call_weight = prepare_call_dispatch_weight( let target_call_weight = prepare_call_dispatch_weight(
@@ -121,7 +131,7 @@ impl SendMessage {
let source_account_id = source_sender_public.into_account(); let source_account_id = source_sender_public.into_account();
message_payload( message_payload(
Target::RUNTIME_VERSION.spec_version, target_spec_version,
target_call_weight, target_call_weight,
match origin { match origin {
Origins::Source => CallOrigin::SourceAccount(source_account_id), Origins::Source => CallOrigin::SourceAccount(source_account_id),
@@ -130,7 +140,7 @@ impl SendMessage {
let digest = account_ownership_digest( let digest = account_ownership_digest(
&target_call, &target_call,
source_account_id.clone(), source_account_id.clone(),
Target::RUNTIME_VERSION.spec_version, target_spec_version,
); );
let target_origin_public = target_sign.public(); let target_origin_public = target_sign.public();
let digest_signature = target_sign.sign(&digest); let digest_signature = target_sign.sign(&digest);
@@ -152,7 +162,7 @@ impl SendMessage {
/// Run the command. /// Run the command.
pub async fn run(mut self) -> anyhow::Result<()> { pub async fn run(mut self) -> anyhow::Result<()> {
crate::select_full_bridge!(self.bridge, { 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>(SOURCE_RUNTIME_VERSION).await?; let source_client = self.source.to_client::<Source>(SOURCE_RUNTIME_VERSION).await?;
let source_sign = self.source_sign.to_keypair::<Source>()?; let source_sign = self.source_sign.to_keypair::<Source>()?;
@@ -291,8 +301,8 @@ mod tests {
use super::*; use super::*;
use hex_literal::hex; use hex_literal::hex;
#[test] #[async_std::test]
fn send_remark_rialto_to_millau() { async fn send_remark_rialto_to_millau() {
// given // given
let mut send_message = SendMessage::from_iter(vec![ let mut send_message = SendMessage::from_iter(vec![
"send-message", "send-message",
@@ -307,7 +317,7 @@ mod tests {
]); ]);
// when // when
let payload = send_message.encode_payload().unwrap(); let payload = send_message.encode_payload().await.unwrap();
// then // then
assert_eq!( assert_eq!(
@@ -324,8 +334,8 @@ mod tests {
); );
} }
#[test] #[async_std::test]
fn send_remark_millau_to_rialto() { async fn send_remark_millau_to_rialto() {
// given // given
let mut send_message = SendMessage::from_iter(vec![ let mut send_message = SendMessage::from_iter(vec![
"send-message", "send-message",
@@ -344,7 +354,7 @@ mod tests {
]); ]);
// when // when
let payload = send_message.encode_payload().unwrap(); let payload = send_message.encode_payload().await.unwrap();
// then // then
// Since signatures are randomized we extract it from here and only check the rest. // 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()); assert!(send_message.is_ok());
} }
#[test] #[async_std::test]
fn accepts_non_default_dispatch_fee_payment() { async fn accepts_non_default_dispatch_fee_payment() {
// given // given
let mut send_message = SendMessage::from_iter(vec![ let mut send_message = SendMessage::from_iter(vec![
"send-message", "send-message",
@@ -404,7 +414,7 @@ mod tests {
]); ]);
// when // when
let payload = send_message.encode_payload().unwrap(); let payload = send_message.encode_payload().await.unwrap();
// then // then
assert_eq!( assert_eq!(