From e2fddc6baa59581e3880e61b8fea1097f589f7a1 Mon Sep 17 00:00:00 2001 From: bear <2630582710@qq.com> Date: Mon, 27 Sep 2021 15:45:12 +0800 Subject: [PATCH] Move calculation relayer reward into `MessageDeliveryAndDispatchPayment` (#1153) * Refactor logic * Thanks svyatonik help, it compile * Fix failed unit test * Remove compile warning * Rename * Return result in pay_relayers_rewards * Fix runtime compile issue * Use MessageNonce * Fix review issue * Missing u64 replacement * Revert return type changes * Fix merge issue * Remove useless clone --- bridges/bin/millau/runtime/src/lib.rs | 1 + bridges/bin/rialto/runtime/src/lib.rs | 1 + .../modules/messages/src/instant_payments.rs | 71 ++++++++++++++----- bridges/modules/messages/src/lib.rs | 46 ++++-------- bridges/modules/messages/src/mock.rs | 17 +++-- .../primitives/messages/src/source_chain.rs | 15 +++- 6 files changed, 93 insertions(+), 58 deletions(-) diff --git a/bridges/bin/millau/runtime/src/lib.rs b/bridges/bin/millau/runtime/src/lib.rs index 698ad1e58046..d97a82d62500 100644 --- a/bridges/bin/millau/runtime/src/lib.rs +++ b/bridges/bin/millau/runtime/src/lib.rs @@ -402,6 +402,7 @@ impl pallet_bridge_messages::Config for Runtime { type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, + (), pallet_balances::Pallet, GetDeliveryConfirmationTransactionFee, RootAccountForPayments, diff --git a/bridges/bin/rialto/runtime/src/lib.rs b/bridges/bin/rialto/runtime/src/lib.rs index 84908fd52bf0..51a5a8957cbd 100644 --- a/bridges/bin/rialto/runtime/src/lib.rs +++ b/bridges/bin/rialto/runtime/src/lib.rs @@ -545,6 +545,7 @@ impl pallet_bridge_messages::Config for Runtime { type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, + (), pallet_balances::Pallet, GetDeliveryConfirmationTransactionFee, RootAccountForPayments, diff --git a/bridges/modules/messages/src/instant_payments.rs b/bridges/modules/messages/src/instant_payments.rs index 4933901c2670..c145687af994 100644 --- a/bridges/modules/messages/src/instant_payments.rs +++ b/bridges/modules/messages/src/instant_payments.rs @@ -19,15 +19,17 @@ //! The payment is first transferred to a special `relayers-fund` account and only transferred //! to the actual relayer in case confirmation is received. +use crate::OutboundMessages; + use bp_messages::{ source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards, Sender}, - MessageNonce, + LaneId, MessageKey, MessageNonce, UnrewardedRelayer, }; use codec::Encode; use frame_support::traits::{Currency as CurrencyT, ExistenceRequirement, Get}; -use num_traits::Zero; +use num_traits::{SaturatingAdd, Zero}; use sp_runtime::traits::Saturating; -use sp_std::fmt::Debug; +use sp_std::{collections::vec_deque::VecDeque, fmt::Debug, ops::RangeInclusive}; /// Instant message payments made in given currency. /// @@ -42,16 +44,17 @@ use sp_std::fmt::Debug; /// 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, Currency, GetConfirmationFee, RootAccount)>, +pub struct InstantCurrencyPayments { + _phantom: sp_std::marker::PhantomData<(T, I, Currency, GetConfirmationFee, RootAccount)>, } -impl +impl MessageDeliveryAndDispatchPayment - for InstantCurrencyPayments + for InstantCurrencyPayments where - T: frame_system::Config, - Currency: CurrencyT, + T: frame_system::Config + crate::Config, + I: 'static, + Currency: CurrencyT, Currency::Balance: From, GetConfirmationFee: Get, RootAccount: Get>, @@ -86,17 +89,53 @@ where } fn pay_relayers_rewards( + lane_id: LaneId, + messages_relayers: VecDeque>, confirmation_relayer: &T::AccountId, - relayers_rewards: RelayersRewards, + received_range: &RangeInclusive, relayer_fund_account: &T::AccountId, ) { - pay_relayers_rewards::( - confirmation_relayer, - relayers_rewards, - relayer_fund_account, - GetConfirmationFee::get(), - ); + let relayers_rewards = + cal_relayers_rewards::(lane_id, messages_relayers, received_range); + if !relayers_rewards.is_empty() { + pay_relayers_rewards::( + confirmation_relayer, + relayers_rewards, + relayer_fund_account, + GetConfirmationFee::get(), + ); + } + } +} + +/// Calculate the relayers rewards +pub(crate) fn cal_relayers_rewards( + lane_id: LaneId, + messages_relayers: VecDeque>, + received_range: &RangeInclusive, +) -> RelayersRewards +where + T: frame_system::Config + crate::Config, + 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<_, T::OutboundMessageFee> = 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 + let mut relayer_reward = relayers_rewards.entry(entry.relayer).or_default(); + for nonce in nonce_begin..nonce_end + 1 { + let message_data = OutboundMessages::::get(MessageKey { lane_id, nonce }) + .expect("message was just confirmed; we never prune unconfirmed messages; qed"); + relayer_reward.reward = relayer_reward.reward.saturating_add(&message_data.fee); + relayer_reward.messages += 1; + } } + relayers_rewards } /// Pay rewards to given relayers, optionally rewarding confirmation relayer. diff --git a/bridges/modules/messages/src/lib.rs b/bridges/modules/messages/src/lib.rs index c5ce27bb7258..ce56fc3f87a7 100644 --- a/bridges/modules/messages/src/lib.rs +++ b/bridges/modules/messages/src/lib.rs @@ -51,7 +51,7 @@ use crate::{ use bp_messages::{ source_chain::{ LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, - OnMessageAccepted, RelayersRewards, TargetHeaderChain, + OnMessageAccepted, TargetHeaderChain, }, target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, @@ -143,7 +143,13 @@ pub mod pallet { /// Payload type of outbound messages. This payload is dispatched on the bridged chain. type OutboundPayload: Parameter + Size; /// Message fee type of outbound messages. This fee is paid on this chain. - type OutboundMessageFee: Default + From + PartialOrd + Parameter + SaturatingAdd + Zero; + type OutboundMessageFee: Default + + From + + PartialOrd + + Parameter + + SaturatingAdd + + Zero + + Copy; /// Payload type of inbound messages. This payload is dispatched on this chain. type InboundPayload: Decode; @@ -548,8 +554,6 @@ pub mod pallet { // mark messages as delivered let mut lane = outbound_lane::(lane_id); - let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = - RelayersRewards::new(); let last_delivered_nonce = lane_data.last_delivered_nonce(); let confirmed_messages = match lane.confirm_delivery( relayers_state.total_messages, @@ -620,40 +624,14 @@ pub mod pallet { let received_range = confirmed_messages.begin..=confirmed_messages.end; Self::deposit_event(Event::MessagesDelivered(lane_id, confirmed_messages)); - // remember to reward relayers that have delivered messages - // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the - // bridged chain - for entry in lane_data.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 - let mut relayer_reward = relayers_rewards.entry(entry.relayer).or_default(); - for nonce in nonce_begin..nonce_end + 1 { - let message_data = OutboundMessages::::get(MessageKey { - lane_id, - nonce, - }) - .expect( - "message was just confirmed; we never prune unconfirmed messages; qed", - ); - relayer_reward.reward = - relayer_reward.reward.saturating_add(&message_data.fee); - relayer_reward.messages += 1; - } - } - } - - // if some new messages have been confirmed, reward relayers - if !relayers_rewards.is_empty() { + // if some new messages have been confirmed, reward relayers let relayer_fund_account = relayer_fund_account_id::(); >::MessageDeliveryAndDispatchPayment::pay_relayers_rewards( + lane_id, + lane_data.relayers, &confirmation_relayer, - relayers_rewards, + &received_range, &relayer_fund_account, ); } diff --git a/bridges/modules/messages/src/mock.rs b/bridges/modules/messages/src/mock.rs index 330cfef4cdea..5cc905d91212 100644 --- a/bridges/modules/messages/src/mock.rs +++ b/bridges/modules/messages/src/mock.rs @@ -17,13 +17,13 @@ // From construct_runtime macro #![allow(clippy::from_over_into)] -use crate::Config; +use crate::{instant_payments::cal_relayers_rewards, Config}; use bitvec::prelude::*; use bp_messages::{ source_chain::{ LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, - OnMessageAccepted, RelayersRewards, Sender, TargetHeaderChain, + OnMessageAccepted, Sender, TargetHeaderChain, }, target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, @@ -43,7 +43,10 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, FixedU128, Perbill, }; -use std::collections::BTreeMap; +use std::{ + collections::{BTreeMap, VecDeque}, + ops::RangeInclusive, +}; pub type AccountId = u64; pub type Balance = u64; @@ -350,11 +353,15 @@ impl MessageDeliveryAndDispatchPayment } fn pay_relayers_rewards( + lane_id: LaneId, + message_relayers: VecDeque>, _confirmation_relayer: &AccountId, - relayers_rewards: RelayersRewards, + received_range: &RangeInclusive, _relayer_fund_account: &AccountId, ) { - for (relayer, reward) in relayers_rewards { + let relayers_rewards = + cal_relayers_rewards::(lane_id, message_relayers, received_range); + for (relayer, reward) in &relayers_rewards { let key = (b":relayer-reward:", relayer, reward.reward).encode(); frame_support::storage::unhashed::put(&key, &true); } diff --git a/bridges/primitives/messages/src/source_chain.rs b/bridges/primitives/messages/src/source_chain.rs index dbe6a5922158..1745180f94cc 100644 --- a/bridges/primitives/messages/src/source_chain.rs +++ b/bridges/primitives/messages/src/source_chain.rs @@ -18,9 +18,14 @@ use crate::{DeliveredMessages, InboundLaneData, LaneId, MessageNonce, OutboundLaneData}; +use crate::UnrewardedRelayer; use bp_runtime::Size; use frame_support::{weights::Weight, Parameter, RuntimeDebug}; -use sp_std::{collections::btree_map::BTreeMap, fmt::Debug}; +use sp_std::{ + collections::{btree_map::BTreeMap, vec_deque::VecDeque}, + fmt::Debug, + ops::RangeInclusive, +}; /// The sender of the message on the source chain. pub type Sender = frame_system::RawOrigin; @@ -122,8 +127,10 @@ pub trait MessageDeliveryAndDispatchPayment { /// The implementation may also choose to pay reward to the `confirmation_relayer`, which is /// a relayer that has submitted delivery confirmation transaction. fn pay_relayers_rewards( + lane_id: LaneId, + messages_relayers: VecDeque>, confirmation_relayer: &AccountId, - relayers_rewards: RelayersRewards, + received_range: &RangeInclusive, relayer_fund_account: &AccountId, ); } @@ -240,8 +247,10 @@ impl MessageDeliveryAndDispatchPayment } fn pay_relayers_rewards( + _lane_id: LaneId, + _messages_relayers: VecDeque>, _confirmation_relayer: &AccountId, - _relayers_rewards: RelayersRewards, + _received_range: &RangeInclusive, _relayer_fund_account: &AccountId, ) { }