diff --git a/primitives/src/vstaging/mod.rs b/primitives/src/vstaging/mod.rs index 64671bd48a60..9f5a99852e37 100644 --- a/primitives/src/vstaging/mod.rs +++ b/primitives/src/vstaging/mod.rs @@ -17,3 +17,26 @@ //! Staging Primitives. // Put any primitives used by staging APIs functions here +pub use crate::v4::*; +use sp_std::prelude::*; + +use parity_scale_codec::{Decode, Encode}; +use primitives::RuntimeDebug; +use scale_info::TypeInfo; + +/// Candidate's acceptance limitations for asynchronous backing per relay parent. +#[derive(RuntimeDebug, Copy, Clone, PartialEq, Encode, Decode, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct AsyncBackingParams { + /// The maximum number of para blocks between the para head in a relay parent + /// and a new candidate. Restricts nodes from building arbitrary long chains + /// and spamming other validators. + /// + /// When async backing is disabled, the only valid value is 0. + pub max_candidate_depth: u32, + /// How many ancestors of a relay parent are allowed to build candidates on top + /// of. + /// + /// When async backing is disabled, the only valid value is 0. + pub allowed_ancestry_len: u32, +} diff --git a/runtime/parachains/src/configuration.rs b/runtime/parachains/src/configuration.rs index 0e8420f51374..b314e47202e9 100644 --- a/runtime/parachains/src/configuration.rs +++ b/runtime/parachains/src/configuration.rs @@ -23,7 +23,10 @@ use frame_support::{pallet_prelude::*, weights::constants::WEIGHT_REF_TIME_PER_M use frame_system::pallet_prelude::*; use parity_scale_codec::{Decode, Encode}; use polkadot_parachain::primitives::{MAX_HORIZONTAL_MESSAGE_NUM, MAX_UPWARD_MESSAGE_NUM}; -use primitives::{Balance, SessionIndex, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE}; +use primitives::{ + vstaging::AsyncBackingParams, Balance, SessionIndex, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, + MAX_POV_SIZE, +}; use sp_runtime::traits::Zero; use sp_std::prelude::*; @@ -118,6 +121,8 @@ pub struct HostConfiguration { * The parameters that are not essential, but still may be of interest for parachains. */ + /// Asynchronous backing parameters. + pub async_backing_params: AsyncBackingParams, /// The maximum POV block size, in bytes. pub max_pov_size: u32, /// The maximum size of a message that can be put in a downward message queue. @@ -243,6 +248,10 @@ pub struct HostConfiguration { impl> Default for HostConfiguration { fn default() -> Self { Self { + async_backing_params: AsyncBackingParams { + max_candidate_depth: 0, + allowed_ancestry_len: 0, + }, group_rotation_frequency: 1u32.into(), chain_availability_period: 1u32.into(), thread_availability_period: 1u32.into(), @@ -1138,6 +1147,22 @@ pub mod pallet { BypassConsistencyCheck::::put(new); Ok(()) } + + /// Set the asynchronous backing parameters. + #[pallet::call_index(45)] + #[pallet::weight(( + T::WeightInfo::set_config_with_option_u32(), // The same size in bytes. + DispatchClass::Operational, + ))] + pub fn set_async_backing_params( + origin: OriginFor, + new: AsyncBackingParams, + ) -> DispatchResult { + ensure_root(origin)?; + Self::schedule_config_update(|config| { + config.async_backing_params = new; + }) + } } #[pallet::hooks] diff --git a/runtime/parachains/src/configuration/migration.rs b/runtime/parachains/src/configuration/migration.rs index f38450a70d40..9f2ebd25c84f 100644 --- a/runtime/parachains/src/configuration/migration.rs +++ b/runtime/parachains/src/configuration/migration.rs @@ -19,6 +19,7 @@ use crate::configuration::{self, ActiveConfig, Config, Pallet, PendingConfigs, MAX_POV_SIZE}; use frame_support::{pallet_prelude::*, traits::StorageVersion, weights::Weight}; use frame_system::pallet_prelude::BlockNumberFor; +use primitives::vstaging::AsyncBackingParams; use sp_std::vec::Vec; /// The current storage version. @@ -27,7 +28,7 @@ use sp_std::vec::Vec; /// v1-v2: /// v2-v3: /// v3-v4: -/// v4-v5: +/// v4-v5: + pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(5); pub mod v5 { @@ -226,6 +227,9 @@ ump_max_individual_weight : pre.ump_max_individual_weight, pvf_checking_enabled : pre.pvf_checking_enabled, pvf_voting_ttl : pre.pvf_voting_ttl, minimum_validation_upgrade_delay : pre.minimum_validation_upgrade_delay, + +// Default values are zeroes, thus it's ensured allowed ancestry never crosses the upgrade block. +async_backing_params : AsyncBackingParams { max_candidate_depth: 0, allowed_ancestry_len: 0 }, } }; @@ -383,6 +387,10 @@ mod tests { assert_eq!(v4.pvf_voting_ttl , v5.pvf_voting_ttl); assert_eq!(v4.minimum_validation_upgrade_delay , v5.minimum_validation_upgrade_delay); }; // ; makes this a statement. `rustfmt::skip` cannot be put on an expression. + + // additional checks for async backing. + assert_eq!(v5.async_backing_params.allowed_ancestry_len, 0); + assert_eq!(v5.async_backing_params.max_candidate_depth, 0); } }); } diff --git a/runtime/parachains/src/configuration/tests.rs b/runtime/parachains/src/configuration/tests.rs index eb29200a12c7..76c46e1f704b 100644 --- a/runtime/parachains/src/configuration/tests.rs +++ b/runtime/parachains/src/configuration/tests.rs @@ -281,6 +281,10 @@ fn consistency_bypass_works() { fn setting_pending_config_members() { new_test_ext(Default::default()).execute_with(|| { let new_config = HostConfiguration { + async_backing_params: primitives::vstaging::AsyncBackingParams { + allowed_ancestry_len: 0, + max_candidate_depth: 0, + }, validation_upgrade_cooldown: 100, validation_upgrade_delay: 10, code_retention_period: 5,