You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(fast-inbox): validator streaming acceptance conditions, flag off (A-1383)
Implements A-1383: the validator's streaming-Inbox acceptance conditions (AZIP-22 Fast Inbox), behind the shared `streamingInbox` flag (default off). Flag off ⇒ byte-identical behavior. Stacked on #24787 (A-1382).
## The four block-proposal checks (`validator-client/src/streaming_inbox_checks.ts`, wired in `proposal_handler.handleBlockProposal`)
- **Exists**: the referenced bucket resolves in the node's own Inbox view and its consensus rolling hash matches the reference. An unknown bucket is an immediate reject (`bucket_unknown`); the bounded-wait soft path is A-1393. The reference is trusted only as a `bucketSeq` lookup hint — timestamp/counts are read from the locally resolved bucket.
- **Moves forward**: the bucket's cumulative total is at least the parent block's (equal ⇒ empty bundle).
- **Not too new**: the bucket is at least `INBOX_LAG_SECONDS` old at validation time (`dateProvider.now()`, inclusive boundary).
- **Caps**: the per-block count and the running per-checkpoint total fit `MAX_L1_TO_L2_MSGS_PER_BLOCK` / `MAX_L1_TO_L2_MSGS_PER_CHECKPOINT`.
The derived bundle is fed into per-block re-execution (`insertMessagesPerBlock` threaded through `openCheckpoint` → `reexecuteTransactions`); the existing state-ref comparison after re-execution stays the final arbiter.
## Last-block censorship check (`validateCheckpointProposal`)
Before attesting, the minimum-consumption rule runs via the shared `isInboxConsumptionSufficient` predicate: the first unconsumed bucket must be absent, past the cutoff, or a cap-escape. A mandatory unconsumed bucket rejects the checkpoint (no attestation, `inbox_consumption_insufficient`).
## Shared-predicate extraction (`refactor` commit)
The cutoff formula and the minimum-consumption/cap-escape rule moved to `stdlib/messaging/inbox_consumption`, so the sequencer's bucket selection and the validator share one source of truth. The sequencer's `selectStreamingBundle` now calls `getInboxCutoffTimestamp` instead of inlining it — behavior unchanged (selector suite still green).
## Corrected cutoff anchor
The cutoff is `getTimestampForSlot(slot - 1) - INBOX_LAG_SECONDS` (mirroring `ProposeLib.validateInboxConsumption`), **not** `getBuildFrameStart`. The A-1371 §13 cross-layer vectors are pinned in `inbox_consumption.test.ts`.
## Parent-ref derivation
Parent/last-consumed buckets are resolved from L1-to-L2 tree leaf counts (compact post-flip indexing == bucket cumulative total) via a new `getInboxBucketByTotalMsgCount` archiver lookup. A leaf count that does not land on a bucket boundary (a pre-flip padded parent) is rejected/deferred; the flip (A-1384) closes that gap.
## CI must typecheck what can't be verified locally
`tsc -b` cannot complete locally due to pre-existing `noir-protocol-circuits-types` breakage (missing artifacts / stale generated types), which cascades to `archiver`/`validator-client`. stdlib builds clean; no errors in the changed files outside the broken zone. Runnable unit suites are green: `streaming_inbox_checks` (14), `inbox_consumption` (10), `proposal_handler` (34, incl. flag-off unchanged + new streaming/censorship tests), `message_store` (35), stdlib `archiver` interface (RPC schema). CI is the typecheck of record for the unbuildable zone.
Out of scope: bounded-wait (A-1393), the flip (A-1384), reorg rejection (A-1389), the full streaming checkpoint rebuild (A-1385).
Replaces #24788.
0 commit comments