From aeeb53343e295303930c65e6df9add2ae21b3918 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky <svyatonik@gmail.com> Date: Tue, 6 Dec 2022 16:09:21 +0300 Subject: [PATCH] DeliveryConfirmationPayments trait for paying relayer rewards at the source chain (#1653) * DeliveryConfirmationPayments * ref proper PR in TODO --- bridges/bin/millau/runtime/src/lib.rs | 10 ++-- .../bin/rialto-parachain/runtime/src/lib.rs | 5 +- bridges/bin/rialto/runtime/src/lib.rs | 5 +- bridges/modules/messages/src/lib.rs | 36 ++---------- bridges/modules/messages/src/mock.rs | 6 +- bridges/modules/relayers/Cargo.toml | 2 - bridges/modules/relayers/src/lib.rs | 2 +- bridges/modules/relayers/src/mock.rs | 33 +---------- .../modules/relayers/src/payment_adapter.rs | 55 ++++++++++++++----- bridges/primitives/messages/src/lib.rs | 26 ++++++++- .../primitives/messages/src/source_chain.rs | 31 +++++++++++ 11 files changed, 118 insertions(+), 93 deletions(-) diff --git a/bridges/bin/millau/runtime/src/lib.rs b/bridges/bin/millau/runtime/src/lib.rs index 2e20afb6457..2bc26002b84 100644 --- a/bridges/bin/millau/runtime/src/lib.rs +++ b/bridges/bin/millau/runtime/src/lib.rs @@ -475,9 +475,10 @@ impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime { type TargetHeaderChain = crate::rialto_messages::Rialto; type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; type MessageDeliveryAndDispatchPayment = - pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< + pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, - WithRialtoMessagesInstance, + frame_support::traits::ConstU64<100_000>, + frame_support::traits::ConstU64<100_000>, >; type SourceHeaderChain = crate::rialto_messages::Rialto; @@ -505,9 +506,10 @@ impl pallet_bridge_messages::Config<WithRialtoParachainMessagesInstance> for Run type TargetHeaderChain = crate::rialto_parachain_messages::RialtoParachain; type LaneMessageVerifier = crate::rialto_parachain_messages::ToRialtoParachainMessageVerifier; type MessageDeliveryAndDispatchPayment = - pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< + pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, - WithRialtoParachainMessagesInstance, + frame_support::traits::ConstU64<100_000>, + frame_support::traits::ConstU64<100_000>, >; type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachain; diff --git a/bridges/bin/rialto-parachain/runtime/src/lib.rs b/bridges/bin/rialto-parachain/runtime/src/lib.rs index 3d19dd4e75d..fd667af738a 100644 --- a/bridges/bin/rialto-parachain/runtime/src/lib.rs +++ b/bridges/bin/rialto-parachain/runtime/src/lib.rs @@ -570,9 +570,10 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime { type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type MessageDeliveryAndDispatchPayment = - pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< + pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, - WithMillauMessagesInstance, + frame_support::traits::ConstU64<100_000>, + frame_support::traits::ConstU64<100_000>, >; type SourceHeaderChain = crate::millau_messages::Millau; diff --git a/bridges/bin/rialto/runtime/src/lib.rs b/bridges/bin/rialto/runtime/src/lib.rs index 0b91faf2eaa..93e2ad92c18 100644 --- a/bridges/bin/rialto/runtime/src/lib.rs +++ b/bridges/bin/rialto/runtime/src/lib.rs @@ -457,9 +457,10 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime { type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type MessageDeliveryAndDispatchPayment = - pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< + pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, - WithMillauMessagesInstance, + frame_support::traits::ConstU64<100_000>, + frame_support::traits::ConstU64<100_000>, >; type SourceHeaderChain = crate::millau_messages::Millau; diff --git a/bridges/modules/messages/src/lib.rs b/bridges/modules/messages/src/lib.rs index d19b17e0ddf..33e250574ba 100644 --- a/bridges/modules/messages/src/lib.rs +++ b/bridges/modules/messages/src/lib.rs @@ -52,24 +52,21 @@ use crate::{ use bp_messages::{ source_chain::{ - LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, - SendMessageArtifacts, TargetHeaderChain, + LaneMessageVerifier, MessageDeliveryAndDispatchPayment, SendMessageArtifacts, + TargetHeaderChain, }, target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, total_unrewarded_messages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId, MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData, - OutboundMessageDetails, UnrewardedRelayer, UnrewardedRelayersState, + OutboundMessageDetails, UnrewardedRelayersState, }; use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get}; use sp_runtime::traits::UniqueSaturatedFrom; -use sp_std::{ - cell::RefCell, collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive, - prelude::*, -}; +use sp_std::{cell::RefCell, marker::PhantomData, prelude::*}; mod inbound_lane; mod outbound_lane; @@ -725,31 +722,6 @@ fn send_message<T: Config<I>, I: 'static>( Ok(SendMessageArtifacts { nonce, weight: actual_weight }) } -/// Calculate the number of messages that the relayers have delivered. -pub fn calc_relayers_rewards<T, I>( - messages_relayers: VecDeque<UnrewardedRelayer<T::AccountId>>, - received_range: &RangeInclusive<MessageNonce>, -) -> RelayersRewards<T::AccountId> -where - T: frame_system::Config + crate::Config<I>, - I: 'static, -{ - // remember to reward relayers that have delivered messages - // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain - let mut relayers_rewards = RelayersRewards::new(); - for entry in messages_relayers { - let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start()); - let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); - - // loop won't proceed if current entry is ahead of received range (begin > end). - // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain - if nonce_end >= nonce_begin { - *relayers_rewards.entry(entry.relayer).or_default() += nonce_end - nonce_begin + 1; - } - } - relayers_rewards -} - /// Ensure that the pallet is in normal operational mode. fn ensure_normal_operating_mode<T: Config<I>, I: 'static>() -> Result<(), Error<T, I>> { if PalletOperatingMode::<T, I>::get() == diff --git a/bridges/modules/messages/src/mock.rs b/bridges/modules/messages/src/mock.rs index 59f72602c84..599d3a6b379 100644 --- a/bridges/modules/messages/src/mock.rs +++ b/bridges/modules/messages/src/mock.rs @@ -17,9 +17,10 @@ // From construct_runtime macro #![allow(clippy::from_over_into)] -use crate::{calc_relayers_rewards, Config}; +use crate::Config; use bp_messages::{ + calc_relayers_rewards, source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, target_chain::{ DispatchMessage, DispatchMessageData, MessageDispatch, ProvedLaneMessages, ProvedMessages, @@ -311,8 +312,7 @@ impl MessageDeliveryAndDispatchPayment<RuntimeOrigin, AccountId> _confirmation_relayer: &AccountId, received_range: &RangeInclusive<MessageNonce>, ) { - let relayers_rewards = - calc_relayers_rewards::<TestRuntime, ()>(message_relayers, received_range); + let relayers_rewards = calc_relayers_rewards(message_relayers, received_range); for (relayer, reward) in &relayers_rewards { let key = (b":relayer-reward:", relayer, reward).encode(); frame_support::storage::unhashed::put(&key, &true); diff --git a/bridges/modules/relayers/Cargo.toml b/bridges/modules/relayers/Cargo.toml index 00d1bb59120..27e7424a97c 100644 --- a/bridges/modules/relayers/Cargo.toml +++ b/bridges/modules/relayers/Cargo.toml @@ -15,7 +15,6 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive" bp-messages = { path = "../../primitives/messages", default-features = false } bp-relayers = { path = "../../primitives/relayers", default-features = false } -pallet-bridge-messages = { path = "../messages", default-features = false } # Substrate Dependencies @@ -41,7 +40,6 @@ std = [ "frame-support/std", "frame-system/std", "log/std", - "pallet-bridge-messages/std", "scale-info/std", "sp-arithmetic/std", "sp-std/std", diff --git a/bridges/modules/relayers/src/lib.rs b/bridges/modules/relayers/src/lib.rs index 0c6454f714a..74676537109 100644 --- a/bridges/modules/relayers/src/lib.rs +++ b/bridges/modules/relayers/src/lib.rs @@ -28,7 +28,7 @@ use sp_std::marker::PhantomData; use weights::WeightInfo; pub use pallet::*; -pub use payment_adapter::MessageDeliveryAndDispatchPaymentAdapter; +pub use payment_adapter::DeliveryConfirmationPaymentsAdapter; pub mod benchmarking; diff --git a/bridges/modules/relayers/src/mock.rs b/bridges/modules/relayers/src/mock.rs index 55db2d575e7..4880e908039 100644 --- a/bridges/modules/relayers/src/mock.rs +++ b/bridges/modules/relayers/src/mock.rs @@ -18,9 +18,7 @@ use crate as pallet_bridge_relayers; -use bp_messages::{ - source_chain::ForbidOutboundMessages, target_chain::ForbidInboundMessages, LaneId, -}; +use bp_messages::LaneId; use bp_relayers::PaymentProcedure; use frame_support::{parameter_types, weights::RuntimeDbWeight}; use sp_core::H256; @@ -43,7 +41,6 @@ frame_support::construct_runtime! { { System: frame_system::{Pallet, Call, Config, Storage, Event<T>}, Balances: pallet_balances::{Pallet, Event<T>}, - Messages: pallet_bridge_messages::{Pallet, Event<T>}, Relayers: pallet_bridge_relayers::{Pallet, Call, Event<T>}, } } @@ -91,34 +88,6 @@ impl pallet_balances::Config for TestRuntime { type ReserveIdentifier = (); } -parameter_types! { - pub const TestBridgedChainId: bp_runtime::ChainId = *b"test"; - pub ActiveOutboundLanes: &'static [bp_messages::LaneId] = &[[0, 0, 0, 0]]; -} - -// we're not testing messages pallet here, so values in this config might be crazy -impl pallet_bridge_messages::Config for TestRuntime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); - type ActiveOutboundLanes = ActiveOutboundLanes; - type MaxUnrewardedRelayerEntriesAtInboundLane = frame_support::traits::ConstU64<8>; - type MaxUnconfirmedMessagesAtInboundLane = frame_support::traits::ConstU64<8>; - - type MaximalOutboundPayloadSize = frame_support::traits::ConstU32<1024>; - type OutboundPayload = (); - - type InboundPayload = (); - type InboundRelayer = AccountId; - - type TargetHeaderChain = ForbidOutboundMessages; - type LaneMessageVerifier = ForbidOutboundMessages; - type MessageDeliveryAndDispatchPayment = (); - - type SourceHeaderChain = ForbidInboundMessages; - type MessageDispatch = ForbidInboundMessages; - type BridgedChainId = TestBridgedChainId; -} - impl pallet_bridge_relayers::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; diff --git a/bridges/modules/relayers/src/payment_adapter.rs b/bridges/modules/relayers/src/payment_adapter.rs index 4939d274c60..750f3397e74 100644 --- a/bridges/modules/relayers/src/payment_adapter.rs +++ b/bridges/modules/relayers/src/payment_adapter.rs @@ -19,22 +19,25 @@ use crate::{Config, Pallet}; -use bp_messages::source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards}; -use frame_support::sp_runtime::SaturatedConversion; +use bp_messages::source_chain::{ + DeliveryConfirmationPayments, MessageDeliveryAndDispatchPayment, RelayersRewards, +}; +use frame_support::{sp_runtime::SaturatedConversion, traits::Get}; use sp_arithmetic::traits::{Saturating, UniqueSaturatedFrom, Zero}; use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive}; /// Adapter that allows relayers pallet to be used as a delivery+dispatch payment mechanism /// for the messages pallet. -pub struct MessageDeliveryAndDispatchPaymentAdapter<T, MessagesInstance>( - PhantomData<(T, MessagesInstance)>, +pub struct DeliveryConfirmationPaymentsAdapter<T, DeliveryReward, ConfirmationReward>( + PhantomData<(T, DeliveryReward, ConfirmationReward)>, ); -impl<T, MessagesInstance> MessageDeliveryAndDispatchPayment<T::RuntimeOrigin, T::AccountId> - for MessageDeliveryAndDispatchPaymentAdapter<T, MessagesInstance> +// TODO (https://github.com/paritytech/parity-bridges-common/pull/1652): this impl must be removed +impl<T, DeliveryReward, ConfirmationReward> + MessageDeliveryAndDispatchPayment<T::RuntimeOrigin, T::AccountId> + for DeliveryConfirmationPaymentsAdapter<T, DeliveryReward, ConfirmationReward> where - T: Config + pallet_bridge_messages::Config<MessagesInstance>, - MessagesInstance: 'static, + T: Config, { type Error = &'static str; @@ -44,23 +47,47 @@ where confirmation_relayer: &T::AccountId, received_range: &RangeInclusive<bp_messages::MessageNonce>, ) { - let relayers_rewards = pallet_bridge_messages::calc_relayers_rewards::<T, MessagesInstance>( - messages_relayers, - received_range, - ); + let relayers_rewards = + bp_messages::calc_relayers_rewards::<T::AccountId>(messages_relayers, received_range); register_relayers_rewards::<T>( confirmation_relayer, relayers_rewards, lane_id, - // TODO (https://github.com/paritytech/parity-bridges-common/issues/1318): this shall be fixed - // in some way. ATM the future of the `register_relayer_reward` is not yet known 100_000_u32.into(), 10_000_u32.into(), ); } } +impl<T, DeliveryReward, ConfirmationReward> DeliveryConfirmationPayments<T::AccountId> + for DeliveryConfirmationPaymentsAdapter<T, DeliveryReward, ConfirmationReward> +where + T: Config, + DeliveryReward: Get<T::Reward>, + ConfirmationReward: Get<T::Reward>, +{ + type Error = &'static str; + + fn pay_reward( + lane_id: bp_messages::LaneId, + messages_relayers: VecDeque<bp_messages::UnrewardedRelayer<T::AccountId>>, + confirmation_relayer: &T::AccountId, + received_range: &RangeInclusive<bp_messages::MessageNonce>, + ) { + let relayers_rewards = + bp_messages::calc_relayers_rewards::<T::AccountId>(messages_relayers, received_range); + + register_relayers_rewards::<T>( + confirmation_relayer, + relayers_rewards, + lane_id, + DeliveryReward::get(), + ConfirmationReward::get(), + ); + } +} + // Update rewards to given relayers, optionally rewarding confirmation relayer. fn register_relayers_rewards<T: Config>( confirmation_relayer: &T::AccountId, diff --git a/bridges/primitives/messages/src/lib.rs b/bridges/primitives/messages/src/lib.rs index 5e7c2593bff..c288323f941 100644 --- a/bridges/primitives/messages/src/lib.rs +++ b/bridges/primitives/messages/src/lib.rs @@ -25,7 +25,7 @@ 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::*}; +use sp_std::{collections::vec_deque::VecDeque, ops::RangeInclusive, prelude::*}; pub mod source_chain; pub mod storage_keys; @@ -360,6 +360,30 @@ pub fn total_unrewarded_messages<RelayerId>( } } +/// Calculate the number of messages that the relayers have delivered. +pub fn calc_relayers_rewards<AccountId>( + messages_relayers: VecDeque<UnrewardedRelayer<AccountId>>, + received_range: &RangeInclusive<MessageNonce>, +) -> source_chain::RelayersRewards<AccountId> +where + AccountId: sp_std::cmp::Ord, +{ + // remember to reward relayers that have delivered messages + // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain + let mut relayers_rewards = source_chain::RelayersRewards::new(); + for entry in messages_relayers { + let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start()); + let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); + + // loop won't proceed if current entry is ahead of received range (begin > end). + // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain + if nonce_end >= nonce_begin { + *relayers_rewards.entry(entry.relayer).or_default() += nonce_end - nonce_begin + 1; + } + } + relayers_rewards +} + #[cfg(test)] mod tests { use super::*; diff --git a/bridges/primitives/messages/src/source_chain.rs b/bridges/primitives/messages/src/source_chain.rs index 1cac449ee63..337fd052517 100644 --- a/bridges/primitives/messages/src/source_chain.rs +++ b/bridges/primitives/messages/src/source_chain.rs @@ -125,6 +125,37 @@ impl<SenderOrigin, AccountId> MessageDeliveryAndDispatchPayment<SenderOrigin, Ac } } +/// Manages payments that are happening at the source chain during delivery confirmation +/// transaction. +pub trait DeliveryConfirmationPayments<AccountId> { + /// Error type. + type Error: Debug + Into<&'static str>; + + /// Pay rewards for delivering messages to the given relayers. + /// + /// The implementation may also choose to pay reward to the `confirmation_relayer`, which is + /// a relayer that has submitted delivery confirmation transaction. + fn pay_reward( + lane_id: LaneId, + messages_relayers: VecDeque<UnrewardedRelayer<AccountId>>, + confirmation_relayer: &AccountId, + received_range: &RangeInclusive<MessageNonce>, + ); +} + +impl<AccountId> DeliveryConfirmationPayments<AccountId> for () { + type Error = &'static str; + + fn pay_reward( + _lane_id: LaneId, + _messages_relayers: VecDeque<UnrewardedRelayer<AccountId>>, + _confirmation_relayer: &AccountId, + _received_range: &RangeInclusive<MessageNonce>, + ) { + // this implementation is not rewarding relayers at all + } +} + /// Send message artifacts. #[derive(Eq, RuntimeDebug, PartialEq)] pub struct SendMessageArtifacts { -- GitLab