mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 08:41:02 +00:00
Elastic scaling: runtime dependency tracking and enactment (#3479)
Changes needed to implement the runtime part of elastic scaling: https://github.com/paritytech/polkadot-sdk/issues/3131, https://github.com/paritytech/polkadot-sdk/issues/3132, https://github.com/paritytech/polkadot-sdk/issues/3202 Also fixes https://github.com/paritytech/polkadot-sdk/issues/3675 TODOs: - [x] storage migration - [x] optimise process_candidates from O(N^2) - [x] drop backable candidates which form cycles - [x] fix unit tests - [x] add more unit tests - [x] check the runtime APIs which use the pending availability storage. We need to expose all of them, see https://github.com/paritytech/polkadot-sdk/issues/3576 - [x] optimise the candidate selection. we're currently picking randomly until we satisfy the weight limit. we need to be smart about not breaking candidate chains while being fair to all paras - https://github.com/paritytech/polkadot-sdk/pull/3573 Relies on the changes made in https://github.com/paritytech/polkadot-sdk/pull/3233 in terms of the inclusion policy and the candidate ordering --------- Signed-off-by: alindima <alin@parity.io> Co-authored-by: command-bot <> Co-authored-by: eskimor <eskimor@users.noreply.github.com>
This commit is contained in:
@@ -147,15 +147,16 @@ All failed checks should lead to an unrecoverable error making the block invalid
|
||||
// return a vector of cleaned-up core IDs.
|
||||
}
|
||||
```
|
||||
* `force_enact(ParaId)`: Forcibly enact the candidate with the given ID as though it had been deemed available by
|
||||
bitfields. Is a no-op if there is no candidate pending availability for this para-id. This should generally not be
|
||||
used but it is useful during execution of Runtime APIs, where the changes to the state are expected to be discarded
|
||||
directly after.
|
||||
* `force_enact(ParaId)`: Forcibly enact the pending candidates of the given paraid as though they had been deemed
|
||||
available by bitfields. Is a no-op if there is no candidate pending availability for this para-id.
|
||||
If there are multiple candidates pending availability for this para-id, it will enact all of
|
||||
them. This should generally not be used but it is useful during execution of Runtime APIs,
|
||||
where the changes to the state are expected to be discarded directly after.
|
||||
* `candidate_pending_availability(ParaId) -> Option<CommittedCandidateReceipt>`: returns the `CommittedCandidateReceipt`
|
||||
pending availability for the para provided, if any.
|
||||
* `pending_availability(ParaId) -> Option<CandidatePendingAvailability>`: returns the metadata around the candidate
|
||||
pending availability for the para, if any.
|
||||
* `collect_disputed(disputed: Vec<CandidateHash>) -> Vec<CoreIndex>`: Sweeps through all paras pending availability. If
|
||||
* `free_disputed(disputed: Vec<CandidateHash>) -> Vec<CoreIndex>`: Sweeps through all paras pending availability. If
|
||||
the candidate hash is one of the disputed candidates, then clean up the corresponding storage for that candidate and
|
||||
the commitments. Return a vector of cleaned-up core IDs.
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ There are a couple of important notes to the operations in this inherent as they
|
||||
this fork.
|
||||
1. When disputes are initiated, we remove the block from pending availability. This allows us to roll back chains to the
|
||||
block before blocks are included as opposed to backing. It's important to do this before processing bitfields.
|
||||
1. `Inclusion::collect_disputed` is kind of expensive so it's important to gate this on whether there are actually any
|
||||
1. `Inclusion::free_disputed` is kind of expensive so it's important to gate this on whether there are actually any
|
||||
new disputes. Which should be never.
|
||||
1. And we don't accept parablocks that have open disputes or disputes that have concluded against the candidate. It's
|
||||
important to import dispute statements before backing, but this is already the case as disputes are imported before
|
||||
|
||||
@@ -285,7 +285,6 @@ No finalization routine runs for this module.
|
||||
- This clears them from `Scheduled` and marks each corresponding `core` in the `AvailabilityCores` as occupied.
|
||||
- Since both the availability cores and the newly-occupied cores lists are sorted ascending, this method can be
|
||||
implemented efficiently.
|
||||
- `core_para(CoreIndex) -> ParaId`: return the currently-scheduled or occupied ParaId for the given core.
|
||||
- `group_validators(GroupIndex) -> Option<Vec<ValidatorIndex>>`: return all validators in a given group, if the group
|
||||
index is valid for this session.
|
||||
- `availability_timeout_predicate() -> Option<impl Fn(CoreIndex, BlockNumber) -> bool>`: returns an optional predicate
|
||||
|
||||
@@ -40,7 +40,7 @@ use sp_runtime::{
|
||||
RuntimeAppPublic,
|
||||
};
|
||||
use sp_std::{
|
||||
collections::{btree_map::BTreeMap, vec_deque::VecDeque},
|
||||
collections::{btree_map::BTreeMap, btree_set::BTreeSet, vec_deque::VecDeque},
|
||||
prelude::Vec,
|
||||
vec,
|
||||
};
|
||||
@@ -104,6 +104,8 @@ pub(crate) struct BenchBuilder<T: paras_inherent::Config> {
|
||||
code_upgrade: Option<u32>,
|
||||
/// Specifies whether the claimqueue should be filled.
|
||||
fill_claimqueue: bool,
|
||||
/// Cores which should not be available when being populated with pending candidates.
|
||||
unavailable_cores: Vec<u32>,
|
||||
_phantom: sp_std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
@@ -133,6 +135,7 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
elastic_paras: Default::default(),
|
||||
code_upgrade: None,
|
||||
fill_claimqueue: true,
|
||||
unavailable_cores: vec![],
|
||||
_phantom: sp_std::marker::PhantomData::<T>,
|
||||
}
|
||||
}
|
||||
@@ -149,6 +152,12 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the cores which should not be available when being populated with pending candidates.
|
||||
pub(crate) fn set_unavailable_cores(mut self, unavailable_cores: Vec<u32>) -> Self {
|
||||
self.unavailable_cores = unavailable_cores;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a map from para id seed to number of validity votes.
|
||||
pub(crate) fn set_backed_and_concluding_paras(
|
||||
mut self,
|
||||
@@ -159,7 +168,6 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
}
|
||||
|
||||
/// Set a map from para id seed to number of cores assigned to it.
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub(crate) fn set_elastic_paras(mut self, elastic_paras: BTreeMap<u32, u8>) -> Self {
|
||||
self.elastic_paras = elastic_paras;
|
||||
self
|
||||
@@ -284,11 +292,13 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
core_idx: CoreIndex,
|
||||
candidate_hash: CandidateHash,
|
||||
availability_votes: BitVec<u8, BitOrderLsb0>,
|
||||
commitments: CandidateCommitments,
|
||||
) -> inclusion::CandidatePendingAvailability<T::Hash, BlockNumberFor<T>> {
|
||||
inclusion::CandidatePendingAvailability::<T::Hash, BlockNumberFor<T>>::new(
|
||||
core_idx, // core
|
||||
candidate_hash, // hash
|
||||
Self::candidate_descriptor_mock(), // candidate descriptor
|
||||
commitments, // commitments
|
||||
availability_votes, // availability votes
|
||||
Default::default(), // backers
|
||||
Zero::zero(), // relay parent
|
||||
@@ -309,12 +319,6 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
availability_votes: BitVec<u8, BitOrderLsb0>,
|
||||
candidate_hash: CandidateHash,
|
||||
) {
|
||||
let candidate_availability = Self::candidate_availability_mock(
|
||||
group_idx,
|
||||
core_idx,
|
||||
candidate_hash,
|
||||
availability_votes,
|
||||
);
|
||||
let commitments = CandidateCommitments::<u32> {
|
||||
upward_messages: Default::default(),
|
||||
horizontal_messages: Default::default(),
|
||||
@@ -323,16 +327,29 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
processed_downward_messages: 0,
|
||||
hrmp_watermark: 0u32.into(),
|
||||
};
|
||||
inclusion::PendingAvailability::<T>::insert(para_id, candidate_availability);
|
||||
inclusion::PendingAvailabilityCommitments::<T>::insert(¶_id, commitments);
|
||||
let candidate_availability = Self::candidate_availability_mock(
|
||||
group_idx,
|
||||
core_idx,
|
||||
candidate_hash,
|
||||
availability_votes,
|
||||
commitments,
|
||||
);
|
||||
inclusion::PendingAvailability::<T>::mutate(para_id, |maybe_andidates| {
|
||||
if let Some(candidates) = maybe_andidates {
|
||||
candidates.push_back(candidate_availability);
|
||||
} else {
|
||||
*maybe_andidates =
|
||||
Some([candidate_availability].into_iter().collect::<VecDeque<_>>());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Create an `AvailabilityBitfield` where `concluding` is a map where each key is a core index
|
||||
/// that is concluding and `cores` is the total number of cores in the system.
|
||||
fn availability_bitvec(concluding: &BTreeMap<u32, u32>, cores: usize) -> AvailabilityBitfield {
|
||||
fn availability_bitvec(concluding_cores: &BTreeSet<u32>, cores: usize) -> AvailabilityBitfield {
|
||||
let mut bitfields = bitvec::bitvec![u8, bitvec::order::Lsb0; 0; 0];
|
||||
for i in 0..cores {
|
||||
if concluding.get(&(i as u32)).is_some() {
|
||||
if concluding_cores.contains(&(i as u32)) {
|
||||
bitfields.push(true);
|
||||
} else {
|
||||
bitfields.push(false)
|
||||
@@ -356,13 +373,13 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Register `cores` count of parachains.
|
||||
/// Register `n_paras` count of parachains.
|
||||
///
|
||||
/// Note that this must be called at least 2 sessions before the target session as there is a
|
||||
/// n+2 session delay for the scheduled actions to take effect.
|
||||
fn setup_para_ids(cores: usize) {
|
||||
fn setup_para_ids(n_paras: usize) {
|
||||
// make sure parachains exist prior to session change.
|
||||
for i in 0..cores {
|
||||
for i in 0..n_paras {
|
||||
let para_id = ParaId::from(i as u32);
|
||||
let validation_code = mock_validation_code();
|
||||
|
||||
@@ -472,7 +489,35 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
let validators =
|
||||
self.validators.as_ref().expect("must have some validators prior to calling");
|
||||
|
||||
let availability_bitvec = Self::availability_bitvec(concluding_paras, total_cores);
|
||||
let mut current_core_idx = 0u32;
|
||||
let mut concluding_cores = BTreeSet::new();
|
||||
|
||||
for (seed, _) in concluding_paras.iter() {
|
||||
// make sure the candidates that will be concluding are marked as pending availability.
|
||||
let para_id = ParaId::from(*seed);
|
||||
|
||||
for _chain_idx in 0..elastic_paras.get(&seed).cloned().unwrap_or(1) {
|
||||
let core_idx = CoreIndex::from(current_core_idx);
|
||||
let group_idx =
|
||||
scheduler::Pallet::<T>::group_assigned_to_core(core_idx, self.block_number)
|
||||
.unwrap();
|
||||
|
||||
Self::add_availability(
|
||||
para_id,
|
||||
core_idx,
|
||||
group_idx,
|
||||
// No validators have made this candidate available yet.
|
||||
bitvec::bitvec![u8, bitvec::order::Lsb0; 0; validators.len()],
|
||||
CandidateHash(H256::from(byte32_slice_from(current_core_idx))),
|
||||
);
|
||||
if !self.unavailable_cores.contains(¤t_core_idx) {
|
||||
concluding_cores.insert(current_core_idx);
|
||||
}
|
||||
current_core_idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let availability_bitvec = Self::availability_bitvec(&concluding_cores, total_cores);
|
||||
|
||||
let bitfields: Vec<UncheckedSigned<AvailabilityBitfield>> = validators
|
||||
.iter()
|
||||
@@ -489,29 +534,6 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut current_core_idx = 0u32;
|
||||
|
||||
for (seed, _) in concluding_paras.iter() {
|
||||
// make sure the candidates that will be concluding are marked as pending availability.
|
||||
let para_id = ParaId::from(*seed);
|
||||
|
||||
for _chain_idx in 0..elastic_paras.get(&seed).cloned().unwrap_or(1) {
|
||||
let core_idx = CoreIndex::from(current_core_idx);
|
||||
let group_idx =
|
||||
scheduler::Pallet::<T>::group_assigned_to_core(core_idx, self.block_number)
|
||||
.unwrap();
|
||||
|
||||
Self::add_availability(
|
||||
para_id,
|
||||
core_idx,
|
||||
group_idx,
|
||||
Self::validator_availability_votes_yes(validators.len()),
|
||||
CandidateHash(H256::from(byte32_slice_from(current_core_idx))),
|
||||
);
|
||||
current_core_idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
bitfields
|
||||
}
|
||||
|
||||
@@ -522,7 +544,7 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
/// validity votes.
|
||||
fn create_backed_candidates(
|
||||
&self,
|
||||
cores_with_backed_candidates: &BTreeMap<u32, u32>,
|
||||
paras_with_backed_candidates: &BTreeMap<u32, u32>,
|
||||
elastic_paras: &BTreeMap<u32, u8>,
|
||||
includes_code_upgrade: Option<u32>,
|
||||
) -> Vec<BackedCandidate<T::Hash>> {
|
||||
@@ -531,7 +553,7 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
let config = configuration::Pallet::<T>::config();
|
||||
|
||||
let mut current_core_idx = 0u32;
|
||||
cores_with_backed_candidates
|
||||
paras_with_backed_candidates
|
||||
.iter()
|
||||
.flat_map(|(seed, num_votes)| {
|
||||
assert!(*num_votes <= validators.len() as u32);
|
||||
@@ -760,7 +782,7 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
|
||||
// NOTE: there is an n+2 session delay for these actions to take effect.
|
||||
// We are currently in Session 0, so these changes will take effect in Session 2.
|
||||
Self::setup_para_ids(used_cores);
|
||||
Self::setup_para_ids(used_cores - extra_cores);
|
||||
configuration::ActiveConfig::<T>::mutate(|c| {
|
||||
c.scheduler_params.num_cores = used_cores as u32;
|
||||
});
|
||||
@@ -782,11 +804,11 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
|
||||
let disputes = builder.create_disputes(
|
||||
builder.backed_and_concluding_paras.len() as u32,
|
||||
used_cores as u32,
|
||||
(used_cores - extra_cores) as u32,
|
||||
builder.dispute_sessions.as_slice(),
|
||||
);
|
||||
let mut disputed_cores = (builder.backed_and_concluding_paras.len() as u32..
|
||||
used_cores as u32)
|
||||
((used_cores - extra_cores) as u32))
|
||||
.into_iter()
|
||||
.map(|idx| (idx, 0))
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
@@ -794,7 +816,7 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
let mut all_cores = builder.backed_and_concluding_paras.clone();
|
||||
all_cores.append(&mut disputed_cores);
|
||||
|
||||
assert_eq!(inclusion::PendingAvailability::<T>::iter().count(), used_cores as usize,);
|
||||
assert_eq!(inclusion::PendingAvailability::<T>::iter().count(), used_cores - extra_cores);
|
||||
|
||||
// Mark all the used cores as occupied. We expect that there are
|
||||
// `backed_and_concluding_paras` that are pending availability and that there are
|
||||
@@ -831,7 +853,7 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
.keys()
|
||||
.flat_map(|para_id| {
|
||||
(0..elastic_paras.get(¶_id).cloned().unwrap_or(1))
|
||||
.map(|_para_local_core_idx| {
|
||||
.filter_map(|_para_local_core_idx| {
|
||||
let ttl = configuration::Pallet::<T>::config().scheduler_params.ttl;
|
||||
// Load an assignment into provider so that one is present to pop
|
||||
let assignment =
|
||||
@@ -844,8 +866,13 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
CoreIndex(core_idx),
|
||||
[ParasEntry::new(assignment, now + ttl)].into(),
|
||||
);
|
||||
let res = if builder.unavailable_cores.contains(&core_idx) {
|
||||
None
|
||||
} else {
|
||||
Some(entry)
|
||||
};
|
||||
core_idx += 1;
|
||||
entry
|
||||
res
|
||||
})
|
||||
.collect::<Vec<(CoreIndex, VecDeque<ParasEntry<_>>)>>()
|
||||
})
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
pub use v1::MigrateToV1;
|
||||
|
||||
pub mod v0 {
|
||||
use crate::inclusion::{Config, Pallet};
|
||||
use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec};
|
||||
use frame_support::{storage_alias, Twox64Concat};
|
||||
use frame_system::pallet_prelude::BlockNumberFor;
|
||||
use parity_scale_codec::{Decode, Encode};
|
||||
use primitives::{
|
||||
AvailabilityBitfield, CandidateCommitments, CandidateDescriptor, CandidateHash, CoreIndex,
|
||||
GroupIndex, Id as ParaId, ValidatorIndex,
|
||||
};
|
||||
use scale_info::TypeInfo;
|
||||
|
||||
#[derive(Encode, Decode, PartialEq, TypeInfo, Clone, Debug)]
|
||||
pub struct CandidatePendingAvailability<H, N> {
|
||||
pub core: CoreIndex,
|
||||
pub hash: CandidateHash,
|
||||
pub descriptor: CandidateDescriptor<H>,
|
||||
pub availability_votes: BitVec<u8, BitOrderLsb0>,
|
||||
pub backers: BitVec<u8, BitOrderLsb0>,
|
||||
pub relay_parent_number: N,
|
||||
pub backed_in_number: N,
|
||||
pub backing_group: GroupIndex,
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, TypeInfo, Debug, PartialEq)]
|
||||
pub struct AvailabilityBitfieldRecord<N> {
|
||||
pub bitfield: AvailabilityBitfield,
|
||||
pub submitted_at: N,
|
||||
}
|
||||
|
||||
#[storage_alias]
|
||||
pub type PendingAvailability<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
Twox64Concat,
|
||||
ParaId,
|
||||
CandidatePendingAvailability<<T as frame_system::Config>::Hash, BlockNumberFor<T>>,
|
||||
>;
|
||||
|
||||
#[storage_alias]
|
||||
pub type PendingAvailabilityCommitments<T: Config> =
|
||||
StorageMap<Pallet<T>, Twox64Concat, ParaId, CandidateCommitments>;
|
||||
|
||||
#[storage_alias]
|
||||
pub type AvailabilityBitfields<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
Twox64Concat,
|
||||
ValidatorIndex,
|
||||
AvailabilityBitfieldRecord<BlockNumberFor<T>>,
|
||||
>;
|
||||
}
|
||||
|
||||
mod v1 {
|
||||
use super::v0::{
|
||||
AvailabilityBitfields, PendingAvailability as V0PendingAvailability,
|
||||
PendingAvailabilityCommitments as V0PendingAvailabilityCommitments,
|
||||
};
|
||||
use crate::inclusion::{
|
||||
CandidatePendingAvailability as V1CandidatePendingAvailability, Config, Pallet,
|
||||
PendingAvailability as V1PendingAvailability,
|
||||
};
|
||||
use frame_support::{traits::OnRuntimeUpgrade, weights::Weight};
|
||||
use sp_core::Get;
|
||||
use sp_std::{collections::vec_deque::VecDeque, vec::Vec};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use frame_support::{
|
||||
ensure,
|
||||
traits::{GetStorageVersion, StorageVersion},
|
||||
};
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use parity_scale_codec::{Decode, Encode};
|
||||
|
||||
pub struct VersionUncheckedMigrateToV1<T>(sp_std::marker::PhantomData<T>);
|
||||
|
||||
impl<T: Config> OnRuntimeUpgrade for VersionUncheckedMigrateToV1<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
log::trace!(target: crate::inclusion::LOG_TARGET, "Running pre_upgrade() for inclusion MigrateToV1");
|
||||
let candidates_before_upgrade = V0PendingAvailability::<T>::iter().count();
|
||||
let commitments_before_upgrade = V0PendingAvailabilityCommitments::<T>::iter().count();
|
||||
|
||||
if candidates_before_upgrade != commitments_before_upgrade {
|
||||
log::warn!(
|
||||
target: crate::inclusion::LOG_TARGET,
|
||||
"Number of pending candidates differ from the number of pending commitments. {} vs {}",
|
||||
candidates_before_upgrade,
|
||||
commitments_before_upgrade
|
||||
);
|
||||
}
|
||||
|
||||
Ok((candidates_before_upgrade as u32).encode())
|
||||
}
|
||||
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let mut weight: Weight = Weight::zero();
|
||||
|
||||
let v0_candidates: Vec<_> = V0PendingAvailability::<T>::drain().collect();
|
||||
|
||||
for (para_id, candidate) in v0_candidates {
|
||||
let commitments = V0PendingAvailabilityCommitments::<T>::take(para_id);
|
||||
// One write for each removal (one candidate and one commitment).
|
||||
weight = weight.saturating_add(T::DbWeight::get().writes(2));
|
||||
|
||||
if let Some(commitments) = commitments {
|
||||
let mut per_para = VecDeque::new();
|
||||
per_para.push_back(V1CandidatePendingAvailability {
|
||||
core: candidate.core,
|
||||
hash: candidate.hash,
|
||||
descriptor: candidate.descriptor,
|
||||
availability_votes: candidate.availability_votes,
|
||||
backers: candidate.backers,
|
||||
relay_parent_number: candidate.relay_parent_number,
|
||||
backed_in_number: candidate.backed_in_number,
|
||||
backing_group: candidate.backing_group,
|
||||
commitments,
|
||||
});
|
||||
V1PendingAvailability::<T>::insert(para_id, per_para);
|
||||
|
||||
weight = weight.saturating_add(T::DbWeight::get().writes(1));
|
||||
}
|
||||
}
|
||||
|
||||
// should've already been drained by the above for loop, but as a sanity check, in case
|
||||
// there are more commitments than candidates.
|
||||
// V0PendingAvailabilityCommitments should not contain too many keys so removing
|
||||
// everything at once should be safe
|
||||
let res = V0PendingAvailabilityCommitments::<T>::clear(u32::MAX, None);
|
||||
weight = weight.saturating_add(
|
||||
T::DbWeight::get().reads_writes(res.loops as u64, res.backend as u64),
|
||||
);
|
||||
|
||||
// AvailabilityBitfields should not contain too many keys so removing everything at once
|
||||
// should be safe.
|
||||
let res = AvailabilityBitfields::<T>::clear(u32::MAX, None);
|
||||
weight = weight.saturating_add(
|
||||
T::DbWeight::get().reads_writes(res.loops as u64, res.backend as u64),
|
||||
);
|
||||
|
||||
weight
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
|
||||
log::trace!(target: crate::inclusion::LOG_TARGET, "Running post_upgrade() for inclusion MigrateToV1");
|
||||
ensure!(
|
||||
Pallet::<T>::on_chain_storage_version() >= StorageVersion::new(1),
|
||||
"Storage version should be >= 1 after the migration"
|
||||
);
|
||||
|
||||
let candidates_before_upgrade =
|
||||
u32::decode(&mut &state[..]).expect("Was properly encoded") as usize;
|
||||
let candidates_after_upgrade = V1PendingAvailability::<T>::iter().fold(
|
||||
0usize,
|
||||
|mut acc, (_paraid, para_candidates)| {
|
||||
acc += para_candidates.len();
|
||||
acc
|
||||
},
|
||||
);
|
||||
|
||||
ensure!(
|
||||
candidates_before_upgrade == candidates_after_upgrade,
|
||||
"Number of pending candidates should be the same as the one before the upgrade."
|
||||
);
|
||||
ensure!(
|
||||
V0PendingAvailability::<T>::iter().next() == None,
|
||||
"Pending availability candidates storage v0 should have been removed"
|
||||
);
|
||||
ensure!(
|
||||
V0PendingAvailabilityCommitments::<T>::iter().next() == None,
|
||||
"Pending availability commitments storage should have been removed"
|
||||
);
|
||||
ensure!(
|
||||
AvailabilityBitfields::<T>::iter().next() == None,
|
||||
"Availability bitfields storage should have been removed"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Migrate to v1 inclusion module storage.
|
||||
/// - merges the `PendingAvailabilityCommitments` into the `CandidatePendingAvailability`
|
||||
/// storage
|
||||
/// - removes the `AvailabilityBitfields` storage, which was never read.
|
||||
pub type MigrateToV1<T> = frame_support::migrations::VersionedMigration<
|
||||
0,
|
||||
1,
|
||||
VersionUncheckedMigrateToV1<T>,
|
||||
Pallet<T>,
|
||||
<T as frame_system::Config>::DbWeight,
|
||||
>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{v1::VersionUncheckedMigrateToV1, *};
|
||||
use crate::{
|
||||
inclusion::{
|
||||
CandidatePendingAvailability as V1CandidatePendingAvailability,
|
||||
PendingAvailability as V1PendingAvailability, *,
|
||||
},
|
||||
mock::{new_test_ext, MockGenesisConfig, Test},
|
||||
};
|
||||
use frame_support::traits::OnRuntimeUpgrade;
|
||||
use primitives::{AvailabilityBitfield, Id as ParaId};
|
||||
use test_helpers::{dummy_candidate_commitments, dummy_candidate_descriptor, dummy_hash};
|
||||
|
||||
#[test]
|
||||
fn migrate_to_v1() {
|
||||
new_test_ext(MockGenesisConfig::default()).execute_with(|| {
|
||||
// No data to migrate.
|
||||
assert_eq!(
|
||||
<VersionUncheckedMigrateToV1<Test> as OnRuntimeUpgrade>::on_runtime_upgrade(),
|
||||
Weight::zero()
|
||||
);
|
||||
assert!(V1PendingAvailability::<Test>::iter().next().is_none());
|
||||
|
||||
let mut expected = vec![];
|
||||
|
||||
for i in 1..5 {
|
||||
let descriptor = dummy_candidate_descriptor(dummy_hash());
|
||||
v0::PendingAvailability::<Test>::insert(
|
||||
ParaId::from(i),
|
||||
v0::CandidatePendingAvailability {
|
||||
core: CoreIndex(i),
|
||||
descriptor: descriptor.clone(),
|
||||
relay_parent_number: i,
|
||||
hash: CandidateHash(dummy_hash()),
|
||||
availability_votes: Default::default(),
|
||||
backed_in_number: i,
|
||||
backers: Default::default(),
|
||||
backing_group: GroupIndex(i),
|
||||
},
|
||||
);
|
||||
v0::PendingAvailabilityCommitments::<Test>::insert(
|
||||
ParaId::from(i),
|
||||
dummy_candidate_commitments(HeadData(vec![i as _])),
|
||||
);
|
||||
|
||||
v0::AvailabilityBitfields::<Test>::insert(
|
||||
ValidatorIndex(i),
|
||||
v0::AvailabilityBitfieldRecord {
|
||||
bitfield: AvailabilityBitfield(Default::default()),
|
||||
submitted_at: i,
|
||||
},
|
||||
);
|
||||
|
||||
expected.push((
|
||||
ParaId::from(i),
|
||||
[V1CandidatePendingAvailability {
|
||||
core: CoreIndex(i),
|
||||
descriptor,
|
||||
relay_parent_number: i,
|
||||
hash: CandidateHash(dummy_hash()),
|
||||
availability_votes: Default::default(),
|
||||
backed_in_number: i,
|
||||
backers: Default::default(),
|
||||
backing_group: GroupIndex(i),
|
||||
commitments: dummy_candidate_commitments(HeadData(vec![i as _])),
|
||||
}]
|
||||
.into_iter()
|
||||
.collect::<VecDeque<_>>(),
|
||||
));
|
||||
}
|
||||
// add some wrong data also, candidates without commitments or commitments without
|
||||
// candidates.
|
||||
v0::PendingAvailability::<Test>::insert(
|
||||
ParaId::from(6),
|
||||
v0::CandidatePendingAvailability {
|
||||
core: CoreIndex(6),
|
||||
descriptor: dummy_candidate_descriptor(dummy_hash()),
|
||||
relay_parent_number: 6,
|
||||
hash: CandidateHash(dummy_hash()),
|
||||
availability_votes: Default::default(),
|
||||
backed_in_number: 6,
|
||||
backers: Default::default(),
|
||||
backing_group: GroupIndex(6),
|
||||
},
|
||||
);
|
||||
v0::PendingAvailabilityCommitments::<Test>::insert(
|
||||
ParaId::from(7),
|
||||
dummy_candidate_commitments(HeadData(vec![7 as _])),
|
||||
);
|
||||
|
||||
// For tests, db weight is zero.
|
||||
assert_eq!(
|
||||
<VersionUncheckedMigrateToV1<Test> as OnRuntimeUpgrade>::on_runtime_upgrade(),
|
||||
Weight::zero()
|
||||
);
|
||||
|
||||
assert_eq!(v0::PendingAvailabilityCommitments::<Test>::iter().next(), None);
|
||||
assert_eq!(v0::PendingAvailability::<Test>::iter().next(), None);
|
||||
assert_eq!(v0::AvailabilityBitfields::<Test>::iter().next(), None);
|
||||
|
||||
let mut actual = V1PendingAvailability::<Test>::iter().collect::<Vec<_>>();
|
||||
actual.sort_by(|(id1, _), (id2, _)| id1.cmp(id2));
|
||||
expected.sort_by(|(id1, _), (id2, _)| id1.cmp(id2));
|
||||
|
||||
assert_eq!(actual, expected);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -23,31 +23,35 @@ use crate::{
|
||||
configuration::{self, HostConfiguration},
|
||||
disputes, dmp, hrmp,
|
||||
paras::{self, SetGoAhead},
|
||||
scheduler::{self, AvailabilityTimeoutStatus},
|
||||
scheduler,
|
||||
shared::{self, AllowedRelayParentsTracker},
|
||||
util::make_persisted_validation_data_with_parent,
|
||||
};
|
||||
use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec};
|
||||
use frame_support::{
|
||||
defensive,
|
||||
pallet_prelude::*,
|
||||
traits::{Defensive, EnqueueMessage, Footprint, QueueFootprint},
|
||||
traits::{EnqueueMessage, Footprint, QueueFootprint},
|
||||
BoundedSlice,
|
||||
};
|
||||
use frame_system::pallet_prelude::*;
|
||||
use pallet_message_queue::OnQueueChanged;
|
||||
use parity_scale_codec::{Decode, Encode};
|
||||
use primitives::{
|
||||
effective_minimum_backing_votes, supermajority_threshold, well_known_keys,
|
||||
AvailabilityBitfield, BackedCandidate, CandidateCommitments, CandidateDescriptor,
|
||||
CandidateHash, CandidateReceipt, CommittedCandidateReceipt, CoreIndex, GroupIndex, Hash,
|
||||
HeadData, Id as ParaId, SignedAvailabilityBitfields, SigningContext, UpwardMessage,
|
||||
ValidatorId, ValidatorIndex, ValidityAttestation,
|
||||
effective_minimum_backing_votes, supermajority_threshold, well_known_keys, BackedCandidate,
|
||||
CandidateCommitments, CandidateDescriptor, CandidateHash, CandidateReceipt,
|
||||
CommittedCandidateReceipt, CoreIndex, GroupIndex, Hash, HeadData, Id as ParaId,
|
||||
SignedAvailabilityBitfields, SigningContext, UpwardMessage, ValidatorId, ValidatorIndex,
|
||||
ValidityAttestation,
|
||||
};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{traits::One, DispatchError, SaturatedConversion, Saturating};
|
||||
#[cfg(feature = "std")]
|
||||
use sp_std::fmt;
|
||||
use sp_std::{collections::btree_set::BTreeSet, prelude::*};
|
||||
use sp_std::{
|
||||
collections::{btree_map::BTreeMap, btree_set::BTreeSet, vec_deque::VecDeque},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
@@ -57,6 +61,8 @@ pub(crate) mod tests;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benchmarking;
|
||||
|
||||
pub mod migration;
|
||||
|
||||
pub trait WeightInfo {
|
||||
fn receive_upward_messages(i: u32) -> Weight;
|
||||
}
|
||||
@@ -80,20 +86,8 @@ impl WeightInfo for () {
|
||||
/// `configuration` pallet to check these values before setting.
|
||||
pub const MAX_UPWARD_MESSAGE_SIZE_BOUND: u32 = 128 * 1024;
|
||||
|
||||
/// A bitfield signed by a validator indicating that it is keeping its piece of the erasure-coding
|
||||
/// for any backed candidates referred to by a `1` bit available.
|
||||
///
|
||||
/// The bitfield's signature should be checked at the point of submission. Afterwards it can be
|
||||
/// dropped.
|
||||
#[derive(Encode, Decode, TypeInfo)]
|
||||
#[cfg_attr(test, derive(Debug))]
|
||||
pub struct AvailabilityBitfieldRecord<N> {
|
||||
bitfield: AvailabilityBitfield, // one bit per core.
|
||||
submitted_at: N, // for accounting, as meaning of bits may change over time.
|
||||
}
|
||||
|
||||
/// A backed candidate pending availability.
|
||||
#[derive(Encode, Decode, PartialEq, TypeInfo)]
|
||||
#[derive(Encode, Decode, PartialEq, TypeInfo, Clone)]
|
||||
#[cfg_attr(test, derive(Debug))]
|
||||
pub struct CandidatePendingAvailability<H, N> {
|
||||
/// The availability core this is assigned to.
|
||||
@@ -102,6 +96,8 @@ pub struct CandidatePendingAvailability<H, N> {
|
||||
hash: CandidateHash,
|
||||
/// The candidate descriptor.
|
||||
descriptor: CandidateDescriptor<H>,
|
||||
/// The candidate commitments.
|
||||
commitments: CandidateCommitments,
|
||||
/// The received availability votes. One bit per validator.
|
||||
availability_votes: BitVec<u8, BitOrderLsb0>,
|
||||
/// The backers of the candidate pending availability.
|
||||
@@ -121,8 +117,11 @@ impl<H, N> CandidatePendingAvailability<H, N> {
|
||||
}
|
||||
|
||||
/// Get the relay-chain block number this was backed in.
|
||||
pub(crate) fn backed_in_number(&self) -> &N {
|
||||
&self.backed_in_number
|
||||
pub(crate) fn backed_in_number(&self) -> N
|
||||
where
|
||||
N: Clone,
|
||||
{
|
||||
self.backed_in_number.clone()
|
||||
}
|
||||
|
||||
/// Get the core index.
|
||||
@@ -140,6 +139,11 @@ impl<H, N> CandidatePendingAvailability<H, N> {
|
||||
&self.descriptor
|
||||
}
|
||||
|
||||
/// Get the candidate commitments.
|
||||
pub(crate) fn candidate_commitments(&self) -> &CandidateCommitments {
|
||||
&self.commitments
|
||||
}
|
||||
|
||||
/// Get the candidate's relay parent's number.
|
||||
pub(crate) fn relay_parent_number(&self) -> N
|
||||
where
|
||||
@@ -148,11 +152,22 @@ impl<H, N> CandidatePendingAvailability<H, N> {
|
||||
self.relay_parent_number.clone()
|
||||
}
|
||||
|
||||
/// Get the candidate backing group.
|
||||
pub(crate) fn backing_group(&self) -> GroupIndex {
|
||||
self.backing_group
|
||||
}
|
||||
|
||||
/// Get the candidate's backers.
|
||||
pub(crate) fn backers(&self) -> &BitVec<u8, BitOrderLsb0> {
|
||||
&self.backers
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "runtime-benchmarks", test))]
|
||||
pub(crate) fn new(
|
||||
core: CoreIndex,
|
||||
hash: CandidateHash,
|
||||
descriptor: CandidateDescriptor<H>,
|
||||
commitments: CandidateCommitments,
|
||||
availability_votes: BitVec<u8, BitOrderLsb0>,
|
||||
backers: BitVec<u8, BitOrderLsb0>,
|
||||
relay_parent_number: N,
|
||||
@@ -163,6 +178,7 @@ impl<H, N> CandidatePendingAvailability<H, N> {
|
||||
core,
|
||||
hash,
|
||||
descriptor,
|
||||
commitments,
|
||||
availability_votes,
|
||||
backers,
|
||||
relay_parent_number,
|
||||
@@ -253,8 +269,10 @@ pub type MaxUmpMessageLenOf<T> =
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
|
||||
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
|
||||
#[pallet::pallet]
|
||||
#[pallet::without_storage_info]
|
||||
#[pallet::storage_version(STORAGE_VERSION)]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
#[pallet::config]
|
||||
@@ -297,30 +315,10 @@ pub mod pallet {
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
/// Validator indices are out of order or contains duplicates.
|
||||
UnsortedOrDuplicateValidatorIndices,
|
||||
/// Dispute statement sets are out of order or contain duplicates.
|
||||
UnsortedOrDuplicateDisputeStatementSet,
|
||||
/// Backed candidates are out of order (core index) or contain duplicates.
|
||||
UnsortedOrDuplicateBackedCandidates,
|
||||
/// A different relay parent was provided compared to the on-chain stored one.
|
||||
UnexpectedRelayParent,
|
||||
/// Availability bitfield has unexpected size.
|
||||
WrongBitfieldSize,
|
||||
/// Bitfield consists of zeros only.
|
||||
BitfieldAllZeros,
|
||||
/// Multiple bitfields submitted by same validator or validators out of order by index.
|
||||
BitfieldDuplicateOrUnordered,
|
||||
/// Validator index out of bounds.
|
||||
ValidatorIndexOutOfBounds,
|
||||
/// Invalid signature
|
||||
InvalidBitfieldSignature,
|
||||
/// Candidate submitted but para not scheduled.
|
||||
UnscheduledCandidate,
|
||||
/// Candidate scheduled despite pending candidate already existing for the para.
|
||||
CandidateScheduledBeforeParaFree,
|
||||
/// Scheduled cores out of order.
|
||||
ScheduledOutOfOrder,
|
||||
/// Head data exceeds the configured maximum.
|
||||
HeadDataTooLarge,
|
||||
/// Code upgrade prematurely.
|
||||
@@ -356,31 +354,22 @@ pub mod pallet {
|
||||
/// The `para_head` hash in the candidate descriptor doesn't match the hash of the actual
|
||||
/// para head in the commitments.
|
||||
ParaHeadMismatch,
|
||||
/// A bitfield that references a freed core,
|
||||
/// either intentionally or as part of a concluded
|
||||
/// invalid dispute.
|
||||
BitfieldReferencesFreedCore,
|
||||
}
|
||||
|
||||
/// The latest bitfield for each validator, referred to by their index in the validator set.
|
||||
#[pallet::storage]
|
||||
pub(crate) type AvailabilityBitfields<T: Config> =
|
||||
StorageMap<_, Twox64Concat, ValidatorIndex, AvailabilityBitfieldRecord<BlockNumberFor<T>>>;
|
||||
|
||||
/// Candidates pending availability by `ParaId`.
|
||||
/// Candidates pending availability by `ParaId`. They form a chain starting from the latest
|
||||
/// included head of the para.
|
||||
/// Use a different prefix post-migration to v1, since the v0 `PendingAvailability` storage
|
||||
/// would otherwise have the exact same prefix which could cause undefined behaviour when doing
|
||||
/// the migration.
|
||||
#[pallet::storage]
|
||||
#[pallet::storage_prefix = "V1"]
|
||||
pub(crate) type PendingAvailability<T: Config> = StorageMap<
|
||||
_,
|
||||
Twox64Concat,
|
||||
ParaId,
|
||||
CandidatePendingAvailability<T::Hash, BlockNumberFor<T>>,
|
||||
VecDeque<CandidatePendingAvailability<T::Hash, BlockNumberFor<T>>>,
|
||||
>;
|
||||
|
||||
/// The commitments of candidates pending availability, by `ParaId`.
|
||||
#[pallet::storage]
|
||||
pub(crate) type PendingAvailabilityCommitments<T: Config> =
|
||||
StorageMap<_, Twox64Concat, ParaId, CandidateCommitments>;
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {}
|
||||
}
|
||||
@@ -469,9 +458,7 @@ impl<T: Config> Pallet<T> {
|
||||
) {
|
||||
// unlike most drain methods, drained elements are not cleared on `Drop` of the iterator
|
||||
// and require consumption.
|
||||
for _ in <PendingAvailabilityCommitments<T>>::drain() {}
|
||||
for _ in <PendingAvailability<T>>::drain() {}
|
||||
for _ in <AvailabilityBitfields<T>>::drain() {}
|
||||
|
||||
Self::cleanup_outgoing_ump_dispatch_queues(outgoing_paras);
|
||||
}
|
||||
@@ -490,27 +477,18 @@ impl<T: Config> Pallet<T> {
|
||||
///
|
||||
/// Bitfields are expected to have been sanitized already. E.g. via `sanitize_bitfields`!
|
||||
///
|
||||
/// Updates storage items `PendingAvailability` and `AvailabilityBitfields`.
|
||||
/// Updates storage items `PendingAvailability`.
|
||||
///
|
||||
/// Returns a `Vec` of `CandidateHash`es and their respective `AvailabilityCore`s that became
|
||||
/// available, and cores free.
|
||||
pub(crate) fn update_pending_availability_and_get_freed_cores<F>(
|
||||
expected_bits: usize,
|
||||
pub(crate) fn update_pending_availability_and_get_freed_cores(
|
||||
validators: &[ValidatorId],
|
||||
signed_bitfields: SignedAvailabilityBitfields,
|
||||
core_lookup: F,
|
||||
) -> Vec<(CoreIndex, CandidateHash)>
|
||||
where
|
||||
F: Fn(CoreIndex) -> Option<ParaId>,
|
||||
{
|
||||
let mut assigned_paras_record = (0..expected_bits)
|
||||
.map(|bit_index| core_lookup(CoreIndex::from(bit_index as u32)))
|
||||
.map(|opt_para_id| {
|
||||
opt_para_id.map(|para_id| (para_id, PendingAvailability::<T>::get(¶_id)))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
) -> Vec<(CoreIndex, CandidateHash)> {
|
||||
let threshold = availability_threshold(validators.len());
|
||||
|
||||
let mut votes_per_core: BTreeMap<CoreIndex, BTreeSet<ValidatorIndex>> = BTreeMap::new();
|
||||
|
||||
let now = <frame_system::Pallet<T>>::block_number();
|
||||
for (checked_bitfield, validator_index) in
|
||||
signed_bitfields.into_iter().map(|signed_bitfield| {
|
||||
let validator_idx = signed_bitfield.validator_index();
|
||||
@@ -518,204 +496,232 @@ impl<T: Config> Pallet<T> {
|
||||
(checked_bitfield, validator_idx)
|
||||
}) {
|
||||
for (bit_idx, _) in checked_bitfield.0.iter().enumerate().filter(|(_, is_av)| **is_av) {
|
||||
let pending_availability = if let Some((_, pending_availability)) =
|
||||
assigned_paras_record[bit_idx].as_mut()
|
||||
{
|
||||
pending_availability
|
||||
} else {
|
||||
// For honest validators, this happens in case of unoccupied cores,
|
||||
// which in turn happens in case of a disputed candidate.
|
||||
// A malicious one might include arbitrary indices, but they are represented
|
||||
// by `None` values and will be sorted out in the next if case.
|
||||
continue
|
||||
};
|
||||
let core_index = CoreIndex(bit_idx as u32);
|
||||
votes_per_core
|
||||
.entry(core_index)
|
||||
.or_insert_with(|| BTreeSet::new())
|
||||
.insert(validator_index);
|
||||
}
|
||||
}
|
||||
|
||||
// defensive check - this is constructed by loading the availability bitfield
|
||||
// record, which is always `Some` if the core is occupied - that's why we're here.
|
||||
let validator_index = validator_index.0 as usize;
|
||||
let mut freed_cores = vec![];
|
||||
|
||||
let pending_paraids: Vec<_> = <PendingAvailability<T>>::iter_keys().collect();
|
||||
for paraid in pending_paraids {
|
||||
<PendingAvailability<T>>::mutate(paraid, |candidates| {
|
||||
if let Some(candidates) = candidates {
|
||||
let mut last_enacted_index: Option<usize> = None;
|
||||
|
||||
for (candidate_index, candidate) in candidates.iter_mut().enumerate() {
|
||||
if let Some(validator_indices) = votes_per_core.remove(&candidate.core) {
|
||||
for validator_index in validator_indices.iter() {
|
||||
// defensive check - this is constructed by loading the
|
||||
// availability bitfield record, which is always `Some` if
|
||||
// the core is occupied - that's why we're here.
|
||||
if let Some(mut bit) =
|
||||
pending_availability.as_mut().and_then(|candidate_pending_availability| {
|
||||
candidate_pending_availability.availability_votes.get_mut(validator_index)
|
||||
}) {
|
||||
candidate.availability_votes.get_mut(validator_index.0 as usize)
|
||||
{
|
||||
*bit = true;
|
||||
}
|
||||
}
|
||||
|
||||
let record =
|
||||
AvailabilityBitfieldRecord { bitfield: checked_bitfield, submitted_at: now };
|
||||
|
||||
<AvailabilityBitfields<T>>::insert(&validator_index, record);
|
||||
}
|
||||
|
||||
let threshold = availability_threshold(validators.len());
|
||||
|
||||
let mut freed_cores = Vec::with_capacity(expected_bits);
|
||||
for (para_id, pending_availability) in assigned_paras_record
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter_map(|(id, p)| p.map(|p| (id, p)))
|
||||
{
|
||||
if pending_availability.availability_votes.count_ones() >= threshold {
|
||||
<PendingAvailability<T>>::remove(¶_id);
|
||||
let commitments = match PendingAvailabilityCommitments::<T>::take(¶_id) {
|
||||
Some(commitments) => commitments,
|
||||
None => {
|
||||
log::warn!(
|
||||
target: LOG_TARGET,
|
||||
"Inclusion::process_bitfields: PendingAvailability and PendingAvailabilityCommitments
|
||||
are out of sync, did someone mess with the storage?",
|
||||
);
|
||||
continue
|
||||
},
|
||||
// We check for the candidate's availability even if we didn't get any new
|
||||
// bitfields for its core, as it may have already been available at a
|
||||
// previous block but wasn't enacted due to its predecessors not being
|
||||
// available.
|
||||
if candidate.availability_votes.count_ones() >= threshold {
|
||||
// We can only enact a candidate if we've enacted all of its
|
||||
// predecessors already.
|
||||
let can_enact = if candidate_index == 0 {
|
||||
last_enacted_index == None
|
||||
} else {
|
||||
let prev_candidate_index = usize::try_from(candidate_index - 1)
|
||||
.expect("Previous `if` would have caught a 0 candidate index.");
|
||||
matches!(last_enacted_index, Some(old_index) if old_index == prev_candidate_index)
|
||||
};
|
||||
|
||||
if can_enact {
|
||||
last_enacted_index = Some(candidate_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trim the pending availability candidates storage and enact candidates of this
|
||||
// para now.
|
||||
if let Some(last_enacted_index) = last_enacted_index {
|
||||
let evicted_candidates = candidates.drain(0..=last_enacted_index);
|
||||
for candidate in evicted_candidates {
|
||||
freed_cores.push((candidate.core, candidate.hash));
|
||||
|
||||
let receipt = CommittedCandidateReceipt {
|
||||
descriptor: pending_availability.descriptor,
|
||||
commitments,
|
||||
descriptor: candidate.descriptor,
|
||||
commitments: candidate.commitments,
|
||||
};
|
||||
let _weight = Self::enact_candidate(
|
||||
pending_availability.relay_parent_number,
|
||||
candidate.relay_parent_number,
|
||||
receipt,
|
||||
pending_availability.backers,
|
||||
pending_availability.availability_votes,
|
||||
pending_availability.core,
|
||||
pending_availability.backing_group,
|
||||
candidate.backers,
|
||||
candidate.availability_votes,
|
||||
candidate.core,
|
||||
candidate.backing_group,
|
||||
);
|
||||
|
||||
freed_cores.push((pending_availability.core, pending_availability.hash));
|
||||
} else {
|
||||
<PendingAvailability<T>>::insert(¶_id, &pending_availability);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
freed_cores
|
||||
}
|
||||
|
||||
/// Process candidates that have been backed. Provide the relay storage root, a set of
|
||||
/// candidates and scheduled cores.
|
||||
/// Process candidates that have been backed. Provide a set of
|
||||
/// candidates along with their scheduled cores.
|
||||
///
|
||||
/// Both should be sorted ascending by core index, and the candidates should be a subset of
|
||||
/// scheduled cores. If these conditions are not met, the execution of the function fails.
|
||||
/// Candidates of the same paraid should be sorted according to their dependency order (they
|
||||
/// should form a chain). If this condition is not met, this function will return an error.
|
||||
/// (This really should not happen here, if the candidates were properly sanitised in
|
||||
/// paras_inherent).
|
||||
pub(crate) fn process_candidates<GV>(
|
||||
allowed_relay_parents: &AllowedRelayParentsTracker<T::Hash, BlockNumberFor<T>>,
|
||||
candidates: Vec<(BackedCandidate<T::Hash>, CoreIndex)>,
|
||||
candidates: &BTreeMap<ParaId, Vec<(BackedCandidate<T::Hash>, CoreIndex)>>,
|
||||
group_validators: GV,
|
||||
core_index_enabled: bool,
|
||||
) -> Result<ProcessedCandidates<T::Hash>, DispatchError>
|
||||
where
|
||||
GV: Fn(GroupIndex) -> Option<Vec<ValidatorIndex>>,
|
||||
{
|
||||
let now = <frame_system::Pallet<T>>::block_number();
|
||||
|
||||
if candidates.is_empty() {
|
||||
return Ok(ProcessedCandidates::default())
|
||||
}
|
||||
|
||||
let minimum_backing_votes = configuration::Pallet::<T>::config().minimum_backing_votes;
|
||||
let now = <frame_system::Pallet<T>>::block_number();
|
||||
let validators = shared::Pallet::<T>::active_validator_keys();
|
||||
|
||||
// Collect candidate receipts with backers.
|
||||
let mut candidate_receipt_with_backing_validator_indices =
|
||||
Vec::with_capacity(candidates.len());
|
||||
let mut core_indices = Vec::with_capacity(candidates.len());
|
||||
|
||||
// Do all checks before writing storage.
|
||||
let core_indices_and_backers = {
|
||||
let mut core_indices_and_backers = Vec::with_capacity(candidates.len());
|
||||
let mut last_core = None;
|
||||
|
||||
let mut check_assignment_in_order = |core_idx| -> DispatchResult {
|
||||
ensure!(
|
||||
last_core.map_or(true, |core| core_idx > core),
|
||||
Error::<T>::ScheduledOutOfOrder,
|
||||
);
|
||||
|
||||
last_core = Some(core_idx);
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// We combine an outer loop over candidates with an inner loop over the scheduled,
|
||||
// where each iteration of the outer loop picks up at the position
|
||||
// in scheduled just after the past iteration left off.
|
||||
//
|
||||
// If the candidates appear in the same order as they appear in `scheduled`,
|
||||
// then they should always be found. If the end of `scheduled` is reached,
|
||||
// then the candidate was either not scheduled or out-of-order.
|
||||
//
|
||||
// In the meantime, we do certain sanity checks on the candidates and on the scheduled
|
||||
// list.
|
||||
for (candidate_idx, (backed_candidate, core_index)) in candidates.iter().enumerate() {
|
||||
let relay_parent_hash = backed_candidate.descriptor().relay_parent;
|
||||
let para_id = backed_candidate.descriptor().para_id;
|
||||
|
||||
let prev_context = <paras::Pallet<T>>::para_most_recent_context(para_id);
|
||||
|
||||
let check_ctx = CandidateCheckContext::<T>::new(prev_context);
|
||||
let signing_context = SigningContext {
|
||||
parent_hash: relay_parent_hash,
|
||||
session_index: shared::Pallet::<T>::session_index(),
|
||||
};
|
||||
|
||||
let relay_parent_number = match check_ctx.verify_backed_candidate(
|
||||
&allowed_relay_parents,
|
||||
candidate_idx,
|
||||
backed_candidate.candidate(),
|
||||
)? {
|
||||
Err(FailedToCreatePVD) => {
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Failed to create PVD for candidate {}",
|
||||
candidate_idx,
|
||||
);
|
||||
// We don't want to error out here because it will
|
||||
// brick the relay-chain. So we return early without
|
||||
// doing anything.
|
||||
return Ok(ProcessedCandidates::default())
|
||||
for (para_id, para_candidates) in candidates {
|
||||
let mut latest_head_data = match Self::para_latest_head_data(para_id) {
|
||||
None => {
|
||||
defensive!("Latest included head data for paraid {:?} is None", para_id);
|
||||
continue
|
||||
},
|
||||
Ok(rpn) => rpn,
|
||||
Some(latest_head_data) => latest_head_data,
|
||||
};
|
||||
|
||||
let (validator_indices, _) =
|
||||
backed_candidate.validator_indices_and_core_index(core_index_enabled);
|
||||
for (candidate, core) in para_candidates.iter() {
|
||||
let candidate_hash = candidate.candidate().hash();
|
||||
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Candidate {:?} on {:?},
|
||||
core_index_enabled = {}",
|
||||
backed_candidate.hash(),
|
||||
core_index,
|
||||
core_index_enabled
|
||||
);
|
||||
let check_ctx = CandidateCheckContext::<T>::new(None);
|
||||
let relay_parent_number = check_ctx.verify_backed_candidate(
|
||||
&allowed_relay_parents,
|
||||
candidate.candidate(),
|
||||
latest_head_data.clone(),
|
||||
)?;
|
||||
|
||||
check_assignment_in_order(core_index)?;
|
||||
|
||||
let mut backers = bitvec::bitvec![u8, BitOrderLsb0; 0; validators.len()];
|
||||
|
||||
ensure!(
|
||||
<PendingAvailability<T>>::get(¶_id).is_none() &&
|
||||
<PendingAvailabilityCommitments<T>>::get(¶_id).is_none(),
|
||||
Error::<T>::CandidateScheduledBeforeParaFree,
|
||||
);
|
||||
|
||||
// The candidate based upon relay parent `N` should be backed by a group
|
||||
// assigned to core at block `N + 1`. Thus, `relay_parent_number + 1`
|
||||
// will always land in the current session.
|
||||
// The candidate based upon relay parent `N` should be backed by a
|
||||
// group assigned to core at block `N + 1`. Thus,
|
||||
// `relay_parent_number + 1` will always land in the current
|
||||
// session.
|
||||
let group_idx = <scheduler::Pallet<T>>::group_assigned_to_core(
|
||||
*core_index,
|
||||
*core,
|
||||
relay_parent_number + One::one(),
|
||||
)
|
||||
.ok_or_else(|| {
|
||||
log::warn!(
|
||||
target: LOG_TARGET,
|
||||
"Failed to compute group index for candidate {}",
|
||||
candidate_idx
|
||||
"Failed to compute group index for candidate {:?}",
|
||||
candidate_hash
|
||||
);
|
||||
Error::<T>::InvalidAssignment
|
||||
})?;
|
||||
let group_vals =
|
||||
group_validators(group_idx).ok_or_else(|| Error::<T>::InvalidGroupIndex)?;
|
||||
|
||||
// Check backing vote count and validity.
|
||||
let (backers, backer_idx_and_attestation) = Self::check_backing_votes(
|
||||
candidate,
|
||||
&validators,
|
||||
group_vals,
|
||||
core_index_enabled,
|
||||
)?;
|
||||
|
||||
// Found a valid candidate.
|
||||
latest_head_data = candidate.candidate().commitments.head_data.clone();
|
||||
candidate_receipt_with_backing_validator_indices
|
||||
.push((candidate.receipt(), backer_idx_and_attestation));
|
||||
core_indices.push((*core, *para_id));
|
||||
|
||||
// Update storage now
|
||||
<PendingAvailability<T>>::mutate(¶_id, |pending_availability| {
|
||||
let new_candidate = CandidatePendingAvailability {
|
||||
core: *core,
|
||||
hash: candidate_hash,
|
||||
descriptor: candidate.candidate().descriptor.clone(),
|
||||
commitments: candidate.candidate().commitments.clone(),
|
||||
// initialize all availability votes to 0.
|
||||
availability_votes: bitvec::bitvec![u8, BitOrderLsb0; 0; validators.len()],
|
||||
relay_parent_number,
|
||||
backers: backers.to_bitvec(),
|
||||
backed_in_number: now,
|
||||
backing_group: group_idx,
|
||||
};
|
||||
|
||||
if let Some(pending_availability) = pending_availability {
|
||||
pending_availability.push_back(new_candidate);
|
||||
} else {
|
||||
*pending_availability =
|
||||
Some([new_candidate].into_iter().collect::<VecDeque<_>>())
|
||||
}
|
||||
});
|
||||
|
||||
// Deposit backed event.
|
||||
Self::deposit_event(Event::<T>::CandidateBacked(
|
||||
candidate.candidate().to_plain(),
|
||||
candidate.candidate().commitments.head_data.clone(),
|
||||
*core,
|
||||
group_idx,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ProcessedCandidates::<T::Hash> {
|
||||
core_indices,
|
||||
candidate_receipt_with_backing_validator_indices,
|
||||
})
|
||||
}
|
||||
|
||||
// Get the latest backed output head data of this para.
|
||||
pub(crate) fn para_latest_head_data(para_id: &ParaId) -> Option<HeadData> {
|
||||
match <PendingAvailability<T>>::get(para_id).and_then(|pending_candidates| {
|
||||
pending_candidates.back().map(|x| x.commitments.head_data.clone())
|
||||
}) {
|
||||
Some(head_data) => Some(head_data),
|
||||
None => <paras::Pallet<T>>::para_head(para_id),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_backing_votes(
|
||||
backed_candidate: &BackedCandidate<T::Hash>,
|
||||
validators: &[ValidatorId],
|
||||
group_vals: Vec<ValidatorIndex>,
|
||||
core_index_enabled: bool,
|
||||
) -> Result<(BitVec<u8, BitOrderLsb0>, Vec<(ValidatorIndex, ValidityAttestation)>), Error<T>> {
|
||||
let minimum_backing_votes = configuration::Pallet::<T>::config().minimum_backing_votes;
|
||||
|
||||
let mut backers = bitvec::bitvec![u8, BitOrderLsb0; 0; validators.len()];
|
||||
let signing_context = SigningContext {
|
||||
parent_hash: backed_candidate.descriptor().relay_parent,
|
||||
session_index: shared::Pallet::<T>::session_index(),
|
||||
};
|
||||
|
||||
let (validator_indices, _) =
|
||||
backed_candidate.validator_indices_and_core_index(core_index_enabled);
|
||||
|
||||
// check the signatures in the backing and that it is a majority.
|
||||
{
|
||||
let maybe_amount_validated = primitives::check_candidate_backing(
|
||||
backed_candidate.candidate().hash(),
|
||||
backed_candidate.validity_votes(),
|
||||
@@ -733,10 +739,7 @@ impl<T: Config> Pallet<T> {
|
||||
match maybe_amount_validated {
|
||||
Ok(amount_validated) => ensure!(
|
||||
amount_validated >=
|
||||
effective_minimum_backing_votes(
|
||||
group_vals.len(),
|
||||
minimum_backing_votes
|
||||
),
|
||||
effective_minimum_backing_votes(group_vals.len(), minimum_backing_votes),
|
||||
Error::<T>::InsufficientBacking,
|
||||
),
|
||||
Err(()) => {
|
||||
@@ -748,7 +751,6 @@ impl<T: Config> Pallet<T> {
|
||||
Vec::<(ValidatorIndex, ValidityAttestation)>::with_capacity(
|
||||
validator_indices.count_ones(),
|
||||
);
|
||||
let candidate_receipt = backed_candidate.receipt();
|
||||
|
||||
for ((bit_idx, _), attestation) in validator_indices
|
||||
.iter()
|
||||
@@ -756,72 +758,13 @@ impl<T: Config> Pallet<T> {
|
||||
.filter(|(_, signed)| **signed)
|
||||
.zip(backed_candidate.validity_votes().iter().cloned())
|
||||
{
|
||||
let val_idx =
|
||||
group_vals.get(bit_idx).expect("this query succeeded above; qed");
|
||||
let val_idx = group_vals.get(bit_idx).expect("this query succeeded above; qed");
|
||||
backer_idx_and_attestation.push((*val_idx, attestation));
|
||||
|
||||
backers.set(val_idx.0 as _, true);
|
||||
}
|
||||
candidate_receipt_with_backing_validator_indices
|
||||
.push((candidate_receipt, backer_idx_and_attestation));
|
||||
}
|
||||
|
||||
core_indices_and_backers.push((
|
||||
(*core_index, para_id),
|
||||
backers,
|
||||
group_idx,
|
||||
relay_parent_number,
|
||||
));
|
||||
}
|
||||
|
||||
core_indices_and_backers
|
||||
};
|
||||
|
||||
// one more sweep for actually writing to storage.
|
||||
let core_indices = core_indices_and_backers.iter().map(|(c, ..)| *c).collect();
|
||||
for ((candidate, _), (core, backers, group, relay_parent_number)) in
|
||||
candidates.into_iter().zip(core_indices_and_backers)
|
||||
{
|
||||
let para_id = candidate.descriptor().para_id;
|
||||
|
||||
// initialize all availability votes to 0.
|
||||
let availability_votes: BitVec<u8, BitOrderLsb0> =
|
||||
bitvec::bitvec![u8, BitOrderLsb0; 0; validators.len()];
|
||||
|
||||
Self::deposit_event(Event::<T>::CandidateBacked(
|
||||
candidate.candidate().to_plain(),
|
||||
candidate.candidate().commitments.head_data.clone(),
|
||||
core.0,
|
||||
group,
|
||||
));
|
||||
|
||||
let candidate_hash = candidate.candidate().hash();
|
||||
|
||||
let (descriptor, commitments) = (
|
||||
candidate.candidate().descriptor.clone(),
|
||||
candidate.candidate().commitments.clone(),
|
||||
);
|
||||
|
||||
<PendingAvailability<T>>::insert(
|
||||
¶_id,
|
||||
CandidatePendingAvailability {
|
||||
core: core.0,
|
||||
hash: candidate_hash,
|
||||
descriptor,
|
||||
availability_votes,
|
||||
relay_parent_number,
|
||||
backers: backers.to_bitvec(),
|
||||
backed_in_number: now,
|
||||
backing_group: group,
|
||||
},
|
||||
);
|
||||
<PendingAvailabilityCommitments<T>>::insert(¶_id, commitments);
|
||||
}
|
||||
|
||||
Ok(ProcessedCandidates::<T::Hash> {
|
||||
core_indices,
|
||||
candidate_receipt_with_backing_validator_indices,
|
||||
})
|
||||
Ok((backers, backer_idx_and_attestation))
|
||||
}
|
||||
|
||||
/// Run the acceptance criteria checks on the given candidate commitments.
|
||||
@@ -1028,110 +971,155 @@ impl<T: Config> Pallet<T> {
|
||||
weight
|
||||
}
|
||||
|
||||
/// Cleans up all paras pending availability that the predicate returns true for.
|
||||
///
|
||||
/// The predicate accepts the index of the core and the block number the core has been occupied
|
||||
/// since (i.e. the block number the candidate was backed at in this fork of the relay chain).
|
||||
/// Cleans up all timed out candidates as well as their descendant candidates.
|
||||
///
|
||||
/// Returns a vector of cleaned-up core IDs.
|
||||
pub(crate) fn collect_pending(
|
||||
pred: impl Fn(BlockNumberFor<T>) -> AvailabilityTimeoutStatus<BlockNumberFor<T>>,
|
||||
) -> Vec<CoreIndex> {
|
||||
let mut cleaned_up_ids = Vec::new();
|
||||
let mut cleaned_up_cores = Vec::new();
|
||||
pub(crate) fn free_timedout() -> Vec<CoreIndex> {
|
||||
let timeout_pred = <scheduler::Pallet<T>>::availability_timeout_predicate();
|
||||
|
||||
for (para_id, pending_record) in <PendingAvailability<T>>::iter() {
|
||||
if pred(pending_record.backed_in_number).timed_out {
|
||||
cleaned_up_ids.push(para_id);
|
||||
cleaned_up_cores.push(pending_record.core);
|
||||
}
|
||||
}
|
||||
let timed_out: Vec<_> = Self::free_failed_cores(
|
||||
|candidate| timeout_pred(candidate.backed_in_number).timed_out,
|
||||
None,
|
||||
)
|
||||
.collect();
|
||||
|
||||
for para_id in cleaned_up_ids {
|
||||
let pending = <PendingAvailability<T>>::take(¶_id);
|
||||
let commitments = <PendingAvailabilityCommitments<T>>::take(¶_id);
|
||||
let mut timed_out_cores = Vec::with_capacity(timed_out.len());
|
||||
for candidate in timed_out.iter() {
|
||||
timed_out_cores.push(candidate.core);
|
||||
|
||||
if let (Some(pending), Some(commitments)) = (pending, commitments) {
|
||||
// defensive: this should always be true.
|
||||
let candidate = CandidateReceipt {
|
||||
descriptor: pending.descriptor,
|
||||
commitments_hash: commitments.hash(),
|
||||
let receipt = CandidateReceipt {
|
||||
descriptor: candidate.descriptor.clone(),
|
||||
commitments_hash: candidate.commitments.hash(),
|
||||
};
|
||||
|
||||
Self::deposit_event(Event::<T>::CandidateTimedOut(
|
||||
candidate,
|
||||
commitments.head_data,
|
||||
pending.core,
|
||||
receipt,
|
||||
candidate.commitments.head_data.clone(),
|
||||
candidate.core,
|
||||
));
|
||||
}
|
||||
|
||||
timed_out_cores
|
||||
}
|
||||
|
||||
cleaned_up_cores
|
||||
}
|
||||
|
||||
/// Cleans up all paras pending availability that are in the given list of disputed candidates.
|
||||
/// Cleans up all cores pending availability occupied by one of the disputed candidates or which
|
||||
/// are descendants of a disputed candidate.
|
||||
///
|
||||
/// Returns a vector of cleaned-up core IDs.
|
||||
pub(crate) fn collect_disputed(disputed: &BTreeSet<CandidateHash>) -> Vec<CoreIndex> {
|
||||
let mut cleaned_up_ids = Vec::new();
|
||||
let mut cleaned_up_cores = Vec::new();
|
||||
/// Returns a vector of cleaned-up core IDs, along with the evicted candidate hashes.
|
||||
pub(crate) fn free_disputed(
|
||||
disputed: &BTreeSet<CandidateHash>,
|
||||
) -> Vec<(CoreIndex, CandidateHash)> {
|
||||
Self::free_failed_cores(
|
||||
|candidate| disputed.contains(&candidate.hash),
|
||||
Some(disputed.len()),
|
||||
)
|
||||
.map(|candidate| (candidate.core, candidate.hash))
|
||||
.collect()
|
||||
}
|
||||
|
||||
for (para_id, pending_record) in <PendingAvailability<T>>::iter() {
|
||||
if disputed.contains(&pending_record.hash) {
|
||||
cleaned_up_ids.push(para_id);
|
||||
cleaned_up_cores.push(pending_record.core);
|
||||
// Clean up cores whose candidates are deemed as failed by the predicate. `pred` returns true if
|
||||
// a candidate is considered failed.
|
||||
// A failed candidate also frees all subsequent cores which hold descendants of said candidate.
|
||||
fn free_failed_cores<
|
||||
P: Fn(&CandidatePendingAvailability<T::Hash, BlockNumberFor<T>>) -> bool,
|
||||
>(
|
||||
pred: P,
|
||||
capacity_hint: Option<usize>,
|
||||
) -> impl Iterator<Item = CandidatePendingAvailability<T::Hash, BlockNumberFor<T>>> {
|
||||
let mut earliest_dropped_indices: BTreeMap<ParaId, usize> = BTreeMap::new();
|
||||
|
||||
for (para_id, pending_candidates) in <PendingAvailability<T>>::iter() {
|
||||
// We assume that pending candidates are stored in dependency order. So we need to store
|
||||
// the earliest dropped candidate. All others that follow will get freed as well.
|
||||
let mut earliest_dropped_idx = None;
|
||||
for (index, candidate) in pending_candidates.iter().enumerate() {
|
||||
if pred(candidate) {
|
||||
earliest_dropped_idx = Some(index);
|
||||
// Since we're looping the candidates in dependency order, we've found the
|
||||
// earliest failed index for this paraid.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for para_id in cleaned_up_ids {
|
||||
let _ = <PendingAvailability<T>>::take(¶_id);
|
||||
let _ = <PendingAvailabilityCommitments<T>>::take(¶_id);
|
||||
if let Some(earliest_dropped_idx) = earliest_dropped_idx {
|
||||
earliest_dropped_indices.insert(para_id, earliest_dropped_idx);
|
||||
}
|
||||
}
|
||||
|
||||
cleaned_up_cores
|
||||
let mut cleaned_up_cores =
|
||||
if let Some(capacity) = capacity_hint { Vec::with_capacity(capacity) } else { vec![] };
|
||||
|
||||
for (para_id, earliest_dropped_idx) in earliest_dropped_indices {
|
||||
// Do cleanups and record the cleaned up cores
|
||||
<PendingAvailability<T>>::mutate(¶_id, |record| {
|
||||
if let Some(record) = record {
|
||||
let cleaned_up = record.drain(earliest_dropped_idx..);
|
||||
cleaned_up_cores.extend(cleaned_up);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Forcibly enact the candidate with the given ID as though it had been deemed available
|
||||
/// by bitfields.
|
||||
cleaned_up_cores.into_iter()
|
||||
}
|
||||
|
||||
/// Forcibly enact the pending candidates of the given paraid as though they had been deemed
|
||||
/// available by bitfields.
|
||||
///
|
||||
/// Is a no-op if there is no candidate pending availability for this para-id.
|
||||
/// This should generally not be used but it is useful during execution of Runtime APIs,
|
||||
/// If there are multiple candidates pending availability for this para-id, it will enact all of
|
||||
/// them. This should generally not be used but it is useful during execution of Runtime APIs,
|
||||
/// where the changes to the state are expected to be discarded directly after.
|
||||
pub(crate) fn force_enact(para: ParaId) {
|
||||
let pending = <PendingAvailability<T>>::take(¶);
|
||||
let commitments = <PendingAvailabilityCommitments<T>>::take(¶);
|
||||
|
||||
if let (Some(pending), Some(commitments)) = (pending, commitments) {
|
||||
let candidate =
|
||||
CommittedCandidateReceipt { descriptor: pending.descriptor, commitments };
|
||||
<PendingAvailability<T>>::mutate(¶, |candidates| {
|
||||
if let Some(candidates) = candidates {
|
||||
for candidate in candidates.drain(..) {
|
||||
let receipt = CommittedCandidateReceipt {
|
||||
descriptor: candidate.descriptor,
|
||||
commitments: candidate.commitments,
|
||||
};
|
||||
|
||||
Self::enact_candidate(
|
||||
pending.relay_parent_number,
|
||||
candidate,
|
||||
pending.backers,
|
||||
pending.availability_votes,
|
||||
pending.core,
|
||||
pending.backing_group,
|
||||
candidate.relay_parent_number,
|
||||
receipt,
|
||||
candidate.backers,
|
||||
candidate.availability_votes,
|
||||
candidate.core,
|
||||
candidate.backing_group,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Returns the `CommittedCandidateReceipt` pending availability for the para provided, if any.
|
||||
/// Returns the first `CommittedCandidateReceipt` pending availability for the para provided, if
|
||||
/// any.
|
||||
pub(crate) fn candidate_pending_availability(
|
||||
para: ParaId,
|
||||
) -> Option<CommittedCandidateReceipt<T::Hash>> {
|
||||
<PendingAvailability<T>>::get(¶)
|
||||
.map(|p| p.descriptor)
|
||||
.and_then(|d| <PendingAvailabilityCommitments<T>>::get(¶).map(move |c| (d, c)))
|
||||
.map(|(d, c)| CommittedCandidateReceipt { descriptor: d, commitments: c })
|
||||
<PendingAvailability<T>>::get(¶).and_then(|p| {
|
||||
p.get(0).map(|p| CommittedCandidateReceipt {
|
||||
descriptor: p.descriptor.clone(),
|
||||
commitments: p.commitments.clone(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the metadata around the candidate pending availability for the
|
||||
/// Returns the metadata around the first candidate pending availability for the
|
||||
/// para provided, if any.
|
||||
pub(crate) fn pending_availability(
|
||||
para: ParaId,
|
||||
) -> Option<CandidatePendingAvailability<T::Hash, BlockNumberFor<T>>> {
|
||||
<PendingAvailability<T>>::get(¶).and_then(|p| p.get(0).cloned())
|
||||
}
|
||||
|
||||
/// Returns the metadata around the candidate pending availability occupying the supplied core,
|
||||
/// if any.
|
||||
pub(crate) fn pending_availability_with_core(
|
||||
para: ParaId,
|
||||
core: CoreIndex,
|
||||
) -> Option<CandidatePendingAvailability<T::Hash, BlockNumberFor<T>>> {
|
||||
<PendingAvailability<T>>::get(¶)
|
||||
.and_then(|p| p.iter().find(|c| c.core == core).cloned())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1182,10 +1170,6 @@ pub(crate) struct CandidateCheckContext<T: Config> {
|
||||
prev_context: Option<BlockNumberFor<T>>,
|
||||
}
|
||||
|
||||
/// An error indicating that creating Persisted Validation Data failed
|
||||
/// while checking a candidate's validity.
|
||||
pub(crate) struct FailedToCreatePVD;
|
||||
|
||||
impl<T: Config> CandidateCheckContext<T> {
|
||||
pub(crate) fn new(prev_context: Option<BlockNumberFor<T>>) -> Self {
|
||||
Self { config: <configuration::Pallet<T>>::config(), prev_context }
|
||||
@@ -1203,9 +1187,9 @@ impl<T: Config> CandidateCheckContext<T> {
|
||||
pub(crate) fn verify_backed_candidate(
|
||||
&self,
|
||||
allowed_relay_parents: &AllowedRelayParentsTracker<T::Hash, BlockNumberFor<T>>,
|
||||
candidate_idx: usize,
|
||||
backed_candidate_receipt: &CommittedCandidateReceipt<<T as frame_system::Config>::Hash>,
|
||||
) -> Result<Result<BlockNumberFor<T>, FailedToCreatePVD>, Error<T>> {
|
||||
parent_head_data: HeadData,
|
||||
) -> Result<BlockNumberFor<T>, Error<T>> {
|
||||
let para_id = backed_candidate_receipt.descriptor().para_id;
|
||||
let relay_parent = backed_candidate_receipt.descriptor().relay_parent;
|
||||
|
||||
@@ -1218,16 +1202,11 @@ impl<T: Config> CandidateCheckContext<T> {
|
||||
};
|
||||
|
||||
{
|
||||
let persisted_validation_data = match crate::util::make_persisted_validation_data::<T>(
|
||||
para_id,
|
||||
let persisted_validation_data = make_persisted_validation_data_with_parent::<T>(
|
||||
relay_parent_number,
|
||||
relay_parent_storage_root,
|
||||
)
|
||||
.defensive_proof("the para is registered")
|
||||
{
|
||||
Some(l) => l,
|
||||
None => return Ok(Err(FailedToCreatePVD)),
|
||||
};
|
||||
parent_head_data,
|
||||
);
|
||||
|
||||
let expected = persisted_validation_data.hash();
|
||||
|
||||
@@ -1268,13 +1247,13 @@ impl<T: Config> CandidateCheckContext<T> {
|
||||
) {
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Validation outputs checking during inclusion of a candidate {} for parachain `{}` failed",
|
||||
candidate_idx,
|
||||
"Validation outputs checking during inclusion of a candidate {:?} for parachain `{}` failed",
|
||||
backed_candidate_receipt.hash(),
|
||||
u32::from(para_id),
|
||||
);
|
||||
Err(err.strip_into_dispatch_err::<T>())?;
|
||||
};
|
||||
Ok(Ok(relay_parent_number))
|
||||
Ok(relay_parent_number)
|
||||
}
|
||||
|
||||
/// Check the given outputs after candidate validation on whether it passes the acceptance
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -145,10 +145,6 @@ benchmarks! {
|
||||
assert_eq!(backing_validators.1.len(), votes);
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
inclusion::PendingAvailabilityCommitments::<T>::iter().count(),
|
||||
cores_with_backed.len()
|
||||
);
|
||||
assert_eq!(
|
||||
inclusion::PendingAvailability::<T>::iter().count(),
|
||||
cores_with_backed.len()
|
||||
@@ -209,10 +205,6 @@ benchmarks! {
|
||||
);
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
inclusion::PendingAvailabilityCommitments::<T>::iter().count(),
|
||||
cores_with_backed.len()
|
||||
);
|
||||
assert_eq!(
|
||||
inclusion::PendingAvailability::<T>::iter().count(),
|
||||
cores_with_backed.len()
|
||||
|
||||
@@ -24,8 +24,7 @@
|
||||
use crate::{
|
||||
configuration,
|
||||
disputes::DisputesHandler,
|
||||
inclusion,
|
||||
inclusion::CandidateCheckContext,
|
||||
inclusion::{self, CandidateCheckContext},
|
||||
initializer,
|
||||
metrics::METRICS,
|
||||
paras,
|
||||
@@ -35,6 +34,7 @@ use crate::{
|
||||
};
|
||||
use bitvec::prelude::BitVec;
|
||||
use frame_support::{
|
||||
defensive,
|
||||
dispatch::{DispatchErrorWithPostInfo, PostDispatchInfo},
|
||||
inherent::{InherentData, InherentIdentifier, MakeFatalError, ProvideInherent},
|
||||
pallet_prelude::*,
|
||||
@@ -45,7 +45,7 @@ use pallet_babe::{self, ParentBlockRandomness};
|
||||
use primitives::{
|
||||
effective_minimum_backing_votes, vstaging::node_features::FeatureIndex, BackedCandidate,
|
||||
CandidateHash, CandidateReceipt, CheckedDisputeStatementSet, CheckedMultiDisputeStatementSet,
|
||||
CoreIndex, DisputeStatementSet, InherentData as ParachainsInherentData,
|
||||
CoreIndex, DisputeStatementSet, HeadData, InherentData as ParachainsInherentData,
|
||||
MultiDisputeStatementSet, ScrapedOnChainVotes, SessionIndex, SignedAvailabilityBitfields,
|
||||
SigningContext, UncheckedSignedAvailabilityBitfield, UncheckedSignedAvailabilityBitfields,
|
||||
ValidatorId, ValidatorIndex, ValidityAttestation, PARACHAINS_INHERENT_IDENTIFIER,
|
||||
@@ -134,18 +134,11 @@ pub mod pallet {
|
||||
/// The hash of the submitted parent header doesn't correspond to the saved block hash of
|
||||
/// the parent.
|
||||
InvalidParentHeader,
|
||||
/// Disputed candidate that was concluded invalid.
|
||||
CandidateConcludedInvalid,
|
||||
/// The data given to the inherent will result in an overweight block.
|
||||
InherentOverweight,
|
||||
/// The ordering of dispute statements was invalid.
|
||||
DisputeStatementsUnsortedOrDuplicates,
|
||||
/// A dispute statement was invalid.
|
||||
DisputeInvalid,
|
||||
/// A candidate was backed by a disabled validator
|
||||
BackedByDisabled,
|
||||
/// A candidate was backed even though the paraid was not scheduled.
|
||||
BackedOnUnscheduledCore,
|
||||
/// A candidate was filtered during inherent execution. This should have only been done
|
||||
/// during creation.
|
||||
CandidatesFilteredDuringExecution,
|
||||
/// Too many candidates supplied.
|
||||
UnscheduledCandidate,
|
||||
}
|
||||
@@ -235,35 +228,6 @@ pub mod pallet {
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect all freed cores based on storage data. (i.e. append cores freed from timeouts to
|
||||
/// the given `freed_concluded`).
|
||||
///
|
||||
/// The parameter `freed_concluded` contains all core indicies that became
|
||||
/// free due to candidate that became available.
|
||||
pub(crate) fn collect_all_freed_cores<T, I>(
|
||||
freed_concluded: I,
|
||||
) -> BTreeMap<CoreIndex, FreedReason>
|
||||
where
|
||||
I: core::iter::IntoIterator<Item = (CoreIndex, CandidateHash)>,
|
||||
T: Config,
|
||||
{
|
||||
// Handle timeouts for any availability core work.
|
||||
let freed_timeout = if <scheduler::Pallet<T>>::availability_timeout_check_required() {
|
||||
let pred = <scheduler::Pallet<T>>::availability_timeout_predicate();
|
||||
<inclusion::Pallet<T>>::collect_pending(pred)
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
// Schedule paras again, given freed cores, and reasons for freeing.
|
||||
let freed = freed_concluded
|
||||
.into_iter()
|
||||
.map(|(c, _hash)| (c, FreedReason::Concluded))
|
||||
.chain(freed_timeout.into_iter().map(|c| (c, FreedReason::TimedOut)))
|
||||
.collect::<BTreeMap<CoreIndex, FreedReason>>();
|
||||
freed
|
||||
}
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Enter the paras inherent. This will process bitfields and backed candidates.
|
||||
@@ -319,7 +283,7 @@ impl<T: Config> Pallet<T> {
|
||||
/// Process inherent data.
|
||||
///
|
||||
/// The given inherent data is processed and state is altered accordingly. If any data could
|
||||
/// not be applied (inconsitencies, weight limit, ...) it is removed.
|
||||
/// not be applied (inconsistencies, weight limit, ...) it is removed.
|
||||
///
|
||||
/// When called from `create_inherent` the `context` must be set to
|
||||
/// `ProcessInherentDataContext::ProvideInherent` so it guarantees the invariant that inherent
|
||||
@@ -526,7 +490,7 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
// Contains the disputes that are concluded in the current session only,
|
||||
// since these are the only ones that are relevant for the occupied cores
|
||||
// and lightens the load on `collect_disputed` significantly.
|
||||
// and lightens the load on `free_disputed` significantly.
|
||||
// Cores can't be occupied with candidates of the previous sessions, and only
|
||||
// things with new votes can have just concluded. We only need to collect
|
||||
// cores with disputes that conclude just now, because disputes that
|
||||
@@ -542,21 +506,17 @@ impl<T: Config> Pallet<T> {
|
||||
.map(|(_session, candidate)| candidate)
|
||||
.collect::<BTreeSet<CandidateHash>>();
|
||||
|
||||
let freed_disputed: BTreeMap<CoreIndex, FreedReason> =
|
||||
<inclusion::Pallet<T>>::collect_disputed(¤t_concluded_invalid_disputes)
|
||||
// Get the cores freed as a result of concluded invalid candidates.
|
||||
let (freed_disputed, concluded_invalid_hashes): (Vec<CoreIndex>, BTreeSet<CandidateHash>) =
|
||||
<inclusion::Pallet<T>>::free_disputed(¤t_concluded_invalid_disputes)
|
||||
.into_iter()
|
||||
.map(|core| (core, FreedReason::Concluded))
|
||||
.collect();
|
||||
.unzip();
|
||||
|
||||
// Create a bit index from the set of core indices where each index corresponds to
|
||||
// a core index that was freed due to a dispute.
|
||||
//
|
||||
// I.e. 010100 would indicate, the candidates on Core 1 and 3 would be disputed.
|
||||
let disputed_bitfield = create_disputed_bitfield(expected_bits, freed_disputed.keys());
|
||||
|
||||
if !freed_disputed.is_empty() {
|
||||
<scheduler::Pallet<T>>::free_cores_and_fill_claimqueue(freed_disputed.clone(), now);
|
||||
}
|
||||
let disputed_bitfield = create_disputed_bitfield(expected_bits, freed_disputed.iter());
|
||||
|
||||
let bitfields = sanitize_bitfields::<T>(
|
||||
bitfields,
|
||||
@@ -571,11 +531,9 @@ impl<T: Config> Pallet<T> {
|
||||
// Process new availability bitfields, yielding any availability cores whose
|
||||
// work has now concluded.
|
||||
let freed_concluded =
|
||||
<inclusion::Pallet<T>>::update_pending_availability_and_get_freed_cores::<_>(
|
||||
expected_bits,
|
||||
<inclusion::Pallet<T>>::update_pending_availability_and_get_freed_cores(
|
||||
&validator_public[..],
|
||||
bitfields.clone(),
|
||||
<scheduler::Pallet<T>>::core_para,
|
||||
);
|
||||
|
||||
// Inform the disputes module of all included candidates.
|
||||
@@ -585,8 +543,24 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
METRICS.on_candidates_included(freed_concluded.len() as u64);
|
||||
|
||||
let freed = collect_all_freed_cores::<T, _>(freed_concluded.iter().cloned());
|
||||
// Get the timed out candidates
|
||||
let freed_timeout = if <scheduler::Pallet<T>>::availability_timeout_check_required() {
|
||||
<inclusion::Pallet<T>>::free_timedout()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
if !freed_timeout.is_empty() {
|
||||
log::debug!(target: LOG_TARGET, "Evicted timed out cores: {:?}", freed_timeout);
|
||||
}
|
||||
|
||||
// We'll schedule paras again, given freed cores, and reasons for freeing.
|
||||
let freed = freed_concluded
|
||||
.into_iter()
|
||||
.map(|(c, _hash)| (c, FreedReason::Concluded))
|
||||
.chain(freed_disputed.into_iter().map(|core| (core, FreedReason::Concluded)))
|
||||
.chain(freed_timeout.into_iter().map(|c| (c, FreedReason::TimedOut)))
|
||||
.collect::<BTreeMap<CoreIndex, FreedReason>>();
|
||||
<scheduler::Pallet<T>>::free_cores_and_fill_claimqueue(freed, now);
|
||||
|
||||
METRICS.on_candidates_processed_total(backed_candidates.len() as u64);
|
||||
@@ -605,55 +579,28 @@ impl<T: Config> Pallet<T> {
|
||||
scheduled.entry(para_id).or_default().insert(core_idx);
|
||||
}
|
||||
|
||||
let SanitizedBackedCandidates {
|
||||
backed_candidates_with_core,
|
||||
votes_from_disabled_were_dropped,
|
||||
dropped_unscheduled_candidates,
|
||||
} = sanitize_backed_candidates::<T, _>(
|
||||
let initial_candidate_count = backed_candidates.len();
|
||||
let backed_candidates_with_core = sanitize_backed_candidates::<T>(
|
||||
backed_candidates,
|
||||
&allowed_relay_parents,
|
||||
|candidate_idx: usize,
|
||||
backed_candidate: &BackedCandidate<<T as frame_system::Config>::Hash>|
|
||||
-> bool {
|
||||
let para_id = backed_candidate.descriptor().para_id;
|
||||
let prev_context = <paras::Pallet<T>>::para_most_recent_context(para_id);
|
||||
let check_ctx = CandidateCheckContext::<T>::new(prev_context);
|
||||
|
||||
// never include a concluded-invalid candidate
|
||||
current_concluded_invalid_disputes.contains(&backed_candidate.hash()) ||
|
||||
// Instead of checking the candidates with code upgrades twice
|
||||
// move the checking up here and skip it in the training wheels fallback.
|
||||
// That way we avoid possible duplicate checks while assuring all
|
||||
// backed candidates fine to pass on.
|
||||
//
|
||||
// NOTE: this is the only place where we check the relay-parent.
|
||||
check_ctx
|
||||
.verify_backed_candidate(&allowed_relay_parents, candidate_idx, backed_candidate.candidate())
|
||||
.is_err()
|
||||
},
|
||||
concluded_invalid_hashes,
|
||||
scheduled,
|
||||
core_index_enabled,
|
||||
);
|
||||
let count = count_backed_candidates(&backed_candidates_with_core);
|
||||
|
||||
ensure!(count <= total_scheduled_cores, Error::<T>::UnscheduledCandidate);
|
||||
|
||||
METRICS.on_candidates_sanitized(count as u64);
|
||||
|
||||
// In `Enter` context (invoked during execution) no more candidates should be filtered,
|
||||
// because they have already been filtered during `ProvideInherent` context. Abort in such
|
||||
// cases.
|
||||
if context == ProcessInherentDataContext::Enter {
|
||||
ensure!(
|
||||
backed_candidates_with_core.len() <= total_scheduled_cores,
|
||||
Error::<T>::UnscheduledCandidate
|
||||
initial_candidate_count == count,
|
||||
Error::<T>::CandidatesFilteredDuringExecution
|
||||
);
|
||||
|
||||
METRICS.on_candidates_sanitized(backed_candidates_with_core.len() as u64);
|
||||
|
||||
// In `Enter` context (invoked during execution) there should be no backing votes from
|
||||
// disabled validators because they should have been filtered out during inherent data
|
||||
// preparation (`ProvideInherent` context). Abort in such cases.
|
||||
if context == ProcessInherentDataContext::Enter {
|
||||
ensure!(!votes_from_disabled_were_dropped, Error::<T>::BackedByDisabled);
|
||||
}
|
||||
|
||||
// In `Enter` context (invoked during execution) we shouldn't have filtered any candidates
|
||||
// due to a para not being scheduled. They have been filtered during inherent data
|
||||
// preparation (`ProvideInherent` context). Abort in such cases.
|
||||
if context == ProcessInherentDataContext::Enter {
|
||||
ensure!(!dropped_unscheduled_candidates, Error::<T>::BackedOnUnscheduledCore);
|
||||
}
|
||||
|
||||
// Process backed candidates according to scheduled cores.
|
||||
@@ -662,7 +609,7 @@ impl<T: Config> Pallet<T> {
|
||||
candidate_receipt_with_backing_validator_indices,
|
||||
} = <inclusion::Pallet<T>>::process_candidates(
|
||||
&allowed_relay_parents,
|
||||
backed_candidates_with_core.clone(),
|
||||
&backed_candidates_with_core,
|
||||
<scheduler::Pallet<T>>::group_validators,
|
||||
core_index_enabled,
|
||||
)?;
|
||||
@@ -683,10 +630,13 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
let processed = ParachainsInherentData {
|
||||
bitfields,
|
||||
backed_candidates: backed_candidates_with_core
|
||||
.into_iter()
|
||||
.map(|(candidate, _)| candidate)
|
||||
.collect(),
|
||||
backed_candidates: backed_candidates_with_core.into_iter().fold(
|
||||
Vec::with_capacity(count),
|
||||
|mut acc, (_id, candidates)| {
|
||||
acc.extend(candidates.into_iter().map(|(c, _)| c));
|
||||
acc
|
||||
},
|
||||
),
|
||||
disputes,
|
||||
parent_header,
|
||||
};
|
||||
@@ -986,83 +936,86 @@ pub(crate) fn sanitize_bitfields<T: crate::inclusion::Config>(
|
||||
bitfields
|
||||
}
|
||||
|
||||
// Result from `sanitize_backed_candidates`
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct SanitizedBackedCandidates<Hash> {
|
||||
// Sanitized backed candidates along with the assigned core. The `Vec` is sorted according to
|
||||
// the occupied core index.
|
||||
backed_candidates_with_core: Vec<(BackedCandidate<Hash>, CoreIndex)>,
|
||||
// Set to true if any votes from disabled validators were dropped from the input.
|
||||
votes_from_disabled_were_dropped: bool,
|
||||
// Set to true if any candidates were dropped due to filtering done in
|
||||
// `map_candidates_to_cores`
|
||||
dropped_unscheduled_candidates: bool,
|
||||
}
|
||||
|
||||
/// Performs various filtering on the backed candidates inherent data.
|
||||
/// Must maintain the invariant that the returned candidate collection contains the candidates
|
||||
/// sorted in dependency order for each para. When doing any filtering, we must therefore drop any
|
||||
/// subsequent candidates after the filtered one.
|
||||
///
|
||||
/// Filter out:
|
||||
/// 1. any candidates that have a concluded invalid dispute
|
||||
/// 2. any unscheduled candidates, as well as candidates whose paraid has multiple cores assigned
|
||||
/// 1. any candidates which don't form a chain with the other candidates of the paraid (even if they
|
||||
/// do form a chain but are not in the right order).
|
||||
/// 2. any candidates that have a concluded invalid dispute or who are descendants of a concluded
|
||||
/// invalid candidate.
|
||||
/// 3. any unscheduled candidates, as well as candidates whose paraid has multiple cores assigned
|
||||
/// but have no injected core index.
|
||||
/// 3. all backing votes from disabled validators
|
||||
/// 4. any candidates that end up with less than `effective_minimum_backing_votes` backing votes
|
||||
/// 4. all backing votes from disabled validators
|
||||
/// 5. any candidates that end up with less than `effective_minimum_backing_votes` backing votes
|
||||
///
|
||||
/// `scheduled` follows the same naming scheme as provided in the
|
||||
/// guide: Currently `free` but might become `occupied`.
|
||||
/// For the filtering here the relevant part is only the current `free`
|
||||
/// state.
|
||||
///
|
||||
/// `candidate_has_concluded_invalid_dispute` must return `true` if the candidate
|
||||
/// is disputed, false otherwise. The passed `usize` is the candidate index.
|
||||
///
|
||||
/// Returns struct `SanitizedBackedCandidates` where `backed_candidates` are sorted according to the
|
||||
/// occupied core index.
|
||||
fn sanitize_backed_candidates<
|
||||
T: crate::inclusion::Config,
|
||||
F: FnMut(usize, &BackedCandidate<T::Hash>) -> bool,
|
||||
>(
|
||||
mut backed_candidates: Vec<BackedCandidate<T::Hash>>,
|
||||
/// Returns the scheduled
|
||||
/// backed candidates which passed filtering, mapped by para id and in the right dependency order.
|
||||
fn sanitize_backed_candidates<T: crate::inclusion::Config>(
|
||||
backed_candidates: Vec<BackedCandidate<T::Hash>>,
|
||||
allowed_relay_parents: &AllowedRelayParentsTracker<T::Hash, BlockNumberFor<T>>,
|
||||
mut candidate_has_concluded_invalid_dispute_or_is_invalid: F,
|
||||
concluded_invalid_with_descendants: BTreeSet<CandidateHash>,
|
||||
scheduled: BTreeMap<ParaId, BTreeSet<CoreIndex>>,
|
||||
core_index_enabled: bool,
|
||||
) -> SanitizedBackedCandidates<T::Hash> {
|
||||
// Remove any candidates that were concluded invalid.
|
||||
// This does not assume sorting.
|
||||
backed_candidates.indexed_retain(move |candidate_idx, backed_candidate| {
|
||||
!candidate_has_concluded_invalid_dispute_or_is_invalid(candidate_idx, backed_candidate)
|
||||
) -> BTreeMap<ParaId, Vec<(BackedCandidate<T::Hash>, CoreIndex)>> {
|
||||
// Map the candidates to the right paraids, while making sure that the order between candidates
|
||||
// of the same para is preserved.
|
||||
let mut candidates_per_para: BTreeMap<ParaId, Vec<_>> = BTreeMap::new();
|
||||
for candidate in backed_candidates {
|
||||
candidates_per_para
|
||||
.entry(candidate.descriptor().para_id)
|
||||
.or_default()
|
||||
.push(candidate);
|
||||
}
|
||||
|
||||
// Check that candidates pertaining to the same para form a chain. Drop the ones that
|
||||
// don't, along with the rest of candidates which follow them in the input vector.
|
||||
filter_unchained_candidates::<T>(&mut candidates_per_para, allowed_relay_parents);
|
||||
|
||||
// Remove any candidates that were concluded invalid or who are descendants of concluded invalid
|
||||
// candidates (along with their descendants).
|
||||
retain_candidates::<T, _, _>(&mut candidates_per_para, |_, candidate| {
|
||||
let keep = !concluded_invalid_with_descendants.contains(&candidate.candidate().hash());
|
||||
|
||||
if !keep {
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Found backed candidate {:?} which was concluded invalid or is a descendant of a concluded invalid candidate, for paraid {:?}.",
|
||||
candidate.candidate().hash(),
|
||||
candidate.descriptor().para_id
|
||||
);
|
||||
}
|
||||
keep
|
||||
});
|
||||
|
||||
let initial_candidate_count = backed_candidates.len();
|
||||
// Map candidates to scheduled cores. Filter out any unscheduled candidates.
|
||||
// Map candidates to scheduled cores. Filter out any unscheduled candidates along with their
|
||||
// descendants.
|
||||
let mut backed_candidates_with_core = map_candidates_to_cores::<T>(
|
||||
&allowed_relay_parents,
|
||||
scheduled,
|
||||
core_index_enabled,
|
||||
backed_candidates,
|
||||
candidates_per_para,
|
||||
);
|
||||
|
||||
let dropped_unscheduled_candidates =
|
||||
initial_candidate_count != backed_candidates_with_core.len();
|
||||
|
||||
// Filter out backing statements from disabled validators
|
||||
let votes_from_disabled_were_dropped = filter_backed_statements_from_disabled_validators::<T>(
|
||||
// Filter out backing statements from disabled validators. If by that we render a candidate with
|
||||
// less backing votes than required, filter that candidate also. As all the other filtering
|
||||
// operations above, we drop the descendants of the dropped candidates also.
|
||||
filter_backed_statements_from_disabled_validators::<T>(
|
||||
&mut backed_candidates_with_core,
|
||||
&allowed_relay_parents,
|
||||
core_index_enabled,
|
||||
);
|
||||
|
||||
// Sort the `Vec` last, once there is a guarantee that these
|
||||
// `BackedCandidates` references the expected relay chain parent,
|
||||
// but more importantly are scheduled for a free core.
|
||||
// This both avoids extra work for obviously invalid candidates,
|
||||
// but also allows this to be done in place.
|
||||
backed_candidates_with_core.sort_by(|(_x, core_x), (_y, core_y)| core_x.cmp(&core_y));
|
||||
backed_candidates_with_core
|
||||
}
|
||||
|
||||
SanitizedBackedCandidates {
|
||||
dropped_unscheduled_candidates,
|
||||
votes_from_disabled_were_dropped,
|
||||
backed_candidates_with_core,
|
||||
}
|
||||
fn count_backed_candidates<B>(backed_candidates: &BTreeMap<ParaId, Vec<B>>) -> usize {
|
||||
backed_candidates.iter().fold(0, |mut count, (_id, candidates)| {
|
||||
count += candidates.len();
|
||||
count
|
||||
})
|
||||
}
|
||||
|
||||
/// Derive entropy from babe provided per block randomness.
|
||||
@@ -1146,48 +1099,82 @@ fn limit_and_sanitize_disputes<
|
||||
}
|
||||
}
|
||||
|
||||
// Filters statements from disabled validators in `BackedCandidate`, non-scheduled candidates and
|
||||
// few more sanity checks. Returns `true` if at least one statement is removed and `false`
|
||||
// otherwise.
|
||||
fn filter_backed_statements_from_disabled_validators<T: shared::Config + scheduler::Config>(
|
||||
backed_candidates_with_core: &mut Vec<(
|
||||
BackedCandidate<<T as frame_system::Config>::Hash>,
|
||||
CoreIndex,
|
||||
)>,
|
||||
// Helper function for filtering candidates which don't pass the given predicate. When/if the first
|
||||
// candidate which failes the predicate is found, all the other candidates that follow are dropped.
|
||||
fn retain_candidates<
|
||||
T: inclusion::Config + paras::Config + inclusion::Config,
|
||||
F: FnMut(ParaId, &mut C) -> bool,
|
||||
C,
|
||||
>(
|
||||
candidates_per_para: &mut BTreeMap<ParaId, Vec<C>>,
|
||||
mut pred: F,
|
||||
) {
|
||||
for (para_id, candidates) in candidates_per_para.iter_mut() {
|
||||
let mut latest_valid_idx = None;
|
||||
|
||||
for (idx, candidate) in candidates.iter_mut().enumerate() {
|
||||
if pred(*para_id, candidate) {
|
||||
// Found a valid candidate.
|
||||
latest_valid_idx = Some(idx);
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(latest_valid_idx) = latest_valid_idx {
|
||||
candidates.truncate(latest_valid_idx + 1);
|
||||
} else {
|
||||
candidates.clear();
|
||||
}
|
||||
}
|
||||
|
||||
candidates_per_para.retain(|_, c| !c.is_empty());
|
||||
}
|
||||
|
||||
// Filters statements from disabled validators in `BackedCandidate` and does a few more sanity
|
||||
// checks.
|
||||
fn filter_backed_statements_from_disabled_validators<
|
||||
T: shared::Config + scheduler::Config + inclusion::Config,
|
||||
>(
|
||||
backed_candidates_with_core: &mut BTreeMap<
|
||||
ParaId,
|
||||
Vec<(BackedCandidate<<T as frame_system::Config>::Hash>, CoreIndex)>,
|
||||
>,
|
||||
allowed_relay_parents: &AllowedRelayParentsTracker<T::Hash, BlockNumberFor<T>>,
|
||||
core_index_enabled: bool,
|
||||
) -> bool {
|
||||
) {
|
||||
let disabled_validators =
|
||||
BTreeSet::<_>::from_iter(shared::Pallet::<T>::disabled_validators().into_iter());
|
||||
|
||||
if disabled_validators.is_empty() {
|
||||
// No disabled validators - nothing to do
|
||||
return false
|
||||
return
|
||||
}
|
||||
|
||||
let backed_len_before = backed_candidates_with_core.len();
|
||||
|
||||
// Flag which will be returned. Set to `true` if at least one vote is filtered.
|
||||
let mut filtered = false;
|
||||
|
||||
let minimum_backing_votes = configuration::Pallet::<T>::config().minimum_backing_votes;
|
||||
|
||||
// Process all backed candidates. `validator_indices` in `BackedCandidates` are indices within
|
||||
// the validator group assigned to the parachain. To obtain this group we need:
|
||||
// 1. Core index assigned to the parachain which has produced the candidate
|
||||
// 2. The relay chain block number of the candidate
|
||||
backed_candidates_with_core.retain_mut(|(bc, core_idx)| {
|
||||
let (validator_indices, maybe_core_index) = bc.validator_indices_and_core_index(core_index_enabled);
|
||||
retain_candidates::<T, _, _>(backed_candidates_with_core, |para_id, (bc, core_idx)| {
|
||||
let (validator_indices, maybe_core_index) =
|
||||
bc.validator_indices_and_core_index(core_index_enabled);
|
||||
let mut validator_indices = BitVec::<_>::from(validator_indices);
|
||||
|
||||
// Get relay parent block number of the candidate. We need this to get the group index assigned to this core at this block number
|
||||
let relay_parent_block_number = match allowed_relay_parents
|
||||
.acquire_info(bc.descriptor().relay_parent, None) {
|
||||
// Get relay parent block number of the candidate. We need this to get the group index
|
||||
// assigned to this core at this block number
|
||||
let relay_parent_block_number =
|
||||
match allowed_relay_parents.acquire_info(bc.descriptor().relay_parent, None) {
|
||||
Some((_, block_num)) => block_num,
|
||||
None => {
|
||||
log::debug!(target: LOG_TARGET, "Relay parent {:?} for candidate is not in the allowed relay parents. Dropping the candidate.", bc.descriptor().relay_parent);
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Relay parent {:?} for candidate is not in the allowed relay parents. Dropping the candidate.",
|
||||
bc.descriptor().relay_parent
|
||||
);
|
||||
return false
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Get the group index for the core
|
||||
@@ -1208,12 +1195,15 @@ fn filter_backed_statements_from_disabled_validators<T: shared::Config + schedul
|
||||
None => {
|
||||
log::debug!(target: LOG_TARGET, "Can't get the validators from group {:?}. Dropping the candidate.", group_idx);
|
||||
return false
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Bitmask with the disabled indices within the validator group
|
||||
let disabled_indices = BitVec::<u8, bitvec::order::Lsb0>::from_iter(validator_group.iter().map(|idx| disabled_validators.contains(idx)));
|
||||
// The indices of statements from disabled validators in `BackedCandidate`. We have to drop these.
|
||||
let disabled_indices = BitVec::<u8, bitvec::order::Lsb0>::from_iter(
|
||||
validator_group.iter().map(|idx| disabled_validators.contains(idx)),
|
||||
);
|
||||
// The indices of statements from disabled validators in `BackedCandidate`. We have to drop
|
||||
// these.
|
||||
let indices_to_drop = disabled_indices.clone() & &validator_indices;
|
||||
// Apply the bitmask to drop the disabled validator from `validator_indices`
|
||||
validator_indices &= !disabled_indices;
|
||||
@@ -1225,62 +1215,218 @@ fn filter_backed_statements_from_disabled_validators<T: shared::Config + schedul
|
||||
bc.validity_votes_mut().remove(idx);
|
||||
}
|
||||
|
||||
// If at least one statement was dropped we need to return `true`
|
||||
if indices_to_drop.count_ones() > 0 {
|
||||
filtered = true;
|
||||
}
|
||||
|
||||
// By filtering votes we might render the candidate invalid and cause a failure in
|
||||
// [`process_candidates`]. To avoid this we have to perform a sanity check here. If there
|
||||
// are not enough backing votes after filtering we will remove the whole candidate.
|
||||
if bc.validity_votes().len() < effective_minimum_backing_votes(
|
||||
validator_group.len(),
|
||||
minimum_backing_votes
|
||||
) {
|
||||
if bc.validity_votes().len() <
|
||||
effective_minimum_backing_votes(validator_group.len(), minimum_backing_votes)
|
||||
{
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Dropping candidate {:?} of paraid {:?} because it was left with too few backing votes after votes from disabled validators were filtered.",
|
||||
bc.candidate().hash(),
|
||||
para_id
|
||||
);
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
// Also return `true` if a whole candidate was dropped from the set
|
||||
filtered || backed_len_before != backed_candidates_with_core.len()
|
||||
// Check that candidates pertaining to the same para form a chain. Drop the ones that
|
||||
// don't, along with the rest of candidates which follow them in the input vector.
|
||||
// In the process, duplicated candidates will also be dropped (even if they form a valid cycle;
|
||||
// cycles are not allowed if they entail backing duplicated candidates).
|
||||
fn filter_unchained_candidates<T: inclusion::Config + paras::Config + inclusion::Config>(
|
||||
candidates: &mut BTreeMap<ParaId, Vec<BackedCandidate<T::Hash>>>,
|
||||
allowed_relay_parents: &AllowedRelayParentsTracker<T::Hash, BlockNumberFor<T>>,
|
||||
) {
|
||||
let mut para_latest_head_data: BTreeMap<ParaId, HeadData> = BTreeMap::new();
|
||||
for para_id in candidates.keys() {
|
||||
let latest_head_data = match <inclusion::Pallet<T>>::para_latest_head_data(¶_id) {
|
||||
None => {
|
||||
defensive!("Latest included head data for paraid {:?} is None", para_id);
|
||||
continue
|
||||
},
|
||||
Some(latest_head_data) => latest_head_data,
|
||||
};
|
||||
para_latest_head_data.insert(*para_id, latest_head_data);
|
||||
}
|
||||
|
||||
let mut para_visited_candidates: BTreeMap<ParaId, BTreeSet<CandidateHash>> = BTreeMap::new();
|
||||
|
||||
retain_candidates::<T, _, _>(candidates, |para_id, candidate| {
|
||||
let Some(latest_head_data) = para_latest_head_data.get(¶_id) else { return false };
|
||||
let candidate_hash = candidate.candidate().hash();
|
||||
|
||||
let visited_candidates =
|
||||
para_visited_candidates.entry(para_id).or_insert_with(|| BTreeSet::new());
|
||||
if visited_candidates.contains(&candidate_hash) {
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Found duplicate candidates for paraid {:?}. Dropping the candidates with hash {:?}",
|
||||
para_id,
|
||||
candidate_hash
|
||||
);
|
||||
|
||||
// If we got a duplicate candidate, stop.
|
||||
return false
|
||||
} else {
|
||||
visited_candidates.insert(candidate_hash);
|
||||
}
|
||||
|
||||
let prev_context = <paras::Pallet<T>>::para_most_recent_context(para_id);
|
||||
let check_ctx = CandidateCheckContext::<T>::new(prev_context);
|
||||
|
||||
let res = match check_ctx.verify_backed_candidate(
|
||||
&allowed_relay_parents,
|
||||
candidate.candidate(),
|
||||
latest_head_data.clone(),
|
||||
) {
|
||||
Ok(_) => true,
|
||||
Err(err) => {
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Backed candidate verification for candidate {:?} of paraid {:?} failed with {:?}",
|
||||
candidate_hash,
|
||||
para_id,
|
||||
err
|
||||
);
|
||||
false
|
||||
},
|
||||
};
|
||||
|
||||
if res {
|
||||
para_latest_head_data
|
||||
.insert(para_id, candidate.candidate().commitments.head_data.clone());
|
||||
}
|
||||
|
||||
res
|
||||
});
|
||||
}
|
||||
|
||||
/// Map candidates to scheduled cores.
|
||||
/// If the para only has one scheduled core and no `CoreIndex` is injected, map the candidate to the
|
||||
/// If the para only has one scheduled core and one candidate supplied, map the candidate to the
|
||||
/// single core. If the para has multiple cores scheduled, only map the candidates which have a
|
||||
/// proper core injected. Filter out the rest.
|
||||
/// Also returns whether or not we dropped any candidates.
|
||||
/// When dropping a candidate of a para, we must drop all subsequent candidates from that para
|
||||
/// (because they form a chain).
|
||||
fn map_candidates_to_cores<T: configuration::Config + scheduler::Config + inclusion::Config>(
|
||||
allowed_relay_parents: &AllowedRelayParentsTracker<T::Hash, BlockNumberFor<T>>,
|
||||
mut scheduled: BTreeMap<ParaId, BTreeSet<CoreIndex>>,
|
||||
core_index_enabled: bool,
|
||||
candidates: Vec<BackedCandidate<T::Hash>>,
|
||||
) -> Vec<(BackedCandidate<T::Hash>, CoreIndex)> {
|
||||
let mut backed_candidates_with_core = Vec::with_capacity(candidates.len());
|
||||
candidates: BTreeMap<ParaId, Vec<BackedCandidate<T::Hash>>>,
|
||||
) -> BTreeMap<ParaId, Vec<(BackedCandidate<T::Hash>, CoreIndex)>> {
|
||||
let mut backed_candidates_with_core = BTreeMap::new();
|
||||
|
||||
// We keep a candidate if the parachain has only one core assigned or if
|
||||
// a core index is provided by block author and it's indeed scheduled.
|
||||
for backed_candidate in candidates {
|
||||
let maybe_injected_core_index = get_injected_core_index::<T>(
|
||||
allowed_relay_parents,
|
||||
&backed_candidate,
|
||||
core_index_enabled,
|
||||
for (para_id, backed_candidates) in candidates.into_iter() {
|
||||
if backed_candidates.len() == 0 {
|
||||
defensive!("Backed candidates for paraid {} is empty.", para_id);
|
||||
continue
|
||||
}
|
||||
|
||||
let scheduled_cores = scheduled.get_mut(¶_id);
|
||||
|
||||
// ParaIds without scheduled cores are silently filtered out.
|
||||
if let Some(scheduled_cores) = scheduled_cores {
|
||||
if scheduled_cores.len() == 0 {
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Paraid: {:?} has no scheduled cores but {} candidates were supplied.",
|
||||
para_id,
|
||||
backed_candidates.len()
|
||||
);
|
||||
|
||||
let scheduled_cores = scheduled.get_mut(&backed_candidate.descriptor().para_id);
|
||||
// Candidates without scheduled cores are silently filtered out.
|
||||
if let Some(scheduled_cores) = scheduled_cores {
|
||||
if let Some(core_idx) = maybe_injected_core_index {
|
||||
if scheduled_cores.contains(&core_idx) {
|
||||
scheduled_cores.remove(&core_idx);
|
||||
backed_candidates_with_core.push((backed_candidate, core_idx));
|
||||
// Non-elastic scaling case. One core per para.
|
||||
} else if scheduled_cores.len() == 1 && !core_index_enabled {
|
||||
backed_candidates_with_core.insert(
|
||||
para_id,
|
||||
vec![(
|
||||
// We need the first one here, as we assume candidates of a para are in
|
||||
// dependency order.
|
||||
backed_candidates.into_iter().next().expect("Length is at least 1"),
|
||||
scheduled_cores.pop_first().expect("Length is 1"),
|
||||
)],
|
||||
);
|
||||
continue;
|
||||
|
||||
// Elastic scaling case. We only allow candidates which have the right core
|
||||
// indices injected.
|
||||
} else if scheduled_cores.len() >= 1 && core_index_enabled {
|
||||
// We must preserve the dependency order given in the input.
|
||||
let mut temp_backed_candidates = Vec::with_capacity(scheduled_cores.len());
|
||||
|
||||
for candidate in backed_candidates {
|
||||
if scheduled_cores.len() == 0 {
|
||||
// We've got candidates for all of this para's assigned cores. Move on to
|
||||
// the next para.
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Found enough candidates for paraid: {:?}.",
|
||||
candidate.descriptor().para_id
|
||||
);
|
||||
break;
|
||||
}
|
||||
} else if scheduled_cores.len() == 1 {
|
||||
let maybe_injected_core_index: Option<CoreIndex> =
|
||||
get_injected_core_index::<T>(allowed_relay_parents, &candidate);
|
||||
|
||||
if let Some(core_index) = maybe_injected_core_index {
|
||||
if scheduled_cores.remove(&core_index) {
|
||||
temp_backed_candidates.push((candidate, core_index));
|
||||
} else {
|
||||
// if we got a candidate for a core index which is not scheduled, stop
|
||||
// the work for this para. the already processed candidate chain in
|
||||
// temp_backed_candidates is still fine though.
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Found a backed candidate {:?} with injected core index {}, which is not scheduled for paraid {:?}.",
|
||||
candidate.candidate().hash(),
|
||||
core_index.0,
|
||||
candidate.descriptor().para_id
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// if we got a candidate which does not contain its core index, stop the
|
||||
// work for this para. the already processed candidate chain in
|
||||
// temp_backed_candidates is still fine though.
|
||||
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Found a backed candidate {:?} with no injected core index, for paraid {:?} which has multiple scheduled cores.",
|
||||
candidate.candidate().hash(),
|
||||
candidate.descriptor().para_id
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if !temp_backed_candidates.is_empty() {
|
||||
backed_candidates_with_core
|
||||
.push((backed_candidate, scheduled_cores.pop_first().expect("Length is 1")));
|
||||
.entry(para_id)
|
||||
.or_insert_with(|| vec![])
|
||||
.extend(temp_backed_candidates);
|
||||
}
|
||||
} else {
|
||||
log::warn!(
|
||||
target: LOG_TARGET,
|
||||
"Found a paraid {:?} which has multiple scheduled cores but ElasticScalingMVP feature is not enabled: {:?}",
|
||||
para_id,
|
||||
scheduled_cores
|
||||
);
|
||||
}
|
||||
} else {
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Paraid: {:?} has no scheduled cores but {} candidates were supplied.",
|
||||
para_id,
|
||||
backed_candidates.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1290,13 +1436,11 @@ fn map_candidates_to_cores<T: configuration::Config + scheduler::Config + inclus
|
||||
fn get_injected_core_index<T: configuration::Config + scheduler::Config + inclusion::Config>(
|
||||
allowed_relay_parents: &AllowedRelayParentsTracker<T::Hash, BlockNumberFor<T>>,
|
||||
candidate: &BackedCandidate<T::Hash>,
|
||||
core_index_enabled: bool,
|
||||
) -> Option<CoreIndex> {
|
||||
// After stripping the 8 bit extensions, the `validator_indices` field length is expected
|
||||
// to be equal to backing group size. If these don't match, the `CoreIndex` is badly encoded,
|
||||
// or not supported.
|
||||
let (validator_indices, maybe_core_idx) =
|
||||
candidate.validator_indices_and_core_index(core_index_enabled);
|
||||
let (validator_indices, maybe_core_idx) = candidate.validator_indices_and_core_index(true);
|
||||
|
||||
let Some(core_idx) = maybe_core_idx else { return None };
|
||||
|
||||
@@ -1306,7 +1450,7 @@ fn get_injected_core_index<T: configuration::Config + scheduler::Config + inclus
|
||||
None => {
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Relay parent {:?} for candidate {:?} is not in the allowed relay parents. Dropping the candidate.",
|
||||
"Relay parent {:?} for candidate {:?} is not in the allowed relay parents.",
|
||||
candidate.descriptor().relay_parent,
|
||||
candidate.candidate().hash(),
|
||||
);
|
||||
@@ -1323,9 +1467,8 @@ fn get_injected_core_index<T: configuration::Config + scheduler::Config + inclus
|
||||
None => {
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Can't get the group index for core idx {:?}. Dropping the candidate {:?}.",
|
||||
"Can't get the group index for core idx {:?}.",
|
||||
core_idx,
|
||||
candidate.candidate().hash(),
|
||||
);
|
||||
return None
|
||||
},
|
||||
@@ -1339,6 +1482,14 @@ fn get_injected_core_index<T: configuration::Config + scheduler::Config + inclus
|
||||
if group_validators.len() == validator_indices.len() {
|
||||
Some(core_idx)
|
||||
} else {
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Expected validator_indices count different than the real one: {}, {} for candidate {:?}",
|
||||
group_validators.len(),
|
||||
validator_indices.len(),
|
||||
candidate.candidate().hash()
|
||||
);
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,7 @@ use crate::{
|
||||
scheduler::{self, CoreOccupied},
|
||||
session_info, shared,
|
||||
};
|
||||
use frame_support::traits::{GetStorageVersion, StorageVersion};
|
||||
use frame_system::pallet_prelude::*;
|
||||
use primitives::{
|
||||
async_backing::{
|
||||
@@ -92,16 +93,41 @@ pub fn availability_cores<T: initializer::Config>() -> Vec<CoreState<T::Hash, Bl
|
||||
.enumerate()
|
||||
.map(|(i, core)| match core {
|
||||
CoreOccupied::Paras(entry) => {
|
||||
let pending_availability =
|
||||
<inclusion::Pallet<T>>::pending_availability(entry.para_id())
|
||||
// Due to https://github.com/paritytech/polkadot-sdk/issues/64, using the new storage types would cause
|
||||
// this runtime API to panic. We explicitly handle the storage for version 0 to
|
||||
// prevent that. When removing the inclusion v0 -> v1 migration, this bit of code
|
||||
// can also be removed.
|
||||
let pending_availability = if <inclusion::Pallet<T>>::on_chain_storage_version() ==
|
||||
StorageVersion::new(0)
|
||||
{
|
||||
inclusion::migration::v0::PendingAvailability::<T>::get(entry.para_id())
|
||||
.expect("Occupied core always has pending availability; qed")
|
||||
} else {
|
||||
let candidate = <inclusion::Pallet<T>>::pending_availability_with_core(
|
||||
entry.para_id(),
|
||||
CoreIndex(i as u32),
|
||||
)
|
||||
.expect("Occupied core always has pending availability; qed");
|
||||
|
||||
let backed_in_number = *pending_availability.backed_in_number();
|
||||
// Translate to the old candidate format, as we don't need the commitments now.
|
||||
inclusion::migration::v0::CandidatePendingAvailability {
|
||||
core: candidate.core_occupied(),
|
||||
hash: candidate.candidate_hash(),
|
||||
descriptor: candidate.candidate_descriptor().clone(),
|
||||
availability_votes: candidate.availability_votes().clone(),
|
||||
backers: candidate.backers().clone(),
|
||||
relay_parent_number: candidate.relay_parent_number(),
|
||||
backed_in_number: candidate.backed_in_number(),
|
||||
backing_group: candidate.backing_group(),
|
||||
}
|
||||
};
|
||||
|
||||
let backed_in_number = pending_availability.backed_in_number;
|
||||
|
||||
// Use the same block number for determining the responsible group as what the
|
||||
// backing subsystem would use when it calls validator_groups api.
|
||||
let backing_group_allocation_time =
|
||||
pending_availability.relay_parent_number() + One::one();
|
||||
pending_availability.relay_parent_number + One::one();
|
||||
CoreState::Occupied(OccupiedCore {
|
||||
next_up_on_available: <scheduler::Pallet<T>>::next_up_on_available(CoreIndex(
|
||||
i as u32,
|
||||
@@ -111,13 +137,13 @@ pub fn availability_cores<T: initializer::Config>() -> Vec<CoreState<T::Hash, Bl
|
||||
next_up_on_time_out: <scheduler::Pallet<T>>::next_up_on_time_out(CoreIndex(
|
||||
i as u32,
|
||||
)),
|
||||
availability: pending_availability.availability_votes().clone(),
|
||||
availability: pending_availability.availability_votes.clone(),
|
||||
group_responsible: group_responsible_for(
|
||||
backing_group_allocation_time,
|
||||
pending_availability.core_occupied(),
|
||||
pending_availability.core,
|
||||
),
|
||||
candidate_hash: pending_availability.candidate_hash(),
|
||||
candidate_descriptor: pending_availability.candidate_descriptor().clone(),
|
||||
candidate_hash: pending_availability.hash,
|
||||
candidate_descriptor: pending_availability.descriptor,
|
||||
})
|
||||
},
|
||||
CoreOccupied::Free => {
|
||||
@@ -200,8 +226,8 @@ pub fn assumed_validation_data<T: initializer::Config>(
|
||||
};
|
||||
|
||||
let persisted_validation_data = make_validation_data().or_else(|| {
|
||||
// Try again with force enacting the core. This check only makes sense if
|
||||
// the core is occupied.
|
||||
// Try again with force enacting the pending candidates. This check only makes sense if
|
||||
// there are any pending candidates.
|
||||
<inclusion::Pallet<T>>::pending_availability(para_id).and_then(|_| {
|
||||
<inclusion::Pallet<T>>::force_enact(para_id);
|
||||
make_validation_data()
|
||||
@@ -465,27 +491,23 @@ pub fn backing_state<T: initializer::Config>(
|
||||
};
|
||||
|
||||
let pending_availability = {
|
||||
// Note: the API deals with a `Vec` as it is future-proof for cases
|
||||
// where there may be multiple candidates pending availability at a time.
|
||||
// But at the moment only one candidate can be pending availability per
|
||||
// parachain.
|
||||
crate::inclusion::PendingAvailability::<T>::get(¶_id)
|
||||
.and_then(|pending| {
|
||||
let commitments =
|
||||
crate::inclusion::PendingAvailabilityCommitments::<T>::get(¶_id);
|
||||
commitments.map(move |c| (pending, c))
|
||||
})
|
||||
.map(|(pending, commitments)| {
|
||||
.map(|pending_candidates| {
|
||||
pending_candidates
|
||||
.into_iter()
|
||||
.map(|candidate| {
|
||||
CandidatePendingAvailability {
|
||||
candidate_hash: pending.candidate_hash(),
|
||||
descriptor: pending.candidate_descriptor().clone(),
|
||||
commitments,
|
||||
relay_parent_number: pending.relay_parent_number(),
|
||||
max_pov_size: constraints.max_pov_size, // assume always same in session.
|
||||
candidate_hash: candidate.candidate_hash(),
|
||||
descriptor: candidate.candidate_descriptor().clone(),
|
||||
commitments: candidate.candidate_commitments().clone(),
|
||||
relay_parent_number: candidate.relay_parent_number(),
|
||||
max_pov_size: constraints.max_pov_size, /* assume always same in
|
||||
* session. */
|
||||
}
|
||||
})
|
||||
.into_iter()
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_else(|| vec![])
|
||||
};
|
||||
|
||||
Some(BackingState { constraints, pending_availability })
|
||||
|
||||
@@ -398,16 +398,6 @@ impl<T: Config> Pallet<T> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Get the para (chain or thread) ID assigned to a particular core or index, if any. Core
|
||||
/// indices out of bounds will return `None`, as will indices of unassigned cores.
|
||||
pub(crate) fn core_para(core_index: CoreIndex) -> Option<ParaId> {
|
||||
let cores = AvailabilityCores::<T>::get();
|
||||
match cores.get(core_index.0 as usize) {
|
||||
None | Some(CoreOccupied::Free) => None,
|
||||
Some(CoreOccupied::Paras(entry)) => Some(entry.para_id()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the validators in the given group, if the group index is valid for this session.
|
||||
pub(crate) fn group_validators(group_index: GroupIndex) -> Option<Vec<ValidatorIndex>> {
|
||||
ValidatorGroups::<T>::get().get(group_index.0 as usize).map(|g| g.clone())
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//! on all modules.
|
||||
|
||||
use frame_system::pallet_prelude::BlockNumberFor;
|
||||
use primitives::{Id as ParaId, PersistedValidationData, ValidatorIndex};
|
||||
use primitives::{HeadData, Id as ParaId, PersistedValidationData, ValidatorIndex};
|
||||
use sp_std::{collections::btree_set::BTreeSet, vec::Vec};
|
||||
|
||||
use crate::{configuration, hrmp, paras};
|
||||
@@ -42,6 +42,23 @@ pub fn make_persisted_validation_data<T: paras::Config + hrmp::Config>(
|
||||
})
|
||||
}
|
||||
|
||||
/// Make the persisted validation data for a particular parachain, a specified relay-parent, its
|
||||
/// storage root and parent head data.
|
||||
pub fn make_persisted_validation_data_with_parent<T: configuration::Config>(
|
||||
relay_parent_number: BlockNumberFor<T>,
|
||||
relay_parent_storage_root: T::Hash,
|
||||
parent_head: HeadData,
|
||||
) -> PersistedValidationData<T::Hash, BlockNumberFor<T>> {
|
||||
let config = <configuration::Pallet<T>>::config();
|
||||
|
||||
PersistedValidationData {
|
||||
parent_head,
|
||||
relay_parent_number,
|
||||
relay_parent_storage_root,
|
||||
max_pov_size: config.max_pov_size,
|
||||
}
|
||||
}
|
||||
|
||||
/// Take an active subset of a set containing all validators.
|
||||
///
|
||||
/// First item in pair will be all items in set have indices found in the `active` indices set (in
|
||||
|
||||
@@ -1663,6 +1663,8 @@ pub mod migrations {
|
||||
|
||||
// permanent
|
||||
pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
|
||||
|
||||
parachains_inclusion::migration::MigrateToV1<Runtime>,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,161 +13,322 @@
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Autogenerated weights for `runtime_parachains::paras_inherent`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2021-11-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 128
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
|
||||
//! DATE: 2024-03-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
|
||||
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// target/release/polkadot
|
||||
// target/production/polkadot
|
||||
// benchmark
|
||||
// --chain=rococo-dev
|
||||
// pallet
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=runtime_parachains::paras_inherent
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --heap-pages=4096
|
||||
// --output=./runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs
|
||||
// --header=./file_header.txt
|
||||
// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
|
||||
// --pallet=runtime_parachains::paras_inherent
|
||||
// --chain=rococo-dev
|
||||
// --header=./polkadot/file_header.txt
|
||||
// --output=./polkadot/runtime/rococo/src/weights/
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use sp_std::marker::PhantomData;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// Weight functions for `runtime_parachains::paras_inherent`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> runtime_parachains::paras_inherent::WeightInfo for WeightInfo<T> {
|
||||
// Storage: ParaInherent Included (r:1 w:1)
|
||||
// Storage: System ParentHash (r:1 w:0)
|
||||
// Storage: ParaScheduler AvailabilityCores (r:1 w:1)
|
||||
// Storage: ParasShared CurrentSessionIndex (r:1 w:0)
|
||||
// Storage: Configuration ActiveConfig (r:1 w:0)
|
||||
// Storage: ParaSessionInfo Sessions (r:1 w:0)
|
||||
// Storage: ParasDisputes Disputes (r:1 w:1)
|
||||
// Storage: ParasDisputes Included (r:1 w:1)
|
||||
// Storage: ParasDisputes SpamSlots (r:1 w:1)
|
||||
// Storage: ParasDisputes Frozen (r:1 w:0)
|
||||
// Storage: ParaInclusion PendingAvailability (r:2 w:1)
|
||||
// Storage: ParasShared ActiveValidatorKeys (r:1 w:0)
|
||||
// Storage: Paras Parachains (r:1 w:0)
|
||||
// Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1)
|
||||
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
|
||||
// Storage: Hrmp HrmpChannelDigests (r:1 w:1)
|
||||
// Storage: Paras FutureCodeUpgrades (r:1 w:0)
|
||||
// Storage: ParaScheduler SessionStartBlock (r:1 w:0)
|
||||
// Storage: ParaScheduler ParathreadQueue (r:1 w:1)
|
||||
// Storage: ParaScheduler Scheduled (r:1 w:1)
|
||||
// Storage: ParaScheduler ValidatorGroups (r:1 w:0)
|
||||
// Storage: Ump NeedsDispatch (r:1 w:1)
|
||||
// Storage: Ump NextDispatchRoundStartWith (r:1 w:1)
|
||||
// Storage: ParaInherent OnChainVotes (r:0 w:1)
|
||||
// Storage: Hrmp HrmpWatermarks (r:0 w:1)
|
||||
// Storage: Paras Heads (r:0 w:1)
|
||||
/// Storage: `ParaInherent::Included` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `System::ParentHash` (r:1 w:0)
|
||||
/// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1)
|
||||
/// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0)
|
||||
/// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0)
|
||||
/// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParaSessionInfo::Sessions` (r:1 w:0)
|
||||
/// Proof: `ParaSessionInfo::Sessions` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Disputes` (r:1 w:1)
|
||||
/// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::BackersOnDisputes` (r:1 w:1)
|
||||
/// Proof: `ParasDisputes::BackersOnDisputes` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Included` (r:1 w:1)
|
||||
/// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaInherent::OnChainVotes` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Frozen` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaInclusion::V1` (r:2 w:1)
|
||||
/// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1)
|
||||
/// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1)
|
||||
/// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1)
|
||||
/// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0)
|
||||
/// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Registrar::Paras` (r:1 w:0)
|
||||
/// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1)
|
||||
/// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::DisabledValidators` (r:1 w:0)
|
||||
/// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1)
|
||||
/// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::Heads` (r:0 w:1)
|
||||
/// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1)
|
||||
/// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::MostRecentContext` (r:0 w:1)
|
||||
/// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// The range of component `v` is `[10, 200]`.
|
||||
fn enter_variable_disputes(v: u32, ) -> Weight {
|
||||
Weight::from_parts(352_590_000 as u64, 0)
|
||||
// Standard Error: 13_000
|
||||
.saturating_add(Weight::from_parts(49_254_000 as u64, 0).saturating_mul(v as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(24 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(16 as u64))
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `67785`
|
||||
// Estimated: `73725 + v * (23 ±0)`
|
||||
// Minimum execution time: 949_716_000 picoseconds.
|
||||
Weight::from_parts(482_361_515, 0)
|
||||
.saturating_add(Weight::from_parts(0, 73725))
|
||||
// Standard Error: 17_471
|
||||
.saturating_add(Weight::from_parts(50_100_764, 0).saturating_mul(v.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(25))
|
||||
.saturating_add(T::DbWeight::get().writes(15))
|
||||
.saturating_add(Weight::from_parts(0, 23).saturating_mul(v.into()))
|
||||
}
|
||||
// Storage: ParaInherent Included (r:1 w:1)
|
||||
// Storage: System ParentHash (r:1 w:0)
|
||||
// Storage: ParaScheduler AvailabilityCores (r:1 w:1)
|
||||
// Storage: ParasShared CurrentSessionIndex (r:1 w:0)
|
||||
// Storage: Configuration ActiveConfig (r:1 w:0)
|
||||
// Storage: ParasDisputes Frozen (r:1 w:0)
|
||||
// Storage: ParasShared ActiveValidatorKeys (r:1 w:0)
|
||||
// Storage: Paras Parachains (r:1 w:0)
|
||||
// Storage: ParaInclusion PendingAvailability (r:2 w:1)
|
||||
// Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1)
|
||||
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
|
||||
// Storage: Hrmp HrmpChannelDigests (r:1 w:1)
|
||||
// Storage: Paras FutureCodeUpgrades (r:1 w:0)
|
||||
// Storage: ParasDisputes Disputes (r:1 w:0)
|
||||
// Storage: ParaScheduler SessionStartBlock (r:1 w:0)
|
||||
// Storage: ParaScheduler ParathreadQueue (r:1 w:1)
|
||||
// Storage: ParaScheduler Scheduled (r:1 w:1)
|
||||
// Storage: ParaScheduler ValidatorGroups (r:1 w:0)
|
||||
// Storage: Ump NeedsDispatch (r:1 w:1)
|
||||
// Storage: Ump NextDispatchRoundStartWith (r:1 w:1)
|
||||
// Storage: ParaInclusion AvailabilityBitfields (r:0 w:1)
|
||||
// Storage: ParaInherent OnChainVotes (r:0 w:1)
|
||||
// Storage: ParasDisputes Included (r:0 w:1)
|
||||
// Storage: Hrmp HrmpWatermarks (r:0 w:1)
|
||||
// Storage: Paras Heads (r:0 w:1)
|
||||
/// Storage: `ParaInherent::Included` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `System::ParentHash` (r:1 w:0)
|
||||
/// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1)
|
||||
/// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0)
|
||||
/// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0)
|
||||
/// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParaInherent::OnChainVotes` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Frozen` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaInclusion::V1` (r:2 w:1)
|
||||
/// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1)
|
||||
/// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1)
|
||||
/// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1)
|
||||
/// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0)
|
||||
/// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Registrar::Paras` (r:1 w:0)
|
||||
/// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Disputes` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1)
|
||||
/// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::DisabledValidators` (r:1 w:0)
|
||||
/// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Included` (r:0 w:1)
|
||||
/// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1)
|
||||
/// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::Heads` (r:0 w:1)
|
||||
/// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1)
|
||||
/// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::MostRecentContext` (r:0 w:1)
|
||||
/// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
fn enter_bitfields() -> Weight {
|
||||
Weight::from_parts(299_878_000 as u64, 0)
|
||||
.saturating_add(T::DbWeight::get().reads(21 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(15 as u64))
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `42757`
|
||||
// Estimated: `48697`
|
||||
// Minimum execution time: 437_627_000 picoseconds.
|
||||
Weight::from_parts(460_975_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 48697))
|
||||
.saturating_add(T::DbWeight::get().reads(23))
|
||||
.saturating_add(T::DbWeight::get().writes(15))
|
||||
}
|
||||
// Storage: ParaInherent Included (r:1 w:1)
|
||||
// Storage: System ParentHash (r:1 w:0)
|
||||
// Storage: ParaScheduler AvailabilityCores (r:1 w:1)
|
||||
// Storage: ParasShared CurrentSessionIndex (r:1 w:0)
|
||||
// Storage: Configuration ActiveConfig (r:1 w:0)
|
||||
// Storage: ParasDisputes Frozen (r:1 w:0)
|
||||
// Storage: ParasShared ActiveValidatorKeys (r:1 w:0)
|
||||
// Storage: Paras Parachains (r:1 w:0)
|
||||
// Storage: ParaInclusion PendingAvailability (r:2 w:1)
|
||||
// Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1)
|
||||
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
|
||||
// Storage: Hrmp HrmpChannelDigests (r:1 w:1)
|
||||
// Storage: Paras FutureCodeUpgrades (r:1 w:0)
|
||||
// Storage: ParasDisputes Disputes (r:2 w:0)
|
||||
// Storage: ParaScheduler SessionStartBlock (r:1 w:0)
|
||||
// Storage: ParaScheduler ParathreadQueue (r:1 w:1)
|
||||
// Storage: ParaScheduler Scheduled (r:1 w:1)
|
||||
// Storage: ParaScheduler ValidatorGroups (r:1 w:0)
|
||||
// Storage: Paras PastCodeMeta (r:1 w:0)
|
||||
// Storage: Paras CurrentCodeHash (r:1 w:0)
|
||||
// Storage: Ump RelayDispatchQueueSize (r:1 w:0)
|
||||
// Storage: Ump NeedsDispatch (r:1 w:1)
|
||||
// Storage: Ump NextDispatchRoundStartWith (r:1 w:1)
|
||||
// Storage: ParaInherent OnChainVotes (r:0 w:1)
|
||||
// Storage: ParasDisputes Included (r:0 w:1)
|
||||
// Storage: Hrmp HrmpWatermarks (r:0 w:1)
|
||||
// Storage: Paras Heads (r:0 w:1)
|
||||
fn enter_backed_candidates_variable(_v: u32) -> Weight {
|
||||
Weight::from_parts(442_472_000 as u64, 0)
|
||||
.saturating_add(T::DbWeight::get().reads(25 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(14 as u64))
|
||||
/// Storage: `ParaInherent::Included` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `System::ParentHash` (r:1 w:0)
|
||||
/// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1)
|
||||
/// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0)
|
||||
/// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0)
|
||||
/// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParaInherent::OnChainVotes` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Frozen` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaInclusion::V1` (r:2 w:1)
|
||||
/// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1)
|
||||
/// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1)
|
||||
/// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1)
|
||||
/// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0)
|
||||
/// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Registrar::Paras` (r:1 w:0)
|
||||
/// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Disputes` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1)
|
||||
/// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::CurrentCodeHash` (r:1 w:0)
|
||||
/// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::ParaLifecycles` (r:1 w:0)
|
||||
/// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `MessageQueue::BookStateFor` (r:1 w:0)
|
||||
/// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::DisabledValidators` (r:1 w:0)
|
||||
/// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Included` (r:0 w:1)
|
||||
/// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1)
|
||||
/// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::Heads` (r:0 w:1)
|
||||
/// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1)
|
||||
/// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::MostRecentContext` (r:0 w:1)
|
||||
/// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// The range of component `v` is `[101, 200]`.
|
||||
fn enter_backed_candidates_variable(v: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `42829`
|
||||
// Estimated: `48769`
|
||||
// Minimum execution time: 1_305_254_000 picoseconds.
|
||||
Weight::from_parts(1_347_160_667, 0)
|
||||
.saturating_add(Weight::from_parts(0, 48769))
|
||||
// Standard Error: 22_128
|
||||
.saturating_add(Weight::from_parts(57_229, 0).saturating_mul(v.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(26))
|
||||
.saturating_add(T::DbWeight::get().writes(15))
|
||||
}
|
||||
// Storage: ParaInherent Included (r:1 w:1)
|
||||
// Storage: System ParentHash (r:1 w:0)
|
||||
// Storage: ParaScheduler AvailabilityCores (r:1 w:1)
|
||||
// Storage: ParasShared CurrentSessionIndex (r:1 w:0)
|
||||
// Storage: Configuration ActiveConfig (r:1 w:0)
|
||||
// Storage: ParasDisputes Frozen (r:1 w:0)
|
||||
// Storage: ParasShared ActiveValidatorKeys (r:1 w:0)
|
||||
// Storage: Paras Parachains (r:1 w:0)
|
||||
// Storage: ParaInclusion PendingAvailability (r:2 w:1)
|
||||
// Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1)
|
||||
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
|
||||
// Storage: Hrmp HrmpChannelDigests (r:1 w:1)
|
||||
// Storage: Paras FutureCodeUpgrades (r:1 w:0)
|
||||
// Storage: ParasDisputes Disputes (r:2 w:0)
|
||||
// Storage: ParaScheduler SessionStartBlock (r:1 w:0)
|
||||
// Storage: ParaScheduler ParathreadQueue (r:1 w:1)
|
||||
// Storage: ParaScheduler Scheduled (r:1 w:1)
|
||||
// Storage: ParaScheduler ValidatorGroups (r:1 w:0)
|
||||
// Storage: Paras PastCodeMeta (r:1 w:0)
|
||||
// Storage: Paras CurrentCodeHash (r:1 w:0)
|
||||
// Storage: Ump RelayDispatchQueueSize (r:1 w:0)
|
||||
// Storage: Ump NeedsDispatch (r:1 w:1)
|
||||
// Storage: Ump NextDispatchRoundStartWith (r:1 w:1)
|
||||
// Storage: ParaInherent OnChainVotes (r:0 w:1)
|
||||
// Storage: ParasDisputes Included (r:0 w:1)
|
||||
// Storage: Hrmp HrmpWatermarks (r:0 w:1)
|
||||
// Storage: Paras Heads (r:0 w:1)
|
||||
/// Storage: `ParaInherent::Included` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `System::ParentHash` (r:1 w:0)
|
||||
/// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1)
|
||||
/// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0)
|
||||
/// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0)
|
||||
/// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParaInherent::OnChainVotes` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Frozen` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaInclusion::V1` (r:2 w:1)
|
||||
/// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1)
|
||||
/// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1)
|
||||
/// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1)
|
||||
/// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0)
|
||||
/// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Registrar::Paras` (r:1 w:0)
|
||||
/// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Disputes` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1)
|
||||
/// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::CurrentCodeHash` (r:1 w:0)
|
||||
/// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::FutureCodeHash` (r:1 w:0)
|
||||
/// Proof: `Paras::FutureCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::UpgradeRestrictionSignal` (r:1 w:0)
|
||||
/// Proof: `Paras::UpgradeRestrictionSignal` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::ParaLifecycles` (r:1 w:0)
|
||||
/// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `MessageQueue::BookStateFor` (r:1 w:0)
|
||||
/// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::DisabledValidators` (r:1 w:0)
|
||||
/// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Included` (r:0 w:1)
|
||||
/// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1)
|
||||
/// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::Heads` (r:0 w:1)
|
||||
/// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1)
|
||||
/// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::MostRecentContext` (r:0 w:1)
|
||||
/// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
fn enter_backed_candidate_code_upgrade() -> Weight {
|
||||
Weight::from_parts(36_903_411_000 as u64, 0)
|
||||
.saturating_add(T::DbWeight::get().reads(25 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(14 as u64))
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `42842`
|
||||
// Estimated: `48782`
|
||||
// Minimum execution time: 38_637_547_000 picoseconds.
|
||||
Weight::from_parts(41_447_412_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 48782))
|
||||
.saturating_add(T::DbWeight::get().reads(28))
|
||||
.saturating_add(T::DbWeight::get().writes(15))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1781,6 +1781,7 @@ pub mod migrations {
|
||||
crate::xcm_config::XcmRouter,
|
||||
GetLegacyLeaseImpl,
|
||||
>,
|
||||
parachains_inclusion::migration::MigrateToV1<Runtime>,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
//! Autogenerated weights for `runtime_parachains::paras_inherent`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-06-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
|
||||
//! DATE: 2024-03-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `runner-xerhrdyb-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024
|
||||
//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
|
||||
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// target/production/polkadot
|
||||
@@ -29,14 +29,13 @@
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --heap-pages=4096
|
||||
// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json
|
||||
// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
|
||||
// --pallet=runtime_parachains::paras_inherent
|
||||
// --chain=westend-dev
|
||||
// --header=./file_header.txt
|
||||
// --output=./runtime/westend/src/weights/
|
||||
// --header=./polkadot/file_header.txt
|
||||
// --output=./polkadot/runtime/westend/src/weights/
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
@@ -49,297 +48,311 @@ use core::marker::PhantomData;
|
||||
/// Weight functions for `runtime_parachains::paras_inherent`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> runtime_parachains::paras_inherent::WeightInfo for WeightInfo<T> {
|
||||
/// Storage: ParaInherent Included (r:1 w:1)
|
||||
/// Proof Skipped: ParaInherent Included (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: System ParentHash (r:1 w:0)
|
||||
/// Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen)
|
||||
/// Storage: ParasShared CurrentSessionIndex (r:1 w:0)
|
||||
/// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler AvailabilityCores (r:1 w:1)
|
||||
/// Proof Skipped: ParaScheduler AvailabilityCores (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParasShared ActiveValidatorKeys (r:1 w:0)
|
||||
/// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Babe AuthorVrfRandomness (r:1 w:0)
|
||||
/// Proof: Babe AuthorVrfRandomness (max_values: Some(1), max_size: Some(33), added: 528, mode: MaxEncodedLen)
|
||||
/// Storage: ParaSessionInfo Sessions (r:1 w:0)
|
||||
/// Proof Skipped: ParaSessionInfo Sessions (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParasDisputes Disputes (r:1 w:1)
|
||||
/// Proof Skipped: ParasDisputes Disputes (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParasDisputes BackersOnDisputes (r:1 w:1)
|
||||
/// Proof Skipped: ParasDisputes BackersOnDisputes (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParasDisputes Included (r:1 w:1)
|
||||
/// Proof Skipped: ParasDisputes Included (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParaSessionInfo AccountKeys (r:1 w:0)
|
||||
/// Proof Skipped: ParaSessionInfo AccountKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Session Validators (r:1 w:0)
|
||||
/// Proof Skipped: Session Validators (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Staking ActiveEra (r:1 w:0)
|
||||
/// Proof: Staking ActiveEra (max_values: Some(1), max_size: Some(13), added: 508, mode: MaxEncodedLen)
|
||||
/// Storage: Staking ErasRewardPoints (r:1 w:1)
|
||||
/// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParaInherent OnChainVotes (r:1 w:1)
|
||||
/// Proof Skipped: ParaInherent OnChainVotes (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParasDisputes Frozen (r:1 w:0)
|
||||
/// Proof Skipped: ParasDisputes Frozen (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaInclusion PendingAvailability (r:2 w:1)
|
||||
/// Proof Skipped: ParaInclusion PendingAvailability (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras Parachains (r:1 w:0)
|
||||
/// Proof Skipped: Paras Parachains (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1)
|
||||
/// Proof Skipped: ParaInclusion PendingAvailabilityCommitments (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Dmp DownwardMessageQueues (r:1 w:1)
|
||||
/// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Dmp DeliveryFeeFactor (r:1 w:1)
|
||||
/// Proof Skipped: Dmp DeliveryFeeFactor (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Hrmp HrmpChannelDigests (r:1 w:1)
|
||||
/// Proof Skipped: Hrmp HrmpChannelDigests (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras FutureCodeUpgrades (r:1 w:0)
|
||||
/// Proof Skipped: Paras FutureCodeUpgrades (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler SessionStartBlock (r:1 w:0)
|
||||
/// Proof Skipped: ParaScheduler SessionStartBlock (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler ParathreadQueue (r:1 w:1)
|
||||
/// Proof Skipped: ParaScheduler ParathreadQueue (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler Scheduled (r:1 w:1)
|
||||
/// Proof Skipped: ParaScheduler Scheduled (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler ValidatorGroups (r:1 w:0)
|
||||
/// Proof Skipped: ParaScheduler ValidatorGroups (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Hrmp HrmpWatermarks (r:0 w:1)
|
||||
/// Proof Skipped: Hrmp HrmpWatermarks (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras Heads (r:0 w:1)
|
||||
/// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras UpgradeGoAheadSignal (r:0 w:1)
|
||||
/// Proof Skipped: Paras UpgradeGoAheadSignal (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: `ParaInherent::Included` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `System::ParentHash` (r:1 w:0)
|
||||
/// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1)
|
||||
/// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0)
|
||||
/// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0)
|
||||
/// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParaSessionInfo::Sessions` (r:1 w:0)
|
||||
/// Proof: `ParaSessionInfo::Sessions` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Disputes` (r:1 w:1)
|
||||
/// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::BackersOnDisputes` (r:1 w:1)
|
||||
/// Proof: `ParasDisputes::BackersOnDisputes` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Included` (r:1 w:1)
|
||||
/// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaSessionInfo::AccountKeys` (r:1 w:0)
|
||||
/// Proof: `ParaSessionInfo::AccountKeys` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::Validators` (r:1 w:0)
|
||||
/// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Staking::ActiveEra` (r:1 w:0)
|
||||
/// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::ErasRewardPoints` (r:1 w:1)
|
||||
/// Proof: `Staking::ErasRewardPoints` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaInherent::OnChainVotes` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Frozen` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaInclusion::V1` (r:2 w:1)
|
||||
/// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1)
|
||||
/// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1)
|
||||
/// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1)
|
||||
/// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0)
|
||||
/// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1)
|
||||
/// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::DisabledValidators` (r:1 w:0)
|
||||
/// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1)
|
||||
/// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::Heads` (r:0 w:1)
|
||||
/// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1)
|
||||
/// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::MostRecentContext` (r:0 w:1)
|
||||
/// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// The range of component `v` is `[10, 200]`.
|
||||
fn enter_variable_disputes(v: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `50518`
|
||||
// Estimated: `56458 + v * (23 ±0)`
|
||||
// Minimum execution time: 998_338_000 picoseconds.
|
||||
Weight::from_parts(468_412_001, 0)
|
||||
.saturating_add(Weight::from_parts(0, 56458))
|
||||
// Standard Error: 20_559
|
||||
.saturating_add(Weight::from_parts(56_965_025, 0).saturating_mul(v.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(27))
|
||||
.saturating_add(T::DbWeight::get().writes(15))
|
||||
// Measured: `67518`
|
||||
// Estimated: `73458 + v * (23 ±0)`
|
||||
// Minimum execution time: 844_022_000 picoseconds.
|
||||
Weight::from_parts(456_682_337, 0)
|
||||
.saturating_add(Weight::from_parts(0, 73458))
|
||||
// Standard Error: 16_403
|
||||
.saturating_add(Weight::from_parts(41_871_245, 0).saturating_mul(v.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(28))
|
||||
.saturating_add(T::DbWeight::get().writes(16))
|
||||
.saturating_add(Weight::from_parts(0, 23).saturating_mul(v.into()))
|
||||
}
|
||||
/// Storage: ParaInherent Included (r:1 w:1)
|
||||
/// Proof Skipped: ParaInherent Included (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: System ParentHash (r:1 w:0)
|
||||
/// Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen)
|
||||
/// Storage: ParasShared CurrentSessionIndex (r:1 w:0)
|
||||
/// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler AvailabilityCores (r:1 w:1)
|
||||
/// Proof Skipped: ParaScheduler AvailabilityCores (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParasShared ActiveValidatorKeys (r:1 w:0)
|
||||
/// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Babe AuthorVrfRandomness (r:1 w:0)
|
||||
/// Proof: Babe AuthorVrfRandomness (max_values: Some(1), max_size: Some(33), added: 528, mode: MaxEncodedLen)
|
||||
/// Storage: ParaInherent OnChainVotes (r:1 w:1)
|
||||
/// Proof Skipped: ParaInherent OnChainVotes (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParasDisputes Frozen (r:1 w:0)
|
||||
/// Proof Skipped: ParasDisputes Frozen (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaInclusion PendingAvailability (r:2 w:1)
|
||||
/// Proof Skipped: ParaInclusion PendingAvailability (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras Parachains (r:1 w:0)
|
||||
/// Proof Skipped: Paras Parachains (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1)
|
||||
/// Proof Skipped: ParaInclusion PendingAvailabilityCommitments (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParaSessionInfo AccountKeys (r:1 w:0)
|
||||
/// Proof Skipped: ParaSessionInfo AccountKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Session Validators (r:1 w:0)
|
||||
/// Proof Skipped: Session Validators (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Staking ActiveEra (r:1 w:0)
|
||||
/// Proof: Staking ActiveEra (max_values: Some(1), max_size: Some(13), added: 508, mode: MaxEncodedLen)
|
||||
/// Storage: Staking ErasRewardPoints (r:1 w:1)
|
||||
/// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Dmp DownwardMessageQueues (r:1 w:1)
|
||||
/// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Dmp DeliveryFeeFactor (r:1 w:1)
|
||||
/// Proof Skipped: Dmp DeliveryFeeFactor (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Hrmp HrmpChannelDigests (r:1 w:1)
|
||||
/// Proof Skipped: Hrmp HrmpChannelDigests (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras FutureCodeUpgrades (r:1 w:0)
|
||||
/// Proof Skipped: Paras FutureCodeUpgrades (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParasDisputes Disputes (r:1 w:0)
|
||||
/// Proof Skipped: ParasDisputes Disputes (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler SessionStartBlock (r:1 w:0)
|
||||
/// Proof Skipped: ParaScheduler SessionStartBlock (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler ParathreadQueue (r:1 w:1)
|
||||
/// Proof Skipped: ParaScheduler ParathreadQueue (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler Scheduled (r:1 w:1)
|
||||
/// Proof Skipped: ParaScheduler Scheduled (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler ValidatorGroups (r:1 w:0)
|
||||
/// Proof Skipped: ParaScheduler ValidatorGroups (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaInclusion AvailabilityBitfields (r:0 w:1)
|
||||
/// Proof Skipped: ParaInclusion AvailabilityBitfields (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParasDisputes Included (r:0 w:1)
|
||||
/// Proof Skipped: ParasDisputes Included (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Hrmp HrmpWatermarks (r:0 w:1)
|
||||
/// Proof Skipped: Hrmp HrmpWatermarks (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras Heads (r:0 w:1)
|
||||
/// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras UpgradeGoAheadSignal (r:0 w:1)
|
||||
/// Proof Skipped: Paras UpgradeGoAheadSignal (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: `ParaInherent::Included` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `System::ParentHash` (r:1 w:0)
|
||||
/// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1)
|
||||
/// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0)
|
||||
/// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0)
|
||||
/// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParaInherent::OnChainVotes` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Frozen` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaInclusion::V1` (r:2 w:1)
|
||||
/// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaSessionInfo::AccountKeys` (r:1 w:0)
|
||||
/// Proof: `ParaSessionInfo::AccountKeys` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::Validators` (r:1 w:0)
|
||||
/// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Staking::ActiveEra` (r:1 w:0)
|
||||
/// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::ErasRewardPoints` (r:1 w:1)
|
||||
/// Proof: `Staking::ErasRewardPoints` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1)
|
||||
/// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1)
|
||||
/// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1)
|
||||
/// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0)
|
||||
/// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Disputes` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1)
|
||||
/// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::DisabledValidators` (r:1 w:0)
|
||||
/// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Included` (r:0 w:1)
|
||||
/// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1)
|
||||
/// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::Heads` (r:0 w:1)
|
||||
/// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1)
|
||||
/// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::MostRecentContext` (r:0 w:1)
|
||||
/// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
fn enter_bitfields() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `42352`
|
||||
// Estimated: `48292`
|
||||
// Minimum execution time: 457_404_000 picoseconds.
|
||||
Weight::from_parts(485_416_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 48292))
|
||||
.saturating_add(T::DbWeight::get().reads(25))
|
||||
// Measured: `43196`
|
||||
// Estimated: `49136`
|
||||
// Minimum execution time: 438_637_000 picoseconds.
|
||||
Weight::from_parts(458_342_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 49136))
|
||||
.saturating_add(T::DbWeight::get().reads(26))
|
||||
.saturating_add(T::DbWeight::get().writes(16))
|
||||
}
|
||||
/// Storage: ParaInherent Included (r:1 w:1)
|
||||
/// Proof Skipped: ParaInherent Included (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: System ParentHash (r:1 w:0)
|
||||
/// Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen)
|
||||
/// Storage: ParasShared CurrentSessionIndex (r:1 w:0)
|
||||
/// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler AvailabilityCores (r:1 w:1)
|
||||
/// Proof Skipped: ParaScheduler AvailabilityCores (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParasShared ActiveValidatorKeys (r:1 w:0)
|
||||
/// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Babe AuthorVrfRandomness (r:1 w:0)
|
||||
/// Proof: Babe AuthorVrfRandomness (max_values: Some(1), max_size: Some(33), added: 528, mode: MaxEncodedLen)
|
||||
/// Storage: ParaInherent OnChainVotes (r:1 w:1)
|
||||
/// Proof Skipped: ParaInherent OnChainVotes (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParasDisputes Frozen (r:1 w:0)
|
||||
/// Proof Skipped: ParasDisputes Frozen (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaInclusion PendingAvailability (r:2 w:1)
|
||||
/// Proof Skipped: ParaInclusion PendingAvailability (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras Parachains (r:1 w:0)
|
||||
/// Proof Skipped: Paras Parachains (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1)
|
||||
/// Proof Skipped: ParaInclusion PendingAvailabilityCommitments (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParaSessionInfo AccountKeys (r:1 w:0)
|
||||
/// Proof Skipped: ParaSessionInfo AccountKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Session Validators (r:1 w:0)
|
||||
/// Proof Skipped: Session Validators (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Staking ActiveEra (r:1 w:0)
|
||||
/// Proof: Staking ActiveEra (max_values: Some(1), max_size: Some(13), added: 508, mode: MaxEncodedLen)
|
||||
/// Storage: Staking ErasRewardPoints (r:1 w:1)
|
||||
/// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Dmp DownwardMessageQueues (r:1 w:1)
|
||||
/// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Dmp DeliveryFeeFactor (r:1 w:1)
|
||||
/// Proof Skipped: Dmp DeliveryFeeFactor (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Hrmp HrmpChannelDigests (r:1 w:1)
|
||||
/// Proof Skipped: Hrmp HrmpChannelDigests (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras FutureCodeUpgrades (r:1 w:0)
|
||||
/// Proof Skipped: Paras FutureCodeUpgrades (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParasDisputes Disputes (r:1 w:0)
|
||||
/// Proof Skipped: ParasDisputes Disputes (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler SessionStartBlock (r:1 w:0)
|
||||
/// Proof Skipped: ParaScheduler SessionStartBlock (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler ParathreadQueue (r:1 w:1)
|
||||
/// Proof Skipped: ParaScheduler ParathreadQueue (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler Scheduled (r:1 w:1)
|
||||
/// Proof Skipped: ParaScheduler Scheduled (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler ValidatorGroups (r:1 w:0)
|
||||
/// Proof Skipped: ParaScheduler ValidatorGroups (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Paras CurrentCodeHash (r:1 w:0)
|
||||
/// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras ParaLifecycles (r:1 w:0)
|
||||
/// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:0)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen)
|
||||
/// Storage: ParasDisputes Included (r:0 w:1)
|
||||
/// Proof Skipped: ParasDisputes Included (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Hrmp HrmpWatermarks (r:0 w:1)
|
||||
/// Proof Skipped: Hrmp HrmpWatermarks (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras Heads (r:0 w:1)
|
||||
/// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras UpgradeGoAheadSignal (r:0 w:1)
|
||||
/// Proof Skipped: Paras UpgradeGoAheadSignal (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: `ParaInherent::Included` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `System::ParentHash` (r:1 w:0)
|
||||
/// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1)
|
||||
/// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0)
|
||||
/// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0)
|
||||
/// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParaInherent::OnChainVotes` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Frozen` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaInclusion::V1` (r:2 w:1)
|
||||
/// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaSessionInfo::AccountKeys` (r:1 w:0)
|
||||
/// Proof: `ParaSessionInfo::AccountKeys` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::Validators` (r:1 w:0)
|
||||
/// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Staking::ActiveEra` (r:1 w:0)
|
||||
/// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::ErasRewardPoints` (r:1 w:1)
|
||||
/// Proof: `Staking::ErasRewardPoints` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1)
|
||||
/// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1)
|
||||
/// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1)
|
||||
/// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0)
|
||||
/// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Disputes` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1)
|
||||
/// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::CurrentCodeHash` (r:1 w:0)
|
||||
/// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::ParaLifecycles` (r:1 w:0)
|
||||
/// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `MessageQueue::BookStateFor` (r:1 w:0)
|
||||
/// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::DisabledValidators` (r:1 w:0)
|
||||
/// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Included` (r:0 w:1)
|
||||
/// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1)
|
||||
/// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::Heads` (r:0 w:1)
|
||||
/// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1)
|
||||
/// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::MostRecentContext` (r:0 w:1)
|
||||
/// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// The range of component `v` is `[101, 200]`.
|
||||
fn enter_backed_candidates_variable(v: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `42387`
|
||||
// Estimated: `48327`
|
||||
// Minimum execution time: 6_864_029_000 picoseconds.
|
||||
Weight::from_parts(1_237_704_892, 0)
|
||||
.saturating_add(Weight::from_parts(0, 48327))
|
||||
// Standard Error: 33_413
|
||||
.saturating_add(Weight::from_parts(56_199_819, 0).saturating_mul(v.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(28))
|
||||
.saturating_add(T::DbWeight::get().writes(15))
|
||||
// Measured: `43269`
|
||||
// Estimated: `49209`
|
||||
// Minimum execution time: 5_955_361_000 picoseconds.
|
||||
Weight::from_parts(1_285_398_956, 0)
|
||||
.saturating_add(Weight::from_parts(0, 49209))
|
||||
// Standard Error: 57_369
|
||||
.saturating_add(Weight::from_parts(47_073_853, 0).saturating_mul(v.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(29))
|
||||
.saturating_add(T::DbWeight::get().writes(16))
|
||||
}
|
||||
/// Storage: ParaInherent Included (r:1 w:1)
|
||||
/// Proof Skipped: ParaInherent Included (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: System ParentHash (r:1 w:0)
|
||||
/// Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen)
|
||||
/// Storage: ParasShared CurrentSessionIndex (r:1 w:0)
|
||||
/// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler AvailabilityCores (r:1 w:1)
|
||||
/// Proof Skipped: ParaScheduler AvailabilityCores (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParasShared ActiveValidatorKeys (r:1 w:0)
|
||||
/// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Babe AuthorVrfRandomness (r:1 w:0)
|
||||
/// Proof: Babe AuthorVrfRandomness (max_values: Some(1), max_size: Some(33), added: 528, mode: MaxEncodedLen)
|
||||
/// Storage: ParaInherent OnChainVotes (r:1 w:1)
|
||||
/// Proof Skipped: ParaInherent OnChainVotes (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParasDisputes Frozen (r:1 w:0)
|
||||
/// Proof Skipped: ParasDisputes Frozen (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaInclusion PendingAvailability (r:2 w:1)
|
||||
/// Proof Skipped: ParaInclusion PendingAvailability (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras Parachains (r:1 w:0)
|
||||
/// Proof Skipped: Paras Parachains (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1)
|
||||
/// Proof Skipped: ParaInclusion PendingAvailabilityCommitments (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParaSessionInfo AccountKeys (r:1 w:0)
|
||||
/// Proof Skipped: ParaSessionInfo AccountKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Session Validators (r:1 w:0)
|
||||
/// Proof Skipped: Session Validators (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Staking ActiveEra (r:1 w:0)
|
||||
/// Proof: Staking ActiveEra (max_values: Some(1), max_size: Some(13), added: 508, mode: MaxEncodedLen)
|
||||
/// Storage: Staking ErasRewardPoints (r:1 w:1)
|
||||
/// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Dmp DownwardMessageQueues (r:1 w:1)
|
||||
/// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Dmp DeliveryFeeFactor (r:1 w:1)
|
||||
/// Proof Skipped: Dmp DeliveryFeeFactor (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Hrmp HrmpChannelDigests (r:1 w:1)
|
||||
/// Proof Skipped: Hrmp HrmpChannelDigests (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras FutureCodeUpgrades (r:1 w:0)
|
||||
/// Proof Skipped: Paras FutureCodeUpgrades (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParasDisputes Disputes (r:1 w:0)
|
||||
/// Proof Skipped: ParasDisputes Disputes (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler SessionStartBlock (r:1 w:0)
|
||||
/// Proof Skipped: ParaScheduler SessionStartBlock (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler ParathreadQueue (r:1 w:1)
|
||||
/// Proof Skipped: ParaScheduler ParathreadQueue (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler Scheduled (r:1 w:1)
|
||||
/// Proof Skipped: ParaScheduler Scheduled (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: ParaScheduler ValidatorGroups (r:1 w:0)
|
||||
/// Proof Skipped: ParaScheduler ValidatorGroups (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Paras CurrentCodeHash (r:1 w:0)
|
||||
/// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras FutureCodeHash (r:1 w:0)
|
||||
/// Proof Skipped: Paras FutureCodeHash (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras UpgradeRestrictionSignal (r:1 w:0)
|
||||
/// Proof Skipped: Paras UpgradeRestrictionSignal (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras ParaLifecycles (r:1 w:0)
|
||||
/// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:0)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen)
|
||||
/// Storage: ParasDisputes Included (r:0 w:1)
|
||||
/// Proof Skipped: ParasDisputes Included (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Hrmp HrmpWatermarks (r:0 w:1)
|
||||
/// Proof Skipped: Hrmp HrmpWatermarks (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras Heads (r:0 w:1)
|
||||
/// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Paras UpgradeGoAheadSignal (r:0 w:1)
|
||||
/// Proof Skipped: Paras UpgradeGoAheadSignal (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: `ParaInherent::Included` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `System::ParentHash` (r:1 w:0)
|
||||
/// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1)
|
||||
/// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0)
|
||||
/// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0)
|
||||
/// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParaInherent::OnChainVotes` (r:1 w:1)
|
||||
/// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Frozen` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaInclusion::V1` (r:2 w:1)
|
||||
/// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaSessionInfo::AccountKeys` (r:1 w:0)
|
||||
/// Proof: `ParaSessionInfo::AccountKeys` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::Validators` (r:1 w:0)
|
||||
/// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Staking::ActiveEra` (r:1 w:0)
|
||||
/// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::ErasRewardPoints` (r:1 w:1)
|
||||
/// Proof: `Staking::ErasRewardPoints` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1)
|
||||
/// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1)
|
||||
/// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1)
|
||||
/// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0)
|
||||
/// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Disputes` (r:1 w:0)
|
||||
/// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0)
|
||||
/// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1)
|
||||
/// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1)
|
||||
/// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::CurrentCodeHash` (r:1 w:0)
|
||||
/// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::FutureCodeHash` (r:1 w:0)
|
||||
/// Proof: `Paras::FutureCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::UpgradeRestrictionSignal` (r:1 w:0)
|
||||
/// Proof: `Paras::UpgradeRestrictionSignal` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::ParaLifecycles` (r:1 w:0)
|
||||
/// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `MessageQueue::BookStateFor` (r:1 w:0)
|
||||
/// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0)
|
||||
/// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::DisabledValidators` (r:1 w:0)
|
||||
/// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `ParasDisputes::Included` (r:0 w:1)
|
||||
/// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1)
|
||||
/// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::Heads` (r:0 w:1)
|
||||
/// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1)
|
||||
/// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Paras::MostRecentContext` (r:0 w:1)
|
||||
/// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
fn enter_backed_candidate_code_upgrade() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `42414`
|
||||
// Estimated: `48354`
|
||||
// Minimum execution time: 43_320_529_000 picoseconds.
|
||||
Weight::from_parts(45_622_613_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 48354))
|
||||
.saturating_add(T::DbWeight::get().reads(30))
|
||||
.saturating_add(T::DbWeight::get().writes(15))
|
||||
// Measured: `43282`
|
||||
// Estimated: `49222`
|
||||
// Minimum execution time: 42_128_606_000 picoseconds.
|
||||
Weight::from_parts(42_822_806_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 49222))
|
||||
.saturating_add(T::DbWeight::get().reads(31))
|
||||
.saturating_add(T::DbWeight::get().writes(16))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
title: "Elastic scaling: runtime dependency tracking and enactment"
|
||||
|
||||
doc:
|
||||
- audience: Node Dev
|
||||
description: |
|
||||
Adds support in the inclusion and paras_inherent runtime modules for backing and including multiple candidates of the same para if they form a chain.
|
||||
|
||||
crates: [ ]
|
||||
Reference in New Issue
Block a user