on-chain node version reporting with vote-scheduled upgrade enforcement#190
Open
Andrew-Pohl wants to merge 1 commit into
Open
on-chain node version reporting with vote-scheduled upgrade enforcement#190Andrew-Pohl wants to merge 1 commit into
Andrew-Pohl wants to merge 1 commit into
Conversation
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.
Summary
Adds an on-chain mechanism to coordinate network (spec) upgrades. Validators self-report the
node/spec version they are running; a network upgrade (required version + activation height) is
scheduled through a validator ballot in the Voting contract; and on the last cycle boundary before
the new spec activates, the Consensus contract jails any validator still running an old version
provided more than 66% of the current validator set has upgraded. This guarantees the validator
set that is active when the fork block arrives consists only of upgraded nodes.
How it works end-to-end
Voting.newNodeVersionBallot(startAfterCycles, cyclesDuration, version, activationBlock, description).exceed 20% of total stake (turnout) and accepts > rejects. On acceptance, Voting calls
Consensus.setRequiredNodeVersion(version, activationBlock).activationBlock, Consensus counts upgraded validators.If more than 66% (
UPGRADE_QUORUM_BP = 6600, headcount-based) have reported at least therequired version, every outdated validator is jailed and excluded from the validator set that
crosses the fork. The check runs exactly once per scheduled upgrade and emits
NodeVersionCheckExecuted(required, upgradedCount, totalCount, quorumReached)either way.unJail()after reporting at least the required version — upgradingis the only way back into the set.
Contract changes
Consensus / ConsensusUtils
reportNodeVersion(uint256)— self-report, encodedmajor * 1e6 + minor * 1e3 + patch(spec
6.0.3→6000003). EmitsNodeVersionReported.setRequiredNodeVersion(version, activationBlock)—onlyVoting(not owner-callable);schedules the upgrade, version
0cancels a scheduled upgrade. EmitsRequiredNodeVersionSet._checkNodeVersions(...)— runs incycle()after the productivity jail check, before the newpending set is read, so jailed laggards are excluded from the fork cycle's set.
unJail()gate: while a required version is set, release requires having reported it.getNodeVersion(validator),getRequiredNodeVersion(),getNodeVersionActivationBlock(),isNodeVersionCheckExecuted().to roll out via the existing proxy upgrade flow.
Voting / VotingUtils / VotingBase
BallotTypesenum (ContractAddress,NodeVersion). Legacy ballots (type 0) finalize throughthe contract-address path, so in-flight ballots survive the implementation swap.
newNodeVersionBallot(...)— validator-only creation, same duration rules and per-validator ballotlimit as existing ballots. Stores proposed version + activation block.
try/catch:onCycleEndruns inside the block-rewardflow, so an accepted ballot whose activation block has gone stale fails gracefully instead of
reverting
cycle()→reward()and stalling block sealing.Validator app / ops
app/index.js: reports the version from theNODE_VERSIONenv var once per process lifetime(a container restart — i.e. an upgrade — triggers a fresh report). Parses the last
x.y.zin the string, so an image tag like
1.29.0-v6.0.3reports the spec version6.0.3. Runs beforethe
isValidatorearly-return (a version-jailed validator is out of the set but must still reportto unjail), and failures are logged without crashing the cycle loop, so an updated app keeps
working against a not-yet-upgraded contract.
nethermind/quickstart.sh: validator container now gets--env NODE_VERSION=$FUSE_CLIENT_DOCKER_IMAGE_VERSION.abis/*.json,app/abi/*.json).Design decisions
AuRa's per-validator block production model.
ballots that replace entire contract implementations. The >66%-actually-upgraded check at the
cycle boundary is an independent, harder gate.
regardless at that point); old nodes then fall to the existing productivity jailing post-fork.
Testing
yarn test— 186 passing, 0 failingcorrect cycle boundary with quorum, no jailing below quorum, no early firing, unjail blocked until
the required version is reported.
rejected and below-turnout ballots don't, stale-activation ballot does not revert
onCycleEnd.Deployment notes
contractType 1 and 4). No re-initialization; storage layout is untouched.
validator-appdocker image needs a rebuild/version bump to ship the app change, andvalidators pick up the quickstart change on their next run.