feat: network-wide consensus config with validation and override protection (A-1168)#23977
Open
spalladino wants to merge 7 commits into
Conversation
…cement - Cross-check all preset consensus fields (not just slot duration) at node startup, covering nodes that bypass the cli env enrichment such as the standalone aztec-node binary and programmatic embedders. - Report instead of crash when the achievability probe derives fewer than one block, and reject non-finite config values instead of silently passing. - Validate preset multipliers against the network minimums rather than >= 1. - Canonicalize numerically-equal operator env values so parseInt-based config parsers cannot diverge from the Number-based equality check (e.g. 6e3). - Record NETWORK from the --network flag so the startup cross-check applies to cli users, and tolerate unknown NETWORK values in embedded contexts. - Parse SEQ_PER_BLOCK_ALLOCATION_MULTIPLIER as a float; parseInt truncated 1.5 to 1, which the new minimum-multiplier guard would have turned into a fatal startup error. - Skip the achievability warning for the intentionally-high default cap.
…ults Replace the in-code per-network consensus presets with values sourced from the generated network config (cli/src/config/generated/networks.ts, generated from spartan/environments/network-defaults.yml). The stdlib module now exposes only the required-env-var list, types, a config extractor, a self-consistency validate function, and an override-check function. Override enforcement moves to cli enrichEnvironmentWithChainName, gated by a compile-time check that every generated network config carries every consensus-critical var. The node startup check is reduced to verifying the rollup contract reports the same slot and epoch durations the node is configured with. ProposerTimetable now warns (and logs) only when local budgets compute more blocks per checkpoint than the network value allows.
100fb3e to
8e6bb08
Compare
- Move MIN_PER_BLOCK_*_ALLOCATION_MULTIPLIER constants to @aztec/constants. - Compose NetworkConsensusConfig by picking fields from L1ContractsConfig and SequencerConfig, and derive getConsensusConfigFromNetworkEnv env names and parsing from the canonical config mappings. - Make checkConsensusEnvOverrides pure: it returns the canonical env writes instead of mutating env; the cli enrichment layer applies them. - Add a compile-time ts-expect-error gate proving ConsensusComplete rejects configs missing a consensus-critical var. - Drop the redundant checkpointProposalSyncGraceSeconds defaulting in the node createAndSync (every consumer has its own fallback). - Switch the p2p gossip layer from ProposerTimetable to ConsensusTimetable and feed gossipsub scoring the network maxBlocksPerCheckpoint directly, dropping the now-unused proposer-budget config fields from p2p.
…ng from generated defaults The network-consensus-config enforcement throws at startup when a node, the deploy-rollup-contracts job, or any pod running the aztec entrypoint with a known NETWORK sets a consensus-critical env var that differs from the generated network defaults. devnet (36s slots, committee size 1) and testnet (slashing round size 2 epochs) intentionally diverge, so they now set ALLOW_OVERRIDING_NETWORK_CONFIG=true. Plumb that flag from the env files through deploy_network.sh into both the deploy-rollup-contracts job env and the deploy-aztec-infra helm releases (via a new global rendered by the shared aztec-node pod template, reaching validators, rpc/full nodes, prover, fisherman, bootnode and bots). Also pass AZTEC_SLOT_DURATION/AZTEC_EPOCH_DURATION into node pods so devnet nodes carry the real deployed 36s slot value and pass the rollup cross-check instead of inheriting the generated 72s default.
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
Identifies and enforces the configuration values that must be identical across all nodes of a network (A-1168), sourcing per-network values from the generated network config. Prevents operators from overriding them unless a new
ALLOW_OVERRIDING_NETWORK_CONFIGflag is set.Also:
Network-wide consensus values
stdlib/src/config/network-consensus-config.tsdefinesNETWORK_CONSENSUS_ENV_VARS, the env vars required to be the same for every node of a network, in three categories:ETHEREUM_SLOT_DURATION,AZTEC_SLOT_DURATION,AZTEC_EPOCH_DURATION,SEQ_BLOCK_DURATION_MS,MAX_BLOCKS_PER_CHECKPOINT,CHECKPOINT_PROPOSAL_SYNC_GRACE_SECONDS.SLASH_*): validators must agree on these to reach slashing quorum.Per-network values live in
spartan/environments/network-defaults.yml(the source ofcli/src/config/generated/networks.ts). This PR adds the two missing ones —MAX_BLOCKS_PER_CHECKPOINT: 10andCHECKPOINT_PROPOSAL_SYNC_GRACE_SECONDS: 12— to the shared prodlike section, and makes devnet'sAZTEC_SLASHING_QUORUM: 17/AZTEC_GOVERNANCE_PROPOSER_QUORUM: 151explicit (values match the Solidityvm.envOrdefaults, so deployment behavior is unchanged).maxBlocksPerCheckpointis an explicit network value rather than derived per node, so nodes with different operational budgets cannot diverge on checkpoint geometry; mainnet/testnet/devnet geometry (72s slots, 12s L1 slots, 6s blocks) derives exactly 10.NetworkConsensusConfigis composed byPicking fields fromL1ContractsConfigandSequencerConfig, andgetConsensusConfigFromNetworkEnvderives env names and parsing from the canonical config mappings, so each field is parsed exactly as the node's config layer would parse it.Enforcement layers
chain_l2_config.tsasserts (viasatisfies) that every generated network config defines every consensus-critical var; a@ts-expect-errorcompile gate in the test file proves the assertion actually rejects configs missing a var.cli/src/config/chain_l2_config.test.tsvalidates each generated network config withvalidateNetworkConsensusConfig, which requiresMAX_BLOCKS_PER_CHECKPOINTto be exactly what aProposerTimetableat the production default budgets derives, plus basic geometry soundness (slot multiples, sub-slot fits in slot, etc.).enrichEnvironmentWithChainNamecalls the purecheckConsensusEnvOverridesbefore enriching: a consensus var already set in the env to a value diverging from the network config makes startup throw, unlessALLOW_OVERRIDING_NETWORK_CONFIG=1is set (then it warns and keeps the operator value). The check returns canonical rewrites for numerically-equal-but-noncanonical values (e.g.6e3, whichparseInt-based config parsing would read as 6), which the cli enrichment layer applies to the env.AztecNodeServiceverifies the rollup contract reports the sameaztecSlotDuration/aztecEpochDurationthe node is configured with, and throws on mismatch. These are the only L1-timing fields the node config carries that the rollup exposes; the other rollup params (committee size, lags, proof submission epochs, mana limit) are read from L1 directly rather than from config.Where maxBlocksPerCheckpoint applies
ProposerTimetablecomputes the locally achievable count from operational budgets and clamps it down to the network value when the network value is lower; sub-slot selection never starts a block past the effective count. When local budgets compute more than the network allows, the timetable warns through an injected logger.proposal_validator.tsrejects (and penalizes peers for) block proposals withindexWithinCheckpoint >= min(maxBlocksPerCheckpoint, MAX_ATTESTABLE_BLOCKS_PER_CHECKPOINT).proposal_handler.tsrefuses to attest to checkpoint proposals with more blocks than the configured value;checkpoint_builder.tscaps the blocks it assembles.ConsensusTimetableand no longer depends on proposer operational budgets (which were also dropped fromP2PConfig).Also in this PR
MIN_PER_BLOCK_ALLOCATION_MULTIPLIER = 1.2/MIN_PER_BLOCK_DA_ALLOCATION_MULTIPLIER = 1.5live in@aztec/constants; the sequencer rejects multipliers below the minimum, andSEQ_PER_BLOCK_ALLOCATION_MULTIPLIERswitched fromnumberConfigHelper(parseInt truncated1.5to1) tofloatConfigHelper(mirrors fix(gas)!: client fallback limits track network per-block budget (A-1154) #23947; deliberate copy, conflicts to be resolved when either lands).checkpointProposalSyncGraceSecondsdefaulting in nodecreateAndSync; every consumer (archiver factory, sequencer, p2p timetable) has its own fallback.Spartan deployments
Existing spartan networks that intentionally diverge from the generated defaults keep deploying:
devnet.env(36s slots, committee size 1) andtestnet.env(slashing round size 2 epochs) now setALLOW_OVERRIDING_NETWORK_CONFIG=true, plumbed throughdeploy_network.shinto both thedeploy-rollup-contractsjob env and every aztec-image helm release (newglobal.allowOverridingNetworkConfigrendered by the shared aztec-node pod template).AZTEC_SLOT_DURATION/AZTEC_EPOCH_DURATIONare also passed through to node pods so devnet nodes carry the real deployed 36s value and pass the rollup cross-check instead of inheriting the generated 72s default. mainnet/staging/next-net set no conflicting consensus vars and are untouched, so enforcement stays loud by default.Known limitations
MIN_PER_BLOCK_DA_ALLOCATION_MULTIPLIERdocuments the network minimum only; its operator knob and runtime enforcement land with fix(gas)!: client fallback limits track network per-block budget (A-1154) #23947.network_config.jsonenrichment runs beforeenrichEnvironmentWithChainName, so a consensus value pushed via the networks repo that diverges from the binary's generated defaults will also be refused at startup (the live JSON sets no consensus values today).ethereumSlotDurationcannot be cross-checked against the rollup contract (no getter); it is enforced via env only on named networks.