diff --git a/runtime/common/src/assigned_slots.rs b/runtime/common/src/assigned_slots.rs index 5186b255168a..8eda793ff3a3 100644 --- a/runtime/common/src/assigned_slots.rs +++ b/runtime/common/src/assigned_slots.rs @@ -201,7 +201,7 @@ pub mod pallet { // TODO: Benchmark this /// Assign a permanent parachain slot and immediately create a lease for it. #[pallet::call_index(0)] - #[pallet::weight(((MAXIMUM_BLOCK_WEIGHT / 10) as Weight, DispatchClass::Operational))] + #[pallet::weight(((MAXIMUM_BLOCK_WEIGHT.limited_or_max() / 10) as Weight, DispatchClass::Operational))] pub fn assign_perm_parachain_slot(origin: OriginFor, id: ParaId) -> DispatchResult { T::AssignSlotOrigin::ensure_origin(origin)?; @@ -260,7 +260,7 @@ pub mod pallet { /// immediately if `SlotLeasePeriodStart::Current` is specified, and if the number /// of currently active temporary slots is below `MaxTemporarySlotPerLeasePeriod`. #[pallet::call_index(1)] - #[pallet::weight(((MAXIMUM_BLOCK_WEIGHT / 10) as Weight, DispatchClass::Operational))] + #[pallet::weight(((MAXIMUM_BLOCK_WEIGHT.limited_or_max() / 10) as Weight, DispatchClass::Operational))] pub fn assign_temp_parachain_slot( origin: OriginFor, id: ParaId, @@ -344,7 +344,7 @@ pub mod pallet { // TODO: Benchmark this /// Unassign a permanent or temporary parachain slot #[pallet::call_index(2)] - #[pallet::weight(((MAXIMUM_BLOCK_WEIGHT / 10) as Weight, DispatchClass::Operational))] + #[pallet::weight(((MAXIMUM_BLOCK_WEIGHT.limited_or_max() / 10) as Weight, DispatchClass::Operational))] pub fn unassign_parachain_slot(origin: OriginFor, id: ParaId) -> DispatchResult { T::AssignSlotOrigin::ensure_origin(origin.clone())?; diff --git a/runtime/common/src/elections.rs b/runtime/common/src/elections.rs index 784aa6560cd2..46f71ab2a7bd 100644 --- a/runtime/common/src/elections.rs +++ b/runtime/common/src/elections.rs @@ -23,6 +23,11 @@ macro_rules! impl_elections_weights { ($runtime:ident) => { parameter_types! { + /// The proof size limit that the off-chain solution submission can consume. + /// + /// Since Polkadot does not have a maximal proof size, we hard-code 128 MiB instead of the default `u64::MAX`. + pub OffchainSolutionProofSizeLimit: u64 = 128 * 1024 * 1024; + /// A limit for off-chain phragmen unsigned solution submission. /// /// We want to keep it as high as possible, but can't risk having it reject, @@ -30,8 +35,12 @@ macro_rules! impl_elections_weights { pub OffchainSolutionWeightLimit: Weight = BlockWeights::get() .get(DispatchClass::Normal) .max_extrinsic - .expect("Normal extrinsics have weight limit configured by default; qed") - .saturating_sub($runtime::weights::BlockExecutionWeight::get()); + .map_proof_limit(|l| + Some(l.map_or(OffchainSolutionProofSizeLimit::get(), |l| + l.min(OffchainSolutionProofSizeLimit::get())))) + .saturating_sub($runtime::weights::BlockExecutionWeight::get()) + .exact_limits() + .expect("There must be a maximal ref time limit; qed"); /// A limit for off-chain phragmen unsigned solution length. /// diff --git a/runtime/common/src/impls.rs b/runtime/common/src/impls.rs index 942fc3373c9c..de11984a76bf 100644 --- a/runtime/common/src/impls.rs +++ b/runtime/common/src/impls.rs @@ -102,7 +102,11 @@ pub fn era_payout( mod tests { use super::*; use frame_support::{ - dispatch::DispatchClass, parameter_types, traits::FindAuthor, weights::Weight, PalletId, + dispatch::DispatchClass, + parameter_types, + traits::FindAuthor, + weights::{Weight, WeightLimit}, + PalletId, }; use frame_system::limits; use primitives::AccountId; @@ -138,7 +142,7 @@ mod tests { weight.base_extrinsic = Weight::from_ref_time(100); }) .for_class(DispatchClass::non_mandatory(), |weight| { - weight.max_total = Some(Weight::from_parts(1024, u64::MAX)); + weight.max_total = WeightLimit::from_time_limit(1024); }) .build_or_panic(); pub BlockLength: limits::BlockLength = limits::BlockLength::max(2 * 1024); diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 6f8818e87e00..de6a7065550f 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -40,7 +40,7 @@ mod mock; use frame_support::{ parameter_types, traits::{ConstU32, Currency, OneSessionHandler}, - weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, WeightLimit}, }; use frame_system::limits; use primitives::{AssignmentId, Balance, BlockNumber, ValidatorId}; @@ -70,9 +70,13 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(1); /// by Operational extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); /// We allow for 2 seconds of compute with a 6 second average block time. -/// The storage proof size is not limited so far. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = - Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX); +/// The storage proof size is not limited since this is the Relay chain config. +// NOTE: Better not use `saturating` in const context, to avoid ignoring overflows. +pub const MAXIMUM_BLOCK_WEIGHT: WeightLimit = + WeightLimit::from_time_limit(2 * WEIGHT_REF_TIME_PER_SECOND); +/// The target Proof size that we aim for. This is not a hard limit and is currently only used to +/// print a warning and emit an event on overflow. +pub const BLOCK_POV_TARGET: u64 = 5 * 1024 * 1024; const_assert!(NORMAL_DISPATCH_RATIO.deconstruct() >= AVERAGE_ON_INITIALIZE_RATIO.deconstruct()); @@ -117,8 +121,8 @@ macro_rules! impl_runtime_weights { use frame_system::limits; use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment}; pub use runtime_common::{ - impl_elections_weights, AVERAGE_ON_INITIALIZE_RATIO, MAXIMUM_BLOCK_WEIGHT, - NORMAL_DISPATCH_RATIO, + impl_elections_weights, AVERAGE_ON_INITIALIZE_RATIO, BLOCK_POV_TARGET, + MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, }; use sp_runtime::{FixedPointNumber, Perquintill}; @@ -138,16 +142,15 @@ macro_rules! impl_runtime_weights { weights.base_extrinsic = $runtime::weights::ExtrinsicBaseWeight::get(); }) .for_class(DispatchClass::Normal, |weights| { - weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + weights.max_total = NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT; }) .for_class(DispatchClass::Operational, |weights| { - weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + weights.max_total = MAXIMUM_BLOCK_WEIGHT; // Operational transactions have an extra reserved space, so that they // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. - weights.reserved = Some( - MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT, - ); + weights.reserved = MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT; }) + .pov_soft_limit(BLOCK_POV_TARGET) .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) .build_or_panic(); } diff --git a/runtime/kusama/constants/src/lib.rs b/runtime/kusama/constants/src/lib.rs index 73ca3d31652b..8151d992068f 100644 --- a/runtime/kusama/constants/src/lib.rs +++ b/runtime/kusama/constants/src/lib.rs @@ -67,9 +67,6 @@ pub mod fee { use smallvec::smallvec; pub use sp_runtime::Perbill; - /// The block saturation level. Fees will be updates based on this value. - pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25); - /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the /// node's balance type. /// @@ -111,7 +108,7 @@ mod tests { // Test that the fee for `MAXIMUM_BLOCK_WEIGHT` of weight has sane bounds. fn full_block_fee_is_correct() { // A full block should cost between 1,000 and 10,000 CENTS. - let full_block = WeightToFee::weight_to_fee(&MAXIMUM_BLOCK_WEIGHT); + let full_block = WeightToFee::weight_to_fee(&MAXIMUM_BLOCK_WEIGHT.limited_or_max()); assert!(full_block >= 1_000 * CENTS); assert!(full_block <= 10_000 * CENTS); } diff --git a/runtime/kusama/src/lib.rs b/runtime/kusama/src/lib.rs index 0d23a476a4e4..95927b47d23d 100644 --- a/runtime/kusama/src/lib.rs +++ b/runtime/kusama/src/lib.rs @@ -1271,7 +1271,7 @@ parameter_types! { pub const MinBid: Balance = 100 * QUID; pub MinReceipt: Perquintill = Perquintill::from_rational(1u64, 10_000_000u64); pub const IntakePeriod: BlockNumber = 5 * MINUTES; - pub MaxIntakeWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10; + pub MaxIntakeWeight: Weight = MAXIMUM_BLOCK_WEIGHT.limited_or_max() / 10; pub const ThawThrottle: (Perquintill, BlockNumber) = (Perquintill::from_percent(25), 5); pub storage NisTarget: Perquintill = Perquintill::zero(); pub const NisPalletId: PalletId = PalletId(*b"py/nis "); @@ -2138,7 +2138,7 @@ mod multiplier_tests { fn multiplier_can_grow_from_zero() { let minimum_multiplier = MinimumMultiplier::get(); let target = TargetBlockFullness::get() * - BlockWeights::get().get(DispatchClass::Normal).max_total.unwrap(); + BlockWeights::get().get(DispatchClass::Normal).max_total.limited_or_max(); // if the min is too small, then this will not change, and we are doomed forever. // the weight is 1/100th bigger than target. run_with_system_weight(target.saturating_mul(101) / 100, || { @@ -2153,7 +2153,8 @@ mod multiplier_tests { // assume the multiplier is initially set to its minimum. We update it with values twice the //target (target is 25%, thus 50%) and we see at which point it reaches 1. let mut multiplier = MinimumMultiplier::get(); - let block_weight = BlockWeights::get().get(DispatchClass::Normal).max_total.unwrap(); + let block_weight = + BlockWeights::get().get(DispatchClass::Normal).max_total.limited_or_max(); let mut blocks = 0; let mut fees_paid = 0; diff --git a/runtime/polkadot/constants/src/lib.rs b/runtime/polkadot/constants/src/lib.rs index 68b2fdcd306e..16bfd5ecbd85 100644 --- a/runtime/polkadot/constants/src/lib.rs +++ b/runtime/polkadot/constants/src/lib.rs @@ -68,9 +68,6 @@ pub mod fee { use smallvec::smallvec; pub use sp_runtime::Perbill; - /// The block saturation level. Fees will be updates based on this value. - pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25); - /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the /// node's balance type. /// @@ -112,7 +109,7 @@ mod tests { // Test that the fee for `MAXIMUM_BLOCK_WEIGHT` of weight has sane bounds. fn full_block_fee_is_correct() { // A full block should cost between 10 and 100 DOLLARS. - let full_block = WeightToFee::weight_to_fee(&MAXIMUM_BLOCK_WEIGHT); + let full_block = WeightToFee::weight_to_fee(&MAXIMUM_BLOCK_WEIGHT.limited_or_max()); assert!(full_block >= 10 * DOLLARS); assert!(full_block <= 100 * DOLLARS); } diff --git a/runtime/polkadot/src/lib.rs b/runtime/polkadot/src/lib.rs index 44a1b31d6b5d..756b58cb5c8c 100644 --- a/runtime/polkadot/src/lib.rs +++ b/runtime/polkadot/src/lib.rs @@ -2306,6 +2306,45 @@ mod test { If the limit is too strong, maybe consider increase the limit", ); } + + #[test] + fn block_limits_locked() { + use frame_support::{ + dispatch::PerDispatchClass, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND as SECONDS, WeightLimit}, + }; + use frame_system::limits::WeightsPerClass; + + assert_eq!( + BlockWeights::get(), + frame_system::limits::BlockWeights { + base_block: Weight::from_parts(6103588000, 0), + // There is no effective block proof size limit, it therefore calculates as `u64::MAX`. + max_block: Weight::from_parts(2 * SECONDS, u64::MAX), + per_class: PerDispatchClass::::new(|class| match class { + DispatchClass::Normal => WeightsPerClass { + base_extrinsic: Weight::from_parts(95479000, 0), + max_extrinsic: WeightLimit::from_time_limit(1479904521000), + max_total: WeightLimit::from_time_limit(1500000000000), + reserved: WeightLimit::nothing(), + }, + DispatchClass::Operational => WeightsPerClass { + base_extrinsic: Weight::from_parts(95479000, 0), + max_extrinsic: WeightLimit::from_time_limit(1979904521000), + max_total: WeightLimit::from_time_limit(2000000000000), + reserved: WeightLimit::from_time_limit(500000000000), + }, + DispatchClass::Mandatory => WeightsPerClass { + base_extrinsic: Weight::from_parts(95479000, 0), + max_extrinsic: WeightLimit::unlimited(), + max_total: WeightLimit::unlimited(), + reserved: WeightLimit::unlimited(), + }, + },), + pov_soft_limit: Some(5 * 1024 * 1024), + } + ); + } } #[cfg(test)] @@ -2334,7 +2373,7 @@ mod multiplier_tests { fn multiplier_can_grow_from_zero() { let minimum_multiplier = MinimumMultiplier::get(); let target = TargetBlockFullness::get() * - BlockWeights::get().get(DispatchClass::Normal).max_total.unwrap(); + BlockWeights::get().get(DispatchClass::Normal).max_total.limited_or_max(); // if the min is too small, then this will not change, and we are doomed forever. // the weight is 1/100th bigger than target. run_with_system_weight(target.saturating_mul(101) / 100, || { @@ -2349,7 +2388,8 @@ mod multiplier_tests { // assume the multiplier is initially set to its minimum. We update it with values twice the //target (target is 25%, thus 50%) and we see at which point it reaches 1. let mut multiplier = MinimumMultiplier::get(); - let block_weight = BlockWeights::get().get(DispatchClass::Normal).max_total.unwrap(); + let block_weight = + BlockWeights::get().get(DispatchClass::Normal).max_total.exact_limits().unwrap(); let mut blocks = 0; let mut fees_paid = 0; diff --git a/runtime/rococo/constants/src/lib.rs b/runtime/rococo/constants/src/lib.rs index 0683bc377e13..199d98f1c41a 100644 --- a/runtime/rococo/constants/src/lib.rs +++ b/runtime/rococo/constants/src/lib.rs @@ -69,9 +69,6 @@ pub mod fee { use smallvec::smallvec; pub use sp_runtime::Perbill; - /// The block saturation level. Fees will be updates based on this value. - pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25); - /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the /// node's balance type. /// @@ -113,7 +110,7 @@ mod tests { // Test that the fee for `MAXIMUM_BLOCK_WEIGHT` of weight has sane bounds. fn full_block_fee_is_correct() { // A full block should cost between 1,000 and 10,000 CENTS. - let full_block = WeightToFee::weight_to_fee(&MAXIMUM_BLOCK_WEIGHT); + let full_block = WeightToFee::weight_to_fee(&MAXIMUM_BLOCK_WEIGHT.limited_or_max()); assert!(full_block >= 1_000 * CENTS); assert!(full_block <= 10_000 * CENTS); } diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index 879db0fa2a45..c16334e88cba 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -1211,7 +1211,7 @@ parameter_types! { pub const MinBid: Balance = 100 * UNITS; pub MinReceipt: Perquintill = Perquintill::from_rational(1u64, 10_000_000u64); pub const IntakePeriod: BlockNumber = 5 * MINUTES; - pub MaxIntakeWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10; + pub MaxIntakeWeight: Weight = MAXIMUM_BLOCK_WEIGHT.limited_or_max() / 10; pub const ThawThrottle: (Perquintill, BlockNumber) = (Perquintill::from_percent(25), 5); pub storage NisTarget: Perquintill = Perquintill::zero(); pub const NisPalletId: PalletId = PalletId(*b"py/nis "); diff --git a/runtime/test-runtime/constants/src/lib.rs b/runtime/test-runtime/constants/src/lib.rs index ca329accec88..ae2e86ba9b88 100644 --- a/runtime/test-runtime/constants/src/lib.rs +++ b/runtime/test-runtime/constants/src/lib.rs @@ -59,9 +59,6 @@ pub mod fee { use smallvec::smallvec; pub use sp_runtime::Perbill; - /// The block saturation level. Fees will be updates based on this value. - pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25); - /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the /// node's balance type. /// diff --git a/runtime/westend/constants/src/lib.rs b/runtime/westend/constants/src/lib.rs index e7d1a627713f..26591f4126d8 100644 --- a/runtime/westend/constants/src/lib.rs +++ b/runtime/westend/constants/src/lib.rs @@ -66,9 +66,6 @@ pub mod fee { use smallvec::smallvec; pub use sp_runtime::Perbill; - /// The block saturation level. Fees will be updates based on this value. - pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25); - /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the /// node's balance type. /// @@ -110,7 +107,7 @@ mod tests { // Test that the fee for `MAXIMUM_BLOCK_WEIGHT` of weight has sane bounds. fn full_block_fee_is_correct() { // A full block should cost between 10 and 100 UNITS. - let full_block = WeightToFee::weight_to_fee(&MAXIMUM_BLOCK_WEIGHT); + let full_block = WeightToFee::weight_to_fee(&MAXIMUM_BLOCK_WEIGHT.limited_or_max()); assert!(full_block >= 10 * UNITS); assert!(full_block <= 100 * UNITS); }