From 8befd605b6a29210cb47c74ed484e90f90ebaaac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sun, 5 Jun 2022 16:21:03 +0200 Subject: [PATCH] Ensure relay chain block number strictly increases (#1280) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Ensure relay chain block number strictly increases This is a safeguard for when async backing is enabled on the relay chain and multiple parachain blocks per relay chain block are legal. We will need to later change this to support then multiple parachain blocks per relay chain block. * Make the check configurable * Fix compilation * Update pallets/parachain-system/src/lib.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Update pallets/parachain-system/src/lib.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Fix test Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> --- pallets/parachain-system/src/lib.rs | 62 ++++++++++++++++++- pallets/parachain-system/src/tests.rs | 20 ++++-- .../src/validate_block/implementation.rs | 4 +- pallets/xcmp-queue/src/mock.rs | 2 + parachain-template/runtime/src/lib.rs | 4 +- .../runtimes/assets/statemine/src/lib.rs | 2 + .../runtimes/assets/statemint/src/lib.rs | 2 + .../runtimes/assets/westmint/src/lib.rs | 4 +- .../contracts/contracts-rococo/src/lib.rs | 2 + .../runtimes/starters/seedling/src/lib.rs | 2 + parachains/runtimes/starters/shell/src/lib.rs | 2 + .../testing/rococo-parachain/src/lib.rs | 2 + test/runtime/src/lib.rs | 1 + 13 files changed, 99 insertions(+), 10 deletions(-) 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! {