mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-22 03:21:03 +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:
@@ -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())
|
||||
.expect("Occupied core always has pending availability; qed");
|
||||
// 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_candidates| {
|
||||
pending_candidates
|
||||
.into_iter()
|
||||
.map(|candidate| {
|
||||
CandidatePendingAvailability {
|
||||
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. */
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.map(|(pending, commitments)| {
|
||||
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.
|
||||
}
|
||||
})
|
||||
.into_iter()
|
||||
.collect()
|
||||
.unwrap_or_else(|| vec![])
|
||||
};
|
||||
|
||||
Some(BackingState { constraints, pending_availability })
|
||||
|
||||
Reference in New Issue
Block a user