Put a bitten relay's Asset Hub staking client in Buffered - #28
Merged
csmnprschv merged 1 commit intoSep 15, 2026
Merged
csmnprschv merged 1 commit into
csmnprschv merged 1 commit into
Conversation
Since staking moved to Asset Hub the relay no longer chooses its own validators. Asset Hub's pallet-staking-async elects from the source chain's staking state and pushes the set to the relay's StakingAhClient. Its Mode reads Active on live Polkadot, Kusama and Paseo, and Passive on live Previewnet. A fork holds session keys for six accounts, so pallet_session drops every elected validator, writes an empty Session::QueuedKeys and announces the next BABE epoch with no authorities. Nobody can claim a slot in that epoch, so no block ever enacts the next rotation and the chain stops at the boundary. Session::Validators and Babe::Authorities both still read six afterwards, so a dead fork looks healthy. Measured on the Polkadot fork: block 32891881 opened epoch 13768 carrying a BABE NextEpochData digest of 34 bytes, 0x01 0x00 followed by 32 bytes of randomness, so no authorities were announced for epoch 13769. Babe::NextAuthorities went from six to zero across that block. The fork produced its last block in the final slot of epoch 13768, slot 298129239, and stopped: the first slot of the empty epoch found no author, and Session::CurrentIndex never advanced past 13768. In Buffered, StakingAhClient answers new_session() with None unconditionally, so pallet_session rebuilds the queue from the injected six, and it refuses any set Asset Hub sends: can_accept_validator_set() holds only in Active, and the call fails with Error::Blocked. Staking::ForceEra predates this and stays. Buffered keeps Asset Hub's set out, so what ForceEra guards is ElectionProviderMultiPhase. Under SessionsPerEra 1, Previewnet's value, EPM opens its signed phase and then its unsigned phase every session, and the unsigned phase never ends: it ends only when elect() is called, and nothing calls it. Validators' offchain workers compute a candidate validator set once and keep resubmitting it as an unsigned transaction. Where SessionsPerEra is 6, as on Polkadot and Kusama, it never opens them and the write changes nothing. Signed-off-by: Cosmin Paraschiv <cosmin@parity.io>
mordamax
approved these changes
Sep 15, 2026
csmnprschv
deleted the
cosmin-put-a-bitten-relays-asset-hub-staking-client-in-buffered
branch
September 15, 2026 20:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Since staking moved to Asset Hub the relay no longer chooses its own
validators. Asset Hub's pallet-staking-async elects from the source
chain's staking state and pushes the set to the relay's StakingAhClient.
Its Mode reads Active on live Polkadot, Kusama and Paseo, and Passive on
live Previewnet.
A fork holds session keys for six accounts, so pallet_session drops
every elected validator, writes an empty Session::QueuedKeys and
announces the next BABE epoch with no authorities. Nobody can claim a
slot in that epoch, so no block ever enacts the next rotation and the
chain stops at the boundary. Session::Validators and Babe::Authorities
both still read six afterwards, so a dead fork looks healthy.
Measured on the Polkadot fork: block 32891881 opened epoch 13768
carrying a BABE NextEpochData digest of 34 bytes, 0x01 0x00 followed by
32 bytes of randomness, so no authorities were announced for epoch
13769. Babe::NextAuthorities went from six to zero across that block.
The fork produced its last block in the final slot of epoch 13768, slot
298129239, and stopped: the first slot of the empty epoch found no
author, and Session::CurrentIndex never advanced past 13768.
In Buffered, StakingAhClient answers new_session() with None
unconditionally, so pallet_session rebuilds the queue from the injected
six, and it refuses any set Asset Hub sends: can_accept_validator_set()
holds only in Active, and the call fails with Error::Blocked.
Staking::ForceEra predates this and stays. Buffered keeps Asset Hub's
set out, so what ForceEra guards is ElectionProviderMultiPhase. Under
SessionsPerEra 1, Previewnet's value, EPM opens its signed phase and
then its unsigned phase every session, and the unsigned phase never
ends: it ends only when elect() is called, and nothing calls it.
Validators' offchain workers compute a candidate validator set once and
keep resubmitting it as an unsigned transaction. Where SessionsPerEra is
6, as on Polkadot and Kusama, it never opens them and the write changes
nothing.