From ed2a3082ef10df411b9589867deafda4b1243538 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 14 Mar 2022 16:36:58 +0300 Subject: [PATCH] Support dedicated lanes for pallets (#962) * pass call origin to the message verifier * is_outbound_lane_enabled -> is_message_accepted * trait SenderOrigin * only accept messages from token swap pallet to token swap lane * tests for edge cases of pay_delivery_and_dispatch_fee * fixed origin verification * fmt * fix benchmarks compilation * fix TODO with None account and non-zero message fee (already covered by tests) * revert cargo fmt changes temporarily --- bridges/bin/millau/runtime/src/lib.rs | 5 +- .../bin/millau/runtime/src/rialto_messages.rs | 40 ++++++- bridges/bin/rialto/runtime/src/lib.rs | 3 +- .../bin/rialto/runtime/src/millau_messages.rs | 20 +++- bridges/bin/runtime-common/Cargo.toml | 5 +- bridges/bin/runtime-common/README.md | 7 +- bridges/bin/runtime-common/src/messages.rs | 92 ++++++++++++---- .../modules/messages/src/instant_payments.rs | 92 +++++++++++++--- bridges/modules/messages/src/lib.rs | 30 +++-- bridges/modules/messages/src/mock.rs | 29 +++-- .../modules/token-swap/src/benchmarking.rs | 3 +- bridges/modules/token-swap/src/lib.rs | 104 +++++++++++++----- bridges/modules/token-swap/src/mock.rs | 13 ++- bridges/primitives/messages/Cargo.toml | 1 + .../primitives/messages/src/source_chain.rs | 46 +++++--- 15 files changed, 361 insertions(+), 129 deletions(-) diff --git a/bridges/bin/millau/runtime/src/lib.rs b/bridges/bin/millau/runtime/src/lib.rs index 7eb6b0247eb6..5f8e50323355 100644 --- a/bridges/bin/millau/runtime/src/lib.rs +++ b/bridges/bin/millau/runtime/src/lib.rs @@ -456,10 +456,9 @@ impl pallet_bridge_messages::Config for Runtime { type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, - (), + WithRialtoMessagesInstance, pallet_balances::Pallet, GetDeliveryConfirmationTransactionFee, - RootAccountForPayments, >; type OnMessageAccepted = (); type OnDeliveryConfirmed = @@ -525,7 +524,7 @@ construct_runtime!( BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, - BridgeRialtoTokenSwap: pallet_bridge_token_swap::{Pallet, Call, Storage, Event}, + BridgeRialtoTokenSwap: pallet_bridge_token_swap::{Pallet, Call, Storage, Event, Origin}, // Westend bridge modules. BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, diff --git a/bridges/bin/millau/runtime/src/rialto_messages.rs b/bridges/bin/millau/runtime/src/rialto_messages.rs index 928fe329d2f8..d925d805dd04 100644 --- a/bridges/bin/millau/runtime/src/rialto_messages.rs +++ b/bridges/bin/millau/runtime/src/rialto_messages.rs @@ -19,7 +19,7 @@ use crate::Runtime; use bp_messages::{ - source_chain::TargetHeaderChain, + source_chain::{SenderOrigin, TargetHeaderChain}, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; @@ -116,12 +116,23 @@ impl messages::ChainWithMessages for Millau { } impl messages::ThisChainWithMessages for Millau { + type Origin = crate::Origin; type Call = crate::Call; - fn is_outbound_lane_enabled(lane: &LaneId) -> bool { - *lane == [0, 0, 0, 0] || - *lane == [0, 0, 0, 1] || - *lane == crate::TokenSwapMessagesLane::get() + fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { + // lanes 0x00000000 && 0x00000001 are accepting any paid messages, while + // `TokenSwapMessageLane` only accepts messages from token swap pallet + let token_swap_dedicated_lane = crate::TokenSwapMessagesLane::get(); + match *lane { + [0, 0, 0, 0] | [0, 0, 0, 1] => send_origin.linked_account().is_some(), + _ if *lane == token_swap_dedicated_lane => matches!( + send_origin.caller, + crate::OriginCaller::BridgeRialtoTokenSwap( + pallet_bridge_token_swap::RawOrigin::TokenSwap { .. } + ) + ), + _ => false, + } } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { @@ -277,6 +288,25 @@ impl SourceHeaderChain for Rialto { } } +impl SenderOrigin for crate::Origin { + fn linked_account(&self) -> Option { + match self.caller { + crate::OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => + Some(submitter.clone()), + crate::OriginCaller::system(frame_system::RawOrigin::Root) | + crate::OriginCaller::system(frame_system::RawOrigin::None) => + crate::RootAccountForPayments::get(), + crate::OriginCaller::BridgeRialtoTokenSwap( + pallet_bridge_token_swap::RawOrigin::TokenSwap { + ref swap_account_at_this_chain, + .. + }, + ) => Some(swap_account_at_this_chain.clone()), + _ => None, + } + } +} + /// Millau -> Rialto message lane pallet parameters. #[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum MillauToRialtoMessagesParameter { diff --git a/bridges/bin/rialto/runtime/src/lib.rs b/bridges/bin/rialto/runtime/src/lib.rs index 05e1a3676627..8dd4c2cc2787 100644 --- a/bridges/bin/rialto/runtime/src/lib.rs +++ b/bridges/bin/rialto/runtime/src/lib.rs @@ -457,10 +457,9 @@ impl pallet_bridge_messages::Config for Runtime { type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, - (), + WithMillauMessagesInstance, pallet_balances::Pallet, GetDeliveryConfirmationTransactionFee, - RootAccountForPayments, >; type OnMessageAccepted = (); type OnDeliveryConfirmed = (); diff --git a/bridges/bin/rialto/runtime/src/millau_messages.rs b/bridges/bin/rialto/runtime/src/millau_messages.rs index 483fa1d56e81..44348383f1d5 100644 --- a/bridges/bin/rialto/runtime/src/millau_messages.rs +++ b/bridges/bin/rialto/runtime/src/millau_messages.rs @@ -19,7 +19,7 @@ use crate::Runtime; use bp_messages::{ - source_chain::TargetHeaderChain, + source_chain::{SenderOrigin, TargetHeaderChain}, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; @@ -116,10 +116,11 @@ impl messages::ChainWithMessages for Rialto { } impl messages::ThisChainWithMessages for Rialto { + type Origin = crate::Origin; type Call = crate::Call; - fn is_outbound_lane_enabled(lane: &LaneId) -> bool { - *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] + fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { + send_origin.linked_account().is_some() && (*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1]) } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { @@ -275,6 +276,19 @@ impl SourceHeaderChain for Millau { } } +impl SenderOrigin for crate::Origin { + fn linked_account(&self) -> Option { + match self.caller { + crate::OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => + Some(submitter.clone()), + crate::OriginCaller::system(frame_system::RawOrigin::Root) | + crate::OriginCaller::system(frame_system::RawOrigin::None) => + crate::RootAccountForPayments::get(), + _ => None, + } + } +} + /// Rialto -> Millau message lane pallet parameters. #[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum RialtoToMillauMessagesParameter { diff --git a/bridges/bin/runtime-common/Cargo.toml b/bridges/bin/runtime-common/Cargo.toml index 0841171757b8..54055e10c5fb 100644 --- a/bridges/bin/runtime-common/Cargo.toml +++ b/bridges/bin/runtime-common/Cargo.toml @@ -26,7 +26,7 @@ pallet-bridge-messages = { path = "../../modules/messages", default-features = f # Substrate dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -45,6 +45,7 @@ std = [ "bp-runtime/std", "codec/std", "frame-support/std", + "frame-system/std", "hash-db/std", "pallet-bridge-dispatch/std", "pallet-bridge-grandpa/std", @@ -60,7 +61,6 @@ std = [ ] runtime-benchmarks = [ "ed25519-dalek/u64_backend", - "frame-system", "pallet-balances", "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", @@ -68,6 +68,5 @@ runtime-benchmarks = [ "sp-version", ] integrity-test = [ - "frame-system", "static_assertions", ] diff --git a/bridges/bin/runtime-common/README.md b/bridges/bin/runtime-common/README.md index 38a47bfdcc9d..5f2298cd787d 100644 --- a/bridges/bin/runtime-common/README.md +++ b/bridges/bin/runtime-common/README.md @@ -62,8 +62,11 @@ corresponding chain. There is single exception, though (it may be changed in the This trait represents this chain from bridge point of view. Let's review every method of this trait: -- `ThisChainWithMessages::is_outbound_lane_enabled`: is used to check whether given lane accepts - outbound messages. +- `ThisChainWithMessages::is_message_accepted`: is used to check whether given lane accepts + messages. The send-message origin is passed to the function, so you may e.g. verify that only + given pallet is able to send messages over selected lane. **IMPORTANT**: if you assume that the + message must be paid by the sender, you must ensure that the sender origin has linked the account + for paying message delivery and dispatch fee. - `ThisChainWithMessages::maximal_pending_messages_at_outbound_lane`: you should return maximal number of pending (undelivered) messages from this function. Returning small values would require diff --git a/bridges/bin/runtime-common/src/messages.rs b/bridges/bin/runtime-common/src/messages.rs index f0e23adec2de..250b68ceffe2 100644 --- a/bridges/bin/runtime-common/src/messages.rs +++ b/bridges/bin/runtime-common/src/messages.rs @@ -22,7 +22,7 @@ use bp_message_dispatch::MessageDispatch as _; use bp_messages::{ - source_chain::{LaneMessageVerifier, Sender}, + source_chain::LaneMessageVerifier, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; @@ -111,11 +111,13 @@ pub struct MessageTransaction { /// This chain that has `pallet-bridge-messages` and `dispatch` modules. pub trait ThisChainWithMessages: ChainWithMessages { + /// Call origin on the chain. + type Origin; /// Call type on the chain. type Call: Encode + Decode; - /// Are we accepting any messages to the given lane? - fn is_outbound_lane_enabled(lane: &LaneId) -> bool; + /// Do we accept message sent by given origin to given lane? + fn is_message_accepted(origin: &Self::Origin, lane: &LaneId) -> bool; /// Maximal number of pending (not yet delivered) messages at This chain. /// @@ -173,6 +175,8 @@ pub type SignatureOf = ::Signature; pub type WeightOf = ::Weight; /// Type of balances that is used on the chain. pub type BalanceOf = ::Balance; +/// Type of origin that is used on the chain. +pub type OriginOf = ::Origin; /// Type of call that is used on this chain. pub type CallOf = ::Call; @@ -270,7 +274,8 @@ pub mod source { pub struct FromThisChainMessageVerifier(PhantomData); /// The error message returned from LaneMessageVerifier when outbound lane is disabled. - pub const OUTBOUND_LANE_DISABLED: &str = "The outbound message lane is disabled."; + pub const MESSAGE_REJECTED_BY_OUTBOUND_LANE: &str = + "The outbound message lane has rejected the message."; /// The error message returned from LaneMessageVerifier when too many pending messages at the /// lane. pub const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane."; @@ -281,26 +286,30 @@ pub mod source { impl LaneMessageVerifier< + OriginOf>, AccountIdOf>, FromThisChainMessagePayload, BalanceOf>, > for FromThisChainMessageVerifier where B: MessageBridge, + // matches requirements from the `frame_system::Config::Origin` + OriginOf>: Clone + + Into>>, OriginOf>>>, AccountIdOf>: PartialEq + Clone, { type Error = &'static str; fn verify_message( - submitter: &Sender>>, + submitter: &OriginOf>, delivery_and_dispatch_fee: &BalanceOf>, lane: &LaneId, lane_outbound_data: &OutboundLaneData, payload: &FromThisChainMessagePayload, ) -> Result<(), Self::Error> { // reject message if lane is blocked - if !ThisChain::::is_outbound_lane_enabled(lane) { - return Err(OUTBOUND_LANE_DISABLED) + if !ThisChain::::is_message_accepted(submitter, lane) { + return Err(MESSAGE_REJECTED_BY_OUTBOUND_LANE) } // reject message if there are too many pending messages at this lane @@ -314,8 +323,23 @@ pub mod source { // Do the dispatch-specific check. We assume that the target chain uses // `Dispatch`, so we verify the message accordingly. - pallet_bridge_dispatch::verify_message_origin(submitter, payload) - .map_err(|_| BAD_ORIGIN)?; + let raw_origin_or_err: Result< + frame_system::RawOrigin>>, + OriginOf>, + > = submitter.clone().into(); + match raw_origin_or_err { + Ok(raw_origin) => + pallet_bridge_dispatch::verify_message_origin(&raw_origin, payload) + .map(drop) + .map_err(|_| BAD_ORIGIN)?, + Err(_) => { + // so what it means that we've failed to convert origin to the + // `frame_system::RawOrigin`? now it means that the custom pallet origin has + // been used to send the message. Do we need to verify it? The answer is no, + // because pallet may craft any origin (e.g. root) && we can't verify whether it + // is valid, or not. + }, + }; let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::( payload, @@ -854,6 +878,18 @@ mod tests { #[codec(index = 84)] Mint, } + #[derive(Clone, Debug)] + struct ThisChainOrigin(Result, ()>); + + impl From + for Result, ThisChainOrigin> + { + fn from( + origin: ThisChainOrigin, + ) -> Result, ThisChainOrigin> { + origin.clone().0.map_err(|_| origin) + } + } #[derive(Debug, PartialEq, Decode, Encode)] struct BridgedChainAccountId(u32); @@ -863,6 +899,18 @@ mod tests { struct BridgedChainSignature(u32); #[derive(Debug, PartialEq, Decode, Encode)] enum BridgedChainCall {} + #[derive(Clone, Debug)] + struct BridgedChainOrigin; + + impl From + for Result, BridgedChainOrigin> + { + fn from( + _origin: BridgedChainOrigin, + ) -> Result, BridgedChainOrigin> { + unreachable!() + } + } macro_rules! impl_wrapped_balance { ($name:ident) => { @@ -940,9 +988,10 @@ mod tests { } impl ThisChainWithMessages for ThisChain { + type Origin = ThisChainOrigin; type Call = ThisChainCall; - fn is_outbound_lane_enabled(lane: &LaneId) -> bool { + fn is_message_accepted(_send_origin: &Self::Origin, lane: &LaneId) -> bool { lane == TEST_LANE_ID } @@ -1000,9 +1049,10 @@ mod tests { } impl ThisChainWithMessages for BridgedChain { + type Origin = BridgedChainOrigin; type Call = BridgedChainCall; - fn is_outbound_lane_enabled(_lane: &LaneId) -> bool { + fn is_message_accepted(_send_origin: &Self::Origin, _lane: &LaneId) -> bool { unreachable!() } @@ -1141,7 +1191,7 @@ mod tests { // and now check that the verifier checks the fee assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1150,7 +1200,7 @@ mod tests { Err(source::TOO_LOW_FEE) ); assert!(source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1173,7 +1223,7 @@ mod tests { // and now check that the verifier checks the fee assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Signed(ThisChainAccountId(0)), + &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(0)))), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1183,7 +1233,7 @@ mod tests { ); assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::None, + &ThisChainOrigin(Ok(frame_system::RawOrigin::None)), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1192,7 +1242,7 @@ mod tests { Err(source::BAD_ORIGIN) ); assert!(source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1215,7 +1265,7 @@ mod tests { // and now check that the verifier checks the fee assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Signed(ThisChainAccountId(0)), + &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(0)))), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1224,7 +1274,7 @@ mod tests { Err(source::BAD_ORIGIN) ); assert!(source::FromThisChainMessageVerifier::::verify_message( - &Sender::Signed(ThisChainAccountId(1)), + &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(1)))), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1237,13 +1287,13 @@ mod tests { fn message_is_rejected_when_sent_using_disabled_lane() { assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1_000_000), b"dsbl", &test_lane_outbound_data(), ®ular_outbound_message_payload(), ), - Err(source::OUTBOUND_LANE_DISABLED) + Err(source::MESSAGE_REJECTED_BY_OUTBOUND_LANE) ); } @@ -1251,7 +1301,7 @@ mod tests { fn message_is_rejected_when_there_are_too_many_pending_messages_at_outbound_lane() { assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1_000_000), TEST_LANE_ID, &OutboundLaneData { diff --git a/bridges/modules/messages/src/instant_payments.rs b/bridges/modules/messages/src/instant_payments.rs index d67b82ade8d2..2a620a952225 100644 --- a/bridges/modules/messages/src/instant_payments.rs +++ b/bridges/modules/messages/src/instant_payments.rs @@ -22,7 +22,7 @@ use crate::OutboundMessages; use bp_messages::{ - source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards, Sender}, + source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards, SenderOrigin}, LaneId, MessageKey, MessageNonce, UnrewardedRelayer, }; use codec::Encode; @@ -31,6 +31,10 @@ use num_traits::{SaturatingAdd, Zero}; use sp_runtime::traits::Saturating; use sp_std::{collections::vec_deque::VecDeque, fmt::Debug, ops::RangeInclusive}; +/// Error that occurs when message fee is non-zero, but payer is not defined. +const NON_ZERO_MESSAGE_FEE_CANT_BE_PAID_BY_NONE: &str = + "Non-zero message fee can't be paid by "; + /// Instant message payments made in given currency. /// /// The balance is initially reserved in a special `relayers-fund` account, and transferred @@ -44,42 +48,50 @@ use sp_std::{collections::vec_deque::VecDeque, fmt::Debug, ops::RangeInclusive}; /// to the relayer account. /// NOTE It's within relayer's interest to keep their balance above ED as well, to make sure they /// can receive the payment. -pub struct InstantCurrencyPayments { - _phantom: sp_std::marker::PhantomData<(T, I, Currency, GetConfirmationFee, RootAccount)>, +pub struct InstantCurrencyPayments { + _phantom: sp_std::marker::PhantomData<(T, I, Currency, GetConfirmationFee)>, } -impl - MessageDeliveryAndDispatchPayment - for InstantCurrencyPayments +impl + MessageDeliveryAndDispatchPayment + for InstantCurrencyPayments where T: frame_system::Config + crate::Config, I: 'static, + T::Origin: SenderOrigin, Currency: CurrencyT, Currency::Balance: From, GetConfirmationFee: Get, - RootAccount: Get>, { type Error = &'static str; fn pay_delivery_and_dispatch_fee( - submitter: &Sender, + submitter: &T::Origin, fee: &Currency::Balance, relayer_fund_account: &T::AccountId, ) -> Result<(), Self::Error> { + let submitter_account = match submitter.linked_account() { + Some(submitter_account) => submitter_account, + None if !fee.is_zero() => { + // if we'll accept some message that has declared that the `fee` has been paid but + // it isn't actually paid, then it'll lead to problems with delivery confirmation + // payments (see `pay_relayer_rewards` && `confirmation_relayer` in particular) + return Err(NON_ZERO_MESSAGE_FEE_CANT_BE_PAID_BY_NONE) + }, + None => { + // message lane verifier has accepted the message before, so this message + // is unpaid **by design** + // => let's just do nothing + return Ok(()) + }, + }; + if !frame_system::Pallet::::account_exists(relayer_fund_account) { return Err("The relayer fund account must exist for the message lanes pallet to work correctly."); } - let root_account = RootAccount::get(); - let account = match submitter { - Sender::Signed(submitter) => submitter, - Sender::Root | Sender::None => root_account - .as_ref() - .ok_or("Sending messages using Root or None origin is disallowed.")?, - }; - Currency::transfer( - account, + &submitter_account, relayer_fund_account, *fee, // it's fine for the submitter to go below Existential Deposit and die. @@ -226,7 +238,9 @@ fn pay_relayer_reward( #[cfg(test)] mod tests { use super::*; - use crate::mock::{run_test, AccountId as TestAccountId, Balance as TestBalance, TestRuntime}; + use crate::mock::{ + run_test, AccountId as TestAccountId, Balance as TestBalance, Origin, TestRuntime, + }; use bp_messages::source_chain::RelayerRewards; type Balances = pallet_balances::Pallet; @@ -245,6 +259,48 @@ mod tests { .collect() } + #[test] + fn pay_delivery_and_dispatch_fee_fails_on_non_zero_fee_and_unknown_payer() { + frame_support::parameter_types! { + const GetConfirmationFee: TestBalance = 0; + }; + + run_test(|| { + let result = InstantCurrencyPayments::< + TestRuntime, + (), + Balances, + GetConfirmationFee, + >::pay_delivery_and_dispatch_fee( + &Origin::root(), + &100, + &RELAYERS_FUND_ACCOUNT, + ); + assert_eq!(result, Err(NON_ZERO_MESSAGE_FEE_CANT_BE_PAID_BY_NONE)); + }); + } + + #[test] + fn pay_delivery_and_dispatch_succeeds_on_zero_fee_and_unknown_payer() { + frame_support::parameter_types! { + const GetConfirmationFee: TestBalance = 0; + }; + + run_test(|| { + let result = InstantCurrencyPayments::< + TestRuntime, + (), + Balances, + GetConfirmationFee, + >::pay_delivery_and_dispatch_fee( + &Origin::root(), + &0, + &RELAYERS_FUND_ACCOUNT, + ); + assert!(result.is_ok()); + }); + } + #[test] fn confirmation_relayer_is_rewarded_if_it_has_also_delivered_messages() { run_test(|| { diff --git a/bridges/modules/messages/src/lib.rs b/bridges/modules/messages/src/lib.rs index f92aa3876f6b..a344cedae241 100644 --- a/bridges/modules/messages/src/lib.rs +++ b/bridges/modules/messages/src/lib.rs @@ -170,12 +170,14 @@ pub mod pallet { type TargetHeaderChain: TargetHeaderChain; /// Message payload verifier. type LaneMessageVerifier: LaneMessageVerifier< + Self::Origin, Self::AccountId, Self::OutboundPayload, Self::OutboundMessageFee, >; /// Message delivery payment. type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment< + Self::Origin, Self::AccountId, Self::OutboundMessageFee, >; @@ -276,16 +278,12 @@ pub mod pallet { payload: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, ) -> DispatchResultWithPostInfo { - crate::send_message::( - origin.into().map_err(|_| BadOrigin)?, - lane_id, - payload, - delivery_and_dispatch_fee, + crate::send_message::(origin, lane_id, payload, delivery_and_dispatch_fee).map( + |sent_message| PostDispatchInfo { + actual_weight: Some(sent_message.weight), + pays_fee: Pays::Yes, + }, ) - .map(|sent_message| PostDispatchInfo { - actual_weight: Some(sent_message.weight), - pays_fee: Pays::Yes, - }) } /// Pay additional fee for the message. @@ -313,17 +311,15 @@ pub mod pallet { ); // withdraw additional fee from submitter - let submitter = origin.into().map_err(|_| BadOrigin)?; T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( - &submitter, + &origin, &additional_fee, &relayer_fund_account_id::(), ) .map_err(|err| { log::trace!( target: "runtime::bridge-messages", - "Submitter {:?} can't pay additional fee {:?} for the message {:?}/{:?} to {:?}: {:?}", - submitter, + "Submitter can't pay additional fee {:?} for the message {:?}/{:?} to {:?}: {:?}", additional_fee, lane_id, nonce, @@ -780,6 +776,7 @@ pub fn relayer_fund_account_id bp_messages::source_chain::MessagesBridge< + T::Origin, T::AccountId, T::OutboundMessageFee, T::OutboundPayload, @@ -791,7 +788,7 @@ where type Error = sp_runtime::DispatchErrorWithPostInfo; fn send_message( - sender: bp_messages::source_chain::Sender, + sender: T::Origin, lane: LaneId, message: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, @@ -802,7 +799,7 @@ where /// Function that actually sends message. fn send_message, I: 'static>( - submitter: bp_messages::source_chain::Sender, + submitter: T::Origin, lane_id: LaneId, payload: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, @@ -856,9 +853,8 @@ fn send_message, I: 'static>( .map_err(|err| { log::trace!( target: "runtime::bridge-messages", - "Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}", + "Message to lane {:?} is rejected because submitter is unable to pay fee {:?}: {:?}", lane_id, - submitter, delivery_and_dispatch_fee, err, ); diff --git a/bridges/modules/messages/src/mock.rs b/bridges/modules/messages/src/mock.rs index ef5081472279..2669ddfbef26 100644 --- a/bridges/modules/messages/src/mock.rs +++ b/bridges/modules/messages/src/mock.rs @@ -23,7 +23,7 @@ use bitvec::prelude::*; use bp_messages::{ source_chain::{ LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, - OnMessageAccepted, Sender, TargetHeaderChain, + OnMessageAccepted, SenderOrigin, TargetHeaderChain, }, target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, @@ -194,6 +194,16 @@ impl Config for TestRuntime { type BridgedChainId = TestBridgedChainId; } +impl SenderOrigin for Origin { + fn linked_account(&self) -> Option { + match self.caller { + OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => + Some(submitter.clone()), + _ => None, + } + } +} + impl Size for TestPayload { fn size_hint(&self) -> u32 { 16 + self.extra.len() as u32 @@ -294,11 +304,13 @@ impl TargetHeaderChain for TestTargetHeaderChain { #[derive(Debug, Default)] pub struct TestLaneMessageVerifier; -impl LaneMessageVerifier for TestLaneMessageVerifier { +impl LaneMessageVerifier + for TestLaneMessageVerifier +{ type Error = &'static str; fn verify_message( - _submitter: &Sender, + _submitter: &Origin, delivery_and_dispatch_fee: &TestMessageFee, _lane: &LaneId, _lane_outbound_data: &OutboundLaneData, @@ -324,8 +336,8 @@ impl TestMessageDeliveryAndDispatchPayment { /// Returns true if given fee has been paid by given submitter. pub fn is_fee_paid(submitter: AccountId, fee: TestMessageFee) -> bool { - frame_support::storage::unhashed::get(b":message-fee:") == - Some((Sender::Signed(submitter), fee)) + let raw_origin: Result, _> = Origin::signed(submitter).into(); + frame_support::storage::unhashed::get(b":message-fee:") == Some((raw_origin.unwrap(), fee)) } /// Returns true if given relayer has been rewarded with given balance. The reward-paid flag is @@ -336,13 +348,13 @@ impl TestMessageDeliveryAndDispatchPayment { } } -impl MessageDeliveryAndDispatchPayment +impl MessageDeliveryAndDispatchPayment for TestMessageDeliveryAndDispatchPayment { type Error = &'static str; fn pay_delivery_and_dispatch_fee( - submitter: &Sender, + submitter: &Origin, fee: &TestMessageFee, _relayer_fund_account: &AccountId, ) -> Result<(), Self::Error> { @@ -350,7 +362,8 @@ impl MessageDeliveryAndDispatchPayment return Err(TEST_ERROR) } - frame_support::storage::unhashed::put(b":message-fee:", &(submitter, fee)); + let raw_origin: Result, _> = submitter.clone().into(); + frame_support::storage::unhashed::put(b":message-fee:", &(raw_origin.unwrap(), fee)); Ok(()) } diff --git a/bridges/modules/token-swap/src/benchmarking.rs b/bridges/modules/token-swap/src/benchmarking.rs index c68fb6b64283..878cb20993a9 100644 --- a/bridges/modules/token-swap/src/benchmarking.rs +++ b/bridges/modules/token-swap/src/benchmarking.rs @@ -18,7 +18,7 @@ use crate::{ swap_account_id, target_account_at_this_chain, BridgedAccountIdOf, BridgedAccountPublicOf, - BridgedAccountSignatureOf, BridgedBalanceOf, Call, Pallet, ThisChainBalance, + BridgedAccountSignatureOf, BridgedBalanceOf, Call, Origin, Pallet, ThisChainBalance, TokenSwapCreationOf, TokenSwapOf, }; @@ -43,6 +43,7 @@ pub trait Config: crate::Config { benchmarks_instance_pallet! { where_clause { where + Origin: Into, BridgedAccountPublicOf: Decode + Parameter, BridgedAccountSignatureOf: Decode, } diff --git a/bridges/modules/token-swap/src/lib.rs b/bridges/modules/token-swap/src/lib.rs index 32fd2db3c7cb..e46a4bc2dd03 100644 --- a/bridges/modules/token-swap/src/lib.rs +++ b/bridges/modules/token-swap/src/lib.rs @@ -70,16 +70,18 @@ use bp_runtime::{messages::DispatchFeePayment, ChainId}; use bp_token_swap::{ RawBridgedTransferCall, TokenSwap, TokenSwapCreation, TokenSwapState, TokenSwapType, }; -use codec::Encode; +use codec::{Decode, Encode}; use frame_support::{ fail, traits::{Currency, ExistenceRequirement}, weights::PostDispatchInfo, + RuntimeDebug, }; +use scale_info::TypeInfo; use sp_core::H256; use sp_io::hashing::blake2_256; use sp_runtime::traits::{Convert, Saturating}; -use sp_std::boxed::Box; +use sp_std::{boxed::Box, marker::PhantomData}; use weights::WeightInfo; pub use weights_ext::WeightInfoExt; @@ -95,6 +97,24 @@ pub mod weights_ext; pub use pallet::*; +/// Name of the `PendingSwaps` storage map. +pub const PENDING_SWAPS_MAP_NAME: &str = "PendingSwaps"; + +/// Origin for the token swap pallet. +#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo)] +pub enum RawOrigin { + /// The call is originated by the token swap account. + TokenSwap { + /// Id of the account that has started the swap. + source_account_at_this_chain: AccountId, + /// Id of the account that holds the funds during this swap. The message fee is paid from + /// this account funds. + swap_account_at_this_chain: AccountId, + }, + /// Dummy to manage the fact we have instancing. + _Phantom(PhantomData), +} + // comes from #[pallet::event] #[allow(clippy::unused_unit)] #[frame_support::pallet] @@ -123,6 +143,7 @@ pub mod pallet { type OutboundMessageLaneId: Get; /// Messages bridge with Bridged chain. type MessagesBridge: MessagesBridge< + Self::Origin, Self::AccountId, >::Balance, MessagePayloadOf, @@ -189,6 +210,7 @@ pub mod pallet { impl, I: 'static> Pallet where BridgedAccountPublicOf: Parameter, + Origin: Into, { /// Start token swap procedure. /// @@ -310,7 +332,11 @@ pub mod pallet { // `Currency::transfer` call on the bridged chain, but no checks are made - it is // the transaction submitter to ensure it is valid. let send_message_result = T::MessagesBridge::send_message( - bp_messages::source_chain::Sender::from(Some(swap_account.clone())), + RawOrigin::TokenSwap { + source_account_at_this_chain: swap.source_account_at_this_chain.clone(), + swap_account_at_this_chain: swap_account.clone(), + } + .into(), T::OutboundMessageLaneId::get(), bp_message_dispatch::MessagePayload { spec_version: bridged_chain_spec_version, @@ -513,6 +539,10 @@ pub mod pallet { InvalidClaimant, } + /// Origin for the token swap pallet. + #[pallet::origin] + pub type Origin = RawOrigin<::AccountId, I>; + /// Pending token swaps states. #[pallet::storage] pub type PendingSwaps, I: 'static = ()> = @@ -685,7 +715,7 @@ mod tests { fn start_test_swap() { assert_ok!(Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(TokenSwapCreation { target_public_at_bridged_chain: bridged_chain_account_public(), @@ -710,7 +740,7 @@ mod tests { run_test(|| { assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT + 1), + mock::Origin::signed(THIS_CHAIN_ACCOUNT + 1), test_swap(), Box::new(test_swap_creation()), ), @@ -726,7 +756,7 @@ mod tests { swap.source_balance_at_this_chain = ExistentialDeposit::get() - 1; assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), swap, Box::new(test_swap_creation()), ), @@ -742,7 +772,7 @@ mod tests { swap.source_balance_at_this_chain = THIS_CHAIN_ACCOUNT_BALANCE + 1; assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), swap, Box::new(test_swap_creation()), ), @@ -760,7 +790,7 @@ mod tests { swap_creation.bridged_currency_transfer = transfer; assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(swap_creation), ), @@ -773,14 +803,14 @@ mod tests { fn create_swap_fails_if_swap_is_active() { run_test(|| { assert_ok!(Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), )); assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), ), @@ -795,7 +825,7 @@ mod tests { frame_system::Pallet::::set_block_number(CAN_START_BLOCK_NUMBER + 1); assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), ), @@ -809,7 +839,7 @@ mod tests { run_test(|| { frame_system::Pallet::::set_block_number(CAN_START_BLOCK_NUMBER); assert_ok!(Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), )); @@ -823,7 +853,7 @@ mod tests { frame_system::Pallet::::reset_events(); assert_ok!(Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), )); @@ -855,7 +885,7 @@ mod tests { run_test(|| { assert_noop!( Pallet::::claim_swap( - Origin::signed( + mock::Origin::signed( 1 + target_account_at_this_chain::(&test_swap()) ), test_swap(), @@ -872,7 +902,9 @@ mod tests { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::SwapIsPending @@ -887,7 +919,9 @@ mod tests { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::SwapIsFailed @@ -900,7 +934,9 @@ mod tests { run_test(|| { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::SwapIsInactive @@ -916,7 +952,9 @@ mod tests { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::FailedToTransferFromSwapAccount @@ -934,7 +972,9 @@ mod tests { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::SwapIsTemporaryLocked @@ -952,7 +992,7 @@ mod tests { frame_system::Pallet::::reset_events(); assert_ok!(Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::(&test_swap())), test_swap(), )); @@ -988,7 +1028,7 @@ mod tests { assert_noop!( Pallet::::cancel_swap( - Origin::signed(THIS_CHAIN_ACCOUNT + 1), + mock::Origin::signed(THIS_CHAIN_ACCOUNT + 1), test_swap() ), Error::::MismatchedSwapSourceOrigin @@ -1002,7 +1042,10 @@ mod tests { start_test_swap(); assert_noop!( - Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Pallet::::cancel_swap( + mock::Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap() + ), Error::::SwapIsPending ); }); @@ -1015,7 +1058,10 @@ mod tests { receive_test_swap_confirmation(true); assert_noop!( - Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Pallet::::cancel_swap( + mock::Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap() + ), Error::::SwapIsConfirmed ); }); @@ -1025,7 +1071,10 @@ mod tests { fn cancel_swap_fails_if_swap_is_inactive() { run_test(|| { assert_noop!( - Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Pallet::::cancel_swap( + mock::Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap() + ), Error::::SwapIsInactive ); }); @@ -1042,7 +1091,10 @@ mod tests { ); assert_noop!( - Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Pallet::::cancel_swap( + mock::Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap() + ), Error::::FailedToTransferFromSwapAccount ); }); @@ -1058,7 +1110,7 @@ mod tests { frame_system::Pallet::::reset_events(); assert_ok!(Pallet::::cancel_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap() )); diff --git a/bridges/modules/token-swap/src/mock.rs b/bridges/modules/token-swap/src/mock.rs index 78b8a3381d3a..ece7b16acc91 100644 --- a/bridges/modules/token-swap/src/mock.rs +++ b/bridges/modules/token-swap/src/mock.rs @@ -56,7 +56,7 @@ frame_support::construct_runtime! { { System: frame_system::{Pallet, Call, Config, Storage, Event}, Balances: pallet_balances::{Pallet, Call, Event}, - TokenSwap: pallet_bridge_token_swap::{Pallet, Call, Event}, + TokenSwap: pallet_bridge_token_swap::{Pallet, Call, Event, Origin}, } } @@ -154,18 +154,23 @@ impl bp_runtime::Chain for BridgedChain { pub struct TestMessagesBridge; -impl MessagesBridge> for TestMessagesBridge { +impl MessagesBridge> + for TestMessagesBridge +{ type Error = (); fn send_message( - sender: frame_system::RawOrigin, + sender: Origin, lane: LaneId, message: MessagePayloadOf, delivery_and_dispatch_fee: Balance, ) -> Result { - assert_ne!(sender, frame_system::RawOrigin::Signed(THIS_CHAIN_ACCOUNT)); assert_eq!(lane, OutboundMessageLaneId::get()); assert_eq!(delivery_and_dispatch_fee, SWAP_DELIVERY_AND_DISPATCH_FEE); + match sender.caller { + OriginCaller::TokenSwap(_) => (), + _ => panic!("unexpected origin"), + } match message.call[0] { OK_TRANSFER_CALL => Ok(SendMessageArtifacts { nonce: MESSAGE_NONCE, weight: 0 }), BAD_TRANSFER_CALL => Err(()), diff --git a/bridges/primitives/messages/Cargo.toml b/bridges/primitives/messages/Cargo.toml index 6c52035cac6b..2142ad028173 100644 --- a/bridges/primitives/messages/Cargo.toml +++ b/bridges/primitives/messages/Cargo.toml @@ -31,6 +31,7 @@ hex-literal = "0.3" [features] default = ["std"] std = [ + "bitvec/std", "bp-runtime/std", "codec/std", "frame-support/std", diff --git a/bridges/primitives/messages/src/source_chain.rs b/bridges/primitives/messages/src/source_chain.rs index 1ff05abf131e..fa7b3bb85ed0 100644 --- a/bridges/primitives/messages/src/source_chain.rs +++ b/bridges/primitives/messages/src/source_chain.rs @@ -28,7 +28,21 @@ use sp_std::{ }; /// The sender of the message on the source chain. -pub type Sender = frame_system::RawOrigin; +pub trait SenderOrigin { + /// Return id of the account that is sending this message. + /// + /// In regular messages configuration, when regular message is sent you'll always get `Some(_)` + /// from this call. This is the account that is paying send costs. However, there are some + /// examples when `None` may be returned from the call: + /// + /// - if the send-message call origin is either `frame_system::RawOrigin::Root` or + /// `frame_system::RawOrigin::None` and your configuration forbids such messages; + /// - if your configuration allows 'unpaid' messages sent by pallets. Then the pallet may just + /// use its own defined origin (not linked to any account) and the message will be accepted. + /// This may be useful for pallets that are sending important system-wide information (like + /// update of runtime version). + fn linked_account(&self) -> Option; +} /// Relayers rewards, grouped by relayer account id. pub type RelayersRewards = BTreeMap>; @@ -82,14 +96,14 @@ pub trait TargetHeaderChain { /// Lane3 until some block, ...), then it may be built using this verifier. /// /// Any fee requirements should also be enforced here. -pub trait LaneMessageVerifier { +pub trait LaneMessageVerifier { /// Error type. type Error: Debug + Into<&'static str>; /// Verify message payload and return Ok(()) if message is valid and allowed to be sent over the /// lane. fn verify_message( - submitter: &Sender, + submitter: &SenderOrigin, delivery_and_dispatch_fee: &Fee, lane: &LaneId, outbound_data: &OutboundLaneData, @@ -110,14 +124,14 @@ pub trait LaneMessageVerifier { /// So to be sure that any non-altruist relayer would agree to deliver message, submitter /// should set `delivery_and_dispatch_fee` to at least (equivalent of): sum of fees from (2) /// to (4) above, plus some interest for the relayer. -pub trait MessageDeliveryAndDispatchPayment { +pub trait MessageDeliveryAndDispatchPayment { /// Error type. type Error: Debug + Into<&'static str>; /// Withhold/write-off delivery_and_dispatch_fee from submitter account to /// some relayers-fund account. fn pay_delivery_and_dispatch_fee( - submitter: &Sender, + submitter: &SenderOrigin, fee: &Balance, relayer_fund_account: &AccountId, ) -> Result<(), Self::Error>; @@ -145,7 +159,7 @@ pub struct SendMessageArtifacts { } /// Messages bridge API to be used from other pallets. -pub trait MessagesBridge { +pub trait MessagesBridge { /// Error type. type Error: Debug; @@ -153,7 +167,7 @@ pub trait MessagesBridge { /// /// Returns unique message nonce or error if send has failed. fn send_message( - sender: Sender, + sender: SenderOrigin, lane: LaneId, message: Payload, delivery_and_dispatch_fee: Balance, @@ -164,13 +178,13 @@ pub trait MessagesBridge { #[derive(RuntimeDebug, PartialEq)] pub struct NoopMessagesBridge; -impl MessagesBridge - for NoopMessagesBridge +impl + MessagesBridge for NoopMessagesBridge { type Error = &'static str; fn send_message( - _sender: Sender, + _sender: SenderOrigin, _lane: LaneId, _message: Payload, _delivery_and_dispatch_fee: Balance, @@ -245,13 +259,13 @@ impl TargetHeaderChain for ForbidOutboun } } -impl LaneMessageVerifier - for ForbidOutboundMessages +impl + LaneMessageVerifier for ForbidOutboundMessages { type Error = &'static str; fn verify_message( - _submitter: &Sender, + _submitter: &SenderOrigin, _delivery_and_dispatch_fee: &Fee, _lane: &LaneId, _outbound_data: &OutboundLaneData, @@ -261,13 +275,13 @@ impl LaneMessageVerifier } } -impl MessageDeliveryAndDispatchPayment - for ForbidOutboundMessages +impl + MessageDeliveryAndDispatchPayment for ForbidOutboundMessages { type Error = &'static str; fn pay_delivery_and_dispatch_fee( - _submitter: &Sender, + _submitter: &SenderOrigin, _fee: &Balance, _relayer_fund_account: &AccountId, ) -> Result<(), Self::Error> {