From 470b51d2a995c99291da84e0bb385060efb35664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 16 Feb 2021 16:26:38 +0100 Subject: [PATCH] Rework relay CLI a bit (#734) * Change CLI UX. * De-duplicate main. * De-duplicate send message. * Add more docs and extract functions. * Fix scripts. * cargo fmt --all * Add missing 'u'. --- bridges/relays/substrate/src/cli.rs | 127 ++++--- bridges/relays/substrate/src/main.rs | 540 +++++++++++++-------------- 2 files changed, 339 insertions(+), 328 deletions(-) diff --git a/bridges/relays/substrate/src/cli.rs b/bridges/relays/substrate/src/cli.rs index a6dd5ab67b..96f13d3384 100644 --- a/bridges/relays/substrate/src/cli.rs +++ b/bridges/relays/substrate/src/cli.rs @@ -26,23 +26,36 @@ pub fn parse_args() -> Command { Command::from_args() } -/// Substrate-to-Substrate relay CLI args. +/// Substrate-to-Substrate bridge utilities. #[derive(StructOpt)] #[structopt(about = "Substrate-to-Substrate relay")] pub enum Command { - /// Initialize Millau headers bridge in Rialto. - InitializeMillauHeadersBridgeInRialto { - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - rialto_sign: RialtoSigningParams, - #[structopt(flatten)] - millau_bridge_params: MillauBridgeInitializationParams, - }, + /// Start headers relay between two chains. + /// + /// The on-chain bridge component should have been already initialized with + /// `init-bridge` sub-command. + RelayHeaders(RelayHeaders), + /// Start messages relay between two chains. + /// + /// Ties up to `MessageLane` pallets on both chains and starts relaying messages. + /// Requires the header relay to be already running. + RelayMessages(RelayMessages), + /// Initialize on-chain bridge pallet with current header data. + /// + /// Sends initialization transaction to bootstrap the bridge with current finalized block data. + InitBridge(InitBridge), + /// Send custom message over the bridge. + /// + /// Allows interacting with the bridge by sending messages over `MessageLane` component. + /// The message is being sent to the source chain, delivered to the target chain and dispatched + /// there. + SendMessage(SendMessage), +} + +#[derive(StructOpt)] +pub enum RelayHeaders { /// Relay Millau headers to Rialto. - MillauHeadersToRialto { + MillauToRialto { #[structopt(flatten)] millau: MillauConnectionParams, #[structopt(flatten)] @@ -52,19 +65,8 @@ pub enum Command { #[structopt(flatten)] prometheus_params: PrometheusParams, }, - /// Initialize Rialto headers bridge in Millau. - InitializeRialtoHeadersBridgeInMillau { - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - millau_sign: MillauSigningParams, - #[structopt(flatten)] - rialto_bridge_params: RialtoBridgeInitializationParams, - }, /// Relay Rialto headers to Millau. - RialtoHeadersToMillau { + RialtoToMillau { #[structopt(flatten)] rialto: RialtoConnectionParams, #[structopt(flatten)] @@ -74,8 +76,12 @@ pub enum Command { #[structopt(flatten)] prometheus_params: PrometheusParams, }, +} + +#[derive(StructOpt)] +pub enum RelayMessages { /// Serve given lane of Millau -> Rialto messages. - MillauMessagesToRialto { + MillauToRialto { #[structopt(flatten)] millau: MillauConnectionParams, #[structopt(flatten)] @@ -90,8 +96,54 @@ pub enum Command { #[structopt(long)] lane: HexLaneId, }, + /// Serve given lane of Rialto -> Millau messages. + RialtoToMillau { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, + /// Hex-encoded id of lane that should be served by relay. + #[structopt(long)] + lane: HexLaneId, + }, +} + +#[derive(StructOpt)] +pub enum InitBridge { + /// Initialize Millau headers bridge in Rialto. + MillauToRialto { + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + #[structopt(flatten)] + millau_bridge_params: MillauBridgeInitializationParams, + }, + /// Initialize Rialto headers bridge in Millau. + RialtoToMillau { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + rialto_bridge_params: RialtoBridgeInitializationParams, + }, +} + +#[derive(StructOpt)] +pub enum SendMessage { /// Submit message to given Millau -> Rialto lane. - SubmitMillauToRialtoMessage { + MillauToRialto { #[structopt(flatten)] millau: MillauConnectionParams, #[structopt(flatten)] @@ -111,24 +163,8 @@ pub enum Command { #[structopt(long, possible_values = &Origins::variants())] origin: Origins, }, - /// Serve given lane of Rialto -> Millau messages. - RialtoMessagesToMillau { - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - rialto_sign: RialtoSigningParams, - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - millau_sign: MillauSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, - /// Hex-encoded id of lane that should be served by relay. - #[structopt(long)] - lane: HexLaneId, - }, /// Submit message to given Rialto -> Millau lane. - SubmitRialtoToMillauMessage { + RialtoToMillau { #[structopt(flatten)] rialto: RialtoConnectionParams, #[structopt(flatten)] @@ -181,6 +217,9 @@ pub enum ToMillauMessage { arg_enum! { #[derive(Debug)] /// The origin to use when dispatching the message on the target chain. + /// + /// - `Target` uses account existing on the target chain (requires target private key). + /// - `Origin` uses account derived from the source-chain account. pub enum Origins { Target, Source, diff --git a/bridges/relays/substrate/src/main.rs b/bridges/relays/substrate/src/main.rs index e0d6149870..c700022a0f 100644 --- a/bridges/relays/substrate/src/main.rs +++ b/bridges/relays/substrate/src/main.rs @@ -60,27 +60,25 @@ fn main() { async fn run_command(command: cli::Command) -> Result<(), String> { match command { - cli::Command::InitializeMillauHeadersBridgeInRialto { + cli::Command::InitBridge(arg) => run_init_bridge(arg).await, + cli::Command::RelayHeaders(arg) => run_relay_headers(arg).await, + cli::Command::RelayMessages(arg) => run_relay_messages(arg).await, + cli::Command::SendMessage(arg) => run_send_message(arg).await, + } +} + +async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { + match command { + cli::InitBridge::MillauToRialto { millau, rialto, rialto_sign, millau_bridge_params, } => { - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let rialto_sign = RialtoSigningParams::from_suri( - &rialto_sign.rialto_signer, - rialto_sign.rialto_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; + let millau_client = millau.into_client().await?; + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; + let rialto_signer_next_index = rialto_client .next_account_index(rialto_sign.signer.public().into()) .await?; @@ -108,50 +106,15 @@ async fn run_command(command: cli::Command) -> Result<(), String> { ) .await; } - cli::Command::MillauHeadersToRialto { - millau, - rialto, - rialto_sign, - prometheus_params, - } => { - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let rialto_sign = RialtoSigningParams::from_suri( - &rialto_sign.rialto_signer, - rialto_sign.rialto_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; - millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await; - } - cli::Command::InitializeRialtoHeadersBridgeInMillau { + cli::InitBridge::RialtoToMillau { rialto, millau, millau_sign, rialto_bridge_params, } => { - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let millau_sign = MillauSigningParams::from_suri( - &millau_sign.millau_signer, - millau_sign.millau_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; + let rialto_client = rialto.into_client().await?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; let millau_signer_next_index = millau_client .next_account_index(millau_sign.signer.public().into()) .await?; @@ -179,31 +142,41 @@ async fn run_command(command: cli::Command) -> Result<(), String> { ) .await; } - cli::Command::RialtoHeadersToMillau { + } + Ok(()) +} + +async fn run_relay_headers(command: cli::RelayHeaders) -> Result<(), String> { + match command { + cli::RelayHeaders::MillauToRialto { + millau, + rialto, + rialto_sign, + prometheus_params, + } => { + let millau_client = millau.into_client().await?; + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; + millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await; + } + cli::RelayHeaders::RialtoToMillau { rialto, millau, millau_sign, prometheus_params, } => { - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let millau_sign = MillauSigningParams::from_suri( - &millau_sign.millau_signer, - millau_sign.millau_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; - + let rialto_client = rialto.into_client().await?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; rialto_headers_to_millau::run(rialto_client, millau_client, millau_sign, prometheus_params.into()).await; } - cli::Command::MillauMessagesToRialto { + } + Ok(()) +} + +async fn run_relay_messages(command: cli::RelayMessages) -> Result<(), String> { + match command { + cli::RelayMessages::MillauToRialto { millau, millau_sign, rialto, @@ -211,26 +184,10 @@ async fn run_command(command: cli::Command) -> Result<(), String> { prometheus_params, lane, } => { - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let millau_sign = MillauSigningParams::from_suri( - &millau_sign.millau_signer, - millau_sign.millau_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let rialto_sign = RialtoSigningParams::from_suri( - &rialto_sign.rialto_signer, - rialto_sign.rialto_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; millau_messages_to_rialto::run( millau_client, @@ -241,7 +198,35 @@ async fn run_command(command: cli::Command) -> Result<(), String> { prometheus_params.into(), ); } - cli::Command::SubmitMillauToRialtoMessage { + cli::RelayMessages::RialtoToMillau { + rialto, + rialto_sign, + millau, + millau_sign, + prometheus_params, + lane, + } => { + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; + + rialto_messages_to_millau::run( + rialto_client, + rialto_sign, + millau_client, + millau_sign, + lane.into(), + prometheus_params.into(), + ); + } + } + Ok(()) +} + +async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { + match command { + cli::SendMessage::MillauToRialto { millau, millau_sign, rialto_sign, @@ -251,89 +236,23 @@ async fn run_command(command: cli::Command) -> Result<(), String> { origin, .. } => { - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let millau_sign = MillauSigningParams::from_suri( - &millau_sign.millau_signer, - millau_sign.millau_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; - let rialto_sign = RialtoSigningParams::from_suri( - &rialto_sign.rialto_signer, - rialto_sign.rialto_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; + let rialto_sign = rialto_sign.parse()?; + let rialto_call = message.into_call(); - let rialto_call = match message { - cli::ToRialtoMessage::Remark => rialto_runtime::Call::System(rialto_runtime::SystemCall::remark( - format!( - "Unix time: {}", - std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .unwrap_or_default() - .as_secs(), - ) - .as_bytes() - .to_vec(), - )), - cli::ToRialtoMessage::Transfer { recipient, amount } => { - rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount)) - } - }; - - let rialto_call_weight = rialto_call.get_dispatch_info().weight; - let millau_sender_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); - let millau_account_id: bp_millau::AccountId = millau_sender_public.into_account(); - let rialto_origin_public = rialto_sign.signer.public(); - - let payload = match origin { - cli::Origins::Source => MessagePayload { - spec_version: rialto_runtime::VERSION.spec_version, - weight: rialto_call_weight, - origin: CallOrigin::SourceAccount(millau_account_id), - call: rialto_call.encode(), - }, - cli::Origins::Target => { - let digest = millau_runtime::rialto_account_ownership_digest( - &rialto_call, - millau_account_id.clone(), - rialto_runtime::VERSION.spec_version, - ); - - let digest_signature = rialto_sign.signer.sign(&digest); - - MessagePayload { - spec_version: rialto_runtime::VERSION.spec_version, - weight: rialto_call_weight, - origin: CallOrigin::TargetAccount( - millau_account_id, - rialto_origin_public.into(), - digest_signature.into(), - ), - call: rialto_call.encode(), - } - } - }; + let payload = millau_to_rialto_message_payload(&millau_sign, &rialto_sign, &rialto_call, origin); let lane = lane.into(); - let fee = match fee { - Some(fee) => fee, - None => match estimate_message_delivery_and_dispatch_fee( + let fee = get_fee(fee, || { + estimate_message_delivery_and_dispatch_fee( &millau_client, bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone(), ) - .await - { - Ok(Some(fee)) => fee, - Ok(None) => return Err("Failed to estimate message fee. Message is too heavy?".into()), - Err(error) => return Err(format!("Failed to estimate message fee: {:?}", error)), - }, - }; + }) + .await?; log::info!(target: "bridge", "Sending message to Rialto. Fee: {}", fee); @@ -354,45 +273,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { .submit_extrinsic(Bytes(signed_millau_call.encode())) .await?; } - cli::Command::RialtoMessagesToMillau { - rialto, - rialto_sign, - millau, - millau_sign, - prometheus_params, - lane, - } => { - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let rialto_sign = RialtoSigningParams::from_suri( - &rialto_sign.rialto_signer, - rialto_sign.rialto_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let millau_sign = MillauSigningParams::from_suri( - &millau_sign.millau_signer, - millau_sign.millau_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; - - rialto_messages_to_millau::run( - rialto_client, - rialto_sign, - millau_client, - millau_sign, - lane.into(), - prometheus_params.into(), - ); - } - cli::Command::SubmitRialtoToMillauMessage { + cli::SendMessage::RialtoToMillau { rialto, rialto_sign, millau_sign, @@ -402,89 +283,23 @@ async fn run_command(command: cli::Command) -> Result<(), String> { origin, .. } => { - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let rialto_sign = RialtoSigningParams::from_suri( - &rialto_sign.rialto_signer, - rialto_sign.rialto_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; - let millau_sign = MillauSigningParams::from_suri( - &millau_sign.millau_signer, - millau_sign.millau_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; + let millau_sign = millau_sign.parse()?; + let millau_call = message.into_call(); - let millau_call = match message { - cli::ToMillauMessage::Remark => millau_runtime::Call::System(millau_runtime::SystemCall::remark( - format!( - "Unix time: {}", - std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .unwrap_or_default() - .as_secs(), - ) - .as_bytes() - .to_vec(), - )), - cli::ToMillauMessage::Transfer { recipient, amount } => { - millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount)) - } - }; - - let millau_call_weight = millau_call.get_dispatch_info().weight; - let rialto_sender_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); - let rialto_account_id: bp_rialto::AccountId = rialto_sender_public.into_account(); - let millau_origin_public = millau_sign.signer.public(); - - let payload = match origin { - cli::Origins::Source => MessagePayload { - spec_version: millau_runtime::VERSION.spec_version, - weight: millau_call_weight, - origin: CallOrigin::SourceAccount(rialto_account_id), - call: millau_call.encode(), - }, - cli::Origins::Target => { - let digest = rialto_runtime::millau_account_ownership_digest( - &millau_call, - rialto_account_id.clone(), - millau_runtime::VERSION.spec_version, - ); - - let digest_signature = millau_sign.signer.sign(&digest); - - MessagePayload { - spec_version: millau_runtime::VERSION.spec_version, - weight: millau_call_weight, - origin: CallOrigin::TargetAccount( - rialto_account_id, - millau_origin_public.into(), - digest_signature.into(), - ), - call: millau_call.encode(), - } - } - }; + let payload = rialto_to_millau_message_payload(&rialto_sign, &millau_sign, &millau_call, origin); let lane = lane.into(); - let fee = match fee { - Some(fee) => fee, - None => match estimate_message_delivery_and_dispatch_fee( + let fee = get_fee(fee, || { + estimate_message_delivery_and_dispatch_fee( &rialto_client, bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone(), ) - .await - { - Ok(Some(fee)) => fee, - Ok(None) => return Err("Failed to estimate message fee. Message is too heavy?".into()), - Err(error) => return Err(format!("Failed to estimate message fee: {:?}", error)), - }, - }; + }) + .await?; log::info!(target: "bridge", "Sending message to Millau. Fee: {}", fee); @@ -506,7 +321,6 @@ async fn run_command(command: cli::Command) -> Result<(), String> { .await?; } } - Ok(()) } @@ -524,6 +338,164 @@ async fn estimate_message_delivery_and_dispatch_fee Vec { + format!( + "Unix time: {}", + std::time::SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .unwrap_or_default() + .as_secs(), + ) + .as_bytes() + .to_vec() +} + +fn rialto_to_millau_message_payload( + rialto_sign: &RialtoSigningParams, + millau_sign: &MillauSigningParams, + millau_call: &millau_runtime::Call, + origin: cli::Origins, +) -> rialto_runtime::millau_messages::ToMillauMessagePayload { + let millau_call_weight = millau_call.get_dispatch_info().weight; + let rialto_sender_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); + let rialto_account_id: bp_rialto::AccountId = rialto_sender_public.into_account(); + let millau_origin_public = millau_sign.signer.public(); + + MessagePayload { + spec_version: millau_runtime::VERSION.spec_version, + weight: millau_call_weight, + origin: match origin { + cli::Origins::Source => CallOrigin::SourceAccount(rialto_account_id), + cli::Origins::Target => { + let digest = rialto_runtime::millau_account_ownership_digest( + &millau_call, + rialto_account_id.clone(), + millau_runtime::VERSION.spec_version, + ); + + let digest_signature = millau_sign.signer.sign(&digest); + + CallOrigin::TargetAccount(rialto_account_id, millau_origin_public.into(), digest_signature.into()) + } + }, + call: millau_call.encode(), + } +} + +fn millau_to_rialto_message_payload( + millau_sign: &MillauSigningParams, + rialto_sign: &RialtoSigningParams, + rialto_call: &rialto_runtime::Call, + origin: cli::Origins, +) -> millau_runtime::rialto_messages::ToRialtoMessagePayload { + let rialto_call_weight = rialto_call.get_dispatch_info().weight; + let millau_sender_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); + let millau_account_id: bp_millau::AccountId = millau_sender_public.into_account(); + let rialto_origin_public = rialto_sign.signer.public(); + + MessagePayload { + spec_version: rialto_runtime::VERSION.spec_version, + weight: rialto_call_weight, + origin: match origin { + cli::Origins::Source => CallOrigin::SourceAccount(millau_account_id), + cli::Origins::Target => { + let digest = millau_runtime::rialto_account_ownership_digest( + &rialto_call, + millau_account_id.clone(), + rialto_runtime::VERSION.spec_version, + ); + + let digest_signature = rialto_sign.signer.sign(&digest); + + CallOrigin::TargetAccount(millau_account_id, rialto_origin_public.into(), digest_signature.into()) + } + }, + call: rialto_call.encode(), + } +} + +async fn get_fee(fee: Option, f: F) -> Result +where + Fee: Decode, + F: FnOnce() -> R, + R: std::future::Future, E>>, + E: std::fmt::Debug, +{ + match fee { + Some(fee) => Ok(fee), + None => match f().await { + Ok(Some(fee)) => Ok(fee), + Ok(None) => Err("Failed to estimate message fee. Message is too heavy?".into()), + Err(error) => Err(format!("Failed to estimate message fee: {:?}", error)), + }, + } +} + +impl crate::cli::RialtoSigningParams { + /// Parse CLI parameters into typed signing params. + pub fn parse(self) -> Result { + RialtoSigningParams::from_suri(&self.rialto_signer, self.rialto_signer_password.as_deref()) + .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e)) + } +} + +impl crate::cli::MillauSigningParams { + /// Parse CLI parameters into typed signing params. + pub fn parse(self) -> Result { + MillauSigningParams::from_suri(&self.millau_signer, self.millau_signer_password.as_deref()) + .map_err(|e| format!("Failed to parse millau-signer: {:?}", e)) + } +} + +impl crate::cli::MillauConnectionParams { + /// Convert CLI connection parameters into Millau RPC Client. + pub async fn into_client(self) -> relay_substrate_client::Result { + MillauClient::new(ConnectionParams { + host: self.millau_host, + port: self.millau_port, + }) + .await + } +} +impl crate::cli::RialtoConnectionParams { + /// Convert CLI connection parameters into Rialto RPC Client. + pub async fn into_client(self) -> relay_substrate_client::Result { + RialtoClient::new(ConnectionParams { + host: self.rialto_host, + port: self.rialto_port, + }) + .await + } +} + +impl crate::cli::ToRialtoMessage { + /// Convert CLI call request into runtime `Call` instance. + pub fn into_call(self) -> rialto_runtime::Call { + match self { + cli::ToRialtoMessage::Remark => { + rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(remark_payload())) + } + cli::ToRialtoMessage::Transfer { recipient, amount } => { + rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount)) + } + } + } +} + +impl crate::cli::ToMillauMessage { + /// Convert CLI call request into runtime `Call` instance. + pub fn into_call(self) -> millau_runtime::Call { + match self { + cli::ToMillauMessage::Remark => { + millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload())) + } + cli::ToMillauMessage::Transfer { recipient, amount } => { + millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount)) + } + } + } +} + #[cfg(test)] mod tests { use sp_core::Pair;