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