From 72f206567fb688823f5b714dd1e1d9ba651b1b4c Mon Sep 17 00:00:00 2001 From: kianenigma Date: Fri, 8 Nov 2019 22:30:39 +0100 Subject: [PATCH 1/4] Initial version that works with proper tests. --- Cargo.lock | 2 + core/sr-primitives/Cargo.toml | 2 + core/sr-primitives/src/generic/header.rs | 11 + .../src/generic/unchecked_extrinsic.rs | 3 + core/sr-primitives/src/testing.rs | 12 +- core/sr-primitives/src/weights.rs | 39 +++- node/runtime/src/lib.rs | 29 +++ srml/example/src/lib.rs | 6 +- srml/executive/Cargo.toml | 2 +- srml/executive/src/lib.rs | 190 +++++++++++++++++- srml/support/src/dispatch.rs | 135 ++++++++++++- srml/system/src/lib.rs | 23 +++ 12 files changed, 439 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7385fd7a5fd9..a1db614b11d74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4278,6 +4278,8 @@ dependencies = [ "sr-arithmetic 2.0.0", "sr-io 2.0.0", "sr-std 2.0.0", + "srml-support 2.0.0", + "srml-system 2.0.0", "substrate-application-crypto 2.0.0", "substrate-offchain 2.0.0", "substrate-primitives 2.0.0", diff --git a/core/sr-primitives/Cargo.toml b/core/sr-primitives/Cargo.toml index 1b1434b91930d..4339b4af932ca 100644 --- a/core/sr-primitives/Cargo.toml +++ b/core/sr-primitives/Cargo.toml @@ -21,6 +21,8 @@ impl-trait-for-tuples = "0.1.3" serde_json = "1.0.41" rand = "0.7.2" substrate-offchain = { path = "../offchain" } +support = { package = "srml-support", path = "../../srml/support" } +system = { package = "srml-system", path = "../../srml/system" } [features] bench = [] diff --git a/core/sr-primitives/src/generic/header.rs b/core/sr-primitives/src/generic/header.rs index 75994749c572e..5220c11a5b023 100644 --- a/core/sr-primitives/src/generic/header.rs +++ b/core/sr-primitives/src/generic/header.rs @@ -163,6 +163,17 @@ impl Header where } } +#[cfg(all(test, feature = "std"))] +impl Header where Self::Hash: Default { + /// A new header with the given number and default hash for all other fields. + pub fn new_from_number(number: ::Number) -> Self { + Self { + number, + ..Default::default() + } + } +} + #[cfg(all(test, feature = "std"))] mod tests { use super::*; diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index befa857dffd64..c703b4c90930a 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -92,6 +92,9 @@ impl Extrinsic } } + +pub trait Marker {} + impl Checkable for diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index b1bd94a5461b1..6a1ee738d6aea 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -145,7 +145,7 @@ pub type DigestItem = generic::DigestItem; pub type Digest = generic::Digest; /// Block Header -#[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode, Default)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] pub struct Header { @@ -198,6 +198,16 @@ impl traits::Header for Header { } } +impl Header { + /// A new header with the given number and default hash for all other fields. + pub fn new_from_number(number: ::Number) -> Self { + Self { + number, + ..Default::default() + } + } +} + impl<'a> Deserialize<'a> for Header { fn deserialize>(de: D) -> Result { let r = >::deserialize(de)?; diff --git a/core/sr-primitives/src/weights.rs b/core/sr-primitives/src/weights.rs index 088f13244eb31..fcca937b7d642 100644 --- a/core/sr-primitives/src/weights.rs +++ b/core/sr-primitives/src/weights.rs @@ -37,8 +37,9 @@ #[cfg(feature = "std")] use serde::{Serialize, Deserialize}; +use impl_trait_for_tuples::impl_for_tuples; use codec::{Encode, Decode}; -use arithmetic::traits::Bounded; +use arithmetic::traits::{Bounded, Zero}; use crate::RuntimeDebug; /// Re-export priority as type @@ -62,6 +63,35 @@ pub trait ClassifyDispatch { fn classify_dispatch(&self, target: T) -> DispatchClass; } +/// Means of determining the weight of a block's lifecycle hooks: on_initialize, on_finalize and +/// such. +pub trait WeighBlock { + /// Return the weight of the block's on_initialize hook. + fn on_initialize() -> Weight { Zero::zero() } + /// Return the weight of the block's on_finalize hook. + fn on_finalize() -> Weight { Zero::zero() } +} + +/// Maybe I can do something to remove the duplicate code here. +#[impl_for_tuples(5)] +impl WeighBlock for SingleModule { + fn on_initialize() -> Weight { + let mut accumulated_weight: Weight = Zero::zero(); + for_tuples!( + #( accumulated_weight = accumulated_weight.saturating_add(SingleModule::on_initialize()); )* + ); + accumulated_weight + } + + fn on_finalize() -> Weight { + let mut accumulated_weight: Weight = Zero::zero(); + for_tuples!( + #( accumulated_weight = accumulated_weight.saturating_add(SingleModule::on_finalize()); )* + ); + accumulated_weight + } +} + /// A generalized group of dispatch types. This is only distinguishing normal, user-triggered transactions /// (`Normal`) and anything beyond which serves a higher purpose to the system (`Operational`). #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -181,3 +211,10 @@ impl Default for SimpleDispatchInfo { SimpleDispatchInfo::FixedNormal(10_000) } } + +impl SimpleDispatchInfo { + /// An _additive zero_ variant of SimpleDispatchInfo. + pub fn zero() -> Self { + Self::FixedNormal(0) + } +} diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index dfed5b4678bc6..315e10df8dd31 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -699,6 +699,7 @@ impl_runtime_apis! { } } } + #[cfg(test)] mod tests { use super::*; @@ -719,4 +720,32 @@ mod tests { let x = SubmitTransaction::default(); is_submit_signed_transaction(x); } + + #[test] + fn block_hooks_weight_should_not_exceed_limits() { + use sr_primitives::weights::WeighBlock; + let block_hooks_weight = + ::on_initialize() + ::on_finalize(); + + assert_eq!( + block_hooks_weight, + 0, + "This test might fail simply because the value being compared to has increased to a \ + module declaring a new weight for a hook or call. In this case update the test and \ + happily move on.", + ); + + // Invariant. Always must be like this to have a sane chain. + // TODO: Maybe add a post-create function for all module that check this stuff. + assert!(block_hooks_weight < MaximumBlockWeight::get()); + + // Warning. + if block_hooks_weight > MaximumBlockWeight::get() / 2 { + println!( + "lock hooks weight is consuming more than a block's capacity. You probably want to \ + re-think this. This test will fail now." + ); + assert!(false); + } + } } diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs index fb05e731bdd4d..731143162161b 100644 --- a/srml/example/src/lib.rs +++ b/srml/example/src/lib.rs @@ -498,13 +498,17 @@ decl_module! { >::put(new_value); } - // The signature could also look like: `fn on_initialize()` + // The signature could also look like: `fn on_initialize()`. + // This function could also very well have a weight annotation, similar to any other. The + // only difference being the default value. + #[weight = SimpleDispatchInfo::FixedNormal(1000)] fn on_initialize(_n: T::BlockNumber) { // Anything that needs to be done at the start of the block. // We don't do anything here. } // The signature could also look like: `fn on_finalize()` + #[weight = SimpleDispatchInfo::FixedNormal(2000)] fn on_finalize(_n: T::BlockNumber) { // Anything that needs to be done at the end of the block. // We just kill our dummy storage item. diff --git a/srml/executive/Cargo.toml b/srml/executive/Cargo.toml index 92191a7aac4db..f184ae981b856 100644 --- a/srml/executive/Cargo.toml +++ b/srml/executive/Cargo.toml @@ -16,8 +16,8 @@ system = { package = "srml-system", path = "../system", default-features = false [dev-dependencies] hex-literal = "0.2.1" primitives = { package = "substrate-primitives", path = "../../core/primitives" } -srml-indices = { path = "../indices" } balances = { package = "srml-balances", path = "../balances" } +indices = { package = "srml-indices", path = "../indices" } transaction-payment = { package = "srml-transaction-payment", path = "../transaction-payment" } [features] diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 146e0ebcadcd8..92f990f7d0223 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -78,7 +78,8 @@ use rstd::{prelude::*, marker::PhantomData}; use sr_primitives::{ - generic::Digest, ApplyResult, weights::GetDispatchInfo, + generic::Digest, ApplyResult, + weights::{GetDispatchInfo, WeighBlock}, traits::{ self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, OnInitialize, NumberFor, Block as BlockT, OffchainWorker, Dispatchable, @@ -110,7 +111,7 @@ impl< Block: traits::Block, Context: Default, UnsignedValidator, - AllModules: OnInitialize + OnFinalize + OffchainWorker, + AllModules: OnInitialize + OnFinalize + OffchainWorker + WeighBlock, > ExecuteBlock for Executive where Block::Extrinsic: Checkable + Codec, @@ -130,7 +131,7 @@ impl< Block: traits::Block, Context: Default, UnsignedValidator, - AllModules: OnInitialize + OnFinalize + OffchainWorker, + AllModules: OnInitialize + OnFinalize + OffchainWorker + WeighBlock, > Executive where Block::Extrinsic: Checkable + Codec, @@ -154,6 +155,10 @@ where ) { >::initialize(block_number, parent_hash, extrinsics_root, digest); >::on_initialize(*block_number); + // TODO: so what if we already know that we are fucked here? Maybe call it unchecked for now + // TODO: add block number as parameter. + >::register_extra_weight(::on_initialize()); + >::register_extra_weight(::on_finalize()); } fn initial_checks(block: &Block) { @@ -309,12 +314,48 @@ mod tests { impl_outer_event, impl_outer_origin, parameter_types, impl_outer_dispatch, traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons, WithdrawReason}, }; - use system::Call as SystemCall; + use system::{Call as SystemCall, ChainContext}; use balances::Call as BalancesCall; use hex_literal::hex; + mod custom { + use sr_primitives::weights::SimpleDispatchInfo; + + pub trait Trait: system::Trait {} + + support::decl_module! { + pub struct Module for enum Call where origin: T::Origin { + #[weight = SimpleDispatchInfo::FixedNormal(100)] + fn some_function(origin) { + // NOTE: does not make any different. + let _ = system::ensure_signed(origin); + } + #[weight = SimpleDispatchInfo::FixedOperational(200)] + fn some_root_operation(origin) { + let _ = system::ensure_root(origin); + } + #[weight = SimpleDispatchInfo::FreeNormal] + fn some_unsigned_message(origin) { + let _ = system::ensure_none(origin); + } + + // module hooks. + // one with block number arg and one without + #[weight = SimpleDispatchInfo::FixedNormal(25)] + fn on_initialize(n: T::BlockNumber) { + println!("on_initialize({})", n); + } + #[weight = SimpleDispatchInfo::FixedNormal(150)] + fn on_finalize() { + println!("on_finalize(?)"); + } + } + } + } + type System = system::Module; type Balances = balances::Module; + type Custom = custom::Module; impl_outer_origin! { pub enum Origin for Runtime { } @@ -386,6 +427,7 @@ mod tests { type WeightToFee = ConvertInto; type FeeMultiplierUpdate = (); } + impl custom::Trait for Runtime {} #[allow(deprecated)] impl ValidateUnsigned for Runtime { @@ -409,8 +451,9 @@ mod tests { system::CheckWeight, transaction_payment::ChargeTransactionPayment ); + type AllModules = (System, Balances, Custom); type TestXt = sr_primitives::testing::TestXt; - type Executive = super::Executive, system::ChainContext, Runtime, ()>; + type Executive = super::Executive, ChainContext, Runtime, AllModules>; fn extra(nonce: u64, fee: u64) -> SignedExtra { ( @@ -534,7 +577,7 @@ mod tests { let xt = sr_primitives::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(33, 0))); let encoded = xt.encode(); let encoded_len = encoded.len() as Weight; - let limit = AvailableBlockRatio::get() * MaximumBlockWeight::get(); + let limit = AvailableBlockRatio::get() * MaximumBlockWeight::get() - 175; let num_to_exhaust_block = limit / encoded_len; t.execute_with(|| { Executive::initialize_block(&Header::new( @@ -544,7 +587,8 @@ mod tests { [69u8; 32].into(), Digest::default(), )); - assert_eq!(>::all_extrinsics_weight(), 0); + // Initial block weight form the custom module. + assert_eq!(>::all_extrinsics_weight(), 175); for nonce in 0..=num_to_exhaust_block { let xt = sr_primitives::testing::TestXt( @@ -555,7 +599,7 @@ mod tests { assert!(res.is_ok()); assert_eq!( >::all_extrinsics_weight(), - encoded_len * (nonce + 1), + encoded_len * (nonce + 1) + 175, ); assert_eq!(>::extrinsic_index(), Some(nonce as u32 + 1)); } else { @@ -652,4 +696,134 @@ mod tests { execute_with_lock(WithdrawReasons::all()); execute_with_lock(WithdrawReasons::except(WithdrawReason::TransactionPayment)); } + + #[test] + fn block_hooks_weight_is_stored() { + new_test_ext(0).execute_with(|| { + + Executive::initialize_block(&Header::new_from_number(1)); + // NOTE: might need updates over time if system and balance introduce new weights. For + // now only accounts for the custom module. + assert_eq!(>::all_extrinsics_weight(), 150 + 25); + }) + } +} + +#[cfg(test)] +mod tests_weights { + use codec::{Encode, Decode, EncodeLike, Codec}; + use sr_primitives::traits::{BlakeTwo256, IdentityLookup, Verify, StaticLookup}; + use sr_primitives::{Perbill, transaction_validity::TransactionValidityError, generic, testing}; + use system::ChainContext; + use super::*; + + mod custom { + use sr_primitives::weights::SimpleDispatchInfo; + + pub trait Trait: system::Trait {} + + support::decl_module! { + pub struct Module for enum Call where origin: T::Origin { + #[weight = SimpleDispatchInfo::FixedNormal(100)] + fn some_function(origin) { + // NOTE: does not make any different. + let _ = system::ensure_signed(origin); + } + #[weight = SimpleDispatchInfo::FixedOperational(200)] + fn some_root_operation(origin) { + let _ = system::ensure_root(origin); + } + #[weight = SimpleDispatchInfo::FreeNormal] + fn some_unsigned_message(origin) { + let _ = system::ensure_none(origin); + } + + // module hooks. + // one with block number arg and one without + #[weight = SimpleDispatchInfo::FixedNormal(50)] + fn on_initialize(n: T::BlockNumber) { + println!("on_initialize({})", n); + } + #[weight = SimpleDispatchInfo::FixedNormal(150)] + fn on_finalize() { + println!("on_finalize(?)"); + } + } + } + } + + support::parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl system::Trait for Runtime { + type Hash = primitives::H256; + type Origin = Origin; + type BlockNumber = u64; + type AccountId = AccountId; + type Hashing = HashT; + type Index = u64; + type Call = Call; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + } + impl indices::Trait for Runtime { + type AccountIndex = u32; + type IsDeadAccount = (); + type ResolveHint = indices::SimpleResolveHint; + type Event = (); + } + impl custom::Trait for Runtime {} + + // impl Checkable for UncheckedExtrinsic { + // type Checked = Self; + // fn check(self, _: &Context) -> Result { Ok(self) } + // } + + type HashT = BlakeTwo256; + type Address = ::Source; + type Signature = primitives::sr25519::Signature; + type AccountId = ::Signer; + // type AccountId = u64; + type UncheckedExtrinsic = generic::UncheckedExtrinsic; + // type Header = testing::Header; + // type Block = testing::Block; + type Header = generic::Header; + type Block = generic::Block; + type Executive = super::Executive, Runtime, AllModules>; + + support::construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Module, Call, Event}, + Indices: indices::{Module, Call}, + Custom: custom::{Module, Call}, + } + ); + + fn new_test_ext() -> runtime_io::TestExternalities { + system::GenesisConfig::default().build_storage::().unwrap().into() + } + + #[test] + fn block_hooks_weight_is_stored() { + new_test_ext().execute_with(|| { + // let a = UncheckedExtrinsic::new_unsigned(Call::System(system::Call::remark(vec![0]))); + // >>::check(a, &Default::default()); + + // Executive::initialize_block(&Header::new_from_number(1)); + // assert_eq!(>::all_extrinsics_weight(), 0); + }) + } } diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index df86f436117a1..0b5653dd9899f 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -26,7 +26,7 @@ pub use srml_metadata::{ pub use sr_primitives::{ weights::{ SimpleDispatchInfo, GetDispatchInfo, DispatchInfo, WeighData, ClassifyDispatch, - TransactionPriority + TransactionPriority, Weight, WeighBlock, }, traits::{Dispatchable, DispatchResult, ModuleDispatchError}, DispatchError, @@ -320,6 +320,7 @@ macro_rules! decl_module { "`deposit_event` function is reserved and must follow the syntax: `$vis:vis fn deposit_event() = default;`" ); }; + // Add on_finalize, without a given weight. (@normalize $(#[$attr:meta])* pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> @@ -343,7 +344,81 @@ macro_rules! decl_module { { $( $other_where_bounds )* } { $( $deposit_event )* } { $( $on_initialize )* } - { fn on_finalize( $( $param_name : $param ),* ) { $( $impl )* } } + { + #[weight = $crate::dispatch::SimpleDispatchInfo::zero()] + fn on_finalize( $( $param_name : $param ),* ) { $( $impl )* } + } + { $( $offchain )* } + { $( $constants )* } + { $( $error_type )* } + [ $( $dispatchables )* ] + $($rest)* + ); + }; + // Add on_finalize, given weight. + (@normalize + $(#[$attr:meta])* + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> + for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident + { $( $other_where_bounds:tt )* } + { $( $deposit_event:tt )* } + { $( $on_initialize:tt )* } + {} + { $( $offchain:tt )* } + { $( $constants:tt )* } + { $( $error_type:tt )* } + [ $( $dispatchables:tt )* ] + $(#[doc = $doc_attr:tt])* + #[weight = $weight:expr] + fn on_finalize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* } + $($rest:tt)* + ) => { + $crate::decl_module!(@normalize + $(#[$attr])* + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> + for enum $call_type where origin: $origin_type, system = $system + { $( $other_where_bounds )* } + { $( $deposit_event )* } + { $( $on_initialize )* } + { + #[weight = $weight] + fn on_finalize( $( $param_name : $param ),* ) { $( $impl )* } + } + { $( $offchain )* } + { $( $constants )* } + { $( $error_type )* } + [ $( $dispatchables )* ] + $($rest)* + ); + }; + // Add on_initialize, without a given weight. + (@normalize + $(#[$attr:meta])* + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> + for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident + { $( $other_where_bounds:tt )* } + { $( $deposit_event:tt )* } + {} + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } + { $( $constants:tt )* } + { $( $error_type:tt )* } + [ $( $dispatchables:tt )* ] + $(#[doc = $doc_attr:tt])* + fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* } + $($rest:tt)* + ) => { + $crate::decl_module!(@normalize + $(#[$attr])* + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> + for enum $call_type where origin: $origin_type, system = $system + { $( $other_where_bounds )* } + { $( $deposit_event )* } + { + #[weight = $crate::dispatch::SimpleDispatchInfo::zero()] + fn on_initialize( $( $param_name : $param ),* ) { $( $impl )* } + } + { $( $on_finalize )* } { $( $offchain )* } { $( $constants )* } { $( $error_type )* } @@ -351,6 +426,7 @@ macro_rules! decl_module { $($rest)* ); }; + // Add on_initialize, given weight. (@normalize $(#[$attr:meta])* pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> @@ -364,6 +440,7 @@ macro_rules! decl_module { { $( $error_type:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* + #[weight = $weight:expr] fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* } $($rest:tt)* ) => { @@ -373,7 +450,10 @@ macro_rules! decl_module { for enum $call_type where origin: $origin_type, system = $system { $( $other_where_bounds )* } { $( $deposit_event )* } - { fn on_initialize( $( $param_name : $param ),* ) { $( $impl )* } } + { + #[weight = $weight] + fn on_initialize( $( $param_name : $param ),* ) { $( $impl )* } + } { $( $on_finalize )* } { $( $offchain )* } { $( $constants )* } @@ -770,6 +850,7 @@ macro_rules! decl_module { (@impl_on_initialize $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; { $( $other_where_bounds:tt )* } + #[weight = $weight:expr] fn on_initialize() { $( $impl:tt )* } ) => { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> @@ -783,6 +864,7 @@ macro_rules! decl_module { (@impl_on_initialize $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; { $( $other_where_bounds:tt )* } + #[weight = $weight:expr] fn on_initialize($param:ident : $param_ty:ty) { $( $impl:tt )* } ) => { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> @@ -806,6 +888,7 @@ macro_rules! decl_module { (@impl_on_finalize $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; { $( $other_where_bounds:tt )* } + #[weight = $weight:expr] fn on_finalize() { $( $impl:tt )* } ) => { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> @@ -819,6 +902,7 @@ macro_rules! decl_module { (@impl_on_finalize $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; { $( $other_where_bounds:tt )* } + #[weight = $weight:expr] fn on_finalize($param:ident : $param_ty:ty) { $( $impl:tt )* } ) => { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> @@ -840,6 +924,35 @@ macro_rules! decl_module { } }; + // TODO: is this how you do optional single repetition? + (@impl_block_hooks_weight + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + { $( $other_where_bounds:tt )* } + @init $( + #[weight = $weight_initialize:expr] + fn on_initialize($( $param_initialize:ident : $param_ty_initialize:ty )*) { $( $impl_initialize:tt )* } + )? + @fin $( + #[weight = $weight_finalize:expr] + fn on_finalize($( $param_finalize:ident : $param_ty_finalize:ty )*) { $( $impl_finalize:tt )* } + )? + ) => { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $crate::dispatch::WeighBlock + for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* + { + $( + fn on_initialize() -> $crate::dispatch::Weight { + >::weigh_data(&$weight_initialize, ()) + } + )? + $( + fn on_finalize() -> $crate::dispatch::Weight { + >::weigh_data(&$weight_finalize, ()) + } + )? + } + }; + (@impl_offchain $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; { $( $other_where_bounds:tt )* } @@ -1083,6 +1196,14 @@ macro_rules! decl_module { $( $on_finalize )* } + $crate::decl_module! { + @impl_block_hooks_weight + $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?>; + { $( $other_where_bounds )* } + @init $( $on_initialize )* + @fin $( $on_finalize )* + } + $crate::decl_module! { @impl_offchain $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?>; @@ -1738,7 +1859,9 @@ mod tests { fn aux_4(_origin, _data: i32) -> Result { unreachable!() } fn aux_5(_origin, _data: i32, #[compact] _data2: u32,) -> Result { unreachable!() } + #[weight = SimpleDispatchInfo::FixedNormal(7)] fn on_initialize(n: T::BlockNumber,) { if n.into() == 42 { panic!("on_initialize") } } + #[weight = SimpleDispatchInfo::FixedOperational(11)] fn on_finalize(n: T::BlockNumber) { if n.into() == 42 { panic!("on_finalize") } } fn offchain_worker() {} @@ -1899,4 +2022,10 @@ mod tests { DispatchInfo { weight: 3, class: DispatchClass::Normal }, ); } + + #[test] + fn weight_for_block_hooks() { + assert_eq!(::on_initialize(), 7); + assert_eq!(::on_finalize(), 11); + } } diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index e07b937751267..93f5006c26cab 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -606,6 +606,29 @@ impl Module { AllExtrinsicsLen::get().unwrap_or_default() } + /// Inform the system module of some additional weight that should be accounted for, in the + /// current block. + /// + /// NOTE: use with extra care; this function is made public only be used for certain modules + /// that need it. A runtime that does not have dynamic calls should never need this and should + /// stick to static weights. A typical use case for this is inner calls or smart contract calls. + /// Furthermore, it only makes sense to use this when it is presumably _cheap_ to provide the + /// argument `weight`; In other words, if this function is to be used to account for some + /// unknown, user provided call's weight, it would only make sense to use it if you are sure you + /// can rapidly compute the weight of the inner call. + /// + /// Even more dangerous is to note that this function does NOT + /// + /// Another use-case could be for the `on_initialise` and `on_finalize` hooks. + /// + /// If no previous transactions exist, the function initializes the weight to zero. + pub fn register_extra_weight(weight: Weight) { + let current_weight = AllExtrinsicsWeight::get().unwrap_or_default(); + let next_weight = current_weight.saturating_add(weight).min(T::MaximumBlockWeight::get()); + // dbg!(current_weight, next_weight); + AllExtrinsicsWeight::put(next_weight); + } + /// Start the execution of a particular block. pub fn initialize( number: &T::BlockNumber, From 15e6efdda85684a6a6189c65962671d3c306ea6b Mon Sep 17 00:00:00 2001 From: kianenigma Date: Sat, 9 Nov 2019 12:08:22 +0100 Subject: [PATCH 2/4] get rid of todos and grumbles and such. --- core/sr-primitives/src/generic/header.rs | 11 ----- .../src/generic/unchecked_extrinsic.rs | 3 -- core/sr-primitives/src/weights.rs | 18 ++++---- node/runtime/src/lib.rs | 46 ++++++++++--------- srml/example/src/lib.rs | 3 +- srml/executive/src/lib.rs | 22 ++++++--- srml/support/src/dispatch.rs | 31 +++++++++---- srml/system/src/lib.rs | 10 ++-- 8 files changed, 79 insertions(+), 65 deletions(-) diff --git a/core/sr-primitives/src/generic/header.rs b/core/sr-primitives/src/generic/header.rs index 5220c11a5b023..75994749c572e 100644 --- a/core/sr-primitives/src/generic/header.rs +++ b/core/sr-primitives/src/generic/header.rs @@ -163,17 +163,6 @@ impl Header where } } -#[cfg(all(test, feature = "std"))] -impl Header where Self::Hash: Default { - /// A new header with the given number and default hash for all other fields. - pub fn new_from_number(number: ::Number) -> Self { - Self { - number, - ..Default::default() - } - } -} - #[cfg(all(test, feature = "std"))] mod tests { use super::*; diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index c703b4c90930a..befa857dffd64 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -92,9 +92,6 @@ impl Extrinsic } } - -pub trait Marker {} - impl Checkable for diff --git a/core/sr-primitives/src/weights.rs b/core/sr-primitives/src/weights.rs index fcca937b7d642..6f2a8676798a4 100644 --- a/core/sr-primitives/src/weights.rs +++ b/core/sr-primitives/src/weights.rs @@ -65,28 +65,28 @@ pub trait ClassifyDispatch { /// Means of determining the weight of a block's lifecycle hooks: on_initialize, on_finalize and /// such. -pub trait WeighBlock { +pub trait WeighBlock { /// Return the weight of the block's on_initialize hook. - fn on_initialize() -> Weight { Zero::zero() } + fn on_initialize(_: BlockNumber) -> Weight { Zero::zero() } /// Return the weight of the block's on_finalize hook. - fn on_finalize() -> Weight { Zero::zero() } + fn on_finalize(_: BlockNumber) -> Weight { Zero::zero() } } /// Maybe I can do something to remove the duplicate code here. -#[impl_for_tuples(5)] -impl WeighBlock for SingleModule { - fn on_initialize() -> Weight { +#[impl_for_tuples(30)] +impl WeighBlock for SingleModule { + fn on_initialize(n: BlockNumber) -> Weight { let mut accumulated_weight: Weight = Zero::zero(); for_tuples!( - #( accumulated_weight = accumulated_weight.saturating_add(SingleModule::on_initialize()); )* + #( accumulated_weight = accumulated_weight.saturating_add(SingleModule::on_initialize(n)); )* ); accumulated_weight } - fn on_finalize() -> Weight { + fn on_finalize(n: BlockNumber) -> Weight { let mut accumulated_weight: Weight = Zero::zero(); for_tuples!( - #( accumulated_weight = accumulated_weight.saturating_add(SingleModule::on_finalize()); )* + #( accumulated_weight = accumulated_weight.saturating_add(SingleModule::on_finalize(n)); )* ); accumulated_weight } diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 315e10df8dd31..ad0a7845b10dd 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -724,28 +724,32 @@ mod tests { #[test] fn block_hooks_weight_should_not_exceed_limits() { use sr_primitives::weights::WeighBlock; - let block_hooks_weight = - ::on_initialize() + ::on_finalize(); - - assert_eq!( - block_hooks_weight, - 0, - "This test might fail simply because the value being compared to has increased to a \ - module declaring a new weight for a hook or call. In this case update the test and \ - happily move on.", - ); + let check_for_block = |b| { + let block_hooks_weight = + >::on_initialize(b) + + >::on_finalize(b); + + assert_eq!( + block_hooks_weight, + 0, + "This test might fail simply because the value being compared to has increased to a \ + module declaring a new weight for a hook or call. In this case update the test and \ + happily move on.", + ); - // Invariant. Always must be like this to have a sane chain. - // TODO: Maybe add a post-create function for all module that check this stuff. - assert!(block_hooks_weight < MaximumBlockWeight::get()); + // Invariant. Always must be like this to have a sane chain. + assert!(block_hooks_weight < MaximumBlockWeight::get()); - // Warning. - if block_hooks_weight > MaximumBlockWeight::get() / 2 { - println!( - "lock hooks weight is consuming more than a block's capacity. You probably want to \ - re-think this. This test will fail now." - ); - assert!(false); - } + // Warning. + if block_hooks_weight > MaximumBlockWeight::get() / 2 { + println!( + "block hooks weight is consuming more than a block's capacity. You probably want \ + to re-think this. This test will fail now." + ); + assert!(false); + } + }; + + let _ = (0..100_000).for_each(check_for_block); } } diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs index 731143162161b..109d2bec102b8 100644 --- a/srml/example/src/lib.rs +++ b/srml/example/src/lib.rs @@ -500,7 +500,8 @@ decl_module! { // The signature could also look like: `fn on_initialize()`. // This function could also very well have a weight annotation, similar to any other. The - // only difference being the default value. + // only difference being that if it is not annotated, the default is + // `SimpleDispatchInfo::zero()`, which resolves into no weight. #[weight = SimpleDispatchInfo::FixedNormal(1000)] fn on_initialize(_n: T::BlockNumber) { // Anything that needs to be done at the start of the block. diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 92f990f7d0223..59ebb9bfee727 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -111,7 +111,11 @@ impl< Block: traits::Block, Context: Default, UnsignedValidator, - AllModules: OnInitialize + OnFinalize + OffchainWorker + WeighBlock, + AllModules: + OnInitialize + + OnFinalize + + OffchainWorker + + WeighBlock, > ExecuteBlock for Executive where Block::Extrinsic: Checkable + Codec, @@ -131,7 +135,11 @@ impl< Block: traits::Block, Context: Default, UnsignedValidator, - AllModules: OnInitialize + OnFinalize + OffchainWorker + WeighBlock, + AllModules: + OnInitialize + + OnFinalize + + OffchainWorker + + WeighBlock, > Executive where Block::Extrinsic: Checkable + Codec, @@ -155,10 +163,12 @@ where ) { >::initialize(block_number, parent_hash, extrinsics_root, digest); >::on_initialize(*block_number); - // TODO: so what if we already know that we are fucked here? Maybe call it unchecked for now - // TODO: add block number as parameter. - >::register_extra_weight(::on_initialize()); - >::register_extra_weight(::on_finalize()); + >::register_extra_weight_unchecked( + >::on_initialize(*block_number) + ); + >::register_extra_weight_unchecked( + >::on_finalize(*block_number) + ); } fn initial_checks(block: &Block) { diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index 0b5653dd9899f..1707fe4867f76 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -924,7 +924,6 @@ macro_rules! decl_module { } }; - // TODO: is this how you do optional single repetition? (@impl_block_hooks_weight $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; { $( $other_where_bounds:tt )* } @@ -937,17 +936,17 @@ macro_rules! decl_module { fn on_finalize($( $param_finalize:ident : $param_ty_finalize:ty )*) { $( $impl_finalize:tt )* } )? ) => { - impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $crate::dispatch::WeighBlock + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $crate::dispatch::WeighBlock<$trait_instance::BlockNumber> for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* { $( - fn on_initialize() -> $crate::dispatch::Weight { - >::weigh_data(&$weight_initialize, ()) + fn on_initialize(n: $trait_instance::BlockNumber) -> $crate::dispatch::Weight { + >::weigh_data(&$weight_initialize, n) } )? $( - fn on_finalize() -> $crate::dispatch::Weight { - >::weigh_data(&$weight_finalize, ()) + fn on_finalize(n: $trait_instance::BlockNumber) -> $crate::dispatch::Weight { + >::weigh_data(&$weight_finalize, n) } )? } @@ -1848,6 +1847,14 @@ mod tests { } } + struct BLockWeight; + impl> WeighData for BLockWeight { + fn weigh_data(&self, target: BlockNumber) -> Weight { + let target: u32 = target.into(); + if target % 2 == 0 { 10 } else { 0 } + } + } + decl_module! { pub struct Module for enum Call where origin: T::Origin, T::AccountId: From { /// Hi, this is a comment. @@ -1861,7 +1868,7 @@ mod tests { #[weight = SimpleDispatchInfo::FixedNormal(7)] fn on_initialize(n: T::BlockNumber,) { if n.into() == 42 { panic!("on_initialize") } } - #[weight = SimpleDispatchInfo::FixedOperational(11)] + #[weight = BLockWeight] fn on_finalize(n: T::BlockNumber) { if n.into() == 42 { panic!("on_finalize") } } fn offchain_worker() {} @@ -2025,7 +2032,13 @@ mod tests { #[test] fn weight_for_block_hooks() { - assert_eq!(::on_initialize(), 7); - assert_eq!(::on_finalize(), 11); + // independent of block number + assert_eq!(>::on_initialize(0), 7); + assert_eq!(>::on_initialize(10), 7); + assert_eq!(>::on_initialize(100), 7); + + // dependent + assert_eq!(>::on_finalize(2), 10); + assert_eq!(>::on_finalize(3), 0); } } diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 93f5006c26cab..23775bdc03e40 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -617,15 +617,15 @@ impl Module { /// unknown, user provided call's weight, it would only make sense to use it if you are sure you /// can rapidly compute the weight of the inner call. /// - /// Even more dangerous is to note that this function does NOT + /// Even more dangerous is to note that this function does NOT take any action, if the new sum + /// of block weight is more than the block weight limit. This is what the _unchecked_. /// - /// Another use-case could be for the `on_initialise` and `on_finalize` hooks. + /// Another potential use-case could be for the `on_initialise` and `on_finalize` hooks. /// - /// If no previous transactions exist, the function initializes the weight to zero. - pub fn register_extra_weight(weight: Weight) { + /// If no previous weight exists, the function initializes the weight to zero. + pub fn register_extra_weight_unchecked(weight: Weight) { let current_weight = AllExtrinsicsWeight::get().unwrap_or_default(); let next_weight = current_weight.saturating_add(weight).min(T::MaximumBlockWeight::get()); - // dbg!(current_weight, next_weight); AllExtrinsicsWeight::put(next_weight); } From cf4c444fdb1fed379a23bb8a290277d517da6f52 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Sun, 10 Nov 2019 12:46:03 +0100 Subject: [PATCH 3/4] Cleanup and fix line-width --- core/test-runtime/src/system.rs | 2 +- srml/executive/src/lib.rs | 119 -------------------------------- srml/support/src/dispatch.rs | 13 ++-- 3 files changed, 10 insertions(+), 124 deletions(-) diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index ba0f25590d793..e12b730db3105 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -19,7 +19,7 @@ use rstd::prelude::*; use runtime_io::{storage_root, storage_changes_root, blake2_256}; -use runtime_support::storage::{self, StorageMap}; +use runtime_support::storage::self; use runtime_support::{decl_storage, decl_module}; use sr_primitives::{ traits::{Hash as HashT, BlakeTwo256, Header as _}, generic, ApplyError, ApplyResult, diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 59ebb9bfee727..11f83d548f89b 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -718,122 +718,3 @@ mod tests { }) } } - -#[cfg(test)] -mod tests_weights { - use codec::{Encode, Decode, EncodeLike, Codec}; - use sr_primitives::traits::{BlakeTwo256, IdentityLookup, Verify, StaticLookup}; - use sr_primitives::{Perbill, transaction_validity::TransactionValidityError, generic, testing}; - use system::ChainContext; - use super::*; - - mod custom { - use sr_primitives::weights::SimpleDispatchInfo; - - pub trait Trait: system::Trait {} - - support::decl_module! { - pub struct Module for enum Call where origin: T::Origin { - #[weight = SimpleDispatchInfo::FixedNormal(100)] - fn some_function(origin) { - // NOTE: does not make any different. - let _ = system::ensure_signed(origin); - } - #[weight = SimpleDispatchInfo::FixedOperational(200)] - fn some_root_operation(origin) { - let _ = system::ensure_root(origin); - } - #[weight = SimpleDispatchInfo::FreeNormal] - fn some_unsigned_message(origin) { - let _ = system::ensure_none(origin); - } - - // module hooks. - // one with block number arg and one without - #[weight = SimpleDispatchInfo::FixedNormal(50)] - fn on_initialize(n: T::BlockNumber) { - println!("on_initialize({})", n); - } - #[weight = SimpleDispatchInfo::FixedNormal(150)] - fn on_finalize() { - println!("on_finalize(?)"); - } - } - } - } - - support::parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Runtime { - type Hash = primitives::H256; - type Origin = Origin; - type BlockNumber = u64; - type AccountId = AccountId; - type Hashing = HashT; - type Index = u64; - type Call = Call; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); - } - impl indices::Trait for Runtime { - type AccountIndex = u32; - type IsDeadAccount = (); - type ResolveHint = indices::SimpleResolveHint; - type Event = (); - } - impl custom::Trait for Runtime {} - - // impl Checkable for UncheckedExtrinsic { - // type Checked = Self; - // fn check(self, _: &Context) -> Result { Ok(self) } - // } - - type HashT = BlakeTwo256; - type Address = ::Source; - type Signature = primitives::sr25519::Signature; - type AccountId = ::Signer; - // type AccountId = u64; - type UncheckedExtrinsic = generic::UncheckedExtrinsic; - // type Header = testing::Header; - // type Block = testing::Block; - type Header = generic::Header; - type Block = generic::Block; - type Executive = super::Executive, Runtime, AllModules>; - - support::construct_runtime!( - pub enum Runtime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: system::{Module, Call, Event}, - Indices: indices::{Module, Call}, - Custom: custom::{Module, Call}, - } - ); - - fn new_test_ext() -> runtime_io::TestExternalities { - system::GenesisConfig::default().build_storage::().unwrap().into() - } - - #[test] - fn block_hooks_weight_is_stored() { - new_test_ext().execute_with(|| { - // let a = UncheckedExtrinsic::new_unsigned(Call::System(system::Call::remark(vec![0]))); - // >>::check(a, &Default::default()); - - // Executive::initialize_block(&Header::new_from_number(1)); - // assert_eq!(>::all_extrinsics_weight(), 0); - }) - } -} diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index 1707fe4867f76..6929838811b7a 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -394,7 +394,9 @@ macro_rules! decl_module { // Add on_initialize, without a given weight. (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> + pub struct $mod_type:ident< + $trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)? + > for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $other_where_bounds:tt )* } { $( $deposit_event:tt )* } @@ -429,7 +431,9 @@ macro_rules! decl_module { // Add on_initialize, given weight. (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> + pub struct $mod_type:ident< + $trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)? + > for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $other_where_bounds:tt )* } { $( $deposit_event:tt )* } @@ -936,8 +940,9 @@ macro_rules! decl_module { fn on_finalize($( $param_finalize:ident : $param_ty_finalize:ty )*) { $( $impl_finalize:tt )* } )? ) => { - impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $crate::dispatch::WeighBlock<$trait_instance::BlockNumber> - for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::dispatch::WeighBlock<$trait_instance::BlockNumber> for $module<$trait_instance$(, $instance)?> where + $( $other_where_bounds )* { $( fn on_initialize(n: $trait_instance::BlockNumber) -> $crate::dispatch::Weight { From 50c83e475da3d75b22d7d4fb8367bc85c61ef389 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Sun, 10 Nov 2019 13:08:02 +0100 Subject: [PATCH 4/4] fix test runtime test --- core/test-runtime/src/system.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index e12b730db3105..36da4498660e3 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -19,7 +19,7 @@ use rstd::prelude::*; use runtime_io::{storage_root, storage_changes_root, blake2_256}; -use runtime_support::storage::self; +use runtime_support::storage; use runtime_support::{decl_storage, decl_module}; use sr_primitives::{ traits::{Hash as HashT, BlakeTwo256, Header as _}, generic, ApplyError, ApplyResult,