diff --git a/polkadot/runtime/kusama/src/lib.rs b/polkadot/runtime/kusama/src/lib.rs index b184bfc086..12b6a9d2cb 100644 --- a/polkadot/runtime/kusama/src/lib.rs +++ b/polkadot/runtime/kusama/src/lib.rs @@ -1488,7 +1488,7 @@ construct_runtime! { Configuration: parachains_configuration::{Pallet, Call, Storage, Config} = 51, ParasShared: parachains_shared::{Pallet, Call, Storage} = 52, ParaInclusion: parachains_inclusion::{Pallet, Call, Storage, Event} = 53, - ParasInherent: parachains_paras_inherent::{Pallet, Call, Storage, Inherent} = 54, + ParaInherent: parachains_paras_inherent::{Pallet, Call, Storage, Inherent} = 54, ParaScheduler: parachains_scheduler::{Pallet, Storage} = 55, Paras: parachains_paras::{Pallet, Call, Storage, Event, Config} = 56, Initializer: parachains_initializer::{Pallet, Call, Storage} = 57, diff --git a/polkadot/runtime/parachains/src/disputes.rs b/polkadot/runtime/parachains/src/disputes.rs index a685910514..aad4d11643 100644 --- a/polkadot/runtime/parachains/src/disputes.rs +++ b/polkadot/runtime/parachains/src/disputes.rs @@ -1150,6 +1150,9 @@ mod tests { while System::block_number() < to { let b = System::block_number(); if b != 0 { + // circumvent requirement to have bitfields and headers in block for testing purposes + crate::paras_inherent::Included::::set(Some(())); + AllPallets::on_finalize(b); System::finalize(); } diff --git a/polkadot/runtime/parachains/src/mock.rs b/polkadot/runtime/parachains/src/mock.rs index db51cc3302..642c99f8e1 100644 --- a/polkadot/runtime/parachains/src/mock.rs +++ b/polkadot/runtime/parachains/src/mock.rs @@ -17,8 +17,8 @@ //! Mocks for all the traits. use crate::{ - configuration, disputes, dmp, hrmp, inclusion, initializer, paras, scheduler, session_info, - shared, ump, + configuration, disputes, dmp, hrmp, inclusion, initializer, paras, paras_inherent, scheduler, + session_info, shared, ump, }; use frame_support::{parameter_types, traits::GenesisBuild}; use frame_support_test::TestRandomness; @@ -45,6 +45,7 @@ frame_support::construct_runtime!( Configuration: configuration::{Pallet, Call, Storage, Config}, ParasShared: shared::{Pallet, Call, Storage}, ParaInclusion: inclusion::{Pallet, Call, Storage, Event}, + ParaInherent: paras_inherent::{Pallet, Call, Storage}, Scheduler: scheduler::{Pallet, Storage}, Initializer: initializer::{Pallet, Call, Storage}, Dmp: dmp::{Pallet, Call, Storage}, diff --git a/polkadot/runtime/parachains/src/paras_inherent.rs b/polkadot/runtime/parachains/src/paras_inherent.rs index fba7107e7f..7ca52731bf 100644 --- a/polkadot/runtime/parachains/src/paras_inherent.rs +++ b/polkadot/runtime/parachains/src/paras_inherent.rs @@ -28,20 +28,18 @@ use crate::{ shared, ump, }; use frame_support::{ - decl_error, decl_module, decl_storage, - dispatch::DispatchResultWithPostInfo, - ensure, inherent::{InherentData, InherentIdentifier, MakeFatalError, ProvideInherent}, - traits::Get, - weights::{DispatchClass, Weight}, + pallet_prelude::*, }; -use frame_system::ensure_none; +use frame_system::pallet_prelude::*; use primitives::v1::{ BackedCandidate, InherentData as ParachainsInherentData, PARACHAINS_INHERENT_IDENTIFIER, }; use sp_runtime::traits::Header as HeaderT; use sp_std::prelude::*; +pub use pallet::*; + const LOG_TARGET: &str = "runtime::inclusion-inherent"; // In the future, we should benchmark these consts; these are all untested assumptions for now. const BACKED_CANDIDATE_WEIGHT: Weight = 100_000; @@ -49,22 +47,20 @@ const INCLUSION_INHERENT_CLAIMED_WEIGHT: Weight = 1_000_000_000; // we assume that 75% of an paras inherent's weight is used processing backed candidates const MINIMAL_INCLUSION_INHERENT_WEIGHT: Weight = INCLUSION_INHERENT_CLAIMED_WEIGHT / 4; -pub trait Config: inclusion::Config + scheduler::Config {} +#[frame_support::pallet] +pub mod pallet { + use super::*; -decl_storage! { - trait Store for Module as ParaInherent { - /// Whether the paras inherent was included within this block. - /// - /// The `Option<()>` is effectively a `bool`, but it never hits storage in the `None` variant - /// due to the guarantees of FRAME's storage APIs. - /// - /// If this is `None` at the end of the block, we panic and render the block invalid. - Included: Option<()>; - } -} + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); -decl_error! { - pub enum Error for Module { + #[pallet::config] + #[pallet::disable_frame_system_supertrait_check] + pub trait Config: inclusion::Config + scheduler::Config {} + + #[pallet::error] + pub enum Error { /// Inclusion inherent called more than once per block. TooManyInclusionInherents, /// The hash of the submitted parent header doesn't correspond to the saved block hash of @@ -73,30 +69,89 @@ decl_error! { /// Potentially invalid candidate. CandidateCouldBeInvalid, } -} -decl_module! { - /// The paras inherent module. - pub struct Module for enum Call where origin: ::Origin { - type Error = Error; + /// Whether the paras inherent was included within this block. + /// + /// The `Option<()>` is effectively a `bool`, but it never hits storage in the `None` variant + /// due to the guarantees of FRAME's storage APIs. + /// + /// If this is `None` at the end of the block, we panic and render the block invalid. + #[pallet::storage] + pub(crate) type Included = StorageValue<_, ()>; - fn on_initialize() -> Weight { + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(_: T::BlockNumber) -> Weight { T::DbWeight::get().reads_writes(1, 1) // in on_finalize. } - fn on_finalize() { - if Included::take().is_none() { + fn on_finalize(_: T::BlockNumber) { + if Included::::take().is_none() { panic!("Bitfields and heads must be included every block"); } } + } + #[pallet::inherent] + impl ProvideInherent for Pallet { + type Call = Call; + type Error = MakeFatalError<()>; + const INHERENT_IDENTIFIER: InherentIdentifier = PARACHAINS_INHERENT_IDENTIFIER; + + fn create_inherent(data: &InherentData) -> Option { + let mut inherent_data: ParachainsInherentData = + match data.get_data(&Self::INHERENT_IDENTIFIER) { + Ok(Some(d)) => d, + Ok(None) => return None, + Err(_) => { + log::warn!(target: LOG_TARGET, "ParachainsInherentData failed to decode",); + + return None + }, + }; + + // filter out any unneeded dispute statements + T::DisputesHandler::filter_multi_dispute_data(&mut inherent_data.disputes); + + // Sanity check: session changes can invalidate an inherent, and we _really_ don't want that to happen. + // See github.com/paritytech/polkadot/issues/1327 + let inherent_data = + match Self::enter(frame_system::RawOrigin::None.into(), inherent_data.clone()) { + Ok(_) => inherent_data, + Err(err) => { + log::warn!( + target: LOG_TARGET, + "dropping signed_bitfields and backed_candidates because they produced \ + an invalid paras inherent: {:?}", + err, + ); + + ParachainsInherentData { + bitfields: Vec::new(), + backed_candidates: Vec::new(), + disputes: Vec::new(), + parent_header: inherent_data.parent_header, + } + }, + }; + + Some(Call::enter(inherent_data)) + } + + fn is_inherent(call: &Self::Call) -> bool { + matches!(call, Call::enter(..)) + } + } + + #[pallet::call] + impl Pallet { /// Enter the paras inherent. This will process bitfields and backed candidates. - #[weight = ( + #[pallet::weight(( MINIMAL_INCLUSION_INHERENT_WEIGHT + data.backed_candidates.len() as Weight * BACKED_CANDIDATE_WEIGHT, DispatchClass::Mandatory, - )] + ))] pub fn enter( - origin, + origin: OriginFor, data: ParachainsInherentData, ) -> DispatchResultWithPostInfo { let ParachainsInherentData { @@ -107,7 +162,7 @@ decl_module! { } = data; ensure_none(origin)?; - ensure!(!::exists(), Error::::TooManyInclusionInherents); + ensure!(!Included::::exists(), Error::::TooManyInclusionInherents); // Check that the submitted parent header indeed corresponds to the previous block hash. let parent_hash = >::parent_hash(); @@ -122,17 +177,16 @@ decl_module! { let fresh_disputes = T::DisputesHandler::provide_multi_dispute_data(disputes)?; if T::DisputesHandler::is_frozen() { // The relay chain we are currently on is invalid. Proceed no further on parachains. - Included::set(Some(())); - return Ok(Some( - MINIMAL_INCLUSION_INHERENT_WEIGHT - ).into()); + Included::::set(Some(())); + return Ok(Some(MINIMAL_INCLUSION_INHERENT_WEIGHT).into()) } - let any_current_session_disputes = fresh_disputes.iter() - .any(|(s, _)| s == ¤t_session); + let any_current_session_disputes = + fresh_disputes.iter().any(|(s, _)| s == ¤t_session); if any_current_session_disputes { - let current_session_disputes: Vec<_> = fresh_disputes.iter() + let current_session_disputes: Vec<_> = fresh_disputes + .iter() .filter(|(s, _)| s == ¤t_session) .map(|(_, c)| *c) .collect(); @@ -170,7 +224,8 @@ decl_module! { }; // Schedule paras again, given freed cores, and reasons for freeing. - let mut freed = freed_disputed.into_iter() + let mut freed = freed_disputed + .into_iter() .chain(freed_concluded.into_iter().map(|(c, _hash)| (c, FreedReason::Concluded))) .chain(freed_timeout.into_iter().map(|c| (c, FreedReason::TimedOut))) .collect::>(); @@ -178,10 +233,7 @@ decl_module! { freed.sort_unstable_by_key(|pair| pair.0); // sort by core index >::clear(); - >::schedule( - freed, - >::block_number(), - ); + >::schedule(freed, >::block_number()); let backed_candidates = limit_backed_candidates::(backed_candidates); let backed_candidates_len = backed_candidates.len() as Weight; @@ -213,12 +265,13 @@ decl_module! { >::process_pending_upward_messages(); // And track that we've finished processing the inherent for this block. - Included::set(Some(())); + Included::::set(Some(())); Ok(Some( MINIMAL_INCLUSION_INHERENT_WEIGHT + - (backed_candidates_len * BACKED_CANDIDATE_WEIGHT) - ).into()) + (backed_candidates_len * BACKED_CANDIDATE_WEIGHT), + ) + .into()) } } } @@ -267,56 +320,6 @@ fn limit_backed_candidates( } } -impl ProvideInherent for Module { - type Call = Call; - type Error = MakeFatalError<()>; - const INHERENT_IDENTIFIER: InherentIdentifier = PARACHAINS_INHERENT_IDENTIFIER; - - fn create_inherent(data: &InherentData) -> Option { - let mut inherent_data: ParachainsInherentData = - match data.get_data(&Self::INHERENT_IDENTIFIER) { - Ok(Some(d)) => d, - Ok(None) => return None, - Err(_) => { - log::warn!(target: LOG_TARGET, "ParachainsInherentData failed to decode",); - - return None - }, - }; - - // filter out any unneeded dispute statements - T::DisputesHandler::filter_multi_dispute_data(&mut inherent_data.disputes); - - // Sanity check: session changes can invalidate an inherent, and we _really_ don't want that to happen. - // See github.com/paritytech/polkadot/issues/1327 - let inherent_data = - match Self::enter(frame_system::RawOrigin::None.into(), inherent_data.clone()) { - Ok(_) => inherent_data, - Err(err) => { - log::warn!( - target: LOG_TARGET, - "dropping signed_bitfields and backed_candidates because they produced \ - an invalid paras inherent: {:?}", - err, - ); - - ParachainsInherentData { - bitfields: Vec::new(), - backed_candidates: Vec::new(), - disputes: Vec::new(), - parent_header: inherent_data.parent_header, - } - }, - }; - - Some(Call::enter(inherent_data)) - } - - fn is_inherent(call: &Self::Call) -> bool { - matches!(call, Call::enter(..)) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 10556b1f1b..d440eba364 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -213,7 +213,7 @@ construct_runtime! { Configuration: parachains_configuration::{Pallet, Call, Storage, Config}, ParasShared: parachains_shared::{Pallet, Call, Storage}, ParaInclusion: parachains_inclusion::{Pallet, Call, Storage, Event}, - ParasInherent: parachains_paras_inherent::{Pallet, Call, Storage, Inherent}, + ParaInherent: parachains_paras_inherent::{Pallet, Call, Storage, Inherent}, ParaScheduler: parachains_scheduler::{Pallet, Storage}, Paras: parachains_paras::{Pallet, Call, Storage, Event, Config}, Initializer: parachains_initializer::{Pallet, Call, Storage}, diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs index 704cdc20b6..762f89b637 100644 --- a/polkadot/runtime/test-runtime/src/lib.rs +++ b/polkadot/runtime/test-runtime/src/lib.rs @@ -531,7 +531,7 @@ construct_runtime! { // Parachains runtime modules Configuration: parachains_configuration::{Pallet, Call, Storage, Config}, ParaInclusion: parachains_inclusion::{Pallet, Call, Storage, Event}, - ParasInherent: parachains_paras_inherent::{Pallet, Call, Storage, Inherent}, + ParaInherent: parachains_paras_inherent::{Pallet, Call, Storage, Inherent}, Initializer: parachains_initializer::{Pallet, Call, Storage}, Paras: parachains_paras::{Pallet, Call, Storage, Origin, Event}, ParasShared: parachains_shared::{Pallet, Call, Storage}, diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 79e38f5539..4fc28eeada 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -1071,7 +1071,7 @@ construct_runtime! { Configuration: parachains_configuration::{Pallet, Call, Storage, Config} = 42, ParasShared: parachains_shared::{Pallet, Call, Storage} = 43, ParaInclusion: parachains_inclusion::{Pallet, Call, Storage, Event} = 44, - ParasInherent: parachains_paras_inherent::{Pallet, Call, Storage, Inherent} = 45, + ParaInherent: parachains_paras_inherent::{Pallet, Call, Storage, Inherent} = 45, ParaScheduler: parachains_scheduler::{Pallet, Storage} = 46, Paras: parachains_paras::{Pallet, Call, Storage, Event, Config} = 47, Initializer: parachains_initializer::{Pallet, Call, Storage} = 48,