provisioner: allow multiple cores assigned to the same para (#3233)

https://github.com/paritytech/polkadot-sdk/issues/3130

builds on top of https://github.com/paritytech/polkadot-sdk/pull/3160

Processes the availability cores and builds a record of how many
candidates it should request from prospective-parachains and their
predecessors.
Tries to supply as many candidates as the runtime can back. Note that
the runtime changes to back multiple candidates per para are not yet
done, but this paves the way for it.

The following backing/inclusion policy is assumed:
1. the runtime will never back candidates of the same para which don't
form a chain with the already backed candidates. Even if the others are
still pending availability. We're optimistic that they won't time out
and we don't want to back parachain forks (as the complexity would be
huge).
2. if a candidate is timed out of the core before being included, all of
its successors occupying a core will be evicted.
3. only the candidates which are made available and form a chain
starting from the on-chain para head may be included/enacted and cleared
from the cores. In other words, if para head is at A and the cores are
occupied by B->C->D, and B and D are made available, only B will be
included and its core cleared. C and D will remain on the cores awaiting
for C to be made available or timed out. As point (2) above already
says, if C is timed out, D will also be dropped.
4. The runtime will deduplicate candidates which form a cycle. For
example if the provisioner supplies candidates A->B->A, the runtime will
only back A (as the state output will be the same)

Note that if a candidate is timed out, we don't guarantee that in the
next relay chain block the block author will be able to fill all of the
timed out cores of the para. That increases complexity by a lot.
Instead, the provisioner will supply N candidates where N is the number
of candidates timed out, but doesn't include their successors which will
be also deleted by the runtime. This'll be backfilled in the next relay
chain block.

Adjacent changes:
- Also fixes: https://github.com/paritytech/polkadot-sdk/issues/3141
- For non prospective-parachains, don't supply multiple candidates per
para (we can't have elastic scaling without prospective parachains
enabled). paras_inherent should already sanitise this input but it's
more efficient this way.

Note: all of these changes are backwards-compatible with the
non-elastic-scaling scenario (one core per para).
This commit is contained in:
Alin Dima
2024-03-01 20:25:24 +02:00
committed by GitHub
parent f0e589d72e
commit 62b78a1615
11 changed files with 1426 additions and 595 deletions
+10 -4
View File
@@ -1112,6 +1112,9 @@ pub struct ProspectiveValidationDataRequest {
/// is present in and the depths of that tree the candidate is present in.
pub type FragmentTreeMembership = Vec<(Hash, Vec<usize>)>;
/// A collection of ancestor candidates of a parachain.
pub type Ancestors = HashSet<CandidateHash>;
/// Messages sent to the Prospective Parachains subsystem.
#[derive(Debug)]
pub enum ProspectiveParachainsMessage {
@@ -1128,15 +1131,18 @@ pub enum ProspectiveParachainsMessage {
/// has been backed. This requires that the candidate was successfully introduced in
/// the past.
CandidateBacked(ParaId, CandidateHash),
/// Get N backable candidate hashes along with their relay parents for the given parachain,
/// under the given relay-parent hash, which is a descendant of the given candidate hashes.
/// Try getting N backable candidate hashes along with their relay parents for the given
/// parachain, under the given relay-parent hash, which is a descendant of the given ancestors.
/// Timed out ancestors should not be included in the collection.
/// N should represent the number of scheduled cores of this ParaId.
/// Returns `None` on the channel if no such candidate exists.
/// A timed out ancestor frees the cores of all of its descendants, so if there's a hole in the
/// supplied ancestor path, we'll get candidates that backfill those timed out slots first. It
/// may also return less/no candidates, if there aren't enough backable candidates recorded.
GetBackableCandidates(
Hash,
ParaId,
u32,
Vec<CandidateHash>,
Ancestors,
oneshot::Sender<Vec<(CandidateHash, Hash)>>,
),
/// Get the hypothetical frontier membership of candidates with the given properties