Skip to content

Commit 73e288c

Browse files
committed
test(fast-inbox): streaming inbox mocks for the validator and prover-node unit suites (A-1384)
With streaming as the only consumption path, the validator proposal handler and the prover node derive consumed messages from L1-to-L2 tree leaf counts and the proposal bucket reference. Give the mocked block headers a leaf count, carry a genesis-bucket reference on test proposals, and resolve bucket queries to the genesis bucket so the acceptance checks pass with an empty bundle.
1 parent 4d7c269 commit 73e288c

2 files changed

Lines changed: 40 additions & 7 deletions

File tree

yarn-project/prover-node/src/prover-node.test.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ describe('ProverNode', () => {
173173
// getBlockData also feeds collectRegisterData when the rebuild re-registers, so it carries a header too.
174174
l2BlockSource.getBlockData.mockResolvedValue({
175175
checkpointNumber: CheckpointNumber(2),
176-
header: { lastArchive: { root: Fr.ZERO } },
176+
header: { lastArchive: { root: Fr.ZERO }, state: { l1ToL2MessageTree: { nextAvailableLeafIndex: 0 } } },
177177
} as any);
178178
await proverNode.handleBlockStreamEvent({
179179
type: 'chain-pruned',
@@ -639,9 +639,9 @@ describe('ProverNode', () => {
639639
l2BlockSource.getBlockNumber.mockResolvedValue(undefined);
640640
setupRegistrationSuccess();
641641
// getBlockData returns a header that lets isEpochFullyProven bail out as "not proven"
642-
// and supplies a lastArchive.root for collectRegisterData.
642+
// and supplies a lastArchive.root plus an L1-to-L2 leaf count for collectRegisterData.
643643
l2BlockSource.getBlockData.mockResolvedValue({
644-
header: { lastArchive: { root: Fr.ZERO } },
644+
header: { lastArchive: { root: Fr.ZERO }, state: { l1ToL2MessageTree: { nextAvailableLeafIndex: 0 } } },
645645
} as any);
646646
}
647647

@@ -655,7 +655,7 @@ describe('ProverNode', () => {
655655
worldState.syncImmediate.mockResolvedValue(undefined as any);
656656
l1ToL2MessageSource.getL1ToL2Messages.mockResolvedValue([]);
657657
l2BlockSource.getBlockData.mockResolvedValue({
658-
header: { lastArchive: { root: Fr.ZERO } },
658+
header: { lastArchive: { root: Fr.ZERO }, state: { l1ToL2MessageTree: { nextAvailableLeafIndex: 0 } } },
659659
} as any);
660660
worldState.getSnapshot.mockReturnValue({
661661
getTreeInfo: () => Promise.resolve({ size: 1n }),
@@ -673,7 +673,15 @@ describe('ProverNode', () => {
673673
number: CheckpointNumber(checkpointNumber),
674674
header: { slotNumber: SlotNumber(slot), inboxRollingHash: Fr.ZERO },
675675
archive: { root: archiveRoot },
676-
blocks: [{ number: blockNumber, header: { hash: () => Promise.resolve('0x01') } }],
676+
blocks: [
677+
{
678+
number: blockNumber,
679+
header: {
680+
hash: () => Promise.resolve('0x01'),
681+
state: { l1ToL2MessageTree: { nextAvailableLeafIndex: 0 } },
682+
},
683+
},
684+
],
677685
hash: () => new Fr(checkpointNumber),
678686
} as unknown as Checkpoint;
679687
}

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

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address';
3232
import { type BlockData, BlockHash, L2Block, type L2BlockSink, type L2BlockSource } from '@aztec/stdlib/block';
3333
import { type Checkpoint, CheckpointReexecutionTracker, type ProposedCheckpointData } from '@aztec/stdlib/checkpoint';
3434
import type { SlasherConfig, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
35-
import { type L1ToL2MessageSource, computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
35+
import {
36+
type InboxBucket,
37+
InboxBucketRef,
38+
type L1ToL2MessageSource,
39+
computeInHashFromL1ToL2Messages,
40+
} from '@aztec/stdlib/messaging';
3641
import type { BlockProposal } from '@aztec/stdlib/p2p';
3742
import { CheckpointHeader } from '@aztec/stdlib/rollup';
3843
import {
@@ -448,11 +453,24 @@ describe('ValidatorClient', () => {
448453
Array.isArray(args) &&
449454
args[0]?.offenseType === OffenseType.ATTESTED_TO_INVALID_CHECKPOINT_PROPOSAL,
450455
);
456+
// AZIP-22 Fast Inbox: an empty-consumption streaming setup. Proposals reference the genesis Inbox bucket, the
457+
// parent block's L1-to-L2 leaf count equals its cumulative total (0), so the derived per-block bundle is empty.
458+
const genesisInboxBucket: InboxBucket = {
459+
seq: 0n,
460+
inboxRollingHash: Fr.ZERO,
461+
totalMsgCount: 0n,
462+
timestamp: 0n,
463+
msgCount: 0,
464+
lastMessageIndex: 0n,
465+
isOpen: false,
466+
};
467+
const genesisBucketRef = InboxBucketRef.fromBucket(genesisInboxBucket);
468+
451469
beforeEach(async () => {
452470
const emptyInHash = computeInHashFromL1ToL2Messages([]);
453471
const blockHeader = makeBlockHeader(1, { blockNumber: BlockNumber(100), slotNumber: SlotNumber(100) });
454472
blockNumber = BlockNumber(blockHeader.globalVariables.blockNumber);
455-
proposal = await makeBlockProposal({ blockHeader, inHash: emptyInHash });
473+
proposal = await makeBlockProposal({ blockHeader, inHash: emptyInHash, bucketRef: genesisBucketRef });
456474
// The proposal targets slot 100, which under pipelining is built during the previous slot. Set the
457475
// wall clock to the start of that build slot (target_slot_start - S), matching how a pipelined
458476
// proposer is positioned when validating an inbound block proposal. With S - 2E = 0 in this config
@@ -512,6 +530,7 @@ describe('ValidatorClient', () => {
512530
getBlockNumber: () => blockNumber - 1,
513531
getSlot: () => parentSlot,
514532
globalVariables: blockHeader.globalVariables,
533+
state: { l1ToL2MessageTree: { nextAvailableLeafIndex: 0 } },
515534
},
516535
archive: new AppendOnlyTreeSnapshot(Fr.random(), blockNumber - 1),
517536
blockHash: BlockHash.random(),
@@ -525,6 +544,11 @@ describe('ValidatorClient', () => {
525544
blockSource.getGenesisValues.mockResolvedValue({ genesisArchiveRoot: new Fr(GENESIS_ARCHIVE_ROOT) });
526545
blockSource.syncImmediate.mockImplementation(() => Promise.resolve());
527546

547+
// Resolve every Inbox bucket query to the genesis bucket, so streaming checks accept with an empty bundle.
548+
l1ToL2MessageSource.getInboxBucket.mockResolvedValue(genesisInboxBucket);
549+
l1ToL2MessageSource.getInboxBucketByTotalMsgCount.mockResolvedValue(genesisInboxBucket);
550+
l1ToL2MessageSource.getL1ToL2MessagesBetweenBuckets.mockResolvedValue([]);
551+
528552
const clonedBlockHeader = blockHeader.clone();
529553
blockBuildResult = {
530554
publicProcessorDuration: 0,
@@ -727,6 +751,7 @@ describe('ValidatorClient', () => {
727751
archiveRoot: proposal.archive,
728752
txHashes: proposal.txHashes,
729753
signer: selfSigner,
754+
bucketRef: genesisBucketRef,
730755
});
731756

732757
epochCache.getProposerAttesterAddressInSlot.mockResolvedValue(selfSigner.address);

0 commit comments

Comments
 (0)