diff --git a/bridges/bin/millau/node/Cargo.toml b/bridges/bin/millau/node/Cargo.toml index 149731529f782..1696f73a48173 100644 --- a/bridges/bin/millau/node/Cargo.toml +++ b/bridges/bin/millau/node/Cargo.toml @@ -16,7 +16,7 @@ structopt = "0.3.21" # Bridge dependencies bp-message-lane = { path = "../../../primitives/message-lane" } -bp-rialto = { path = "../../../primitives/rialto" } +bp-millau= { path = "../../../primitives/millau" } bp-runtime = { path = "../../../primitives/runtime" } millau-runtime = { path = "../runtime" } pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } diff --git a/bridges/bin/millau/node/src/chain_spec.rs b/bridges/bin/millau/node/src/chain_spec.rs index 8c7c40472751b..2ead8612fac21 100644 --- a/bridges/bin/millau/node/src/chain_spec.rs +++ b/bridges/bin/millau/node/src/chain_spec.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use bp_millau::derive_account_from_rialto_id; use millau_runtime::{ AccountId, AuraConfig, BalancesConfig, BridgeRialtoConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, @@ -121,6 +122,9 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Dave"), + )), ], true, ) @@ -173,3 +177,13 @@ fn testnet_genesis( }), } } + +#[test] +fn derived_dave_account_is_as_expected() { + let dave = get_account_id_from_seed::("Dave"); + let derived: AccountId = derive_account_from_rialto_id(bp_runtime::SourceAccount::Account(dave)); + assert_eq!( + derived.to_string(), + "5G81vRqUUysQGtN5aEThD5UsLdt4rZWSbVLkjuZzLHadp8ZD".to_string() + ); +} diff --git a/bridges/bin/rialto/node/src/chain_spec.rs b/bridges/bin/rialto/node/src/chain_spec.rs index 229fbd1cc90ef..dc2a9afea6135 100644 --- a/bridges/bin/rialto/node/src/chain_spec.rs +++ b/bridges/bin/rialto/node/src/chain_spec.rs @@ -122,7 +122,6 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), - derive_account_from_millau_id(bp_runtime::SourceAccount::Root), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Dave"), )), @@ -206,12 +205,3 @@ fn derived_dave_account_is_as_expected() { "5Hg7WQyk8C1FmPzxY3xSjR7S6zZZC5sAL35vMr6NpW17jBhQ".to_string() ); } - -#[test] -fn derived_root_account_is_as_expected() { - let root: AccountId = derive_account_from_millau_id(bp_runtime::SourceAccount::Root); - assert_eq!( - root.to_string(), - "5HYYwXQvxhgdcBYs6kzqfK1HW6M3UF3Kh4YM7j288yiqbhnt".to_string() - ); -} diff --git a/bridges/modules/message-lane/src/instant_payments.rs b/bridges/modules/message-lane/src/instant_payments.rs index fe860fdb3f8ac..41f8b48b74749 100644 --- a/bridges/modules/message-lane/src/instant_payments.rs +++ b/bridges/modules/message-lane/src/instant_payments.rs @@ -46,9 +46,11 @@ where Currency::transfer(submitter, relayer_fund_account, *fee, ExistenceRequirement::AllowDeath) .map_err(Into::into) } - Sender::Root | Sender::None => { - // fixme: we might want to add root account id to this struct. - Err("Root and None account is not allowed to send regular messages.") + Sender::Root => { + Err("Sending messages from Root account is not supported yet. See GitHub issue #559 for more.") + } + Sender::None => { + Err("Sending messages from None account is not supported yet. See GitHub issue #559 for more.") } } } diff --git a/bridges/primitives/millau/src/lib.rs b/bridges/primitives/millau/src/lib.rs index 5b74ec54c1318..8642b04cf0d43 100644 --- a/bridges/primitives/millau/src/lib.rs +++ b/bridges/primitives/millau/src/lib.rs @@ -29,6 +29,7 @@ use frame_support::{ RuntimeDebug, }; use sp_core::Hasher as HasherT; +use sp_runtime::traits::Convert; use sp_runtime::{ traits::{IdentifyAccount, Verify}, MultiSignature, MultiSigner, Perbill, @@ -161,6 +162,19 @@ impl sp_runtime::traits::Convert for AccountIdConverte } } +/// We use this to get the account on Millau (target) which is derived from Rialto's (source) +/// account. We do this so we can fund the derived account on Millau at Genesis to it can pay +/// transaction fees. +/// +/// The reason we can use the same `AccountId` type for both chains is because they share the same +/// development seed phrase. +/// +/// Note that this should only be used for testing. +pub fn derive_account_from_rialto_id(id: bp_runtime::SourceAccount) -> AccountId { + let encoded_id = bp_runtime::derive_account_id(bp_runtime::RIALTO_BRIDGE_INSTANCE, id); + AccountIdConverter::convert(encoded_id) +} + /// Get a struct which defines the weight limits and values used during extrinsic execution. pub fn runtime_block_weights() -> frame_system::limits::BlockWeights { frame_system::limits::BlockWeights::builder() diff --git a/bridges/primitives/rialto/src/lib.rs b/bridges/primitives/rialto/src/lib.rs index 26599786c2d45..71f0329afc37d 100644 --- a/bridges/primitives/rialto/src/lib.rs +++ b/bridges/primitives/rialto/src/lib.rs @@ -132,7 +132,7 @@ impl Convert for AccountIdConverter { // // Note that this should only be used for testing. pub fn derive_account_from_millau_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(*b"mlau", id); + let encoded_id = bp_runtime::derive_account_id(bp_runtime::MILLAU_BRIDGE_INSTANCE, id); AccountIdConverter::convert(encoded_id) } diff --git a/bridges/relays/substrate/src/cli.rs b/bridges/relays/substrate/src/cli.rs index d3662ba26840e..0e7f92001a355 100644 --- a/bridges/relays/substrate/src/cli.rs +++ b/bridges/relays/substrate/src/cli.rs @@ -138,12 +138,15 @@ pub enum Command { /// Hex-encoded lane id. #[structopt(long)] lane: HexLaneId, - /// Message type. - #[structopt(long, possible_values = &ToMillauMessage::variants())] - message: ToMillauMessage, /// Delivery and dispatch fee. #[structopt(long)] fee: bp_rialto::Balance, + /// Message type. + #[structopt(subcommand)] + message: ToMillauMessage, + /// The origin to use when dispatching the message on the target chain. + #[structopt(long, possible_values = &Origins::variants())] + origin: Origins, }, } @@ -161,19 +164,24 @@ pub enum ToRialtoMessage { }, } -arg_enum! { - #[derive(Debug)] - /// All possible messages that may be delivered to the Millau chain. - pub enum ToMillauMessage { - Remark, - } +/// All possible messages that may be delivered to the Millau chain. +#[derive(StructOpt, Debug)] +pub enum ToMillauMessage { + /// Make an on-chain remark (comment). + Remark, + /// Transfer the specified `amount` of native tokens to a particular `recipient`. + Transfer { + #[structopt(long)] + recipient: bp_millau::AccountId, + #[structopt(long)] + amount: bp_millau::Balance, + }, } arg_enum! { #[derive(Debug)] /// The origin to use when dispatching the message on the target chain. pub enum Origins { - Root, Target, Source, } diff --git a/bridges/relays/substrate/src/main.rs b/bridges/relays/substrate/src/main.rs index 789105a27b18a..a63dc9623ed16 100644 --- a/bridges/relays/substrate/src/main.rs +++ b/bridges/relays/substrate/src/main.rs @@ -97,7 +97,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { &rialto_client, &rialto_sign.signer, rialto_signer_next_index, - millau_runtime::SudoCall::sudo(Box::new( + rialto_runtime::SudoCall::sudo(Box::new( rialto_runtime::BridgeMillauCall::initialize(initialization_data).into(), )) .into(), @@ -290,12 +290,6 @@ async fn run_command(command: cli::Command) -> Result<(), String> { let rialto_origin_public = rialto_sign.signer.public(); let payload = match origin { - cli::Origins::Root => MessagePayload { - spec_version: rialto_runtime::VERSION.spec_version, - weight: rialto_call_weight, - origin: CallOrigin::SourceRoot, - call: rialto_call.encode(), - }, cli::Origins::Source => MessagePayload { spec_version: rialto_runtime::VERSION.spec_version, weight: rialto_call_weight, @@ -312,7 +306,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { spec_version: rialto_runtime::VERSION.spec_version, weight: rialto_call_weight, origin: CallOrigin::TargetAccount( - millau_account_id.clone(), + millau_account_id, rialto_origin_public.into(), rialto_origin_signature.into(), ), @@ -383,6 +377,8 @@ async fn run_command(command: cli::Command) -> Result<(), String> { lane, message, fee, + origin, + .. } => { let rialto_client = RialtoClient::new(ConnectionParams { host: rialto.rialto_host, @@ -412,21 +408,29 @@ async fn run_command(command: cli::Command) -> Result<(), String> { .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 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 mut millau_origin_signature_message = Vec::new(); - millau_call.encode_to(&mut millau_origin_signature_message); - rialto_account_id.encode_to(&mut millau_origin_signature_message); - let millau_origin_signature = millau_sign.signer.sign(&millau_origin_signature_message); + 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 mut millau_origin_signature_message = Vec::new(); + millau_call.encode_to(&mut millau_origin_signature_message); + rialto_account_id.encode_to(&mut millau_origin_signature_message); + let millau_origin_signature = millau_sign.signer.sign(&millau_origin_signature_message); - let rialto_call = - rialto_runtime::Call::BridgeMillauMessageLane(rialto_runtime::MessageLaneCall::send_message( - lane.into(), MessagePayload { spec_version: millau_runtime::VERSION.spec_version, weight: millau_call_weight, @@ -436,9 +440,13 @@ async fn run_command(command: cli::Command) -> Result<(), String> { millau_origin_signature.into(), ), call: millau_call.encode(), - }, - fee, - )); + } + } + }; + + let rialto_call = rialto_runtime::Call::BridgeMillauMessageLane( + rialto_runtime::MessageLaneCall::send_message(lane.into(), payload, fee), + ); let signed_rialto_call = Rialto::sign_transaction( &rialto_client,