Skip to content

Commit bffc4a3

Browse files
committed
test(fast-inbox): stub streaming inbox methods in sequencer and validator suites (A-1384)
Streaming is now the only consumption path, so the sequencer checkpoint job resolves the parent Inbox bucket from a world-state fork and every block proposal carries a bucket reference. Stub getInboxBucketByTotalMsgCount and the fork tree info in the sequencer unit suites, and attach the consumed bucket reference (plus a non-zero L1 genesis time) in the validator integration suite so proposals pass the streaming acceptance checks.
1 parent 0460c32 commit bffc4a3

3 files changed

Lines changed: 48 additions & 2 deletions

File tree

yarn-project/sequencer-client/src/sequencer/checkpoint_proposal_job.timing.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
BlockBuilderOptions,
1717
MerkleTreeWriteOperations,
1818
ResolvedSequencerConfig,
19+
TreeInfo,
1920
WorldStateSynchronizer,
2021
} from '@aztec/stdlib/interfaces/server';
2122
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
@@ -448,10 +449,22 @@ describe('CheckpointProposalJob Timing Tests', () => {
448449
const mockFork = mock<MerkleTreeWriteOperations>({
449450
[Symbol.asyncDispose]: jest.fn().mockReturnValue(Promise.resolve()) as () => Promise<void>,
450451
});
452+
// AZIP-22 streaming inbox: the checkpoint job resolves the parent Inbox bucket from the fork's
453+
// L1-to-L2 tree leaf count. Default to an empty tree so it starts at the genesis bucket.
454+
mockFork.getTreeInfo.mockResolvedValue({ size: 0n } as TreeInfo);
451455
worldState.fork.mockResolvedValue(mockFork);
452456

453457
l1ToL2MessageSource = mock<L1ToL2MessageSource>();
454458
l1ToL2MessageSource.getL1ToL2Messages.mockResolvedValue(Array(4).fill(Fr.ZERO));
459+
l1ToL2MessageSource.getInboxBucketByTotalMsgCount.mockResolvedValue({
460+
seq: 0n,
461+
inboxRollingHash: Fr.ZERO,
462+
totalMsgCount: 0n,
463+
timestamp: 0n,
464+
msgCount: 0,
465+
lastMessageIndex: 0n,
466+
isOpen: false,
467+
});
455468

456469
l2BlockSource = mock<L2BlockSource>();
457470
l2BlockSource.getCheckpointsData.mockResolvedValue([]);

yarn-project/sequencer-client/src/sequencer/sequencer.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ import type { ChainConfig } from '@aztec/stdlib/config';
3535
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
3636
import { GasFees } from '@aztec/stdlib/gas';
3737
import {
38+
type MerkleTreeWriteOperations,
3839
type SequencerConfig,
40+
type TreeInfo,
3941
WorldStateRunningState,
4042
type WorldStateSyncStatus,
4143
type WorldStateSynchronizer,
@@ -166,6 +168,8 @@ describe('sequencer', () => {
166168
expect.any(Checkpoint),
167169
attestationsAndSigners,
168170
getSignatures()[0].signature,
171+
// AZIP-22 streaming inbox: the checkpoint job passes the parent bucket hint (genesis => 0n).
172+
0n,
169173
expect.objectContaining({
170174
txTimeoutAt: expect.any(Date),
171175
}),
@@ -285,6 +289,13 @@ describe('sequencer', () => {
285289
},
286290
} satisfies WorldStateSynchronizerStatus),
287291
});
292+
// AZIP-22 streaming inbox: the checkpoint job forks world state and resolves the parent Inbox bucket
293+
// from the fork's L1-to-L2 tree leaf count. Default to an empty tree so it starts at the genesis bucket.
294+
const mockFork = mock<MerkleTreeWriteOperations>({
295+
[Symbol.asyncDispose]: jest.fn().mockReturnValue(Promise.resolve()) as () => Promise<void>,
296+
});
297+
mockFork.getTreeInfo.mockResolvedValue({ size: 0n } as TreeInfo);
298+
worldState.fork.mockResolvedValue(mockFork);
288299

289300
// Create fake CheckpointsBuilder and CheckpointBuilder
290301
// Uses blockProvider to return the current `block` variable (set per-test)
@@ -355,6 +366,15 @@ describe('sequencer', () => {
355366
},
356367
}),
357368
});
369+
l1ToL2MessageSource.getInboxBucketByTotalMsgCount.mockResolvedValue({
370+
seq: 0n,
371+
inboxRollingHash: Fr.ZERO,
372+
totalMsgCount: 0n,
373+
timestamp: 0n,
374+
msgCount: 0,
375+
lastMessageIndex: 0n,
376+
isOpen: false,
377+
});
358378

359379
validatorClient = mock<ValidatorClient>();
360380
validatorClient.collectAttestations.mockImplementation(() => Promise.resolve(getCheckpointAttestations()));
@@ -839,6 +859,8 @@ describe('sequencer', () => {
839859
expect.any(Checkpoint),
840860
attestationsAndSigners,
841861
getSignatures()[0].signature,
862+
// AZIP-22 streaming inbox: the checkpoint job passes the parent bucket hint (genesis => 0n).
863+
0n,
842864
expect.objectContaining({
843865
txTimeoutAt: expect.any(Date),
844866
}),

yarn-project/validator-client/src/validator.integration.test.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { CheckpointReexecutionTracker, L1PublishedData, PublishedCheckpoint } fr
2626
import { type L1RollupConstants, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
2727
import { Gas, GasFees } from '@aztec/stdlib/gas';
2828
import { tryStop } from '@aztec/stdlib/interfaces/server';
29-
import { computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
29+
import { InboxBucketRef, computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
3030
import { type BlockProposal, CheckpointProposal } from '@aztec/stdlib/p2p';
3131
import { mockTx } from '@aztec/stdlib/testing';
3232
import { BlockHeader, type CheckpointGlobalVariables, Tx } from '@aztec/stdlib/tx';
@@ -48,7 +48,9 @@ jest.setTimeout(60_000);
4848
describe('ValidatorClient Integration', () => {
4949
// Constants for L1
5050
const l1Constants: L1RollupConstants = {
51-
l1GenesisTime: 0n,
51+
// Non-zero genesis time so the slot-1 validation clock is well past INBOX_LAG_SECONDS; otherwise the streaming
52+
// Inbox acceptance check rejects even a genesis-timestamp (0) bucket as `bucket_too_new` (AZIP-22 Fast Inbox).
53+
l1GenesisTime: 1_700_000_000n,
5254
slotDuration: 24,
5355
epochDuration: 16,
5456
ethereumSlotDuration: 12,
@@ -255,6 +257,14 @@ describe('ValidatorClient Integration', () => {
255257
minValidTxs: 0,
256258
});
257259

260+
// Resolve the Inbox bucket this block consumed through (keyed by its cumulative L1-to-L2 leaf count) and attach
261+
// the reference, mirroring the sequencer's block-building loop which carries a bucketRef on every proposal
262+
// (AZIP-22 Fast Inbox). Without it the validator's streaming acceptance check rejects the proposal as
263+
// `bucket_unknown`. A block that consumed nothing resolves to the genesis (or reused parent) bucket.
264+
const blockTotal = BigInt(block.header.state.l1ToL2MessageTree.nextAvailableLeafIndex);
265+
const bucket = await proposer.archiver.getInboxBucketByTotalMsgCount(blockTotal);
266+
const bucketRef = bucket ? InboxBucketRef.fromBucket(bucket) : undefined;
267+
258268
const proposal = await proposer.validator.createBlockProposal(
259269
block.header,
260270
cpNumber,
@@ -264,6 +274,7 @@ describe('ValidatorClient Integration', () => {
264274
usedTxs,
265275
proposerSigner.address,
266276
{},
277+
bucketRef,
267278
);
268279

269280
logger.warn(`Built block proposal for block ${blockNumber}`, { ...block.toBlockInfo() });

0 commit comments

Comments
 (0)