From 02ef3a1a2586cea0eb4af689bfc8b21022a511da Mon Sep 17 00:00:00 2001
From: Branislav Kontur <bkontur@gmail.com>
Date: Wed, 30 Nov 2022 16:44:30 +0100
Subject: [PATCH] Added generic DispatchLevelResult to the
 MessageDispatchResult (#1670)

* Added generic DispatchLevelResult to the MessageDispatchResult

* Removed unnecessery `Clone + Decode + sp_std::fmt::Debug + Eq` + clippy
---
 bridges/bin/millau/runtime/src/xcm_config.rs  |  1 +
 .../bin/rialto-parachain/runtime/src/lib.rs   |  1 +
 bridges/bin/rialto/runtime/src/xcm_config.rs  |  1 +
 bridges/bin/runtime-common/src/messages.rs    |  4 +++-
 bridges/modules/messages/src/inbound_lane.rs  |  2 +-
 bridges/modules/messages/src/lib.rs           |  8 +++++++-
 bridges/modules/messages/src/mock.rs          | 11 ++++++++---
 bridges/primitives/messages/src/lib.rs        | 19 +++++++++++--------
 .../primitives/messages/src/target_chain.rs   | 12 ++++++++++--
 bridges/primitives/runtime/src/messages.rs    |  4 +++-
 10 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/bridges/bin/millau/runtime/src/xcm_config.rs b/bridges/bin/millau/runtime/src/xcm_config.rs
index 41f336e61b8..b5be117ac77 100644
--- a/bridges/bin/millau/runtime/src/xcm_config.rs
+++ b/bridges/bin/millau/runtime/src/xcm_config.rs
@@ -319,6 +319,7 @@ mod tests {
 				MessageDispatchResult {
 					unspent_weight: frame_support::weights::Weight::from_ref_time(0),
 					dispatch_fee_paid_during_dispatch: false,
+					dispatch_level_result: (),
 				}
 			);
 		})
diff --git a/bridges/bin/rialto-parachain/runtime/src/lib.rs b/bridges/bin/rialto-parachain/runtime/src/lib.rs
index e80ecdf188d..f946abf4c1d 100644
--- a/bridges/bin/rialto-parachain/runtime/src/lib.rs
+++ b/bridges/bin/rialto-parachain/runtime/src/lib.rs
@@ -897,6 +897,7 @@ mod tests {
 				MessageDispatchResult {
 					unspent_weight: frame_support::weights::Weight::from_ref_time(0),
 					dispatch_fee_paid_during_dispatch: false,
+					dispatch_level_result: (),
 				}
 			);
 		})
diff --git a/bridges/bin/rialto/runtime/src/xcm_config.rs b/bridges/bin/rialto/runtime/src/xcm_config.rs
index 895522655d2..892c1ed747b 100644
--- a/bridges/bin/rialto/runtime/src/xcm_config.rs
+++ b/bridges/bin/rialto/runtime/src/xcm_config.rs
@@ -278,6 +278,7 @@ mod tests {
 				MessageDispatchResult {
 					unspent_weight: frame_support::weights::Weight::from_ref_time(0),
 					dispatch_fee_paid_during_dispatch: false,
+					dispatch_level_result: (),
 				}
 			);
 		})
diff --git a/bridges/bin/runtime-common/src/messages.rs b/bridges/bin/runtime-common/src/messages.rs
index 696d059cf63..23c79b1c583 100644
--- a/bridges/bin/runtime-common/src/messages.rs
+++ b/bridges/bin/runtime-common/src/messages.rs
@@ -449,6 +449,7 @@ pub mod target {
 		WeightCredit: Get<Weight>,
 	{
 		type DispatchPayload = FromBridgedChainMessagePayload<CallOf<ThisChain<B>>>;
+		type DispatchLevelResult = ();
 
 		fn dispatch_weight(
 			message: &mut DispatchMessage<Self::DispatchPayload>,
@@ -482,7 +483,7 @@ pub mod target {
 		fn dispatch(
 			_relayer_account: &AccountIdOf<ThisChain<B>>,
 			message: DispatchMessage<Self::DispatchPayload>,
-		) -> MessageDispatchResult {
+		) -> MessageDispatchResult<Self::DispatchLevelResult> {
 			let message_id = (message.key.lane_id, message.key.nonce);
 			let do_dispatch = move || -> sp_std::result::Result<Outcome, codec::Error> {
 				let FromBridgedChainMessagePayload { xcm: (location, xcm), weight: weight_limit } =
@@ -544,6 +545,7 @@ pub mod target {
 			MessageDispatchResult {
 				unspent_weight: Weight::zero(),
 				dispatch_fee_paid_during_dispatch: false,
+				dispatch_level_result: (),
 			}
 		}
 	}
diff --git a/bridges/modules/messages/src/inbound_lane.rs b/bridges/modules/messages/src/inbound_lane.rs
index 0797cbfb946..00c63b5d670 100644
--- a/bridges/modules/messages/src/inbound_lane.rs
+++ b/bridges/modules/messages/src/inbound_lane.rs
@@ -165,7 +165,7 @@ impl<S: InboundLaneStorage> InboundLane<S> {
 		relayer_at_this_chain: &AccountId,
 		nonce: MessageNonce,
 		message_data: DispatchMessageData<Dispatch::DispatchPayload>,
-	) -> ReceivalResult {
+	) -> ReceivalResult<Dispatch::DispatchLevelResult> {
 		let mut data = self.storage.data();
 		let is_correct_message = nonce == data.last_delivered_nonce() + 1;
 		if !is_correct_message {
diff --git a/bridges/modules/messages/src/lib.rs b/bridges/modules/messages/src/lib.rs
index abe6ec67983..0df6c686cc6 100644
--- a/bridges/modules/messages/src/lib.rs
+++ b/bridges/modules/messages/src/lib.rs
@@ -515,7 +515,13 @@ pub mod pallet {
 		/// Message has been accepted and is waiting to be delivered.
 		MessageAccepted { lane_id: LaneId, nonce: MessageNonce },
 		/// Messages have been received from the bridged chain.
-		MessagesReceived(Vec<ReceivedMessages<ReceivalResult>>),
+		MessagesReceived(
+			Vec<
+				ReceivedMessages<
+					<T::MessageDispatch as MessageDispatch<T::AccountId>>::DispatchLevelResult,
+				>,
+			>,
+		),
 		/// Messages in the inclusive range have been delivered to the bridged chain.
 		MessagesDelivered { lane_id: LaneId, messages: DeliveredMessages },
 	}
diff --git a/bridges/modules/messages/src/mock.rs b/bridges/modules/messages/src/mock.rs
index 7a59eb4fc3e..36c38677e53 100644
--- a/bridges/modules/messages/src/mock.rs
+++ b/bridges/modules/messages/src/mock.rs
@@ -60,12 +60,13 @@ pub struct TestPayload {
 	///
 	/// Note: in correct code `dispatch_result.unspent_weight` will always be <= `declared_weight`,
 	/// but for test purposes we'll be making it larger than `declared_weight` sometimes.
-	pub dispatch_result: MessageDispatchResult,
+	pub dispatch_result: MessageDispatchResult<TestDispatchLevelResult>,
 	/// Extra bytes that affect payload size.
 	pub extra: Vec<u8>,
 }
 pub type TestMessageFee = u64;
 pub type TestRelayer = u64;
+pub type TestDispatchLevelResult = ();
 
 type Block = frame_system::mocking::MockBlock<TestRuntime>;
 type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<TestRuntime>;
@@ -345,6 +346,7 @@ pub struct TestMessageDispatch;
 
 impl MessageDispatch<AccountId> for TestMessageDispatch {
 	type DispatchPayload = TestPayload;
+	type DispatchLevelResult = TestDispatchLevelResult;
 
 	fn dispatch_weight(message: &mut DispatchMessage<TestPayload>) -> Weight {
 		match message.data.payload.as_ref() {
@@ -356,7 +358,7 @@ impl MessageDispatch<AccountId> for TestMessageDispatch {
 	fn dispatch(
 		_relayer_account: &AccountId,
 		message: DispatchMessage<TestPayload>,
-	) -> MessageDispatchResult {
+	) -> MessageDispatchResult<TestDispatchLevelResult> {
 		match message.data.payload.as_ref() {
 			Ok(payload) => payload.dispatch_result.clone(),
 			Err(_) => dispatch_result(0),
@@ -391,10 +393,13 @@ pub const fn message_payload(id: u64, declared_weight: u64) -> TestPayload {
 }
 
 /// Returns message dispatch result with given unspent weight.
-pub const fn dispatch_result(unspent_weight: u64) -> MessageDispatchResult {
+pub const fn dispatch_result(
+	unspent_weight: u64,
+) -> MessageDispatchResult<TestDispatchLevelResult> {
 	MessageDispatchResult {
 		unspent_weight: Weight::from_ref_time(unspent_weight),
 		dispatch_fee_paid_during_dispatch: true,
+		dispatch_level_result: (),
 	}
 }
 
diff --git a/bridges/primitives/messages/src/lib.rs b/bridges/primitives/messages/src/lib.rs
index 722a73cb24e..daaa2800988 100644
--- a/bridges/primitives/messages/src/lib.rs
+++ b/bridges/primitives/messages/src/lib.rs
@@ -30,8 +30,8 @@ pub mod source_chain;
 pub mod storage_keys;
 pub mod target_chain;
 
-// Weight is reexported to avoid additional frame-support dependencies in related crates.
 use bp_runtime::messages::MessageDispatchResult;
+// Weight is reexported to avoid additional frame-support dependencies in related crates.
 pub use frame_support::weights::Weight;
 
 /// Messages pallet operating mode.
@@ -212,21 +212,24 @@ pub struct UnrewardedRelayer<RelayerId> {
 
 /// Received messages with their dispatch result.
 #[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)]
-pub struct ReceivedMessages<Result> {
+pub struct ReceivedMessages<DispatchLevelResult> {
 	/// Id of the lane which is receiving messages.
 	pub lane: LaneId,
 	/// Result of messages which we tried to dispatch
-	pub receive_results: Vec<(MessageNonce, Result)>,
+	pub receive_results: Vec<(MessageNonce, ReceivalResult<DispatchLevelResult>)>,
 	/// Messages which were skipped and never dispatched
 	pub skipped_for_not_enough_weight: Vec<MessageNonce>,
 }
 
-impl<Result> ReceivedMessages<Result> {
-	pub fn new(lane: LaneId, receive_results: Vec<(MessageNonce, Result)>) -> Self {
+impl<DispatchLevelResult> ReceivedMessages<DispatchLevelResult> {
+	pub fn new(
+		lane: LaneId,
+		receive_results: Vec<(MessageNonce, ReceivalResult<DispatchLevelResult>)>,
+	) -> Self {
 		ReceivedMessages { lane, receive_results, skipped_for_not_enough_weight: Vec::new() }
 	}
 
-	pub fn push(&mut self, message: MessageNonce, result: Result) {
+	pub fn push(&mut self, message: MessageNonce, result: ReceivalResult<DispatchLevelResult>) {
 		self.receive_results.push((message, result));
 	}
 
@@ -237,12 +240,12 @@ impl<Result> ReceivedMessages<Result> {
 
 /// Result of single message receival.
 #[derive(RuntimeDebug, Encode, Decode, PartialEq, Eq, Clone, TypeInfo)]
-pub enum ReceivalResult {
+pub enum ReceivalResult<DispatchLevelResult> {
 	/// Message has been received and dispatched. Note that we don't care whether dispatch has
 	/// been successful or not - in both case message falls into this category.
 	///
 	/// The message dispatch result is also returned.
-	Dispatched(MessageDispatchResult),
+	Dispatched(MessageDispatchResult<DispatchLevelResult>),
 	/// Message has invalid nonce and lane has rejected to accept this message.
 	InvalidNonce,
 	/// There are too many unrewarded relayer entries at the lane.
diff --git a/bridges/primitives/messages/src/target_chain.rs b/bridges/primitives/messages/src/target_chain.rs
index 6487508588d..63c8b639e6c 100644
--- a/bridges/primitives/messages/src/target_chain.rs
+++ b/bridges/primitives/messages/src/target_chain.rs
@@ -89,6 +89,9 @@ pub trait MessageDispatch<AccountId> {
 	/// (opaque `MessagePayload` used in delivery and this `DispatchPayload` used in dispatch).
 	type DispatchPayload: Decode;
 
+	/// Fine-grained result of single message dispatch (for better diagnostic purposes)
+	type DispatchLevelResult: Clone + Decode + sp_std::fmt::Debug + Eq;
+
 	/// Estimate dispatch weight.
 	///
 	/// This function must return correct upper bound of dispatch weight. The return value
@@ -106,7 +109,7 @@ pub trait MessageDispatch<AccountId> {
 	fn dispatch(
 		relayer_account: &AccountId,
 		message: DispatchMessage<Self::DispatchPayload>,
-	) -> MessageDispatchResult;
+	) -> MessageDispatchResult<Self::DispatchLevelResult>;
 }
 
 impl<Message> Default for ProvedLaneMessages<Message> {
@@ -149,15 +152,20 @@ impl SourceHeaderChain for ForbidInboundMessages {
 
 impl<AccountId> MessageDispatch<AccountId> for ForbidInboundMessages {
 	type DispatchPayload = ();
+	type DispatchLevelResult = ();
 
 	fn dispatch_weight(_message: &mut DispatchMessage<Self::DispatchPayload>) -> Weight {
 		Weight::MAX
 	}
 
-	fn dispatch(_: &AccountId, _: DispatchMessage<Self::DispatchPayload>) -> MessageDispatchResult {
+	fn dispatch(
+		_: &AccountId,
+		_: DispatchMessage<Self::DispatchPayload>,
+	) -> MessageDispatchResult<Self::DispatchLevelResult> {
 		MessageDispatchResult {
 			unspent_weight: Weight::zero(),
 			dispatch_fee_paid_during_dispatch: false,
+			dispatch_level_result: (),
 		}
 	}
 }
diff --git a/bridges/primitives/runtime/src/messages.rs b/bridges/primitives/runtime/src/messages.rs
index b2e8aacedfa..0bb09090df9 100644
--- a/bridges/primitives/runtime/src/messages.rs
+++ b/bridges/primitives/runtime/src/messages.rs
@@ -22,7 +22,7 @@ use scale_info::TypeInfo;
 
 /// Message dispatch result.
 #[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)]
-pub struct MessageDispatchResult {
+pub struct MessageDispatchResult<DispatchLevelResult> {
 	/// Unspent dispatch weight. This weight that will be deducted from total delivery transaction
 	/// weight, thus reducing the transaction cost. This shall not be zero in (at least) two cases:
 	///
@@ -34,4 +34,6 @@ pub struct MessageDispatchResult {
 	/// configuration supports pay-dispatch-fee-at-target-chain option and message sender has
 	/// enabled this option.
 	pub dispatch_fee_paid_during_dispatch: bool,
+	/// Fine-grained result of single message dispatch (for better diagnostic purposes)
+	pub dispatch_level_result: DispatchLevelResult,
 }
-- 
GitLab