From 08a83e89b7cbd7916e276dfe32ac4e30c76e9b04 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Tue, 16 Jun 2026 09:41:11 +0000 Subject: [PATCH] test(e2e): stop governance proposal chain monitor --- .../gov_proposal.parallel.test.ts | 138 +++++++++--------- 1 file changed, 71 insertions(+), 67 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_sequencer/gov_proposal.parallel.test.ts b/yarn-project/end-to-end/src/e2e_sequencer/gov_proposal.parallel.test.ts index ba0b9048a3c8..9c5cd78d747d 100644 --- a/yarn-project/end-to-end/src/e2e_sequencer/gov_proposal.parallel.test.ts +++ b/yarn-project/end-to-end/src/e2e_sequencer/gov_proposal.parallel.test.ts @@ -210,74 +210,78 @@ describe('e2e_gov_proposal', () => { it('should vote even when unable to build blocks', async () => { const monitor = new ChainMonitor(rollup, dateProvider).start(); - // Disable the in-process proposer→archiver block shortcut (validator-client and - // checkpoint_proposal_job both push the just-built block into the local archiver) and then - // disable the blob client. The archiver-side `skipPromoteProposedCheckpointDuringL1Sync` - // shortcut is disabled at setup() — without it the L1 synchronizer would promote the locally - // proposed checkpoint into a published one without going through the blob client, and the - // tx would still be observed as `checkpointed` regardless of the disabled blob client. With - // all three shortcuts off the node has no choice but to rely on the blob client for sync. - await aztecNodeAdmin!.setConfig({ skipPushProposedBlocksToArchiver: true }); - ((aztecNodeAdmin as AztecNodeService).getBlobClient() as HttpBlobClient).setDisabled(true); - await sleep(1000); - const lastBlockSynced = await aztecNode!.getBlockNumber(); - const lastCheckpointOnL1 = await rollup.getCheckpointNumber(); - logger.warn(`blob client is disabled`, { lastBlockSynced, lastCheckpointOnL1 }); - - // And send a tx which shouldnt be syncable but does move the block forward. - // Under proposer pipelining the proposer builds in slot N-1 and the L1 propose mines in slot N, so a single - // slot is not enough to observe the L1 checkpoint advance. Wait at least two slots before declaring the tx - // un-syncable and before checking that L1 has progressed. - await expect(() => - testContract.methods - .create_l2_to_l1_message_arbitrary_recipient_private(Fr.random(), EthAddress.random()) - .send({ from: defaultAccountAddress, wait: { timeout: AZTEC_SLOT_DURATION * 2 + 2 } }), - ).rejects.toThrow(TimeoutError); - logger.warn(`Test tx timed out as expected`); - - // Check that the checkpoint number has indeed increased on L1 so sequencers cant pass the sync check. - // Allow another slot for any in-flight L1 propose to mine, since the work loop above hits its wait timeout the - // moment the tx misses L2 sync, not the moment the L1 tx lands. - const checkpointAfterBlobDisable = await retryUntil( - async () => { - const snapshot = await monitor.run(); - return snapshot.checkpointNumber > lastCheckpointOnL1 ? snapshot : undefined; - }, - 'L1 checkpoint to advance after disabling blob client', - AZTEC_SLOT_DURATION + 5, - 1, - ); - expect(checkpointAfterBlobDisable.checkpointNumber).toBeGreaterThan(lastCheckpointOnL1); - logger.warn(`L1 checkpoint number has increased`, { - checkpointNumber: checkpointAfterBlobDisable.checkpointNumber, - l2SlotNumber: checkpointAfterBlobDisable.l2SlotNumber, - }); - - await aztecNodeAdmin!.setConfig({ governanceProposerPayload: newGovernanceProposerAddress }); - - // The checkpoint that advanced L1 may have a pipelined successor still waiting for the disabled blob client. - // Wait through the target slot end plus the two-L1-slot sync tolerance before starting the vote-only round. - const voteOnlySlot = SlotNumber(Number(checkpointAfterBlobDisable.l2SlotNumber) + 2); - logger.warn(`Waiting until slot ${voteOnlySlot} before starting vote-only round`); - await retryUntil( - async () => ((await rollup.getSlotNumber()) >= voteOnlySlot ? true : undefined), - 'stale pipelined checkpoint to expire after disabling blob client', - AZTEC_SLOT_DURATION * 4, - 1, - ); - - // Select the voting round. - const { round, roundDuration, nextRoundBeginsAtSlot } = await setupVotingRound(); + try { + // Disable the in-process proposer→archiver block shortcut (validator-client and + // checkpoint_proposal_job both push the just-built block into the local archiver) and then + // disable the blob client. The archiver-side `skipPromoteProposedCheckpointDuringL1Sync` + // shortcut is disabled at setup() — without it the L1 synchronizer would promote the locally + // proposed checkpoint into a published one without going through the blob client, and the + // tx would still be observed as `checkpointed` regardless of the disabled blob client. With + // all three shortcuts off the node has no choice but to rely on the blob client for sync. + await aztecNodeAdmin!.setConfig({ skipPushProposedBlocksToArchiver: true }); + ((aztecNodeAdmin as AztecNodeService).getBlobClient() as HttpBlobClient).setDisabled(true); + await sleep(1000); + const lastBlockSynced = await aztecNode!.getBlockNumber(); + const lastCheckpointOnL1 = await rollup.getCheckpointNumber(); + logger.warn(`blob client is disabled`, { lastBlockSynced, lastCheckpointOnL1 }); + + // And send a tx which shouldnt be syncable but does move the block forward. + // Under proposer pipelining the proposer builds in slot N-1 and the L1 propose mines in slot N, so a single + // slot is not enough to observe the L1 checkpoint advance. Wait at least two slots before declaring the tx + // un-syncable and before checking that L1 has progressed. + await expect(() => + testContract.methods + .create_l2_to_l1_message_arbitrary_recipient_private(Fr.random(), EthAddress.random()) + .send({ from: defaultAccountAddress, wait: { timeout: AZTEC_SLOT_DURATION * 2 + 2 } }), + ).rejects.toThrow(TimeoutError); + logger.warn(`Test tx timed out as expected`); + + // Check that the checkpoint number has indeed increased on L1 so sequencers cant pass the sync check. + // Allow another slot for any in-flight L1 propose to mine, since the work loop above hits its wait timeout the + // moment the tx misses L2 sync, not the moment the L1 tx lands. + const checkpointAfterBlobDisable = await retryUntil( + async () => { + const snapshot = await monitor.run(); + return snapshot.checkpointNumber > lastCheckpointOnL1 ? snapshot : undefined; + }, + 'L1 checkpoint to advance after disabling blob client', + AZTEC_SLOT_DURATION + 5, + 1, + ); + expect(checkpointAfterBlobDisable.checkpointNumber).toBeGreaterThan(lastCheckpointOnL1); + logger.warn(`L1 checkpoint number has increased`, { + checkpointNumber: checkpointAfterBlobDisable.checkpointNumber, + l2SlotNumber: checkpointAfterBlobDisable.l2SlotNumber, + }); - // And wait until the round is over. Add one extra slot to absorb pipelining catch-up after the L1 warp in - // setupVotingRound — the proposer for round_start builds during the slot before it, so the L1 chain takes - // an extra slot to advance past nextRoundEndsAtSlot. - const nextRoundEndsAtSlot = SlotNumber(nextRoundBeginsAtSlot + Number(roundDuration)); - const timeout = AZTEC_SLOT_DURATION * Number(roundDuration + 2n) + 20; - logger.warn(`Waiting until slot ${nextRoundEndsAtSlot} for round to end (timeout ${timeout}s)`); - await retryUntil(() => rollup.getSlotNumber().then(s => s > nextRoundEndsAtSlot), 'round end', timeout, 1); + await aztecNodeAdmin!.setConfig({ governanceProposerPayload: newGovernanceProposerAddress }); + + // The checkpoint that advanced L1 may have a pipelined successor still waiting for the disabled blob client. + // Wait through the target slot end plus the two-L1-slot sync tolerance before starting the vote-only round. + const voteOnlySlot = SlotNumber(Number(checkpointAfterBlobDisable.l2SlotNumber) + 2); + logger.warn(`Waiting until slot ${voteOnlySlot} before starting vote-only round`); + await retryUntil( + async () => ((await rollup.getSlotNumber()) >= voteOnlySlot ? true : undefined), + 'stale pipelined checkpoint to expire after disabling blob client', + AZTEC_SLOT_DURATION * 4, + 1, + ); - // We should have voted despite being unable to build blocks - await verifyVotes(round, roundDuration); + // Select the voting round. + const { round, roundDuration, nextRoundBeginsAtSlot } = await setupVotingRound(); + + // And wait until the round is over. Add one extra slot to absorb pipelining catch-up after the L1 warp in + // setupVotingRound — the proposer for round_start builds during the slot before it, so the L1 chain takes + // an extra slot to advance past nextRoundEndsAtSlot. + const nextRoundEndsAtSlot = SlotNumber(nextRoundBeginsAtSlot + Number(roundDuration)); + const timeout = AZTEC_SLOT_DURATION * Number(roundDuration + 2n) + 20; + logger.warn(`Waiting until slot ${nextRoundEndsAtSlot} for round to end (timeout ${timeout}s)`); + await retryUntil(() => rollup.getSlotNumber().then(s => s > nextRoundEndsAtSlot), 'round end', timeout, 1); + + // We should have voted despite being unable to build blocks + await verifyVotes(round, roundDuration); + } finally { + await monitor.stop(); + } }); });