feat: add extra getters - #22563
Merged
Merged
feat: add extra getters#22563
Conversation
LHerskind
force-pushed
the
lh/tmnt-520-make-it-stupid-simple-to-check-cross-chain-replay-for
branch
from
April 15, 2026 12:39
fb34548 to
5a02d69
Compare
LHerskind
force-pushed
the
lh/tmnt-517-add-extra-getters
branch
from
April 15, 2026 12:40
66d8749 to
0eb7829
Compare
LHerskind
force-pushed
the
lh/tmnt-520-make-it-stupid-simple-to-check-cross-chain-replay-for
branch
3 times, most recently
from
April 16, 2026 18:21
7003b54 to
7256238
Compare
LHerskind
force-pushed
the
lh/tmnt-520-make-it-stupid-simple-to-check-cross-chain-replay-for
branch
2 times, most recently
from
April 28, 2026 11:59
41f782d to
63e0b5c
Compare
Base automatically changed from
lh/tmnt-520-make-it-stupid-simple-to-check-cross-chain-replay-for
to
merge-train/spartan
April 28, 2026 12:32
LHerskind
force-pushed
the
lh/tmnt-517-add-extra-getters
branch
from
April 28, 2026 12:53
0eb7829 to
0697a9c
Compare
LHerskind
marked this pull request as ready for review
April 29, 2026 11:24
ElusAegis
pushed a commit
to ElusAegis/aztec-packages
that referenced
this pull request
Apr 30, 2026
BEGIN_COMMIT_OVERRIDE chore: pass through p2p tx pool size (AztecProtocol#22804) feat: track sequencer state time (AztecProtocol#22800) feat(rpc)!: updated rpc api for blocks and checkpoints (AztecProtocol#22781) feat(pipelining): complete attestations by build-slot end (AztecProtocol#22735) feat(archiver): handle multiple proposed checkpoints (AztecProtocol#22784) feat: scrape bench-10tps (AztecProtocol#22803) feat!: make proposals EIP-712 (AztecProtocol#22531) chore: remove default env (AztecProtocol#22837) chore: remove default env (AztecProtocol#22839) chore: grafana provisioning (AztecProtocol#22843) feat: add extra getters (AztecProtocol#22563) fix: use number config helper for NaN protection (AztecProtocol#22598) test(e2e): relax blocks per checkpoint in high tps e2e (AztecProtocol#22846) test(e2e): equivocation recovery under proposer pipelining (AztecProtocol#22831) feat: scrape metrics data (AztecProtocol#22840) END_COMMIT_OVERRIDE
This was referenced Aug 25, 2026
spalladino
added a commit
that referenced
this pull request
Sep 1, 2026
…ir getters (#25313) `RollupContract.getVkTreeRoot` and `getProtocolContractsHash` read raw storage at `keccak256("aztec.stf.storage") + 3` and `+ 4` instead of calling the contract. `IRollup` has exposed `getVkTreeRoot()` and `getProtocolContractsHash()` since #22563, so the slot arithmetic was never necessary. This switches both to the ABI getters. ### Why it matters The slot offsets hardcode the field order of `RollupStore.config`. Reordering or removing a field there does not break the read — it returns a wrong-but-well-formed `bytes32`, which surfaces downstream as a spurious VK mismatch in `checkRollupCompatibility` rather than as an error at the read site. That is not hypothetical: a change on the `next` line moves these values out of `RollupStore` entirely (they are constructor-only and have no setter, so they belong in immutables). A node still doing the raw read would see zeroes against such a rollup and sit in standby forever. Landing the getter read on the v5 line first means node binaries cut from it work against a rollup deployed from either version. ### Scope Two functions in `yarn-project/ethereum/src/contracts/rollup.ts`, plus two test descriptions that said "from storage". The remaining `stfStorageSlot` consumers use offsets `+0` (tips), `+1` (archives) and `+2` (tempCheckpointLogs) and are untouched. The existing tests in `rollup.test.ts` cover both getters against a real anvil deployment, so they exercise the new path unchanged.
spalladino
added a commit
that referenced
this pull request
Sep 4, 2026
…5314) This is the bottom of the Fast Inbox stack: it targets `project/fast-inbox` directly and is independently mergeable — nothing in it depends on the inbox work above it. ## Context Every field of `RollupConfig` — `vkTreeRoot`, `protocolContractsHash`, `version`, `feeAsset`, `feeAssetPortal`, `epochProofVerifier`, `inbox`, `outbox` — is written exactly once in the Rollup's constructor and has no setter anywhere in `src/`. They were nonetheless kept in storage, so every read paid a cold `SLOAD`. `propose` paid one, `submitEpochRootProof` paid six. ## Approach Move all eight into immutables and drop `config` from `RollupStore`. Libraries cannot read a contract's immutables, and the `*ExtLib` libraries here are `external` (delegatecalled), so they cannot either. The values are assembled into a memory `RollupConfig` by `RollupCore._getRollupConfig()` and threaded down as parameters: the full struct into the epoch-proof path, the `IInbox` into propose, and the fee asset into the reward claims. Propose needed its `IInbox` bundled with the existing `checkBlob` flag into a `ProposeConfig` struct — a seventh scalar parameter pushed `ProposeLib.propose` over the stack limit, and a memory struct costs one slot instead of two. `config` was the last member of `RollupStore`, so `tips`, `archives` and `tempCheckpointLogs` keep slots 0–2 and every raw-slot consumer of `keccak256("aztec.stf.storage")` is unaffected — all of them use offsets ≤ +2. The two that used `+3`/`+4` were `RollupContract.getVkTreeRoot` and `getProtocolContractsHash` in the TS client, which now call the contract getters that `IRollup` has exposed since #22563. The second commit is bytecode budget, not gas. Each immutable read inlines a 32-byte push, which grew `Rollup`'s runtime code to within 148 bytes of the EIP-170 limit. `Rollup.validateHeaderWithAttestations` was decoding seven parameters, building a `ValidateHeaderArgs` (which embeds a full `ProposedHeader`) in memory, resolving the mana min fee through two delegatecall hops, and re-encoding four arguments — all in the Rollup's own runtime code. Forwarding the parameters straight through and assembling the struct in `RollupOperationsExtLib` frees 629 bytes. The fee value is unchanged: `RewardExtLib.summedMinFee` and `.getManaMinFeeComponentsAt` are one-line forwarders to the `FeeLib` / `ProposeLib` functions the ExtLib now calls directly. ## Gas | Benchmark | Before | After | Δ | |---|---|---|---| | `propose` (no validators) | 199,366 | 197,433 | **−1,933** | | `submitEpochRootProof` (no validators) | 991,032 | 980,225 | **−10,807** | | `propose` (100 validators) | 327,774 | 325,847 | **−1,927** | | `submitEpochRootProof` (100 validators) | 1,572,081 | 1,561,291 | **−10,790** | | `aggregate3` (100 validators) | 376,665 | 374,738 | **−1,927** | The config getters lose their cold `SLOAD` outright — `getInbox` 2,543 → 878, `getVersion` 1,447 → 852, `getOutbox` 2,521 → 856. A handful of unrelated views move by 22–44 gas as the Rollup's selector dispatch shifts. Deployment also drops eight `SSTORE`s. `Rollup` runtime bytecode ends at 23,799 against the 24,576 limit — 777 bytes of margin, against 886 before this change. Note on the regenerated `gas_report.json`: call counts on a few entries drop by 36 because the three tests that fail only under `FORGE_GAS_REPORT` (`testExtraBlobs`, `testRevertInvalidCoinbase`, `testRevertInvalidTimestamp` — all failing identically on the base commit) abort at a slightly different point. Per-call gas for those entries is unchanged. ## Node compatibility Node binaries already in the field read `vkTreeRoot` and `protocolContractsHash` from raw slots `+3`/`+4`. Against a rollup deployed from this branch those slots are zero, so such a node's `waitForCompatibleRollup` reports a VK mismatch and sits in standby. #25313 lands the getter-based read on the v5 line so binaries cut from it work against a rollup deployed from either version; it does nothing for binaries already released, so this needs sequencing against any node rollout.
spalladino
added a commit
that referenced
this pull request
Sep 10, 2026
…5314) This is the bottom of the Fast Inbox stack: it targets `project/fast-inbox` directly and is independently mergeable — nothing in it depends on the inbox work above it. Every field of `RollupConfig` — `vkTreeRoot`, `protocolContractsHash`, `version`, `feeAsset`, `feeAssetPortal`, `epochProofVerifier`, `inbox`, `outbox` — is written exactly once in the Rollup's constructor and has no setter anywhere in `src/`. They were nonetheless kept in storage, so every read paid a cold `SLOAD`. `propose` paid one, `submitEpochRootProof` paid six. Move all eight into immutables and drop `config` from `RollupStore`. Libraries cannot read a contract's immutables, and the `*ExtLib` libraries here are `external` (delegatecalled), so they cannot either. The values are assembled into a memory `RollupConfig` by `RollupCore._getRollupConfig()` and threaded down as parameters: the full struct into the epoch-proof path, the `IInbox` into propose, and the fee asset into the reward claims. Propose needed its `IInbox` bundled with the existing `checkBlob` flag into a `ProposeConfig` struct — a seventh scalar parameter pushed `ProposeLib.propose` over the stack limit, and a memory struct costs one slot instead of two. `config` was the last member of `RollupStore`, so `tips`, `archives` and `tempCheckpointLogs` keep slots 0–2 and every raw-slot consumer of `keccak256("aztec.stf.storage")` is unaffected — all of them use offsets ≤ +2. The two that used `+3`/`+4` were `RollupContract.getVkTreeRoot` and `getProtocolContractsHash` in the TS client, which now call the contract getters that `IRollup` has exposed since #22563. The second commit is bytecode budget, not gas. Each immutable read inlines a 32-byte push, which grew `Rollup`'s runtime code to within 148 bytes of the EIP-170 limit. `Rollup.validateHeaderWithAttestations` was decoding seven parameters, building a `ValidateHeaderArgs` (which embeds a full `ProposedHeader`) in memory, resolving the mana min fee through two delegatecall hops, and re-encoding four arguments — all in the Rollup's own runtime code. Forwarding the parameters straight through and assembling the struct in `RollupOperationsExtLib` frees 629 bytes. The fee value is unchanged: `RewardExtLib.summedMinFee` and `.getManaMinFeeComponentsAt` are one-line forwarders to the `FeeLib` / `ProposeLib` functions the ExtLib now calls directly. | Benchmark | Before | After | Δ | |---|---|---|---| | `propose` (no validators) | 199,366 | 197,433 | **−1,933** | | `submitEpochRootProof` (no validators) | 991,032 | 980,225 | **−10,807** | | `propose` (100 validators) | 327,774 | 325,847 | **−1,927** | | `submitEpochRootProof` (100 validators) | 1,572,081 | 1,561,291 | **−10,790** | | `aggregate3` (100 validators) | 376,665 | 374,738 | **−1,927** | The config getters lose their cold `SLOAD` outright — `getInbox` 2,543 → 878, `getVersion` 1,447 → 852, `getOutbox` 2,521 → 856. A handful of unrelated views move by 22–44 gas as the Rollup's selector dispatch shifts. Deployment also drops eight `SSTORE`s. `Rollup` runtime bytecode ends at 23,799 against the 24,576 limit — 777 bytes of margin, against 886 before this change. Note on the regenerated `gas_report.json`: call counts on a few entries drop by 36 because the three tests that fail only under `FORGE_GAS_REPORT` (`testExtraBlobs`, `testRevertInvalidCoinbase`, `testRevertInvalidTimestamp` — all failing identically on the base commit) abort at a slightly different point. Per-call gas for those entries is unchanged. Node binaries already in the field read `vkTreeRoot` and `protocolContractsHash` from raw slots `+3`/`+4`. Against a rollup deployed from this branch those slots are zero, so such a node's `waitForCompatibleRollup` reports a VK mismatch and sits in standby. it work against a rollup deployed from either version; it does nothing for binaries already released, so this needs sequencing against any node rollout.
spalladino
added a commit
that referenced
this pull request
Sep 10, 2026
…5314) This is the bottom of the Fast Inbox stack: it targets `project/fast-inbox` directly and is independently mergeable — nothing in it depends on the inbox work above it. Every field of `RollupConfig` — `vkTreeRoot`, `protocolContractsHash`, `version`, `feeAsset`, `feeAssetPortal`, `epochProofVerifier`, `inbox`, `outbox` — is written exactly once in the Rollup's constructor and has no setter anywhere in `src/`. They were nonetheless kept in storage, so every read paid a cold `SLOAD`. `propose` paid one, `submitEpochRootProof` paid six. Move all eight into immutables and drop `config` from `RollupStore`. Libraries cannot read a contract's immutables, and the `*ExtLib` libraries here are `external` (delegatecalled), so they cannot either. The values are assembled into a memory `RollupConfig` by `RollupCore._getRollupConfig()` and threaded down as parameters: the full struct into the epoch-proof path, the `IInbox` into propose, and the fee asset into the reward claims. Propose needed its `IInbox` bundled with the existing `checkBlob` flag into a `ProposeConfig` struct — a seventh scalar parameter pushed `ProposeLib.propose` over the stack limit, and a memory struct costs one slot instead of two. `config` was the last member of `RollupStore`, so `tips`, `archives` and `tempCheckpointLogs` keep slots 0–2 and every raw-slot consumer of `keccak256("aztec.stf.storage")` is unaffected — all of them use offsets ≤ +2. The two that used `+3`/`+4` were `RollupContract.getVkTreeRoot` and `getProtocolContractsHash` in the TS client, which now call the contract getters that `IRollup` has exposed since #22563. The second commit is bytecode budget, not gas. Each immutable read inlines a 32-byte push, which grew `Rollup`'s runtime code to within 148 bytes of the EIP-170 limit. `Rollup.validateHeaderWithAttestations` was decoding seven parameters, building a `ValidateHeaderArgs` (which embeds a full `ProposedHeader`) in memory, resolving the mana min fee through two delegatecall hops, and re-encoding four arguments — all in the Rollup's own runtime code. Forwarding the parameters straight through and assembling the struct in `RollupOperationsExtLib` frees 629 bytes. The fee value is unchanged: `RewardExtLib.summedMinFee` and `.getManaMinFeeComponentsAt` are one-line forwarders to the `FeeLib` / `ProposeLib` functions the ExtLib now calls directly. | Benchmark | Before | After | Δ | |---|---|---|---| | `propose` (no validators) | 199,366 | 197,433 | **−1,933** | | `submitEpochRootProof` (no validators) | 991,032 | 980,225 | **−10,807** | | `propose` (100 validators) | 327,774 | 325,847 | **−1,927** | | `submitEpochRootProof` (100 validators) | 1,572,081 | 1,561,291 | **−10,790** | | `aggregate3` (100 validators) | 376,665 | 374,738 | **−1,927** | The config getters lose their cold `SLOAD` outright — `getInbox` 2,543 → 878, `getVersion` 1,447 → 852, `getOutbox` 2,521 → 856. A handful of unrelated views move by 22–44 gas as the Rollup's selector dispatch shifts. Deployment also drops eight `SSTORE`s. `Rollup` runtime bytecode ends at 23,799 against the 24,576 limit — 777 bytes of margin, against 886 before this change. Note on the regenerated `gas_report.json`: call counts on a few entries drop by 36 because the three tests that fail only under `FORGE_GAS_REPORT` (`testExtraBlobs`, `testRevertInvalidCoinbase`, `testRevertInvalidTimestamp` — all failing identically on the base commit) abort at a slightly different point. Per-call gas for those entries is unchanged. Node binaries already in the field read `vkTreeRoot` and `protocolContractsHash` from raw slots `+3`/`+4`. Against a rollup deployed from this branch those slots are zero, so such a node's `waitForCompatibleRollup` reports a VK mismatch and sits in standby. it work against a rollup deployed from either version; it does nothing for binaries already released, so this needs sequencing against any node rollout.
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.
Adds external getters for the last three
RollupConfigfields that were previously unreachable from outside the contract:getVkTreeRoot()getProtocolContractsHash()getEpochProofVerifier()These were omitted originally because the rollup was tight on bytecode. Recent size reductions (TMNT-509, TMNT-513, TMNT-514) freed enough room to add them directly in
Rollup.solwithout needing ExtLib delegation.