Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Co #13164: Optional PoV block limits #6580

Closed
wants to merge 16 commits into from
6 changes: 3 additions & 3 deletions runtime/common/src/assigned_slots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>, id: ParaId) -> DispatchResult {
T::AssignSlotOrigin::ensure_origin(origin)?;

Expand Down Expand Up @@ -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<T>,
id: ParaId,
Expand Down Expand Up @@ -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<T>, id: ParaId) -> DispatchResult {
T::AssignSlotOrigin::ensure_origin(origin.clone())?;

Expand Down
13 changes: 11 additions & 2 deletions runtime/common/src/elections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,24 @@
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,
/// so we always subtract the base block execution weight.
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.
///
Expand Down
8 changes: 6 additions & 2 deletions runtime/common/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
25 changes: 14 additions & 11 deletions runtime/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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());

Expand Down Expand Up @@ -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};

Expand All @@ -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();
}
Expand Down
5 changes: 1 addition & 4 deletions runtime/kusama/constants/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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);
}
Expand Down
7 changes: 4 additions & 3 deletions runtime/kusama/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ");
Expand Down Expand Up @@ -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, || {
Expand All @@ -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;

Expand Down
5 changes: 1 addition & 4 deletions runtime/polkadot/constants/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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);
}
Expand Down
44 changes: 42 additions & 2 deletions runtime/polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<WeightsPerClass>::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)]
Expand Down Expand Up @@ -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, || {
Expand All @@ -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;

Expand Down
5 changes: 1 addition & 4 deletions runtime/rococo/constants/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ");
Expand Down
3 changes: 0 additions & 3 deletions runtime/test-runtime/constants/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down
5 changes: 1 addition & 4 deletions runtime/westend/constants/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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);
}
Expand Down