chore(fast-inbox): circuits cleanup and checkpoint header format (A-1387) - #24792
Closed
spalladino wants to merge 8 commits into
Closed
chore(fast-inbox): circuits cleanup and checkpoint header format (A-1387)#24792spalladino wants to merge 8 commits into
spalladino wants to merge 8 commits into
Conversation
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 19, 2026 01:25
86a8360 to
a7eb238
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
from
July 19, 2026 01:25
d06eb0f to
7e1dc3d
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 19, 2026 14:05
a7eb238 to
721cb08
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
from
July 19, 2026 14:05
7e1dc3d to
0e1e0ed
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 19, 2026 15:10
721cb08 to
f09a847
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
2 times, most recently
from
July 19, 2026 15:36
2277ca8 to
43ac45a
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 19, 2026 15:36
f09a847 to
8fa5988
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
3 times, most recently
from
July 19, 2026 20:30
8287158 to
4c4c1a8
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 19, 2026 20:30
225d2e7 to
3eb6939
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
2 times, most recently
from
July 19, 2026 20:51
c51c85b to
de57be7
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 19, 2026 20:51
70acb89 to
7a02f46
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
from
July 20, 2026 13:32
de57be7 to
ce83790
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 20, 2026 13:32
7a02f46 to
180983d
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
from
July 20, 2026 14:07
ce83790 to
f853ebe
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
2 times, most recently
from
July 20, 2026 15:30
7d55b36 to
df4a7eb
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
2 times, most recently
from
July 20, 2026 17:28
9d37080 to
c50ce18
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 20, 2026 17:28
df4a7eb to
480a601
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
from
July 20, 2026 21:21
c50ce18 to
6b53788
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 20, 2026 21:21
480a601 to
670ebbf
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
from
July 21, 2026 02:58
6b53788 to
ff21647
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 21, 2026 03:39
11b1638 to
cf29763
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
2 times, most recently
from
July 21, 2026 04:43
4a8dc8a to
9e63607
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 21, 2026 04:43
cf29763 to
7b32375
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
from
July 21, 2026 12:06
9e63607 to
d743db2
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 21, 2026 12:06
7b32375 to
2b91492
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
from
July 21, 2026 15:02
d743db2 to
141286e
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 21, 2026 15:02
2b91492 to
5295095
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
from
July 21, 2026 22:32
141286e to
92c4a70
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 21, 2026 22:32
5295095 to
e853cd3
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
from
July 27, 2026 20:53
92c4a70 to
f4cc2db
Compare
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 27, 2026 20:53
e853cd3 to
b6d1007
Compare
…uits (A-1387) Remove the dead unconstrained in_hash pass-through from InboxParity and ParityPublicInputs, and remove in_hash from the CheckpointHeader consensus format (struct, to_be_bytes, serialization length, Empty, hash fixtures). The Inbox rolling hash is now the checkpoint's only inbox commitment. Retire NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP in favor of MAX_L1_TO_L2_MSGS_PER_CHECKPOINT, and drop the now-unused L1_TO_L2_MSG_SUBTREE_ROOT_SIBLING_PATH_LENGTH and the NUM_MSGS_PER_BASE_PARITY / NUM_BASE_PARITY_PER_ROOT_PARITY frontier fan-in constants. Regenerated constants.gen.ts and ConstantsGen.sol via remake-constants.
…te FrontierLib (A-1387) Remove inHash from the ProposedHeader struct and its hash preimage in ProposedHeaderLib, keeping the packing byte-for-byte in lockstep with the noir and stdlib checkpoint headers. Update the decoder base struct and the propose test helpers, and regenerate the checkpoint fixtures (drop header.inHash, recompute headerHash). Delete FrontierLib and its only remaining users: the parity cross-check test (Parity.t.sol, which verified the deleted parity circuits) and the frontier merkle test/harness. The frontier tree is gone from both circuits and L1.
…h stdlib and node (A-1387) Mirror the consensus-format change in the stdlib CheckpointHeader (struct, serialization, viem, hash fixtures) and the circuit-ABI stdlib types (ParityPublicInputs, InboxParityPrivateInputs) and their noir conversion mappings. Sweep the header-inHash populate/read sites: the lightweight checkpoint builder, the checkpoint-proving orchestrator, the sequencer fixture writer, and the checkpoint proposal (its block-level inHash now sources zero rather than the removed header field). Regenerate the checkpoint p2p wire fixture for the shorter header. Replace NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP with MAX_L1_TO_L2_MSGS_PER_CHECKPOINT across the TS consumers. The block-level inHash struct fields (BlockProposal, L2Block) and stdlib/src/messaging/in_hash.ts remain for the node cleanup issue.
…oval (A-1387) The propose-failure test asserted the deleted Rollup__InvalidInHash selector (0xcd6f4233). With the legacy inHash L1 check gone, a checkpoint carrying messages that do not match the Inbox now reverts at validateInboxConsumption with Rollup__InvalidInboxRollingHash (0xed1f7bb5).
… checkpoint header (A-1387) Dropping inHash from the checkpoint header changes the checkpoint hash preimage, so the checkpoint ids the tips store persists change value. The stored format is unchanged (read-defaultable), so only the snapshot is regenerated; no PXE_DATA_SCHEMA_VERSION bump.
…reaming bucket selector (A-1387) The A-1387 rewrite that removed inHash left this test's inbox handling half-adapted: it hardcoded previousInboxRollingHash to Fr.ZERO and proposed with bucketHint 0n while consuming real L1->L2 messages, so message-consuming checkpoints reverted on L1 with Rollup__InvalidInboxRollingHash / UnconsumedInboxMessages. INBOX_LAG_SECONDS is an L1-time censorship cutoff (not whole checkpoints), so no checkpoint-depth shift register can reproduce the aged bucket set. Mirror the real Inbox buckets into the test's MockL1ToL2MessageSource, then reuse the production selectInboxBucketForBlock (which mirrors ProposeLib.validateInboxConsumption) to pick exactly the buckets each checkpoint must consume, deriving the consumed bundle, the propose bucket hint, and the header rolling hash from that one selection so header, world state, and L1 agree. Matches the A-1388 rewrite of this file so the segment rebase dissolves to zero.
…ationale (A-1387)
spalladino
force-pushed
the
spl/a-1386-l1-cleanup
branch
from
July 28, 2026 12:37
b6d1007 to
7239dcb
Compare
spalladino
force-pushed
the
spl/a-1387-circuits-cleanup
branch
from
July 28, 2026 12:38
f4cc2db to
666df4c
Compare
Contributor
Author
|
Superseded by #25038. The Fast Inbox stack has been regrouped from 20 per-issue PRs (plus 2 umbrellas) down to 3 area PRs plus an umbrella, and rebased onto New structure: #25036 (circuits + L1) → #25037 (node + flip) → #25038 (cleanup), with #25039 as the full-stack umbrella. The original branch for this PR is left on the remote as a recovery point. Closing here to cut the rebase and review overhead of maintaining 22 PRs; the work is not abandoned. |
spalladino
added a commit
that referenced
this pull request
Jul 28, 2026
…387) FI-17 of the Fast Inbox (AZIP-22) stack. Stacked on #24791 (A-1386); it removes the legacy `inHash` from the checkpoint header now that the consensus flip (#24789, A-1384) has switched validation to the streaming rolling hash. After this PR, `inboxRollingHash` is the checkpoint's only inbox commitment. ## Consensus-format change - The checkpoint header loses its `inHash` field across all three preimage layers in lockstep: noir `CheckpointHeader` (`checkpoint_header.nr`), TS `CheckpointHeader` (`stdlib/src/rollup/checkpoint_header.ts`), and Solidity `ProposedHeaderLib` (struct + hash packing). The field ordering is otherwise unchanged; the header shrinks by one field (32 bytes: `CHECKPOINT_HEADER_SIZE_IN_BYTES` 380 to 348, `CHECKPOINT_HEADER_LENGTH` 14 to 13). - The header-hash fixtures were regenerated from `checkpoint_header.test.ts` (the established workflow) and pasted into the noir tests; the p2p golden-byte fixture (`wire_compat_fixtures.ts`) was refreshed for the checkpoint-proposal serialization, which shrinks by exactly the one removed field. The block-proposal wire fixture is unchanged (block-level `inHash` is out of scope, see A-1388). ## Circuits and constants - Strips the dead unconstrained `in_hash` pass-through from the sized `InboxParity<S>` circuit and `ParityPublicInputs` (noir + TS + the hand-written `noir-protocol-circuits-types` conversion wrappers). The circuit is kept (sized-parity, per FI-06's topology decision), so no VK-tree indices move. - Retires `NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP` (replaced everywhere by `MAX_L1_TO_L2_MSGS_PER_CHECKPOINT`, same value 1024) and the now-dead `NUM_MSGS_PER_BASE_PARITY`, `NUM_BASE_PARITY_PER_ROOT_PARITY`, and `L1_TO_L2_MSG_SUBTREE_ROOT_SIBLING_PATH_LENGTH`. Generated constants (`constants.gen.ts`, `ConstantsGen.sol`) were regenerated via `remake-constants`. - Deletes `FrontierLib.sol` and its tests (`Parity.t.sol`, the `Frontier` harness and merkle test) now that their last users are gone. ## Verification - Noir: `types::checkpoint_header` (5/5), `rollup_lib::parity` and `checkpoint_root::parity_tests` (15/15), and the checkpoint-root header-assembly path pass locally. The full `checkpoint_root` suite (68 tests) is too slow to run in full locally and rides CI. - Solidity: `forge test` green across `Rollup`, `RollupFieldRange`, `Inbox`, `InboxBuckets`, `RollupGetters` (76/76), covering header hashing and the regenerated checkpoint fixtures. - Jest: `checkpoint_header`, the p2p wire-compat suites, and the parity/messaging suites pass (43 tests), confirming the fixture regeneration is byte-consistent. - VK/artifact/Prover.toml regeneration and the generated Noir ABI types ride CI (local `yarn build` in `noir-protocol-circuits-types` / `simulator` / `prover-client` is expected to fail on stale circuit artifacts until then); e2e and the broken-zone typecheck are the CI-of-record for those. ## Stack Part of the Fast Inbox stack #24784 through #24791 (umbrella #24774): A-1379 (#24784), A-1380 (#24785), A-1381 (#24786), A-1382 (#24787), A-1383 (#24788), A-1384 flip (#24789), A-1385 (#24790), A-1386 (#24791, base of this PR). Resolves A-1387. ## l1 publisher inbox consumption via the streaming selector (CI fix, pass-8) The A-1387 inHash-removal rewrite left `l1_publisher.integration.test.ts` hardcoding `previousInboxRollingHash = Fr.ZERO` and `bucketHint = 0n` while consuming real L1→L2 messages, so message-consuming checkpoints reverted on L1 with `Rollup__InvalidInboxRollingHash` / `UnconsumedInboxMessages` (masked every prior CI round behind earlier failures). `INBOX_LAG_SECONDS` is an L1-time censorship cutoff, not whole checkpoints, so no checkpoint-depth shift register reproduces the aged bucket set. The test now mirrors the real Inbox buckets into its `MockL1ToL2MessageSource` and reuses the production `selectInboxBucketForBlock` (which mirrors `ProposeLib.validateInboxConsumption`) to pick exactly the buckets each checkpoint must consume, deriving the consumed bundle, the propose bucket hint, and the header rolling hash from that one selection. Box: 13/13, verified at a-1387 and a-1388. Replaces #24792.
spalladino
added a commit
that referenced
this pull request
Jul 28, 2026
Node cleanup for the Fast Inbox (AZIP-22) project — removes the legacy L1-to-L2 message paths the flip (#24789) left dead. Sits on the Fast Inbox stack (#24784..#24792); base is `spl/a-1387-circuits-cleanup`. ## What's removed - **stdlib / p2p**: `computeInHashFromL1ToL2Messages` and the whole `in_hash.ts`; the `inHash` field on `BlockProposal` (constructor, signed payload, wire, and the `createBlockProposal` validator-interface argument); the `CheckpointProposal.getBlockProposal` `inHash` pass-through; the padded per-checkpoint `InboxLeaf` helpers (`smallestIndexForCheckpoint` / `indexRangeForCheckpoint` / `checkpointNumberFromIndex`); the legacy `getL1ToL2Messages(checkpointNumber)` member from the `L1ToL2MessageSource` and archiver RPC interfaces. - **archiver**: the legacy per-checkpoint `getL1ToL2Messages` flow, the padded per-checkpoint index invariants, the `inboxTreeInProgress` readiness gate + `L1ToL2MessagesNotReadyError`, and the 128-bit keccak rolling hash. `InboxMessage` now carries only the compact global index and the full-width consensus rolling hash (the vacuous derived `checkpointNumber` and the 128-bit `rollingHash` are gone). Reorg detection compares the local consensus rolling hash and total against the Inbox's current rolling-hash bucket (new `getBucket` / `getCurrentBucketSeq` / `getCurrentBucket` wrappers) instead of the 128-bit `getState`. - **sequencer / validator**: the dead `inHash = Fr.ZERO` threading through the checkpoint proposal job and the validator/validation-service create-proposal path, plus the dead `in_hash_mismatch` validation-failure reason. - **world-state**: the no-op first-in-checkpoint padding alias and the obsolete non-first-block-empty-bundle transitional test (the production assertion was already removed at the flip). - **node**: the public-calls simulator's dead next-checkpoint message fetch and its now-unused `l1ToL2MessageSource` dependency. - **config / env**: `AZTEC_INBOX_LAG` / `inboxLag` from ethereum config, foundation env vars, the network-consensus-config list, the l1-contracts + spartan network defaults, and the e2e option plumbing. - **docs**: `THREAT_MODEL.md` and the archiver README rewritten from the `inHash == inbox.consume(...)` model to the consensus rolling-hash / bucket model. ## Format / store / wire notes - **Store version bump**: `ARCHIVER_DB_VERSION` 8 → 9 because `InboxMessage` serialization dropped `rollingHash` + `checkpointNumber` and the `inboxTreeInProgress` singleton is gone. No migration — nodes resync (fresh rollup instance per release line, same no-migration policy as the rest of the stack). - **p2p wire format**: dropping the (zeroed-since-flip) `inHash` shrinks the block-proposal bytes. Done as a plain removal at a release boundary (fresh networks), matching the A-1381 optional-tail precedent; the golden `wire_compat_fixtures.ts` buffers were regenerated. The checkpoint-proposal fixture is unaffected (it never carried `inHash`). - **L1 follow-through: done (leftover sweep, below).** The on-chain Inbox 128-bit `messagesRollingHash` accumulation, `InboxState.rollingHash`, and the `MessageSent.rollingHash` event arg are now removed in this PR — this is the earliest branch where it is safe, since the TS reads disappear here. `getState()` / `getTotalMessagesInserted()` are kept: `chain_monitor` and fast node sync still read the message count. ## Testing Locally green (unit suites that run without `@aztec/bb-avm-sim`): archiver (561), stdlib p2p + interfaces (76), world-state synchronizer + native (74), validator-client unit (38), ethereum config (6). Suites that import `@aztec/bb-avm-sim` (p2p libp2p, sequencer-client, node simulator, validator integration) and full typecheck of the packages downstream of the pinned-VK blocker are CI-validated. No e2e / VK regen locally. ## Review follow-up (phase-2 final review) Four commits were appended by the final review pass: - The env sweep removed `AZTEC_INBOX_LAG` from `scripts/network-defaults.json` while both L1 deploy-script test setUps still `readUint` the key, reverting before any test ran; the reads are gone. - The p2p attestation store version is bumped 2 -> 3: it persists proposal/attestation buffers whose formats changed in this stack (checkpoint header lost `inHash`; block-proposal wire dropped it), and stored checkpoint attestations decode without a tolerant fallback. - `l1_publisher.integration.test.ts` is reworked for streaming consumption: each checkpoint consumes every message sent while it was built, threading the previous checkpoint's rolling hash and reading the propose `bucketHint` from the Inbox's current bucket (the legacy inboxLag shift register is gone). - Remaining `inboxLag`/`inHash` references are swept from the spartan environment profiles, the governance-upgrade tutorial, the validator/sequencer READMEs, and stale e2e comments. ## l1 publisher test dissolved into A-1387 (pass-8) This branch's rewrite of `l1_publisher.integration.test.ts` is superseded by the corrected streaming-selector version landed at A-1387 (#24792): the branch's own message-reconstruction rework commit is dropped and the file is byte-identical to A-1387's here (segment diff for this file is zero). The A-1384 world-state mock bucket registration coexists with this branch's legacy-message-path deletion (the buckets survive the cleanup). First real box verification of this suite at A-1388: l1_publisher 13/13; world-state integration 12/12 at top. ## Leftover sweep (post-review) - Removed the legacy 128-bit keccak inbox rolling hash from L1: `InboxState.rollingHash`, the `MessageSent` `bytes16 rollingHash` event arg, and its keccak accumulation in `Inbox.sol`, updating the four Solidity test suites that asserted it (`Inbox.t`, `InboxBuckets.t`, `TokenPortal.t`, `depositToAztecPublic.t`) and the three live docs-example inbox ABIs that embedded the old event shape. The node's message sync and L1-reorg detection already run entirely on the full-width consensus rolling hash from the buckets. - Deleted the dead `InboxLeaf` class from stdlib (this branch had already removed its per-checkpoint index helpers) and fixed a stale `InboxLeaf` mention in the archiver retrieval JSDoc. - Clarified the checkpoint-builder comments: the up-front whole-checkpoint message insertion (`insertMessagesPerBlock = false`) is only exercised by tests; production always streams messages per block. Replaces #24793.
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.
FI-17 of the Fast Inbox (AZIP-22) stack. Stacked on #24791 (A-1386); it removes the legacy
inHashfrom the checkpoint header now that the consensus flip (#24789, A-1384) has switched validation to the streaming rolling hash. After this PR,inboxRollingHashis the checkpoint's only inbox commitment.Consensus-format change
inHashfield across all three preimage layers in lockstep: noirCheckpointHeader(checkpoint_header.nr), TSCheckpointHeader(stdlib/src/rollup/checkpoint_header.ts), and SolidityProposedHeaderLib(struct + hash packing). The field ordering is otherwise unchanged; the header shrinks by one field (32 bytes:CHECKPOINT_HEADER_SIZE_IN_BYTES380 to 348,CHECKPOINT_HEADER_LENGTH14 to 13).checkpoint_header.test.ts(the established workflow) and pasted into the noir tests; the p2p golden-byte fixture (wire_compat_fixtures.ts) was refreshed for the checkpoint-proposal serialization, which shrinks by exactly the one removed field. The block-proposal wire fixture is unchanged (block-levelinHashis out of scope, see A-1388).Circuits and constants
in_hashpass-through from the sizedInboxParity<S>circuit andParityPublicInputs(noir + TS + the hand-writtennoir-protocol-circuits-typesconversion wrappers). The circuit is kept (sized-parity, per FI-06's topology decision), so no VK-tree indices move.NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP(replaced everywhere byMAX_L1_TO_L2_MSGS_PER_CHECKPOINT, same value 1024) and the now-deadNUM_MSGS_PER_BASE_PARITY,NUM_BASE_PARITY_PER_ROOT_PARITY, andL1_TO_L2_MSG_SUBTREE_ROOT_SIBLING_PATH_LENGTH. Generated constants (constants.gen.ts,ConstantsGen.sol) were regenerated viaremake-constants.FrontierLib.soland its tests (Parity.t.sol, theFrontierharness and merkle test) now that their last users are gone.Verification
types::checkpoint_header(5/5),rollup_lib::parityandcheckpoint_root::parity_tests(15/15), and the checkpoint-root header-assembly path pass locally. The fullcheckpoint_rootsuite (68 tests) is too slow to run in full locally and rides CI.forge testgreen acrossRollup,RollupFieldRange,Inbox,InboxBuckets,RollupGetters(76/76), covering header hashing and the regenerated checkpoint fixtures.checkpoint_header, the p2p wire-compat suites, and the parity/messaging suites pass (43 tests), confirming the fixture regeneration is byte-consistent.yarn buildinnoir-protocol-circuits-types/simulator/prover-clientis expected to fail on stale circuit artifacts until then); e2e and the broken-zone typecheck are the CI-of-record for those.Stack
Part of the Fast Inbox stack #24784 through #24791 (umbrella #24774): A-1379 (#24784), A-1380 (#24785), A-1381 (#24786), A-1382 (#24787), A-1383 (#24788), A-1384 flip (#24789), A-1385 (#24790), A-1386 (#24791, base of this PR).
Resolves A-1387.
l1 publisher inbox consumption via the streaming selector (CI fix, pass-8)
The A-1387 inHash-removal rewrite left
l1_publisher.integration.test.tshardcodingpreviousInboxRollingHash = Fr.ZEROandbucketHint = 0nwhile consuming real L1→L2 messages, so message-consuming checkpoints reverted on L1 withRollup__InvalidInboxRollingHash/UnconsumedInboxMessages(masked every prior CI round behind earlier failures).INBOX_LAG_SECONDSis an L1-time censorship cutoff, not whole checkpoints, so no checkpoint-depth shift register reproduces the aged bucket set. The test now mirrors the real Inbox buckets into itsMockL1ToL2MessageSourceand reuses the productionselectInboxBucketForBlock(which mirrorsProposeLib.validateInboxConsumption) to pick exactly the buckets each checkpoint must consume, deriving the consumed bundle, the propose bucket hint, and the header rolling hash from that one selection. Box: 13/13, verified at a-1387 and a-1388.