Skip to content

Commit

Permalink
Refactor e2e epoch tests and add multi proof
Browse files Browse the repository at this point in the history
  • Loading branch information
spalladino committed Feb 19, 2025
1 parent ee3abb1 commit 29dd5eb
Show file tree
Hide file tree
Showing 13 changed files with 478 additions and 382 deletions.
2 changes: 2 additions & 0 deletions yarn-project/circuit-types/src/interfaces/prover-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ export interface EpochProverManager {

getProvingJobSource(): ProvingJobConsumer;

getProverId(): Fr;

updateProverConfig(config: Partial<ProverConfig>): Promise<void>;
}

Expand Down
4 changes: 3 additions & 1 deletion yarn-project/end-to-end/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ function test_cmds {
echo "$prefix simple e2e_deploy_contract/deploy_method"
echo "$prefix simple e2e_deploy_contract/legacy"
echo "$prefix simple e2e_deploy_contract/private_initialization"
echo "$prefix simple e2e_epochs"
echo "$prefix simple e2e_epochs/epochs_empty_blocks"
echo "$prefix simple e2e_epochs/epochs_multi_proof"
echo "$prefix simple e2e_epochs/epochs_proof_fails"
echo "$prefix simple e2e_escrow_contract"
echo "$prefix simple e2e_event_logs"

Expand Down
2 changes: 1 addition & 1 deletion yarn-project/end-to-end/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,4 @@
"../../foundation/src/jest/setup.mjs"
]
}
}
}
210 changes: 0 additions & 210 deletions yarn-project/end-to-end/src/e2e_epochs.test.ts

This file was deleted.

84 changes: 84 additions & 0 deletions yarn-project/end-to-end/src/e2e_epochs/epochs_empty_blocks.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { type Logger, sleep } from '@aztec/aztec.js';
import { ChainMonitor } from '@aztec/aztec.js/ethereum';
// eslint-disable-next-line no-restricted-imports
import { RollupContract } from '@aztec/ethereum/contracts';

import { jest } from '@jest/globals';

import { type EndToEndContext } from '../fixtures/utils.js';
import {
EPOCH_DURATION_IN_L2_SLOTS,
EpochsTestContext,
L1_BLOCK_TIME_IN_S,
WORLD_STATE_BLOCK_HISTORY,
} from './epochs_test.js';

jest.setTimeout(1000 * 60 * 10);

describe('e2e_epochs/epochs_empty_blocks', () => {
let context: EndToEndContext;
let rollup: RollupContract;
let logger: Logger;
let monitor: ChainMonitor;

let test: EpochsTestContext;

beforeEach(async () => {
test = await EpochsTestContext.setup();
({ context, rollup, logger, monitor } = test);
});

afterEach(async () => {
jest.restoreAllMocks();
await test.teardown();
});

it('submits proof even if there are no txs to build a block', async () => {
await context.sequencer?.updateSequencerConfig({ minTxsPerBlock: 1 });
await test.waitUntilEpochStarts(1);

// Sleep to make sure any pending blocks are published
await sleep(L1_BLOCK_TIME_IN_S * 1000);
const blockNumberAtEndOfEpoch0 = Number(await rollup.getBlockNumber());
logger.info(`Starting epoch 1 after L2 block ${blockNumberAtEndOfEpoch0}`);

await test.waitUntilProvenL2BlockNumber(blockNumberAtEndOfEpoch0, 120);
expect(monitor.l2BlockNumber).toEqual(blockNumberAtEndOfEpoch0);
logger.info(`Test succeeded`);
});

it('successfully proves multiple epochs', async () => {
const targetProvenEpochs = 8;
const targetProvenBlockNumber = targetProvenEpochs * EPOCH_DURATION_IN_L2_SLOTS;

let provenBlockNumber = 0;
let epochNumber = 0;
while (provenBlockNumber < targetProvenBlockNumber) {
logger.info(`Waiting for the end of epoch ${epochNumber}`);
await test.waitUntilEpochStarts(epochNumber + 1);
const epochTargetBlockNumber = Number(await rollup.getBlockNumber());
logger.info(`Epoch ${epochNumber} ended with PENDING block number ${epochTargetBlockNumber}`);
await test.waitUntilL2BlockNumber(epochTargetBlockNumber);
provenBlockNumber = epochTargetBlockNumber;
logger.info(
`Reached PENDING L2 block ${epochTargetBlockNumber}, proving should now start, waiting for PROVEN block to reach ${provenBlockNumber}`,
);
await test.waitUntilProvenL2BlockNumber(provenBlockNumber, 120);
expect(Number(await rollup.getProvenBlockNumber())).toBe(provenBlockNumber);
logger.info(`Reached PROVEN block number ${provenBlockNumber}, epoch ${epochNumber} is now proven`);
epochNumber++;

// Verify the state syncs
await test.waitForNodeToSync(provenBlockNumber, 'finalised');
await test.verifyHistoricBlock(provenBlockNumber, true);
const expectedOldestHistoricBlock = provenBlockNumber - WORLD_STATE_BLOCK_HISTORY + 1;
const expectedBlockRemoved = expectedOldestHistoricBlock - 1;
await test.waitForNodeToSync(expectedOldestHistoricBlock, 'historic');
await test.verifyHistoricBlock(Math.max(expectedOldestHistoricBlock, 1), true);
if (expectedBlockRemoved > 0) {
await test.verifyHistoricBlock(expectedBlockRemoved, false);
}
}
logger.info('Test Succeeded');
});
});
67 changes: 67 additions & 0 deletions yarn-project/end-to-end/src/e2e_epochs/epochs_multi_proof.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { type Logger, retryUntil, sleep } from '@aztec/aztec.js';
// eslint-disable-next-line no-restricted-imports
import { type L1RollupConstants, getSlotRangeForEpoch } from '@aztec/circuit-types';
import { EthAddress } from '@aztec/circuits.js';
import { RollupContract } from '@aztec/ethereum/contracts';

import { jest } from '@jest/globals';

import { type EndToEndContext } from '../fixtures/utils.js';
import { EPOCH_DURATION_IN_L2_SLOTS, EpochsTestContext, L1_BLOCK_TIME_IN_S } from './epochs_test.js';

jest.setTimeout(1000 * 60 * 10);

describe('e2e_epochs/epochs_multi_proof', () => {
let context: EndToEndContext;
let rollup: RollupContract;
let constants: L1RollupConstants;
let logger: Logger;

let test: EpochsTestContext;

beforeEach(async () => {
test = await EpochsTestContext.setup();
({ context, rollup, constants, logger } = test);
});

afterEach(async () => {
jest.restoreAllMocks();
await test.teardown();
});

it('submits proofs from multiple prover-nodes', async () => {
await test.createProverNode();
await test.createProverNode();
const proverIds = test.proverNodes.map(prover => EthAddress.fromField(prover.getProverId()));
logger.info(`Prover nodes running with ids ${proverIds.map(id => id.toString()).join(', ')}`);

// Wait until the start of epoch one and collect info on epoch zero
await test.waitUntilEpochStarts(1);
await sleep(L1_BLOCK_TIME_IN_S * 1000);
const [_firstEpochStartSlot, firstEpochEndSlot] = getSlotRangeForEpoch(0n, constants);
const firstEpochBlocks = await context.aztecNode
.getBlocks(1, EPOCH_DURATION_IN_L2_SLOTS)
.then(blocks => blocks.filter(block => block.header.getSlot() <= firstEpochEndSlot));
const firstEpochLength = firstEpochBlocks.length;
const firstEpochLastBlockNum = firstEpochBlocks.at(-1)!.number;
logger.info(`Starting epoch 1 with length ${firstEpochLength} after L2 block ${firstEpochLastBlockNum}`);

// Wait until all three provers have submitted proofs
await retryUntil(
async () => {
const haveSubmitted = await Promise.all(
proverIds.map(proverId => rollup.getHasSubmittedProof(0, firstEpochLength, proverId)),
);
logger.info(`Proof submissions: ${haveSubmitted.join(', ')}`);
return haveSubmitted.every(submitted => submitted);
},
'Provers have submitted proofs',
120,
);

const provenBlockNumber = await context.aztecNode.getProvenBlockNumber();
expect(provenBlockNumber).toEqual(firstEpochLastBlockNum);

logger.info(`Test succeeded`);
});
});
Loading

0 comments on commit 29dd5eb

Please sign in to comment.