feat(fast-inbox): same-block L1-to-L2 message consumption for non-first blocks (A-1432)#24781
Open
spalladino wants to merge 2 commits into
Open
feat(fast-inbox): same-block L1-to-L2 message consumption for non-first blocks (A-1432)#24781spalladino wants to merge 2 commits into
spalladino wants to merge 2 commits into
Conversation
…st blocks (A-1432) The non-first tx-carrying block-root variants (block_root, block_root_single_tx) now take their start L1-to-L2 tree snapshot as a witness input, pinned by block-merge continuity (right.start_state == left.end_state) to the previous block's end state, and assert the tx constants carry their own post-bundle root via validate_l1_to_l2_tree_snapshot_in_constants, exactly like the first-block variants. This lets a public/AVM tx in block N read the messages block N inserts (same-block consumption) instead of only from block N+1. Previously the non-first variants read their start snapshot from constants.l1_to_l2_tree_snapshot and never asserted the post-bundle root, so mid-checkpoint insertions were next-block-visible. Bit-identical pre-flip: non-first bundles are empty, so post-bundle == start == today's constants value, and the new assert passes with unchanged values. The tx-less variants (empty-first, msgs-only) carry no tx constants and already witness their start snapshot, so they are unchanged. Adds negative nargo tests (a non-first block whose constants snapshot differs from its post-bundle root must fail) and mirrors the new witness field through stdlib serialization, the Noir ABI conversion, and the prover-client block-root input builders. VK/artifact regen, checkpoint-root/block-root Prover.toml sample-input regen, and the generated noir-protocol-circuits-types (index.ts) regen ride the mainframe/CI flow; they are not regenerated locally (bb write_vk OOMs on large circuits on dev boxes).
…in the TS BlockConstantData (A-1432)
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.
What
Makes every block's
BlockConstantData.l1_to_l2_tree_snapshotthe post-bundle snapshot for that block — first block or not — so a public/AVM tx in block N can read the L1-to-L2 messages block N inserts (same-block consumption), instead of only from block N+1.Previously the non-first tx-carrying variants (
block_root,block_root_single_tx) read their start snapshot fromconstants.l1_to_l2_tree_snapshotand never asserted the post-bundle root, giving next-block visibility for mid-checkpoint insertions. Now they:previous_l1_to_l2), pinned by block-merge continuity (right.start_state == left.end_state) to the previous block's end state — the checkpoint root forces the leftmost block to be a first-block variant, so every non-first block has a left neighbour pinning its start;validate_l1_to_l2_tree_snapshot_in_constants(constants, new_l1_to_l2), exactly like the first-block variants.The tx-less variants (
block_root_empty_tx_first,block_root_msgs_only) carry no tx constants to read against and already witness their start snapshot, so they are unchanged.Soundness
The witnessed start snapshot cannot be forged: block-merge / checkpoint-root continuity asserts
right.start_state == left.end_state, and the checkpoint root asserts the leftmost block is a first-block variant (whose start is pinned to the previous checkpoint). The start is therefore anchored, and the new assert pins the tx-constants snapshot to the computed post-bundle root. The start is not derived from "constants minus the bundle" (not expressible).Bit-identical pre-flip (public inputs)
Non-first bundles are empty today, so
new_l1_to_l2 == start == today's constants value; the new assert passes with unchanged values and the block-root public inputs / state are unchanged. The circuit constraints, private-input ABI, proof, and VK do change (hence the regen below). This is a restructure-now / flip-minimal change.Flip follow-on (not in this PR)
The recursive pinning of the witnessed
previous_l1_to_l2is already exercised byblock_merge::tests::consecutive_block_rollups_tests::non_consecutive_l1_to_l2_message_tree_snapshots(a right block whosestart_state.l1_to_l2_message_tree— i.e. this witness — doesn't match the left block's end is rejected on continuity).One flip requirement this change surfaces: today the prover gives every non-first block the checkpoint's post-first-block snapshot as its
previousL1ToL2(block-proving-state.ts), which is correct only while non-first bundles are empty. Once non-first blocks insert their own bundles (A-1384), the prover must instead feed block N+1 the end snapshot of block N plus the matching frontier hint. Flagged for the flip plan (A-1384).Tests
Adds negative nargo tests: a non-first block (two-tx and single-tx) whose
constants.l1_to_l2_tree_snapshotdiffers from its post-bundle root must fail. Red/green verified locally — with the new asserts removed the four negative tests report "Test passed when it should have failed"; restored, they pass.rollup_libblock_root suite green (63 tests), block_merge (45), checkpoint_root structure tests (17).TS wiring
Mirrors the new
previous_l1_to_l2field throughstdlib(BlockRootRollupPrivateInputs/BlockRootSingleTxRollupPrivateInputsserialization + factory), the Noir ABI conversion (server.ts), and the prover-client block-root input builders (block-proving-state.ts), which pass the block'slastL1ToL2MessageTreeSnapshot(for non-first blocks, the checkpoint's post-first-block snapshot).stdlibbuilds and its serialization test passes.Artifact regen (rides CI / mainframe)
This changes the
block_rootandblock_root_single_txcircuit ABIs, so it invalidates their VKs, the checkpoint-root/block-rootProver.tomlsample inputs, and the generatednoir-protocol-circuits-types/src/types/index.ts. These are not regenerated locally (bb write_vkOOMs on large circuits on dev boxes; the generatedindex.tsalso depends on recompiled circuit artifacts). They ride the seeded-S3-cache mainframe/CI flow, consistent with the rest of the Fast Inbox stack.Stack
Stacked on
spl/a-1427-inbox-parity; the L1 PRs (#24771, #24773) are rebased on top of this. Part of the Fast Inbox stack (umbrella #24774).Fixes A-1432