feat(fast-inbox): single variable-size InboxParity proof per checkpoint (A-1427)#24759
Open
spalladino wants to merge 7 commits into
Open
feat(fast-inbox): single variable-size InboxParity proof per checkpoint (A-1427)#24759spalladino wants to merge 7 commits into
spalladino wants to merge 7 commits into
Conversation
spalladino
force-pushed
the
spl/a-1427-inbox-parity
branch
from
July 17, 2026 02:04
071f3d1 to
4375d97
Compare
This was referenced Jul 17, 2026
spalladino
force-pushed
the
spl/a-1375-msgs-only-block
branch
from
July 17, 2026 19:38
9d669cb to
eb88eba
Compare
spalladino
force-pushed
the
spl/a-1427-inbox-parity
branch
from
July 17, 2026 19:38
c18b69c to
1872323
Compare
Replace the parity base (x4) + parity root fan-in with one variable-size
InboxParity<S> proof per checkpoint, S in {64, 256, 1024} (one VK per size;
the prover proves the smallest rung >= the checkpoint's message count). The
parity-root circuit is deleted; the checkpoint root keeps one parity
verification, now accepting the 3-rung VK ladder. Net +1 VK.
Two transitional decisions (dev-only, closed by the future Fast Inbox flip):
- in_hash is kept in the parity public inputs as an unconstrained pass-through
hint (the orchestrator supplies the true sha256 frontier root via
computeInHashFromL1ToL2Messages), so L1's inHash == inbox.consume() check
still passes with no L1 changes. The frontier tree is no longer built in
circuit.
- The block-root message sponge absorbs at the real message count while the
L1-to-L2 tree insert stays a padded fixed subtree, decoupled via a new
L1ToL2MessageBundle { messages, num_msgs, num_real_msgs } struct so the real
count can be dropped later with minimal change. num_msgs is not otherwise
pinned in-circuit; documented as a dev-mode gap backstopped by the L1
pending-chain header hash.
Threads the single sized proof through the orchestrator, bb-prover, proving
broker, and TS bindings, collapsing getBaseParityProof/getRootParityProof into
getInboxParityProof and PARITY_BASE/PARITY_ROOT into one INBOX_PARITY request
type. The UltraHonk parity benchmark and bb.js debug test move to InboxParity256.
…e parity method merge Deleting getRootParityProof removed the last uses of NESTED_RECURSIVE_PROOF_LENGTH in mock_prover.ts and broker_prover_facade.ts; @typescript-eslint/no-unused-vars is error-level so yarn lint would fail. Also corrects two 'base parity' JSDoc lines to 'inbox parity'.
The generated L1ToL2MessageBundle.messages type is a fixed-length (1024) array, but the bundle's messages field is a plain Fr[], so mapFieldArrayToNoir inferred length `number` and tsc rejected it (TS2322) at the six block-root mapper call sites. Pass MAX_L1_TO_L2_MSGS_PER_BLOCK explicitly to produce the fixed length.
Removing the value constants (NUM_BASE_PARITY_PER_ROOT_PARITY, NUM_MSGS_PER_BASE_PARITY) left an @aztec/constants import whose members are all inline-type, which @typescript-eslint/no-import-type-side-effects rejects. Convert to import type.
Replacing the parity base/root artifacts with the single variable-size InboxParity ladder (64/256/1024) grew the playground main entrypoint to 1936.74 KB on CI, just over the 1925 KB hard limit. Bump with headroom, following the existing bump-log pattern in vite.config.ts.
ParityPublicInputs requires inHash to be a 31-byte (top-byte-zero) sha frontier root; the InboxParity circuit passes in_hash through unconstrained, so a raw Fr.random() input reappears in the output and fails the constructor check. Compute inHash from the messages instead.
spalladino
force-pushed
the
spl/a-1375-msgs-only-block
branch
from
July 17, 2026 20:04
eb88eba to
5f7c796
Compare
spalladino
force-pushed
the
spl/a-1427-inbox-parity
branch
from
July 17, 2026 20:04
1872323 to
347a6e1
Compare
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.
Replaces the parity base (×4) + parity root fan-in with one variable-size
InboxParity<S>proof per checkpoint, S ∈ {64, 256, 1024} (one VK per size; the prover proves the smallest rung ≥ the checkpoint's message count). The parity-root circuit is deleted; the checkpoint root keeps a single parity verification, now accepting the 3-rung VK ladder. Net +1 VK.Stacked on #24612 (
spl/a-1375-msgs-only-block).Two transitional decisions (dev-only; closed by the future Fast Inbox flip)
in_hashunconstrained pass-through. The circuit no longer builds the sha256 frontier tree.in_hashstays in the parity public inputs as an unconstrained hint — the orchestrator supplies the true frontier root viacomputeInHashFromL1ToL2Messages, the circuit echoes it out, and the checkpoint root copies it into the header. L1'srequire(header.inHash == inbox.consume())still passes, so no L1 changes (ConstantsGen.solregenerates byte-identical to the base).L1ToL2MessageBundle { messages, num_msgs, num_real_msgs }struct so the real count can be dropped later with minimal change.num_msgsis not otherwise pinned in-circuit — documented as a dev-mode gap backstopped by the L1 pending-chain header hash, parallel toin_hash.Scope
Threads the single sized proof through the orchestrator, bb-prover, proving broker, and TS bindings — collapsing
getBaseParityProof/getRootParityProofintogetInboxParityProofandPARITY_BASE/PARITY_ROOTinto oneINBOX_PARITYrequest type. The UltraHonk parity benchmark and bb.js debug test move toInboxParity256.Validation
rollup_libnargo suite: 387/387 passing.yarn build, VK/artifact regen, real proofs, and e2e run in CI (blocked locally by abb write_vkmemory-arena OOM on the unchangedrollup_rootcircuit).Known follow-up (out of scope, pre-existing on base)
inbox_rolling_hash.nr's doc comment claims the sha256 chain "matches the L1 Inbox," butInbox.solaccumulatesbytes16(keccak256(...)). Harmless today (the rolling hash isn't validated on L1), but the comment should be corrected on the base branch.