Derive bridged accounts (#781)

* Add derivation support.

* Add custom decoder for Accounts.

* cargo fmt --all

* Fix warn.

* Fix articles.

Co-authored-by: Hernando Castano <castano.ha@gmail.com>
This commit is contained in:
Tomasz Drwięga
2021-03-02 01:26:03 +01:00
committed by Bastian Köcher
parent 3764cda726
commit 077e2cc11b
2 changed files with 96 additions and 6 deletions
+66 -4
View File
@@ -20,6 +20,7 @@ use bp_message_lane::LaneId;
use frame_support::weights::Weight; use frame_support::weights::Weight;
use sp_core::Bytes; use sp_core::Bytes;
use sp_finality_grandpa::SetId as GrandpaAuthoritiesSetId; use sp_finality_grandpa::SetId as GrandpaAuthoritiesSetId;
use sp_runtime::app_crypto::Ss58Codec;
use structopt::{clap::arg_enum, StructOpt}; use structopt::{clap::arg_enum, StructOpt};
/// Parse relay CLI args. /// Parse relay CLI args.
@@ -63,6 +64,8 @@ pub enum Command {
EncodeMessagePayload(EncodeMessagePayload), EncodeMessagePayload(EncodeMessagePayload),
/// Estimate Delivery and Dispatch Fee required for message submission to message lane. /// Estimate Delivery and Dispatch Fee required for message submission to message lane.
EstimateFee(EstimateFee), EstimateFee(EstimateFee),
/// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain.
DeriveAccount(DeriveAccount),
} }
/// Start headers relayer process. /// Start headers relayer process.
@@ -268,6 +271,20 @@ pub enum 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 {
/// Given Rialto AccountId, display corresponding Millau AccountId.
RialtoToMillau { account: AccountId },
/// Given Millau AccountId, display corresponding Rialto AccountId.
MillauToRialto { account: AccountId },
}
/// MessagePayload that can be delivered to message lane pallet on Millau. /// MessagePayload that can be delivered to message lane pallet on Millau.
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
pub enum MillauToRialtoMessagePayload { pub enum MillauToRialtoMessagePayload {
@@ -284,7 +301,7 @@ pub enum MillauToRialtoMessagePayload {
message: ToRialtoMessage, message: ToRialtoMessage,
/// SS58 encoded account that will send the payload (must have SS58Prefix = 42) /// SS58 encoded account that will send the payload (must have SS58Prefix = 42)
#[structopt(long)] #[structopt(long)]
sender: bp_rialto::AccountId, sender: AccountId,
}, },
} }
@@ -305,7 +322,7 @@ pub enum RialtoToMillauMessagePayload {
/// SS58 encoded account that will send the payload (must have SS58Prefix = 42) /// SS58 encoded account that will send the payload (must have SS58Prefix = 42)
#[structopt(long)] #[structopt(long)]
sender: bp_rialto::AccountId, sender: AccountId,
}, },
} }
@@ -327,7 +344,7 @@ pub enum ToRialtoMessage {
Transfer { Transfer {
/// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42)
#[structopt(long)] #[structopt(long)]
recipient: bp_rialto::AccountId, recipient: AccountId,
/// Amount of target tokens to send. /// Amount of target tokens to send.
#[structopt(long)] #[structopt(long)]
amount: bp_rialto::Balance, amount: bp_rialto::Balance,
@@ -352,7 +369,7 @@ pub enum ToMillauMessage {
Transfer { Transfer {
/// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42)
#[structopt(long)] #[structopt(long)]
recipient: bp_millau::AccountId, recipient: AccountId,
/// Amount of target tokens to send. /// Amount of target tokens to send.
#[structopt(long)] #[structopt(long)]
amount: bp_millau::Balance, amount: bp_millau::Balance,
@@ -371,6 +388,51 @@ arg_enum! {
} }
} }
/// Generic account id with custom parser.
#[derive(Debug)]
pub struct AccountId {
account: sp_runtime::AccountId32,
version: sp_core::crypto::Ss58AddressFormat,
}
impl std::str::FromStr for AccountId {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (account, version) = sp_runtime::AccountId32::from_ss58check_with_version(s)
.map_err(|err| format!("Unable to decode SS58 address: {:?}", err))?;
Ok(Self { account, version })
}
}
impl AccountId {
/// Perform runtime checks of SS58 version and get Rialto's AccountId.
pub fn into_rialto(self) -> bp_rialto::AccountId {
self.check_and_get("Rialto", rialto_runtime::SS58Prefix::get())
}
/// Perform runtime checks of SS58 version and get Millau's AccountId.
pub fn into_millau(self) -> bp_millau::AccountId {
self.check_and_get("Millau", millau_runtime::SS58Prefix::get())
}
/// Check SS58Prefix and return the account id.
fn check_and_get(self, net: &str, expected_prefix: u8) -> sp_runtime::AccountId32 {
let version: u16 = self.version.into();
println!("Version: {} vs {}", version, expected_prefix);
if version != expected_prefix as u16 {
log::warn!(
target: "bridge",
"Following address: {} does not seem to match {}'s format, got: {}",
self.account,
net,
self.version,
)
}
self.account
}
}
/// Lane id. /// Lane id.
#[derive(Debug)] #[derive(Debug)]
pub struct HexLaneId(LaneId); pub struct HexLaneId(LaneId);
+30 -2
View File
@@ -68,6 +68,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> {
cli::Command::EncodeCall(arg) => run_encode_call(arg).await, cli::Command::EncodeCall(arg) => run_encode_call(arg).await,
cli::Command::EncodeMessagePayload(arg) => run_encode_message_payload(arg).await, cli::Command::EncodeMessagePayload(arg) => run_encode_message_payload(arg).await,
cli::Command::EstimateFee(arg) => run_estimate_fee(arg).await, cli::Command::EstimateFee(arg) => run_estimate_fee(arg).await,
cli::Command::DeriveAccount(arg) => run_derive_account(arg).await,
} }
} }
@@ -412,6 +413,31 @@ async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> {
Ok(()) Ok(())
} }
async fn run_derive_account(cmd: cli::DeriveAccount) -> Result<(), String> {
match cmd {
cli::DeriveAccount::RialtoToMillau { account } => {
let account = account.into_rialto();
let acc = bp_runtime::SourceAccount::Account(account.clone());
let id = bp_millau::derive_account_from_rialto_id(acc);
println!(
"{} (Rialto)\n\nCorresponding (derived) account id:\n-> {} (Millau)",
account, id
)
}
cli::DeriveAccount::MillauToRialto { account } => {
let account = account.into_millau();
let acc = bp_runtime::SourceAccount::Account(account.clone());
let id = bp_rialto::derive_account_from_millau_id(acc);
println!(
"{} (Millau)\n\nCorresponding (derived) account id:\n-> {} (Rialto)",
account, id
)
}
}
Ok(())
}
async fn estimate_message_delivery_and_dispatch_fee<Fee: Decode, C: Chain, P: Encode>( async fn estimate_message_delivery_and_dispatch_fee<Fee: Decode, C: Chain, P: Encode>(
client: &relay_substrate_client::Client<C>, client: &relay_substrate_client::Client<C>,
estimate_fee_method: &str, estimate_fee_method: &str,
@@ -615,7 +641,7 @@ impl crate::cli::MillauToRialtoMessagePayload {
.map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)),
Self::Message { message, sender } => { Self::Message { message, sender } => {
let spec_version = rialto_runtime::VERSION.spec_version; let spec_version = rialto_runtime::VERSION.spec_version;
let origin = CallOrigin::SourceAccount(sender); let origin = CallOrigin::SourceAccount(sender.into_millau());
let call = message.into_call()?; let call = message.into_call()?;
let weight = call.get_dispatch_info().weight; let weight = call.get_dispatch_info().weight;
@@ -635,7 +661,7 @@ impl crate::cli::RialtoToMillauMessagePayload {
.map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)),
Self::Message { message, sender } => { Self::Message { message, sender } => {
let spec_version = millau_runtime::VERSION.spec_version; let spec_version = millau_runtime::VERSION.spec_version;
let origin = CallOrigin::SourceAccount(sender); let origin = CallOrigin::SourceAccount(sender.into_rialto());
let call = message.into_call()?; let call = message.into_call()?;
let weight = call.get_dispatch_info().weight; let weight = call.get_dispatch_info().weight;
@@ -699,6 +725,7 @@ impl crate::cli::ToRialtoMessage {
))) )))
} }
cli::ToRialtoMessage::Transfer { recipient, amount } => { cli::ToRialtoMessage::Transfer { recipient, amount } => {
let recipient = recipient.into_rialto();
rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount)) rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount))
} }
}; };
@@ -728,6 +755,7 @@ impl crate::cli::ToMillauMessage {
))) )))
} }
cli::ToMillauMessage::Transfer { recipient, amount } => { cli::ToMillauMessage::Transfer { recipient, amount } => {
let recipient = recipient.into_millau();
millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount)) millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount))
} }
}; };