Files
pezkuwi-subxt/polkadot/roadmap/implementers-guide/src/runtime/parainherent.md
T
Bernhard Schuster 1aa6a4aba4 move paras inherent filtering to runtime (#4028)
* move things around, add filter methods

* validator keys, modify availability bitfields according to disputes

* simplify, keep the filter -> sanitize generic for both usecases

* minor

* assure tests still work, reduce changeset

* integration

* start entropy passing

* fixins

* compile, 1 failing test

* filter with coverage

* fixins

* Update runtime/parachains/src/paras_inherent.rs

Co-authored-by: Robert Habermeier <rphmeier@gmail.com>

* slip of the pen

* improve test cases

* misc

* fix

* fixins

* test avoid extra into() calls in assert_noop!

* chores

* ff

* test fixup superfluous into call

* chore: pfmt

* improve apply_block_weight_limit to try to maximize the number of sufficiently backed

blocks and add extra bitfields in a round-robin fashion

* new code treats the lack of backed candidates as ok

* Use vrf based entropy

* fixup vrf random

* add warn

* slip of the pen

* fixup

* assure ordering

* rethink apply_weights

* mock

* use a closure as predicate check

* extract and use DisputedBitfield

* chore: simplify

* remove stray dbg

* chore: fmt

* address feedback

* fix test, halfway there

* stage1

* dbg stuff

* make group selection align

* fix session index

* fix wrongly returned candidates

* cleanup

* chore fmt

* fix ensure check

* make good case test work

* more tests for bitfields

* create sanitize_backed_candidates

* fixup tests

* update guide

* add check referenced in the guide

* improve weights code

* fmt

* fixins

* Update roadmap/implementers-guide/src/runtime/inclusion.md

Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com>

* compiling + address review

* add comments

* fix weight calc

* address review comments and test failure

* fix

* fix: condition

* Fix random_sel function

* Fix overlength block check

* Zeke + Ladi commit for disputes filtering + integration test builder + runtime benchmarks + integration tests

* Add benchmarks for code upgrades

* Code upgrade bench; Feature gate TestWeightInfo

* Try and make CI happier

* Feature gate enter test to not(benchmarks)

* Make sure no unused imports/fn

* refactor, re-use, the beginning

* Fix issue with frame benchmarking dep compilation

* More precise feature gating for some derives

* integrate piece-wise

* foo

* fixins

* chore fmt

* fixins

* rename const generic

* Update runtime/parachains/src/paras_inherent.rs

Co-authored-by: Zeke Mostov <z.mostov@gmail.com>

* Fix compilation

* limit to test

* remove unused spam slots

* spellcheck

* remove a tick, fix a typo

* Add Code upgrade weights

* comment improvements + >=

Co-authored-by: Zeke Mostov <z.mostov@gmail.com>

* remove another tick

* Update runtime/parachains/src/paras_inherent/benchmarking.rs

Co-authored-by: Zeke Mostov <z.mostov@gmail.com>

* saturating fixins + some spaces

* fix

* benchmarking - preliminary results

* Add training wheels

* Refactor some early exit logic for enter

* Gracefully handle filtering bitfields & candidates (#4280)

This updates the logic for sanitize_bitfields and sanitize_backed_candidates to never error when there is an issue, but instead to simply skip the problematic items.

* Refactor inherent data weight limiting logic (#4287)

* Apply suggestions from code review

* Update runtime/parachains/src/builder.rs

Co-authored-by: Zeke Mostov <z.mostov@gmail.com>

* Update runtime/parachains/src/builder.rs

* Update runtime/parachains/src/paras_inherent.rs

* final pass

* Run cargo +nightly-2021-10-29 fmt

* Update implementors guide with `sanitize_*` & `enter` (#4294)

* Make spell check happier

* Make wasm runtimes compile with benchmarks enabled (#4303)

* comment stuff out, use old toml

* Seems to be working?

* Remove feature gating from builder

* Remove commented out stuff

* Remove generic from digest

* Update weight files for runtime

Co-authored-by: Robert Habermeier <rphmeier@gmail.com>
Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com>
Co-authored-by: Lldenaurois <Ljdenaurois@gmail.com>
Co-authored-by: Zeke Mostov <z.mostov@gmail.com>
Co-authored-by: Bastian Köcher <info@kchr.de>
2021-11-16 18:39:39 +00:00

8.6 KiB

ParaInherent

This module is responsible for providing all data given to the runtime by the block author to the various parachains modules. The entry-point is mandatory, in that it must be invoked exactly once within every block, and it is also "inherent", in that it is provided with no origin by the block author. The data within it carries its own authentication; i.e. the data takes the form of signed statements by validators. If any of the steps within fails, the entry-point is considered as having failed and the block will be invalid.

This module does not have the same initialization/finalization concerns as the others, as it only requires that entry points be triggered after all modules have initialized and that finalization happens after entry points are triggered. Both of these are assumptions we have already made about the runtime's order of operations, so this module doesn't need to be initialized or finalized by the Initializer.

There are a couple of important notes to the operations in this inherent as they relate to disputes.

  1. We don't accept bitfields or backed candidates if in "governance-only" mode from having a local dispute conclude on this fork.
  2. When disputes are initiated, we remove the block from pending availability. This allows us to roll back chains to the block before blocks are included as opposed to backing. It's important to do this before processing bitfields.
  3. Inclusion::collect_disputed is kind of expensive so it's important to gate this on whether there are actually any new disputes. Which should be never.
  4. And we don't accept parablocks that have open disputes or disputes that have concluded against the candidate. It's important to import dispute statements before backing, but this is already the case as disputes are imported before processing bitfields.

Storage

/// Whether the para inherent was included or not.
Included: Option<()>,
/// Scraped on chain votes to be used in disputes off-chain.
OnChainVotes: Option<ScrapedOnChainVotes>,

Finalization

  1. Take (get and clear) the value of Included. If it is not Some, throw an unrecoverable error.

Entry Points

  • enter: This entry-point accepts one parameter: ParaInherentData.

    1. Ensure the origin is none.
    2. Ensure Included is set as None.
    3. Set Included as Some.
    4. Unpack ParachainsInherentData into signed_bitfields, backed_candidates, parent_header, and disputes.
    5. Hash the parent header and make sure that it corresponds to the block hash of the parent (tracked by the frame_system FRAME module).
    6. Calculate the candidate_weight, bitfields_weight, and disputes_weight.
    7. If the sum of candidate_weight, bitfields_weight, and disputes_weight is greater than the max block weight we do the following with the goal of prioritizing the inclusion of disputes without making it game-able by block authors: 1. clear bitfields and set bitfields_weight equal to 0. 1. clear backed_candidates and set candidate_weight equal to 0. 1. invoke limit_disputes on the disputes with the max block weight iff the disputes weight is greater than the max block weight.
    8. Invoke Disputes::provide_multi_dispute_data.
    9. If Disputes::is_frozen, return.
    10. If there are any concluded disputes from the current session, invoke Inclusion::collect_disputed with the disputed candidates. Annotate each returned core with FreedReason::Concluded, sort them, and invoke Scheduler::free_cores with them.
    11. The Bitfields are first forwarded to the Inclusion::process_bitfields routine, returning a set included candidates and the respective freed cores. Provide the number of availability cores (Scheduler::availability_cores().len()) as the expected number of bits and a Scheduler::core_para as a core-lookup to the process_bitfields routine. Annotate each of these freed cores with FreedReason::Concluded.
    12. For each freed candidate from the Inclusion::process_bitfields call, invoke Disputes::note_included(current_session, candidate).
    13. If Scheduler::availability_timeout_predicate is Some, invoke Inclusion::collect_pending using it and annotate each of those freed cores with FreedReason::TimedOut.
    14. Combine and sort the the bitfield-freed cores and the timed-out cores.
    15. Invoke Scheduler::clear
    16. Invoke Scheduler::schedule(freed_cores, System::current_block())
    17. Extract parent_storage_root from the parent header,
    18. If Disputes::concluded_invalid(current_session, candidate) is true for any of the backed_candidates, fail.
    19. Invoke the Inclusion::process_candidates routine with the parameters (parent_storage_root, backed_candidates, Scheduler::scheduled(), Scheduler::group_validators).
    20. Deconstruct the returned ProcessedCandidates value into occupied core indices, and backing validators by candidate backing_validators_per_candidate represented by Vec<(CandidateReceipt, Vec<(ValidatorIndex, ValidityAttestation)>)>.
    21. Set OnChainVotes to ScrapedOnChainVotes, based on the current_session, concluded disputes, and backing_validators_per_candidate.
    22. Call Scheduler::occupied using the occupied core indices of the returned above, first sorting the list of assigned core indices.
    23. Call the Ump::process_pending_upward_messages routine to execute all messages in upward dispatch queues.
    24. If all of the above succeeds, set Included to Some(()).
  • create_inherent: This entry-point accepts one parameter: InherentData.

    1. Invoke create_inherent_inner(InherentData), the unit testable logic for filtering and sanitzing the inherent data used when invoking enter. Save the result as inherent_data.
    2. If the inherent_data is an Err variant, return the enter call signature with all inherent data cleared else return the enter call signature with inherent_data passed in as the data param.

Routines

  • create_inherent_inner(data: &InherentData) -> Option<ParachainsInherentData<T::Header>>
    1. Unpack InherentData into its parts, bitfields, backed_candidates, disputes and the parent_header. If data cannot be unpacked return None.
    2. Hash the parent_header and make sure that it corresponds to the block hash of the parent (tracked by the frame_system FRAME module).
    3. Invoke Disputes::filter_multi_dispute_data to remove duplicates et al from disputes.
    4. Run the following within a with_transaction closure to avoid side effects (we are essentially replicating the logic that would otherwise happen within enter so we can get the filtered bitfields and the concluded_invalid_disputes + scheduled to use in filtering the backed_candidates.):
    5. Invoke Disputes::provide_multi_dispute_data.
    6. Collect current_concluded_invalid_disputes, the disputed candidate hashes from the current session that have concluded invalid.
    7. Collect concluded_invalid_disputes, the disputed candidate hashes from the given backed_candidates.
    8. Invoke Inclusion::collect_disputed with the newly disputed candidates. Annotate each returned core with FreedReason::Concluded, sort them, and invoke Scheduler::free_cores with them.
    9. Collect filtered bitfields by invoking sanitize_bitfields<false>.
    10. Collect freed_concluded by invoking update_pending_availability_and_get_freed_cores on the filtered bitfields.
    11. Collect all freed cores by invoking collect_all_freed_cores on freed_concluding.
    12. Invoke scheduler::Pallet<T>>::clear().
    13. Invoke scheduler::Pallet<T>>::schedule with freed and the current block number to create the same schedule of the cores that enter will create.
    14. Read the new <scheduler::Pallet<T>>::scheduled() into schedule.
    15. From the with_transaction closure return concluded_invalid_disputes, bitfields, and scheduled.
    16. Invoke sanitize_backed_candidates using the scheduled return from the with_transaction and pass the closure |candidate_hash: CandidateHash| -> bool { DisputesHandler::concluded_invalid(current_session, candidate_hash) } for the param candidate_has_concluded_invalid_dispute.
    17. create a rng from rand_chacha::ChaChaRng::from_seed(compute_entropy::<T>(parent_hash)).
    18. Invoke limit_disputes with the max block weight and rng, storing the returned weigh in remaining_weight.
    19. Fill up the remaining of the block weight with backed candidates and bitfields by invoking apply_weight_limit with remaining_weigh and rng.
    20. Return Some(ParachainsInherentData { bitfields, backed_candidates, disputes, parent_header }.