Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Changes from 17 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
38299d3
don't modify inherent data on heavy block
coriolinus Dec 2, 2020
fd587b8
write up current thinking on block weight detection
coriolinus Dec 7, 2020
5e59e4e
extract inherent inclusion check into its own function
coriolinus Dec 8, 2020
0f373fd
put heavy block check into runtime
coriolinus Dec 8, 2020
e58858d
the `inclusion` inherent call is Operational, not Mandatory
coriolinus Dec 10, 2020
f670124
Revert "the `inclusion` inherent call is Operational, not Mandatory"
coriolinus Dec 14, 2020
d1c570f
Revert "write up current thinking on block weight detection"
coriolinus Dec 14, 2020
c260f94
Revert "don't modify inherent data on heavy block"
coriolinus Dec 14, 2020
684309d
add backed candidate block weight assumption to configuration
coriolinus Dec 14, 2020
66834f5
Limit backed candidates according to a candidate weight heuristic.
coriolinus Dec 14, 2020
174f906
simplify limit_backed_candidates and weight assumption
coriolinus Dec 14, 2020
63b4869
don't trust the provisioner to fairly distribute candidates
coriolinus Dec 14, 2020
e8d16fd
use saturating subtraction
coriolinus Dec 15, 2020
13bf41b
empty commit to restart ci
coriolinus Dec 15, 2020
38e5f66
Merge remote-tracking branch 'origin/master' into prgn-heavy-blocks
coriolinus Dec 16, 2020
5bc1f4f
use new mechanism for getting max block weight
coriolinus Dec 16, 2020
3dbed6d
apply weight refunds to the inclusion inherent
coriolinus Dec 16, 2020
8aa71bd
use a correct fixed weight for the inclusion inherent
coriolinus Dec 16, 2020
88fe99a
use dynamic inclusion weight so we reduce calculated weight when excl…
coriolinus Dec 16, 2020
84afca7
don't double-count this intrinsic's weight in the block weight
coriolinus Dec 16, 2020
d43f2ab
add unit tests of fn limit_backed_candidates
coriolinus Dec 18, 2020
accd5f7
add tests that the inclusion inherent's weight correctly updates
coriolinus Jan 4, 2021
bb6a038
Merge remote-tracking branch 'origin/master' into prgn-heavy-blocks
coriolinus Jan 5, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 56 additions & 7 deletions runtime/parachains/src/inclusion_inherent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use primitives::v1::{
};
use frame_support::{
decl_error, decl_module, decl_storage, ensure,
dispatch::DispatchResult,
dispatch::DispatchResultWithPostInfo,
weights::{DispatchClass, Weight},
traits::Get,
};
Expand All @@ -39,6 +39,12 @@ use crate::{
};
use inherents::{InherentIdentifier, InherentData, MakeFatalError, ProvideInherent};

// In the future, we should benchmark these consts; these are all untested assumptions for now.
const BACKED_CANDIDATE_WEIGHT: Weight = 100_000;
const INCLUSION_INHERENT_CLAIMED_WEIGHT: Weight = 1_000_000_000;
// we assume that 75% of an inclusion 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 {}

decl_storage! {
Expand Down Expand Up @@ -76,12 +82,12 @@ decl_module! {
}

/// Include backed candidates and bitfields.
#[weight = (1_000_000_000, DispatchClass::Mandatory)]
#[weight = (INCLUSION_INHERENT_CLAIMED_WEIGHT, DispatchClass::Mandatory)]
pub fn inclusion(
origin,
signed_bitfields: SignedAvailabilityBitfields,
backed_candidates: Vec<BackedCandidate<T::Hash>>,
) -> DispatchResult {
) -> DispatchResultWithPostInfo {
ensure_none(origin)?;
ensure!(!<Included>::exists(), Error::<T>::TooManyInclusionInherents);

Expand All @@ -106,6 +112,9 @@ decl_module! {

<scheduler::Module<T>>::schedule(freed);

let backed_candidates = limit_backed_candidates::<T>(backed_candidates);
let backed_candidates_len = backed_candidates.len() as Weight;

// Process backed candidates according to scheduled cores.
let occupied = <inclusion::Module<T>>::process_candidates(
backed_candidates,
Expand All @@ -122,11 +131,53 @@ decl_module! {
// And track that we've finished processing the inherent for this block.
Included::set(Some(()));

Ok(())
Ok(Some(
MINIMAL_INCLUSION_INHERENT_WEIGHT +
(backed_candidates_len * BACKED_CANDIDATE_WEIGHT)
).into())
}
}
}

/// Limit the number of backed candidates processed in order to stay within block weight limits.
///
/// Use a configured assumption about the weight required to process a backed candidate and the
/// current block weight as of the execution of this function to ensure that we don't overload
/// the block with candidate processing.
///
/// If the backed candidates exceed the available block weight remaining, then skips all of them.
/// This is somewhat less desirable than attempting to fit some of them, but is more fair in the
/// even that we can't trust the provisioner to provide a fair / random ordering of candidates.
fn limit_backed_candidates<T: Config>(
backed_candidates: Vec<BackedCandidate<T::Hash>>,
) -> Vec<BackedCandidate<T::Hash>> {
let block_weight_remaining = <T as frame_system::Config>::BlockWeights::get().max_block
.saturating_sub(frame_system::Module::<T>::block_weight().total());

if backed_candidates.len() as Weight * BACKED_CANDIDATE_WEIGHT > block_weight_remaining {
Vec::new()
} else {
backed_candidates
}
}

/// We should only include the inherent under certain circumstances.
///
/// Most importantly, we check that the inherent is itself valid. It may not be, for example, in the
/// event of a session change.
fn should_include_inherent<T: Config>(
signed_bitfields: &SignedAvailabilityBitfields,
backed_candidates: &[BackedCandidate<T::Hash>],
) -> bool {
// Sanity check: session changes can invalidate an inherent, and we _really_ don't want that to happen.
// See github.com/paritytech/polkadot/issues/1327
Module::<T>::inclusion(
frame_system::RawOrigin::None.into(),
signed_bitfields.clone(),
backed_candidates.to_vec(),
).is_ok()
}

impl<T: Config> ProvideInherent for Module<T> {
type Call = Call<T>;
type Error = MakeFatalError<()>;
Expand All @@ -136,9 +187,7 @@ impl<T: Config> ProvideInherent for Module<T> {
data.get_data(&Self::INHERENT_IDENTIFIER)
.expect("inclusion inherent data failed to decode")
.map(|(signed_bitfields, backed_candidates): (SignedAvailabilityBitfields, Vec<BackedCandidate<T::Hash>>)| {
// Sanity check: session changes can invalidate an inherent, and we _really_ don't want that to happen.
// See github.com/paritytech/polkadot/issues/1327
if Self::inclusion(frame_system::RawOrigin::None.into(), signed_bitfields.clone(), backed_candidates.clone()).is_ok() {
if should_include_inherent::<T>(&signed_bitfields, &backed_candidates) {
Call::inclusion(signed_bitfields, backed_candidates)
} else {
Call::inclusion(Vec::new().into(), Vec::new())
Expand Down