feat: reject out-of-range checkpoint header fields at propose (A-1254) - #24199
Merged
just-mitch merged 1 commit intoJun 19, 2026
Conversation
spalladino
force-pushed
the
spl/a-1254-l1-field-range-checks
branch
from
June 19, 2026 15:53
d2e8d4f to
b30ce6e
Compare
A malicious proposer could store header or archive field values >= the BN254 scalar field modulus on L1. Off-chain archivers decode those storage slots into Fr elements, so an out-of-range value bricks honest archivers' L1 sync. Reject such values at propose time: - validateHeader: blockHeadersHash, outHash, feeRecipient, accumulatedFees - propose: the new checkpoint archive root Other header fields are already safe (equality-checked against field-reduced on-chain values, or type-bounded), so they are left unchecked. This is the L1 half of A-1254; the archiver-side defense-in-depth is a separate follow-up PR.
spalladino
force-pushed
the
spl/a-1254-l1-field-range-checks
branch
from
June 19, 2026 15:58
b30ce6e to
310c8ac
Compare
just-mitch
reviewed
Jun 19, 2026
| * (`type(uint256).max`), and that an otherwise-valid header with every checked field at `P - 1` still goes through. | ||
| */ | ||
| contract RollupFieldRangeTest is RollupBase { | ||
| uint256 internal constant FIELD_MAX = Constants.P - 1; |
Collaborator
There was a problem hiding this comment.
Not worth fixing, just funny: I sanity checked Constants.P, and turns out there is a Constants.MAX_FIELD_VALUE.
just-mitch
approved these changes
Jun 19, 2026
just-mitch
merged commit Jun 19, 2026
ac27fa0
into
mitch/gk-722-protect-fees-against-unsound-verifier-v5
7 of 9 checks passed
spalladino
added a commit
that referenced
this pull request
Jun 19, 2026
…ue ids Rebuild the out-of-range checkpoint-header e2e to exercise full recovery: a lone proposer lands an under-attested checkpoint, its stored archive root is corrupted to a value above the BN254 modulus via setStorageAt, and the honest validators plus an archiver-only observer keep syncing through the hardened status()/archiveAt() reads, invalidate the under-attested checkpoint, and build past it. The corruption is injected post-propose because the L1 propose path now reverts on out-of-range fields (#24199). Also strip Linear issue-id mentions from the decode-robustness comments across archiver, ethereum, stdlib, and sequencer-client, keeping the technical rationale and the #24199 PR cross-reference.
spalladino
added a commit
that referenced
this pull request
Jun 19, 2026
…-of-range root RollupContract.getCheckpoint eagerly converted the on-chain archive root to Fr, which throws when the stored value is outside the BN254 field. A malicious proposer can land such a value, bricking any honest node that reads the checkpoint on a sync/startup path (e.g. the tx-pool fee provider booting against the pending tip). Carry the archive as Buffer32 on the read path and compare archive roots as bytes in the prover-node publisher so a mismatching out-of-range value reports a mismatch instead of throwing. Refs #24199
rangozd
pushed a commit
to rangozd/aztec-packages
that referenced
this pull request
Aug 5, 2026
…-range-next feat: reject out-of-range checkpoint header fields at propose (port of AztecProtocol#24199 to next)
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
Part of A-1254.
A malicious proposer can currently store checkpoint header or archive field values that are
>=the BN254 scalar field modulus (Constants.P) on L1. Off-chain archivers decode those storage slots intoFrelements, so an out-of-range value bricks honest archivers' L1 sync. This is the L1 half of the fix: reject such values at write time so they can never reach L1 storage.Changes
A new helper
FieldLib.requireValidFieldElement(bytes32)wraps thevalue < Constants.Pcheck and reverts withErrors.Rollup__FieldElementOutOfRange(bytes32 value). It is used to range-check the attacker-controlled,Fr-decoded values that are not otherwise constrained:ProposeLib.validateHeader— header fieldsblockHeadersHash,outHash,feeRecipient,accumulatedFees.ProposeLib.propose— the new checkpoint archive root (_args.archive), which is not part of the header, checked before the digest/header validation/storage.STFLib.initialize— the genesis archive root, which is written toarchives[0]at deployment and propagates into the first header'slastArchiveRoot.Why the other fields are already safe
lastArchiveRoot,inHash,blobsHash— equality-constrained to on-chain values that are already field-reduced (tipArchive,inbox.consume(),blobsHashesCommitment).totalManaUsed— bounded by<= FeeLib.getManaLimit(), and the mana limit is capped attype(uint32).max, far belowP.gasFees(uint128),coinbase(address),slotNumber/timestamp— type-bounded or equality-checked against slot-derived values.Tests
New
test/RollupFieldRange.t.sol:Rollup__FieldElementOutOfRangewhen set toConstants.P(boundary) and totype(uint256).max.Constants.P - 1proposes successfully, confirming the boundary is exclusive and legitimate field elements are not rejected.Verified red/green for both the propose checks and the genesis check; the broader
RollupTest, escape-hatch, and fees suites remain green.Follow-up
The archiver-side defense-in-depth (decoding out-of-range values without bricking sync) is a separate follow-up PR that will close A-1254.