* rename GlobalValidationSchedule to GlobalValidationData * guide: update candidate descriptor to contain validation data hash * guide: add note in inclusion module about checking validation data hash * primitives: update CandidateDescriptor to contain new hash * fix payload computation * add helpers for computing validation data to runtime modules * guide: note routines * inclusion: check validation data hash and fix local_validation_data bug * add a case to candidate_checks and improve that test substantially * bump versions * address review comments * add a test for including code upgrade * bump kusama version * bump westend & polkadot versions
6.2 KiB
Inclusion Module
The inclusion module is responsible for inclusion and availability of scheduled parachains and parathreads.
Storage
Helper structs:
struct AvailabilityBitfield {
bitfield: BitVec, // one bit per core.
submitted_at: BlockNumber, // for accounting, as meaning of bits may change over time.
}
struct CandidatePendingAvailability {
core: CoreIndex, // availability core
descriptor: CandidateDescriptor,
availability_votes: Bitfield, // one bit per validator.
relay_parent_number: BlockNumber, // number of the relay-parent.
backed_in_number: BlockNumber,
}
Storage Layout:
/// The latest bitfield for each validator, referred to by index.
bitfields: map ValidatorIndex => AvailabilityBitfield;
/// Candidates pending availability.
PendingAvailability: map ParaId => CandidatePendingAvailability;
/// The commitments of candidates pending availability, by ParaId.
PendingAvailabilityCommitments: map ParaId => CandidateCommitments;
/// The current validators, by their parachain session keys.
Validators: Vec<ValidatorId>;
/// The current session index.
CurrentSessionIndex: SessionIndex;
Session Change
- Clear out all candidates pending availability.
- Clear out all validator bitfields.
- Update
Validatorswith the validators from the session change notification. - Update
CurrentSessionIndexwith the session index from the session change notification.
Routines
All failed checks should lead to an unrecoverable error making the block invalid.
-
process_bitfields(Bitfields, core_lookup: Fn(CoreIndex) -> Option<ParaId>):- check that the number of bitfields and bits in each bitfield is correct.
- check that there are no duplicates
- check all validator signatures.
- apply each bit of bitfield to the corresponding pending candidate. looking up parathread cores using the
core_lookup. Disregard bitfields that have a1bit for any free cores. - For each applied bit of each availability-bitfield, set the bit for the validator in the
CandidatePendingAvailability'savailability_votesbitfield. Track all candidates that now have >2/3 of bits set in theiravailability_votes. These candidates are now available and can be enacted. - For all now-available candidates, invoke the
enact_candidateroutine with the candidate and relay-parent number. -
TODO: pass it onwards to
Validitymodule. - Return a list of freed cores consisting of the cores where candidates have become available.
-
process_candidates(BackedCandidates, scheduled: Vec<CoreAssignment>, group_validators: Fn(GroupIndex) -> Option<Vec<ValidatorIndex>>):- check that each candidate corresponds to a scheduled core and that they are ordered in the same order the cores appear in assignments in
scheduled. - check that
scheduledis sorted ascending byCoreIndex, without duplicates. - check that there is no candidate pending availability for any scheduled
ParaId. - check that each candidate's
validation_data_hashcorresponds to a(LocalValidationData, GlobalValidationData)computed from the current state. - If the core assignment includes a specific collator, ensure the backed candidate is issued by that collator.
- Ensure that any code upgrade scheduled by the candidate does not happen within
config.validation_upgrade_frequencyofParas::last_code_upgrade(para_id, true), if any, comparing against the value ofParas::FutureCodeUpgradesfor the given para ID. - Check the collator's signature on the candidate data.
- check the backing of the candidate using the signatures and the bitfields, comparing against the validators assigned to the groups, fetched with the
group_validatorslookup. - check that the upward messages, when combined with the existing queue size, are not exceeding
config.max_upward_queue_countandconfig.watermark_upward_queue_sizeparameters. - create an entry in the
PendingAvailabilitymap for each backed candidate with a blankavailability_votesbitfield. - create a corresponding entry in the
PendingAvailabilityCommitmentswith the commitments. - Return a
Vec<CoreIndex>of all scheduled cores of the list of passed assignments that a candidate was successfully backed for, sorted ascending by CoreIndex.
- check that each candidate corresponds to a scheduled core and that they are ordered in the same order the cores appear in assignments in
-
enact_candidate(relay_parent_number: BlockNumber, CommittedCandidateReceipt):- If the receipt contains a code upgrade, Call
Paras::schedule_code_upgrade(para_id, code, relay_parent_number + config.validationl_upgrade_delay).
TODO: Note that this is safe as long as we never enact candidates where the relay parent is across a session boundary. In that case, which we should be careful to avoid with contextual execution, the configuration might have changed and the para may de-sync from the host's understanding of it.
- call
Router::queue_upward_messagesfor each backed candidate, using theUpwardMessages from theCandidateCommitments. - Call
Paras::note_new_headusing theHeadDatafrom the receipt andrelay_parent_number.
- If the receipt contains a code upgrade, Call
-
collect_pending:fn collect_pending(f: impl Fn(CoreIndex, BlockNumber) -> bool) -> Vec<u32> { // sweep through all paras pending availability. if the predicate returns true, when given the core index and // the block number the candidate has been pending availability since, then clean up the corresponding storage for that candidate and the commitments. // 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. -
candidate_pending_availability(ParaId) -> Option<CommittedCandidateReceipt>: returns theCommittedCandidateReceiptpending 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.