diff --git a/Cargo.lock b/Cargo.lock index 969ed49c8c..989dd56b74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -865,6 +865,7 @@ name = "bp-relayers" version = "0.1.0" dependencies = [ "bp-messages", + "bp-rialto", "frame-support", "hex", "hex-literal", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index d6e99afb2d..237c2aaa4c 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -379,7 +379,8 @@ impl pallet_session::Config for Runtime { impl pallet_bridge_relayers::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; - type PaymentProcedure = bp_relayers::MintReward, AccountId>; + type PaymentProcedure = + bp_relayers::PayLaneRewardFromAccount, AccountId>; type WeightInfo = (); } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 2d0be49a07..8186e13313 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -511,7 +511,8 @@ impl pallet_aura::Config for Runtime { impl pallet_bridge_relayers::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; - type PaymentProcedure = bp_relayers::MintReward, AccountId>; + type PaymentProcedure = + bp_relayers::PayLaneRewardFromAccount, AccountId>; type WeightInfo = (); } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 59284df910..dd4d254f17 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -396,7 +396,8 @@ impl pallet_authority_discovery::Config for Runtime { impl pallet_bridge_relayers::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; - type PaymentProcedure = bp_relayers::MintReward, AccountId>; + type PaymentProcedure = + bp_relayers::PayLaneRewardFromAccount, AccountId>; type WeightInfo = (); } diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 921ec0e4d9..9ae211e9b9 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -157,7 +157,10 @@ mod tests { use mock::{RuntimeEvent as TestEvent, *}; use crate::Event::RewardPaid; - use frame_support::{assert_noop, assert_ok, traits::fungible::Inspect}; + use frame_support::{ + assert_noop, assert_ok, + traits::fungible::{Inspect, Mutate}, + }; use frame_system::{EventRecord, Pallet as System, Phase}; use sp_runtime::DispatchError; @@ -232,16 +235,31 @@ mod tests { } #[test] - fn mint_reward_payment_procedure_actually_mints_tokens() { + fn pay_lane_reward_from_account_actually_pays_reward() { type Balances = pallet_balances::Pallet; + type PayLaneRewardFromAccount = bp_relayers::PayLaneRewardFromAccount; run_test(|| { + let lane0_rewards_account = + PayLaneRewardFromAccount::lane_rewards_account([0, 0, 0, 0]); + let lane1_rewards_account = + PayLaneRewardFromAccount::lane_rewards_account([0, 0, 0, 1]); + + Balances::mint_into(&lane0_rewards_account, 100).unwrap(); + Balances::mint_into(&lane1_rewards_account, 100).unwrap(); + assert_eq!(Balances::balance(&lane0_rewards_account), 100); + assert_eq!(Balances::balance(&lane1_rewards_account), 100); assert_eq!(Balances::balance(&1), 0); - assert_eq!(Balances::total_issuance(), 0); - bp_relayers::MintReward::::pay_reward(&1, TEST_LANE_ID, 100) - .unwrap(); + + PayLaneRewardFromAccount::pay_reward(&1, [0, 0, 0, 0], 100).unwrap(); + assert_eq!(Balances::balance(&lane0_rewards_account), 0); + assert_eq!(Balances::balance(&lane1_rewards_account), 100); assert_eq!(Balances::balance(&1), 100); - assert_eq!(Balances::total_issuance(), 100); + + PayLaneRewardFromAccount::pay_reward(&1, [0, 0, 0, 1], 100).unwrap(); + assert_eq!(Balances::balance(&lane0_rewards_account), 0); + assert_eq!(Balances::balance(&lane1_rewards_account), 0); + assert_eq!(Balances::balance(&1), 200); }); } } diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index daaa280098..3a14724f9d 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -24,6 +24,7 @@ use bp_runtime::{BasicOperatingMode, OperatingMode}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::RuntimeDebug; use scale_info::TypeInfo; +use sp_core::TypeId; use sp_std::{collections::vec_deque::VecDeque, prelude::*}; pub mod source_chain; @@ -68,6 +69,16 @@ impl OperatingMode for MessagesOperatingMode { /// Lane identifier. pub type LaneId = [u8; 4]; +/// Lane id which implements `TypeId`. +// TODO (https://github.com/paritytech/parity-bridges-common/issues/1694): +// `LaneId` shall be replaced with this across all codebase (codec-compatible) +#[derive(Decode, Encode, RuntimeDebug)] +pub struct TypedLaneId(pub [u8; 4]); + +impl TypeId for TypedLaneId { + const TYPE_ID: [u8; 4] = *b"blan"; +} + /// Message nonce. Valid messages will never have 0 nonce. pub type MessageNonce = u64; diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 4dc09f8d12..4f893f9f83 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -19,6 +19,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] +bp-rialto = { path = "../chain-rialto" } hex = "0.4" hex-literal = "0.3" diff --git a/primitives/relayers/src/lib.rs b/primitives/relayers/src/lib.rs index bd456d3631..04c43d5c78 100644 --- a/primitives/relayers/src/lib.rs +++ b/primitives/relayers/src/lib.rs @@ -19,7 +19,11 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -use bp_messages::LaneId; +use bp_messages::{LaneId, TypedLaneId}; +use sp_runtime::{ + codec::{Decode, Encode}, + traits::AccountIdConversion, +}; use sp_std::{fmt::Debug, marker::PhantomData}; /// Reward payment procedure. @@ -31,20 +35,56 @@ pub trait PaymentProcedure { fn pay_reward(relayer: &Relayer, lane_id: LaneId, reward: Reward) -> Result<(), Self::Error>; } -/// Reward payment procedure that is simply minting given amount of tokens. -pub struct MintReward(PhantomData<(T, Relayer)>); +/// Reward payment procedure that does `balances::transfer` call from the account, derived from +/// given lane. +pub struct PayLaneRewardFromAccount(PhantomData<(T, Relayer)>); -impl PaymentProcedure for MintReward +impl PayLaneRewardFromAccount where - T: frame_support::traits::fungible::Mutate, + Relayer: Decode + Encode, +{ + /// Return account that pay rewards for serving given lane. + pub fn lane_rewards_account(lane_id: LaneId) -> Relayer { + TypedLaneId(lane_id).into_sub_account_truncating(b"bridge-lane") + } +} + +impl PaymentProcedure for PayLaneRewardFromAccount +where + T: frame_support::traits::fungible::Transfer, + Relayer: Decode + Encode, { type Error = sp_runtime::DispatchError; fn pay_reward( relayer: &Relayer, - _lane_id: LaneId, + lane_id: LaneId, reward: T::Balance, ) -> Result<(), Self::Error> { - T::mint_into(relayer, reward) + T::transfer(&Self::lane_rewards_account(lane_id), relayer, reward, false).map(drop) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn lanes_are_using_different_accounts() { + assert_eq!( + PayLaneRewardFromAccount::<(), bp_rialto::AccountId>::lane_rewards_account([ + 0, 0, 0, 0 + ]), + hex_literal::hex!("626c616e000000006272696467652d6c616e6500000000000000000000000000") + .into(), + ); + + assert_eq!( + PayLaneRewardFromAccount::<(), bp_rialto::AccountId>::lane_rewards_account([ + 0, 0, 0, 1 + ]), + hex_literal::hex!("626c616e000000016272696467652d6c616e6500000000000000000000000000") + .into(), + ); } }