* Take 2 at the upward messages * Trying to restore stuff from unsuccesful rebase * Fix whitespace * Clean up * Change rustdoc to comment * Pivot to a less stricter, w.r.t. to acceptance, model * Rename `max_upward_message_num_per_candidate` * Update docs for DownwardMessage * Apply suggestions from code review Co-authored-by: Robert Habermeier <rphmeier@gmail.com> * Rephrase "Dispatchable objects ready to ..." * Finish the sentence * Add a note about imprecision of the current weight formula * Elaborate on potential use-cases for the upward message kinds. * s/later/below Co-authored-by: Robert Habermeier <rphmeier@gmail.com>
7.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 aPersistedValidationDatacomputed from the current state.
NOTE: With contextual execution in place, validation data will be obtained as of the state of the context block. However, only the state of the current block can be used for such a query.
- 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. - call
Router::check_upward_messages(para, commitments.upward_messages)to check that the upward messages are valid. - call
Router::check_processed_downward_messages(para, commitments.processed_downward_messages)to check that the DMQ is properly drained. - call
Router::check_hrmp_watermark(para, commitments.hrmp_watermark)for each candidate to check rules of processing the HRMP watermark. - check that in the commitments of each candidate the horizontal messages are sorted by ascending recipient ParaId and there is no two horizontal messages have the same recipient.
- using
Router::verify_outbound_hrmp(sender, commitments.horizontal_messages)ensure that the each candidate send a valid set of horizontal messages - 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::enact_upward_messagesfor each backed candidate, using theUpwardMessages from theCandidateCommitments. - call
Router::queue_outbound_hrmpwith the para id of the candidate and the list of horizontal messages taken from the commitment, - call
Router::prune_hrmpwith the para id of the candiate and the candidate'shrmp_watermark. - call
Router::prune_dmqwith the para id of the candidate and the candidate'sprocessed_downward_messages. - 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.