Skip to content
Snippets Groups Projects
Commit 0d7291d7 authored by Tomasz Drwięga's avatar Tomasz Drwięga Committed by Bastian Köcher
Browse files

CLI: Derive Account (#860)

* Move derive account.

* Fix account derivation.
parent da3f94d9
Branches
No related merge requests found
// 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::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::<Source>();
let acc = bp_runtime::SourceAccount::Account(account.raw_id());
let id = derive_account(acc);
let derived_account = AccountId::from_raw::<Target>(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);
}
}
......@@ -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,
......
......@@ -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)
}
......
......@@ -29,7 +29,7 @@ pub type MillauClient = relay_substrate_client::Client<Millau>;
pub type RialtoClient = relay_substrate_client::Client<Rialto>;
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::<Source>();
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::<Target>(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::<Source>();
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::<Target>(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<Fee: Decode, C: Chain, P: Encode>(
client: &relay_substrate_client::Client<C>,
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::<Millau>();
millau1.enforce_chain::<Rialto>();
// then
assert_eq!(
&format!("{}", rialto1),
"752paRyW1EGfq9YLTSSqcSJ5hqnBDidBmaftGhBo8fy6ypW9"
);
assert_eq!(
&format!("{}", millau1),
"5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU"
);
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment