-
Notifications
You must be signed in to change notification settings - Fork 371
Asynchronous backing: handle code upgrade signals properly #2580
Description
When a parachain wants to upgrade its code, it submits the new validation code to the relay chain. After some checks and a mandatory waiting period, the relay-chain sets a signal in its storage - either GoAhead or Abort. It is illegal to create a candidate that attempts to upgrade the code if there is already a pending code upgrade.
The GoAhead signal is cleared in the relay chain runtime after the first candidate which used a relay-parent at or after the relay-chain block where it was set is included. This means that the go-ahead signal may hang around in the relay-chain state for a few blocks afterwards.
pallet-parachain-system currently has this code, which panics if the GoAhead signal is set and there is no pending upgrade:
cumulus/pallets/parachain-system/src/lib.rs
Lines 404 to 423 in a82d5af
| match upgrade_go_ahead_signal { | |
| Some(relay_chain::UpgradeGoAhead::GoAhead) => { | |
| assert!( | |
| <PendingValidationCode<T>>::exists(), | |
| "No new validation function found in storage, GoAhead signal is not expected", | |
| ); | |
| let validation_code = <PendingValidationCode<T>>::take(); | |
| Self::put_parachain_code(&validation_code); | |
| <T::OnSystemEvent as OnSystemEvent>::on_validation_code_applied(); | |
| Self::deposit_event(Event::ValidationFunctionApplied { | |
| relay_chain_block_num: vfp.relay_parent_number, | |
| }); | |
| }, | |
| Some(relay_chain::UpgradeGoAhead::Abort) => { | |
| <PendingValidationCode<T>>::kill(); | |
| Self::deposit_event(Event::ValidationFunctionDiscarded); | |
| }, | |
| None => {}, | |
| } |
This means that if the parachain has scheduled a code upgrade, one candidate might see the GoAhead signal and process the code upgrade correctly, but the subsequent candidates (at the same relay-parent or within a few blocks of it) will be invalid. They will become valid again only once the relay-parent has advanced to a point where the GoAhead signal has vanished from the relay-chain state.
The issue here is just to avoid small amounts of downtime after parachains upgrade their code. The fix is to handle the code upgrade signals "properly" i.e. to ignore them when there is no pending code upgrade or the unincluded segment contains an applied/aborted code upgrade.