mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 06:21:11 +00:00
pvf-precheck: update implementers' guide (#4612)
This commit incorporates the changes made to the runtime in the following PRs: - https://github.com/paritytech/polkadot/pull/4408 - https://github.com/paritytech/polkadot/pull/4457 - https://github.com/paritytech/polkadot/pull/4540 - https://github.com/paritytech/polkadot/pull/4542 - https://github.com/paritytech/polkadot/pull/4581 Note that this PR does not include the description of the PVF pre-checker subsystem. This should be addressed within https://github.com/paritytech/polkadot/issues/4611 Co-authored-by: sandreim <54316454+sandreim@users.noreply.github.com>
This commit is contained in:
@@ -12,29 +12,51 @@ The configuration module is responsible for two main pieces of storage.
|
||||
/// The current configuration to be used.
|
||||
Configuration: HostConfiguration;
|
||||
/// A pending configuration to be applied on session change.
|
||||
PendingConfiguration: Option<HostConfiguration>;
|
||||
PendingConfigs: Vec<(SessionIndex, HostConfiguration)>;
|
||||
/// A flag that says if the consistency checks should be omitted.
|
||||
BypassConsistencyCheck: bool;
|
||||
```
|
||||
|
||||
## Session change
|
||||
|
||||
The session change routine for the Configuration module is simple. If the `PendingConfiguration` is `Some`, take its value and set `Configuration` to be equal to it. Reset `PendingConfiguration` to `None`.
|
||||
The session change routine works as follows:
|
||||
|
||||
- If there is no pending configurations, then return early.
|
||||
- Take all pending configurations that are less than or equal to the current session index.
|
||||
- Get the pending configuration with the highest session index and apply it to the current configuration. Discard the earlier ones if any.
|
||||
|
||||
## Routines
|
||||
|
||||
```rust
|
||||
enum InconsistentErrror {
|
||||
// ...
|
||||
}
|
||||
|
||||
impl HostConfiguration {
|
||||
fn check_consistency(&self) -> Result<(), InconsistentError> { /* ... */ }
|
||||
}
|
||||
|
||||
/// Get the host configuration.
|
||||
pub fn configuration() -> HostConfiguration {
|
||||
Configuration::get()
|
||||
}
|
||||
|
||||
/// Updating the pending configuration to be applied later.
|
||||
fn update_configuration(f: impl FnOnce(&mut HostConfiguration)) {
|
||||
PendingConfiguration::mutate(|pending| {
|
||||
let mut x = pending.unwrap_or_else(Self::configuration);
|
||||
f(&mut x);
|
||||
*pending = Some(x);
|
||||
})
|
||||
}
|
||||
/// Schedules updating the host configuration. The update is given by the `updater` closure. The
|
||||
/// closure takes the current version of the configuration and returns the new version.
|
||||
/// Returns an `Err` if the closure returns a broken configuration. However, there are a couple of
|
||||
/// exceptions:
|
||||
///
|
||||
/// - if the configuration that was passed in the closure is already broken, then it will pass the
|
||||
/// update: you cannot break something that is already broken.
|
||||
/// - If the `BypassConsistencyCheck` flag is set, then the checks will be skipped.
|
||||
///
|
||||
/// The changes made by this function will always be scheduled at session X, where X is the current session index + 2.
|
||||
/// If there is already a pending update for X, then the closure will receive the already pending configuration for
|
||||
/// session X.
|
||||
///
|
||||
/// If there is already a pending update for the current session index + 1, then it won't be touched. Otherwise,
|
||||
/// that would violate the promise of this function that changes will be applied on the second session change (cur + 2).
|
||||
fn schedule_config_update(updater: impl FnOnce(&mut HostConfiguration<T::BlockNumber>)) -> DispatchResult
|
||||
```
|
||||
|
||||
## Entry-points
|
||||
|
||||
@@ -5,8 +5,11 @@ parachains and parathreads cannot change except at session boundaries and after
|
||||
session has passed. This is primarily to ensure that the number and meaning of bits required for the
|
||||
availability bitfields does not change except at session boundaries.
|
||||
|
||||
It's also responsible for managing parachain validation code upgrades as well as maintaining
|
||||
availability of old parachain code and its pruning.
|
||||
It's also responsible for:
|
||||
|
||||
- managing parachain validation code upgrades as well as maintaining availability of old parachain
|
||||
code and its pruning.
|
||||
- vetting PVFs by means of the PVF pre-checking mechanism.
|
||||
|
||||
## Storage
|
||||
|
||||
@@ -38,13 +41,6 @@ pub struct ParaPastCodeMeta {
|
||||
last_pruned: Option<BlockNumber>,
|
||||
}
|
||||
|
||||
enum UseCodeAt {
|
||||
// Use the current code.
|
||||
Current,
|
||||
// Use the code that was replaced at the given block number.
|
||||
ReplacedAt(BlockNumber),
|
||||
}
|
||||
|
||||
struct ParaGenesisArgs {
|
||||
/// The initial head-data to use.
|
||||
genesis_head: HeadData,
|
||||
@@ -71,18 +67,49 @@ pub enum ParaLifecycle {
|
||||
/// Parachain is being offboarded.
|
||||
OutgoingParachain,
|
||||
}
|
||||
|
||||
enum PvfCheckCause {
|
||||
/// PVF vote was initiated by the initial onboarding process of the given para.
|
||||
Onboarding(ParaId),
|
||||
/// PVF vote was initiated by signalling of an upgrade by the given para.
|
||||
Upgrade {
|
||||
/// The ID of the parachain that initiated or is waiting for the conclusion of pre-checking.
|
||||
id: ParaId,
|
||||
/// The relay-chain block number that was used as the relay-parent for the parablock that
|
||||
/// initiated the upgrade.
|
||||
relay_parent_number: BlockNumber,
|
||||
},
|
||||
}
|
||||
|
||||
struct PvfCheckActiveVoteState {
|
||||
// The two following vectors have their length equal to the number of validators in the active
|
||||
// set. They start with all zeroes. A 1 is set at an index when the validator at the that index
|
||||
// makes a vote. Once a 1 is set for either of the vectors, that validator cannot vote anymore.
|
||||
// Since the active validator set changes each session, the bit vectors are reinitialized as
|
||||
// well: zeroed and resized so that each validator gets its own bit.
|
||||
votes_accept: BitVec,
|
||||
votes_reject: BitVec,
|
||||
|
||||
/// The number of session changes this PVF vote has observed. Therefore, this number is
|
||||
/// increased at each session boundary. When created, it is initialized with 0.
|
||||
age: SessionIndex,
|
||||
/// The block number at which this PVF vote was created.
|
||||
created_at: BlockNumber,
|
||||
/// A list of causes for this PVF pre-checking. Has at least one.
|
||||
causes: Vec<PvfCheckCause>,
|
||||
}
|
||||
```
|
||||
|
||||
#### Para Lifecycle
|
||||
|
||||
Because the state of parachains and parathreads are delayed by a session, we track the specific
|
||||
state of the para using the `ParaLifecycle` enum.
|
||||
Because the state changes of parachains and parathreads are delayed, we track the specific state of
|
||||
the para using the `ParaLifecycle` enum.
|
||||
|
||||
```
|
||||
None Parathread Parachain
|
||||
+ + +
|
||||
| | |
|
||||
| (2 Session Delay) | |
|
||||
| (≈2 Session Delay) | |
|
||||
| | |
|
||||
+----------------------->+ |
|
||||
| Onboarding | |
|
||||
@@ -105,11 +132,21 @@ None Parathread Parachain
|
||||
+ + +
|
||||
```
|
||||
|
||||
Note that if PVF pre-checking is enabled, onboarding of a para may potentially be delayed. This can
|
||||
happen due to PVF pre-checking voting concluding late.
|
||||
|
||||
During the transition period, the para object is still considered in its existing state.
|
||||
|
||||
### Storage Layout
|
||||
|
||||
```rust
|
||||
/// All currently active PVF pre-checking votes.
|
||||
///
|
||||
/// Invariant:
|
||||
/// - There are no PVF pre-checking votes that exists in list but not in the set and vice versa.
|
||||
PvfActiveVoteMap: map ValidationCodeHash => PvfCheckActiveVoteState;
|
||||
/// The list of all currently active PVF votes. Auxiliary to `PvfActiveVoteMap`.
|
||||
PvfActiveVoteList: Vec<ValidationCodeHash>;
|
||||
/// All parachains. Ordered ascending by ParaId. Parathreads are not included.
|
||||
Parachains: Vec<ParaId>,
|
||||
/// The current lifecycle state of all known Para Ids.
|
||||
@@ -169,6 +206,9 @@ UpcomingUpgrades: Vec<(ParaId, T::BlockNumber)>;
|
||||
/// The actions to perform during the start of a specific session index.
|
||||
ActionsQueue: map SessionIndex => Vec<ParaId>;
|
||||
/// Upcoming paras instantiation arguments.
|
||||
///
|
||||
/// NOTE that after PVF pre-checking is enabled the para genesis arg will have it's code set
|
||||
/// to empty. Instead, the code will be saved into the storage right away via `CodeByHash`.
|
||||
UpcomingParasGenesis: map ParaId => Option<ParaGenesisArgs>;
|
||||
/// The number of references on the validation code in `CodeByHash` storage.
|
||||
CodeByHashRefs: map ValidationCodeHash => u32;
|
||||
@@ -194,8 +234,13 @@ CodeByHash: map ValidationCodeHash => Option<ValidationCode>
|
||||
`ParaLifecycle`.
|
||||
1. Downgrade all parachains that should become parathreads, updating the `Parachains` list and
|
||||
`ParaLifecycle`.
|
||||
1. Return list of outgoing paras to the initializer for use by other modules.
|
||||
|
||||
1. (Deferred) Return list of outgoing paras to the initializer for use by other modules.
|
||||
1. Go over all active PVF pre-checking votes:
|
||||
1. Increment `age` of the vote.
|
||||
1. If `age` reached `cfg.pvf_voting_ttl`, then enact PVF rejection and remove the vote from the active list.
|
||||
1. Otherwise, reinitialize the ballots.
|
||||
1. Resize the `votes_accept`/`votes_reject` to have the same length as the incoming validator set.
|
||||
1. Zero all the votes.
|
||||
## Initialization
|
||||
|
||||
1. Do pruning based on all entries in `PastCodePruning` with `BlockNumber <= now`. Update the
|
||||
@@ -211,9 +256,10 @@ CodeByHash: map ValidationCodeHash => Option<ValidationCode>
|
||||
* `schedule_para_cleanup(ParaId)`: Schedule a para to be cleaned up after the next full session.
|
||||
* `schedule_parathread_upgrade(ParaId)`: Schedule a parathread to be upgraded to a parachain.
|
||||
* `schedule_parachain_downgrade(ParaId)`: Schedule a parachain to be downgraded to a parathread.
|
||||
* `schedule_code_upgrade(ParaId, CurrentCode, relay_parent: BlockNumber, HostConfiguration)`: Schedule a future code
|
||||
upgrade of the given parachain, to be applied after inclusion of a block of the same parachain
|
||||
* `schedule_code_upgrade(ParaId, new_code, relay_parent: BlockNumber, HostConfiguration)`: Schedule a future code
|
||||
upgrade of the given parachain. In case the PVF pre-checking is disabled, or the new code is already present in the storage, the upgrade will be applied after inclusion of a block of the same parachain
|
||||
executed in the context of a relay-chain block with number >= `relay_parent + config.validation_upgrade_delay`. If the upgrade is scheduled `UpgradeRestrictionSignal` is set and it will remain set until `relay_parent + config.validation_upgrade_frequency`.
|
||||
In case the PVF pre-checking is enabled, or the new code is not already present in the storage, then the PVF pre-checking run will be scheduled for that validation code. If the pre-checking concludes with rejection, then the upgrade is canceled. Otherwise, after pre-checking is concluded the upgrade will be scheduled and be enacted as described above.
|
||||
* `note_new_head(ParaId, HeadData, BlockNumber)`: note that a para has progressed to a new head,
|
||||
where the new head was executed in the context of a relay-chain block with given number. This will
|
||||
apply pending code upgrades based on the block number provided. If an upgrade took place it will clear the `UpgradeGoAheadSignal`.
|
||||
@@ -225,6 +271,7 @@ CodeByHash: map ValidationCodeHash => Option<ValidationCode>
|
||||
* `is_valid_para(ParaId) -> bool`: Returns true if the para ID references either a live parathread
|
||||
or live parachain.
|
||||
* `can_upgrade_validation_code(ParaId) -> bool`: Returns true if the given para can signal code upgrade right now.
|
||||
* `pvfs_require_prechecking() -> Vec<ValidationCodeHash>`: Returns the list of PVF validation code hashes that require PVF pre-checking votes.
|
||||
|
||||
## Finalization
|
||||
|
||||
|
||||
Reference in New Issue
Block a user