From 1a514f6d3753189c21a6b68d38cc6289999de047 Mon Sep 17 00:00:00 2001
From: girazoki <gorka.irazoki@gmail.com>
Date: Fri, 21 Mar 2025 13:38:10 +0100
Subject: [PATCH] Add digest processor xcm emulator (#7915)

Currently parachains are injecting through the xcm-emulator the default
digests in each block, something that can prevent testing certain
consensus aspects.

We propose to add the type `DigestProvider`, which needs to implement
the trait `Convert<blockNumber, Digest>`. The idea is that we can call
the implementation of this trait before initializing every block, and
thus, allowing us to inject custom digests provided by this trait.

Obviously the default behavior persists if you set this type to `().`

The utilization of the `Convert` trait was arbitrary, as it was the
easiest to accomplish the solution. I am not against using a custom
trait defined for this purpose if that is preferred.

---------

Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
 .../assets/asset-hub-rococo/src/lib.rs          |  1 +
 .../assets/asset-hub-westend/src/lib.rs         |  1 +
 cumulus/xcm/xcm-emulator/src/lib.rs             | 17 ++++++++++++-----
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/lib.rs
index 1a075b9fe6b..ceb4d23c294 100644
--- a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/lib.rs
+++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/lib.rs
@@ -42,6 +42,7 @@ decl_test_parachains! {
 			LocationToAccountId: asset_hub_rococo_runtime::xcm_config::LocationToAccountId,
 			ParachainInfo: asset_hub_rococo_runtime::ParachainInfo,
 			MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
+			DigestProvider: (),
 		},
 		pallets = {
 			PolkadotXcm: asset_hub_rococo_runtime::PolkadotXcm,
diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/lib.rs
index 3e240ed6748..3e63fa4917d 100644
--- a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/lib.rs
+++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/lib.rs
@@ -42,6 +42,7 @@ decl_test_parachains! {
 			LocationToAccountId: asset_hub_westend_runtime::xcm_config::LocationToAccountId,
 			ParachainInfo: asset_hub_westend_runtime::ParachainInfo,
 			MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
+			DigestProvider: (),
 		},
 		pallets = {
 			PolkadotXcm: asset_hub_westend_runtime::PolkadotXcm,
diff --git a/cumulus/xcm/xcm-emulator/src/lib.rs b/cumulus/xcm/xcm-emulator/src/lib.rs
index 8fe6181ab23..28719c8654e 100644
--- a/cumulus/xcm/xcm-emulator/src/lib.rs
+++ b/cumulus/xcm/xcm-emulator/src/lib.rs
@@ -37,8 +37,8 @@ pub use cumulus_primitives_core::AggregateMessageOrigin as CumulusAggregateMessa
 pub use frame_support::{
 	assert_ok,
 	sp_runtime::{
-		traits::{Dispatchable, Header as HeaderT},
-		DispatchResult,
+		traits::{Convert, Dispatchable, Header as HeaderT},
+		Digest, DispatchResult,
 	},
 	traits::{
 		EnqueueMessage, ExecuteOverweightError, Get, Hooks, OnInitialize, OriginTrait,
@@ -108,7 +108,6 @@ thread_local! {
 	/// Most recent `HeadData` of each parachain, encoded.
 	pub static LAST_HEAD: RefCell<HashMap<String, HashMap<u32, HeadData>>> = RefCell::new(HashMap::new());
 }
-
 pub trait CheckAssertion<Origin, Destination, Hops, Args>
 where
 	Origin: Chain + Clone,
@@ -264,6 +263,7 @@ pub trait Parachain: Chain {
 	type ParachainInfo: Get<ParaId>;
 	type ParachainSystem;
 	type MessageProcessor: ProcessMessage + ServiceQueues;
+	type DigestProvider: sp_runtime::traits::Convert<BlockNumberFor<Self::Runtime>, Digest>;
 
 	fn init();
 
@@ -599,6 +599,7 @@ macro_rules! decl_test_parachains {
 					LocationToAccountId: $location_to_account:path,
 					ParachainInfo: $parachain_info:path,
 					MessageOrigin: $message_origin:path,
+					$( DigestProvider: $digest_provider:ty, )?
 				},
 				pallets = {
 					$($pallet_name:ident: $pallet_path:path,)*
@@ -639,6 +640,7 @@ macro_rules! decl_test_parachains {
 				type ParachainSystem = $crate::ParachainSystemPallet<<Self as $crate::Chain>::Runtime>;
 				type ParachainInfo = $parachain_info;
 				type MessageProcessor = $crate::DefaultParaMessageProcessor<$name<N>, $message_origin>;
+				$crate::decl_test_parachains!(@inner_digest_provider $($digest_provider)?);
 
 				// We run an empty block during initialisation to open HRMP channels
 				// and have them ready for the next block
@@ -657,7 +659,7 @@ macro_rules! decl_test_parachains {
 				}
 
 				fn new_block() {
-					use $crate::{Chain, HeadData, Network, Hooks, Encode, Parachain, TestExt};
+					use $crate::{Chain, Convert, HeadData, Network, Hooks, Encode, Parachain, TestExt};
 
 					let para_id = Self::para_id().into();
 
@@ -677,7 +679,10 @@ macro_rules! decl_test_parachains {
 							.expect("network not initialized?")
 							.clone()
 						);
-						<Self as Chain>::System::initialize(&block_number, &parent_head_data.hash(), &Default::default());
+
+						let digest = <Self as Parachain>::DigestProvider::convert(block_number);
+
+						<Self as Chain>::System::initialize(&block_number, &parent_head_data.hash(), &digest);
 						<<Self as Parachain>::ParachainSystem as Hooks<$crate::BlockNumberFor<Self::Runtime>>>::on_initialize(block_number);
 
 						let _ = <Self as Parachain>::ParachainSystem::set_validation_data(
@@ -734,6 +739,8 @@ macro_rules! decl_test_parachains {
 			$crate::__impl_check_assertion!($name, N);
 		)+
 	};
+	( @inner_digest_provider $digest_provider:ty ) => { type DigestProvider = $digest_provider; };
+	( @inner_digest_provider /* none */ ) => { type DigestProvider = (); };
 }
 
 #[macro_export]
-- 
GitLab