DeliveryConfirmationPayments trait for paying relayer rewards at the source chain (#1653)

* DeliveryConfirmationPayments

* ref proper PR in TODO
This commit is contained in:
Svyatoslav Nikolsky
2022-12-06 16:09:21 +03:00
committed by Bastian Köcher
parent 7014046485
commit aeeb53343e
11 changed files with 118 additions and 93 deletions
+6 -4
View File
@@ -475,9 +475,10 @@ impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime {
type TargetHeaderChain = crate::rialto_messages::Rialto; type TargetHeaderChain = crate::rialto_messages::Rialto;
type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier;
type MessageDeliveryAndDispatchPayment = type MessageDeliveryAndDispatchPayment =
pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
Runtime, Runtime,
WithRialtoMessagesInstance, frame_support::traits::ConstU64<100_000>,
frame_support::traits::ConstU64<100_000>,
>; >;
type SourceHeaderChain = crate::rialto_messages::Rialto; 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 TargetHeaderChain = crate::rialto_parachain_messages::RialtoParachain;
type LaneMessageVerifier = crate::rialto_parachain_messages::ToRialtoParachainMessageVerifier; type LaneMessageVerifier = crate::rialto_parachain_messages::ToRialtoParachainMessageVerifier;
type MessageDeliveryAndDispatchPayment = type MessageDeliveryAndDispatchPayment =
pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
Runtime, Runtime,
WithRialtoParachainMessagesInstance, frame_support::traits::ConstU64<100_000>,
frame_support::traits::ConstU64<100_000>,
>; >;
type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachain; type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachain;
@@ -570,9 +570,10 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
type TargetHeaderChain = crate::millau_messages::Millau; type TargetHeaderChain = crate::millau_messages::Millau;
type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier;
type MessageDeliveryAndDispatchPayment = type MessageDeliveryAndDispatchPayment =
pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
Runtime, Runtime,
WithMillauMessagesInstance, frame_support::traits::ConstU64<100_000>,
frame_support::traits::ConstU64<100_000>,
>; >;
type SourceHeaderChain = crate::millau_messages::Millau; type SourceHeaderChain = crate::millau_messages::Millau;
+3 -2
View File
@@ -457,9 +457,10 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
type TargetHeaderChain = crate::millau_messages::Millau; type TargetHeaderChain = crate::millau_messages::Millau;
type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier;
type MessageDeliveryAndDispatchPayment = type MessageDeliveryAndDispatchPayment =
pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
Runtime, Runtime,
WithMillauMessagesInstance, frame_support::traits::ConstU64<100_000>,
frame_support::traits::ConstU64<100_000>,
>; >;
type SourceHeaderChain = crate::millau_messages::Millau; type SourceHeaderChain = crate::millau_messages::Millau;
+4 -32
View File
@@ -52,24 +52,21 @@ use crate::{
use bp_messages::{ use bp_messages::{
source_chain::{ source_chain::{
LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, LaneMessageVerifier, MessageDeliveryAndDispatchPayment, SendMessageArtifacts,
SendMessageArtifacts, TargetHeaderChain, TargetHeaderChain,
}, },
target_chain::{ target_chain::{
DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain,
}, },
total_unrewarded_messages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId, total_unrewarded_messages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId,
MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData, MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData,
OutboundMessageDetails, UnrewardedRelayer, UnrewardedRelayersState, OutboundMessageDetails, UnrewardedRelayersState,
}; };
use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size}; use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size};
use codec::{Decode, Encode, MaxEncodedLen}; use codec::{Decode, Encode, MaxEncodedLen};
use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get}; use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get};
use sp_runtime::traits::UniqueSaturatedFrom; use sp_runtime::traits::UniqueSaturatedFrom;
use sp_std::{ use sp_std::{cell::RefCell, marker::PhantomData, prelude::*};
cell::RefCell, collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive,
prelude::*,
};
mod inbound_lane; mod inbound_lane;
mod outbound_lane; mod outbound_lane;
@@ -725,31 +722,6 @@ fn send_message<T: Config<I>, I: 'static>(
Ok(SendMessageArtifacts { nonce, weight: actual_weight }) 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. /// Ensure that the pallet is in normal operational mode.
fn ensure_normal_operating_mode<T: Config<I>, I: 'static>() -> Result<(), Error<T, I>> { fn ensure_normal_operating_mode<T: Config<I>, I: 'static>() -> Result<(), Error<T, I>> {
if PalletOperatingMode::<T, I>::get() == if PalletOperatingMode::<T, I>::get() ==
+3 -3
View File
@@ -17,9 +17,10 @@
// From construct_runtime macro // From construct_runtime macro
#![allow(clippy::from_over_into)] #![allow(clippy::from_over_into)]
use crate::{calc_relayers_rewards, Config}; use crate::Config;
use bp_messages::{ use bp_messages::{
calc_relayers_rewards,
source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain},
target_chain::{ target_chain::{
DispatchMessage, DispatchMessageData, MessageDispatch, ProvedLaneMessages, ProvedMessages, DispatchMessage, DispatchMessageData, MessageDispatch, ProvedLaneMessages, ProvedMessages,
@@ -311,8 +312,7 @@ impl MessageDeliveryAndDispatchPayment<RuntimeOrigin, AccountId>
_confirmation_relayer: &AccountId, _confirmation_relayer: &AccountId,
received_range: &RangeInclusive<MessageNonce>, received_range: &RangeInclusive<MessageNonce>,
) { ) {
let relayers_rewards = let relayers_rewards = calc_relayers_rewards(message_relayers, received_range);
calc_relayers_rewards::<TestRuntime, ()>(message_relayers, received_range);
for (relayer, reward) in &relayers_rewards { for (relayer, reward) in &relayers_rewards {
let key = (b":relayer-reward:", relayer, reward).encode(); let key = (b":relayer-reward:", relayer, reward).encode();
frame_support::storage::unhashed::put(&key, &true); frame_support::storage::unhashed::put(&key, &true);
-2
View File
@@ -15,7 +15,6 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive"
bp-messages = { path = "../../primitives/messages", default-features = false } bp-messages = { path = "../../primitives/messages", default-features = false }
bp-relayers = { path = "../../primitives/relayers", default-features = false } bp-relayers = { path = "../../primitives/relayers", default-features = false }
pallet-bridge-messages = { path = "../messages", default-features = false }
# Substrate Dependencies # Substrate Dependencies
@@ -41,7 +40,6 @@ std = [
"frame-support/std", "frame-support/std",
"frame-system/std", "frame-system/std",
"log/std", "log/std",
"pallet-bridge-messages/std",
"scale-info/std", "scale-info/std",
"sp-arithmetic/std", "sp-arithmetic/std",
"sp-std/std", "sp-std/std",
+1 -1
View File
@@ -28,7 +28,7 @@ use sp_std::marker::PhantomData;
use weights::WeightInfo; use weights::WeightInfo;
pub use pallet::*; pub use pallet::*;
pub use payment_adapter::MessageDeliveryAndDispatchPaymentAdapter; pub use payment_adapter::DeliveryConfirmationPaymentsAdapter;
pub mod benchmarking; pub mod benchmarking;
+1 -32
View File
@@ -18,9 +18,7 @@
use crate as pallet_bridge_relayers; use crate as pallet_bridge_relayers;
use bp_messages::{ use bp_messages::LaneId;
source_chain::ForbidOutboundMessages, target_chain::ForbidInboundMessages, LaneId,
};
use bp_relayers::PaymentProcedure; use bp_relayers::PaymentProcedure;
use frame_support::{parameter_types, weights::RuntimeDbWeight}; use frame_support::{parameter_types, weights::RuntimeDbWeight};
use sp_core::H256; use sp_core::H256;
@@ -43,7 +41,6 @@ frame_support::construct_runtime! {
{ {
System: frame_system::{Pallet, Call, Config, Storage, Event<T>}, System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Balances: pallet_balances::{Pallet, Event<T>}, Balances: pallet_balances::{Pallet, Event<T>},
Messages: pallet_bridge_messages::{Pallet, Event<T>},
Relayers: pallet_bridge_relayers::{Pallet, Call, Event<T>}, Relayers: pallet_bridge_relayers::{Pallet, Call, Event<T>},
} }
} }
@@ -91,34 +88,6 @@ impl pallet_balances::Config for TestRuntime {
type ReserveIdentifier = (); 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 { impl pallet_bridge_relayers::Config for TestRuntime {
type RuntimeEvent = RuntimeEvent; type RuntimeEvent = RuntimeEvent;
type Reward = Balance; type Reward = Balance;
+41 -14
View File
@@ -19,22 +19,25 @@
use crate::{Config, Pallet}; use crate::{Config, Pallet};
use bp_messages::source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards}; use bp_messages::source_chain::{
use frame_support::sp_runtime::SaturatedConversion; DeliveryConfirmationPayments, MessageDeliveryAndDispatchPayment, RelayersRewards,
};
use frame_support::{sp_runtime::SaturatedConversion, traits::Get};
use sp_arithmetic::traits::{Saturating, UniqueSaturatedFrom, Zero}; use sp_arithmetic::traits::{Saturating, UniqueSaturatedFrom, Zero};
use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive}; 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 /// Adapter that allows relayers pallet to be used as a delivery+dispatch payment mechanism
/// for the messages pallet. /// for the messages pallet.
pub struct MessageDeliveryAndDispatchPaymentAdapter<T, MessagesInstance>( pub struct DeliveryConfirmationPaymentsAdapter<T, DeliveryReward, ConfirmationReward>(
PhantomData<(T, MessagesInstance)>, PhantomData<(T, DeliveryReward, ConfirmationReward)>,
); );
impl<T, MessagesInstance> MessageDeliveryAndDispatchPayment<T::RuntimeOrigin, T::AccountId> // TODO (https://github.com/paritytech/parity-bridges-common/pull/1652): this impl must be removed
for MessageDeliveryAndDispatchPaymentAdapter<T, MessagesInstance> impl<T, DeliveryReward, ConfirmationReward>
MessageDeliveryAndDispatchPayment<T::RuntimeOrigin, T::AccountId>
for DeliveryConfirmationPaymentsAdapter<T, DeliveryReward, ConfirmationReward>
where where
T: Config + pallet_bridge_messages::Config<MessagesInstance>, T: Config,
MessagesInstance: 'static,
{ {
type Error = &'static str; type Error = &'static str;
@@ -44,23 +47,47 @@ where
confirmation_relayer: &T::AccountId, confirmation_relayer: &T::AccountId,
received_range: &RangeInclusive<bp_messages::MessageNonce>, received_range: &RangeInclusive<bp_messages::MessageNonce>,
) { ) {
let relayers_rewards = pallet_bridge_messages::calc_relayers_rewards::<T, MessagesInstance>( let relayers_rewards =
messages_relayers, bp_messages::calc_relayers_rewards::<T::AccountId>(messages_relayers, received_range);
received_range,
);
register_relayers_rewards::<T>( register_relayers_rewards::<T>(
confirmation_relayer, confirmation_relayer,
relayers_rewards, relayers_rewards,
lane_id, 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(), 100_000_u32.into(),
10_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. // Update rewards to given relayers, optionally rewarding confirmation relayer.
fn register_relayers_rewards<T: Config>( fn register_relayers_rewards<T: Config>(
confirmation_relayer: &T::AccountId, confirmation_relayer: &T::AccountId,
+25 -1
View File
@@ -25,7 +25,7 @@ use codec::{Decode, Encode, MaxEncodedLen};
use frame_support::RuntimeDebug; use frame_support::RuntimeDebug;
use scale_info::TypeInfo; use scale_info::TypeInfo;
use sp_core::TypeId; 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 source_chain;
pub mod storage_keys; 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)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@@ -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. /// Send message artifacts.
#[derive(Eq, RuntimeDebug, PartialEq)] #[derive(Eq, RuntimeDebug, PartialEq)]
pub struct SendMessageArtifacts { pub struct SendMessageArtifacts {