diff --git a/yarn-project/archiver/src/index.ts b/yarn-project/archiver/src/index.ts index 78587150a24b..d5a4868892af 100644 --- a/yarn-project/archiver/src/index.ts +++ b/yarn-project/archiver/src/index.ts @@ -4,6 +4,7 @@ export * from './archiver.js'; export * from './modules/data_source_base.js'; export * from './modules/data_store_updater.js'; export * from './config.js'; +export * from './errors.js'; export { type L1PublishedData } from './structs/published.js'; export { diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 95440a05ffb2..3bf6933939cd 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -1,4 +1,4 @@ -import { Archiver, createArchiver } from '@aztec/archiver'; +import { Archiver, L1ToL2MessagesNotReadyError, createArchiver } from '@aztec/archiver'; import { BBCircuitVerifier, BatchChonkVerifier, QueuedIVCVerifier } from '@aztec/bb-prover'; import { TestCircuitVerifier } from '@aztec/bb-prover/test'; import { type BlobClientInterface, createBlobClientWithFileStores } from '@aztec/blob-client/client'; @@ -20,6 +20,7 @@ import { retryUntil } from '@aztec/foundation/retry'; import { count } from '@aztec/foundation/string'; import { DateProvider, Timer } from '@aztec/foundation/timer'; import { MembershipWitness, SiblingPath } from '@aztec/foundation/trees'; +import { isErrorClass } from '@aztec/foundation/types'; import { type KeyStore, KeystoreManager, loadKeystores, mergeKeystores } from '@aztec/node-keystore'; import { trySnapshotSync, uploadSnapshot } from '@aztec/node-lib/actions'; import { createForwarderL1TxUtilsFromSigners, createL1TxUtilsFromSigners } from '@aztec/node-lib/factories'; @@ -1516,11 +1517,24 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, AztecNodeDeb // the world state tree so simulation can take them into account. We detect if the next block would // start a new checkpoint by checking if the proposed checkpoint's block number matches the latest block number, // which means the next block would be the first block of the next checkpoint. + const targetCheckpoint = CheckpointNumber( + (l2Tips.proposedCheckpoint.checkpoint.number ?? CheckpointNumber.ZERO) + 1, + ); const nextCheckpointMessages: Fr[] | undefined = l2Tips.proposedCheckpoint.block.number === l2Tips.proposed.number - ? await this.l1ToL2MessageSource.getL1ToL2Messages( - CheckpointNumber((l2Tips.proposedCheckpoint.checkpoint.number ?? CheckpointNumber.ZERO) + 1), - ) + ? await this.l1ToL2MessageSource.getL1ToL2Messages(targetCheckpoint).catch(err => { + if (isErrorClass(err, L1ToL2MessagesNotReadyError)) { + this.log.warn( + `L1-to-L2 messages for checkpoint ${targetCheckpoint} are not ready yet (simulating without them)`, + ); + } else { + this.log.error( + `Failed to get L1-to-L2 messages for checkpoint ${targetCheckpoint} (simulating without them)`, + err, + ); + } + return undefined; + }) : undefined; // Request a new fork of the world state at the latest block number, and apply any overrides and next checkpoint messages to it before simulation diff --git a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts index 16d74bb5b0bc..bef33db22659 100644 --- a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts +++ b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts @@ -9,6 +9,7 @@ import { AvmTestContract } from '@aztec/noir-test-contracts.js/AvmTest'; import { jest } from '@jest/globals'; +import { PIPELINING_SETUP_OPTS } from './fixtures/fixtures.js'; import { ensureAccountContractsPublished, setup } from './fixtures/utils.js'; const TIMEOUT = 600_000; @@ -22,239 +23,256 @@ describe('e2e_avm_simulator', () => { let teardown: () => Promise; beforeAll(async () => { - // TODO(kill-non-pipelined): runs under legacy until §6 B7 (simulator + inboxLag mismatch in - // AztecNodeService.simulatePublicCalls) is fixed. Test uses `.simulate(...)` heavily and - // observed Rollup__InvalidArchive cascade ~12min into the run, consistent with archiver/L1 - // drift triggered by pipelined simulate path. Same un-opt-in pattern as e2e_bot - // (commit e32ea4fb60) and e2e_fees/failures (commit eb542676f8). ({ teardown, wallet, aztecNode, accounts: [defaultAccountAddress], - } = await setup(1)); + } = await setup(1, { ...PIPELINING_SETUP_OPTS, aztecProofSubmissionEpochs: 640 })); await ensureAccountContractsPublished(wallet, [defaultAccountAddress]); }); afterAll(() => teardown()); describe('AvmTestContract', () => { - let avmContract: AvmTestContract; - let avmContractInstance: ContractInstanceWithAddress; - let secondAvmContract: AvmTestContract; - - beforeEach(async () => { - ({ contract: avmContract, instance: avmContractInstance } = await AvmTestContract.deploy(wallet).send({ - from: defaultAccountAddress, - })); - ({ contract: secondAvmContract } = await AvmTestContract.deploy(wallet).send({ from: defaultAccountAddress })); - }); + // Read-only / non-mutating tests share a single deployment to keep slot-paced deploy txs + // out of the per-test critical path under proposer pipelining. + describe('with shared deployment', () => { + let avmContract: AvmTestContract; + let avmContractInstance: ContractInstanceWithAddress; + + beforeAll(async () => { + ({ contract: avmContract, instance: avmContractInstance } = await AvmTestContract.deploy(wallet).send({ + from: defaultAccountAddress, + })); + }); - describe('Assertions & error enriching', () => { - /** - * Expect an error like: - * Assertion failed: This assertion should fail! 'assert(not_true == true, "This assertion should fail!")' - * ... - * at assert(not_true == true, "This assertion should fail!") (../../../../../../../home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/test/avm_test_contract/src/main.nr:223:5) - * at inner_helper_with_failed_assertion() (../../../../../../../home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/test/avm_test_contract/src/main.nr:228:9) - * at quote { $self } (../std/meta/expr.nr:269:9) - * at function.name(); - * let call = quote { $name($args) (/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/macros/dispatch.nr:59:20) - * at AvmTest.0xc3515746 - */ - describe('Not nested', () => { - it('PXE processes user code assertions and recovers message (properly enriched)', async () => { - await expect( - avmContract.methods.assertion_failure().simulate({ from: defaultAccountAddress }), - ).rejects.toThrow( - expect.objectContaining({ - message: expect.stringMatching( - /Assertion failed: This assertion should fail! 'assert\(not_true == true, "This assertion should fail!"\)'/, - ), - stack: expect.stringMatching(/at inner_helper_with_failed_assertion[\s\S]*at AvmTest\..*/), - }), - ); - }); - it('PXE processes user code assertions and recovers message (complex)', async () => { - await expect( - avmContract.methods.assert_nullifier_exists(123).simulate({ from: defaultAccountAddress }), - ).rejects.toThrow("Assertion failed: Nullifier doesn't exist!"); + describe('Assertions & error enriching', () => { + /** + * Expect an error like: + * Assertion failed: This assertion should fail! 'assert(not_true == true, "This assertion should fail!")' + * ... + * at assert(not_true == true, "This assertion should fail!") (../../../../../../../home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/test/avm_test_contract/src/main.nr:223:5) + * at inner_helper_with_failed_assertion() (../../../../../../../home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/test/avm_test_contract/src/main.nr:228:9) + * at quote { $self } (../std/meta/expr.nr:269:9) + * at function.name(); + * let call = quote { $name($args) (/home/aztec-dev/aztec-packages/noir-projects/aztec-nr/aztec/src/macros/dispatch.nr:59:20) + * at AvmTest.0xc3515746 + */ + describe('Not nested', () => { + it('PXE processes user code assertions and recovers message (properly enriched)', async () => { + await expect( + avmContract.methods.assertion_failure().simulate({ from: defaultAccountAddress }), + ).rejects.toThrow( + expect.objectContaining({ + message: expect.stringMatching( + /Assertion failed: This assertion should fail! 'assert\(not_true == true, "This assertion should fail!"\)'/, + ), + stack: expect.stringMatching(/at inner_helper_with_failed_assertion[\s\S]*at AvmTest\..*/), + }), + ); + }); + it('PXE processes user code assertions and recovers message (complex)', async () => { + await expect( + avmContract.methods.assert_nullifier_exists(123).simulate({ from: defaultAccountAddress }), + ).rejects.toThrow("Assertion failed: Nullifier doesn't exist!"); + }); + it('PXE processes intrinsic assertions and recovers message', async () => { + await expect( + avmContract.methods.divide_by_zero(0).simulate({ from: defaultAccountAddress }), + ).rejects.toThrow('Division by zero'); + }); }); - it('PXE processes intrinsic assertions and recovers message', async () => { - await expect(avmContract.methods.divide_by_zero(0).simulate({ from: defaultAccountAddress })).rejects.toThrow( - 'Division by zero', - ); + describe('Nested', () => { + it('PXE processes user code assertions and recovers message', async () => { + await expect( + avmContract.methods.external_call_to_assertion_failure().simulate({ from: defaultAccountAddress }), + ).rejects.toThrow('Assertion failed: This assertion should fail!'); + }); + it('PXE processes intrinsic assertions and recovers message', async () => { + await expect( + avmContract.methods.external_call_to_divide_by_zero().simulate({ from: defaultAccountAddress }), + ).rejects.toThrow('Division by zero'); + }); }); }); - describe('Nested', () => { - it('PXE processes user code assertions and recovers message', async () => { - await expect( - avmContract.methods.external_call_to_assertion_failure().simulate({ from: defaultAccountAddress }), - ).rejects.toThrow('Assertion failed: This assertion should fail!'); - }); - it('PXE processes intrinsic assertions and recovers message', async () => { - await expect( - avmContract.methods.external_call_to_divide_by_zero().simulate({ from: defaultAccountAddress }), - ).rejects.toThrow('Division by zero'); + + describe('From private', () => { + it('Should enqueue a public function correctly', async () => { + const request = await avmContract.methods.enqueue_public_from_private().request(); + const simulation = await wallet.simulateTx(request, { from: defaultAccountAddress }); + expect(simulation.publicOutput!.revertReason).toBeUndefined(); }); }); - }); - describe('From private', () => { - it('Should enqueue a public function correctly', async () => { - const request = await avmContract.methods.enqueue_public_from_private().request(); - const simulation = await wallet.simulateTx(request, { from: defaultAccountAddress }); - expect(simulation.publicOutput!.revertReason).toBeUndefined(); + describe('Gas metering', () => { + it('Tracks L2 gas usage on simulation', async () => { + const request = await avmContract.methods.add_args_return(20n, 30n).request(); + const simulation = await wallet.simulateTx(request, { from: defaultAccountAddress }); + // Subtract the teardown gas from the total gas to figure out the gas used by the contract logic. + const l2TeardownGas = simulation.publicOutput!.gasUsed.teardownGas.l2Gas; + const l2GasUsed = simulation.publicOutput!.gasUsed.totalGas.l2Gas - l2TeardownGas; + // L2 gas used will vary a lot depending on codegen and other factors, + // so we just set a wide range for it, and check it's not a suspiciously round number. + expect(l2GasUsed).toBeGreaterThan(150); + expect(l2GasUsed).toBeLessThan(1e6); + expect(l2GasUsed! % 1000).not.toEqual(0); + }); }); - }); - describe('Gas metering', () => { - it('Tracks L2 gas usage on simulation', async () => { - const request = await avmContract.methods.add_args_return(20n, 30n).request(); - const simulation = await wallet.simulateTx(request, { from: defaultAccountAddress }); - // Subtract the teardown gas from the total gas to figure out the gas used by the contract logic. - const l2TeardownGas = simulation.publicOutput!.gasUsed.teardownGas.l2Gas; - const l2GasUsed = simulation.publicOutput!.gasUsed.totalGas.l2Gas - l2TeardownGas; - // L2 gas used will vary a lot depending on codegen and other factors, - // so we just set a wide range for it, and check it's not a suspiciously round number. - expect(l2GasUsed).toBeGreaterThan(150); - expect(l2GasUsed).toBeLessThan(1e6); - expect(l2GasUsed! % 1000).not.toEqual(0); + describe('Contract instance', () => { + it('Works', async () => { + const { receipt: tx } = await avmContract.methods + .test_get_contract_instance_matches( + avmContract.address, + avmContractInstance.deployer, + avmContractInstance.currentContractClassId, + avmContractInstance.initializationHash, + ) + .send({ from: defaultAccountAddress }); + expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); + }); }); - }); - describe('Storage', () => { - it('Modifies storage (Field)', async () => { - await avmContract.methods.set_storage_single(20n).send({ from: defaultAccountAddress }); - expect( - (await avmContract.methods.read_storage_single().simulate({ from: defaultAccountAddress })).result, - ).toEqual(20n); + describe('L2 to L1 messages', () => { + it('Should fail if emitting to an invalid ethereum address', async () => { + const recipient = Fr.MAX_FIELD_VALUE; + await expect( + avmContract.methods + .raw_l2_to_l1_msg({ address: recipient }, new Fr(1)) + .send({ from: defaultAccountAddress }), + ).rejects.toThrow(); + }); }); - it('Modifies storage (Map)', async () => { - const address = AztecAddress.fromBigInt(9090n); - await avmContract.methods.set_storage_map(address, 100).send({ from: defaultAccountAddress }); - await avmContract.methods.add_storage_map(address, 100).send({ from: defaultAccountAddress }); - expect( - (await avmContract.methods.read_storage_map(address).simulate({ from: defaultAccountAddress })).result, - ).toEqual(200n); - }); + describe('Nested calls', () => { + it('Nested call to non-existent contract reverts & rethrows by default', async () => { + // The nested call reverts and by default caller rethrows + await expect( + avmContract.methods.nested_call_to_nothing().simulate({ from: defaultAccountAddress }), + ).rejects.toThrow(/not deployed/); + }); - it('Preserves storage across enqueued public calls', async () => { - const address = AztecAddress.fromBigInt(9090n); - // This will create 1 tx with 2 public calls in it. - await new BatchCall(wallet, [ - avmContract.methods.set_storage_map(address, 100), - avmContract.methods.add_storage_map(address, 100), - ]).send({ from: defaultAccountAddress }); - // On a separate tx, we check the result. - expect( - (await avmContract.methods.read_storage_map(address).simulate({ from: defaultAccountAddress })).result, - ).toEqual(200n); + it('Nested CALL instruction to non-existent contract returns failure, but caller can recover', async () => { + // The nested call reverts (returns failure), but the caller doesn't HAVE to rethrow. + const { receipt: tx } = await avmContract.methods + .nested_call_to_nothing_recovers() + .send({ from: defaultAccountAddress }); + expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); + }); + it('Should NOT be able to emit the same unsiloed nullifier from the same contract', async () => { + const nullifier = new Fr(1); + await expect( + avmContract.methods + .create_same_nullifier_in_nested_call(avmContract.address, nullifier) + .send({ from: defaultAccountAddress }), + ).rejects.toThrow(); + }); }); }); - describe('Contract instance', () => { - it('Works', async () => { - const { receipt: tx } = await avmContract.methods - .test_get_contract_instance_matches( - avmContract.address, - avmContractInstance.deployer, - avmContractInstance.currentContractClassId, - avmContractInstance.initializationHash, - ) - .send({ from: defaultAccountAddress }); - expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); + // State-mutating tests get a fresh deployment per test to avoid cross-test leakage of + // storage writes or persisted nullifiers. + describe('with fresh deployment per test', () => { + let avmContract: AvmTestContract; + let secondAvmContract: AvmTestContract; + + beforeEach(async () => { + ({ contract: avmContract } = await AvmTestContract.deploy(wallet).send({ + from: defaultAccountAddress, + })); + ({ contract: secondAvmContract } = await AvmTestContract.deploy(wallet).send({ from: defaultAccountAddress })); }); - }); - describe('Nullifiers', () => { - // Nullifier will not yet be siloed by the kernel. - it('Emit and check in the same tx', async () => { - const { receipt: tx } = await avmContract.methods - .emit_nullifier_and_check(123456) - .send({ from: defaultAccountAddress }); - expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); - }); + describe('Storage', () => { + it('Modifies storage (Field)', async () => { + await avmContract.methods.set_storage_single(20n).send({ from: defaultAccountAddress }); + expect( + (await avmContract.methods.read_storage_single().simulate({ from: defaultAccountAddress })).result, + ).toEqual(20n); + }); - // Nullifier will have been siloed by the kernel, but we check against the unsiloed one. - it('Emit and check in separate tx', async () => { - const nullifier = new Fr(123456); - let { receipt: tx } = await avmContract.methods.new_nullifier(nullifier).send({ from: defaultAccountAddress }); - expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); + it('Modifies storage (Map)', async () => { + const address = AztecAddress.fromBigInt(9090n); + await avmContract.methods.set_storage_map(address, 100).send({ from: defaultAccountAddress }); + await avmContract.methods.add_storage_map(address, 100).send({ from: defaultAccountAddress }); + expect( + (await avmContract.methods.read_storage_map(address).simulate({ from: defaultAccountAddress })).result, + ).toEqual(200n); + }); - ({ receipt: tx } = await avmContract.methods - .assert_nullifier_exists(nullifier) - .send({ from: defaultAccountAddress })); - expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); + it('Preserves storage across enqueued public calls', async () => { + const address = AztecAddress.fromBigInt(9090n); + // This will create 1 tx with 2 public calls in it. + await new BatchCall(wallet, [ + avmContract.methods.set_storage_map(address, 100), + avmContract.methods.add_storage_map(address, 100), + ]).send({ from: defaultAccountAddress }); + // On a separate tx, we check the result. + expect( + (await avmContract.methods.read_storage_map(address).simulate({ from: defaultAccountAddress })).result, + ).toEqual(200n); + }); }); - it('Emit and check in separate enqueued calls but same tx', async () => { - const nullifier = new Fr(123456); - - // This will create 1 tx with 2 public calls in it. - await new BatchCall(wallet, [ - avmContract.methods.new_nullifier(nullifier), - avmContract.methods.assert_nullifier_exists(nullifier), - ]).send({ from: defaultAccountAddress }); - }); - }); + describe('Nullifiers', () => { + // Nullifier will not yet be siloed by the kernel. + it('Emit and check in the same tx', async () => { + const { receipt: tx } = await avmContract.methods + .emit_nullifier_and_check(123456) + .send({ from: defaultAccountAddress }); + expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); + }); - describe('L2 to L1 messages', () => { - it('Should fail if emitting to an invalid ethereum address', async () => { - const recipient = Fr.MAX_FIELD_VALUE; - await expect( - avmContract.methods.raw_l2_to_l1_msg({ address: recipient }, new Fr(1)).send({ from: defaultAccountAddress }), - ).rejects.toThrow(); - }); - }); + // Nullifier will have been siloed by the kernel, but we check against the unsiloed one. + it('Emit and check in separate tx', async () => { + const nullifier = new Fr(123456); + let { receipt: tx } = await avmContract.methods + .new_nullifier(nullifier) + .send({ from: defaultAccountAddress }); + expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); + + ({ receipt: tx } = await avmContract.methods + .assert_nullifier_exists(nullifier) + .send({ from: defaultAccountAddress })); + expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); + }); - describe('Nested calls', () => { - it('Nested call to non-existent contract reverts & rethrows by default', async () => { - // The nested call reverts and by default caller rethrows - await expect( - avmContract.methods.nested_call_to_nothing().simulate({ from: defaultAccountAddress }), - ).rejects.toThrow(/not deployed/); - }); + it('Emit and check in separate enqueued calls but same tx', async () => { + const nullifier = new Fr(123456); - it('Nested CALL instruction to non-existent contract returns failure, but caller can recover', async () => { - // The nested call reverts (returns failure), but the caller doesn't HAVE to rethrow. - const { receipt: tx } = await avmContract.methods - .nested_call_to_nothing_recovers() - .send({ from: defaultAccountAddress }); - expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); - }); - it('Should NOT be able to emit the same unsiloed nullifier from the same contract', async () => { - const nullifier = new Fr(1); - await expect( - avmContract.methods - .create_same_nullifier_in_nested_call(avmContract.address, nullifier) - .send({ from: defaultAccountAddress }), - ).rejects.toThrow(); + // This will create 1 tx with 2 public calls in it. + await new BatchCall(wallet, [ + avmContract.methods.new_nullifier(nullifier), + avmContract.methods.assert_nullifier_exists(nullifier), + ]).send({ from: defaultAccountAddress }); + }); }); - it('Should be able to emit different unsiloed nullifiers from the same contract', async () => { - const nullifier = new Fr(1); - const { receipt: tx } = await avmContract.methods - .create_different_nullifier_in_nested_call(avmContract.address, nullifier) - .send({ from: defaultAccountAddress }); - expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); - }); + describe('Nested calls', () => { + it('Should be able to emit different unsiloed nullifiers from the same contract', async () => { + const nullifier = new Fr(1); + const { receipt: tx } = await avmContract.methods + .create_different_nullifier_in_nested_call(avmContract.address, nullifier) + .send({ from: defaultAccountAddress }); + expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); + }); - it('Should be able to emit the same unsiloed nullifier from two different contracts', async () => { - const nullifier = new Fr(1); - const { receipt: tx } = await avmContract.methods - .create_same_nullifier_in_nested_call(secondAvmContract.address, nullifier) - .send({ from: defaultAccountAddress }); - expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); - }); + it('Should be able to emit the same unsiloed nullifier from two different contracts', async () => { + const nullifier = new Fr(1); + const { receipt: tx } = await avmContract.methods + .create_same_nullifier_in_nested_call(secondAvmContract.address, nullifier) + .send({ from: defaultAccountAddress }); + expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); + }); - it('Should be able to emit different unsiloed nullifiers from two different contracts', async () => { - const nullifier = new Fr(1); - const { receipt: tx } = await avmContract.methods - .create_different_nullifier_in_nested_call(secondAvmContract.address, nullifier) - .send({ from: defaultAccountAddress }); - expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); + it('Should be able to emit different unsiloed nullifiers from two different contracts', async () => { + const nullifier = new Fr(1); + const { receipt: tx } = await avmContract.methods + .create_different_nullifier_in_nested_call(secondAvmContract.address, nullifier) + .send({ from: defaultAccountAddress }); + expect(tx.executionResult).toEqual(TxExecutionResult.SUCCESS); + }); }); }); }); diff --git a/yarn-project/end-to-end/src/e2e_bot.test.ts b/yarn-project/end-to-end/src/e2e_bot.test.ts index 4782ccac0ea8..6ff803dd388e 100644 --- a/yarn-project/end-to-end/src/e2e_bot.test.ts +++ b/yarn-project/end-to-end/src/e2e_bot.test.ts @@ -23,6 +23,7 @@ import { EmbeddedWallet } from '@aztec/wallets/embedded'; import { jest } from '@jest/globals'; +import { PIPELINED_FEE_PADDING, PIPELINING_SETUP_OPTS } from './fixtures/fixtures.js'; import { getPrivateKeyFromIndex, setup } from './fixtures/utils.js'; describe('e2e_bot', () => { @@ -36,15 +37,11 @@ describe('e2e_bot', () => { beforeAll(async () => { const [botAccount] = await getInitialTestAccountsData(); - // TODO(palla/pipelining): re-opt-in once public-call simulation handles `inboxLag`. Under - // pipelining with `inboxLag=2`, `AztecNodeService.simulatePublicCalls` queries - // `getL1ToL2Messages(proposedCheckpoint+1)` at checkpoint boundaries and throws - // `L1ToL2MessagesNotReadyError` because that checkpoint isn't yet sealed on L1 (see - // server.ts:1508 + message_store.ts:233). This breaks the bridge/amm/cross-chain bot flows. - // The `transaction-bot` cluster additionally needs the bot's `minFeePadding` bumped to - // `PIPELINED_FEE_PADDING` (the bot overrides the wallet padding via - // `wallet.setMinFeePadding(config.minFeePadding)` in `bot/src/factory.ts:60`). - const setupResult = await setup(0, { initialFundedAccounts: [botAccount] }); + const setupResult = await setup(0, { + ...PIPELINING_SETUP_OPTS, + aztecProofSubmissionEpochs: 640, + initialFundedAccounts: [botAccount], + }); ({ teardown, aztecNode, @@ -70,6 +67,7 @@ describe('e2e_bot', () => { ...getBotDefaultConfig(), followChain: 'CHECKPOINTED', botMode: 'transfer', + minFeePadding: PIPELINED_FEE_PADDING, }; bot = await Bot.create(config, wallet, aztecNode, undefined, new BotStore(await openTmpStore('bot'))); }); @@ -260,7 +258,7 @@ describe('e2e_bot', () => { // See 'can consume L1 to L2 message in %s after inbox drifts away from the rollup' // in end-to-end/src/e2e_cross_chain_messaging/l1_to_l2.test.ts for context on this test. it('creates bot after inbox drift', async () => { - await cheatCodes.rollup.advanceInboxInProgress(10); + await cheatCodes.rollup.advanceInboxInProgress(4); await Bot.create(config, wallet, aztecNode, aztecNodeAdmin, new BotStore(await openTmpStore('bot'))); }, 300_000); }); diff --git a/yarn-project/end-to-end/src/e2e_fees/failures.test.ts b/yarn-project/end-to-end/src/e2e_fees/failures.test.ts index 7348575a2189..13ddaadf0980 100644 --- a/yarn-project/end-to-end/src/e2e_fees/failures.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/failures.test.ts @@ -16,7 +16,7 @@ import { ExecutionPayload } from '@aztec/stdlib/tx'; import { jest } from '@jest/globals'; -import { U128_UNDERFLOW_ERROR } from '../fixtures/fixtures.js'; +import { PIPELINING_SETUP_OPTS, U128_UNDERFLOW_ERROR } from '../fixtures/fixtures.js'; import { expectMapping } from '../fixtures/utils.js'; import { FeesTest } from './fees_test.js'; @@ -37,12 +37,10 @@ describe('e2e_fees failures', () => { const t = new FeesTest('failures', 3, { coinbase }); beforeAll(async () => { - // TODO(kill-non-pipelined): runs under legacy until §6 B7 (simulator + inboxLag mismatch in - // AztecNodeService.simulatePublicCalls) is fixed. Under pipelining with `inboxLag=2`, - // `simulatePublicCalls` queries `getL1ToL2Messages(proposedCheckpoint+1)` at checkpoint - // boundaries and throws `L1ToL2MessagesNotReadyError`. Same root cause as e2e_bot - // (un-opt-in commit e32ea4fb60); 4/5 tests in this suite hit it via `.simulate(...)`. - await t.setup(); + // Shorter epochs (default 32 → 4) speed the per-test `advanceToNextEpoch + waitForProven` + // cycle: the prover-node submits a proof as soon as the epoch is complete, so ~8x shorter + // epochs ≈ ~8x faster proof cadence per cycle. Setup itself stays slot-bound. + await t.setup({ ...PIPELINING_SETUP_OPTS, aztecProofSubmissionEpochs: 640, aztecEpochDuration: 4 }); await t.applyFPCSetup(); ({ wallet, aliceAddress, sequencerAddress, bananaCoin, bananaFPC, gasSettings } = t); aztecNode = t.aztecNode; diff --git a/yarn-project/end-to-end/src/e2e_fees/private_payments.test.ts b/yarn-project/end-to-end/src/e2e_fees/private_payments.test.ts index 3b61a9b69dcb..15b37f516b5d 100644 --- a/yarn-project/end-to-end/src/e2e_fees/private_payments.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/private_payments.test.ts @@ -9,6 +9,7 @@ import { TX_ERROR_INSUFFICIENT_FEE_PAYER_BALANCE } from '@aztec/stdlib/tx'; import { jest } from '@jest/globals'; +import { PIPELINING_SETUP_OPTS } from '../fixtures/fixtures.js'; import { expectMapping } from '../fixtures/utils.js'; import type { TestWallet } from '../test-wallet/test_wallet.js'; import { proveInteraction } from '../test-wallet/utils.js'; @@ -31,13 +32,10 @@ describe('e2e_fees private_payment', () => { const t = new FeesTest('private_payment'); beforeAll(async () => { - // TODO(kill-non-pipelined): runs under legacy until §6 B7 (simulator + inboxLag mismatch in - // AztecNodeService.simulatePublicCalls) is fixed. Under pipelining with `inboxLag=2`, - // `simulatePublicCalls` queries `getL1ToL2Messages(proposedCheckpoint+1)` at checkpoint - // boundaries and throws `L1ToL2MessagesNotReadyError`. Same root cause as e2e_bot - // (un-opt-in commit e32ea4fb60) and e2e_fees/failures (eb542676f8); all 6 tests in this - // suite hit it via `getBananaPublicBalanceFn` -> `.simulate(...)`. - await t.setup(); + // Shorter epochs (default 32 → 4) speed the per-test `advanceToNextEpoch + waitForProven` + // cycle: the prover-node submits a proof as soon as the epoch is complete, so ~8x shorter + // epochs ≈ ~8x faster proof cadence per cycle. Setup itself stays slot-bound. + await t.setup({ ...PIPELINING_SETUP_OPTS, aztecProofSubmissionEpochs: 640, aztecEpochDuration: 4 }); await t.applyFPCSetup(); await t.applyFundAliceWithBananas(); ({ wallet, aliceAddress, bobAddress, sequencerAddress, bananaCoin, bananaFPC, gasSettings, aztecNode } = t);