Skip to content

Commit 8d2c62e

Browse files
authored
chore: (A-347) verify non-validator re-executes and stores mbps into archiver (#20071)
A test verifying that non-validators can reexecute and store multiple proposed blocks per slot into archiver since this process is already set up for mbps
2 parents c225327 + fdff823 commit 8d2c62e

File tree

1 file changed

+73
-1
lines changed

1 file changed

+73
-1
lines changed

yarn-project/end-to-end/src/e2e_epochs/epochs_mbps.parallel.test.ts

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { waitForTx } from '@aztec/aztec.js/node';
1010
import { RollupContract } from '@aztec/ethereum/contracts';
1111
import type { Operator } from '@aztec/ethereum/deploy-aztec-l1-contracts';
1212
import { asyncMap } from '@aztec/foundation/async-map';
13-
import { CheckpointNumber } from '@aztec/foundation/branded-types';
13+
import { CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
1414
import { times, timesAsync } from '@aztec/foundation/collection';
1515
import { SecretValue } from '@aztec/foundation/config';
1616
import { retryUntil } from '@aztec/foundation/retry';
@@ -363,4 +363,76 @@ describe('e2e_epochs/epochs_mbps', () => {
363363

364364
await assertMultipleBlocksPerSlot(2, logger);
365365
});
366+
367+
it('builds multiple blocks per slot and non-validator re-executes and stores proposed multi-block slots', async () => {
368+
await setupTest({ syncChainTip: 'proposed', minTxsPerBlock: 1, maxTxsPerBlock: 1 });
369+
370+
logger.warn(`Creating non-validator node`);
371+
const nonValidatorNode = await test.createNonValidatorNode({
372+
alwaysReexecuteBlockProposals: true,
373+
skipPushProposedBlocksToArchiver: false,
374+
});
375+
376+
await Promise.all(nodes.map(n => n.getSequencer()!.start()));
377+
logger.warn(`Started all sequencers`);
378+
379+
logger.warn(`Pre-proving ${TX_COUNT / 2} transactions`);
380+
const txs = await timesAsync(TX_COUNT / 2, i => {
381+
const nullifier = new Fr(i + 100);
382+
return proveInteraction(context.wallet, contract.methods.emit_nullifier(nullifier), { from });
383+
});
384+
logger.warn(`Pre-proved ${txs.length} transactions`);
385+
386+
const sentTxHashes = await Promise.all(txs.map(tx => tx.send({ wait: NO_WAIT })));
387+
logger.warn(`Sent ${sentTxHashes.length} transactions`);
388+
389+
const nonValidatorArchiver = nonValidatorNode.getBlockSource();
390+
391+
let multiBlockSlotNumber: number | undefined;
392+
let checkpointedBlockNumber: number | undefined;
393+
await retryUntil(
394+
async () => {
395+
const tips = await nonValidatorArchiver.getL2Tips();
396+
if (tips.proposed.number <= tips.checkpointed.block.number) {
397+
return false;
398+
}
399+
const header = await nonValidatorArchiver.getBlockHeader(tips.proposed.number);
400+
if (!header) {
401+
return false;
402+
}
403+
const blocksInSlot = await nonValidatorArchiver.getBlocksForSlot(header.globalVariables.slotNumber);
404+
if (blocksInSlot.length < 2) {
405+
return false;
406+
}
407+
multiBlockSlotNumber = header.globalVariables.slotNumber;
408+
checkpointedBlockNumber = tips.checkpointed.block.number;
409+
return true;
410+
},
411+
'non-validator node to store multi-block proposed slot',
412+
test.L2_SLOT_DURATION_IN_S * 5,
413+
0.5,
414+
);
415+
416+
// ensure the proposed multi-block slot has valid effects
417+
expect(multiBlockSlotNumber).toBeDefined();
418+
const blocksInSlot = await nonValidatorArchiver.getBlocksForSlot(SlotNumber(multiBlockSlotNumber!));
419+
expect(blocksInSlot.length).toBeGreaterThanOrEqual(2);
420+
expect(checkpointedBlockNumber).toBeDefined();
421+
expect(blocksInSlot.every(block => block.number > checkpointedBlockNumber!)).toBe(true); // ensure the block is proposed
422+
const txHashesInSlot = blocksInSlot.flatMap(block => block.body.txEffects.map(effect => effect.txHash));
423+
expect(txHashesInSlot.length).toBeGreaterThan(0);
424+
const effectsInSlot = await Promise.all(txHashesInSlot.map(txHash => nonValidatorArchiver.getTxEffect(txHash)));
425+
expect(effectsInSlot.every(effect => effect !== undefined)).toBe(true);
426+
427+
const maxBlockNumberInSlot = Math.max(...blocksInSlot.map(block => block.number));
428+
await retryUntil(
429+
async () => {
430+
const tips = await nonValidatorArchiver.getL2Tips();
431+
return tips.checkpointed.block.number >= maxBlockNumberInSlot;
432+
},
433+
'non-validator node to sync checkpointed block',
434+
test.L2_SLOT_DURATION_IN_S * 5,
435+
0.5,
436+
);
437+
});
366438
});

0 commit comments

Comments
 (0)