mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 06:21:02 +00:00
5174b9d2d7
* inclusion emulator logic for asynchronous backing (#4790) * initial stab at candidate_context * fmt * docs & more TODOs * some cleanups * reframe as inclusion_emulator * documentations yes * update types * add constraint modifications * watermark * produce modifications * v2 primitives: re-export all v1 for consistency * vstaging primitives * emulator constraints: handle code upgrades * produce outbound HRMP modifications * stack. * method for applying modifications * method just for sanity-checking modifications * fragments produce modifications, not prospectives * make linear * add some TODOs * remove stacking; handle code upgrades * take `fragment` private * reintroduce stacking. * fragment constructor * add TODO * allow validating fragments against future constraints * docs * relay-parent number and min code size checks * check code upgrade restriction * check max hrmp per candidate * fmt * remove GoAhead logic because it wasn't helpful * docs on code upgrade failure * test stacking * test modifications against constraints * fmt * test fragments * descending or duplicate test * fmt * remove unused imports in vstaging * wrong primitives * spellcheck * Runtime changes for Asynchronous Backing (#4786) * inclusion: utility for allowed relay-parents * inclusion: use prev number instead of prev hash * track most recent context of paras * inclusion: accept previous relay-parents * update dmp advancement rule for async backing * fmt * add a comment about validation outputs * clean up a couple of TODOs * weights * fix weights * fmt * Resolve dmp todo * Restore inclusion tests * Restore paras_inherent tests * MostRecentContext test * Benchmark for new paras dispatchable * Prepare check_validation_outputs for upgrade * cargo run --quiet --profile=production --features=runtime-benchmarks -- benchmark --chain=kusama-dev --steps=50 --repeat=20 --pallet=runtime_parachains::paras --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --output=./runtime/kusama/src/weights/runtime_parachains_paras.rs * cargo run --quiet --profile=production --features=runtime-benchmarks -- benchmark --chain=westend-dev --steps=50 --repeat=20 --pallet=runtime_parachains::paras --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --output=./runtime/westend/src/weights/runtime_parachains_paras.rs * cargo run --quiet --profile=production --features=runtime-benchmarks -- benchmark --chain=polkadot-dev --steps=50 --repeat=20 --pallet=runtime_parachains::paras --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --output=./runtime/polkadot/src/weights/runtime_parachains_paras.rs * cargo run --quiet --profile=production --features=runtime-benchmarks -- benchmark --chain=rococo-dev --steps=50 --repeat=20 --pallet=runtime_parachains::paras --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --output=./runtime/rococo/src/weights/runtime_parachains_paras.rs * Implementers guide changes * More tests for allowed relay parents * Add a github issue link * Compute group index based on relay parent * Storage migration * Move allowed parents tracker to shared * Compile error * Get group assigned to core at the next block * Test group assignment * fmt * Error instead of panic * Update guide * Extend doc-comment * Update runtime/parachains/src/shared.rs Co-authored-by: Robert Habermeier <rphmeier@gmail.com> Co-authored-by: Chris Sosnin <chris125_@live.com> Co-authored-by: Parity Bot <admin@parity.io> Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> * Prospective Parachains Subsystem (#4913) * docs and skeleton * subsystem skeleton * main loop * fragment tree basics & fmt * begin fragment trees & view * flesh out more of view update logic * further flesh out update logic * some refcount functions for fragment trees * add fatal/non-fatal errors * use non-fatal results * clear up some TODOs * ideal format for scheduling info * add a bunch of TODOs * some more fluff * extract fragment graph to submodule * begin fragment graph API * trees, not graphs * improve docs * scope and constructor for trees * add some test TODOs * limit max ancestors and store constraints * constructor * constraints: fix bug in HRMP watermarks * fragment tree population logic * set::retain * extract population logic * implement add_and_populate * fmt * add some TODOs in tests * implement child-selection * strip out old stuff based on wrong assumptions * use fatality * implement pruning * remove unused ancestor constraints * fragment tree instantiation * remove outdated comment * add message/request types and skeleton for handling * fmt * implement handle_candidate_seconded * candidate storage: handle backed * implement handle_candidate_backed * implement answer_get_backable_candidate * remove async where not needed * implement fetch_ancestry * add logic for run_iteration * add some docs * remove global allow(unused), fix warnings * make spellcheck happy (despite English) * fmt * bump Cargo.lock * replace tracing with gum * introduce PopulateFrom trait * implement GetHypotheticalDepths * revise docs slightly * first fragment tree scope test * more scope tests * test add_candidate * fmt * test retain * refactor test code * test populate is recursive * test contiguity of depth 0 is maintained * add_and_populate tests * cycle tests * remove PopulateFrom trait * fmt * test hypothetical depths (non-recursive) * have CandidateSeconded return membership * tree membership requests * Add a ProspectiveParachainsSubsystem struct * add a staging API for base constraints * add a `From` impl * add runtime API for staging_validity_constraints * implement fetch_base_constraints * implement `fetch_upcoming_paras` * remove reconstruction of candidate receipt; no obvious usecase * fmt * export message to broader module * remove last TODO * correctly export * fix compilation and add GetMinimumRelayParent request * make provisioner into a real subsystem with proper mesage bounds * fmt * fix ChannelsOut in overseer test * fix overseer tests * fix again * fmt * Integrate prospective parachains subsystem into backing: Part 1 (#5557) * BEGIN ASYNC candidate-backing CHANGES * rename & document modes * answer prospective validation data requests * GetMinimumRelayParents request is now plural * implement an implicit view utility for backing subsystems * implicit-view: get allowed relay parents * refactorings and improvements to implicit view * add some TODOs for tests * split implicit view updates into 2 functions * backing: define State to prepare for functional refactor * add some docs * backing: implement bones of new leaf activation logic * backing: create per-relay-parent-states * use new handle_active_leaves_update * begin extracting logic from CandidateBackingJob * mostly extract statement import from job logic * handle statement imports outside of job logic * do some TODO planning for prospective parachains integration * finish rewriting backing subsystem in functional style * add prospective parachains mode to relay parent entries * fmt * add a RejectedByProspectiveParachains error * notify prospective parachains of seconded and backed candidates * always validate candidates exhaustively in backing. * return persisted_validation_data from validation * handle rejections by prospective parachains * implement seconding sanity check * invoke validate_and_second * Alter statement table to allow multiple seconded messages per validator * refactor backing to have statements carry PVD * clean up all warnings * Add tests for implicit view * Improve doc comments * Prospective parachains mode based on Runtime API version * Add a TODO * Rework seconding_sanity_check * Iterate over responses * Update backing tests * collator-protocol: load PVD from runtime * Fix validator side tests * Update statement-distribution to fetch PVD * Fix statement-distribution tests * Backing tests with prospective paras #1 * fix per_relay_parent pruning in backing * Test multiple leaves * Test seconding sanity check * Import statement order Before creating an entry in `PerCandidateState` map wait for the approval from the prospective parachains * Add a test for correct state updates * Second multiple candidates per relay parent test * Add backing tests with prospective paras * Second more than one test without prospective paras * Add a test for prospective para blocks * Update malus * typos Co-authored-by: Chris Sosnin <chris125_@live.com> * Track occupied depth in backing per parachain (#5778) * provisioner: async backing changes (#5711) * Provisioner changes for async backing * Select candidates based on prospective paras mode * Revert naming * Update tests * Update TODO comment * review * provisioner: async backing changes (#5711) * Provisioner changes for async backing * Select candidates based on prospective paras mode * Revert naming * Update tests * Update TODO comment * review * fmt * Network bridge changes for asynchronous backing + update subsystems to handle versioned packets (#5991) * BEGIN STATEMENT DISTRIBUTION WORK create a vstaging network protocol which is the same as v1 * mostly make network bridge amenable to vstaging * network-bridge: fully adapt to vstaging * add some TODOs for tests * fix fallout in bitfield-distribution * bitfield distribution tests + TODOs * fix fallout in gossip-support * collator-protocol: fix message fallout * collator-protocol: load PVD from runtime * add TODO for vstaging tests * make things compile * set used network protocol version using a feature * fmt * get approval-distribution building * fix approval-distribution tests * spellcheck * nits * approval distribution net protocol test * bitfield distribution net protocol test * Revert "collator-protocol: fix message fallout" This reverts commit 07cc887303e16c6b3843ecb25cdc7cc2080e2ed1. * Network bridge tests Co-authored-by: Chris Sosnin <chris125_@live.com> * remove max_pov_size requirement from prospective pvd request (#6014) * remove max_pov_size requirement from prospective pvd request * fmt * Extract legacy statement distribution to its own module (#6026) * add compatibility type to v2 statement distribution message * warning cleanup * handle compatibility layer for v2 * clean up an unimplemented!() block * circulate statements based on version * extract legacy v1 code into separate module * remove unimplemented * clean up naming of from_requester/responder * remove TODOs * have backing share seconded statements with PVD * fmt * fix warning * Quick fix unused warning for not yet implemented/used staging messages. * Fix network bridge test * Fix wrong merge. We now have 23 subsystems (network bridge split + prospective parachains) Co-authored-by: Robert Klotzner <robert.klotzner@gmx.at> * Version 3 is already live. * Fix tests (#6055) * Fix backing tests * Fix warnings. * fmt * collator-protocol: asynchronous backing changes (#5740) * Draft collator side changes * Start working on collations management * Handle peer's view change * Versioning on advertising * Versioned collation fetching request * Handle versioned messages * Improve docs for collation requests * Add spans * Add request receiver to overseer * Fix collator side tests * Extract relay parent mode to lib * Validator side draft * Add more checks for advertisement * Request pvd based on async backing mode * review * Validator side improvements * Make old tests green * More fixes * Collator side tests draft * Send collation test * fmt * Collator side network protocol versioning * cleanup * merge artifacts * Validator side net protocol versioning * Remove fragment tree membership request * Resolve todo * Collator side core state test * Improve net protocol compatibility * Validator side tests * more improvements * style fixes * downgrade log * Track implicit assignments * Limit the number of seconded candidates per para * Add a sanity check * Handle fetched candidate * fix tests * Retry fetch * Guard against dequeueing while already fetching * Reintegrate connection management * Timeout on advertisements * fmt * spellcheck * update tests after merge * validator assignment fixes for backing and collator protocol (#6158) * Rename depth->ancestry len in tests * Refactor group assignments * Remove implicit assignments * backing: consider occupied core assignments * Track a single para on validator side * Refactor prospective parachains mode request (#6179) * Extract prospective parachains mode into util * Skip activations depending on the mode * backing: don't send backed candidate to provisioner (#6185) * backing: introduce `CanSecond` request for advertisements filtering (#6225) * Drop BoundToRelayParent * draft changes * fix backing tests * Fix genesis ancestry * Fix validator side tests * more tests * cargo generate-lockfile * Implement `StagingValidityConstraints` Runtime API method (#6258) * Implement StagingValidityConstraints * spellcheck * fix ump params * Update hrmp comment * Introduce ump per candidate limit * hypothetical earliest block * refactor primitives usage * hypothetical earliest block number test * fix build * Prepare the Runtime for asynchronous backing upgrade (#6287) * Introduce async backing params to runtime config * fix cumulus config * use config * finish runtimes * Introduce new staging API * Update collator protocol * Update provisioner * Update prospective parachains * Update backing * Move async backing params lower in the config * make naming consistent * misc * Use real prospective parachains subsystem (#6407) * Backport `HypotheticalFrontier` into the feature branch (#6605) * implement more general HypotheticalFrontier * fmt * drop unneeded request Co-authored-by: Robert Habermeier <rphmeier@gmail.com> * Resolve todo about legacy leaf activation (#6447) * fix bug/warning in handling membership answers * Remove `HypotheticalDepthRequest` in favor of `HypotheticalFrontierRequest` (#6521) * Remove `HypotheticalDepthRequest` for `HypotheticalFrontierRequest` * Update tests * Fix (removed wrong docstring) * Fix can_second request * Patch some dead_code errors --------- Co-authored-by: Chris Sosnin <chris125_@live.com> * Async Backing: Send Statement Distribution "Backed" messages (#6634) * Backing: Send Statement Distribution "Backed" messages Closes #6590. **TODO:** - [ ] Adjust tests * Fix compile errors * (Mostly) fix tests * Fix comment * Fix test and compile error * Test that `StatementDistributionMessage::Backed` is sent * Fix compile error * Fix some clippy errors * Add prospective parachains subsystem tests (#6454) * Add prospective parachains subsystem test * Add `should_do_no_work_if_async_backing_disabled_for_leaf` test * Implement `activate_leaf` helper, up to getting ancestry * Finish implementing `activate_leaf` * Small refactor in `activate_leaf` * Get `CandidateSeconded` working * Finish `send_candidate_and_check_if_found` test * Refactor; send more leaves & candidates * Refactor test * Implement `check_candidate_parent_leaving_view` test * Start work on `check_candidate_on_multiple_forks` test * Don’t associate specific parachains with leaf * Finish `correctly_updates_leaves` test * Fix cycle due to reused head data * Fix `check_backable_query` test * Fix `check_candidate_on_multiple_forks` test * Add `check_depth_and_pvd_queries` test * Address review comments * Remove TODO * add a new index for output head data to candidate storage * Resolve test TODOs * Fix compile errors * test candidate storage pruning, make sure new index is cleaned up --------- Co-authored-by: Robert Habermeier <rphmeier@gmail.com> * Node-side metrics for asynchronous backing (#6549) * Add metrics for `prune_view_candidate_storage` * Add metrics for `request_unblocked_collations` * Fix docstring * Couple fixes from review comments * Fix `check_depth_query` test * inclusion-emulator: mirror advancement rule check (#6361) * inclusion-emulator: mirror advancement rule check * fix build * prospective-parachains: introduce `backed_in_path_only` flag for advertisements (#6649) * Introduce `backed_in_path_only` flag for depth request * fmt * update doc comment * fmt * Add async-backing zombienet tests (#6314) * Async backing: impl guide for statement distribution (#6738) Co-authored-by: Bradley Olson <34992650+BradleyOlson64@users.noreply.github.com> Co-authored-by: alexgparity <115470171+alexgparity@users.noreply.github.com> * Asynchronous backing statement distribution: Take III (#5999) * add notification types for v2 statement-distribution * improve protocol docs * add empty vstaging module * fmt * add backed candidate packet request types * start putting down structure of new logic * handle activated leaf * some sanity-checking on outbound statements * fmt * update vstaging share to use statements with PVD * tiny refactor, candidate_hash location * import local statements * refactor statement import * first stab at broadcast logic * fmt * fill out some TODOs * start on handling incoming * split off session info into separate map * start in on a knowledge tracker * address some grumbles * format * missed comment * some docs for direct * add note on slashing * amend * simplify 'direct' code * finish up the 'direct' logic * add a bunch of tests for the direct-in-group logic * rename 'direct' to 'cluster', begin a candidate_entry module * distill candidate_entry * start in on a statement-store module * some utilities for the statement store * rewrite 'send_statement_direct' using new tools * filter sending logic on peers which have the relay-parent in their view. * some more logic for handling incoming statements * req/res: BackedCandidatePacket -> AttestedCandidate + tweaks * add a `validated_in_group` bitfield to BackedCandidateInventory * BackedCandidateInventory -> Manifest * start in on requester module * add outgoing request for attested candidate * add a priority mechanism for requester * some request dispatch logic * add seconded mask to tagged-request * amend manifest to hold group index * handle errors and set up scaffold for response validation * validate attested candidate responses * requester -> requests * add some utilities for manipulating requests * begin integrating requester * start grid module * tiny * refactor grid topology to expose more info to subsystems * fix grid_topology test * fix overseer test * implement topology group-based view construction logic * fmt * flesh out grid slightly more * add indexed groups utility * integrate Groups into per-session info * refactor statement store to borrow Groups * implement manifest knowledge utility * add a test for topology setup * don't send to group members * test for conflicting manifests * manifest knowledge tests * fmt * rename field * garbage collection for grid tracker * routines for finding correct/incorrect advertisers * add manifest import logic * tweak naming * more tests for manifest import * add comment * rework candidates into a view-wide tracker * fmt * start writing boilerplate for grid sending * fmt * some more group boilerplate * refactor handling of topology and authority IDs * fmt * send statements directly to grid peers where possible * send to cluster only if statement belongs to cluster * improve handling of cluster statements * handle incoming statements along the grid * API for introduction of candidates into the tree * backing: use new prospective parachains API * fmt prospective parachains changes * fmt statement-dist * fix condition * get ready for tracking importable candidates * prospective parachains: add Cow logic * incomplete and complete hypothetical candidates * remove keep_if_unneeded * fmt * implement more general HypotheticalFrontier * fmt, cleanup * add a by_parent_hash index to candidate tracker * more framework for future code * utilities for getting all hypothetical candidates for frontier * track origin in statement store * fmt * requests should return peer * apply post-confirmation reckoning * flesh out import/announce/circulate logic on new statements * adjust * adjust TODO comment * fix backing tests * update statement-distribution to use new indexedvec * fmt * query hypothetical candidates * implement `note_importable_under` * extract common utility of fragment tree updates * add a helper function for getting statements unknown by backing * import fresh statements to backing * send announcements and acknowledgements over grid * provide freshly importable statements also avoid tracking backed candidates in statement distribution * do not issue requests on newly importable candidates * add TODO for later when confirming candidate * write a routine for handling backed candidate notifications * simplify grid substantially * add some test TODOs * handle confirmed candidates & grid announcements * finish implementing manifest handling, including follow up statements * send follow-up statements when acknowledging freshly backed * fmt * handle incoming acknowledgements * a little DRYing * wire up network messages to handlers * fmt * some skeleton code for peer view update handling * more peer view skeleton stuff * Fix async backing statement distribution tests (#6621) * Fix compile errors in tests * Cargo fmt * Resolve some todos in async backing statement-distribution branch (#6482) * Implement `remove_by_relay_parent` * Extract `minimum_votes` to shared primitives. * Add `can_send_statements_received_with_prejudice` test * Fix test * Update docstrings * Cargo fmt * Fix compile error * Fix compile errors in tests * Cargo fmt * Add module docs; write `test_priority_ordering` (first draft) * Fix `test_priority_ordering` * Move `insert_or_update_priority`: `Drop` -> `set_cluster_priority` * Address review comments * Remove `Entry::get_mut` * fix test compilation * add a TODO for a test * clean up a couple of TODOs * implement sending pending cluster statements * refactor utility function for sending acknowledgement and statements * mostly implement catching peers up via grid * Fix clippy error * alter grid to track all pending statements * fix more TODOs and format * tweak a TODO in requests * some logic for dispatching requests * fmt * skeleton for response receiving * Async backing statement distribution: cluster tests (#6678) * Add `pending_statements_set_when_receiving_fresh_statements` * Add `pending_statements_updated_when_sending_statements` test * fix up * fmt * update TODO * rework seconded mask in requests * change doc * change unhandledresponse not to borrow request manager * only accept responses sufficient to back * finish implementing response handling * extract statement filter to protocol crate * rework requests: use statement filter in network protocol * dispatch cluster requests correctly * rework cluster statement sending * implement request answering * fmt * only send confirmed candidate statement messages on unified relay-parent * Fix Tests In Statement Distribution Branch * Async Backing: Integrate `vstaging` of statement distribution into `lib.rs` (#6715) * Integrate `handle_active_leaves_update` * Integrate `share_local_statement`/`handle_backed_candidate_message` * Start hooking up request/response flow * Finish hooking up request/response flow * Limit number of parallel requests in responder * Fix test compilation errors * Fix missing check for prospective parachains mode * Fix some more compile errors * clean up some review comments * clean up warnings * Async backing statement distribution: grid tests (#6673) * Add `manifest_import_returns_ok_true` test * cargo fmt * Add pending_communication_receiving_manifest_on_confirmed_candidate * Add `senders_can_provide_manifests_in_acknowledgement` test * Add a couple of tests for pending statements * Add `pending_statements_cleared_when_sending` test * Add `pending_statements_respect_remote_knowledge` test * Refactor group creation in tests * Clarify docs * Address some review comments * Make some clarifications * Fix post-merge errors * Clarify test `senders_can_provide_manifests_in_acknowledgement` * Try writing `pending_statements_are_updated_after_manifest_exchange` * Document "seconding limit" and `reject_overflowing_manifests` test * Test that seconding counts are not updated for validators on error * Fix tests * Fix manifest exchange test * Add more tests in `requests.rs` (#6707) This resolves remaining TODOs in this file. * remove outdated inventory terminology * Async backing statement distribution: `Candidates` tests (#6658) * Async Backing: Fix clippy errors in statement distribution branch (#6720) * Integrate `handle_active_leaves_update` * Integrate `share_local_statement`/`handle_backed_candidate_message` * Start hooking up request/response flow * Finish hooking up request/response flow * Limit number of parallel requests in responder * Fix test compilation errors * Fix missing check for prospective parachains mode * Fix some more compile errors * Async Backing: Fix clippy errors in statement distribution branch * Fix some more clippy lints * add tests module * fix warnings in existing tests * create basic test harness * create a test state struct * fmt * create empty cluster & grid modules for tests * some TODOs for cluster test suite * describe test-suite for grid logic * describe request test suite * fix seconding-limit bug * Remove extraneous `pub` This somehow made it into my clippy PR. * Fix some test compile warnings * Remove some unneeded `allow`s * adapt some new test helpers from Marcin * add helper for activating a gossip topology * add utility for signing statements * helpers for connecting/disconnecting peers * round out network utilities * fmt * fix bug in initializing validator-meta * fix compilation * implement first cluster test * TODOs for incoming request tests * Remove unneeded `make_committed_candidate` helper * fmt * some more tests for cluster * add a TODO about grid senders * integrate inbound req/res into test harness * polish off initial cluster test suite * keep introduce candidate request * fix tests after introduce candidate request * fmt * Add grid protocol to module docs * Fix comments * Test `backed_in_path_only: true` * Update node/network/protocol/src/lib.rs Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> * Update node/network/protocol/src/request_response/mod.rs Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> * Mark receiver with `vstaging` * validate grid senders based on manifest kind * fix mask_seconded/valid * fix unwanted-mask check * fix build * resolve todo on leaf mode * Unify protocol naming to vstaging * fmt, fix grid test after topology change * typo Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> * address review * adjust comment, make easier to understand * Fix typo --------- Co-authored-by: Marcin S <marcin@bytedude.com> Co-authored-by: Marcin S <marcin@realemail.net> Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> Co-authored-by: Chris Sosnin <chris125_@live.com> * miscellaneous fixes to make asynchronous backing work (#6791) * propagate network-protocol-staging feature * add feature to adder-collator as well * allow collation-generation of occupied cores * prospective parachains: special treatment for pending availability candidates * runtime: fetch candidates pending availability * lazily construct PVD for pending candidates * fix fallout in prospective parachains hypothetical/select_child * runtime: enact candidates when creating paras-inherent * make tests compile * test pending availability in the scope * add prospective parachains test * fix validity constraints leftovers * drop prints * Fix typos --------- Co-authored-by: Chris Sosnin <chris125_@live.com> Co-authored-by: Marcin S <marcin@realemail.net> * Remove restart from test (#6840) * Async Backing: Statement Distribution Tests (#6755) * start on handling incoming * split off session info into separate map * start in on a knowledge tracker * address some grumbles * format * missed comment * some docs for direct * add note on slashing * amend * simplify 'direct' code * finish up the 'direct' logic * add a bunch of tests for the direct-in-group logic * rename 'direct' to 'cluster', begin a candidate_entry module * distill candidate_entry * start in on a statement-store module * some utilities for the statement store * rewrite 'send_statement_direct' using new tools * filter sending logic on peers which have the relay-parent in their view. * some more logic for handling incoming statements * req/res: BackedCandidatePacket -> AttestedCandidate + tweaks * add a `validated_in_group` bitfield to BackedCandidateInventory * BackedCandidateInventory -> Manifest * start in on requester module * add outgoing request for attested candidate * add a priority mechanism for requester * some request dispatch logic * add seconded mask to tagged-request * amend manifest to hold group index * handle errors and set up scaffold for response validation * validate attested candidate responses * requester -> requests * add some utilities for manipulating requests * begin integrating requester * start grid module * tiny * refactor grid topology to expose more info to subsystems * fix grid_topology test * fix overseer test * implement topology group-based view construction logic * fmt * flesh out grid slightly more * add indexed groups utility * integrate Groups into per-session info * refactor statement store to borrow Groups * implement manifest knowledge utility * add a test for topology setup * don't send to group members * test for conflicting manifests * manifest knowledge tests * fmt * rename field * garbage collection for grid tracker * routines for finding correct/incorrect advertisers * add manifest import logic * tweak naming * more tests for manifest import * add comment * rework candidates into a view-wide tracker * fmt * start writing boilerplate for grid sending * fmt * some more group boilerplate * refactor handling of topology and authority IDs * fmt * send statements directly to grid peers where possible * send to cluster only if statement belongs to cluster * improve handling of cluster statements * handle incoming statements along the grid * API for introduction of candidates into the tree * backing: use new prospective parachains API * fmt prospective parachains changes * fmt statement-dist * fix condition * get ready for tracking importable candidates * prospective parachains: add Cow logic * incomplete and complete hypothetical candidates * remove keep_if_unneeded * fmt * implement more general HypotheticalFrontier * fmt, cleanup * add a by_parent_hash index to candidate tracker * more framework for future code * utilities for getting all hypothetical candidates for frontier * track origin in statement store * fmt * requests should return peer * apply post-confirmation reckoning * flesh out import/announce/circulate logic on new statements * adjust * adjust TODO comment * fix backing tests * update statement-distribution to use new indexedvec * fmt * query hypothetical candidates * implement `note_importable_under` * extract common utility of fragment tree updates * add a helper function for getting statements unknown by backing * import fresh statements to backing * send announcements and acknowledgements over grid * provide freshly importable statements also avoid tracking backed candidates in statement distribution * do not issue requests on newly importable candidates * add TODO for later when confirming candidate * write a routine for handling backed candidate notifications * simplify grid substantially * add some test TODOs * handle confirmed candidates & grid announcements * finish implementing manifest handling, including follow up statements * send follow-up statements when acknowledging freshly backed * fmt * handle incoming acknowledgements * a little DRYing * wire up network messages to handlers * fmt * some skeleton code for peer view update handling * more peer view skeleton stuff * Fix async backing statement distribution tests (#6621) * Fix compile errors in tests * Cargo fmt * Resolve some todos in async backing statement-distribution branch (#6482) * Implement `remove_by_relay_parent` * Extract `minimum_votes` to shared primitives. * Add `can_send_statements_received_with_prejudice` test * Fix test * Update docstrings * Cargo fmt * Fix compile error * Fix compile errors in tests * Cargo fmt * Add module docs; write `test_priority_ordering` (first draft) * Fix `test_priority_ordering` * Move `insert_or_update_priority`: `Drop` -> `set_cluster_priority` * Address review comments * Remove `Entry::get_mut` * fix test compilation * add a TODO for a test * clean up a couple of TODOs * implement sending pending cluster statements * refactor utility function for sending acknowledgement and statements * mostly implement catching peers up via grid * Fix clippy error * alter grid to track all pending statements * fix more TODOs and format * tweak a TODO in requests * some logic for dispatching requests * fmt * skeleton for response receiving * Async backing statement distribution: cluster tests (#6678) * Add `pending_statements_set_when_receiving_fresh_statements` * Add `pending_statements_updated_when_sending_statements` test * fix up * fmt * update TODO * rework seconded mask in requests * change doc * change unhandledresponse not to borrow request manager * only accept responses sufficient to back * finish implementing response handling * extract statement filter to protocol crate * rework requests: use statement filter in network protocol * dispatch cluster requests correctly * rework cluster statement sending * implement request answering * fmt * only send confirmed candidate statement messages on unified relay-parent * Fix Tests In Statement Distribution Branch * Async Backing: Integrate `vstaging` of statement distribution into `lib.rs` (#6715) * Integrate `handle_active_leaves_update` * Integrate `share_local_statement`/`handle_backed_candidate_message` * Start hooking up request/response flow * Finish hooking up request/response flow * Limit number of parallel requests in responder * Fix test compilation errors * Fix missing check for prospective parachains mode * Fix some more compile errors * clean up some review comments * clean up warnings * Async backing statement distribution: grid tests (#6673) * Add `manifest_import_returns_ok_true` test * cargo fmt * Add pending_communication_receiving_manifest_on_confirmed_candidate * Add `senders_can_provide_manifests_in_acknowledgement` test * Add a couple of tests for pending statements * Add `pending_statements_cleared_when_sending` test * Add `pending_statements_respect_remote_knowledge` test * Refactor group creation in tests * Clarify docs * Address some review comments * Make some clarifications * Fix post-merge errors * Clarify test `senders_can_provide_manifests_in_acknowledgement` * Try writing `pending_statements_are_updated_after_manifest_exchange` * Document "seconding limit" and `reject_overflowing_manifests` test * Test that seconding counts are not updated for validators on error * Fix tests * Fix manifest exchange test * Add more tests in `requests.rs` (#6707) This resolves remaining TODOs in this file. * remove outdated inventory terminology * Async backing statement distribution: `Candidates` tests (#6658) * Async Backing: Fix clippy errors in statement distribution branch (#6720) * Integrate `handle_active_leaves_update` * Integrate `share_local_statement`/`handle_backed_candidate_message` * Start hooking up request/response flow * Finish hooking up request/response flow * Limit number of parallel requests in responder * Fix test compilation errors * Fix missing check for prospective parachains mode * Fix some more compile errors * Async Backing: Fix clippy errors in statement distribution branch * Fix some more clippy lints * add tests module * fix warnings in existing tests * create basic test harness * create a test state struct * fmt * create empty cluster & grid modules for tests * some TODOs for cluster test suite * describe test-suite for grid logic * describe request test suite * fix seconding-limit bug * Remove extraneous `pub` This somehow made it into my clippy PR. * Fix some test compile warnings * Remove some unneeded `allow`s * adapt some new test helpers from Marcin * add helper for activating a gossip topology * add utility for signing statements * helpers for connecting/disconnecting peers * round out network utilities * fmt * fix bug in initializing validator-meta * fix compilation * implement first cluster test * TODOs for incoming request tests * Remove unneeded `make_committed_candidate` helper * fmt * Hook up request sender * Add `valid_statement_without_prior_seconded_is_ignored` test * Fix `valid_statement_without_prior_seconded_is_ignored` test * some more tests for cluster * add a TODO about grid senders * integrate inbound req/res into test harness * polish off initial cluster test suite * keep introduce candidate request * fix tests after introduce candidate request * fmt * Add grid protocol to module docs * Remove obsolete test * Fix comments * Test `backed_in_path_only: true` * Update node/network/protocol/src/lib.rs Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> * Update node/network/protocol/src/request_response/mod.rs Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> * Mark receiver with `vstaging` * First draft of `ensure_seconding_limit_is_respected` test * validate grid senders based on manifest kind * fix mask_seconded/valid * fix unwanted-mask check * fix build * resolve todo on leaf mode * Unify protocol naming to vstaging * Fix `ensure_seconding_limit_is_respected` test * Start `backed_candidate_leads_to_advertisement` test * fmt, fix grid test after topology change * Send Backed notification * Finish `backed_candidate_leads_to_advertisement` test * Finish `peer_reported_for_duplicate_statements` test * Finish `received_advertisement_before_confirmation_leads_to_request` * Add `advertisements_rejected_from_incorrect_peers` test * Add `manifest_rejected_*` tests * Add `manifest_rejected_when_group_does_not_match_para` test * Add `local_node_sanity_checks_incoming_requests` test * Add `local_node_respects_statement_mask` test * Add tests where peer is reported for providing invalid signatures * Add `cluster_peer_allowed_to_send_incomplete_statements` test * Add `received_advertisement_after_backing_leads_to_acknowledgement` * Add `received_advertisement_after_confirmation_before_backing` test * peer_reported_for_advertisement_conflicting_with_confirmed_candidate * Add `peer_reported_for_not_enough_statements` test * Add `peer_reported_for_providing_statements_meant_to_be_masked_out` * Add `additional_statements_are_shared_after_manifest_exchange` * Add `grid_statements_imported_to_backing` test * Add `relay_parent_entering_peer_view_leads_to_advertisement` test * Add `advertisement_not_re_sent_when_peer_re_enters_view` test * Update node/network/statement-distribution/src/vstaging/tests/grid.rs Co-authored-by: asynchronous rob <rphmeier@gmail.com> * Resolve TODOs, update test * Address unused code * Add check after every test for unhandled requests * Refactor (`make_dummy_leaf` and `handle_sent_request`) * Refactor (`make_dummy_topology`) * Minor refactor --------- Co-authored-by: Robert Habermeier <rphmeier@gmail.com> Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> Co-authored-by: Chris Sosnin <chris125_@live.com> * Fix some clippy lints in tests * Async backing: minor fixes (#6920) * bitfield-distribution test * implicit view tests * Refactor parameters -> params * scheduler: update storage migration (#6963) * update scheduler migration * Adjust weight to account for storage read * Statement Distribution Guide Edits (#7025) * Statement distribution guide edits * Addressed Marcin's comments * Add attested candidate request retry timeouts (#6833) Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> Co-authored-by: asynchronous rob <rphmeier@gmail.com> Co-authored-by: Robert Habermeier <rphmeier@gmail.com> Co-authored-by: Chris Sosnin <chris125_@live.com> Fix async backing statement distribution tests (#6621) Resolve some todos in async backing statement-distribution branch (#6482) Fix clippy errors in statement distribution branch (#6720) * Async backing: add Prospective Parachains impl guide (#6933) Co-authored-by: Bradley Olson <34992650+BradleyOlson64@users.noreply.github.com> * Updates to Provisioner Guide for Async Backing (#7106) * Initial corrections and clarifications * Partial first draft * Finished first draft * Adding back wrongly removed test bit * fmt * Update roadmap/implementers-guide/src/node/utility/provisioner.md Co-authored-by: Marcin S. <marcin@realemail.net> * Addressing comments * Reorganization * fmt --------- Co-authored-by: Marcin S. <marcin@realemail.net> * fmt * Renaming Parathread Mentions (#7287) * Renaming parathreads * Renaming module to pallet * More updates * PVF: Refactor workers into separate crates, remove host dependency (#7253) * PVF: Refactor workers into separate crates, remove host dependency * Fix compile error * Remove some leftover code * Fix compile errors * Update Cargo.lock * Remove worker main.rs files I accidentally copied these from the other PR. This PR isn't intended to introduce standalone workers yet. * Address review comments * cargo fmt * Update a couple of comments * Update log targets * Update quote to 1.0.27 (#7280) Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: parity-processbot <> * pallets: implement `Default` for `GenesisConfig` in `no_std` (#7271) * pallets: implement Default for GenesisConfig in no_std This change is follow-up of: https://github.com/paritytech/substrate/pull/14108 It is a step towards: https://github.com/paritytech/substrate/issues/13334 * Cargo.lock updated * update lockfile for {"substrate"} --------- Co-authored-by: parity-processbot <> * cli: enable BEEFY by default on test networks (#7293) We consider BEEFY mature enough to run by default on all nodes for test networks (Rococo/Wococo/Versi). Right now, most nodes are not running it since it's opt-in using --beefy flag. Switch to an opt-out model for test networks. Replace --beefy flag from CLI with --no-beefy and have BEEFY client start by default on test networks. Signed-off-by: acatangiu <adrian@parity.io> * runtime: past session slashing runtime API (#6667) * runtime/vstaging: unapplied_slashes runtime API * runtime/vstaging: key_ownership_proof runtime API * runtime/ParachainHost: submit_report_dispute_lost * fix key_ownership_proof API * runtime: submit_report_dispute_lost runtime API * nits * Update node/subsystem-types/src/messages.rs Co-authored-by: Marcin S. <marcin@bytedude.com> * revert unrelated fmt changes * post merge fixes * fix compilation --------- Co-authored-by: Marcin S. <marcin@bytedude.com> * Correcting git mishap * Document usage of `gum` crate (#7294) * Document usage of gum crate * Small fix * Add some more basic info * Update node/gum/src/lib.rs Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com> * Update target docs --------- Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com> * XCM: Fix issue with RequestUnlock (#7278) * XCM: Fix issue with RequestUnlock * Leave API changes for v4 * Fix clippy errors * Fix tests --------- Co-authored-by: parity-processbot <> * Companion for Substrate#14228 (#7295) * Companion for Substrate#14228 https://github.com/paritytech/substrate/pull/14228 * update lockfile for {"substrate"} --------- Co-authored-by: parity-processbot <> * Companion for #14237: Use latest sp-crates (#7300) * To revert: Update substrate branch to "lexnv/bump_sp_crates" Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Revert "To revert: Update substrate branch to "lexnv/bump_sp_crates"" This reverts commit 5f1db84eac4a226c37b7f6ce6ee19b49dc7e2008. * Update cargo lock Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Update cargo.lock Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Update cargo.lock Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> --------- Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * bounded-collections bump to 0.1.7 (#7305) * bounded-collections bump to 0.1.7 Companion for: paritytech/substrate#14225 * update lockfile for {"substrate"} --------- Co-authored-by: parity-processbot <> * bump to quote 1.0.28 (#7306) * `RollingSessionWindow` cleanup (#7204) * Replace `RollingSessionWindow` with `RuntimeInfo` - initial commit * Fix tests in import * Fix the rest of the tests * Remove dead code * Fix todos * Simplify session caching * Comments for `SessionInfoProvider` * Separate `SessionInfoProvider` from `State` * `cache_session_info_for_head` becomes freestanding function * Remove unneeded `mut` usage * fn session_info -> fn get_session_info() to avoid name clashes. The function also tries to initialize `SessionInfoProvider` * Fix SessionInfo retrieval * Code cleanup * Don't wrap `SessionInfoProvider` in an `Option` * Remove `earliest_session()` * Remove pre-caching -> wip * Fix some tests and code cleanup * Fix all tests * Fixes in tests * Fix comments, variable names and small style changes * Fix a warning * impl From<SessionWindowSize> for NonZeroUsize * Fix logging for `get_session_info` - remove redundant logs and decrease log level to DEBUG * Code review feedback * Storage migration removing `COL_SESSION_WINDOW_DATA` from parachains db * Remove `col_session_data` usages * Storage migration clearing columns w/o removing them * Remove session data column usages from `approval-voting` and `dispute-coordinator` tests * Add some test cases from `RollingSessionWindow` to `dispute-coordinator` tests * Fix formatting in initialized.rs * Fix a corner case in `SessionInfo` caching for `dispute-coordinator` * Remove `RollingSessionWindow` ;( * Revert "Fix formatting in initialized.rs" This reverts commit 0f94664ec9f3a7e3737a30291195990e1e7065fc. * v2 to v3 migration drops `COL_DISPUTE_COORDINATOR_DATA` instead of clearing it * Fix `NUM_COLUMNS` in `approval-voting` * Use `columns::v3::NUM_COLUMNS` when opening db * Update node/service/src/parachains_db/upgrade.rs Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com> * Don't write in `COL_DISPUTE_COORDINATOR_DATA` for `test_rocksdb_migrate_2_to_3` * Fix `NUM+COLUMNS` in approval_voting * Fix formatting * Fix columns usage * Clarification comments about the different db versions --------- Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com> * pallet-para-config: Remove remnant WeightInfo functions (#7308) * pallet-para-config: Remove remnant WeightInfo functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * set_config_with_weight begone Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * ".git/.scripts/commands/bench/bench.sh" runtime kusama-dev runtime_parachains::configuration --------- Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: command-bot <> * XCM: PayOverXcm config (#6900) * Move XCM query functionality to trait * Fix tests * Add PayOverXcm implementation * fix the PayOverXcm trait to compile * moved doc comment out of trait implmeentation and to the trait * PayOverXCM documentation * Change documentation a bit * Added empty benchmark methods implementation and changed docs * update PayOverXCM to convert AccountIds to MultiLocations * Implement benchmarking method * Change v3 to latest * Descend origin to an asset sender (#6970) * descend origin to an asset sender * sender as tuple of dest and sender * Add more variants to the QueryResponseStatus enum * Change Beneficiary to Into<[u8; 32]> * update PayOverXcm to return concrete errors and use AccountId as sender * use polkadot-primitives for AccountId * fix dependency to use polkadot-core-primitives * force Unpaid instruction to the top of the instructions list * modify report_outcome to accept interior argument * use new_query directly for building final xcm query, instead of report_outcome * fix usage of new_query to use the XcmQueryHandler * fix usage of new_query to use the XcmQueryHandler * tiny method calling fix * xcm query handler (#7198) * drop redundant query status * rename ReportQueryStatus to OuterQueryStatus * revert rename of QueryResponseStatus * update mapping * Update xcm/xcm-builder/src/pay.rs Co-authored-by: Gavin Wood <gavin@parity.io> * Updates * Docs * Fix benchmarking stuff * Destination can be determined based on asset_kind * Tweaking API to minimise clones * Some repotting and docs --------- Co-authored-by: Anthony Alaribe <anthonyalaribe@gmail.com> Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com> Co-authored-by: Anthony Alaribe <anthony.alaribe@parity.io> Co-authored-by: Gavin Wood <gavin@parity.io> * Companion for #14265 (#7307) * Update Cargo.lock Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Update Cargo.lock Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> --------- Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: parity-processbot <> * bump serde to 1.0.163 (#7315) * bump serde to 1.0.163 * bump ci * update lockfile for {"substrate"} --------- Co-authored-by: parity-processbot <> * fmt * Updated fmt * Removing changes accidentally pulled from master * fix another master pull issue * Another master pull fix * fmt * Fixing implementers guide build * Revert "Merge branch 'rh-async-backing-feature-while-frozen' of https://github.com/paritytech/polkadot into brad-rename-parathread" This reverts commit bebc24af52ab61155e3fe02cb3ce66a592bce49c, reversing changes made to 1b2de662dfb11173679d6da5bd0da9d149c85547. --------- Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Signed-off-by: acatangiu <adrian@parity.io> Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: Marcin S <marcin@realemail.net> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> Co-authored-by: Adrian Catangiu <adrian@parity.io> Co-authored-by: ordian <write@reusable.software> Co-authored-by: Marcin S. <marcin@bytedude.com> Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com> Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com> Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Co-authored-by: Sam Johnson <sam@durosoft.com> Co-authored-by: Tsvetomir Dimitrov <tsvetomir@parity.io> Co-authored-by: Anthony Alaribe <anthonyalaribe@gmail.com> Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com> Co-authored-by: Anthony Alaribe <anthony.alaribe@parity.io> Co-authored-by: Gavin Wood <gavin@parity.io> * fix bitfield distribution test * approval distribution tests * fix bridge tests * update Cargo.lock * [async-backing-branch] Optimize collator-protocol validator-side request fetching (#7457) * Optimize collator-protocol validator-side request fetching * address feedback: replace tuples with structs * feedback: add doc comments * move collation types to subfolder --------- Signed-off-by: alindima <alin@parity.io> * Update collation generation for asynchronous backing (#7405) * break candidate receipt construction and distribution into own function * update implementers' guide to include SubmitCollation * implement SubmitCollation for collation-generation * fmt * fix test compilation & remove unnecessary submodule * add some TODOs for a test suite. * Update roadmap/implementers-guide/src/types/overseer-protocol.md Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com> * add new test harness and first test * refactor to avoid requiring background sender * ensure collation gets packaged and distributed * tests for the fallback case with no hint * add parent rp-number hint tests * fmt * update uses of CollationGenerationConfig * fix remaining test * address review comments * use subsystemsender for background tasks * fmt * remove ValidationCodeHashHint and related tests --------- Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com> * fix some more fallout from merge * fmt * remove staging APIs from Rococo & Westend (#7513) * send network messages on main protocol name (#7515) * misc async backing improvements for allowed ancestry blocks (#7532) * shared: fix acquire_info * backwards-compat test for prospective parachains * same relay parent is allowed * provisioner: request candidate receipt by relay parent (#7527) * return candidates hash from prospective parachains * update provisioner * update tests * guide changes * send a single message to backing * fix test * revert to old `handle_new_activations` logic in some cases (#7514) * revert to old `handle_new_activations` logic * gate sending messages on scheduled cores to max_depth >= 2 * fmt * 2->1 * Omnibus asynchronous backing bugfix PR (#7529) * fix a bug in backing * add some more logs * prospective parachains: take ancestry only up to session bounds * add test * fix zombienet tests (#7614) Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * fix runtime compilation * make bitfield distribution tests compile * attempt to fix zombienet disputes (#7618) * update metric name * update some metric names * avoid cycles when creating fake candidates * make undying collator more friendly to malformed parents * fix a bug in malus * fmt * clippy * add RUN_IN_CONTAINER to new ZombieNet tests (#7631) * remove duplicated migration happened because of master-merge --------- Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Signed-off-by: acatangiu <adrian@parity.io> Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Signed-off-by: alindima <alin@parity.io> Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> Co-authored-by: Chris Sosnin <chris125_@live.com> Co-authored-by: Parity Bot <admin@parity.io> Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> Co-authored-by: Robert Klotzner <robert.klotzner@gmx.at> Co-authored-by: Robert Klotzner <eskimor@users.noreply.github.com> Co-authored-by: Marcin S <marcin@bytedude.com> Co-authored-by: Marcin S <marcin@realemail.net> Co-authored-by: Mattia L.V. Bradascio <28816406+bredamatt@users.noreply.github.com> Co-authored-by: Bradley Olson <34992650+BradleyOlson64@users.noreply.github.com> Co-authored-by: alexgparity <115470171+alexgparity@users.noreply.github.com> Co-authored-by: BradleyOlson64 <lotrftw9@gmail.com> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> Co-authored-by: Adrian Catangiu <adrian@parity.io> Co-authored-by: ordian <write@reusable.software> Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com> Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com> Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Co-authored-by: Sam Johnson <sam@durosoft.com> Co-authored-by: Tsvetomir Dimitrov <tsvetomir@parity.io> Co-authored-by: Anthony Alaribe <anthonyalaribe@gmail.com> Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com> Co-authored-by: Anthony Alaribe <anthony.alaribe@parity.io> Co-authored-by: Gavin Wood <gavin@parity.io> Co-authored-by: Alin Dima <alin@parity.io>
1358 lines
45 KiB
Rust
1358 lines
45 KiB
Rust
// 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.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//! The inclusion pallet is responsible for inclusion and availability of scheduled parachains.
|
|
//!
|
|
//! It is responsible for carrying candidates from being backable to being backed, and then from
|
|
//! backed to included.
|
|
|
|
use crate::{
|
|
configuration::{self, HostConfiguration},
|
|
disputes, dmp, hrmp, paras,
|
|
scheduler::{self, common::CoreAssignment},
|
|
shared::{self, AllowedRelayParentsTracker},
|
|
};
|
|
use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec};
|
|
use frame_support::{
|
|
defensive,
|
|
pallet_prelude::*,
|
|
traits::{Defensive, EnqueueMessage},
|
|
BoundedSlice,
|
|
};
|
|
use frame_system::pallet_prelude::*;
|
|
use pallet_message_queue::OnQueueChanged;
|
|
use parity_scale_codec::{Decode, Encode};
|
|
use primitives::{
|
|
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,
|
|
};
|
|
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::*};
|
|
|
|
pub use pallet::*;
|
|
|
|
#[cfg(test)]
|
|
pub(crate) mod tests;
|
|
|
|
#[cfg(feature = "runtime-benchmarks")]
|
|
mod benchmarking;
|
|
|
|
pub trait WeightInfo {
|
|
fn receive_upward_messages(i: u32) -> Weight;
|
|
}
|
|
|
|
pub struct TestWeightInfo;
|
|
impl WeightInfo for TestWeightInfo {
|
|
fn receive_upward_messages(_: u32) -> Weight {
|
|
Weight::MAX
|
|
}
|
|
}
|
|
|
|
impl WeightInfo for () {
|
|
fn receive_upward_messages(_: u32) -> Weight {
|
|
Weight::zero()
|
|
}
|
|
}
|
|
|
|
/// Maximum value that `config.max_upward_message_size` can be set to.
|
|
///
|
|
/// This is used for benchmarking sanely bounding relevant storage items. It is expected from the
|
|
/// `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)]
|
|
#[cfg_attr(test, derive(Debug))]
|
|
pub struct CandidatePendingAvailability<H, N> {
|
|
/// The availability core this is assigned to.
|
|
core: CoreIndex,
|
|
/// The candidate hash.
|
|
hash: CandidateHash,
|
|
/// The candidate descriptor.
|
|
descriptor: CandidateDescriptor<H>,
|
|
/// The received availability votes. One bit per validator.
|
|
availability_votes: BitVec<u8, BitOrderLsb0>,
|
|
/// The backers of the candidate pending availability.
|
|
backers: BitVec<u8, BitOrderLsb0>,
|
|
/// The block number of the relay-parent of the receipt.
|
|
relay_parent_number: N,
|
|
/// The block number of the relay-chain block this was backed in.
|
|
backed_in_number: N,
|
|
/// The group index backing this block.
|
|
backing_group: GroupIndex,
|
|
}
|
|
|
|
impl<H, N> CandidatePendingAvailability<H, N> {
|
|
/// Get the availability votes on the candidate.
|
|
pub(crate) fn availability_votes(&self) -> &BitVec<u8, BitOrderLsb0> {
|
|
&self.availability_votes
|
|
}
|
|
|
|
/// Get the relay-chain block number this was backed in.
|
|
pub(crate) fn backed_in_number(&self) -> &N {
|
|
&self.backed_in_number
|
|
}
|
|
|
|
/// Get the core index.
|
|
pub(crate) fn core_occupied(&self) -> CoreIndex {
|
|
self.core
|
|
}
|
|
|
|
/// Get the candidate hash.
|
|
pub(crate) fn candidate_hash(&self) -> CandidateHash {
|
|
self.hash
|
|
}
|
|
|
|
/// Get the candidate descriptor.
|
|
pub(crate) fn candidate_descriptor(&self) -> &CandidateDescriptor<H> {
|
|
&self.descriptor
|
|
}
|
|
|
|
/// Get the candidate's relay parent's number.
|
|
pub(crate) fn relay_parent_number(&self) -> N
|
|
where
|
|
N: Clone,
|
|
{
|
|
self.relay_parent_number.clone()
|
|
}
|
|
|
|
#[cfg(any(feature = "runtime-benchmarks", test))]
|
|
pub(crate) fn new(
|
|
core: CoreIndex,
|
|
hash: CandidateHash,
|
|
descriptor: CandidateDescriptor<H>,
|
|
availability_votes: BitVec<u8, BitOrderLsb0>,
|
|
backers: BitVec<u8, BitOrderLsb0>,
|
|
relay_parent_number: N,
|
|
backed_in_number: N,
|
|
backing_group: GroupIndex,
|
|
) -> Self {
|
|
Self {
|
|
core,
|
|
hash,
|
|
descriptor,
|
|
availability_votes,
|
|
backers,
|
|
relay_parent_number,
|
|
backed_in_number,
|
|
backing_group,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A hook for applying validator rewards
|
|
pub trait RewardValidators {
|
|
// Reward the validators with the given indices for issuing backing statements.
|
|
fn reward_backing(validators: impl IntoIterator<Item = ValidatorIndex>);
|
|
// Reward the validators with the given indices for issuing availability bitfields.
|
|
// Validators are sent to this hook when they have contributed to the availability
|
|
// of a candidate by setting a bit in their bitfield.
|
|
fn reward_bitfields(validators: impl IntoIterator<Item = ValidatorIndex>);
|
|
}
|
|
|
|
/// Helper return type for `process_candidates`.
|
|
#[derive(Encode, Decode, PartialEq, TypeInfo)]
|
|
#[cfg_attr(test, derive(Debug))]
|
|
pub(crate) struct ProcessedCandidates<H = Hash> {
|
|
pub(crate) core_indices: Vec<(CoreIndex, ParaId)>,
|
|
pub(crate) candidate_receipt_with_backing_validator_indices:
|
|
Vec<(CandidateReceipt<H>, Vec<(ValidatorIndex, ValidityAttestation)>)>,
|
|
}
|
|
|
|
impl<H> Default for ProcessedCandidates<H> {
|
|
fn default() -> Self {
|
|
Self {
|
|
core_indices: Vec::new(),
|
|
candidate_receipt_with_backing_validator_indices: Vec::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Number of backing votes we need for a valid backing.
|
|
///
|
|
/// WARNING: This check has to be kept in sync with the node side checks.
|
|
pub fn minimum_backing_votes(n_validators: usize) -> usize {
|
|
// For considerations on this value see:
|
|
// https://github.com/paritytech/polkadot/pull/1656#issuecomment-999734650
|
|
// and
|
|
// https://github.com/paritytech/polkadot/issues/4386
|
|
sp_std::cmp::min(n_validators, 2)
|
|
}
|
|
|
|
/// Reads the footprint of queues for a specific origin type.
|
|
pub trait QueueFootprinter {
|
|
type Origin;
|
|
|
|
fn message_count(origin: Self::Origin) -> u64;
|
|
}
|
|
|
|
impl QueueFootprinter for () {
|
|
type Origin = UmpQueueId;
|
|
|
|
fn message_count(_: Self::Origin) -> u64 {
|
|
0
|
|
}
|
|
}
|
|
|
|
/// Aggregate message origin for the `MessageQueue` pallet.
|
|
///
|
|
/// Can be extended to serve further use-cases besides just UMP. Is stored in storage, so any change
|
|
/// to existing values will require a migration.
|
|
#[derive(Encode, Decode, Clone, MaxEncodedLen, Eq, PartialEq, RuntimeDebug, TypeInfo)]
|
|
pub enum AggregateMessageOrigin {
|
|
/// Inbound upward message.
|
|
#[codec(index = 0)]
|
|
Ump(UmpQueueId),
|
|
}
|
|
|
|
/// Identifies a UMP queue inside the `MessageQueue` pallet.
|
|
///
|
|
/// It is written in verbose form since future variants like `Loopback` and `Bridged` are already
|
|
/// forseeable.
|
|
#[derive(Encode, Decode, Clone, MaxEncodedLen, Eq, PartialEq, RuntimeDebug, TypeInfo)]
|
|
pub enum UmpQueueId {
|
|
/// The message originated from this parachain.
|
|
#[codec(index = 0)]
|
|
Para(ParaId),
|
|
}
|
|
|
|
#[cfg(feature = "runtime-benchmarks")]
|
|
impl From<u32> for AggregateMessageOrigin {
|
|
fn from(n: u32) -> Self {
|
|
// Some dummy for the benchmarks.
|
|
Self::Ump(UmpQueueId::Para(n.into()))
|
|
}
|
|
}
|
|
|
|
/// The maximal length of a UMP message.
|
|
pub type MaxUmpMessageLenOf<T> =
|
|
<<T as Config>::MessageQueue as EnqueueMessage<AggregateMessageOrigin>>::MaxMessageLen;
|
|
|
|
#[frame_support::pallet]
|
|
pub mod pallet {
|
|
use super::*;
|
|
|
|
#[pallet::pallet]
|
|
#[pallet::without_storage_info]
|
|
pub struct Pallet<T>(_);
|
|
|
|
#[pallet::config]
|
|
pub trait Config:
|
|
frame_system::Config
|
|
+ shared::Config
|
|
+ paras::Config
|
|
+ dmp::Config
|
|
+ hrmp::Config
|
|
+ configuration::Config
|
|
+ scheduler::Config
|
|
{
|
|
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
|
type DisputesHandler: disputes::DisputesHandler<BlockNumberFor<Self>>;
|
|
type RewardValidators: RewardValidators;
|
|
|
|
/// The system message queue.
|
|
///
|
|
/// The message queue provides general queueing and processing functionality. Currently it
|
|
/// replaces the old `UMP` dispatch queue. Other use-cases can be implemented as well by
|
|
/// adding new variants to `AggregateMessageOrigin`.
|
|
type MessageQueue: EnqueueMessage<AggregateMessageOrigin>;
|
|
|
|
/// Weight info for the calls of this pallet.
|
|
type WeightInfo: WeightInfo;
|
|
}
|
|
|
|
#[pallet::event]
|
|
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
|
pub enum Event<T: Config> {
|
|
/// A candidate was backed. `[candidate, head_data]`
|
|
CandidateBacked(CandidateReceipt<T::Hash>, HeadData, CoreIndex, GroupIndex),
|
|
/// A candidate was included. `[candidate, head_data]`
|
|
CandidateIncluded(CandidateReceipt<T::Hash>, HeadData, CoreIndex, GroupIndex),
|
|
/// A candidate timed out. `[candidate, head_data]`
|
|
CandidateTimedOut(CandidateReceipt<T::Hash>, HeadData, CoreIndex),
|
|
/// Some upward messages have been received and will be processed.
|
|
UpwardMessagesReceived { from: ParaId, count: u32 },
|
|
}
|
|
|
|
#[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.
|
|
PrematureCodeUpgrade,
|
|
/// Output code is too large
|
|
NewCodeTooLarge,
|
|
/// The candidate's relay-parent was not allowed. Either it was
|
|
/// not recent enough or it didn't advance based on the last parachain block.
|
|
DisallowedRelayParent,
|
|
/// Failed to compute group index for the core: either it's out of bounds
|
|
/// or the relay parent doesn't belong to the current session.
|
|
InvalidAssignment,
|
|
/// Invalid group index in core assignment.
|
|
InvalidGroupIndex,
|
|
/// Insufficient (non-majority) backing.
|
|
InsufficientBacking,
|
|
/// Invalid (bad signature, unknown validator, etc.) backing.
|
|
InvalidBacking,
|
|
/// Collator did not sign PoV.
|
|
NotCollatorSigned,
|
|
/// The validation data hash does not match expected.
|
|
ValidationDataHashMismatch,
|
|
/// The downward message queue is not processed correctly.
|
|
IncorrectDownwardMessageHandling,
|
|
/// At least one upward message sent does not pass the acceptance criteria.
|
|
InvalidUpwardMessages,
|
|
/// The candidate didn't follow the rules of HRMP watermark advancement.
|
|
HrmpWatermarkMishandling,
|
|
/// The HRMP messages sent by the candidate is not valid.
|
|
InvalidOutboundHrmp,
|
|
/// The validation code hash of the candidate is not valid.
|
|
InvalidValidationCodeHash,
|
|
/// 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`.
|
|
#[pallet::storage]
|
|
pub(crate) type PendingAvailability<T: Config> = StorageMap<
|
|
_,
|
|
Twox64Concat,
|
|
ParaId,
|
|
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> {}
|
|
}
|
|
|
|
const LOG_TARGET: &str = "runtime::inclusion";
|
|
|
|
/// The reason that a candidate's outputs were rejected for.
|
|
#[derive(derive_more::From)]
|
|
#[cfg_attr(feature = "std", derive(Debug))]
|
|
enum AcceptanceCheckErr<BlockNumber> {
|
|
HeadDataTooLarge,
|
|
/// Code upgrades are not permitted at the current time.
|
|
PrematureCodeUpgrade,
|
|
/// The new runtime blob is too large.
|
|
NewCodeTooLarge,
|
|
/// The candidate violated this DMP acceptance criteria.
|
|
ProcessedDownwardMessages(dmp::ProcessedDownwardMessagesAcceptanceErr),
|
|
/// The candidate violated this UMP acceptance criteria.
|
|
UpwardMessages(UmpAcceptanceCheckErr),
|
|
/// The candidate violated this HRMP watermark acceptance criteria.
|
|
HrmpWatermark(hrmp::HrmpWatermarkAcceptanceErr<BlockNumber>),
|
|
/// The candidate violated this outbound HRMP acceptance criteria.
|
|
OutboundHrmp(hrmp::OutboundHrmpAcceptanceErr),
|
|
}
|
|
|
|
/// An error returned by [`check_upward_messages`] that indicates a violation of one of acceptance
|
|
/// criteria rules.
|
|
#[cfg_attr(test, derive(PartialEq))]
|
|
pub enum UmpAcceptanceCheckErr {
|
|
/// The maximal number of messages that can be submitted in one batch was exceeded.
|
|
MoreMessagesThanPermitted { sent: u32, permitted: u32 },
|
|
/// The maximal size of a single message was exceeded.
|
|
MessageSize { idx: u32, msg_size: u32, max_size: u32 },
|
|
/// The allowed number of messages in the queue was exceeded.
|
|
CapacityExceeded { count: u64, limit: u64 },
|
|
/// The allowed combined message size in the queue was exceeded.
|
|
TotalSizeExceeded { total_size: u64, limit: u64 },
|
|
/// A para-chain cannot send UMP messages while it is offboarding.
|
|
IsOffboarding,
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
impl fmt::Debug for UmpAcceptanceCheckErr {
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
match *self {
|
|
UmpAcceptanceCheckErr::MoreMessagesThanPermitted { sent, permitted } => write!(
|
|
fmt,
|
|
"more upward messages than permitted by config ({} > {})",
|
|
sent, permitted,
|
|
),
|
|
UmpAcceptanceCheckErr::MessageSize { idx, msg_size, max_size } => write!(
|
|
fmt,
|
|
"upward message idx {} larger than permitted by config ({} > {})",
|
|
idx, msg_size, max_size,
|
|
),
|
|
UmpAcceptanceCheckErr::CapacityExceeded { count, limit } => write!(
|
|
fmt,
|
|
"the ump queue would have more items than permitted by config ({} > {})",
|
|
count, limit,
|
|
),
|
|
UmpAcceptanceCheckErr::TotalSizeExceeded { total_size, limit } => write!(
|
|
fmt,
|
|
"the ump queue would have grown past the max size permitted by config ({} > {})",
|
|
total_size, limit,
|
|
),
|
|
UmpAcceptanceCheckErr::IsOffboarding =>
|
|
write!(fmt, "upward message rejected because the para is off-boarding",),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T: Config> Pallet<T> {
|
|
/// Block initialization logic, called by initializer.
|
|
pub(crate) fn initializer_initialize(_now: BlockNumberFor<T>) -> Weight {
|
|
Weight::zero()
|
|
}
|
|
|
|
/// Block finalization logic, called by initializer.
|
|
pub(crate) fn initializer_finalize() {}
|
|
|
|
/// Handle an incoming session change.
|
|
pub(crate) fn initializer_on_new_session(
|
|
_notification: &crate::initializer::SessionChangeNotification<BlockNumberFor<T>>,
|
|
outgoing_paras: &[ParaId],
|
|
) {
|
|
// 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);
|
|
}
|
|
|
|
pub(crate) fn cleanup_outgoing_ump_dispatch_queues(outgoing: &[ParaId]) {
|
|
for outgoing_para in outgoing {
|
|
Self::cleanup_outgoing_ump_dispatch_queue(*outgoing_para);
|
|
}
|
|
}
|
|
|
|
pub(crate) fn cleanup_outgoing_ump_dispatch_queue(para: ParaId) {
|
|
T::MessageQueue::sweep_queue(AggregateMessageOrigin::Ump(UmpQueueId::Para(para)));
|
|
}
|
|
|
|
/// Extract the freed cores based on cores that became available.
|
|
///
|
|
/// Bitfields are expected to have been sanitized already. E.g. via `sanitize_bitfields`!
|
|
///
|
|
/// Updates storage items `PendingAvailability` and `AvailabilityBitfields`.
|
|
///
|
|
/// 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,
|
|
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<_>>();
|
|
|
|
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();
|
|
let checked_bitfield = signed_bitfield.into_payload();
|
|
(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
|
|
};
|
|
|
|
// 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;
|
|
if let Some(mut bit) =
|
|
pending_availability.as_mut().and_then(|candidate_pending_availability| {
|
|
candidate_pending_availability.availability_votes.get_mut(validator_index)
|
|
}) {
|
|
*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
|
|
},
|
|
};
|
|
|
|
let receipt = CommittedCandidateReceipt {
|
|
descriptor: pending_availability.descriptor,
|
|
commitments,
|
|
};
|
|
let _weight = Self::enact_candidate(
|
|
pending_availability.relay_parent_number,
|
|
receipt,
|
|
pending_availability.backers,
|
|
pending_availability.availability_votes,
|
|
pending_availability.core,
|
|
pending_availability.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.
|
|
///
|
|
/// 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.
|
|
pub(crate) fn process_candidates<GV>(
|
|
allowed_relay_parents: &AllowedRelayParentsTracker<T::Hash, BlockNumberFor<T>>,
|
|
candidates: Vec<BackedCandidate<T::Hash>>,
|
|
scheduled: Vec<CoreAssignment<BlockNumberFor<T>>>,
|
|
group_validators: GV,
|
|
) -> Result<ProcessedCandidates<T::Hash>, DispatchError>
|
|
where
|
|
GV: Fn(GroupIndex) -> Option<Vec<ValidatorIndex>>,
|
|
{
|
|
let now = <frame_system::Pallet<T>>::block_number();
|
|
|
|
ensure!(candidates.len() <= scheduled.len(), Error::<T>::UnscheduledCandidate);
|
|
|
|
if scheduled.is_empty() {
|
|
return Ok(ProcessedCandidates::default())
|
|
}
|
|
|
|
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());
|
|
|
|
// Do all checks before writing storage.
|
|
let core_indices_and_backers = {
|
|
let mut skip = 0;
|
|
let mut core_indices_and_backers = Vec::with_capacity(candidates.len());
|
|
let mut last_core = None;
|
|
|
|
let mut check_assignment_in_order =
|
|
|assignment: &CoreAssignment<BlockNumberFor<T>>| -> DispatchResult {
|
|
ensure!(
|
|
last_core.map_or(true, |core| assignment.core > core),
|
|
Error::<T>::ScheduledOutOfOrder,
|
|
);
|
|
|
|
last_core = Some(assignment.core);
|
|
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.
|
|
'next_backed_candidate: for (candidate_idx, backed_candidate) 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,
|
|
)? {
|
|
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())
|
|
},
|
|
Ok(rpn) => rpn,
|
|
};
|
|
|
|
let para_id = backed_candidate.descriptor().para_id;
|
|
let mut backers = bitvec::bitvec![u8, BitOrderLsb0; 0; validators.len()];
|
|
|
|
for (i, core_assignment) in scheduled[skip..].iter().enumerate() {
|
|
check_assignment_in_order(core_assignment)?;
|
|
|
|
if para_id == core_assignment.paras_entry.para_id() {
|
|
ensure!(
|
|
<PendingAvailability<T>>::get(¶_id).is_none() &&
|
|
<PendingAvailabilityCommitments<T>>::get(¶_id).is_none(),
|
|
Error::<T>::CandidateScheduledBeforeParaFree,
|
|
);
|
|
|
|
// account for already skipped, and then skip this one.
|
|
skip = i + skip + 1;
|
|
|
|
// 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_assignment.core,
|
|
relay_parent_number + One::one(),
|
|
)
|
|
.ok_or_else(|| {
|
|
log::warn!(
|
|
target: LOG_TARGET,
|
|
"Failed to compute group index for candidate {}",
|
|
candidate_idx
|
|
);
|
|
Error::<T>::InvalidAssignment
|
|
})?;
|
|
let group_vals = group_validators(group_idx)
|
|
.ok_or_else(|| Error::<T>::InvalidGroupIndex)?;
|
|
|
|
// check the signatures in the backing and that it is a majority.
|
|
{
|
|
let maybe_amount_validated = primitives::check_candidate_backing(
|
|
&backed_candidate,
|
|
&signing_context,
|
|
group_vals.len(),
|
|
|intra_group_vi| {
|
|
group_vals
|
|
.get(intra_group_vi)
|
|
.and_then(|vi| validators.get(vi.0 as usize))
|
|
.map(|v| v.clone())
|
|
},
|
|
);
|
|
|
|
match maybe_amount_validated {
|
|
Ok(amount_validated) => ensure!(
|
|
amount_validated >= minimum_backing_votes(group_vals.len()),
|
|
Error::<T>::InsufficientBacking,
|
|
),
|
|
Err(()) => {
|
|
Err(Error::<T>::InvalidBacking)?;
|
|
},
|
|
}
|
|
|
|
let mut backer_idx_and_attestation =
|
|
Vec::<(ValidatorIndex, ValidityAttestation)>::with_capacity(
|
|
backed_candidate.validator_indices.count_ones(),
|
|
);
|
|
let candidate_receipt = backed_candidate.receipt();
|
|
|
|
for ((bit_idx, _), attestation) in backed_candidate
|
|
.validator_indices
|
|
.iter()
|
|
.enumerate()
|
|
.filter(|(_, signed)| **signed)
|
|
.zip(backed_candidate.validity_votes.iter().cloned())
|
|
{
|
|
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_assignment.core, core_assignment.paras_entry.para_id()),
|
|
backers,
|
|
group_idx,
|
|
relay_parent_number,
|
|
));
|
|
continue 'next_backed_candidate
|
|
}
|
|
}
|
|
|
|
// end of loop reached means that the candidate didn't appear in the non-traversed
|
|
// section of the `scheduled` slice. either it was not scheduled or didn't appear in
|
|
// `candidates` in the correct order.
|
|
ensure!(false, Error::<T>::UnscheduledCandidate);
|
|
}
|
|
|
|
// check remainder of scheduled cores, if any.
|
|
for assignment in scheduled[skip..].iter() {
|
|
check_assignment_in_order(assignment)?;
|
|
}
|
|
|
|
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, candidate.candidate.commitments);
|
|
|
|
<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,
|
|
})
|
|
}
|
|
|
|
/// Run the acceptance criteria checks on the given candidate commitments.
|
|
pub(crate) fn check_validation_outputs_for_runtime_api(
|
|
para_id: ParaId,
|
|
relay_parent_number: BlockNumberFor<T>,
|
|
validation_outputs: primitives::CandidateCommitments,
|
|
) -> bool {
|
|
let prev_context = <paras::Pallet<T>>::para_most_recent_context(para_id);
|
|
let check_ctx = CandidateCheckContext::<T>::new(prev_context);
|
|
|
|
if check_ctx
|
|
.check_validation_outputs(
|
|
para_id,
|
|
relay_parent_number,
|
|
&validation_outputs.head_data,
|
|
&validation_outputs.new_validation_code,
|
|
validation_outputs.processed_downward_messages,
|
|
&validation_outputs.upward_messages,
|
|
BlockNumberFor::<T>::from(validation_outputs.hrmp_watermark),
|
|
&validation_outputs.horizontal_messages,
|
|
)
|
|
.is_err()
|
|
{
|
|
log::debug!(
|
|
target: LOG_TARGET,
|
|
"Validation outputs checking for parachain `{}` failed",
|
|
u32::from(para_id),
|
|
);
|
|
false
|
|
} else {
|
|
true
|
|
}
|
|
}
|
|
|
|
fn enact_candidate(
|
|
relay_parent_number: BlockNumberFor<T>,
|
|
receipt: CommittedCandidateReceipt<T::Hash>,
|
|
backers: BitVec<u8, BitOrderLsb0>,
|
|
availability_votes: BitVec<u8, BitOrderLsb0>,
|
|
core_index: CoreIndex,
|
|
backing_group: GroupIndex,
|
|
) -> Weight {
|
|
let plain = receipt.to_plain();
|
|
let commitments = receipt.commitments;
|
|
let config = <configuration::Pallet<T>>::config();
|
|
|
|
T::RewardValidators::reward_backing(
|
|
backers
|
|
.iter()
|
|
.enumerate()
|
|
.filter(|(_, backed)| **backed)
|
|
.map(|(i, _)| ValidatorIndex(i as _)),
|
|
);
|
|
|
|
T::RewardValidators::reward_bitfields(
|
|
availability_votes
|
|
.iter()
|
|
.enumerate()
|
|
.filter(|(_, voted)| **voted)
|
|
.map(|(i, _)| ValidatorIndex(i as _)),
|
|
);
|
|
|
|
// initial weight is config read.
|
|
let mut weight = T::DbWeight::get().reads_writes(1, 0);
|
|
if let Some(new_code) = commitments.new_validation_code {
|
|
// Block number of candidate's inclusion.
|
|
let now = <frame_system::Pallet<T>>::block_number();
|
|
|
|
weight.saturating_add(<paras::Pallet<T>>::schedule_code_upgrade(
|
|
receipt.descriptor.para_id,
|
|
new_code,
|
|
now,
|
|
&config,
|
|
));
|
|
}
|
|
|
|
// enact the messaging facet of the candidate.
|
|
weight.saturating_accrue(<dmp::Pallet<T>>::prune_dmq(
|
|
receipt.descriptor.para_id,
|
|
commitments.processed_downward_messages,
|
|
));
|
|
weight.saturating_accrue(Self::receive_upward_messages(
|
|
receipt.descriptor.para_id,
|
|
commitments.upward_messages.as_slice(),
|
|
));
|
|
weight.saturating_accrue(<hrmp::Pallet<T>>::prune_hrmp(
|
|
receipt.descriptor.para_id,
|
|
BlockNumberFor::<T>::from(commitments.hrmp_watermark),
|
|
));
|
|
weight.saturating_accrue(<hrmp::Pallet<T>>::queue_outbound_hrmp(
|
|
receipt.descriptor.para_id,
|
|
commitments.horizontal_messages,
|
|
));
|
|
|
|
Self::deposit_event(Event::<T>::CandidateIncluded(
|
|
plain,
|
|
commitments.head_data.clone(),
|
|
core_index,
|
|
backing_group,
|
|
));
|
|
|
|
weight.saturating_add(<paras::Pallet<T>>::note_new_head(
|
|
receipt.descriptor.para_id,
|
|
commitments.head_data,
|
|
relay_parent_number,
|
|
))
|
|
}
|
|
|
|
pub(crate) fn relay_dispatch_queue_size(para_id: ParaId) -> (u32, u32) {
|
|
let fp = T::MessageQueue::footprint(AggregateMessageOrigin::Ump(UmpQueueId::Para(para_id)));
|
|
(fp.count as u32, fp.size as u32)
|
|
}
|
|
|
|
/// Check that all the upward messages sent by a candidate pass the acceptance criteria.
|
|
pub(crate) fn check_upward_messages(
|
|
config: &HostConfiguration<BlockNumberFor<T>>,
|
|
para: ParaId,
|
|
upward_messages: &[UpwardMessage],
|
|
) -> Result<(), UmpAcceptanceCheckErr> {
|
|
// Cannot send UMP messages while off-boarding.
|
|
if <paras::Pallet<T>>::is_offboarding(para) {
|
|
ensure!(upward_messages.is_empty(), UmpAcceptanceCheckErr::IsOffboarding);
|
|
}
|
|
|
|
let additional_msgs = upward_messages.len() as u32;
|
|
if additional_msgs > config.max_upward_message_num_per_candidate {
|
|
return Err(UmpAcceptanceCheckErr::MoreMessagesThanPermitted {
|
|
sent: additional_msgs,
|
|
permitted: config.max_upward_message_num_per_candidate,
|
|
})
|
|
}
|
|
|
|
let (para_queue_count, mut para_queue_size) = Self::relay_dispatch_queue_size(para);
|
|
|
|
if para_queue_count.saturating_add(additional_msgs) > config.max_upward_queue_count {
|
|
return Err(UmpAcceptanceCheckErr::CapacityExceeded {
|
|
count: para_queue_count.saturating_add(additional_msgs).into(),
|
|
limit: config.max_upward_queue_count.into(),
|
|
})
|
|
}
|
|
|
|
for (idx, msg) in upward_messages.into_iter().enumerate() {
|
|
let msg_size = msg.len() as u32;
|
|
if msg_size > config.max_upward_message_size {
|
|
return Err(UmpAcceptanceCheckErr::MessageSize {
|
|
idx: idx as u32,
|
|
msg_size,
|
|
max_size: config.max_upward_message_size,
|
|
})
|
|
}
|
|
// make sure that the queue is not overfilled.
|
|
// we do it here only once since returning false invalidates the whole relay-chain
|
|
// block.
|
|
if para_queue_size.saturating_add(msg_size) > config.max_upward_queue_size {
|
|
return Err(UmpAcceptanceCheckErr::TotalSizeExceeded {
|
|
total_size: para_queue_size.saturating_add(msg_size).into(),
|
|
limit: config.max_upward_queue_size.into(),
|
|
})
|
|
}
|
|
para_queue_size.saturating_accrue(msg_size);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Enqueues `upward_messages` from a `para`'s accepted candidate block.
|
|
///
|
|
/// This function is infallible since the candidate was already accepted and we therefore need
|
|
/// to deal with the messages as given. Messages that are too long will be ignored since such
|
|
/// candidates should have already been rejected in [`Self::check_upward_messages`].
|
|
pub(crate) fn receive_upward_messages(para: ParaId, upward_messages: &[Vec<u8>]) -> Weight {
|
|
let bounded = upward_messages
|
|
.iter()
|
|
.filter_map(|d| {
|
|
BoundedSlice::try_from(&d[..])
|
|
.map_err(|e| {
|
|
defensive!("Accepted candidate contains too long msg, len=", d.len());
|
|
e
|
|
})
|
|
.ok()
|
|
})
|
|
.collect();
|
|
Self::receive_bounded_upward_messages(para, bounded)
|
|
}
|
|
|
|
/// Enqueues storage-bounded `upward_messages` from a `para`'s accepted candidate block.
|
|
pub(crate) fn receive_bounded_upward_messages(
|
|
para: ParaId,
|
|
messages: Vec<BoundedSlice<'_, u8, MaxUmpMessageLenOf<T>>>,
|
|
) -> Weight {
|
|
let count = messages.len() as u32;
|
|
if count == 0 {
|
|
return Weight::zero()
|
|
}
|
|
|
|
T::MessageQueue::enqueue_messages(
|
|
messages.into_iter(),
|
|
AggregateMessageOrigin::Ump(UmpQueueId::Para(para)),
|
|
);
|
|
let weight = <T as Config>::WeightInfo::receive_upward_messages(count);
|
|
Self::deposit_event(Event::UpwardMessagesReceived { from: para, count });
|
|
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).
|
|
///
|
|
/// Returns a vector of cleaned-up core IDs.
|
|
pub(crate) fn collect_pending(
|
|
pred: impl Fn(CoreIndex, BlockNumberFor<T>) -> bool,
|
|
) -> Vec<CoreIndex> {
|
|
let mut cleaned_up_ids = Vec::new();
|
|
let mut cleaned_up_cores = Vec::new();
|
|
|
|
for (para_id, pending_record) in <PendingAvailability<T>>::iter() {
|
|
if pred(pending_record.core, pending_record.backed_in_number) {
|
|
cleaned_up_ids.push(para_id);
|
|
cleaned_up_cores.push(pending_record.core);
|
|
}
|
|
}
|
|
|
|
for para_id in cleaned_up_ids {
|
|
let pending = <PendingAvailability<T>>::take(¶_id);
|
|
let commitments = <PendingAvailabilityCommitments<T>>::take(¶_id);
|
|
|
|
if let (Some(pending), Some(commitments)) = (pending, commitments) {
|
|
// defensive: this should always be true.
|
|
let candidate = CandidateReceipt {
|
|
descriptor: pending.descriptor,
|
|
commitments_hash: commitments.hash(),
|
|
};
|
|
|
|
Self::deposit_event(Event::<T>::CandidateTimedOut(
|
|
candidate,
|
|
commitments.head_data,
|
|
pending.core,
|
|
));
|
|
}
|
|
}
|
|
|
|
cleaned_up_cores
|
|
}
|
|
|
|
/// Cleans up all paras pending availability that are in the given list of disputed candidates.
|
|
///
|
|
/// 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();
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
for para_id in cleaned_up_ids {
|
|
let _ = <PendingAvailability<T>>::take(¶_id);
|
|
let _ = <PendingAvailabilityCommitments<T>>::take(¶_id);
|
|
}
|
|
|
|
cleaned_up_cores
|
|
}
|
|
|
|
/// 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.
|
|
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 };
|
|
|
|
Self::enact_candidate(
|
|
pending.relay_parent_number,
|
|
candidate,
|
|
pending.backers,
|
|
pending.availability_votes,
|
|
pending.core,
|
|
pending.backing_group,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Returns the `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 })
|
|
}
|
|
|
|
/// Returns the metadata around the 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(¶)
|
|
}
|
|
}
|
|
|
|
const fn availability_threshold(n_validators: usize) -> usize {
|
|
supermajority_threshold(n_validators)
|
|
}
|
|
|
|
impl<BlockNumber> AcceptanceCheckErr<BlockNumber> {
|
|
/// Returns the same error so that it can be threaded through a needle of `DispatchError` and
|
|
/// ultimately returned from a `Dispatchable`.
|
|
fn strip_into_dispatch_err<T: Config>(self) -> Error<T> {
|
|
use AcceptanceCheckErr::*;
|
|
match self {
|
|
HeadDataTooLarge => Error::<T>::HeadDataTooLarge,
|
|
PrematureCodeUpgrade => Error::<T>::PrematureCodeUpgrade,
|
|
NewCodeTooLarge => Error::<T>::NewCodeTooLarge,
|
|
ProcessedDownwardMessages(_) => Error::<T>::IncorrectDownwardMessageHandling,
|
|
UpwardMessages(_) => Error::<T>::InvalidUpwardMessages,
|
|
HrmpWatermark(_) => Error::<T>::HrmpWatermarkMishandling,
|
|
OutboundHrmp(_) => Error::<T>::InvalidOutboundHrmp,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T: Config> OnQueueChanged<AggregateMessageOrigin> for Pallet<T> {
|
|
// Write back the remaining queue capacity into `relay_dispatch_queue_remaining_capacity`.
|
|
fn on_queue_changed(origin: AggregateMessageOrigin, count: u64, size: u64) {
|
|
let para = match origin {
|
|
AggregateMessageOrigin::Ump(UmpQueueId::Para(p)) => p,
|
|
};
|
|
let (count, size) = (count.saturated_into(), size.saturated_into());
|
|
// TODO paritytech/polkadot#6283: Remove all usages of `relay_dispatch_queue_size`
|
|
#[allow(deprecated)]
|
|
well_known_keys::relay_dispatch_queue_size_typed(para).set((count, size));
|
|
|
|
let config = <configuration::Pallet<T>>::config();
|
|
let remaining_count = config.max_upward_queue_count.saturating_sub(count);
|
|
let remaining_size = config.max_upward_queue_size.saturating_sub(size);
|
|
well_known_keys::relay_dispatch_queue_remaining_capacity(para)
|
|
.set((remaining_count, remaining_size));
|
|
}
|
|
}
|
|
|
|
/// A collection of data required for checking a candidate.
|
|
pub(crate) struct CandidateCheckContext<T: Config> {
|
|
config: configuration::HostConfiguration<BlockNumberFor<T>>,
|
|
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 }
|
|
}
|
|
|
|
/// Execute verification of the candidate.
|
|
///
|
|
/// Assures:
|
|
/// * relay-parent in-bounds
|
|
/// * collator signature check passes
|
|
/// * code hash of commitments matches current code hash
|
|
/// * para head in the descriptor and commitments match
|
|
///
|
|
/// Returns the relay-parent block number.
|
|
pub(crate) fn verify_backed_candidate(
|
|
&self,
|
|
allowed_relay_parents: &AllowedRelayParentsTracker<T::Hash, BlockNumberFor<T>>,
|
|
candidate_idx: usize,
|
|
backed_candidate: &BackedCandidate<<T as frame_system::Config>::Hash>,
|
|
) -> Result<Result<BlockNumberFor<T>, FailedToCreatePVD>, Error<T>> {
|
|
let para_id = backed_candidate.descriptor().para_id;
|
|
let relay_parent = backed_candidate.descriptor().relay_parent;
|
|
|
|
// Check that the relay-parent is one of the allowed relay-parents.
|
|
let (relay_parent_storage_root, relay_parent_number) = {
|
|
match allowed_relay_parents.acquire_info(relay_parent, self.prev_context) {
|
|
None => return Err(Error::<T>::DisallowedRelayParent),
|
|
Some(info) => info,
|
|
}
|
|
};
|
|
|
|
{
|
|
let persisted_validation_data = match crate::util::make_persisted_validation_data::<T>(
|
|
para_id,
|
|
relay_parent_number,
|
|
relay_parent_storage_root,
|
|
)
|
|
.defensive_proof("the para is registered")
|
|
{
|
|
Some(l) => l,
|
|
None => return Ok(Err(FailedToCreatePVD)),
|
|
};
|
|
|
|
let expected = persisted_validation_data.hash();
|
|
|
|
ensure!(
|
|
expected == backed_candidate.descriptor().persisted_validation_data_hash,
|
|
Error::<T>::ValidationDataHashMismatch,
|
|
);
|
|
}
|
|
|
|
ensure!(
|
|
backed_candidate.descriptor().check_collator_signature().is_ok(),
|
|
Error::<T>::NotCollatorSigned,
|
|
);
|
|
|
|
let validation_code_hash = <paras::Pallet<T>>::current_code_hash(para_id)
|
|
// A candidate for a parachain without current validation code is not scheduled.
|
|
.ok_or_else(|| Error::<T>::UnscheduledCandidate)?;
|
|
ensure!(
|
|
backed_candidate.descriptor().validation_code_hash == validation_code_hash,
|
|
Error::<T>::InvalidValidationCodeHash,
|
|
);
|
|
|
|
ensure!(
|
|
backed_candidate.descriptor().para_head ==
|
|
backed_candidate.candidate.commitments.head_data.hash(),
|
|
Error::<T>::ParaHeadMismatch,
|
|
);
|
|
|
|
if let Err(err) = self.check_validation_outputs(
|
|
para_id,
|
|
relay_parent_number,
|
|
&backed_candidate.candidate.commitments.head_data,
|
|
&backed_candidate.candidate.commitments.new_validation_code,
|
|
backed_candidate.candidate.commitments.processed_downward_messages,
|
|
&backed_candidate.candidate.commitments.upward_messages,
|
|
BlockNumberFor::<T>::from(backed_candidate.candidate.commitments.hrmp_watermark),
|
|
&backed_candidate.candidate.commitments.horizontal_messages,
|
|
) {
|
|
log::debug!(
|
|
target: LOG_TARGET,
|
|
"Validation outputs checking during inclusion of a candidate {} for parachain `{}` failed",
|
|
candidate_idx,
|
|
u32::from(para_id),
|
|
);
|
|
Err(err.strip_into_dispatch_err::<T>())?;
|
|
};
|
|
Ok(Ok(relay_parent_number))
|
|
}
|
|
|
|
/// Check the given outputs after candidate validation on whether it passes the acceptance
|
|
/// criteria.
|
|
///
|
|
/// The things that are checked can be roughly divided into limits and minimums.
|
|
///
|
|
/// Limits are things like max message queue sizes and max head data size.
|
|
///
|
|
/// Minimums are things like the minimum amount of messages that must be processed
|
|
/// by the parachain block.
|
|
///
|
|
/// Limits are checked against the current state. The parachain block must be acceptable
|
|
/// by the current relay-chain state regardless of whether it was acceptable at some relay-chain
|
|
/// state in the past.
|
|
///
|
|
/// Minimums are checked against the current state but modulated by
|
|
/// considering the information available at the relay-parent of the parachain block.
|
|
fn check_validation_outputs(
|
|
&self,
|
|
para_id: ParaId,
|
|
relay_parent_number: BlockNumberFor<T>,
|
|
head_data: &HeadData,
|
|
new_validation_code: &Option<primitives::ValidationCode>,
|
|
processed_downward_messages: u32,
|
|
upward_messages: &[primitives::UpwardMessage],
|
|
hrmp_watermark: BlockNumberFor<T>,
|
|
horizontal_messages: &[primitives::OutboundHrmpMessage<ParaId>],
|
|
) -> Result<(), AcceptanceCheckErr<BlockNumberFor<T>>> {
|
|
ensure!(
|
|
head_data.0.len() <= self.config.max_head_data_size as _,
|
|
AcceptanceCheckErr::HeadDataTooLarge,
|
|
);
|
|
|
|
// if any, the code upgrade attempt is allowed.
|
|
if let Some(new_validation_code) = new_validation_code {
|
|
ensure!(
|
|
<paras::Pallet<T>>::can_upgrade_validation_code(para_id),
|
|
AcceptanceCheckErr::PrematureCodeUpgrade,
|
|
);
|
|
ensure!(
|
|
new_validation_code.0.len() <= self.config.max_code_size as _,
|
|
AcceptanceCheckErr::NewCodeTooLarge,
|
|
);
|
|
}
|
|
|
|
// check if the candidate passes the messaging acceptance criteria
|
|
<dmp::Pallet<T>>::check_processed_downward_messages(
|
|
para_id,
|
|
relay_parent_number,
|
|
processed_downward_messages,
|
|
)?;
|
|
Pallet::<T>::check_upward_messages(&self.config, para_id, upward_messages)?;
|
|
<hrmp::Pallet<T>>::check_hrmp_watermark(para_id, relay_parent_number, hrmp_watermark)?;
|
|
<hrmp::Pallet<T>>::check_outbound_hrmp(&self.config, para_id, horizontal_messages)?;
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl<T: Config> QueueFootprinter for Pallet<T> {
|
|
type Origin = UmpQueueId;
|
|
|
|
fn message_count(origin: Self::Origin) -> u64 {
|
|
T::MessageQueue::footprint(AggregateMessageOrigin::Ump(origin)).count
|
|
}
|
|
}
|