Skip to content

feat(fast-inbox): single variable-size InboxParity proof per checkpoint (A-1427)#24759

Open
spalladino wants to merge 7 commits into
spl/a-1375-msgs-only-blockfrom
spl/a-1427-inbox-parity
Open

feat(fast-inbox): single variable-size InboxParity proof per checkpoint (A-1427)#24759
spalladino wants to merge 7 commits into
spl/a-1375-msgs-only-blockfrom
spl/a-1427-inbox-parity

Conversation

@spalladino

@spalladino spalladino commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

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_hash unconstrained pass-through. The circuit no longer builds the sha256 frontier tree. in_hash stays in the parity public inputs as an unconstrained hint — the orchestrator supplies the true frontier root via computeInHashFromL1ToL2Messages, the circuit echoes it out, and the checkpoint root copies it into the header. L1's require(header.inHash == inbox.consume()) still passes, so no L1 changes (ConstantsGen.sol regenerates byte-identical to the base).
  • Sponge real-count decoupling. Block roots absorb the message sponge at the real count while the L1-to-L2 tree insert stays a padded fixed subtree, 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, parallel to in_hash.

Scope

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.

Validation

  • rollup_lib nargo suite: 387/387 passing.
  • Reviewed by a second model (Fable) and codex sol; their build-break and consistency findings are folded in.
  • Full yarn build, VK/artifact regen, real proofs, and e2e run in CI (blocked locally by a bb write_vk memory-arena OOM on the unchanged rollup_root circuit).

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," but Inbox.sol accumulates bytes16(keccak256(...)). Harmless today (the rolling hash isn't validated on L1), but the comment should be corrected on the base branch.

Note: proving-broker scheduling relocated

The oldest-epoch-first proving-broker scheduling fix that previously headed this branch has been moved down to #24603 (A-1374), where it is required to keep long_proving_time green on the intermediate stack. The stack top is unchanged — only the commit's position changed.

@spalladino
spalladino requested a review from LeilaWang as a code owner July 17, 2026 01:49
@spalladino
spalladino force-pushed the spl/a-1427-inbox-parity branch from 071f3d1 to 4375d97 Compare July 17, 2026 02:04
@spalladino spalladino added the ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure label Jul 17, 2026
@spalladino
spalladino requested a review from Thunkar as a code owner July 17, 2026 03:29
@spalladino spalladino changed the title feat: single variable-size InboxParity proof per checkpoint (A-1427) feat(fast-inbox): single variable-size InboxParity proof per checkpoint (A-1427) Jul 17, 2026
@spalladino
spalladino force-pushed the spl/a-1375-msgs-only-block branch from 9d669cb to eb88eba Compare July 17, 2026 19:38
@spalladino
spalladino requested a review from just-mitch as a code owner July 17, 2026 19:38
@spalladino
spalladino force-pushed the spl/a-1427-inbox-parity branch from c18b69c to 1872323 Compare July 17, 2026 19:38
@spalladino
spalladino force-pushed the spl/a-1375-msgs-only-block branch from eb88eba to 5f7c796 Compare July 17, 2026 20:04
@spalladino
spalladino force-pushed the spl/a-1427-inbox-parity branch 2 times, most recently from 347a6e1 to 00c602f Compare July 19, 2026 14:05
@spalladino
spalladino force-pushed the spl/a-1375-msgs-only-block branch from 5f7c796 to 225af28 Compare July 19, 2026 14:05
@spalladino
spalladino force-pushed the spl/a-1427-inbox-parity branch 2 times, most recently from f6f7fa3 to c211ed4 Compare July 19, 2026 20:48
@spalladino
spalladino force-pushed the spl/a-1375-msgs-only-block branch 2 times, most recently from f0ea9e4 to bd88da8 Compare July 20, 2026 15:30
@spalladino
spalladino force-pushed the spl/a-1427-inbox-parity branch 2 times, most recently from 1a60442 to 6ad8216 Compare July 20, 2026 17:28
@spalladino
spalladino force-pushed the spl/a-1375-msgs-only-block branch from bd88da8 to 415a05a Compare July 20, 2026 17:28
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.
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.
…e_bundle input shape (A-1427)

The inbox-parity branch reshapes the block-root private inputs around
message_bundle; carry the sample inputs generated at this state so nargo
execute passes for the five block-root crates.
@spalladino
spalladino force-pushed the spl/a-1375-msgs-only-block branch from 415a05a to aacbdb1 Compare July 20, 2026 21:21
@spalladino
spalladino force-pushed the spl/a-1427-inbox-parity branch from 6ad8216 to 20b46ed Compare July 20, 2026 21:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant