diff --git a/pallets/parachain-system/src/lib.rs b/pallets/parachain-system/src/lib.rs index abb78adbf7b..b42453401a0 100644 --- a/pallets/parachain-system/src/lib.rs +++ b/pallets/parachain-system/src/lib.rs @@ -88,6 +88,51 @@ pub use relay_state_snapshot::{MessagingStateSnapshot, RelayChainStateProof}; pub use pallet::*; +/// Something that can check the associated relay block number. +/// +/// Each Parachain block is built in the context of a relay chain block, this trait allows us +/// to validate the given relay chain block number. With async backing it is legal to build +/// multiple Parachain blocks per relay chain parent. With this trait it is possible for the +/// Parachain to ensure that still only one Parachain block is build per relay chain parent. +/// +/// By default [`RelayNumberStrictlyIncreases`] and [`AnyRelayNumber`] are provided. +pub trait CheckAssociatedRelayNumber { + /// Check the current relay number versus the previous relay number. + /// + /// The implementation should panic when there is something wrong. + fn check_associated_relay_number( + current: RelayChainBlockNumber, + previous: RelayChainBlockNumber, + ); +} + +/// Provides an implementation of [`CheckAssociatedRelayNumber`]. +/// +/// It will ensure that the associated relay block number strictly increases between Parachain +/// blocks. This should be used by production Parachains when in doubt. +pub struct RelayNumberStrictlyIncreases; + +impl CheckAssociatedRelayNumber for RelayNumberStrictlyIncreases { + fn check_associated_relay_number( + current: RelayChainBlockNumber, + previous: RelayChainBlockNumber, + ) { + if current <= previous { + panic!("Relay chain block number needs to strictly increase between Parachain blocks!") + } + } +} + +/// Provides an implementation of [`CheckAssociatedRelayNumber`]. +/// +/// This will accept any relay chain block number combination. This is mainly useful for +/// test parachains. +pub struct AnyRelayNumber; + +impl CheckAssociatedRelayNumber for AnyRelayNumber { + fn check_associated_relay_number(_: RelayChainBlockNumber, _: RelayChainBlockNumber) {} +} + #[frame_support::pallet] pub mod pallet { use super::*; @@ -128,6 +173,9 @@ pub mod pallet { /// The weight we reserve at the beginning of the block for processing XCMP messages. type ReservedXcmpWeight: Get; + + /// Something that can check the associated relay parent block number. + type CheckAssociatedRelayNumber: CheckAssociatedRelayNumber; } #[pallet::hooks] @@ -232,7 +280,7 @@ pub mod pallet { } // Remove the validation from the old block. - >::kill(); + ValidationData::::kill(); ProcessedDownwardMessages::::kill(); HrmpWatermark::::kill(); UpwardMessages::::kill(); @@ -307,6 +355,13 @@ pub mod pallet { Self::validate_validation_data(&vfp); + // Check that the associated relay chain block number is as expected. + T::CheckAssociatedRelayNumber::check_associated_relay_number( + vfp.relay_parent_number, + LastRelayChainBlockNumber::::get(), + ); + LastRelayChainBlockNumber::::put(vfp.relay_parent_number); + let relay_state_proof = RelayChainStateProof::new( T::SelfParaId::get(), vfp.relay_parent_storage_root, @@ -474,6 +529,11 @@ pub mod pallet { #[pallet::storage] pub(super) type DidSetValidationCode = StorageValue<_, bool, ValueQuery>; + /// The relay chain block number associated with the last parachain block. + #[pallet::storage] + pub(super) type LastRelayChainBlockNumber = + StorageValue<_, RelayChainBlockNumber, ValueQuery>; + /// An option which indicates if the relay-chain restricts signalling a validation code upgrade. /// In other words, if this is `Some` and [`NewValidationCode`] is `Some` then the produced /// candidate will be invalid. diff --git a/pallets/parachain-system/src/tests.rs b/pallets/parachain-system/src/tests.rs index 0f7ac4b1984..65896fa9b29 100755 --- a/pallets/parachain-system/src/tests.rs +++ b/pallets/parachain-system/src/tests.rs @@ -107,6 +107,7 @@ impl Config for Test { type ReservedDmpWeight = ReservedDmpWeight; type XcmpMessageHandler = SaveIntoThreadLocal; type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; } pub struct FromThreadLocal; @@ -226,8 +227,7 @@ struct BlockTests { ran: bool, relay_sproof_builder_hook: Option>, - persisted_validation_data_hook: - Option>, + persisted_validation_data_hook: Option>, inherent_data_hook: Option>, } @@ -274,10 +274,9 @@ impl BlockTests { self } - #[allow(dead_code)] // might come in handy in future. If now is future and it still hasn't - feel free. fn with_validation_data(mut self, f: F) -> Self where - F: 'static + Fn(&BlockTests, RelayChainBlockNumber, &mut PersistedValidationData), + F: 'static + Fn(&BlockTests, &mut PersistedValidationData), { self.persisted_validation_data_hook = Some(Box::new(f)); self @@ -319,7 +318,7 @@ impl BlockTests { ..Default::default() }; if let Some(ref hook) = self.persisted_validation_data_hook { - hook(self, *n as RelayChainBlockNumber, &mut vfp); + hook(self, &mut vfp); } >::put(&vfp); @@ -964,3 +963,14 @@ fn receive_hrmp_after_pause() { }); }); } + +#[test] +#[should_panic = "Relay chain block number needs to strictly increase between Parachain blocks!"] +fn test() { + BlockTests::new() + .with_validation_data(|_, data| { + data.relay_parent_number = 1; + }) + .add(1, || {}) + .add(2, || {}); +} diff --git a/pallets/parachain-system/src/validate_block/implementation.rs b/pallets/parachain-system/src/validate_block/implementation.rs index 7ef3d81a545..ae361d84811 100644 --- a/pallets/parachain-system/src/validate_block/implementation.rs +++ b/pallets/parachain-system/src/validate_block/implementation.rs @@ -67,8 +67,8 @@ where assert!(parent_head.hash() == *block.header().parent_hash(), "Invalid parent hash",); // Create the db - let (db, root) = match storage_proof.to_memory_db(Some(parent_head.state_root())) { - Ok((db, root)) => (db, root), + let db = match storage_proof.to_memory_db(Some(parent_head.state_root())) { + Ok((db, _)) => db, Err(_) => panic!("Compact proof decoding failure."), }; diff --git a/pallets/xcmp-queue/src/mock.rs b/pallets/xcmp-queue/src/mock.rs index 1a3b5616db6..60aff179b82 100644 --- a/pallets/xcmp-queue/src/mock.rs +++ b/pallets/xcmp-queue/src/mock.rs @@ -16,6 +16,7 @@ use super::*; use crate as xcmp_queue; use core::marker::PhantomData; +use cumulus_pallet_parachain_system::AnyRelayNumber; use cumulus_primitives_core::{IsSystem, ParaId}; use frame_support::{parameter_types, traits::OriginTrait}; use frame_system::EnsureRoot; @@ -109,6 +110,7 @@ impl cumulus_pallet_parachain_system::Config for Test { type ReservedDmpWeight = (); type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = (); + type CheckAssociatedRelayNumber = AnyRelayNumber; } parameter_types! { diff --git a/parachain-template/runtime/src/lib.rs b/parachain-template/runtime/src/lib.rs index 887de0b010d..7429b832c91 100644 --- a/parachain-template/runtime/src/lib.rs +++ b/parachain-template/runtime/src/lib.rs @@ -9,6 +9,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); mod weights; pub mod xcm_config; +use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use smallvec::smallvec; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; @@ -369,11 +370,12 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type Event = Event; type OnSystemEvent = (); type SelfParaId = parachain_info::Pallet; + type OutboundXcmpMessageSource = XcmpQueue; type DmpMessageHandler = DmpQueue; type ReservedDmpWeight = ReservedDmpWeight; - type OutboundXcmpMessageSource = XcmpQueue; type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; } impl parachain_info::Config for Runtime {} diff --git a/parachains/runtimes/assets/statemine/src/lib.rs b/parachains/runtimes/assets/statemine/src/lib.rs index e9a279a9604..b9e739934cb 100644 --- a/parachains/runtimes/assets/statemine/src/lib.rs +++ b/parachains/runtimes/assets/statemine/src/lib.rs @@ -28,6 +28,7 @@ pub mod constants; mod weights; pub mod xcm_config; +use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ @@ -416,6 +417,7 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type OutboundXcmpMessageSource = XcmpQueue; type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; } impl parachain_info::Config for Runtime {} diff --git a/parachains/runtimes/assets/statemint/src/lib.rs b/parachains/runtimes/assets/statemint/src/lib.rs index 2f229aa560f..cebdce87011 100644 --- a/parachains/runtimes/assets/statemint/src/lib.rs +++ b/parachains/runtimes/assets/statemint/src/lib.rs @@ -57,6 +57,7 @@ pub mod constants; mod weights; pub mod xcm_config; +use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ @@ -446,6 +447,7 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type OutboundXcmpMessageSource = XcmpQueue; type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; } impl parachain_info::Config for Runtime {} diff --git a/parachains/runtimes/assets/westmint/src/lib.rs b/parachains/runtimes/assets/westmint/src/lib.rs index 14f5bead6cd..44293376f04 100644 --- a/parachains/runtimes/assets/westmint/src/lib.rs +++ b/parachains/runtimes/assets/westmint/src/lib.rs @@ -28,6 +28,7 @@ pub mod constants; mod weights; pub mod xcm_config; +use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ @@ -406,11 +407,12 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type Event = Event; type OnSystemEvent = (); type SelfParaId = parachain_info::Pallet; + type OutboundXcmpMessageSource = XcmpQueue; type DmpMessageHandler = DmpQueue; type ReservedDmpWeight = ReservedDmpWeight; - type OutboundXcmpMessageSource = XcmpQueue; type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; } impl parachain_info::Config for Runtime {} diff --git a/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index eb0813a75ec..b6d28cf81bf 100644 --- a/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -30,6 +30,7 @@ mod contracts; mod weights; mod xcm_config; +use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ @@ -252,6 +253,7 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type OutboundXcmpMessageSource = XcmpQueue; type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ConstU64<{ MAXIMUM_BLOCK_WEIGHT / 4 }>; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; } impl pallet_randomness_collective_flip::Config for Runtime {} diff --git a/parachains/runtimes/starters/seedling/src/lib.rs b/parachains/runtimes/starters/seedling/src/lib.rs index 58071e1acb1..146a769fd5a 100644 --- a/parachains/runtimes/starters/seedling/src/lib.rs +++ b/parachains/runtimes/starters/seedling/src/lib.rs @@ -27,6 +27,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use sp_api::impl_runtime_apis; use sp_core::OpaqueMetadata; use sp_runtime::{ @@ -166,6 +167,7 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type ReservedDmpWeight = (); type XcmpMessageHandler = (); type ReservedXcmpWeight = (); + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; } impl parachain_info::Config for Runtime {} diff --git a/parachains/runtimes/starters/shell/src/lib.rs b/parachains/runtimes/starters/shell/src/lib.rs index 787d72816aa..d08cebe47e0 100644 --- a/parachains/runtimes/starters/shell/src/lib.rs +++ b/parachains/runtimes/starters/shell/src/lib.rs @@ -32,6 +32,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod xcm_config; use codec::{Decode, Encode}; +use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use frame_support::unsigned::TransactionValidityError; use scale_info::TypeInfo; use sp_api::impl_runtime_apis; @@ -170,6 +171,7 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type ReservedDmpWeight = ReservedDmpWeight; type XcmpMessageHandler = (); type ReservedXcmpWeight = (); + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; } impl parachain_info::Config for Runtime {} diff --git a/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 837632b67fe..6fd21f98cec 100644 --- a/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -22,6 +22,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use sp_api::impl_runtime_apis; use sp_core::OpaqueMetadata; use sp_runtime::{ @@ -265,6 +266,7 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type ReservedDmpWeight = ReservedDmpWeight; type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; } impl parachain_info::Config for Runtime {} diff --git a/test/runtime/src/lib.rs b/test/runtime/src/lib.rs index bfa8db32899..a28855bace8 100644 --- a/test/runtime/src/lib.rs +++ b/test/runtime/src/lib.rs @@ -265,6 +265,7 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type ReservedDmpWeight = (); type XcmpMessageHandler = (); type ReservedXcmpWeight = (); + type CheckAssociatedRelayNumber = cumulus_pallet_parachain_system::AnyRelayNumber; } parameter_types! {