From 0d7291d72927673bce8eaf8ce02ea4d460d197b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 5 Apr 2021 17:58:34 +0200 Subject: [PATCH] CLI: Derive Account (#860) * Move derive account. * Fix account derivation. --- .../bin-substrate/src/cli/derive_account.rs | 135 ++++++++++++++++++ bridges/relays/bin-substrate/src/cli/mod.rs | 27 +--- .../bin-substrate/src/rialto_millau/cli.rs | 24 ---- .../bin-substrate/src/rialto_millau/mod.rs | 60 +------- 4 files changed, 139 insertions(+), 107 deletions(-) create mode 100644 bridges/relays/bin-substrate/src/cli/derive_account.rs diff --git a/bridges/relays/bin-substrate/src/cli/derive_account.rs b/bridges/relays/bin-substrate/src/cli/derive_account.rs new file mode 100644 index 0000000000..cd40fb5891 --- /dev/null +++ b/bridges/relays/bin-substrate/src/cli/derive_account.rs @@ -0,0 +1,135 @@ +// 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::AccountId; +use relay_substrate_client::Chain; +use structopt::{clap::arg_enum, StructOpt}; + +/// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. +/// +/// The (derived) target chain `AccountId` is going to be used as dispatch origin of the call +/// that has been sent over the bridge. +/// This account can also be used to receive target-chain funds (or other form of ownership), +/// since messages sent over the bridge will be able to spend these. +#[derive(StructOpt)] +pub struct DeriveAccount { + /// A bridge instance to initalize. + #[structopt(possible_values = &DeriveAccountBridge::variants(), case_insensitive = true)] + bridge: DeriveAccountBridge, + /// Source-chain address to derive Target-chain address from. + account: AccountId, +} + +arg_enum! { + #[derive(Debug)] + /// Bridge to derive account for. + pub enum DeriveAccountBridge { + MillauToRialto, + RialtoToMillau, + } +} + +macro_rules! select_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + DeriveAccountBridge::MillauToRialto => { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_client::Rialto; + + #[allow(unused_imports)] // the import is not used in `run` + use bp_millau::derive_account_from_rialto_id as derive_account; + + $generic + } + DeriveAccountBridge::RialtoToMillau => { + type Source = relay_rialto_client::Rialto; + type Target = relay_millau_client::Millau; + + #[allow(unused_imports)] // the import is not used in `run`. + use bp_rialto::derive_account_from_millau_id as derive_account; + + $generic + } + } + }; +} + +impl DeriveAccount { + /// Parse CLI arguments and derive account. + /// + /// Returns both the Source account in correct SS58 format and the derived account. + fn derive_account(&self) -> (AccountId, AccountId) { + select_bridge!(self.bridge, { + let mut account = self.account.clone(); + account.enforce_chain::(); + let acc = bp_runtime::SourceAccount::Account(account.raw_id()); + let id = derive_account(acc); + let derived_account = AccountId::from_raw::(id); + (account, derived_account) + }) + } + + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + select_bridge!(self.bridge, { + let (account, derived_account) = self.derive_account(); + println!("Source address:\n{} ({})", account, Source::NAME); + println!( + "->Corresponding (derived) address:\n{} ({})", + derived_account, + Target::NAME, + ); + + Ok(()) + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn derive_account_cli(bridge: &str, account: &str) -> (AccountId, AccountId) { + DeriveAccount::from_iter(vec!["derive-account", bridge, account]).derive_account() + } + + #[test] + fn should_derive_accounts_correctly() { + // given + let rialto = "5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU"; + let millau = "752paRyW1EGfq9YLTSSqcSJ5hqnBDidBmaftGhBo8fy6ypW9"; + + // when + let (rialto_parsed, rialto_derived) = derive_account_cli("RialtoToMillau", rialto); + let (millau_parsed, millau_derived) = derive_account_cli("MillauToRialto", millau); + let (millau2_parsed, millau2_derived) = derive_account_cli("MillauToRialto", rialto); + + // then + assert_eq!(format!("{}", rialto_parsed), rialto); + assert_eq!(format!("{}", millau_parsed), millau); + assert_eq!(format!("{}", millau2_parsed), millau); + + assert_eq!( + format!("{}", rialto_derived), + "73gLnUwrAdH4vMjbXCiNEpgyz1PLk9JxCaY4cKzvfSZT73KE" + ); + assert_eq!( + format!("{}", millau_derived), + "5rpTJqGv1BPAYy2sXzkPpc3Wx1ZpQtgfuBsrDpNV4HsXAmbi" + ); + assert_eq!(millau_derived, millau2_derived); + } +} diff --git a/bridges/relays/bin-substrate/src/cli/mod.rs b/bridges/relays/bin-substrate/src/cli/mod.rs index 5419f82637..3bcc1bf584 100644 --- a/bridges/relays/bin-substrate/src/cli/mod.rs +++ b/bridges/relays/bin-substrate/src/cli/mod.rs @@ -25,6 +25,7 @@ use frame_support::weights::Weight; use sp_runtime::app_crypto::Ss58Codec; use structopt::{clap::arg_enum, StructOpt}; +mod derive_account; mod init_bridge; mod relay_headers; mod relay_messages; @@ -71,7 +72,7 @@ pub enum Command { /// Estimate Delivery and Dispatch Fee required for message submission to messages pallet. EstimateFee(EstimateFee), /// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. - DeriveAccount(DeriveAccount), + DeriveAccount(derive_account::DeriveAccount), } impl Command { @@ -159,28 +160,6 @@ impl EstimateFee { } } -/// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. -/// -/// The (derived) target chain `AccountId` is going to be used as dispatch origin of the call -/// that has been sent over the bridge. -/// This account can also be used to receive target-chain funds (or other form of ownership), -/// since messages sent over the bridge will be able to spend these. -#[derive(StructOpt)] -pub enum DeriveAccount { - #[structopt(flatten)] - RialtoMillau(rialto_millau::DeriveAccount), -} - -impl DeriveAccount { - /// 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. @@ -213,7 +192,7 @@ impl Balance { } /// Generic account id with custom parser. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct AccountId { account: sp_runtime::AccountId32, ss58_format: sp_core::crypto::Ss58AddressFormat, diff --git a/bridges/relays/bin-substrate/src/rialto_millau/cli.rs b/bridges/relays/bin-substrate/src/rialto_millau/cli.rs index 3d314cc71b..2f11156537 100644 --- a/bridges/relays/bin-substrate/src/rialto_millau/cli.rs +++ b/bridges/relays/bin-substrate/src/rialto_millau/cli.rs @@ -176,30 +176,6 @@ impl EstimateFee { } } -/// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. -/// -/// The (derived) target chain `AccountId` is going to be used as dispatch origin of the call -/// that has been sent over the bridge. -/// This account can also be used to receive target-chain funds (or other form of ownership), -/// since messages sent over the bridge will be able to spend these. -/// -/// TODO [#855] Move to separate module. -#[derive(StructOpt)] -pub enum DeriveAccount { - /// Given Rialto AccountId, display corresponding Millau AccountId. - RialtoToMillau { account: AccountId }, - /// Given Millau AccountId, display corresponding Rialto AccountId. - MillauToRialto { account: AccountId }, -} - -impl DeriveAccount { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - super::run_derive_account(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 5446e382a7..bcc7821e20 100644 --- a/bridges/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/bridges/relays/bin-substrate/src/rialto_millau/mod.rs @@ -29,7 +29,7 @@ pub type MillauClient = relay_substrate_client::Client; pub type RialtoClient = relay_substrate_client::Client; use crate::cli::{ - AccountId, CliChain, ExplicitOrMaximal, HexBytes, Origins, SourceConnectionParams, SourceSigningParams, + CliChain, ExplicitOrMaximal, HexBytes, Origins, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, TargetSigningParams, }; use codec::{Decode, Encode}; @@ -337,43 +337,6 @@ async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { Ok(()) } -async fn run_derive_account(cmd: cli::DeriveAccount) -> Result<(), String> { - match cmd { - cli::DeriveAccount::RialtoToMillau { mut account } => { - type Source = Rialto; - type Target = Millau; - - account.enforce_chain::(); - let acc = bp_runtime::SourceAccount::Account(account.raw_id()); - let id = bp_millau::derive_account_from_rialto_id(acc); - let derived_account = AccountId::from_raw::(id); - println!("Source address:\n{} ({})", account, Source::NAME); - println!( - "->Corresponding (derived) address:\n{} ({})", - derived_account, - Target::NAME, - ); - } - cli::DeriveAccount::MillauToRialto { mut account } => { - type Source = Millau; - type Target = Rialto; - - account.enforce_chain::(); - let acc = bp_runtime::SourceAccount::Account(account.raw_id()); - let id = bp_rialto::derive_account_from_millau_id(acc); - let derived_account = AccountId::from_raw::(id); - println!("Source address:\n{} ({})", account, Source::NAME); - println!( - "->Corresponding (derived) address:\n{} ({})", - derived_account, - Target::NAME, - ); - } - } - - Ok(()) -} - async fn estimate_message_delivery_and_dispatch_fee( client: &relay_substrate_client::Client, estimate_fee_method: &str, @@ -864,25 +827,4 @@ mod tests { extra_bytes_in_transaction, ); } - - #[test] - fn should_reformat_addresses() { - // given - let mut rialto1: AccountId = "5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU".parse().unwrap(); - let mut millau1: AccountId = "752paRyW1EGfq9YLTSSqcSJ5hqnBDidBmaftGhBo8fy6ypW9".parse().unwrap(); - - // when - rialto1.enforce_chain::(); - millau1.enforce_chain::(); - - // then - assert_eq!( - &format!("{}", rialto1), - "752paRyW1EGfq9YLTSSqcSJ5hqnBDidBmaftGhBo8fy6ypW9" - ); - assert_eq!( - &format!("{}", millau1), - "5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU" - ); - } }