Add Derived Account Origins to Dispatcher (#519)

* Update some docs

* Add derived account origin

* Add tests for derived origin

* Do a little bit of cleanup

* Change Origin type to use AccountIds instead of Public keys

* Update (most) tests to use new Origin types

* Remove redundant test

* Update `runtime-common` tests to use new Origin types

* Remove unused import

* Fix documentation around origin verification

* Update config types to use AccountIds in runtime

* Update Origin type used in message relay

* Use correct type when verifying message origin

* Make CallOrigin docs more consistent

* Use AccountIds instead of Public keys in Runtime types

* Introduce trait for converting AccountIds

* Bring back standalone function for deriving account IDs

* Remove AccountIdConverter configuration trait

* Remove old bridge_account_id derivation function

* Handle target ID decoding errors more gracefully

* Update message-lane to use new AccountId derivation

* Update merged code to use new Origin types

* Use explicit conversion between H256 and AccountIds

* Make relayer fund account a config option in `message-lane` pallet

* Add note about deriving the same account on different chains

* Fix test weight

* Use AccountId instead of Public key when signing Calls

* Semi-hardcode relayer fund address into Message Lane pallet
This commit is contained in:
Hernando Castano
2020-11-30 14:49:09 -05:00
committed by Bastian Köcher
parent c20b4c868f
commit 951aa36c2b
15 changed files with 383 additions and 203 deletions
@@ -39,7 +39,7 @@ pub trait MessageDispatch<MessageId> {
///
/// `bridge` indicates instance of deployed bridge where the message came from.
///
/// `id` is a short unique if of the message.
/// `id` is a short unique identifier of the message.
///
/// Returns post-dispatch (actual) message weight.
fn dispatch(bridge: InstanceId, id: MessageId, message: Self::Message);
@@ -93,8 +93,17 @@ pub trait MessageDeliveryAndDispatchPayment<AccountId, Balance> {
/// Withhold/write-off delivery_and_dispatch_fee from submitter account to
/// some relayers-fund account.
fn pay_delivery_and_dispatch_fee(submitter: &AccountId, fee: &Balance) -> Result<(), Self::Error>;
fn pay_delivery_and_dispatch_fee(
submitter: &AccountId,
fee: &Balance,
relayer_fund_account: &AccountId,
) -> Result<(), Self::Error>;
/// Pay reward for delivering message to the given relayer account.
fn pay_relayer_reward(confirmation_relayer: &AccountId, relayer: &AccountId, reward: &Balance);
fn pay_relayer_reward(
confirmation_relayer: &AccountId,
relayer: &AccountId,
reward: &Balance,
relayer_fund_account: &AccountId,
);
}
+8
View File
@@ -136,6 +136,14 @@ pub type AccountSigner = MultiSigner;
/// Balance of an account.
pub type Balance = u64;
/// Convert a 256-bit hash into an AccountId.
pub struct AccountIdConverter;
impl sp_runtime::traits::Convert<sp_core::H256, AccountId> for AccountIdConverter {
fn convert(hash: sp_core::H256) -> AccountId {
hash.to_fixed_bytes().into()
}
}
sp_api::decl_runtime_apis! {
/// API for querying information about Millau headers from the Bridge Pallet instance.
///
+9
View File
@@ -98,6 +98,15 @@ pub type AccountSigner = MultiSigner;
/// Balance of an account.
pub type Balance = u128;
/// Convert a 256-bit hash into an AccountId.
pub struct AccountIdConverter;
impl sp_runtime::traits::Convert<sp_core::H256, AccountId> for AccountIdConverter {
fn convert(hash: sp_core::H256) -> AccountId {
hash.to_fixed_bytes().into()
}
}
sp_api::decl_runtime_apis! {
/// API for querying information about Rialto headers from the Bridge Pallet instance.
///
+2
View File
@@ -13,6 +13,7 @@ num-traits = { version = "0.2", default-features = false }
# Substrate Dependencies
frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false }
sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false }
@@ -23,6 +24,7 @@ std = [
"codec/std",
"frame-support/std",
"num-traits/std",
"sp-core/std",
"sp-io/std",
"sp-runtime/std",
"sp-std/std",
+43 -14
View File
@@ -18,7 +18,8 @@
#![cfg_attr(not(feature = "std"), no_std)]
use codec::{Decode, Encode};
use codec::Encode;
use sp_core::hash::H256;
use sp_io::hashing::blake2_256;
pub use chain::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf};
@@ -46,17 +47,45 @@ pub const MESSAGE_LANE_MODULE_PREFIX: &[u8] = b"pallet-bridge/message-lane";
/// to identify deployed instance dynamically. This type is used for that.
pub type InstanceId = [u8; 4];
/// Returns id of account that acts as "system" account of given bridge instance.
/// The `module_prefix` (arbitrary slice) may be used to generate module-level
/// "system" account, so you could have separate "system" accounts for currency
/// exchange, message dispatch and other modules.
///
/// The account is not supposed to actually exists on the chain, or to have any funds.
/// It is only used to
pub fn bridge_account_id<AccountId>(bridge: InstanceId, module_prefix: &[u8]) -> AccountId
where
AccountId: Decode + Default,
{
let entropy = (module_prefix, bridge).using_encoded(blake2_256);
AccountId::decode(&mut &entropy[..]).unwrap_or_default()
/// Type of accounts on the source chain.
pub enum SourceAccount<T> {
/// An account that belongs to Root (priviledged origin).
Root,
/// A non-priviledged account.
///
/// The embedded account ID may or may not have a private key depending on the "owner" of the
/// account (private key, pallet, proxy, etc.).
Account(T),
}
/// Derive an account ID from a foreign account ID.
///
/// This function returns an encoded Blake2 hash. It is the responsibility of the caller to ensure
/// this can be succesfully decoded into an AccountId.
///
/// The `bridge_id` is used to provide extra entropy when producing account IDs. This helps prevent
/// AccountId collisions between different bridges on a single target chain.
///
/// Note: If the same `bridge_id` is used across different chains (for example, if one source chain
/// is bridged to multiple target chains), then all the derived accounts would be the same across
/// the different chains. This could negatively impact users' privacy across chains.
pub fn derive_account_id<AccountId>(bridge_id: InstanceId, id: SourceAccount<AccountId>) -> H256
where
AccountId: Encode,
{
match id {
SourceAccount::Root => ("root", bridge_id).using_encoded(blake2_256),
SourceAccount::Account(id) => ("account", bridge_id, id).using_encoded(blake2_256),
}
.into()
}
/// Derive the account ID of the shared relayer fund account.
///
/// This account is used to collect fees for relayers that are passing messages across the bridge.
///
/// The account ID can be the same across different instances of `message-lane` if the same
/// `bridge_id` is used.
pub fn derive_relayer_fund_account_id(bridge_id: InstanceId) -> H256 {
("relayer-fund-account", bridge_id).using_encoded(blake2_256).into()
}