From df8b870032794b06440bcb8855bdb4c289c7f5da Mon Sep 17 00:00:00 2001
From: Alin Dima <alin@parity.io>
Date: Mon, 7 Oct 2024 11:25:59 +0300
Subject: [PATCH] parachain-system: send core selector ump signal (#5888)

Runtime side of https://github.com/paritytech/polkadot-sdk/issues/5048

Send the core selector ump signal in cumulus. Guarded by a compile time
feature until nodes are upgraded to a version that includes
https://github.com/paritytech/polkadot-sdk/pull/5423 for gracefully
handling ump signals.

---------

Co-authored-by: GitHub Action <action@github.com>
---
 .../consensus/aura/src/collators/lookahead.rs |  7 +--
 cumulus/pallets/parachain-system/Cargo.toml   |  2 +
 cumulus/pallets/parachain-system/src/lib.rs   | 53 +++++++++++++++++--
 cumulus/primitives/core/src/lib.rs            |  2 +-
 prdoc/pr_5888.prdoc                           | 16 ++++++
 5 files changed, 72 insertions(+), 8 deletions(-)
 create mode 100644 prdoc/pr_5888.prdoc

diff --git a/cumulus/client/consensus/aura/src/collators/lookahead.rs b/cumulus/client/consensus/aura/src/collators/lookahead.rs
index 322baaa0149..8ac43fbd116 100644
--- a/cumulus/client/consensus/aura/src/collators/lookahead.rs
+++ b/cumulus/client/consensus/aura/src/collators/lookahead.rs
@@ -36,7 +36,9 @@ use cumulus_client_collator::service::ServiceInterface as CollatorServiceInterfa
 use cumulus_client_consensus_common::{self as consensus_common, ParachainBlockImportMarker};
 use cumulus_client_consensus_proposer::ProposerInterface;
 use cumulus_primitives_aura::AuraUnincludedSegmentApi;
-use cumulus_primitives_core::{ClaimQueueOffset, CollectCollationInfo, PersistedValidationData};
+use cumulus_primitives_core::{
+	ClaimQueueOffset, CollectCollationInfo, PersistedValidationData, DEFAULT_CLAIM_QUEUE_OFFSET,
+};
 use cumulus_relay_chain_interface::RelayChainInterface;
 
 use polkadot_node_primitives::{PoV, SubmitCollationParams};
@@ -260,8 +262,7 @@ where
 				relay_parent,
 				params.para_id,
 				&mut params.relay_client,
-				// Use depth 0, to preserve behaviour.
-				ClaimQueueOffset(0),
+				ClaimQueueOffset(DEFAULT_CLAIM_QUEUE_OFFSET),
 			)
 			.await
 			.get(0)
diff --git a/cumulus/pallets/parachain-system/Cargo.toml b/cumulus/pallets/parachain-system/Cargo.toml
index 66429625d5b..3cb0394c4b9 100644
--- a/cumulus/pallets/parachain-system/Cargo.toml
+++ b/cumulus/pallets/parachain-system/Cargo.toml
@@ -121,3 +121,5 @@ try-runtime = [
 	"polkadot-runtime-parachains/try-runtime",
 	"sp-runtime/try-runtime",
 ]
+
+experimental-ump-signals = []
diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs
index 21af35fe3de..a4b505b98e5 100644
--- a/cumulus/pallets/parachain-system/src/lib.rs
+++ b/cumulus/pallets/parachain-system/src/lib.rs
@@ -193,20 +193,46 @@ pub mod ump_constants {
 
 /// Trait for selecting the next core to build the candidate for.
 pub trait SelectCore {
-	fn select_core_for_child() -> (CoreSelector, ClaimQueueOffset);
+	/// Core selector information for the current block.
+	fn selected_core() -> (CoreSelector, ClaimQueueOffset);
+	/// Core selector information for the next block.
+	fn select_next_core() -> (CoreSelector, ClaimQueueOffset);
 }
 
 /// The default core selection policy.
 pub struct DefaultCoreSelector<T>(PhantomData<T>);
 
 impl<T: frame_system::Config> SelectCore for DefaultCoreSelector<T> {
-	fn select_core_for_child() -> (CoreSelector, ClaimQueueOffset) {
+	fn selected_core() -> (CoreSelector, ClaimQueueOffset) {
+		let core_selector: U256 = frame_system::Pallet::<T>::block_number().into();
+
+		(CoreSelector(core_selector.byte(0)), ClaimQueueOffset(DEFAULT_CLAIM_QUEUE_OFFSET))
+	}
+
+	fn select_next_core() -> (CoreSelector, ClaimQueueOffset) {
 		let core_selector: U256 = (frame_system::Pallet::<T>::block_number() + One::one()).into();
 
 		(CoreSelector(core_selector.byte(0)), ClaimQueueOffset(DEFAULT_CLAIM_QUEUE_OFFSET))
 	}
 }
 
+/// Core selection policy that builds on claim queue offset 1.
+pub struct LookaheadCoreSelector<T>(PhantomData<T>);
+
+impl<T: frame_system::Config> SelectCore for LookaheadCoreSelector<T> {
+	fn selected_core() -> (CoreSelector, ClaimQueueOffset) {
+		let core_selector: U256 = frame_system::Pallet::<T>::block_number().into();
+
+		(CoreSelector(core_selector.byte(0)), ClaimQueueOffset(1))
+	}
+
+	fn select_next_core() -> (CoreSelector, ClaimQueueOffset) {
+		let core_selector: U256 = (frame_system::Pallet::<T>::block_number() + One::one()).into();
+
+		(CoreSelector(core_selector.byte(0)), ClaimQueueOffset(1))
+	}
+}
+
 #[frame_support::pallet]
 pub mod pallet {
 	use super::*;
@@ -365,6 +391,11 @@ pub mod pallet {
 				UpwardMessages::<T>::put(&up[..num as usize]);
 				*up = up.split_off(num as usize);
 
+				// Send the core selector UMP signal. This is experimental until relay chain
+				// validators are upgraded to handle ump signals.
+				#[cfg(feature = "experimental-ump-signals")]
+				Self::send_ump_signal();
+
 				// If the total size of the pending messages is less than the threshold,
 				// we decrease the fee factor, since the queue is less congested.
 				// This makes delivery of new messages cheaper.
@@ -1397,9 +1428,9 @@ impl<T: Config> Pallet<T> {
 		}
 	}
 
-	/// Returns the core selector.
+	/// Returns the core selector for the next block.
 	pub fn core_selector() -> (CoreSelector, ClaimQueueOffset) {
-		T::SelectCore::select_core_for_child()
+		T::SelectCore::select_next_core()
 	}
 
 	/// Set a custom head data that should be returned as result of `validate_block`.
@@ -1418,6 +1449,20 @@ impl<T: Config> Pallet<T> {
 		CustomValidationHeadData::<T>::put(head_data);
 	}
 
+	/// Send the ump signals
+	#[cfg(feature = "experimental-ump-signals")]
+	fn send_ump_signal() {
+		use cumulus_primitives_core::relay_chain::vstaging::{UMPSignal, UMP_SEPARATOR};
+
+		UpwardMessages::<T>::mutate(|up| {
+			up.push(UMP_SEPARATOR);
+
+			// Send the core selector signal.
+			let core_selector = T::SelectCore::selected_core();
+			up.push(UMPSignal::SelectCore(core_selector.0, core_selector.1).encode());
+		});
+	}
+
 	/// Open HRMP channel for using it in benchmarks or tests.
 	///
 	/// The caller assumes that the pallet will accept regular outbound message to the sibling
diff --git a/cumulus/primitives/core/src/lib.rs b/cumulus/primitives/core/src/lib.rs
index 6bad65b3ff2..dfb574ef330 100644
--- a/cumulus/primitives/core/src/lib.rs
+++ b/cumulus/primitives/core/src/lib.rs
@@ -335,7 +335,7 @@ pub mod rpsr_digest {
 
 /// The default claim queue offset to be used if it's not configured/accessible in the parachain
 /// runtime
-pub const DEFAULT_CLAIM_QUEUE_OFFSET: u8 = 1;
+pub const DEFAULT_CLAIM_QUEUE_OFFSET: u8 = 0;
 
 /// Information about a collation.
 ///
diff --git a/prdoc/pr_5888.prdoc b/prdoc/pr_5888.prdoc
new file mode 100644
index 00000000000..9552eada691
--- /dev/null
+++ b/prdoc/pr_5888.prdoc
@@ -0,0 +1,16 @@
+title: 'parachain-system: send core selector ump signal'
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      Send the core selector ump signal in cumulus. Guarded by a compile time feature called `experimental-ump-signals`
+      until nodes are upgraded to a version that includes https://github.com/paritytech/polkadot-sdk/pull/5423 for
+      gracefully handling ump signals.
+
+crates:
+  - name: cumulus-client-consensus-aura
+    bump: minor
+  - name: cumulus-pallet-parachain-system
+    bump: major
+  - name: cumulus-primitives-core
+    bump: minor
-- 
GitLab