From 3ea497b5a0fdda252f9c5a3c257cfaf8685f02fd Mon Sep 17 00:00:00 2001
From: asynchronous rob <rphmeier@gmail.com>
Date: Tue, 3 Oct 2023 09:23:22 -0500
Subject: [PATCH] expose the last relay chain block number as an API from
 parachain-system (#1761)

re:
https://forum.polkadot.network/t/blocknumber-vs-timestamps-should-we-abandon-blocktimes-altogether/4077

This exposes the `LastRelayChainBlockNumber` storage member of
`cumulus-pallet-parachain-system` with a getter and alters the behavior
of this storage item to only be updated in `on_finalize` to ensure a
consistent value throughout `on_initialize` and within transactions.

Parachains, especially with features such as asynchronous backing and
agile coretime, should not use the parachain block number as a clock.
Any feature of Polkadot intended to optimize core utilization and
parachain coretime consumption is likely to worsen this clock as it is
practically applied.
---
 cumulus/pallets/parachain-system/src/lib.rs | 23 ++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs
index a8f0a49223f..eaf15768e29 100644
--- a/cumulus/pallets/parachain-system/src/lib.rs
+++ b/cumulus/pallets/parachain-system/src/lib.rs
@@ -245,10 +245,10 @@ pub mod pallet {
 			<UpgradeRestrictionSignal<T>>::kill();
 			let relay_upgrade_go_ahead = <UpgradeGoAhead<T>>::take();
 
-			assert!(
-				<ValidationData<T>>::exists(),
-				"set_validation_data inherent needs to be present in every block!"
-			);
+			let vfp = <ValidationData<T>>::get()
+				.expect("set_validation_data inherent needs to be present in every block!");
+
+			LastRelayChainBlockNumber::<T>::put(vfp.relay_parent_number);
 
 			let host_config = match Self::host_configuration() {
 				Some(ok) => ok,
@@ -380,8 +380,7 @@ pub mod pallet {
 				let ancestor = Ancestor::new_unchecked(used_bandwidth, consumed_go_ahead_signal);
 
 				let watermark = HrmpWatermark::<T>::get();
-				let watermark_update =
-					HrmpWatermarkUpdate::new(watermark, LastRelayChainBlockNumber::<T>::get());
+				let watermark_update = HrmpWatermarkUpdate::new(watermark, vfp.relay_parent_number);
 
 				aggregated_segment
 					.append(&ancestor, watermark_update, &total_bandwidth_out)
@@ -460,6 +459,9 @@ pub mod pallet {
 				4 + hrmp_max_message_num_per_candidate as u64,
 			);
 
+			// Weight for updating the last relay chain block number in `on_finalize`.
+			weight += T::DbWeight::get().reads_writes(1, 1);
+
 			// Weight for adjusting the unincluded segment in `on_finalize`.
 			weight += T::DbWeight::get().reads_writes(6, 3);
 
@@ -515,7 +517,6 @@ pub mod pallet {
 				vfp.relay_parent_number,
 				LastRelayChainBlockNumber::<T>::get(),
 			);
-			LastRelayChainBlockNumber::<T>::put(vfp.relay_parent_number);
 
 			let relay_state_proof = RelayChainStateProof::new(
 				T::SelfParaId::get(),
@@ -756,6 +757,8 @@ pub mod pallet {
 	pub(super) type DidSetValidationCode<T: Config> = StorageValue<_, bool, ValueQuery>;
 
 	/// The relay chain block number associated with the last parachain block.
+	///
+	/// This is updated in `on_finalize`.
 	#[pallet::storage]
 	pub(super) type LastRelayChainBlockNumber<T: Config> =
 		StorageValue<_, RelayChainBlockNumber, ValueQuery>;
@@ -1501,6 +1504,12 @@ impl<T: Config> Pallet<T> {
 		Self::deposit_event(Event::UpwardMessageSent { message_hash: Some(hash) });
 		Ok((0, hash))
 	}
+
+	/// Get the relay chain block number which was used as an anchor for the last block in this
+	/// chain.
+	pub fn last_relay_block_number(&self) -> RelayChainBlockNumber {
+		LastRelayChainBlockNumber::<T>::get()
+	}
 }
 
 impl<T: Config> UpwardMessageSender for Pallet<T> {
-- 
GitLab