diff --git a/yarn-project/end-to-end/src/bench/client_flows/account_deployments.test.ts b/yarn-project/end-to-end/src/bench/client_flows/account_deployments.test.ts index e6e888183b8a..d73eb358f7de 100644 --- a/yarn-project/end-to-end/src/bench/client_flows/account_deployments.test.ts +++ b/yarn-project/end-to-end/src/bench/client_flows/account_deployments.test.ts @@ -26,8 +26,8 @@ describe('Deployment benchmark', () => { let userWallet: TestWallet; beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyDeploySponsoredFPCSnapshot(); + await t.setupBasicContracts(); + await t.deploySponsoredFPC(); ({ adminWallet, adminAddress, sponsoredFPC, userWallet } = await t.setup()); // Ensure the ECDSAR1 contract is already registered, to avoid benchmarking an extra call to the ContractClassRegistry // The typical interaction would be for a user to deploy an account contract that is already registered in the diff --git a/yarn-project/end-to-end/src/bench/client_flows/amm.test.ts b/yarn-project/end-to-end/src/bench/client_flows/amm.test.ts index 652c36dd536f..a8a6d4ce8306 100644 --- a/yarn-project/end-to-end/src/bench/client_flows/amm.test.ts +++ b/yarn-project/end-to-end/src/bench/client_flows/amm.test.ts @@ -44,12 +44,12 @@ describe('AMM benchmark', () => { const config = t.config.amm; beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyDeployBananaTokenSnapshot(); - await t.applyFPCSetupSnapshot(); - await t.applyDeployCandyBarTokenSnapshot(); - await t.applyDeployAmmSnapshot(); - await t.applyDeploySponsoredFPCSnapshot(); + await t.setupBasicContracts(); + await t.deployBananaToken(); + await t.setupFPC(); + await t.deployCandyBarToken(); + await t.deployAMM(); + await t.deploySponsoredFPC(); ({ adminWallet, userWallet, adminAddress, bananaFPC, bananaCoin, candyBarCoin, amm, liquidityToken, sponsoredFPC } = await t.setup()); }); diff --git a/yarn-project/end-to-end/src/bench/client_flows/bridging.test.ts b/yarn-project/end-to-end/src/bench/client_flows/bridging.test.ts index 91dc7632dd6b..10bd29af6912 100644 --- a/yarn-project/end-to-end/src/bench/client_flows/bridging.test.ts +++ b/yarn-project/end-to-end/src/bench/client_flows/bridging.test.ts @@ -29,10 +29,10 @@ describe('Bridging benchmark', () => { const config = t.config.bridging; beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyDeployBananaTokenSnapshot(); - await t.applyFPCSetupSnapshot(); - await t.applyDeploySponsoredFPCSnapshot(); + await t.setupBasicContracts(); + await t.deployBananaToken(); + await t.setupFPC(); + await t.deploySponsoredFPC(); ({ userWallet, bananaFPC, bananaCoin, adminAddress, sponsoredFPC } = await t.setup()); }); diff --git a/yarn-project/end-to-end/src/bench/client_flows/client_flows_benchmark.ts b/yarn-project/end-to-end/src/bench/client_flows/client_flows_benchmark.ts index abe8bb0d93ca..64e87c906cc2 100644 --- a/yarn-project/end-to-end/src/bench/client_flows/client_flows_benchmark.ts +++ b/yarn-project/end-to-end/src/bench/client_flows/client_flows_benchmark.ts @@ -1,11 +1,13 @@ import { AztecAddress } from '@aztec/aztec.js/addresses'; -import { FeeJuicePaymentMethodWithClaim } from '@aztec/aztec.js/fee'; -import { type FeePaymentMethod, PrivateFeePaymentMethod, SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee'; -import { type Logger, createLogger } from '@aztec/aztec.js/log'; -import type { AztecNode } from '@aztec/aztec.js/node'; +import { + FeeJuicePaymentMethodWithClaim, + type FeePaymentMethod, + PrivateFeePaymentMethod, + SponsoredFeePaymentMethod, +} from '@aztec/aztec.js/fee'; +import { createLogger } from '@aztec/aztec.js/log'; import type { Wallet } from '@aztec/aztec.js/wallet'; -import { CheatCodes } from '@aztec/aztec/testing'; -import { type DeployL1ContractsArgs, RollupContract, createExtendedL1Client, deployL1Contract } from '@aztec/ethereum'; +import { RollupContract, createExtendedL1Client, deployL1Contract } from '@aztec/ethereum'; import { ChainMonitor } from '@aztec/ethereum/test'; import { randomBytes } from '@aztec/foundation/crypto'; import { EthAddress } from '@aztec/foundation/eth-address'; @@ -24,13 +26,8 @@ import { GasSettings } from '@aztec/stdlib/gas'; import { deriveSigningKey } from '@aztec/stdlib/keys'; import { TestWallet } from '@aztec/test-wallet/server'; +import { BaseEndToEndTest } from '../../fixtures/base_end_to_end_test.js'; import { MNEMONIC } from '../../fixtures/fixtures.js'; -import { - type ISnapshotManager, - type SubsystemsContext, - createSnapshotManager, - deployAccounts, -} from '../../fixtures/snapshot_manager.js'; import { mintTokensToPrivate } from '../../fixtures/token_utils.js'; import { type SetupOptions, setupSponsoredFPC } from '../../fixtures/utils.js'; import { CrossChainTestHarness } from '../../shared/cross_chain_test_harness.js'; @@ -41,19 +38,16 @@ import { import { ProxyLogger } from './benchmark.js'; import { type ClientFlowsConfig, FULL_FLOWS_CONFIG, KEY_FLOWS_CONFIG } from './config.js'; -const { E2E_DATA_PATH: dataPath, BENCHMARK_CONFIG } = process.env; +const { BENCHMARK_CONFIG } = process.env; export type AccountType = 'ecdsar1' | 'schnorr'; export type FeePaymentMethodGetter = (wallet: Wallet, sender: AztecAddress) => Promise; export type BenchmarkingFeePaymentMethod = 'bridged_fee_juice' | 'private_fpc' | 'sponsored_fpc' | 'fee_juice'; -export class ClientFlowsBenchmark { - private snapshotManager: ISnapshotManager; +export class ClientFlowsBenchmark extends BaseEndToEndTest { + // Properties inherited from BaseEndToEndTest: + // - aztecNode, wallet, accounts, cheatCodes, deployL1ContractsValues, logger, context - public logger: Logger; - public aztecNode!: AztecNode; - public cheatCodes!: CheatCodes; - public context!: SubsystemsContext; public chainMonitor!: ChainMonitor; public feeJuiceBridgeTestHarness!: GasBridgingTestHarness; public adminWallet!: TestWallet; @@ -115,33 +109,29 @@ export class ClientFlowsBenchmark { public config: ClientFlowsConfig; private proxyLogger: ProxyLogger; + private setupOptions: Partial; - constructor(testName?: string, setupOptions: Partial = {}) { - this.logger = createLogger(`bench:client_flows${testName ? `:${testName}` : ''}`); - this.snapshotManager = createSnapshotManager( - `bench_client_flows${testName ? `/${testName}` : ''}`, - dataPath, - { startProverNode: true, ...setupOptions }, - { ...setupOptions }, - ); + constructor(testName?: string, setupOptions: Partial = {}) { + super(testName ?? 'client_flows', createLogger(`bench:client_flows${testName ? `:${testName}` : ''}`)); + this.setupOptions = setupOptions; this.config = BENCHMARK_CONFIG === 'key_flows' ? KEY_FLOWS_CONFIG : FULL_FLOWS_CONFIG; ProxyLogger.create(); this.proxyLogger = ProxyLogger.getInstance(); } - async setup() { - const context = await this.snapshotManager.setup(); - await context.aztecNode.setConfig({ feeRecipient: this.sequencerAddress, coinbase: this.coinbase }); + override async setup(): Promise { + await super.setup(2, { startProverNode: true, ...this.setupOptions }); + await this.aztecNode.setConfig({ feeRecipient: this.sequencerAddress, coinbase: this.coinbase }); - const rollupContract = RollupContract.getFromConfig(context.aztecNodeConfig); - this.chainMonitor = new ChainMonitor(rollupContract, context.dateProvider, this.logger, 200).start(); + const rollupContract = RollupContract.getFromConfig(this.context.config); + this.chainMonitor = new ChainMonitor(rollupContract, this.dateProvider!, this.logger, 200).start(); return this; } - async teardown() { + override async teardown() { await this.chainMonitor.stop(); - await this.snapshotManager.teardown(); + await super.teardown(); } async mintAndBridgeFeeJuice(address: AztecAddress) { @@ -183,137 +173,86 @@ export class ClientFlowsBenchmark { } } - public async applyBaseSnapshots() { - await this.applyInitialAccountsSnapshot(); - await this.applySetupFeeJuiceSnapshot(); + public async setupBasicContracts() { + await this.initializeAccounts(); + await this.setupFeeJuice(); } - async applyInitialAccountsSnapshot() { - await this.snapshotManager.snapshot( - 'initial_accounts', - deployAccounts(2, this.logger), - async ( - { deployedAccounts: [{ address: adminAddress }, { address: sequencerAddress }] }, - { wallet, aztecNode, cheatCodes }, - ) => { - this.adminWallet = wallet; - this.aztecNode = aztecNode; - this.cheatCodes = cheatCodes; - - this.adminAddress = adminAddress; - this.sequencerAddress = sequencerAddress; - - const canonicalFeeJuice = await getCanonicalFeeJuice(); - this.feeJuiceContract = await FeeJuiceContract.at(canonicalFeeJuice.address, this.adminWallet); - this.coinbase = EthAddress.random(); - - const userPXEConfig = getPXEConfig(); - const userPXEConfigWithContracts = { - ...userPXEConfig, - proverEnabled: this.realProofs, - } as PXEConfig; - - this.userWallet = await TestWallet.create(this.aztecNode, userPXEConfigWithContracts, { - loggers: { - prover: this.proxyLogger.createLogger('pxe:bb:wasm:bundle:proxied'), - }, - }); + async initializeAccounts() { + // Accounts are already deployed by setup() - just assign them + this.adminWallet = this.wallet; + this.adminAddress = this.accounts[0]; + this.sequencerAddress = this.accounts[1]; + + const canonicalFeeJuice = await getCanonicalFeeJuice(); + this.feeJuiceContract = await FeeJuiceContract.at(canonicalFeeJuice.address, this.adminWallet); + this.coinbase = EthAddress.random(); + + const userPXEConfig = getPXEConfig(); + const userPXEConfigWithContracts = { + ...userPXEConfig, + proverEnabled: this.realProofs, + } as PXEConfig; + + this.userWallet = await TestWallet.create(this.aztecNode, userPXEConfigWithContracts, { + loggers: { + prover: this.proxyLogger.createLogger('pxe:bb:wasm:bundle:proxied'), }, - ); + }); } - async applySetupFeeJuiceSnapshot() { - await this.snapshotManager.snapshot( - 'setup_fee_juice', - async () => {}, - async (_data, context) => { - this.context = context; - - this.feeJuiceContract = await FeeJuiceContract.at(ProtocolContractAddress.FeeJuice, this.adminWallet); - - this.feeJuiceBridgeTestHarness = await FeeJuicePortalTestingHarnessFactory.create({ - aztecNode: context.aztecNode, - aztecNodeAdmin: context.aztecNode, - l1Client: context.deployL1ContractsValues.l1Client, - wallet: this.adminWallet, - logger: this.logger, - }); - }, - ); + async setupFeeJuice() { + this.feeJuiceContract = await FeeJuiceContract.at(ProtocolContractAddress.FeeJuice, this.adminWallet); + + this.feeJuiceBridgeTestHarness = await FeeJuicePortalTestingHarnessFactory.create({ + aztecNode: this.aztecNode, + aztecNodeAdmin: this.aztecNode, + l1Client: this.deployL1ContractsValues.l1Client, + wallet: this.adminWallet, + logger: this.logger, + }); } - async applyDeployBananaTokenSnapshot() { - await this.snapshotManager.snapshot( - 'deploy_banana_token', - async () => { - const bananaCoin = await BananaCoin.deploy(this.adminWallet, this.adminAddress, 'BC', 'BC', 18n) - .send({ from: this.adminAddress }) - .deployed(); - this.logger.info(`BananaCoin deployed at ${bananaCoin.address}`); - return { bananaCoinAddress: bananaCoin.address }; - }, - async ({ bananaCoinAddress }) => { - this.bananaCoin = await BananaCoin.at(bananaCoinAddress, this.adminWallet); - }, - ); + async deployBananaToken() { + const bananaCoin = await BananaCoin.deploy(this.adminWallet, this.adminAddress, 'BC', 'BC', 18n) + .send({ from: this.adminAddress }) + .deployed(); + this.logger.info(`BananaCoin deployed at ${bananaCoin.address}`); + this.bananaCoin = await BananaCoin.at(bananaCoin.address, this.adminWallet); } - async applyDeployCandyBarTokenSnapshot() { - await this.snapshotManager.snapshot( - 'deploy_candy_bar_token', - async () => { - const candyBarCoin = await TokenContract.deploy(this.adminWallet, this.adminAddress, 'CBC', 'CBC', 18n) - .send({ from: this.adminAddress }) - .deployed(); - this.logger.info(`CandyBarCoin deployed at ${candyBarCoin.address}`); - return { candyBarCoinAddress: candyBarCoin.address }; - }, - async ({ candyBarCoinAddress }) => { - this.candyBarCoin = await TokenContract.at(candyBarCoinAddress, this.adminWallet); - }, - ); + async deployCandyBarToken() { + const candyBarCoin = await TokenContract.deploy(this.adminWallet, this.adminAddress, 'CBC', 'CBC', 18n) + .send({ from: this.adminAddress }) + .deployed(); + this.logger.info(`CandyBarCoin deployed at ${candyBarCoin.address}`); + this.candyBarCoin = await TokenContract.at(candyBarCoin.address, this.adminWallet); } - public async applyFPCSetupSnapshot() { - await this.snapshotManager.snapshot( - 'fpc_setup', - async context => { - const feeJuiceContract = this.feeJuiceBridgeTestHarness.feeJuice; - expect((await context.wallet.getContractMetadata(feeJuiceContract.address)).isContractPublished).toBe(true); + public async setupFPC() { + const feeJuiceContract = this.feeJuiceBridgeTestHarness.feeJuice; + expect((await this.wallet.getContractMetadata(feeJuiceContract.address)).isContractPublished).toBe(true); - const bananaCoin = this.bananaCoin; - const bananaFPC = await FPCContract.deploy(this.adminWallet, bananaCoin.address, this.adminAddress) - .send({ from: this.adminAddress }) - .deployed(); + const bananaCoin = this.bananaCoin; + const bananaFPC = await FPCContract.deploy(this.adminWallet, bananaCoin.address, this.adminAddress) + .send({ from: this.adminAddress }) + .deployed(); - this.logger.info(`BananaPay deployed at ${bananaFPC.address}`); + this.logger.info(`BananaPay deployed at ${bananaFPC.address}`); - await this.feeJuiceBridgeTestHarness.bridgeFromL1ToL2(bananaFPC.address, this.adminAddress); + await this.feeJuiceBridgeTestHarness.bridgeFromL1ToL2(bananaFPC.address, this.adminAddress); - return { bananaFPCAddress: bananaFPC.address }; - }, - async data => { - this.bananaFPC = await FPCContract.at(data.bananaFPCAddress, this.adminWallet); - }, - ); + this.bananaFPC = await FPCContract.at(bananaFPC.address, this.adminWallet); } - async applyDeploySponsoredFPCSnapshot() { - await this.snapshotManager.snapshot( - 'deploy_sponsored_fpc', - async () => { - const sponsoredFPC = await setupSponsoredFPC(this.adminWallet); - this.logger.info(`SponsoredFPC at ${sponsoredFPC.address}`); - return { sponsoredFPCAddress: sponsoredFPC.address }; - }, - async ({ sponsoredFPCAddress }) => { - this.sponsoredFPC = await SponsoredFPCContract.at(sponsoredFPCAddress, this.adminWallet); - }, - ); + async deploySponsoredFPC() { + const sponsoredFPC = await setupSponsoredFPC(this.adminWallet); + this.logger.info(`SponsoredFPC at ${sponsoredFPC.address}`); + this.sponsoredFPC = await SponsoredFPCContract.at(sponsoredFPC.address, this.adminWallet); } public async createCrossChainTestHarness(owner: AztecAddress) { - const l1Client = createExtendedL1Client(this.context.aztecNodeConfig.l1RpcUrls, MNEMONIC); + const l1Client = createExtendedL1Client(this.context.config.l1RpcUrls, MNEMONIC); const underlyingERC20Address = await deployL1Contract(l1Client, TestERC20Abi, TestERC20Bytecode, [ 'Underlying', @@ -357,30 +296,23 @@ export class ClientFlowsBenchmark { return accountManager.address; } - public async applyDeployAmmSnapshot() { - await this.snapshotManager.snapshot( - 'deploy_amm', - async () => { - const liquidityToken = await TokenContract.deploy(this.adminWallet, this.adminAddress, 'LPT', 'LPT', 18n) - .send({ from: this.adminAddress }) - .deployed(); - const amm = await AMMContract.deploy( - this.adminWallet, - this.bananaCoin.address, - this.candyBarCoin.address, - liquidityToken.address, - ) - .send({ from: this.adminAddress }) - .deployed(); - this.logger.info(`AMM deployed at ${amm.address}`); - await liquidityToken.methods.set_minter(amm.address, true).send({ from: this.adminAddress }).wait(); - return { ammAddress: amm.address, liquidityTokenAddress: liquidityToken.address }; - }, - async ({ ammAddress, liquidityTokenAddress }) => { - this.liquidityToken = await TokenContract.at(liquidityTokenAddress, this.adminWallet); - this.amm = await AMMContract.at(ammAddress, this.adminWallet); - }, - ); + public async deployAMM() { + const liquidityToken = await TokenContract.deploy(this.adminWallet, this.adminAddress, 'LPT', 'LPT', 18n) + .send({ from: this.adminAddress }) + .deployed(); + const amm = await AMMContract.deploy( + this.adminWallet, + this.bananaCoin.address, + this.candyBarCoin.address, + liquidityToken.address, + ) + .send({ from: this.adminAddress }) + .deployed(); + this.logger.info(`AMM deployed at ${amm.address}`); + await liquidityToken.methods.set_minter(amm.address, true).send({ from: this.adminAddress }).wait(); + + this.liquidityToken = await TokenContract.at(liquidityToken.address, this.adminWallet); + this.amm = await AMMContract.at(amm.address, this.adminWallet); } public async getBridgedFeeJuicePaymentMethodForWallet(_wallet: Wallet, sender: AztecAddress) { diff --git a/yarn-project/end-to-end/src/bench/client_flows/deployments.test.ts b/yarn-project/end-to-end/src/bench/client_flows/deployments.test.ts index 9365ba0d843d..223177be59c9 100644 --- a/yarn-project/end-to-end/src/bench/client_flows/deployments.test.ts +++ b/yarn-project/end-to-end/src/bench/client_flows/deployments.test.ts @@ -25,8 +25,8 @@ describe('Deployment benchmark', () => { const config = t.config.deployments; beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyDeploySponsoredFPCSnapshot(); + await t.setupBasicContracts(); + await t.deploySponsoredFPC(); ({ aztecNode: node, sponsoredFPC, userWallet } = await t.setup()); }); diff --git a/yarn-project/end-to-end/src/bench/client_flows/transfers.test.ts b/yarn-project/end-to-end/src/bench/client_flows/transfers.test.ts index b996463a8d20..36c70e6a42aa 100644 --- a/yarn-project/end-to-end/src/bench/client_flows/transfers.test.ts +++ b/yarn-project/end-to-end/src/bench/client_flows/transfers.test.ts @@ -42,11 +42,11 @@ describe('Transfer benchmark', () => { const config = t.config.transfers; beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyDeployBananaTokenSnapshot(); - await t.applyFPCSetupSnapshot(); - await t.applyDeployCandyBarTokenSnapshot(); - await t.applyDeploySponsoredFPCSnapshot(); + await t.setupBasicContracts(); + await t.deployBananaToken(); + await t.setupFPC(); + await t.deployCandyBarToken(); + await t.deploySponsoredFPC(); ({ adminWallet, diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/access_control.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/access_control.test.ts index a6e58ab55c98..74bae3e0400d 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/access_control.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/access_control.test.ts @@ -6,7 +6,6 @@ describe('e2e_blacklist_token_contract access control', () => { const t = new BlacklistTokenContractTest('access_control'); beforeAll(async () => { - await t.applyBaseSnapshots(); await t.setup(); }); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts index 639f81bce6b6..ff3c2b662f6b 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts @@ -1,29 +1,18 @@ import { AztecAddress } from '@aztec/aztec.js/addresses'; import { computeSecretHash } from '@aztec/aztec.js/crypto'; import { Fr } from '@aztec/aztec.js/fields'; -import { type Logger, createLogger } from '@aztec/aztec.js/log'; -import type { AztecNode } from '@aztec/aztec.js/node'; +import { createLogger } from '@aztec/aztec.js/log'; import type { TxHash } from '@aztec/aztec.js/tx'; -import type { CheatCodes } from '@aztec/aztec/testing'; import type { TokenContract } from '@aztec/noir-contracts.js/Token'; import { TokenBlacklistContract } from '@aztec/noir-contracts.js/TokenBlacklist'; import { InvalidAccountContract } from '@aztec/noir-test-contracts.js/InvalidAccount'; -import type { SequencerClient } from '@aztec/sequencer-client'; -import type { TestWallet } from '@aztec/test-wallet/server'; import { jest } from '@jest/globals'; -import { - type ISnapshotManager, - type SubsystemsContext, - createSnapshotManager, - deployAccounts, - publicDeployAccounts, -} from '../fixtures/snapshot_manager.js'; +import { BaseEndToEndTest } from '../fixtures/base_end_to_end_test.js'; +import { ensureAccountContractsPublished } from '../fixtures/utils.js'; import { TokenSimulator } from '../simulators/token_simulator.js'; -const { E2E_DATA_PATH: dataPath } = process.env; - export class Role { private isAdmin = false; private isMinter = false; @@ -51,118 +40,84 @@ export class Role { } } -export class BlacklistTokenContractTest { +export class BlacklistTokenContractTest extends BaseEndToEndTest { // This value MUST match the same value that we have in the contract static CHANGE_ROLES_DELAY = 86400; - private snapshotManager: ISnapshotManager; - logger: Logger; - wallet!: TestWallet; asset!: TokenBlacklistContract; tokenSim!: TokenSimulator; badAccount!: InvalidAccountContract; - cheatCodes!: CheatCodes; - sequencer!: SequencerClient; - aztecNode!: AztecNode; adminAddress!: AztecAddress; otherAddress!: AztecAddress; blacklistedAddress!: AztecAddress; constructor(testName: string) { - this.logger = createLogger(`e2e:e2e_blacklist_token_contract:${testName}`); - this.snapshotManager = createSnapshotManager(`e2e_blacklist_token_contract/${testName}`, dataPath); + super(testName, createLogger(`e2e:e2e_blacklist_token_contract:${testName}`)); } async crossTimestampOfChange() { await this.cheatCodes.warpL2TimeAtLeastBy( - this.sequencer, + this.sequencer!, this.aztecNode, BlacklistTokenContractTest.CHANGE_ROLES_DELAY, ); } /** - * Adds two state shifts to snapshot manager. + * Sets up base state: * 1. Add 3 accounts. * 2. Publicly deploy accounts, deploy token contract and a "bad account". */ - async applyBaseSnapshots() { + async deployContracts() { // Adding a timeout of 2 minutes in here such that it is propagated to the underlying tests jest.setTimeout(120_000); - await this.snapshotManager.snapshot( - '3_accounts', - deployAccounts(3, this.logger), - ({ deployedAccounts }, { cheatCodes, aztecNode, sequencer, wallet }) => { - this.cheatCodes = cheatCodes; - this.aztecNode = aztecNode; - this.sequencer = sequencer; - this.wallet = wallet; - this.adminAddress = deployedAccounts[0].address; - this.otherAddress = deployedAccounts[1].address; - this.blacklistedAddress = deployedAccounts[2].address; - return Promise.resolve(); - }, + // Accounts are already deployed by setup() + this.adminAddress = this.accounts[0]; + this.otherAddress = this.accounts[1]; + this.blacklistedAddress = this.accounts[2]; + + // Public deploy accounts + this.logger.verbose(`Public deploy accounts...`); + await ensureAccountContractsPublished(this.wallet, [this.adminAddress, this.otherAddress, this.blacklistedAddress]); + + // Deploy token contract + this.logger.verbose(`Deploying TokenContract...`); + this.asset = await TokenBlacklistContract.deploy(this.wallet, this.adminAddress) + .send({ from: this.adminAddress }) + .deployed(); + this.logger.verbose(`Token deployed to ${this.asset.address}`); + + // Deploy bad account + this.logger.verbose(`Deploying bad account...`); + this.badAccount = await InvalidAccountContract.deploy(this.wallet).send({ from: this.adminAddress }).deployed(); + this.logger.verbose(`Deployed to ${this.badAccount.address}.`); + + await this.crossTimestampOfChange(); + + // Setup references + this.logger.verbose(`Token contract address: ${this.asset.address}`); + + this.tokenSim = new TokenSimulator( + this.asset as unknown as TokenContract, + this.wallet, + this.adminAddress, + this.logger, + [this.adminAddress, this.otherAddress, this.blacklistedAddress], ); - await this.snapshotManager.snapshot( - 'e2e_blacklist_token_contract', - async () => { - // Create the token contract state. - // Move this account thing to addAccounts above? - this.logger.verbose(`Public deploy accounts...`); - await publicDeployAccounts(this.wallet, [this.adminAddress, this.otherAddress, this.blacklistedAddress]); - - this.logger.verbose(`Deploying TokenContract...`); - this.asset = await TokenBlacklistContract.deploy(this.wallet, this.adminAddress) - .send({ from: this.adminAddress }) - .deployed(); - this.logger.verbose(`Token deployed to ${this.asset.address}`); - - this.logger.verbose(`Deploying bad account...`); - this.badAccount = await InvalidAccountContract.deploy(this.wallet).send({ from: this.adminAddress }).deployed(); - this.logger.verbose(`Deployed to ${this.badAccount.address}.`); - - await this.crossTimestampOfChange(); - - return { tokenContractAddress: this.asset.address, badAccountAddress: this.badAccount.address }; - }, - async ({ tokenContractAddress, badAccountAddress }) => { - // Restore the token contract state. - this.asset = await TokenBlacklistContract.at(tokenContractAddress, this.wallet); - this.logger.verbose(`Token contract address: ${this.asset.address}`); - - this.tokenSim = new TokenSimulator( - this.asset as unknown as TokenContract, - this.wallet, - this.adminAddress, - this.logger, - [this.adminAddress, this.otherAddress, this.blacklistedAddress], - ); - - this.badAccount = await InvalidAccountContract.at(badAccountAddress, this.wallet); - this.logger.verbose(`Bad account address: ${this.badAccount.address}`); - - expect(await this.asset.methods.get_roles(this.adminAddress).simulate({ from: this.adminAddress })).toEqual( - new Role().withAdmin().toNoirStruct(), - ); - }, - ); - } + this.logger.verbose(`Bad account address: ${this.badAccount.address}`); - async setup() { - await this.snapshotManager.setup(); + expect(await this.asset.methods.get_roles(this.adminAddress).simulate({ from: this.adminAddress })).toEqual( + new Role().withAdmin().toNoirStruct(), + ); } - snapshot = ( - name: string, - apply: (context: SubsystemsContext) => Promise, - restore: (snapshotData: T, context: SubsystemsContext) => Promise = () => Promise.resolve(), - ): Promise => this.snapshotManager.snapshot(name, apply, restore); - - async teardown() { - await this.snapshotManager.teardown(); + override async setup(): Promise { + await super.setup(3); + await this.deployContracts(); + return this; } async addPendingShieldNoteToPXE( @@ -186,71 +141,58 @@ export class BlacklistTokenContractTest { .simulate({ from: recipient }); } - async applyMintSnapshot() { - await this.snapshotManager.snapshot( - 'mint', - async () => { - const { asset } = this; - const amount = 10000n; - - const adminMinterRole = new Role().withAdmin().withMinter(); - await this.asset.methods - .update_roles(this.adminAddress, adminMinterRole.toNoirStruct()) - .send({ from: this.adminAddress }) - .wait(); - - const blacklistRole = new Role().withBlacklisted(); - await this.asset.methods - .update_roles(this.blacklistedAddress, blacklistRole.toNoirStruct()) - .send({ from: this.adminAddress }) - .wait(); - - await this.crossTimestampOfChange(); - - expect(await this.asset.methods.get_roles(this.adminAddress).simulate({ from: this.adminAddress })).toEqual( - adminMinterRole.toNoirStruct(), - ); - - this.logger.verbose(`Minting ${amount} publicly...`); - await asset.methods.mint_public(this.adminAddress, amount).send({ from: this.adminAddress }).wait(); - - this.logger.verbose(`Minting ${amount} privately...`); - const secret = Fr.random(); - const secretHash = await computeSecretHash(secret); - const receipt = await asset.methods.mint_private(amount, secretHash).send({ from: this.adminAddress }).wait(); - - await this.addPendingShieldNoteToPXE(asset, this.adminAddress, amount, secretHash, receipt.txHash); - const txClaim = asset.methods - .redeem_shield(this.adminAddress, amount, secret) - .send({ from: this.adminAddress }); - await txClaim.wait(); - this.logger.verbose(`Minting complete.`); - - return { amount }; - }, - async ({ amount }) => { - const { asset, tokenSim } = this; - tokenSim.mintPublic(this.adminAddress, amount); - - const publicBalance = await asset.methods - .balance_of_public(this.adminAddress) - .simulate({ from: this.adminAddress }); - this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`); - expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(this.adminAddress)); - - tokenSim.mintPrivate(this.adminAddress, amount); - const privateBalance = await asset.methods - .balance_of_private(this.adminAddress) - .simulate({ from: this.adminAddress }); - this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`); - expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(this.adminAddress)); - - const totalSupply = await asset.methods.total_supply().simulate({ from: this.adminAddress }); - this.logger.verbose(`Total supply: ${totalSupply}`); - expect(totalSupply).toEqual(tokenSim.totalSupply); - - return Promise.resolve(); - }, + async mintTokensAndSetupRoles() { + const { asset, tokenSim } = this; + const amount = 10000n; + + const adminMinterRole = new Role().withAdmin().withMinter(); + await this.asset.methods + .update_roles(this.adminAddress, adminMinterRole.toNoirStruct()) + .send({ from: this.adminAddress }) + .wait(); + + const blacklistRole = new Role().withBlacklisted(); + await this.asset.methods + .update_roles(this.blacklistedAddress, blacklistRole.toNoirStruct()) + .send({ from: this.adminAddress }) + .wait(); + + await this.crossTimestampOfChange(); + + expect(await this.asset.methods.get_roles(this.adminAddress).simulate({ from: this.adminAddress })).toEqual( + adminMinterRole.toNoirStruct(), ); + + this.logger.verbose(`Minting ${amount} publicly...`); + await asset.methods.mint_public(this.adminAddress, amount).send({ from: this.adminAddress }).wait(); + + this.logger.verbose(`Minting ${amount} privately...`); + const secret = Fr.random(); + const secretHash = await computeSecretHash(secret); + const receipt = await asset.methods.mint_private(amount, secretHash).send({ from: this.adminAddress }).wait(); + + await this.addPendingShieldNoteToPXE(asset, this.adminAddress, amount, secretHash, receipt.txHash); + const txClaim = asset.methods.redeem_shield(this.adminAddress, amount, secret).send({ from: this.adminAddress }); + await txClaim.wait(); + this.logger.verbose(`Minting complete.`); + + tokenSim.mintPublic(this.adminAddress, amount); + + const publicBalance = await asset.methods + .balance_of_public(this.adminAddress) + .simulate({ from: this.adminAddress }); + this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`); + expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(this.adminAddress)); + + tokenSim.mintPrivate(this.adminAddress, amount); + const privateBalance = await asset.methods + .balance_of_private(this.adminAddress) + .simulate({ from: this.adminAddress }); + this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`); + expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(this.adminAddress)); + + const totalSupply = await asset.methods.total_supply().simulate({ from: this.adminAddress }); + this.logger.verbose(`Total supply: ${totalSupply}`); + expect(totalSupply).toEqual(tokenSim.totalSupply); } } diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/burn.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/burn.test.ts index b37e45c9c951..6851d43e3688 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/burn.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/burn.test.ts @@ -9,9 +9,8 @@ describe('e2e_blacklist_token_contract burn', () => { let { asset, tokenSim, wallet, adminAddress, otherAddress, blacklistedAddress } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); // Beware that we are adding the wallet as minter here, which is very slow because it needs multiple blocks. - await t.applyMintSnapshot(); + await t.mintTokensAndSetupRoles(); await t.setup(); // Have to destructure again to ensure we have latest refs. ({ asset, tokenSim, wallet, adminAddress, otherAddress, blacklistedAddress } = t); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/minting.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/minting.test.ts index b1ab9f91e6f0..48758c57c3d3 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/minting.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/minting.test.ts @@ -10,9 +10,8 @@ describe('e2e_blacklist_token_contract mint', () => { let { asset, tokenSim, adminAddress, otherAddress, blacklistedAddress } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); // Beware that we are adding the admin as minter here, which is very slow because it needs multiple blocks. - await t.applyMintSnapshot(); + await t.mintTokensAndSetupRoles(); await t.setup(); // Have to destructure again to ensure we have latest refs. ({ asset, tokenSim, adminAddress, otherAddress, blacklistedAddress } = t); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/shielding.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/shielding.test.ts index 5d06522ebc9b..1c6db551afd7 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/shielding.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/shielding.test.ts @@ -9,8 +9,7 @@ describe('e2e_blacklist_token_contract shield + redeem_shield', () => { let { asset, tokenSim, wallet, adminAddress, otherAddress, blacklistedAddress } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyMintSnapshot(); // Beware that we are adding the admin as minter here + await t.mintTokensAndSetupRoles(); // Beware that we are adding the admin as minter here await t.setup(); // Have to destructure again to ensure we have latest refs. ({ asset, tokenSim, wallet, adminAddress, otherAddress, blacklistedAddress } = t); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_private.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_private.test.ts index 7970e60ad096..a5258a79c2fd 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_private.test.ts @@ -9,9 +9,8 @@ describe('e2e_blacklist_token_contract transfer private', () => { let { asset, tokenSim, wallet, adminAddress, otherAddress, blacklistedAddress } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); // Beware that we are adding the admin as minter here, which is very slow because it needs multiple blocks. - await t.applyMintSnapshot(); + await t.mintTokensAndSetupRoles(); await t.setup(); // Have to destructure again to ensure we have latest refs. ({ asset, tokenSim, wallet, adminAddress, otherAddress, blacklistedAddress } = t); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_public.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_public.test.ts index 98ff87f54b58..0fd1cde024f9 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_public.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_public.test.ts @@ -8,9 +8,8 @@ describe('e2e_blacklist_token_contract transfer public', () => { let { asset, tokenSim, wallet, adminAddress, otherAddress, blacklistedAddress } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); // Beware that we are adding the admin as minter here, which is very slow because it needs multiple blocks. - await t.applyMintSnapshot(); + await t.mintTokensAndSetupRoles(); await t.setup(); // Have to destructure again to ensure we have latest refs. ({ asset, tokenSim, wallet, adminAddress, otherAddress, blacklistedAddress } = t); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/unshielding.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/unshielding.test.ts index 534bf03ed6a5..fff72610c257 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/unshielding.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/unshielding.test.ts @@ -9,9 +9,8 @@ describe('e2e_blacklist_token_contract unshielding', () => { let { asset, tokenSim, wallet, adminAddress, otherAddress, blacklistedAddress } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); // Beware that we are adding the admin as minter here, which is very slow because it needs multiple blocks. - await t.applyMintSnapshot(); + await t.mintTokensAndSetupRoles(); await t.setup(); // Have to destructure again to ensure we have latest refs. ({ asset, tokenSim, wallet, adminAddress, otherAddress, blacklistedAddress } = t); diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts index c3017c32f048..2bc084cf1e91 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts @@ -1,47 +1,25 @@ import type { AztecNodeConfig } from '@aztec/aztec-node'; import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses'; -import { type Logger, createLogger } from '@aztec/aztec.js/log'; -import type { AztecNode } from '@aztec/aztec.js/node'; -import { CheatCodes } from '@aztec/aztec/testing'; -import { - type DeployL1ContractsArgs, - type DeployL1ContractsReturnType, - type ExtendedViemWalletClient, - createExtendedL1Client, - deployL1Contract, -} from '@aztec/ethereum'; +import { createLogger } from '@aztec/aztec.js/log'; +import { type ExtendedViemWalletClient, createExtendedL1Client, deployL1Contract } from '@aztec/ethereum'; import { InboxAbi, OutboxAbi, TestERC20Abi, TestERC20Bytecode } from '@aztec/l1-artifacts'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; import { TokenBridgeContract } from '@aztec/noir-contracts.js/TokenBridge'; -import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client'; -import type { TestWallet } from '@aztec/test-wallet/server'; import { getContract } from 'viem'; +import { BaseEndToEndTest } from '../fixtures/base_end_to_end_test.js'; import { MNEMONIC } from '../fixtures/fixtures.js'; -import { - type ISnapshotManager, - type SubsystemsContext, - createSnapshotManager, - deployAccounts, - publicDeployAccounts, -} from '../fixtures/snapshot_manager.js'; -import type { SetupOptions } from '../fixtures/utils.js'; +import { type SetupOptions, ensureAccountContractsPublished } from '../fixtures/utils.js'; import { CrossChainTestHarness } from '../shared/cross_chain_test_harness.js'; -const { E2E_DATA_PATH: dataPath } = process.env; +export class CrossChainMessagingTest extends BaseEndToEndTest { + // Properties inherited from BaseEndToEndTest: + // - aztecNode, wallet, cheatCodes, deployL1ContractsValues, logger -export class CrossChainMessagingTest { - private snapshotManager: ISnapshotManager; - logger: Logger; - aztecNode!: AztecNode; aztecNodeConfig!: AztecNodeConfig; - aztecNodeAdmin!: AztecNodeAdmin; - ctx!: SubsystemsContext; - l1Client!: ExtendedViemWalletClient | undefined; - wallet!: TestWallet; ownerAddress!: AztecAddress; user1Address!: AztecAddress; user2Address!: AztecAddress; @@ -52,127 +30,102 @@ export class CrossChainMessagingTest { inbox!: any; // GetContractReturnType | undefined; outbox!: any; // GetContractReturnType | undefined; - cheatCodes!: CheatCodes; - deployL1ContractsValues!: DeployL1ContractsReturnType; + private setupOptions: SetupOptions; - constructor(testName: string, opts: SetupOptions = {}, deployL1ContractsArgs: Partial = {}) { - this.logger = createLogger(`e2e:e2e_cross_chain_messaging:${testName}`); - this.snapshotManager = createSnapshotManager(`e2e_cross_chain_messaging/${testName}`, dataPath, opts, { - initialValidators: [], - ...deployL1ContractsArgs, - }); + // Expose ctx for backward compatibility with existing tests + get ctx() { + return this.context; + } + + constructor(testName: string, opts: SetupOptions = {}) { + super(testName, createLogger(`e2e:e2e_cross_chain_messaging:${testName}`)); + this.setupOptions = opts; } async assumeProven() { await this.cheatCodes.rollup.markAsProven(); } - async setup() { - this.ctx = await this.snapshotManager.setup(); - this.aztecNode = this.ctx.aztecNode; - this.wallet = this.ctx.wallet; - this.aztecNodeConfig = this.ctx.aztecNodeConfig; - this.cheatCodes = this.ctx.cheatCodes; - this.deployL1ContractsValues = this.ctx.deployL1ContractsValues; - this.aztecNodeAdmin = this.ctx.aztecNode; + override async setup(): Promise { + await super.setup(3, this.setupOptions); + this.aztecNodeConfig = this.context.config; + this.aztecNodeAdmin = this.context.aztecNodeAdmin; + await this.setupCrossChainInfrastructure(); + return this; } - snapshot = ( - name: string, - apply: (context: SubsystemsContext) => Promise, - restore: (snapshotData: T, context: SubsystemsContext) => Promise = () => Promise.resolve(), - ): Promise => this.snapshotManager.snapshot(name, apply, restore); + async setupCrossChainInfrastructure() { + // Accounts are already deployed by setup() - just assign them + [this.ownerAddress, this.user1Address, this.user2Address] = this.accounts.slice(0, 3); + + // Public deploy accounts + this.logger.verbose(`Public deploy accounts...`); + await ensureAccountContractsPublished(this.wallet, [this.ownerAddress, this.user1Address, this.user2Address]); + + // Create L1 client + this.l1Client = createExtendedL1Client(this.aztecNodeConfig.l1RpcUrls, MNEMONIC); + + // Deploy underlying ERC20 + const underlyingERC20Address = await deployL1Contract(this.l1Client, TestERC20Abi, TestERC20Bytecode, [ + 'Underlying', + 'UND', + this.l1Client.account.address, + ]).then(({ address }) => address); + + // Setup cross chain harness + this.logger.verbose(`Setting up cross chain harness...`); + this.crossChainTestHarness = await CrossChainTestHarness.new( + this.aztecNode, + this.l1Client, + this.wallet, + this.ownerAddress, + this.logger, + underlyingERC20Address, + ); - async teardown() { - await this.snapshotManager.teardown(); - } + this.logger.verbose(`L2 token deployed to: ${this.crossChainTestHarness.l2Token.address}`); - async applyBaseSnapshots() { - // Note that we are using the same `wallet`, `aztecNodeConfig` and `aztecNode` across all snapshots. - // This is to not have issues with different networks. - - await this.snapshotManager.snapshot( - '3_accounts', - deployAccounts(3, this.logger), - ({ deployedAccounts }, { wallet, aztecNodeConfig, aztecNode }) => { - [this.ownerAddress, this.user1Address, this.user2Address] = deployedAccounts.map(a => a.address); - this.wallet = wallet; - this.aztecNode = aztecNode; - this.aztecNodeConfig = aztecNodeConfig; - return Promise.resolve(); - }, - ); + // Get the cross chain context + const crossChainContext = this.crossChainTestHarness.toCrossChainContext(); - await this.snapshotManager.snapshot( - 'e2e_cross_chain_messaging', - async () => { - // Create the token contract state. - // Move this account thing to addAccounts above? - this.logger.verbose(`Public deploy accounts...`); - await publicDeployAccounts(this.wallet, [this.ownerAddress, this.user1Address, this.user2Address]); - - this.l1Client = createExtendedL1Client(this.aztecNodeConfig.l1RpcUrls, MNEMONIC); - - const underlyingERC20Address = await deployL1Contract(this.l1Client, TestERC20Abi, TestERC20Bytecode, [ - 'Underlying', - 'UND', - this.l1Client.account.address, - ]).then(({ address }) => address); - - this.logger.verbose(`Setting up cross chain harness...`); - this.crossChainTestHarness = await CrossChainTestHarness.new( - this.aztecNode, - this.l1Client, - this.wallet, - this.ownerAddress, - this.logger, - underlyingERC20Address, - ); - - this.logger.verbose(`L2 token deployed to: ${this.crossChainTestHarness.l2Token.address}`); - - return this.crossChainTestHarness.toCrossChainContext(); - }, - async crossChainContext => { - this.l2Token = await TokenContract.at(crossChainContext.l2Token, this.wallet); - this.l2Bridge = await TokenBridgeContract.at(crossChainContext.l2Bridge, this.wallet); - - // There is an issue with the reviver so we are getting strings sometimes. Working around it here. - this.ethAccount = EthAddress.fromString(crossChainContext.ethAccount.toString()); - const tokenPortalAddress = EthAddress.fromString(crossChainContext.tokenPortal.toString()); - - const l1Client = createExtendedL1Client(this.aztecNodeConfig.l1RpcUrls, MNEMONIC); - - const inbox = getContract({ - address: this.aztecNodeConfig.l1Contracts.inboxAddress.toString(), - abi: InboxAbi, - client: l1Client, - }); - const outbox = getContract({ - address: this.aztecNodeConfig.l1Contracts.outboxAddress.toString(), - abi: OutboxAbi, - client: l1Client, - }); - - this.crossChainTestHarness = new CrossChainTestHarness( - this.aztecNode, - this.logger, - this.l2Token, - this.l2Bridge, - this.ethAccount, - tokenPortalAddress, - crossChainContext.underlying, - l1Client, - this.aztecNodeConfig.l1Contracts, - this.wallet, - this.ownerAddress, - ); - - this.l1Client = l1Client; - this.inbox = inbox; - this.outbox = outbox; - }, + // Restore logic - setup contracts from context + this.l2Token = await TokenContract.at(crossChainContext.l2Token, this.wallet); + this.l2Bridge = await TokenBridgeContract.at(crossChainContext.l2Bridge, this.wallet); + + // There is an issue with the reviver so we are getting strings sometimes. Working around it here. + this.ethAccount = EthAddress.fromString(crossChainContext.ethAccount.toString()); + const tokenPortalAddress = EthAddress.fromString(crossChainContext.tokenPortal.toString()); + + const l1Client = createExtendedL1Client(this.aztecNodeConfig.l1RpcUrls, MNEMONIC); + + const inbox = getContract({ + address: this.aztecNodeConfig.l1Contracts.inboxAddress.toString(), + abi: InboxAbi, + client: l1Client, + }); + const outbox = getContract({ + address: this.aztecNodeConfig.l1Contracts.outboxAddress.toString(), + abi: OutboxAbi, + client: l1Client, + }); + + this.crossChainTestHarness = new CrossChainTestHarness( + this.aztecNode, + this.logger, + this.l2Token, + this.l2Bridge, + this.ethAccount, + tokenPortalAddress, + crossChainContext.underlying, + l1Client, + this.aztecNodeConfig.l1Contracts, + this.wallet, + this.ownerAddress, ); + + this.l1Client = l1Client; + this.inbox = inbox; + this.outbox = outbox; } } diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l1_to_l2.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l1_to_l2.test.ts index a5c09dbb3058..9d8d88619f26 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l1_to_l2.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l1_to_l2.test.ts @@ -26,12 +26,11 @@ describe('e2e_cross_chain_messaging l1_to_l2', () => { let testContract: TestContract; beforeEach(async () => { - t = new CrossChainMessagingTest( - 'l1_to_l2', - { minTxsPerBlock: 1 }, - { aztecProofSubmissionEpochs: 2, aztecEpochDuration: 4 }, - ); - await t.applyBaseSnapshots(); + t = new CrossChainMessagingTest('l1_to_l2', { + minTxsPerBlock: 1, + aztecProofSubmissionEpochs: 2, + aztecEpochDuration: 4, + }); await t.setup(); ({ logger: log, crossChainTestHarness, wallet, user1Address, aztecNode } = t); @@ -168,7 +167,7 @@ describe('e2e_cross_chain_messaging l1_to_l2', () => { // Stop proving const lastProven = await aztecNode.getBlockNumber(); log.warn(`Stopping proof submission at block ${lastProven} to allow drift`); - t.ctx.watcher.setIsMarkingAsProven(false); + t.ctx.watcher!.setIsMarkingAsProven(false); // Mine several blocks to ensure drift log.warn(`Mining blocks to allow drift`); @@ -210,14 +209,14 @@ describe('e2e_cross_chain_messaging l1_to_l2', () => { // On private, we simulate the tx locally and check that we get a missing message error, then we advance to the next block await expect(() => consume().simulate({ from: user1Address })).rejects.toThrow(/No L1 to L2 message found/); await tryAdvanceBlock(); - await t.ctx.watcher.markAsProven(); + await t.ctx.watcher!.markAsProven(); } else { // On public, we actually send the tx and check that it reverts due to the missing message. // This advances the block too as a side-effect. Note that we do not rely on a simulation since the cross chain messages // do not get added at the beginning of the block during node_simulatePublicCalls (maybe they should?). const { status } = await consume().send({ from: user1Address }).wait({ dontThrowOnRevert: true }); expect(status).toEqual(TxStatus.APP_LOGIC_REVERTED); - await t.ctx.watcher.markAsProven(); + await t.ctx.watcher!.markAsProven(); } }); diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l2_to_l1.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l2_to_l1.test.ts index fadb1b210d87..8f7adf1ac912 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l2_to_l1.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/l2_to_l1.test.ts @@ -34,9 +34,9 @@ describe('e2e_cross_chain_messaging l2_to_l1', () => { let contract: TestContract; beforeAll(async () => { - await t.applyBaseSnapshots(); await t.setup(); - ({ crossChainTestHarness, aztecNode, aztecNodeAdmin, wallet, user1Address } = t); + ({ crossChainTestHarness, aztecNode, wallet, user1Address } = t); + aztecNodeAdmin = t.aztecNodeAdmin!; msgSender = EthAddress.fromString(t.deployL1ContractsValues.l1Client.account.address); diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_failure_cases.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_failure_cases.test.ts index eb83ac773bef..20a9a9f5ec47 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_failure_cases.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_failure_cases.test.ts @@ -16,7 +16,6 @@ describe('e2e_cross_chain_messaging token_bridge_failure_cases', () => { let { crossChainTestHarness, ethAccount, l2Bridge, ownerAddress, user1Address, user2Address } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); await t.setup(); // Have to destructure again to ensure we have latest refs. ({ crossChainTestHarness, user1Address, user2Address, ownerAddress } = t); diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_private.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_private.test.ts index 8e051ed6d273..1f363c96bc6f 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_private.test.ts @@ -29,7 +29,6 @@ describe('e2e_cross_chain_messaging token_bridge_private', () => { let cheatCodes: CheatCodes; beforeEach(async () => { - await t.applyBaseSnapshots(); await t.setup(); // Have to destructure again to ensure we have latest refs. ({ crossChainTestHarness, ethAccount, aztecNode, logger, ownerAddress, l2Bridge, l2Token, wallet, user2Address } = diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_public.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_public.test.ts index 19352f322cac..290502db2565 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_public.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_public.test.ts @@ -11,7 +11,6 @@ describe('e2e_cross_chain_messaging token_bridge_public', () => { t; beforeEach(async () => { - await t.applyBaseSnapshots(); await t.setup(); // Have to destructure again to ensure we have latest refs. ({ crossChainTestHarness, wallet, user2Address } = t); diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts index 5c314e438735..62136b4aaf06 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts @@ -126,7 +126,7 @@ describe('e2e_deploy_contract deploy method', () => { }, 300_000); it('publicly deploys a contract in one tx and calls a public function on it later in the same block', async () => { - await t.aztecNodeAdmin.setConfig({ minTxsPerBlock: 2 }); + await t.aztecNodeAdmin!.setConfig({ minTxsPerBlock: 2 }); const owner = defaultAccountAddress; logger.debug('Initializing deploy method'); diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_test.ts index 51e703e84d7c..91fe29dcb753 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_test.ts @@ -3,47 +3,27 @@ import type { AztecAddress } from '@aztec/aztec.js/addresses'; import { type ContractBase, getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts'; import { Fr } from '@aztec/aztec.js/fields'; import type { PublicKeys } from '@aztec/aztec.js/keys'; -import { type Logger, createLogger } from '@aztec/aztec.js/log'; -import type { AztecNode } from '@aztec/aztec.js/node'; +import { createLogger } from '@aztec/aztec.js/log'; import type { Wallet } from '@aztec/aztec.js/wallet'; import type { StatefulTestContract } from '@aztec/noir-test-contracts.js/StatefulTest'; -import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client'; -import type { TestWallet } from '@aztec/test-wallet/server'; -import { type ISnapshotManager, createSnapshotManager, deployAccounts } from '../fixtures/snapshot_manager.js'; +import { BaseEndToEndTest } from '../fixtures/base_end_to_end_test.js'; -const { E2E_DATA_PATH: dataPath } = process.env; - -export class DeployTest { - private snapshotManager: ISnapshotManager; - public logger: Logger; - public wallet!: TestWallet; +export class DeployTest extends BaseEndToEndTest { public defaultAccountAddress!: AztecAddress; - public aztecNode!: AztecNode; - public aztecNodeAdmin!: AztecNodeAdmin; constructor(testName: string) { - this.logger = createLogger(`e2e:e2e_deploy_contract:${testName}`); - this.snapshotManager = createSnapshotManager(`e2e_deploy_contract/${testName}`, dataPath); + super(testName, createLogger(`e2e:e2e_deploy_contract:${testName}`)); } - async setup() { - await this.applyInitialAccountSnapshot(); - const context = await this.snapshotManager.setup(); - ({ aztecNode: this.aztecNode, wallet: this.wallet } = context); - this.aztecNodeAdmin = context.aztecNode; + override async setup() { + await super.setup(1); + this.initializeAccount(); return this; } - async teardown() { - await this.snapshotManager.teardown(); - } - - private async applyInitialAccountSnapshot() { - await this.snapshotManager.snapshot('initial_account', deployAccounts(1, this.logger), ({ deployedAccounts }) => { - this.defaultAccountAddress = deployedAccounts[0].address; - return Promise.resolve(); - }); + private initializeAccount() { + this.defaultAccountAddress = this.accounts[0]; } async registerContract( diff --git a/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts b/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts index 0d77d87f2e6d..1067c666335f 100644 --- a/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts @@ -25,10 +25,10 @@ describe('e2e_fees account_init', () => { const t = new FeesTest('account_init', 1); beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyFundAliceWithBananas(); - await t.applyFPCSetupSnapshot(); - ({ aliceAddress, wallet, bananaCoin, bananaFPC, logger, aztecNode } = await t.setup()); + ({ aliceAddress, wallet, bananaCoin, logger, aztecNode } = await t.setup()); + await t.fundAliceWithBananas(); + await t.setupFPC(); + ({ bananaFPC } = t); }); afterAll(async () => { diff --git a/yarn-project/end-to-end/src/e2e_fees/bridging_race.notest.ts b/yarn-project/end-to-end/src/e2e_fees/bridging_race.notest.ts index edf44b1b4055..a840068b0b83 100644 --- a/yarn-project/end-to-end/src/e2e_fees/bridging_race.notest.ts +++ b/yarn-project/end-to-end/src/e2e_fees/bridging_race.notest.ts @@ -26,9 +26,9 @@ describe('e2e_fees bridging_race', () => { }); beforeAll(async () => { - await t.applyInitialAccountsSnapshot(); - await t.applyPublicDeployAccountsSnapshot(); - await t.applySetupFeeJuiceSnapshot(); + await t.initializeAccounts(); + await t.publishAccountContracts(); + await t.setupFeeJuice(); ({ wallet, logger } = await t.setup()); }); 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 869d6e6df1ba..0d7d67ae3e6f 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 @@ -28,13 +28,13 @@ describe('e2e_fees failures', () => { const t = new FeesTest('failures', 3, { coinbase }); beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyFPCSetupSnapshot(); - ({ wallet, aliceAddress, sequencerAddress, bananaCoin, bananaFPC, gasSettings } = await t.setup()); + ({ wallet, aliceAddress, sequencerAddress, bananaCoin, gasSettings } = await t.setup()); + await t.setupFPC(); + ({ bananaFPC } = t); // Prove up until the current state by just marking it as proven. // Then turn off the watcher to prevent it from keep proving - await t.context.watcher.trigger(); + await t.context.watcher!.trigger(); await t.cheatCodes.rollup.advanceToNextEpoch(); await t.catchUpProvenChain(); t.setIsMarkingAsProven(false); @@ -78,7 +78,7 @@ describe('e2e_fees failures', () => { await expectMapping(t.getGasBalanceFn, [aliceAddress, bananaFPC.address], [initialAliceGas, initialFPCGas]); // We wait until the proven chain is caught up so all previous fees are paid out. - await t.context.watcher.trigger(); + await t.context.watcher!.trigger(); await t.cheatCodes.rollup.advanceToNextEpoch(); await t.catchUpProvenChain(); @@ -100,7 +100,7 @@ describe('e2e_fees failures', () => { // @note There is a potential race condition here if other tests send transactions that get into the same // epoch and thereby pays out fees at the same time (when proven). - await t.context.watcher.trigger(); + await t.context.watcher!.trigger(); await t.cheatCodes.rollup.advanceToNextEpoch(); await t.catchUpProvenChain(); diff --git a/yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts b/yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts index 8b3391445f36..9a966a63e3ac 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts @@ -20,9 +20,8 @@ describe('e2e_fees Fee Juice payments', () => { const t = new FeesTest('fee_juice', 1); beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyFundAliceWithBananas(); ({ feeJuiceContract, aliceAddress, wallet, bananaCoin, gasSettings } = await t.setup()); + await t.fundAliceWithBananas(); const [bob] = await generateSchnorrAccounts(1); const bobsAccountManager = await wallet.createAccount({ diff --git a/yarn-project/end-to-end/src/e2e_fees/fee_settings.test.ts b/yarn-project/end-to-end/src/e2e_fees/fee_settings.test.ts index 23ebdfe8a9af..9433fb1efdac 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fee_settings.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fee_settings.test.ts @@ -24,8 +24,6 @@ describe('e2e_fees fee settings', () => { const t = new FeesTest('fee_juice', 1); beforeAll(async () => { - await t.applyBaseSnapshots(); - ({ aliceAddress, wallet, gasSettings, cheatCodes, aztecNode } = await t.setup()); testContract = await TestContract.deploy(wallet).send({ from: aliceAddress }).deployed(); diff --git a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts index ed25fc4a1dd8..d10833f72658 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts @@ -1,7 +1,5 @@ import type { AztecAddress } from '@aztec/aztec.js/addresses'; -import { type Logger, createLogger } from '@aztec/aztec.js/log'; -import type { AztecNode } from '@aztec/aztec.js/node'; -import { CheatCodes } from '@aztec/aztec/testing'; +import { createLogger } from '@aztec/aztec.js/log'; import { type DeployL1ContractsArgs, RollupContract, createExtendedL1Client } from '@aztec/ethereum'; import { ChainMonitor } from '@aztec/ethereum/test'; import { EthAddress } from '@aztec/foundation/eth-address'; @@ -16,17 +14,11 @@ import { CounterContract } from '@aztec/noir-test-contracts.js/Counter'; import { ProtocolContractAddress } from '@aztec/protocol-contracts'; import { getCanonicalFeeJuice } from '@aztec/protocol-contracts/fee-juice'; import { GasSettings } from '@aztec/stdlib/gas'; -import { TestWallet } from '@aztec/test-wallet/server'; import { getContract } from 'viem'; +import { BaseEndToEndTest } from '../fixtures/base_end_to_end_test.js'; import { MNEMONIC } from '../fixtures/fixtures.js'; -import { - type ISnapshotManager, - type SubsystemsContext, - createSnapshotManager, - deployAccounts, -} from '../fixtures/snapshot_manager.js'; import { mintTokensToPrivate } from '../fixtures/token_utils.js'; import { type BalancesFn, @@ -37,10 +29,8 @@ import { } from '../fixtures/utils.js'; import { FeeJuicePortalTestingHarnessFactory, type GasBridgingTestHarness } from '../shared/gas_portal_test_harness.js'; -const { E2E_DATA_PATH: dataPath } = process.env; - /** - * Test fixture for testing fees. Provides the following snapshots: + * Test fixture for testing fees. Provides the following setup steps: * InitialAccounts: Initializes 3 Schnorr account contracts. * PublicDeployAccounts: Deploys the accounts publicly. * DeployFeeJuice: Deploys the Fee Juice contract. @@ -49,15 +39,7 @@ const { E2E_DATA_PATH: dataPath } = process.env; * FundAlice: Mints private and public bananas to Alice. * SetupSubscription: Deploys a counter contract and a subscription contract, and mints Fee Juice to the subscription contract. */ -export class FeesTest { - private snapshotManager: ISnapshotManager; - private accounts: AztecAddress[] = []; - - public logger: Logger; - public aztecNode!: AztecNode; - public cheatCodes!: CheatCodes; - - public wallet!: TestWallet; +export class FeesTest extends BaseEndToEndTest { public aliceAddress!: AztecAddress; public bobAddress!: AztecAddress; public sequencerAddress!: AztecAddress; @@ -77,7 +59,6 @@ export class FeesTest { public subscriptionContract!: AppSubscriptionContract; public feeJuiceBridgeTestHarness!: GasBridgingTestHarness; - public context!: SubsystemsContext; public chainMonitor!: ChainMonitor; public getCoinbaseBalance!: () => Promise; @@ -91,41 +72,41 @@ export class FeesTest { public readonly SUBSCRIPTION_AMOUNT = BigInt(1e19); public readonly APP_SPONSORED_TX_GAS_LIMIT = BigInt(10e9); + private setupOptions: Partial; + constructor( testName: string, private numberOfAccounts = 3, setupOptions: Partial = {}, ) { + super(testName, createLogger(`e2e:e2e_fees:${testName}`)); if (!numberOfAccounts) { throw new Error('There must be at least 1 initial account.'); } setupOptions.coinbase ??= EthAddress.random(); this.coinbase = setupOptions.coinbase!; - this.logger = createLogger(`e2e:e2e_fees:${testName}`); - this.snapshotManager = createSnapshotManager( - `e2e_fees/${testName}-${numberOfAccounts}`, - dataPath, - { startProverNode: true, ...setupOptions }, - { ...setupOptions }, - ); + setupOptions.startProverNode = true; + this.setupOptions = setupOptions; } - async setup() { - const context = await this.snapshotManager.setup(); + override async setup() { + await super.setup(this.numberOfAccounts, this.setupOptions); + + this.rollupContract = RollupContract.getFromConfig(this.context.config); + this.chainMonitor = new ChainMonitor(this.rollupContract, this.dateProvider!, this.logger, 200).start(); - this.rollupContract = RollupContract.getFromConfig(context.aztecNodeConfig); - this.chainMonitor = new ChainMonitor(this.rollupContract, context.dateProvider, this.logger, 200).start(); + await this.setupBasicContracts(); return this; } - async teardown() { - await this.chainMonitor.stop(); - await this.snapshotManager.teardown(); + override async teardown() { + await this.chainMonitor?.stop(); + await super.teardown(); } setIsMarkingAsProven(b: boolean) { - this.context.watcher.setIsMarkingAsProven(b); + this.context.watcher!.setIsMarkingAsProven(b); } async catchUpProvenChain() { @@ -173,206 +154,145 @@ export class FeesTest { expect(balanceAfter).toEqual(balanceBefore + amount); } - public async applyBaseSnapshots() { - await this.applyInitialAccountsSnapshot(); - await this.applyPublicDeployAccountsSnapshot(); - await this.applySetupFeeJuiceSnapshot(); - await this.applyDeployBananaTokenSnapshot(); + public async setupBasicContracts() { + await this.initializeAccounts(); + await this.publishAccountContracts(); + await this.setupFeeJuice(); + await this.deployBananaToken(); } - async applyInitialAccountsSnapshot() { - await this.snapshotManager.snapshot( - 'initial_accounts', - deployAccounts(this.numberOfAccounts, this.logger), - async ({ deployedAccounts }, { wallet, aztecNode, cheatCodes }) => { - this.wallet = wallet; - this.aztecNode = aztecNode; - this.gasSettings = GasSettings.default({ maxFeesPerGas: (await this.aztecNode.getCurrentBaseFees()).mul(2) }); - this.cheatCodes = cheatCodes; - this.accounts = deployedAccounts.map(a => a.address); - this.accounts.forEach((a, i) => this.logger.verbose(`Account ${i} address: ${a}`)); - [this.aliceAddress, this.bobAddress, this.sequencerAddress] = this.accounts.slice(0, 3); - - // We set Alice as the FPC admin to avoid the need for deployment of another account. - this.fpcAdmin = this.aliceAddress; - - const canonicalFeeJuice = await getCanonicalFeeJuice(); - this.feeJuiceContract = await FeeJuiceContract.at(canonicalFeeJuice.address, this.wallet); - }, - ); + async initializeAccounts() { + // Accounts are already deployed by setup(), just initialize the addresses + this.gasSettings = GasSettings.default({ maxFeesPerGas: (await this.aztecNode.getCurrentBaseFees()).mul(2) }); + this.accounts.forEach((a, i) => this.logger.verbose(`Account ${i} address: ${a}`)); + [this.aliceAddress, this.bobAddress, this.sequencerAddress] = this.accounts.slice(0, 3); + + // We set Alice as the FPC admin to avoid the need for deployment of another account. + this.fpcAdmin = this.aliceAddress; + + const canonicalFeeJuice = await getCanonicalFeeJuice(); + this.feeJuiceContract = await FeeJuiceContract.at(canonicalFeeJuice.address, this.wallet); } - async applyPublicDeployAccountsSnapshot() { - await this.snapshotManager.snapshot('public_deploy_accounts', () => - ensureAccountContractsPublished(this.wallet, this.accounts), - ); + async publishAccountContracts() { + await ensureAccountContractsPublished(this.wallet, this.accounts); } - async applySetupFeeJuiceSnapshot() { - await this.snapshotManager.snapshot( - 'setup_fee_juice', - async () => {}, - async (_data, context) => { - this.context = context; - - this.feeJuiceContract = await FeeJuiceContract.at(ProtocolContractAddress.FeeJuice, this.wallet); - - this.getGasBalanceFn = getBalancesFn( - '⛽', - this.feeJuiceContract.methods.balance_of_public, - this.aliceAddress, - this.logger, - ); - - this.feeJuiceBridgeTestHarness = await FeeJuicePortalTestingHarnessFactory.create({ - aztecNode: context.aztecNode, - aztecNodeAdmin: context.aztecNode, - l1Client: context.deployL1ContractsValues.l1Client, - wallet: this.wallet, - logger: this.logger, - }); - }, + async setupFeeJuice() { + this.feeJuiceContract = await FeeJuiceContract.at(ProtocolContractAddress.FeeJuice, this.wallet); + + this.getGasBalanceFn = getBalancesFn( + '⛽', + this.feeJuiceContract.methods.balance_of_public, + this.aliceAddress, + this.logger, ); + + this.feeJuiceBridgeTestHarness = await FeeJuicePortalTestingHarnessFactory.create({ + aztecNode: this.aztecNode, + aztecNodeAdmin: this.aztecNodeAdmin!, + l1Client: this.deployL1ContractsValues.l1Client, + wallet: this.wallet, + logger: this.logger, + }); } - async applyDeployBananaTokenSnapshot() { - await this.snapshotManager.snapshot( - 'deploy_banana_token', - async () => { - const bananaCoin = await BananaCoin.deploy(this.wallet, this.aliceAddress, 'BC', 'BC', 18n) - .send({ from: this.aliceAddress }) - .deployed(); - this.logger.info(`BananaCoin deployed at ${bananaCoin.address}`); - return { bananaCoinAddress: bananaCoin.address }; - }, - async ({ bananaCoinAddress }) => { - this.bananaCoin = await BananaCoin.at(bananaCoinAddress, this.wallet); - const logger = this.logger; - this.getBananaPublicBalanceFn = getBalancesFn( - '🍌.public', - this.bananaCoin.methods.balance_of_public, - this.aliceAddress, - logger, - ); - this.getBananaPrivateBalanceFn = getBalancesFn( - '🍌.private', - this.bananaCoin.methods.balance_of_private, - this.aliceAddress, - logger, - ); - }, + async deployBananaToken() { + const bananaCoin = await BananaCoin.deploy(this.wallet, this.aliceAddress, 'BC', 'BC', 18n) + .send({ from: this.aliceAddress }) + .deployed(); + this.logger.info(`BananaCoin deployed at ${bananaCoin.address}`); + + this.bananaCoin = await BananaCoin.at(bananaCoin.address, this.wallet); + this.getBananaPublicBalanceFn = getBalancesFn( + '🍌.public', + this.bananaCoin.methods.balance_of_public, + this.aliceAddress, + this.logger, + ); + this.getBananaPrivateBalanceFn = getBalancesFn( + '🍌.private', + this.bananaCoin.methods.balance_of_private, + this.aliceAddress, + this.logger, ); } - public async applyFPCSetupSnapshot() { - await this.snapshotManager.snapshot( - 'fpc_setup', - async context => { - const feeJuiceContract = this.feeJuiceBridgeTestHarness.feeJuice; - expect((await context.wallet.getContractMetadata(feeJuiceContract.address)).isContractPublished).toBe(true); - - const bananaCoin = this.bananaCoin; - const bananaFPC = await FPCContract.deploy(this.wallet, bananaCoin.address, this.fpcAdmin) - .send({ from: this.aliceAddress }) - .deployed(); - - this.logger.info(`BananaPay deployed at ${bananaFPC.address}`); - - await this.feeJuiceBridgeTestHarness.bridgeFromL1ToL2(bananaFPC.address, this.aliceAddress); - - return { - bananaFPCAddress: bananaFPC.address, - feeJuiceAddress: feeJuiceContract.address, - l1FeeJuiceAddress: this.feeJuiceBridgeTestHarness.l1FeeJuiceAddress, - rollupAddress: context.deployL1ContractsValues.l1ContractAddresses.rollupAddress, - }; - }, - async (data, context) => { - const bananaFPC = await FPCContract.at(data.bananaFPCAddress, this.wallet); - this.bananaFPC = bananaFPC; - - this.getCoinbaseBalance = async () => { - const l1Client = createExtendedL1Client(context.aztecNodeConfig.l1RpcUrls, MNEMONIC); - const gasL1 = getContract({ - address: data.l1FeeJuiceAddress.toString(), - abi: TestERC20Abi, - client: l1Client, - }); - return await gasL1.read.balanceOf([this.coinbase.toString()]); - }; - - this.getCoinbaseSequencerRewards = async () => { - return await this.rollupContract.getSequencerRewards(this.coinbase); - }; - - this.getProverFee = async (blockNumber: number) => { - const block = await this.aztecNode.getBlock(blockNumber); - - // @todo @lherskind As we deal with #13601 - // Right now the value is from `FeeLib.sol` - const L1_GAS_PER_EPOCH_VERIFIED = 1000000n; - - // We round up - const mulDiv = (a: bigint, b: bigint, c: bigint) => (a * b) / c + ((a * b) % c > 0n ? 1n : 0n); - - const { baseFee } = await this.rollupContract.getL1FeesAt(block!.header.globalVariables.timestamp); - const proverCost = - mulDiv( - mulDiv(L1_GAS_PER_EPOCH_VERIFIED, baseFee, await this.rollupContract.getEpochDuration()), - 1n, - await this.rollupContract.getManaTarget(), - ) + (await this.rollupContract.getProvingCostPerMana()); - - const price = await this.rollupContract.getFeeAssetPerEth(); - - const mana = block!.header.totalManaUsed.toBigInt(); - return mulDiv(mana * proverCost, price, 10n ** 9n); - }; - }, - ); + public async setupFPC() { + const feeJuiceContract = this.feeJuiceBridgeTestHarness.feeJuice; + expect((await this.wallet.getContractMetadata(feeJuiceContract.address)).isContractPublished).toBe(true); + + const bananaCoin = this.bananaCoin; + const bananaFPC = await FPCContract.deploy(this.wallet, bananaCoin.address, this.fpcAdmin) + .send({ from: this.aliceAddress }) + .deployed(); + + this.logger.info(`BananaPay deployed at ${bananaFPC.address}`); + + await this.feeJuiceBridgeTestHarness.bridgeFromL1ToL2(bananaFPC.address, this.aliceAddress); + + this.bananaFPC = await FPCContract.at(bananaFPC.address, this.wallet); + + const l1FeeJuiceAddress = this.feeJuiceBridgeTestHarness.l1FeeJuiceAddress; + + this.getCoinbaseBalance = async () => { + const l1Client = createExtendedL1Client(this.context.config.l1RpcUrls, MNEMONIC); + const gasL1 = getContract({ + address: l1FeeJuiceAddress.toString(), + abi: TestERC20Abi, + client: l1Client, + }); + return await gasL1.read.balanceOf([this.coinbase.toString()]); + }; + + this.getCoinbaseSequencerRewards = async () => { + return await this.rollupContract.getSequencerRewards(this.coinbase); + }; + + this.getProverFee = async (blockNumber: number) => { + const block = await this.aztecNode.getBlock(blockNumber); + + // @todo @lherskind As we deal with #13601 + // Right now the value is from `FeeLib.sol` + const L1_GAS_PER_EPOCH_VERIFIED = 1000000n; + + // We round up + const mulDiv = (a: bigint, b: bigint, c: bigint) => (a * b) / c + ((a * b) % c > 0n ? 1n : 0n); + + const { baseFee } = await this.rollupContract.getL1FeesAt(block!.header.globalVariables.timestamp); + const proverCost = + mulDiv( + mulDiv(L1_GAS_PER_EPOCH_VERIFIED, baseFee, await this.rollupContract.getEpochDuration()), + 1n, + await this.rollupContract.getManaTarget(), + ) + (await this.rollupContract.getProvingCostPerMana()); + + const price = await this.rollupContract.getFeeAssetPerEth(); + + const mana = block!.header.totalManaUsed.toBigInt(); + return mulDiv(mana * proverCost, price, 10n ** 9n); + }; } - public async applySponsoredFPCSetupSnapshot() { - await this.snapshotManager.snapshot( - 'sponsored_fpc_setup', - async context => { - const feeJuiceContract = this.feeJuiceBridgeTestHarness.feeJuice; - expect((await context.wallet.getContractMetadata(feeJuiceContract.address)).isContractPublished).toBe(true); - - const sponsoredFPC = await setupSponsoredFPC(this.wallet); - this.logger.info(`SponsoredFPC at ${sponsoredFPC.address}`); - - return { - sponsoredFPCAddress: sponsoredFPC.address, - }; - }, - async data => { - this.sponsoredFPC = await SponsoredFPCContract.at(data.sponsoredFPCAddress, this.wallet); - }, - ); + public async setupSponsoredFPC() { + const feeJuiceContract = this.feeJuiceBridgeTestHarness.feeJuice; + expect((await this.wallet.getContractMetadata(feeJuiceContract.address)).isContractPublished).toBe(true); + + const sponsoredFPC = await setupSponsoredFPC(this.wallet); + this.logger.info(`SponsoredFPC at ${sponsoredFPC.address}`); + + this.sponsoredFPC = await SponsoredFPCContract.at(sponsoredFPC.address, this.wallet); } - public async applyFundAliceWithBananas() { - await this.snapshotManager.snapshot( - 'fund_alice', - async () => { - await this.mintPrivateBananas(this.ALICE_INITIAL_BANANAS, this.aliceAddress); - await this.bananaCoin.methods - .mint_to_public(this.aliceAddress, this.ALICE_INITIAL_BANANAS) - .send({ from: this.aliceAddress }) - .wait(); - }, - () => Promise.resolve(), - ); + public async fundAliceWithBananas() { + await this.mintPrivateBananas(this.ALICE_INITIAL_BANANAS, this.aliceAddress); + await this.bananaCoin.methods + .mint_to_public(this.aliceAddress, this.ALICE_INITIAL_BANANAS) + .send({ from: this.aliceAddress }) + .wait(); } - public async applyFundAliceWithPrivateBananas() { - await this.snapshotManager.snapshot( - 'fund_alice_with_private_bananas', - async () => { - await this.mintPrivateBananas(this.ALICE_INITIAL_BANANAS, this.aliceAddress); - }, - () => Promise.resolve(), - ); + public async fundAliceWithPrivateBananas() { + await this.mintPrivateBananas(this.ALICE_INITIAL_BANANAS, this.aliceAddress); } } diff --git a/yarn-project/end-to-end/src/e2e_fees/gas_estimation.test.ts b/yarn-project/end-to-end/src/e2e_fees/gas_estimation.test.ts index c58c945d26f7..5d76e518878b 100644 --- a/yarn-project/end-to-end/src/e2e_fees/gas_estimation.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/gas_estimation.test.ts @@ -32,10 +32,10 @@ describe('e2e_fees gas_estimation', () => { const t = new FeesTest('gas_estimation'); beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyFPCSetupSnapshot(); - await t.applyFundAliceWithBananas(); - ({ wallet, aliceAddress, bobAddress, bananaCoin, bananaFPC, gasSettings, logger, aztecNode } = await t.setup()); + ({ wallet, aliceAddress, bobAddress, bananaCoin, gasSettings, logger, aztecNode } = await t.setup()); + await t.setupFPC(); + await t.fundAliceWithBananas(); + ({ bananaFPC } = t); }); beforeEach(async () => { 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 b2259ae710da..e71ca0617b90 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 @@ -25,11 +25,10 @@ describe('e2e_fees private_payment', () => { const t = new FeesTest('private_payment'); beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyFPCSetupSnapshot(); - await t.applyFundAliceWithBananas(); - ({ wallet, aliceAddress, bobAddress, sequencerAddress, bananaCoin, bananaFPC, gasSettings, aztecNode } = - await t.setup()); + ({ wallet, aliceAddress, bobAddress, sequencerAddress, bananaCoin, gasSettings, aztecNode } = await t.setup()); + await t.setupFPC(); + await t.fundAliceWithBananas(); + ({ bananaFPC } = t); // Prove up until the current state by just marking it as proven. // Then turn off the watcher to prevent it from keep proving diff --git a/yarn-project/end-to-end/src/e2e_fees/public_payments.test.ts b/yarn-project/end-to-end/src/e2e_fees/public_payments.test.ts index b9d8422a4ce2..e424d5925f8e 100644 --- a/yarn-project/end-to-end/src/e2e_fees/public_payments.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/public_payments.test.ts @@ -22,11 +22,10 @@ describe('e2e_fees public_payment', () => { const t = new FeesTest('public_payment'); beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyFPCSetupSnapshot(); - await t.applyFundAliceWithBananas(); - ({ wallet, aliceAddress, bobAddress, sequencerAddress, bananaCoin, bananaFPC, gasSettings, aztecNode } = - await t.setup()); + ({ wallet, aliceAddress, bobAddress, sequencerAddress, bananaCoin, gasSettings, aztecNode } = await t.setup()); + await t.setupFPC(); + await t.fundAliceWithBananas(); + ({ bananaFPC } = t); }); afterAll(async () => { diff --git a/yarn-project/end-to-end/src/e2e_fees/sponsored_payments.test.ts b/yarn-project/end-to-end/src/e2e_fees/sponsored_payments.test.ts index c2df86d90f07..43026eb097bb 100644 --- a/yarn-project/end-to-end/src/e2e_fees/sponsored_payments.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/sponsored_payments.test.ts @@ -20,11 +20,10 @@ describe('e2e_fees sponsored_public_payment', () => { const t = new FeesTest('sponsored_payment'); beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applySponsoredFPCSetupSnapshot(); - await t.applyFundAliceWithBananas(); - ({ aztecNode, aliceAddress, bobAddress, sequencerAddress, sponsoredFPC, bananaCoin, gasSettings } = - await t.setup()); + ({ aztecNode, aliceAddress, bobAddress, sequencerAddress, bananaCoin, gasSettings } = await t.setup()); + await t.setupSponsoredFPC(); + await t.fundAliceWithBananas(); + ({ sponsoredFPC } = t); }); afterAll(async () => { diff --git a/yarn-project/end-to-end/src/e2e_nested_contract/importer.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract/importer.test.ts index 6b0066f9ba90..4af04de2d7cf 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract/importer.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract/importer.test.ts @@ -10,7 +10,6 @@ describe('e2e_nested_contract manual', () => { let { wallet, logger, defaultAccountAddress } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); await t.setup(); ({ wallet, logger, defaultAccountAddress } = t); }); diff --git a/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_call.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_call.test.ts index e1ccaf248350..da70515d3336 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_call.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_call.test.ts @@ -5,8 +5,6 @@ describe('e2e_nested_contract manual', () => { let { parentContract, childContract, defaultAccountAddress } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyManualSnapshots(); await t.setup(); ({ parentContract, childContract, defaultAccountAddress } = t); }); diff --git a/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_enqueue.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_enqueue.test.ts index dc69a8a53156..15b472e29c0d 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_enqueue.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract/manual_private_enqueue.test.ts @@ -13,7 +13,6 @@ describe('e2e_nested_contract manual_enqueue', () => { aztecNode.getPublicStorageAt('latest', child.address, new Fr(1)); beforeAll(async () => { - await t.applyBaseSnapshots(); // We don't have the manual snapshot because every test requires a fresh setup and teardown await t.setup(); ({ wallet, defaultAccountAddress, aztecNode } = t); diff --git a/yarn-project/end-to-end/src/e2e_nested_contract/manual_public.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract/manual_public.test.ts index 122aaa2a8acd..c3ed1bf2e30b 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract/manual_public.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract/manual_public.test.ts @@ -14,8 +14,6 @@ describe('e2e_nested_contract manual', () => { aztecNode.getPublicStorageAt('latest', child.address, new Fr(1)); beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyManualSnapshots(); await t.setup(); ({ wallet, parentContract, childContract, defaultAccountAddress, aztecNode } = t); }); diff --git a/yarn-project/end-to-end/src/e2e_nested_contract/nested_contract_test.ts b/yarn-project/end-to-end/src/e2e_nested_contract/nested_contract_test.ts index 6a1dcdbaca23..3e17ae324abb 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract/nested_contract_test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract/nested_contract_test.ts @@ -1,26 +1,13 @@ import { AztecAddress } from '@aztec/aztec.js/addresses'; -import { type Logger, createLogger } from '@aztec/aztec.js/log'; -import type { AztecNode } from '@aztec/aztec.js/node'; -import type { Wallet } from '@aztec/aztec.js/wallet'; +import { createLogger } from '@aztec/aztec.js/log'; import { ChildContract } from '@aztec/noir-test-contracts.js/Child'; import { ParentContract } from '@aztec/noir-test-contracts.js/Parent'; -import { - type ISnapshotManager, - type SubsystemsContext, - createSnapshotManager, - deployAccounts, - publicDeployAccounts, -} from '../fixtures/snapshot_manager.js'; +import { BaseEndToEndTest } from '../fixtures/base_end_to_end_test.js'; +import { ensureAccountContractsPublished } from '../fixtures/utils.js'; -const { E2E_DATA_PATH: dataPath } = process.env; - -export class NestedContractTest { - private snapshotManager: ISnapshotManager; - logger: Logger; - wallet!: Wallet; +export class NestedContractTest extends BaseEndToEndTest { defaultAccountAddress!: AztecAddress; - aztecNode!: AztecNode; parentContract!: ParentContract; childContract!: ChildContract; @@ -29,67 +16,34 @@ export class NestedContractTest { testName: string, private numberOfAccounts = 1, ) { - this.logger = createLogger(`e2e:e2e_nested_contract:${testName}`); - this.snapshotManager = createSnapshotManager(`e2e_nested_contract/${testName}-${numberOfAccounts}`, dataPath); + super(testName, createLogger(`e2e:e2e_nested_contract:${testName}`)); } /** - * Adds two state shifts to snapshot manager. - * 1. Add 3 accounts. + * Sets up base state: + * 1. Add accounts. * 2. Publicly deploy accounts */ - async applyBaseSnapshots() { - await this.snapshotManager.snapshot( - 'accounts', - deployAccounts(this.numberOfAccounts, this.logger), - ({ deployedAccounts }, { wallet, aztecNode }) => { - this.wallet = wallet; - [{ address: this.defaultAccountAddress }] = deployedAccounts; - this.aztecNode = aztecNode; - return Promise.resolve(); - }, - ); - - await this.snapshotManager.snapshot( - 'public_deploy', - async () => {}, - async () => { - this.logger.verbose(`Public deploy accounts...`); - await publicDeployAccounts(this.wallet, [this.defaultAccountAddress]); - }, - ); - } + async publishAccountContracts() { + this.defaultAccountAddress = this.accounts[0]; - async setup() { - await this.snapshotManager.setup(); + this.logger.verbose(`Public deploy accounts...`); + await ensureAccountContractsPublished(this.wallet, [this.defaultAccountAddress]); } - async teardown() { - await this.snapshotManager.teardown(); + override async setup(): Promise { + await super.setup(this.numberOfAccounts); + await this.publishAccountContracts(); + return this; } - snapshot = ( - name: string, - apply: (context: SubsystemsContext) => Promise, - restore: (snapshotData: T, context: SubsystemsContext) => Promise = () => Promise.resolve(), - ): Promise => this.snapshotManager.snapshot(name, apply, restore); + async deployContracts() { + const parentContract = await ParentContract.deploy(this.wallet) + .send({ from: this.defaultAccountAddress }) + .deployed(); + const childContract = await ChildContract.deploy(this.wallet).send({ from: this.defaultAccountAddress }).deployed(); - async applyManualSnapshots() { - await this.snapshotManager.snapshot( - 'manual', - async () => { - const parentContract = await ParentContract.deploy(this.wallet) - .send({ from: this.defaultAccountAddress }) - .deployed(); - const childContract = await ChildContract.deploy(this.wallet) - .send({ from: this.defaultAccountAddress }) - .deployed(); - return { parentContractAddress: parentContract.address, childContractAddress: childContract.address }; - }, - async ({ parentContractAddress, childContractAddress }) => { - this.parentContract = await ParentContract.at(parentContractAddress, this.wallet); - this.childContract = await ChildContract.at(childContractAddress, this.wallet); - }, - ); + this.parentContract = await ParentContract.at(parentContract.address, this.wallet); + this.childContract = await ChildContract.at(childContract.address, this.wallet); } } diff --git a/yarn-project/end-to-end/src/e2e_p2p/add_rollup.test.ts b/yarn-project/end-to-end/src/e2e_p2p/add_rollup.test.ts index 58fbbe8e92dc..a2300a18c7f5 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/add_rollup.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/add_rollup.test.ts @@ -83,7 +83,7 @@ describe('e2e_p2p_add_rollup', () => { }, }); - await t.applyBaseSnapshots(); + await t.setupValidators(); await t.setup(); await t.removeInitialNode(); @@ -155,29 +155,29 @@ describe('e2e_p2p_add_rollup', () => { vkTreeRoot: getVKTreeRoot(), protocolContractsHash, genesisArchiveRoot, - ethereumSlotDuration: t.ctx.aztecNodeConfig.ethereumSlotDuration, - aztecSlotDuration: t.ctx.aztecNodeConfig.aztecSlotDuration, - aztecEpochDuration: t.ctx.aztecNodeConfig.aztecEpochDuration, - aztecTargetCommitteeSize: t.ctx.aztecNodeConfig.aztecTargetCommitteeSize, - lagInEpochs: t.ctx.aztecNodeConfig.lagInEpochs, - aztecProofSubmissionEpochs: t.ctx.aztecNodeConfig.aztecProofSubmissionEpochs, - slashingQuorum: t.ctx.aztecNodeConfig.slashingQuorum, - slashingRoundSizeInEpochs: t.ctx.aztecNodeConfig.slashingRoundSizeInEpochs, - slashingLifetimeInRounds: t.ctx.aztecNodeConfig.slashingLifetimeInRounds, - slashingExecutionDelayInRounds: t.ctx.aztecNodeConfig.slashingExecutionDelayInRounds, - slashingVetoer: t.ctx.aztecNodeConfig.slashingVetoer, - slashingDisableDuration: t.ctx.aztecNodeConfig.slashingDisableDuration, - manaTarget: t.ctx.aztecNodeConfig.manaTarget, - provingCostPerMana: t.ctx.aztecNodeConfig.provingCostPerMana, + ethereumSlotDuration: t.ctx.config.ethereumSlotDuration, + aztecSlotDuration: t.ctx.config.aztecSlotDuration, + aztecEpochDuration: t.ctx.config.aztecEpochDuration, + aztecTargetCommitteeSize: t.ctx.config.aztecTargetCommitteeSize, + lagInEpochs: t.ctx.config.lagInEpochs, + aztecProofSubmissionEpochs: t.ctx.config.aztecProofSubmissionEpochs, + slashingQuorum: t.ctx.config.slashingQuorum, + slashingRoundSizeInEpochs: t.ctx.config.slashingRoundSizeInEpochs, + slashingLifetimeInRounds: t.ctx.config.slashingLifetimeInRounds, + slashingExecutionDelayInRounds: t.ctx.config.slashingExecutionDelayInRounds, + slashingVetoer: t.ctx.config.slashingVetoer, + slashingDisableDuration: t.ctx.config.slashingDisableDuration, + manaTarget: t.ctx.config.manaTarget, + provingCostPerMana: t.ctx.config.provingCostPerMana, feeJuicePortalInitialBalance: fundingNeeded, realVerifier: false, - exitDelaySeconds: t.ctx.aztecNodeConfig.exitDelaySeconds, - slasherFlavor: t.ctx.aztecNodeConfig.slasherFlavor, - slashingOffsetInRounds: t.ctx.aztecNodeConfig.slashingOffsetInRounds, - slashAmountSmall: t.ctx.aztecNodeConfig.slashAmountSmall, - slashAmountMedium: t.ctx.aztecNodeConfig.slashAmountMedium, - slashAmountLarge: t.ctx.aztecNodeConfig.slashAmountLarge, - localEjectionThreshold: t.ctx.aztecNodeConfig.localEjectionThreshold, + exitDelaySeconds: t.ctx.config.exitDelaySeconds, + slasherFlavor: t.ctx.config.slasherFlavor, + slashingOffsetInRounds: t.ctx.config.slashingOffsetInRounds, + slashAmountSmall: t.ctx.config.slashAmountSmall, + slashAmountMedium: t.ctx.config.slashAmountMedium, + slashAmountLarge: t.ctx.config.slashAmountLarge, + localEjectionThreshold: t.ctx.config.localEjectionThreshold, }, t.ctx.deployL1ContractsValues.l1ContractAddresses.registryAddress, t.logger, @@ -215,7 +215,7 @@ describe('e2e_p2p_add_rollup', () => { t.logger.info('Creating nodes'); nodes = await createNodes( - { ...t.ctx.aztecNodeConfig, governanceProposerPayload: newPayloadAddress }, + { ...t.ctx.config, governanceProposerPayload: newPayloadAddress }, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_VALIDATORS, @@ -377,8 +377,8 @@ describe('e2e_p2p_add_rollup', () => { t.ctx.initialFundedAccounts[0], t.ctx.deployL1ContractsValues.l1Client, t.ctx.deployL1ContractsValues.l1ContractAddresses, - BigInt(t.ctx.aztecNodeConfig.rollupVersion), - t.ctx.aztecNodeConfig.l1RpcUrls, + BigInt(t.ctx.config.rollupVersion), + t.ctx.config.l1RpcUrls, ); let govData; @@ -387,7 +387,7 @@ describe('e2e_p2p_add_rollup', () => { if (govData.leaderVotes >= quorumSize) { break; } - await sleep(t.ctx.aztecNodeConfig.ethereumSlotDuration * t.ctx.aztecNodeConfig.aztecSlotDuration * 1000); + await sleep(t.ctx.config.ethereumSlotDuration * t.ctx.config.aztecSlotDuration * 1000); } const nextRoundTimestamp2 = await rollup.getTimestampForSlot( @@ -480,7 +480,7 @@ describe('e2e_p2p_add_rollup', () => { // With all down, we make a time jump such that we ensure that we will be at a point where epochs are non-empty // This is to avoid conflicts when the checkpoints are looking further back. const futureEpoch = 500n + (await newRollup.getCurrentEpochNumber()); - const time = await newRollup.getTimestampForSlot(futureEpoch * BigInt(t.ctx.aztecNodeConfig.aztecEpochDuration)); + const time = await newRollup.getTimestampForSlot(futureEpoch * BigInt(t.ctx.config.aztecEpochDuration)); if (time > BigInt(await t.ctx.cheatCodes.eth.timestamp())) { await t.ctx.cheatCodes.eth.warp(Number(time)); await waitL1Block(); @@ -498,7 +498,7 @@ describe('e2e_p2p_add_rollup', () => { const blobSinkPort = await getPort(); const newConfig = { - ...t.ctx.aztecNodeConfig, + ...t.ctx.config, rollupVersion: Number(newVersion), governanceProposerPayload: EthAddress.ZERO, l1Contracts: { ...t.ctx.deployL1ContractsValues.l1ContractAddresses, ...addresses }, diff --git a/yarn-project/end-to-end/src/e2e_p2p/broadcasted_invalid_block_proposal_slash.test.ts b/yarn-project/end-to-end/src/e2e_p2p/broadcasted_invalid_block_proposal_slash.test.ts index 5e71266e243a..33323103a61f 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/broadcasted_invalid_block_proposal_slash.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/broadcasted_invalid_block_proposal_slash.test.ts @@ -69,7 +69,7 @@ describe('e2e_p2p_broadcasted_invalid_block_proposal_slash', () => { }, }); - await t.applyBaseSnapshots(); + await t.setupValidators(); await t.setup(); }); @@ -103,13 +103,13 @@ describe('e2e_p2p_broadcasted_invalid_block_proposal_slash', () => { const biggestEjection = ejectionThreshold > localEjectionThreshold ? ejectionThreshold : localEjectionThreshold; expect(activationThreshold - slashingAmount).toBeLessThan(biggestEjection); - t.ctx.aztecNodeConfig.slashBroadcastedInvalidBlockPenalty = slashingAmount; + t.ctx.config.slashBroadcastedInvalidBlockPenalty = slashingAmount; t.logger.warn('Creating nodes'); // Create first node that broadcasts invalid proposals const invalidProposerConfig = { - ...t.ctx.aztecNodeConfig, + ...t.ctx.config, broadcastInvalidBlockProposal: true, }; const invalidProposerNodes = await createNodes( @@ -129,7 +129,7 @@ describe('e2e_p2p_broadcasted_invalid_block_proposal_slash', () => { // Create remaining honest nodes const honestNodes = await createNodes( - t.ctx.aztecNodeConfig, + t.ctx.config, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_VALIDATORS - 1, @@ -148,7 +148,7 @@ describe('e2e_p2p_broadcasted_invalid_block_proposal_slash', () => { await awaitCommitteeExists({ rollup, logger: t.logger }); const offenses = await awaitOffenseDetected({ - epochDuration: t.ctx.aztecNodeConfig.aztecEpochDuration, + epochDuration: t.ctx.config.aztecEpochDuration, logger: t.logger, nodeAdmin: nodes[1], // Use honest node to check for offenses slashingRoundSize, diff --git a/yarn-project/end-to-end/src/e2e_p2p/data_withholding_slash.test.ts b/yarn-project/end-to-end/src/e2e_p2p/data_withholding_slash.test.ts index 913cc2708f02..b272bbbcbc73 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/data_withholding_slash.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/data_withholding_slash.test.ts @@ -73,7 +73,7 @@ describe('e2e_p2p_data_withholding_slash', () => { }, }); - await t.applyBaseSnapshots(); + await t.setupValidators(); await t.setup(); }); @@ -111,14 +111,14 @@ describe('e2e_p2p_data_withholding_slash', () => { const biggestEjection = ejectionThreshold > localEjectionThreshold ? ejectionThreshold : localEjectionThreshold; expect(activationThreshold - slashingAmount).toBeLessThan(biggestEjection); - t.ctx.aztecNodeConfig.slashDataWithholdingPenalty = slashingAmount; - t.ctx.aztecNodeConfig.slashPrunePenalty = slashingAmount; - t.ctx.aztecNodeConfig.validatorReexecute = false; - t.ctx.aztecNodeConfig.minTxsPerBlock = 1; + t.ctx.config.slashDataWithholdingPenalty = slashingAmount; + t.ctx.config.slashPrunePenalty = slashingAmount; + t.ctx.config.validatorReexecute = false; + t.ctx.config.minTxsPerBlock = 1; t.logger.warn('Creating nodes'); nodes = await createNodes( - t.ctx.aztecNodeConfig, + t.ctx.config, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_VALIDATORS, @@ -148,7 +148,7 @@ describe('e2e_p2p_data_withholding_slash', () => { // Send Aztec txs t.logger.warn('Setup account'); - await t.setupAccount(); + t.setupAccount(); t.logger.warn('Stopping nodes'); // Note, we needed to keep the initial node running, as that is the one the txs were sent to. await t.removeInitialNode(); @@ -163,7 +163,7 @@ describe('e2e_p2p_data_withholding_slash', () => { // ASSUMING they sync in the middle of the epoch, they will "see" the reorg, and try to slash. t.logger.warn('Re-creating nodes'); nodes = await createNodes( - t.ctx.aztecNodeConfig, + t.ctx.config, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_VALIDATORS, @@ -176,7 +176,7 @@ describe('e2e_p2p_data_withholding_slash', () => { await t.waitForP2PMeshConnectivity(nodes, NUM_VALIDATORS); const offenses = await awaitOffenseDetected({ - epochDuration: t.ctx.aztecNodeConfig.aztecEpochDuration, + epochDuration: t.ctx.config.aztecEpochDuration, logger: t.logger, nodeAdmin: nodes[0], slashingRoundSize, diff --git a/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts index c77800b8ee02..75d3ecc9358f 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts @@ -69,7 +69,7 @@ describe('e2e_p2p_network', () => { }, }); - await t.applyBaseSnapshots(); + await t.setupValidators(); await t.setup(); }); @@ -96,7 +96,7 @@ describe('e2e_p2p_network', () => { throw new Error('Bootstrap node ENR is not available'); } - t.ctx.aztecNodeConfig.validatorReexecute = true; + t.ctx.config.validatorReexecute = true; // create our network of nodes and submit txs into each of them // the number of txs per node and the number of txs per rollup @@ -105,7 +105,7 @@ describe('e2e_p2p_network', () => { const txsSentViaDifferentNodes: SentTx[][] = []; t.logger.info('Creating validator nodes'); nodes = await createNodes( - t.ctx.aztecNodeConfig, + t.ctx.config, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_VALIDATORS, @@ -119,7 +119,7 @@ describe('e2e_p2p_network', () => { // create a prover node that uses p2p only (not rpc) to gather txs to test prover tx collection t.logger.warn(`Creating prover node`); proverNode = await createProverNode( - t.ctx.aztecNodeConfig, + t.ctx.config, BOOT_NODE_UDP_PORT + NUM_VALIDATORS + 1, t.bootstrapNodeEnr, ATTESTER_PRIVATE_KEYS_START_INDEX + NUM_VALIDATORS + 1, @@ -131,7 +131,7 @@ describe('e2e_p2p_network', () => { await proverNode.start(); t.logger.warn(`Creating non validator node`); - const monitoringNodeConfig: AztecNodeConfig = { ...t.ctx.aztecNodeConfig, alwaysReexecuteBlockProposals: true }; + const monitoringNodeConfig: AztecNodeConfig = { ...t.ctx.config, alwaysReexecuteBlockProposals: true }; monitoringNode = await createNonValidatorNode( monitoringNodeConfig, t.ctx.dateProvider, @@ -148,7 +148,7 @@ describe('e2e_p2p_network', () => { // We need to `createNodes` before we setup account, because // those nodes actually form the committee, and so we cannot build // blocks without them (since targetCommitteeSize is set to the number of nodes) - await t.setupAccount(); + t.setupAccount(); t.logger.info('Submitting transactions'); for (const node of nodes) { diff --git a/yarn-project/end-to-end/src/e2e_p2p/gossip_network_no_cheat.test.ts b/yarn-project/end-to-end/src/e2e_p2p/gossip_network_no_cheat.test.ts index da7e4d735734..43c05a4e8be5 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/gossip_network_no_cheat.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/gossip_network_no_cheat.test.ts @@ -90,7 +90,7 @@ describe('e2e_p2p_network', () => { throw new Error('Bootstrap node ENR is not available'); } - t.ctx.aztecNodeConfig.validatorReexecute = true; + t.ctx.config.validatorReexecute = true; expect(t.ctx.deployL1ContractsValues.l1ContractAddresses.stakingAssetHandlerAddress).toBeDefined(); @@ -123,8 +123,8 @@ describe('e2e_p2p_network', () => { const validator = validators[i]; const mockPassportProof = ZkPassportProofParams.random().toBuffer(); await addL1Validator({ - rpcUrls: t.ctx.aztecNodeConfig.l1RpcUrls, - chainId: t.ctx.aztecNodeConfig.l1ChainId, + rpcUrls: t.ctx.config.l1RpcUrls, + chainId: t.ctx.config.l1ChainId, privateKey: t.baseAccountPrivateKey, mnemonic: undefined, attesterAddress: EthAddress.fromString(validator.attester.toString()), @@ -158,7 +158,7 @@ describe('e2e_p2p_network', () => { } // Wait for the validators to be added to the rollup - const timestamp = await t.ctx.cheatCodes.rollup.advanceToEpoch(BigInt(t.ctx.aztecNodeConfig.lagInEpochs + 1)); + const timestamp = await t.ctx.cheatCodes.rollup.advanceToEpoch(BigInt(t.ctx.config.lagInEpochs + 1)); // Changes have now taken effect const attesters = await rollupWrapper.getAttesters(); @@ -185,7 +185,7 @@ describe('e2e_p2p_network', () => { const txsSentViaDifferentNodes: SentTx[][] = []; t.logger.info('Creating nodes'); nodes = await createNodes( - t.ctx.aztecNodeConfig, + t.ctx.config, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_VALIDATORS, @@ -202,7 +202,7 @@ describe('e2e_p2p_network', () => { // We need to `createNodes` before we setup account, because // those nodes actually form the committee, and so we cannot build // blocks without them (since targetCommitteeSize is set to the number of nodes) - await t.setupAccount(); + t.setupAccount(); t.logger.info('Submitting transactions'); for (const node of nodes) { diff --git a/yarn-project/end-to-end/src/e2e_p2p/inactivity_slash_test.ts b/yarn-project/end-to-end/src/e2e_p2p/inactivity_slash_test.ts index 4b90aa4ca1d1..d9bbc1bdb518 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/inactivity_slash_test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/inactivity_slash_test.ts @@ -81,7 +81,7 @@ export class P2PInactivityTest { } public async setup() { - await this.test.applyBaseSnapshots(); + await this.test.setupValidators(); await this.test.setup(); // Set slashing penalties for inactivity @@ -93,7 +93,7 @@ export class P2PInactivityTest { ]); const biggestEjection = ejectionThreshold > localEjectionThreshold ? ejectionThreshold : localEjectionThreshold; expect(activationThreshold - SLASHING_AMOUNT).toBeLessThan(biggestEjection); - this.test.ctx.aztecNodeConfig.slashInactivityPenalty = SLASHING_AMOUNT; + this.test.ctx.config.slashInactivityPenalty = SLASHING_AMOUNT; this.rollup = rollup; if (!this.keepInitialNode) { @@ -102,7 +102,7 @@ export class P2PInactivityTest { // Create all active nodes this.activeNodes = await createNodes( - this.test.ctx.aztecNodeConfig, + this.test.ctx.config, this.test.ctx.dateProvider, this.test.bootstrapNodeEnr, NUM_NODES - this.inactiveNodeCount - Number(this.keepInitialNode), @@ -114,7 +114,7 @@ export class P2PInactivityTest { ); // And the ones with an initially disabled sequencer - const inactiveConfig = { ...this.test.ctx.aztecNodeConfig, dontStartSequencer: true }; + const inactiveConfig = { ...this.test.ctx.config, dontStartSequencer: true }; this.inactiveNodes = await createNodes( inactiveConfig, this.test.ctx.dateProvider, diff --git a/yarn-project/end-to-end/src/e2e_p2p/inactivity_slash_with_consecutive_epochs.test.ts b/yarn-project/end-to-end/src/e2e_p2p/inactivity_slash_with_consecutive_epochs.test.ts index 259e211a475e..b8b2854e26f2 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/inactivity_slash_with_consecutive_epochs.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/inactivity_slash_with_consecutive_epochs.test.ts @@ -35,7 +35,7 @@ describe('e2e_p2p_inactivity_slash_with_consecutive_epochs', () => { slashingOffsetInRounds, slashingRoundSizeInEpochs, aztecSlotDuration, - } = test.ctx.aztecNodeConfig; + } = test.ctx.config; const initialEpoch = Number(test.test.monitor.l2EpochNumber) + 1; test.logger.warn(`Waiting until end of epoch ${initialEpoch} to reenable validator ${reenabledValidator}`); diff --git a/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts b/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts index 37f67fb044ac..987cc36bbfae 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts @@ -17,7 +17,7 @@ import { } from '@aztec/ethereum'; import { ChainMonitor } from '@aztec/ethereum/test'; import { SecretValue } from '@aztec/foundation/config'; -import { type Logger, createLogger } from '@aztec/foundation/log'; +import { createLogger } from '@aztec/foundation/log'; import { retryUntil } from '@aztec/foundation/retry'; import { RollupAbi, SlasherAbi, TestERC20Abi } from '@aztec/l1-artifacts'; import { SpamContract } from '@aztec/noir-test-contracts.js/Spam'; @@ -27,25 +27,24 @@ import { tryStop } from '@aztec/stdlib/interfaces/server'; import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts'; import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees'; import { ZkPassportProofParams } from '@aztec/stdlib/zkpassport'; -import type { TestWallet } from '@aztec/test-wallet/server'; import { getGenesisValues } from '@aztec/world-state/testing'; import getPort from 'get-port'; import { type GetContractReturnType, getAddress, getContract } from 'viem'; import { privateKeyToAccount } from 'viem/accounts'; +import { BaseEndToEndTest } from '../fixtures/base_end_to_end_test.js'; import { ATTESTER_PRIVATE_KEYS_START_INDEX, createValidatorConfig, generatePrivateKeys, } from '../fixtures/setup_p2p_test.js'; import { - type ISnapshotManager, - type SubsystemsContext, - createSnapshotManager, - deployAccounts, -} from '../fixtures/snapshot_manager.js'; -import { type SetupOptions, getPrivateKeyFromIndex, getSponsoredFPCAddress } from '../fixtures/utils.js'; + type EndToEndContext, + type SetupOptions, + getPrivateKeyFromIndex, + getSponsoredFPCAddress, +} from '../fixtures/utils.js'; import { getEndToEndTestTelemetryClient } from '../fixtures/with_telemetry_utils.js'; // Use a fixed bootstrap node private key so that we can re-use the same snapshot and the nodes can find each other @@ -59,32 +58,38 @@ export const SHORTENED_BLOCK_TIME_CONFIG_NO_PRUNES = { aztecProofSubmissionWindow: 640, }; -export class P2PNetworkTest { - private snapshotManager: ISnapshotManager; +export class P2PNetworkTest extends BaseEndToEndTest { + // Properties inherited from BaseEndToEndTest: + // - aztecNode, wallet, accounts, cheatCodes, deployL1ContractsValues, logger, context + public baseAccountPrivateKey: `0x${string}`; public baseAccount; - public logger: Logger; public monitor!: ChainMonitor; - public ctx!: SubsystemsContext; public attesterPrivateKeys: `0x${string}`[] = []; public attesterPublicKeys: string[] = []; public peerIdPrivateKeys: string[] = []; public validators: Operator[] = []; public deployedAccounts: InitialAccountData[] = []; - public prefilledPublicData: PublicDataTreeLeaf[] = []; + public override prefilledPublicData: PublicDataTreeLeaf[] = []; - // The re-execution test needs a wallet and a spam contract - public wallet?: TestWallet; + // The re-execution test needs a spam contract public defaultAccountAddress?: AztecAddress; public spamContract?: SpamContract; public bootstrapNode?: BootstrapNode; + private initialValidatorConfig: SetupOptions; + + // Expose ctx for backward compatibility with existing tests + get ctx(): EndToEndContext { + return this.context; + } + constructor( - public readonly testName: string, + testName: string, public bootstrapNodeEnr: string, public bootNodePort: number, public numberOfValidators: number, @@ -95,7 +100,7 @@ export class P2PNetworkTest { startProverNode?: boolean, mockZkPassportVerifier?: boolean, ) { - this.logger = createLogger(`e2e:e2e_p2p:${testName}`); + super(testName, createLogger(`e2e:e2e_p2p:${testName}`)); // Set up the base account and node private keys for the initial network deployment this.baseAccountPrivateKey = `0x${getPrivateKeyFromIndex(1)!.toString('hex')}`; @@ -108,45 +113,30 @@ export class P2PNetworkTest { const zkPassportParams = ZkPassportProofParams.random(); - this.snapshotManager = createSnapshotManager( - `e2e_p2p_network/${testName}`, - process.env.E2E_DATA_PATH, - { - ...initialValidatorConfig, - ethereumSlotDuration: initialValidatorConfig.ethereumSlotDuration ?? l1ContractsConfig.ethereumSlotDuration, - aztecEpochDuration: initialValidatorConfig.aztecEpochDuration ?? l1ContractsConfig.aztecEpochDuration, - aztecSlotDuration: initialValidatorConfig.aztecSlotDuration ?? l1ContractsConfig.aztecSlotDuration, - aztecProofSubmissionEpochs: - initialValidatorConfig.aztecProofSubmissionEpochs ?? l1ContractsConfig.aztecProofSubmissionEpochs, - slashingRoundSizeInEpochs: - initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs, - slasherFlavor: initialValidatorConfig.slasherFlavor ?? 'tally', - aztecTargetCommitteeSize: numberOfValidators, - salt: 420, - metricsPort: metricsPort, - numberOfInitialFundedAccounts: 2, - startProverNode, - }, - { - ...initialValidatorConfig, - aztecEpochDuration: initialValidatorConfig.aztecEpochDuration ?? l1ContractsConfig.aztecEpochDuration, - slashingRoundSizeInEpochs: - initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs, - slasherFlavor: initialValidatorConfig.slasherFlavor ?? 'tally', - - ethereumSlotDuration: initialValidatorConfig.ethereumSlotDuration ?? l1ContractsConfig.ethereumSlotDuration, - aztecSlotDuration: initialValidatorConfig.aztecSlotDuration ?? l1ContractsConfig.aztecSlotDuration, - aztecProofSubmissionEpochs: - initialValidatorConfig.aztecProofSubmissionEpochs ?? l1ContractsConfig.aztecProofSubmissionEpochs, - aztecTargetCommitteeSize: numberOfValidators, - initialValidators: [], + this.initialValidatorConfig = { + ...initialValidatorConfig, + ethereumSlotDuration: initialValidatorConfig.ethereumSlotDuration ?? l1ContractsConfig.ethereumSlotDuration, + aztecEpochDuration: initialValidatorConfig.aztecEpochDuration ?? l1ContractsConfig.aztecEpochDuration, + aztecSlotDuration: initialValidatorConfig.aztecSlotDuration ?? l1ContractsConfig.aztecSlotDuration, + aztecProofSubmissionEpochs: + initialValidatorConfig.aztecProofSubmissionEpochs ?? l1ContractsConfig.aztecProofSubmissionEpochs, + slashingRoundSizeInEpochs: + initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs, + slasherFlavor: initialValidatorConfig.slasherFlavor ?? 'tally', + aztecTargetCommitteeSize: numberOfValidators, + salt: 420, + metricsPort: metricsPort, + numberOfInitialFundedAccounts: 2, + startProverNode, + initialValidators: [], + deployL1ContractsArgs: { zkPassportArgs: { mockZkPassportVerifier, zkPassportDomain: zkPassportParams.domain, zkPassportScope: zkPassportParams.scope, }, }, - ); + }; } static async create({ @@ -199,17 +189,15 @@ export class P2PNetworkTest { } async addBootstrapNode() { - await this.snapshotManager.snapshot('add-bootstrap-node', async ({ aztecNodeConfig }) => { - const telemetry = getEndToEndTestTelemetryClient(this.metricsPort); - this.bootstrapNode = await createBootstrapNodeFromPrivateKey( - BOOTSTRAP_NODE_PRIVATE_KEY, - this.bootNodePort, - telemetry, - aztecNodeConfig, - ); - // Overwrite enr with updated info - this.bootstrapNodeEnr = this.bootstrapNode.getENR().encodeTxt(); - }); + const telemetry = getEndToEndTestTelemetryClient(this.metricsPort); + this.bootstrapNode = await createBootstrapNodeFromPrivateKey( + BOOTSTRAP_NODE_PRIVATE_KEY, + this.bootNodePort, + telemetry, + this.context.config, + ); + // Overwrite enr with updated info + this.bootstrapNodeEnr = this.bootstrapNode.getENR().encodeTxt(); } getValidators() { @@ -230,125 +218,104 @@ export class P2PNetworkTest { return { validators }; } - async applyBaseSnapshots() { + async setupValidators() { await this.addBootstrapNode(); - await this.snapshotManager.snapshot('add-validators', async ({ deployL1ContractsValues, cheatCodes }) => { - const rollup = getContract({ - address: deployL1ContractsValues.l1ContractAddresses.rollupAddress.toString(), - abi: RollupAbi, - client: deployL1ContractsValues.l1Client, - }); - this.logger.info(`Adding ${this.numberOfValidators} validators`); + // Add validators + const rollup = getContract({ + address: this.deployL1ContractsValues.l1ContractAddresses.rollupAddress.toString(), + abi: RollupAbi, + client: this.deployL1ContractsValues.l1Client, + }); + + this.logger.info(`Adding ${this.numberOfValidators} validators`); - const stakingAsset = getContract({ - address: deployL1ContractsValues.l1ContractAddresses.stakingAssetAddress.toString(), - abi: TestERC20Abi, - client: deployL1ContractsValues.l1Client, - }); + const stakingAsset = getContract({ + address: this.deployL1ContractsValues.l1ContractAddresses.stakingAssetAddress.toString(), + abi: TestERC20Abi, + client: this.deployL1ContractsValues.l1Client, + }); - const { address: multiAdderAddress } = await deployL1Contract( - deployL1ContractsValues.l1Client, - MultiAdderArtifact.contractAbi, - MultiAdderArtifact.contractBytecode, - [rollup.address, deployL1ContractsValues.l1Client.account.address], - ); - - const multiAdder = getContract({ - address: multiAdderAddress.toString(), - abi: MultiAdderArtifact.contractAbi, - client: deployL1ContractsValues.l1Client, - }); + const { address: multiAdderAddress } = await deployL1Contract( + this.deployL1ContractsValues.l1Client, + MultiAdderArtifact.contractAbi, + MultiAdderArtifact.contractBytecode, + [rollup.address, this.deployL1ContractsValues.l1Client.account.address], + ); - const stakeNeeded = (await rollup.read.getActivationThreshold()) * BigInt(this.numberOfValidators); - await Promise.all( - [await stakingAsset.write.mint([multiAdder.address, stakeNeeded], {} as any)].map(txHash => - deployL1ContractsValues.l1Client.waitForTransactionReceipt({ hash: txHash }), - ), - ); - - const { validators } = this.getValidators(); - this.validators = validators; - - const gseAddress = deployL1ContractsValues.l1ContractAddresses.gseAddress!; - if (!gseAddress) { - throw new Error('GSE contract not deployed'); - } - - const gseContract = new GSEContract(deployL1ContractsValues.l1Client, gseAddress.toString()); - - const makeValidatorTuples = async (validator: Operator) => { - const registrationTuple = await gseContract.makeRegistrationTuple(validator.bn254SecretKey.getValue()); - return { - attester: validator.attester.toString() as `0x${string}`, - withdrawer: validator.withdrawer.toString() as `0x${string}`, - ...registrationTuple, - }; - }; - const validatorTuples = await Promise.all(validators.map(makeValidatorTuples)); + const multiAdder = getContract({ + address: multiAdderAddress.toString(), + abi: MultiAdderArtifact.contractAbi, + client: this.deployL1ContractsValues.l1Client, + }); - await deployL1ContractsValues.l1Client.waitForTransactionReceipt({ - hash: await multiAdder.write.addValidators([validatorTuples]), - }); + const stakeNeeded = (await rollup.read.getActivationThreshold()) * BigInt(this.numberOfValidators); + await Promise.all( + [await stakingAsset.write.mint([multiAdder.address, stakeNeeded])].map(txHash => + this.deployL1ContractsValues.l1Client.waitForTransactionReceipt({ hash: txHash }), + ), + ); - await cheatCodes.rollup.advanceToEpoch( - (await cheatCodes.rollup.getEpoch()) + (await rollup.read.getLagInEpochs()) + 1n, - ); + const { validators } = this.getValidators(); + this.validators = validators; - // Send and await a tx to make sure we mine a block for the warp to correctly progress. - await this._sendDummyTx(deployL1ContractsValues.l1Client); + const gseAddress = this.deployL1ContractsValues.l1ContractAddresses.gseAddress!; + if (!gseAddress) { + throw new Error('GSE contract not deployed'); + } + + const gseContract = new GSEContract(this.deployL1ContractsValues.l1Client, gseAddress.toString()); + + const makeValidatorTuples = async (validator: Operator) => { + const registrationTuple = await gseContract.makeRegistrationTuple(validator.bn254SecretKey.getValue()); + return { + attester: validator.attester.toString() as `0x${string}`, + withdrawer: validator.withdrawer.toString() as `0x${string}`, + ...registrationTuple, + }; + }; + const validatorTuples = await Promise.all(validators.map(makeValidatorTuples)); + + await this.deployL1ContractsValues.l1Client.waitForTransactionReceipt({ + hash: await multiAdder.write.addValidators([validatorTuples]), }); - } - async setupAccount() { - await this.snapshotManager.snapshot( - 'setup-account', - deployAccounts(1, this.logger), - ({ deployedAccounts }, { wallet }) => { - this.deployedAccounts = deployedAccounts; - [{ address: this.defaultAccountAddress }] = deployedAccounts; - this.wallet = wallet; - return Promise.resolve(); - }, + await this.cheatCodes.rollup.advanceToEpoch( + (await this.cheatCodes.rollup.getEpoch()) + (await rollup.read.getLagInEpochs()) + 1n, ); + + // Send and await a tx to make sure we mine a block for the warp to correctly progress. + await this._sendDummyTx(this.deployL1ContractsValues.l1Client); + } + + setupAccount() { + // Account is already deployed by setup() if numberOfAccounts > 0 + // For P2P tests, we need to deploy accounts separately as they're not part of initial setup + if (this.accounts.length > 0) { + this.deployedAccounts = this.initialFundedAccounts; + this.defaultAccountAddress = this.accounts[0]; + } } async deploySpamContract() { - await this.snapshotManager.snapshot( - 'add-spam-contract', - async () => { - if (!this.wallet) { - throw new Error('Call snapshot t.setupAccount before deploying account contract'); - } - - const spamContract = await SpamContract.deploy(this.wallet) - .send({ from: this.defaultAccountAddress! }) - .deployed(); - return { contractAddress: spamContract.address }; - }, - async ({ contractAddress }) => { - if (!this.wallet) { - throw new Error('Call snapshot t.setupAccount before deploying account contract'); - } - this.spamContract = await SpamContract.at(contractAddress, this.wallet); - }, - ); + if (!this.wallet) { + throw new Error('Call setupAccount before deploying spam contract'); + } + + const spamContract = await SpamContract.deploy(this.wallet).send({ from: this.defaultAccountAddress! }).deployed(); + + this.spamContract = await SpamContract.at(spamContract.address, this.wallet); } async removeInitialNode() { - await this.snapshotManager.snapshot( - 'remove-initial-validator', - async ({ deployL1ContractsValues, aztecNode, dateProvider }) => { - // Send and await a tx to make sure we mine a block for the warp to correctly progress. - const { receipt } = await this._sendDummyTx(deployL1ContractsValues.l1Client); - const block = await deployL1ContractsValues.l1Client.getBlock({ - blockNumber: receipt.blockNumber, - }); - dateProvider.setTime(Number(block.timestamp) * 1000); - - await aztecNode.stop(); - }, - ); + // Send and await a tx to make sure we mine a block for the warp to correctly progress. + const { receipt } = await this._sendDummyTx(this.deployL1ContractsValues.l1Client); + const block = await this.deployL1ContractsValues.l1Client.getBlock({ + blockNumber: receipt.blockNumber, + }); + this.dateProvider!.setTime(Number(block.timestamp) * 1000); + + await tryStop(this.aztecNode); } async sendDummyTx() { @@ -363,18 +330,20 @@ export class P2PNetworkTest { }); } - async setup() { - this.ctx = await this.snapshotManager.setup(); + override async setup(): Promise { + await super.setup(0, this.initialValidatorConfig); const sponsoredFPCAddress = await getSponsoredFPCAddress(); - const initialFundedAccounts = [...this.ctx.initialFundedAccounts.map(a => a.address), sponsoredFPCAddress]; + const initialFundedAccounts = [...this.initialFundedAccounts.map(a => a.address), sponsoredFPCAddress]; const { prefilledPublicData } = await getGenesisValues(initialFundedAccounts); this.prefilledPublicData = prefilledPublicData; - const rollupContract = RollupContract.getFromL1ContractsValues(this.ctx.deployL1ContractsValues); - this.monitor = new ChainMonitor(rollupContract, this.ctx.dateProvider).start(); - this.monitor.on('l1-block', ({ timestamp }) => this.ctx.dateProvider.setTime(Number(timestamp) * 1000)); + const rollupContract = RollupContract.getFromL1ContractsValues(this.deployL1ContractsValues); + this.monitor = new ChainMonitor(rollupContract, this.dateProvider!).start(); + this.monitor.on('l1-block', ({ timestamp }) => this.dateProvider!.setTime(Number(timestamp) * 1000)); + + return this; } async stopNodes(nodes: AztecNodeService[]) { @@ -432,10 +401,10 @@ export class P2PNetworkTest { this.logger.warn('All nodes connected to P2P mesh'); } - async teardown() { + override async teardown() { await this.monitor.stop(); await tryStop(this.bootstrapNode, this.logger); - await this.snapshotManager.teardown(); + await super.teardown(); } async getContracts(): Promise<{ diff --git a/yarn-project/end-to-end/src/e2e_p2p/preferred_gossip_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p/preferred_gossip_network.test.ts index 30c7801ff9bf..17286b15d49d 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/preferred_gossip_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/preferred_gossip_network.test.ts @@ -141,7 +141,7 @@ describe('e2e_p2p_preferred_network', () => { }, }); - await t.applyBaseSnapshots(); + await t.setupValidators(); await t.setup(); }); @@ -166,10 +166,10 @@ describe('e2e_p2p_preferred_network', () => { throw new Error('Bootstrap node ENR is not available'); } - t.ctx.aztecNodeConfig.validatorReexecute = true; + t.ctx.config.validatorReexecute = true; const preferredNodeConfig: AztecNodeConfig = { - ...t.ctx.aztecNodeConfig, + ...t.ctx.config, disableValidator: true, // Only permit validators to connect and switch off discovery p2pAllowOnlyValidators: true, @@ -211,7 +211,7 @@ describe('e2e_p2p_preferred_network', () => { }); const nodeConfig: AztecNodeConfig = { - ...t.ctx.aztecNodeConfig, + ...t.ctx.config, disableValidator: true, // The regular nodes will attempt to connect to the preferred nodes but they should fail the authentication @@ -237,7 +237,7 @@ describe('e2e_p2p_preferred_network', () => { t.logger.info('Creating validators'); const validatorConfig: AztecNodeConfig = { - ...t.ctx.aztecNodeConfig, + ...t.ctx.config, disableValidator: false, preferredPeers: preferredNodeEnrs.filter(enr => enr !== undefined), }; @@ -260,7 +260,7 @@ describe('e2e_p2p_preferred_network', () => { // This last validator disables discovery to avoid connecting to anyone but preferred nodes // We do this to test that it receives ALL data via the preferred nodes const lastValidatorConfig: AztecNodeConfig = { - ...t.ctx.aztecNodeConfig, + ...t.ctx.config, p2pDiscoveryDisabled: true, disableValidator: false, preferredPeers: preferredNodeEnrs.filter(enr => enr !== undefined), @@ -331,7 +331,7 @@ describe('e2e_p2p_preferred_network', () => { // We need to `createNodes` before we setup account, because // those nodes actually form the committee, and so we cannot build // blocks without them (since targetCommitteeSize is set to the number of nodes) - await t.setupAccount(); + t.setupAccount(); // Send the required number of transactions to each node t.logger.info('Submitting transactions'); diff --git a/yarn-project/end-to-end/src/e2e_p2p/rediscovery.test.ts b/yarn-project/end-to-end/src/e2e_p2p/rediscovery.test.ts index 4dac50600efa..ea7e3b666916 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/rediscovery.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/rediscovery.test.ts @@ -35,7 +35,7 @@ describe('e2e_p2p_rediscovery', () => { listenAddress: '127.0.0.1', }, }); - await t.applyBaseSnapshots(); + await t.setupValidators(); await t.setup(); }); @@ -51,7 +51,7 @@ describe('e2e_p2p_rediscovery', () => { it('should re-discover stored peers without bootstrap node', async () => { const txsSentViaDifferentNodes: SentTx[][] = []; nodes = await createNodes( - t.ctx.aztecNodeConfig, + t.ctx.config, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_VALIDATORS, @@ -68,7 +68,7 @@ describe('e2e_p2p_rediscovery', () => { // We need to `createNodes` before we setup account, because // those nodes actually form the committee, and so we cannot build // blocks without them (since targetCommitteeSize is set to the number of nodes) - await t.setupAccount(); + t.setupAccount(); // stop bootstrap node await t.bootstrapNode?.stop(); @@ -84,7 +84,7 @@ describe('e2e_p2p_rediscovery', () => { await sleep(2500); const newNode = await createNode( - t.ctx.aztecNodeConfig, + t.ctx.config, t.ctx.dateProvider, i + 1 + BOOT_NODE_UDP_PORT, undefined, diff --git a/yarn-project/end-to-end/src/e2e_p2p/reex.test.ts b/yarn-project/end-to-end/src/e2e_p2p/reex.test.ts index 5ad8b0811dd3..719e5689b3db 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/reex.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/reex.test.ts @@ -51,7 +51,7 @@ describe('e2e_p2p_reex', () => { }); t.logger.info('Apply base snapshots'); - await t.applyBaseSnapshots(); + await t.setupValidators(); t.logger.info('Setup snapshot manager'); await t.setup(); @@ -66,7 +66,7 @@ describe('e2e_p2p_reex', () => { t.logger.info('Creating peer nodes'); nodes = await createNodes( { - ...t.ctx.aztecNodeConfig, + ...t.ctx.config, validatorReexecute: true, minTxsPerBlock: 1, maxTxsPerBlock: NUM_TXS_PER_NODE, @@ -86,7 +86,7 @@ describe('e2e_p2p_reex', () => { await sleep(8000); t.logger.info('Setup account'); - await t.setupAccount(); + t.setupAccount(); t.logger.info('Deploy spam contract'); await t.deploySpamContract(); @@ -237,7 +237,7 @@ describe('e2e_p2p_reex', () => { const txResults = await Promise.allSettled( txs.map(async (tx: SentTx, i: number) => { t.logger.info(`Waiting for tx ${i}: ${(await tx.getTxHash()).toString()} to be mined`); - return await tx.wait({ timeout: t.ctx.aztecNodeConfig.aztecSlotDuration * 2 }); + return await tx.wait({ timeout: t.ctx.config.aztecSlotDuration * 2 }); }), ); diff --git a/yarn-project/end-to-end/src/e2e_p2p/reqresp.test.ts b/yarn-project/end-to-end/src/e2e_p2p/reqresp.test.ts index 418811ef3c86..8d2f40ff1fce 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/reqresp.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/reqresp.test.ts @@ -41,7 +41,7 @@ describe('e2e_p2p_reqresp_tx', () => { aztecEpochDuration: 64, // stable committee }, }); - await t.applyBaseSnapshots(); + await t.setupValidators(); await t.setup(); }); @@ -75,7 +75,7 @@ describe('e2e_p2p_reqresp_tx', () => { t.logger.info('Creating nodes'); nodes = await createNodes( - t.ctx.aztecNodeConfig, + t.ctx.config, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_VALIDATORS, @@ -88,7 +88,7 @@ describe('e2e_p2p_reqresp_tx', () => { t.logger.info('Sleeping to allow nodes to connect'); await sleep(4000); - await t.setupAccount(); + t.setupAccount(); t.logger.info('Preparing transactions to send'); const txss = await timesAsync(2, () => diff --git a/yarn-project/end-to-end/src/e2e_p2p/reqresp_no_handshake.test.ts b/yarn-project/end-to-end/src/e2e_p2p/reqresp_no_handshake.test.ts index 1a3dc9fe17c6..bf19f2ec6bbc 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/reqresp_no_handshake.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/reqresp_no_handshake.test.ts @@ -46,7 +46,7 @@ describe('e2e_p2p_reqresp_tx_no_handshake', () => { aztecEpochDuration: 64, // stable committee }, }); - await t.applyBaseSnapshots(); + await t.setupValidators(); await t.setup(); }); @@ -76,7 +76,7 @@ describe('e2e_p2p_reqresp_tx_no_handshake', () => { t.logger.info('Creating nodes'); nodes = await createNodes( - { ...t.ctx.aztecNodeConfig, p2pDisableStatusHandshake: true }, // DIFFERENCE FROM reqresp.test.ts + { ...t.ctx.config, p2pDisableStatusHandshake: true }, // DIFFERENCE FROM reqresp.test.ts t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_VALIDATORS, @@ -93,7 +93,7 @@ describe('e2e_p2p_reqresp_tx_no_handshake', () => { t.logger.info('Sleeping to allow nodes to connect'); await sleep(4000); - await t.setupAccount(); + t.setupAccount(); t.logger.info('Preparing transactions to send'); const txss = await timesAsync(2, () => diff --git a/yarn-project/end-to-end/src/e2e_p2p/slash_veto_demo.test.ts b/yarn-project/end-to-end/src/e2e_p2p/slash_veto_demo.test.ts index 59461ba49b50..8906b05dee4e 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/slash_veto_demo.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/slash_veto_demo.test.ts @@ -96,11 +96,11 @@ describe('veto slash', () => { }, }); - await t.applyBaseSnapshots(); + await t.setupValidators(); await t.setup(); nodes = await createNodes( - t.ctx.aztecNodeConfig, + t.ctx.config, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_NODES, // Note we do not create the last validator yet, so it shows as offline @@ -111,7 +111,7 @@ describe('veto slash', () => { ); vetoerL1Client = createExtendedL1Client( - t.ctx.aztecNodeConfig.l1RpcUrls, + t.ctx.config.l1RpcUrls, bufferToHex(getPrivateKeyFromIndex(VETOER_PRIVATE_KEY_INDEX)!), ); vetoerL1TxUtils = createL1TxUtilsFromViemWallet(vetoerL1Client, { @@ -130,7 +130,7 @@ describe('veto slash', () => { slashingAmount = SLASHING_UNIT * 3n; expect(activationThreshold - slashingAmount).toBeLessThan(ejectionThreshold); - t.ctx.aztecNodeConfig.slashInactivityPenalty = slashingAmount; + t.ctx.config.slashInactivityPenalty = slashingAmount; for (const node of nodes) { await node.setConfig({ slashInactivityPenalty: slashingAmount }); } diff --git a/yarn-project/end-to-end/src/e2e_p2p/upgrade_governance_proposer.test.ts b/yarn-project/end-to-end/src/e2e_p2p/upgrade_governance_proposer.test.ts index e52f7665eb75..c8e4e6ca5caa 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/upgrade_governance_proposer.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/upgrade_governance_proposer.test.ts @@ -54,7 +54,7 @@ describe('e2e_p2p_governance_proposer', () => { }, }); - await t.applyBaseSnapshots(); + await t.setupValidators(); await t.setup(); l1TxUtils = createL1TxUtilsFromViemWallet(t.ctx.deployL1ContractsValues.l1Client); @@ -144,7 +144,7 @@ describe('e2e_p2p_governance_proposer', () => { t.logger.info('Creating nodes'); nodes = await createNodes( - { ...t.ctx.aztecNodeConfig, governanceProposerPayload: newPayloadAddress }, + { ...t.ctx.config, governanceProposerPayload: newPayloadAddress }, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_VALIDATORS, diff --git a/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned_slash.test.ts b/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned_slash.test.ts index 82cdad7b1bf8..90d057e39294 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned_slash.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned_slash.test.ts @@ -67,7 +67,7 @@ describe('e2e_p2p_valid_epoch_pruned_slash', () => { }, }); - await t.applyBaseSnapshots(); + await t.setupValidators(); await t.setup(); }); @@ -101,14 +101,14 @@ describe('e2e_p2p_valid_epoch_pruned_slash', () => { const biggestEjection = ejectionThreshold > localEjectionThreshold ? ejectionThreshold : localEjectionThreshold; expect(activationThreshold - slashingAmount).toBeLessThan(biggestEjection); - t.ctx.aztecNodeConfig.slashPrunePenalty = slashingAmount; - t.ctx.aztecNodeConfig.validatorReexecute = false; - t.ctx.aztecNodeConfig.minTxsPerBlock = 1; - t.ctx.aztecNodeConfig.txPoolDeleteTxsAfterReorg = true; + t.ctx.config.slashPrunePenalty = slashingAmount; + t.ctx.config.validatorReexecute = false; + t.ctx.config.minTxsPerBlock = 1; + t.ctx.config.txPoolDeleteTxsAfterReorg = true; t.logger.warn(`Creating ${NUM_VALIDATORS} new nodes`); nodes = await createNodes( - t.ctx.aztecNodeConfig, + t.ctx.config, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_VALIDATORS, @@ -131,7 +131,7 @@ describe('e2e_p2p_valid_epoch_pruned_slash', () => { // Set up a wallet and keep it out of reorgs await t.ctx.cheatCodes.rollup.markAsProven(); - await t.setupAccount(); + t.setupAccount(); await t.ctx.cheatCodes.rollup.markAsProven(); // Warp forward to after the initial grace period @@ -163,7 +163,7 @@ describe('e2e_p2p_valid_epoch_pruned_slash', () => { logger: t.logger, nodeAdmin: nodes[0], slashingRoundSize, - epochDuration: t.ctx.aztecNodeConfig.aztecEpochDuration, + epochDuration: t.ctx.config.aztecEpochDuration, waitUntilOffenseCount: COMMITTEE_SIZE, }); diff --git a/yarn-project/end-to-end/src/e2e_p2p/validators_sentinel.test.ts b/yarn-project/end-to-end/src/e2e_p2p/validators_sentinel.test.ts index 35c5e75898f1..c16f950a59b4 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/validators_sentinel.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/validators_sentinel.test.ts @@ -53,11 +53,11 @@ describe('e2e_p2p_validators_sentinel', () => { }, }); - await t.applyBaseSnapshots(); + await t.setupValidators(); await t.setup(); nodes = await createNodes( - t.ctx.aztecNodeConfig, + t.ctx.config, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_NODES, // Note we do not create the last validator yet, so it shows as offline @@ -157,7 +157,7 @@ describe('e2e_p2p_validators_sentinel', () => { const l2BlockNumber = t.monitor.l2BlockNumber; const nodeIndex = NUM_NODES + 1; const newNode = await createNode( - t.ctx.aztecNodeConfig, + t.ctx.config, t.ctx.dateProvider, BOOT_NODE_UDP_PORT + nodeIndex + 1, t.bootstrapNodeEnr!, diff --git a/yarn-project/end-to-end/src/e2e_prover/full.test.ts b/yarn-project/end-to-end/src/e2e_prover/full.test.ts index 82f09dbb1331..29beb6276ce6 100644 --- a/yarn-project/end-to-end/src/e2e_prover/full.test.ts +++ b/yarn-project/end-to-end/src/e2e_prover/full.test.ts @@ -43,9 +43,8 @@ describe('full_prover', () => { beforeAll(async () => { t.logger.warn(`Running suite with ${REAL_PROOFS ? 'real' : 'fake'} proofs`); - await t.applyBaseSnapshots(); - await t.applyMintSnapshot(); await t.setup(); + await t.applyMintSnapshot(); ({ provenAsset, accounts, tokenSim, logger, cheatCodes, provenWallet, aztecNode } = t); [sender, recipient] = accounts; diff --git a/yarn-project/end-to-end/src/e2e_token_contract/access_control.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/access_control.test.ts index 9a009e343e30..4e4dfa8ccb94 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/access_control.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/access_control.test.ts @@ -4,7 +4,6 @@ describe('e2e_token_contract access control', () => { const t = new TokenContractTest('access_control'); beforeAll(async () => { - await t.applyBaseSnapshots(); await t.setup(); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/burn.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/burn.test.ts index aae6c0c08362..bdb9c4770b40 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/burn.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/burn.test.ts @@ -9,9 +9,8 @@ describe('e2e_token_contract burn', () => { let { asset, tokenSim, wallet, adminAddress, account1Address, account2Address } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyMintSnapshot(); await t.setup(); + await t.mintTokens(); // Have to destructure again to ensure we have latest refs. ({ asset, wallet, adminAddress, tokenSim, adminAddress, account1Address, account2Address } = t); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/minting.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/minting.test.ts index cc26fb6f7d53..e016e5df0dd8 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/minting.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/minting.test.ts @@ -6,7 +6,6 @@ describe('e2e_token_contract minting', () => { let { asset, tokenSim, adminAddress, account1Address } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); await t.setup(); ({ asset, tokenSim, adminAddress, account1Address } = t); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts index 10d03d851386..17290def902a 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts @@ -8,7 +8,6 @@ describe('e2e_token_contract private transfer recursion', () => { let { asset, wallet, adminAddress, account1Address, node } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); await t.setup(); ({ asset, wallet, adminAddress, account1Address, node } = t); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/reading_constants.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/reading_constants.test.ts index aa11f767f224..74560dd2f0e7 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/reading_constants.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/reading_constants.test.ts @@ -7,7 +7,6 @@ describe('e2e_token_contract reading constants', () => { const { TOKEN_DECIMALS, TOKEN_NAME, TOKEN_SYMBOL } = TokenContractTest; beforeAll(async () => { - await t.applyBaseSnapshots(); await t.setup(); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/token_contract_test.ts b/yarn-project/end-to-end/src/e2e_token_contract/token_contract_test.ts index 36747e3e9366..0a96085538d6 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/token_contract_test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/token_contract_test.ts @@ -1,167 +1,120 @@ import { AztecAddress } from '@aztec/aztec.js/addresses'; -import { type Logger, createLogger } from '@aztec/aztec.js/log'; -import type { AztecNode } from '@aztec/aztec.js/node'; +import { createLogger } from '@aztec/aztec.js/log'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; import { InvalidAccountContract } from '@aztec/noir-test-contracts.js/InvalidAccount'; -import type { TestWallet } from '@aztec/test-wallet/server'; import { jest } from '@jest/globals'; -import { - type ISnapshotManager, - type SubsystemsContext, - createSnapshotManager, - deployAccounts, - publicDeployAccounts, -} from '../fixtures/snapshot_manager.js'; +import { BaseEndToEndTest } from '../fixtures/base_end_to_end_test.js'; import { mintTokensToPrivate } from '../fixtures/token_utils.js'; +import { ensureAccountContractsPublished } from '../fixtures/utils.js'; import { TokenSimulator } from '../simulators/token_simulator.js'; -const { E2E_DATA_PATH: dataPath, METRICS_PORT: metricsPort } = process.env; +const { METRICS_PORT: metricsPort } = process.env; -export class TokenContractTest { +export class TokenContractTest extends BaseEndToEndTest { static TOKEN_NAME = 'USDC'; static TOKEN_SYMBOL = 'USD'; static TOKEN_DECIMALS = 18n; - private snapshotManager: ISnapshotManager; - logger: Logger; asset!: TokenContract; tokenSim!: TokenSimulator; - node!: AztecNode; + + // Alias for compatibility + get node() { + return this.aztecNode; + } badAccount!: InvalidAccountContract; - wallet!: TestWallet; adminAddress!: AztecAddress; account1Address!: AztecAddress; account2Address!: AztecAddress; constructor(testName: string) { - this.logger = createLogger(`e2e:e2e_token_contract:${testName}`); - this.snapshotManager = createSnapshotManager(`e2e_token_contract/${testName}`, dataPath, { + super(testName, createLogger(`e2e:e2e_token_contract:${testName}`)); + } + + override async setup(): Promise { + await super.setup(3, { metricsPort: metricsPort ? parseInt(metricsPort) : undefined, }); + await this.deployContracts(); + return this; } /** - * Adds two state shifts to snapshot manager. + * Sets up base state: * 1. Add 3 accounts. * 2. Publicly deploy accounts, deploy token contract and a "bad account". */ - async applyBaseSnapshots() { + async deployContracts() { // Adding a timeout of 2 minutes in here such that it is propagated to the underlying tests jest.setTimeout(120_000); - await this.snapshotManager.snapshot( - '3_accounts', - deployAccounts(3, this.logger), - ({ deployedAccounts }, { wallet, aztecNode }) => { - this.node = aztecNode; - this.wallet = wallet; - [this.adminAddress, this.account1Address, this.account2Address] = deployedAccounts.map(acc => acc.address); - return Promise.resolve(); - }, + // Accounts are already deployed by setup() + [this.adminAddress, this.account1Address, this.account2Address] = this.accounts.slice(0, 3); + + // Public deploy accounts + this.logger.verbose(`Public deploy accounts...`); + await ensureAccountContractsPublished(this.wallet, [this.adminAddress, this.account1Address]); + + // Deploy token contract + this.logger.verbose(`Deploying TokenContract...`); + const asset = await TokenContract.deploy( + this.wallet, + this.adminAddress, + TokenContractTest.TOKEN_NAME, + TokenContractTest.TOKEN_SYMBOL, + TokenContractTest.TOKEN_DECIMALS, + ) + .send({ from: this.adminAddress }) + .deployed(); + this.logger.verbose(`Token deployed to ${asset.address}`); + + // Deploy bad account + this.logger.verbose(`Deploying bad account...`); + this.badAccount = await InvalidAccountContract.deploy(this.wallet).send({ from: this.adminAddress }).deployed(); + this.logger.verbose(`Deployed to ${this.badAccount.address}.`); + + // Setup asset reference + this.asset = await TokenContract.at(asset.address, this.wallet); + this.logger.verbose(`Token contract address: ${this.asset.address}`); + + this.tokenSim = new TokenSimulator(this.asset, this.wallet, this.adminAddress, this.logger, [ + this.adminAddress, + this.account1Address, + ]); + + this.logger.verbose(`Bad account address: ${this.badAccount.address}`); + + expect(await this.asset.methods.get_admin().simulate({ from: this.adminAddress })).toBe( + this.adminAddress.toBigInt(), ); + } - await this.snapshotManager.snapshot( - 'e2e_token_contract', - async () => { - // Create the token contract state. - // Move this account thing to addAccounts above? - this.logger.verbose(`Public deploy accounts...`); - await publicDeployAccounts(this.wallet, [this.adminAddress, this.account1Address]); - - this.logger.verbose(`Deploying TokenContract...`); - const asset = await TokenContract.deploy( - this.wallet, - this.adminAddress, - TokenContractTest.TOKEN_NAME, - TokenContractTest.TOKEN_SYMBOL, - TokenContractTest.TOKEN_DECIMALS, - ) - .send({ from: this.adminAddress }) - .deployed(); - this.logger.verbose(`Token deployed to ${asset.address}`); - - this.logger.verbose(`Deploying bad account...`); - this.badAccount = await InvalidAccountContract.deploy(this.wallet).send({ from: this.adminAddress }).deployed(); - this.logger.verbose(`Deployed to ${this.badAccount.address}.`); - - return { tokenContractAddress: asset.address, badAccountAddress: this.badAccount.address }; - }, - async ({ tokenContractAddress, badAccountAddress }) => { - // Restore the token contract state. - this.asset = await TokenContract.at(tokenContractAddress, this.wallet); - this.logger.verbose(`Token contract address: ${this.asset.address}`); - - this.tokenSim = new TokenSimulator(this.asset, this.wallet, this.adminAddress, this.logger, [ - this.adminAddress, - this.account1Address, - ]); - - this.badAccount = await InvalidAccountContract.at(badAccountAddress, this.wallet); - this.logger.verbose(`Bad account address: ${this.badAccount.address}`); - - expect(await this.asset.methods.get_admin().simulate({ from: this.adminAddress })).toBe( - this.adminAddress.toBigInt(), - ); - }, - ); + async mintTokens() { + const { asset, adminAddress, tokenSim } = this; + const amount = 10000n; - // TokenContract.artifact.functions.forEach(fn => { - // const sig = decodeFunctionSignature(fn.name, fn.parameters); - // logger.verbose(`Function ${sig} and the selector: ${FunctionSelector.fromNameAndParameters(fn.name, fn.parameters)}`); - // }); - } + this.logger.verbose(`Minting ${amount} publicly...`); + await asset.methods.mint_to_public(adminAddress, amount).send({ from: adminAddress }).wait(); - async setup() { - await this.snapshotManager.setup(); - } + this.logger.verbose(`Minting ${amount} privately...`); + await mintTokensToPrivate(asset, adminAddress, adminAddress, amount); + this.logger.verbose(`Minting complete.`); - snapshot = ( - name: string, - apply: (context: SubsystemsContext) => Promise, - restore: (snapshotData: T, context: SubsystemsContext) => Promise = () => Promise.resolve(), - ): Promise => this.snapshotManager.snapshot(name, apply, restore); + tokenSim.mintPublic(adminAddress, amount); - async teardown() { - await this.snapshotManager.teardown(); - } + const publicBalance = await asset.methods.balance_of_public(adminAddress).simulate({ from: adminAddress }); + this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`); + expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(adminAddress)); - async applyMintSnapshot() { - await this.snapshotManager.snapshot( - 'mint', - async () => { - const { asset, adminAddress } = this; - const amount = 10000n; - - this.logger.verbose(`Minting ${amount} publicly...`); - await asset.methods.mint_to_public(adminAddress, amount).send({ from: adminAddress }).wait(); - - this.logger.verbose(`Minting ${amount} privately...`); - await mintTokensToPrivate(asset, adminAddress, adminAddress, amount); - this.logger.verbose(`Minting complete.`); - - return { amount }; - }, - async ({ amount }) => { - const { asset, adminAddress, tokenSim } = this; - tokenSim.mintPublic(adminAddress, amount); - - const publicBalance = await asset.methods.balance_of_public(adminAddress).simulate({ from: adminAddress }); - this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`); - expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(adminAddress)); - - tokenSim.mintPrivate(adminAddress, amount); - const privateBalance = await asset.methods.balance_of_private(adminAddress).simulate({ from: adminAddress }); - this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`); - expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(adminAddress)); - - const totalSupply = await asset.methods.total_supply().simulate({ from: adminAddress }); - this.logger.verbose(`Total supply: ${totalSupply}`); - expect(totalSupply).toEqual(tokenSim.totalSupply); - - return Promise.resolve(); - }, - ); + tokenSim.mintPrivate(adminAddress, amount); + const privateBalance = await asset.methods.balance_of_private(adminAddress).simulate({ from: adminAddress }); + this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`); + expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(adminAddress)); + + const totalSupply = await asset.methods.total_supply().simulate({ from: adminAddress }); + this.logger.verbose(`Total supply: ${totalSupply}`); + expect(totalSupply).toEqual(tokenSim.totalSupply); } } diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts index eca283fff0fd..ee98a423f360 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts @@ -8,9 +8,8 @@ describe('e2e_token_contract transfer private', () => { let { asset, adminAddress, wallet, account1Address, tokenSim } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyMintSnapshot(); await t.setup(); + await t.mintTokens(); ({ asset, adminAddress, wallet, account1Address, tokenSim } = t); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_private.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_private.test.ts index f353e4a72e85..0082551e2d4f 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_private.test.ts @@ -9,9 +9,8 @@ describe('e2e_token_contract transfer private', () => { let { asset, tokenSim, wallet, adminAddress, account1Address, account2Address, badAccount } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyMintSnapshot(); await t.setup(); + await t.mintTokens(); ({ asset, tokenSim, wallet, adminAddress, account1Address, account2Address, badAccount } = t); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_public.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_public.test.ts index 38ad834fe4ce..ebac60c77cc5 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_public.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer_in_public.test.ts @@ -23,9 +23,8 @@ describe('e2e_token_contract transfer public', () => { let { asset, tokenSim, wallet, adminAddress, account1Address, badAccount } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyMintSnapshot(); await t.setup(); + await t.mintTokens(); // Have to destructure again to ensure we have latest refs. ({ asset, tokenSim, wallet, adminAddress, account1Address, badAccount } = t); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_private.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_private.test.ts index 91a291507c3d..c04fc06ae8ab 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_private.test.ts @@ -6,9 +6,8 @@ describe('e2e_token_contract transfer_to_private', () => { let { asset, adminAddress, account1Address, tokenSim } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyMintSnapshot(); await t.setup(); + await t.mintTokens(); // Have to destructure again to ensure we have latest refs. ({ asset, adminAddress, account1Address, tokenSim } = t); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_public.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_public.test.ts index d76d82f4e9b4..f2df56d4dbe0 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_public.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer_to_public.test.ts @@ -9,9 +9,8 @@ describe('e2e_token_contract transfer_to_public', () => { let { asset, wallet, adminAddress, account1Address, account2Address, tokenSim } = t; beforeAll(async () => { - await t.applyBaseSnapshots(); - await t.applyMintSnapshot(); await t.setup(); + await t.mintTokens(); // Have to destructure again to ensure we have latest refs. ({ asset, wallet, adminAddress, account1Address, account2Address, tokenSim } = t); }); diff --git a/yarn-project/end-to-end/src/fixtures/base_end_to_end_test.ts b/yarn-project/end-to-end/src/fixtures/base_end_to_end_test.ts new file mode 100644 index 000000000000..9fdce3eeba2b --- /dev/null +++ b/yarn-project/end-to-end/src/fixtures/base_end_to_end_test.ts @@ -0,0 +1,96 @@ +import type { InitialAccountData } from '@aztec/accounts/testing'; +import type { AztecNodeService } from '@aztec/aztec-node'; +import type { AztecAddress } from '@aztec/aztec.js/addresses'; +import type { Logger } from '@aztec/aztec.js/log'; +import type { CheatCodes } from '@aztec/aztec/testing'; +import type { BlobSinkServer } from '@aztec/blob-sink/server'; +import type { DeployL1ContractsReturnType } from '@aztec/ethereum'; +import type { EthCheatCodes } from '@aztec/ethereum/test'; +import type { TestDateProvider } from '@aztec/foundation/timer'; +import type { MockGossipSubNetwork } from '@aztec/p2p/test-helpers'; +import type { ProverNode } from '@aztec/prover-node'; +import type { SequencerClient } from '@aztec/sequencer-client'; +import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client'; +import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees'; +import type { TelemetryClient } from '@aztec/telemetry-client'; +import type { TestWallet } from '@aztec/test-wallet/server'; + +import type { Anvil } from '@viem/anvil'; + +import { type EndToEndContext, type SetupOptions, setup } from './utils.js'; + +/** + * Base class for end-to-end tests that provides common setup, teardown, and helper methods. + */ +export abstract class BaseEndToEndTest { + public context!: EndToEndContext; + + // Core services + public aztecNode!: AztecNodeService; + public aztecNodeAdmin?: AztecNodeAdmin; + public sequencer?: SequencerClient; + public proverNode?: ProverNode; + public wallet!: TestWallet; + public cheatCodes!: CheatCodes; + public ethCheatCodes!: EthCheatCodes; + public dateProvider?: TestDateProvider; + public blobSink?: BlobSinkServer; + public telemetryClient?: TelemetryClient; + + // L1 related + public deployL1ContractsValues!: DeployL1ContractsReturnType; + public anvil?: Anvil; + public watcher?: any; + + // Accounts + public accounts: AztecAddress[] = []; + public initialFundedAccounts: InitialAccountData[] = []; + + // P2P + public mockGossipSubNetwork?: MockGossipSubNetwork; + + // Other + public prefilledPublicData?: PublicDataTreeLeaf[]; + public logger: Logger; + + constructor( + public readonly testName: string, + logger: Logger, + ) { + this.logger = logger; + } + + /** + * Sets up the test environment with the given options. + */ + async setup(numberOfAccounts: number = 0, opts: SetupOptions = {}): Promise { + this.context = await setup(numberOfAccounts, opts); + + // Extract all the fields from context + this.aztecNode = this.context.aztecNode; + this.aztecNodeAdmin = this.context.aztecNodeAdmin; + this.sequencer = this.context.sequencer; + this.proverNode = this.context.proverNode; + this.wallet = this.context.wallet; + this.cheatCodes = this.context.cheatCodes; + this.ethCheatCodes = this.context.ethCheatCodes; + this.dateProvider = this.context.dateProvider; + this.blobSink = this.context.blobSink; + this.telemetryClient = this.context.telemetryClient; + this.deployL1ContractsValues = this.context.deployL1ContractsValues; + this.watcher = this.context.watcher; + this.accounts = this.context.accounts; + this.initialFundedAccounts = this.context.initialFundedAccounts; + this.mockGossipSubNetwork = this.context.mockGossipSubNetwork; + this.prefilledPublicData = this.context.prefilledPublicData; + + return this; + } + + /** + * Tears down the test environment. + */ + async teardown() { + await this.context?.teardown(); + } +} diff --git a/yarn-project/end-to-end/src/fixtures/e2e_prover_test.ts b/yarn-project/end-to-end/src/fixtures/e2e_prover_test.ts index 2c63ce590b96..d9fa24ad3bc3 100644 --- a/yarn-project/end-to-end/src/fixtures/e2e_prover_test.ts +++ b/yarn-project/end-to-end/src/fixtures/e2e_prover_test.ts @@ -1,9 +1,7 @@ import type { InitialAccountData } from '@aztec/accounts/testing'; import { type Archiver, createArchiver } from '@aztec/archiver'; -import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses'; -import { type Logger, createLogger } from '@aztec/aztec.js/log'; -import type { AztecNode } from '@aztec/aztec.js/node'; -import { CheatCodes } from '@aztec/aztec/testing'; +import { EthAddress } from '@aztec/aztec.js/addresses'; +import { createLogger } from '@aztec/aztec.js/log'; import { BBCircuitVerifier, type ClientProtocolCircuitVerifier, @@ -11,14 +9,12 @@ import { TestCircuitVerifier, } from '@aztec/bb-prover'; import { createBlobSinkClient } from '@aztec/blob-sink/client'; -import type { BlobSinkServer } from '@aztec/blob-sink/server'; import type { DeployL1ContractsReturnType } from '@aztec/ethereum'; import { Buffer32 } from '@aztec/foundation/buffer'; import { SecretValue } from '@aztec/foundation/config'; import { FeeAssetHandlerAbi } from '@aztec/l1-artifacts'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; import { type ProverNode, type ProverNodeConfig, createProverNode } from '@aztec/prover-node'; -import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client'; import { TestWallet } from '@aztec/test-wallet/server'; import { getGenesisValues } from '@aztec/world-state/testing'; @@ -26,18 +22,15 @@ import { type Hex, getContract } from 'viem'; import { privateKeyToAddress } from 'viem/accounts'; import { TokenSimulator } from '../simulators/token_simulator.js'; +import { BaseEndToEndTest } from './base_end_to_end_test.js'; import { getACVMConfig } from './get_acvm_config.js'; import { getBBConfig } from './get_bb_config.js'; import { - type ISnapshotManager, - type SubsystemsContext, - createSnapshotManager, - deployAccounts, - publicDeployAccounts, -} from './snapshot_manager.js'; -import { getPrivateKeyFromIndex, getSponsoredFPCAddress, setupPXEAndGetWallet } from './utils.js'; - -const { E2E_DATA_PATH: dataPath } = process.env; + ensureAccountContractsPublished, + getPrivateKeyFromIndex, + getSponsoredFPCAddress, + setupPXEAndGetWallet, +} from './utils.js'; type ProvenSetup = { wallet: TestWallet; @@ -51,125 +44,91 @@ type ProvenSetup = { * We then prove and verify transactions created via this full prover PXE. */ -export class FullProverTest { +export class FullProverTest extends BaseEndToEndTest { static TOKEN_NAME = 'USDC'; static TOKEN_SYMBOL = 'USD'; static TOKEN_DECIMALS = 18n; - private snapshotManager: ISnapshotManager; - logger: Logger; - wallet!: TestWallet; provenWallet!: TestWallet; - accounts: AztecAddress[] = []; deployedAccounts!: InitialAccountData[]; fakeProofsAsset!: TokenContract; tokenSim!: TokenSimulator; - aztecNode!: AztecNode; - aztecNodeAdmin!: AztecNodeAdmin; - cheatCodes!: CheatCodes; - blobSink!: BlobSinkServer; private provenComponents: ProvenSetup[] = []; private bbConfigCleanup?: () => Promise; private acvmConfigCleanup?: () => Promise; circuitProofVerifier?: ClientProtocolCircuitVerifier; provenAsset!: TokenContract; - private context!: SubsystemsContext; - private proverNode!: ProverNode; + private proverNodeInstance!: ProverNode; private simulatedProverNode!: ProverNode; - public l1Contracts!: DeployL1ContractsReturnType; public proverAddress!: EthAddress; + // Alias for compatibility with tests + get l1Contracts(): DeployL1ContractsReturnType { + return this.deployL1ContractsValues; + } + constructor( testName: string, private minNumberOfTxsPerBlock: number, - coinbase: EthAddress, + private coinbase: EthAddress, private realProofs = true, ) { - this.logger = createLogger(`e2e:full_prover_test:${testName}`); - this.snapshotManager = createSnapshotManager( - `full_prover_integration/${testName}`, - dataPath, - { startProverNode: true, fundRewardDistributor: true, coinbase }, - { - realVerifier: realProofs, - }, - ); + super(testName, createLogger(`e2e:full_prover_test:${testName}`)); } /** - * Adds two state shifts to snapshot manager. + * Sets up base state: * 1. Add 2 accounts. * 2. Publicly deploy accounts, deploy token contract */ async applyBaseSnapshots() { - await this.snapshotManager.snapshot( - '2_accounts', - deployAccounts(2, this.logger), - ({ deployedAccounts }, { wallet }) => { - this.deployedAccounts = deployedAccounts; - this.accounts = deployedAccounts.map(a => a.address); - this.wallet = wallet; - return Promise.resolve(); - }, - ); - - await this.snapshotManager.snapshot( - 'client_prover_integration', - async () => { - // Create the token contract state. - // Move this account thing to addAccounts above? - this.logger.verbose(`Public deploy accounts...`); - await publicDeployAccounts(this.wallet, this.accounts.slice(0, 2)); - - this.logger.verbose(`Deploying TokenContract...`); - const asset = await TokenContract.deploy( - this.wallet, - this.accounts[0], - FullProverTest.TOKEN_NAME, - FullProverTest.TOKEN_SYMBOL, - FullProverTest.TOKEN_DECIMALS, - ) - .send({ from: this.accounts[0] }) - .deployed(); - this.logger.verbose(`Token deployed to ${asset.address}`); - - return { tokenContractAddress: asset.address }; - }, - async ({ tokenContractAddress }) => { - // Restore the token contract state. - this.fakeProofsAsset = await TokenContract.at(tokenContractAddress, this.wallet); - this.logger.verbose(`Token contract address: ${this.fakeProofsAsset.address}`); - - this.tokenSim = new TokenSimulator( - this.fakeProofsAsset, - this.wallet, - this.accounts[0], - this.logger, - this.accounts, - ); - - expect(await this.fakeProofsAsset.methods.get_admin().simulate({ from: this.accounts[0] })).toBe( - this.accounts[0].toBigInt(), - ); - }, + // Accounts are already deployed by setup(), just use the deployed ones + this.deployedAccounts = this.initialFundedAccounts.slice(0, 2); + this.accounts = this.deployedAccounts.map(a => a.address); + + // Public deploy accounts + this.logger.verbose(`Public deploy accounts...`); + await ensureAccountContractsPublished(this.wallet, this.accounts.slice(0, 2)); + + // Deploy token contract + this.logger.verbose(`Deploying TokenContract...`); + const asset = await TokenContract.deploy( + this.wallet, + this.accounts[0], + FullProverTest.TOKEN_NAME, + FullProverTest.TOKEN_SYMBOL, + FullProverTest.TOKEN_DECIMALS, + ) + .send({ from: this.accounts[0] }) + .deployed(); + this.logger.verbose(`Token deployed to ${asset.address}`); + + this.fakeProofsAsset = await TokenContract.at(asset.address, this.wallet); + this.logger.verbose(`Token contract address: ${this.fakeProofsAsset.address}`); + + this.tokenSim = new TokenSimulator(this.fakeProofsAsset, this.wallet, this.accounts[0], this.logger, this.accounts); + + expect(await this.fakeProofsAsset.methods.get_admin().simulate({ from: this.accounts[0] })).toBe( + this.accounts[0].toBigInt(), ); } - async setup() { - this.context = await this.snapshotManager.setup(); + override async setup() { + await super.setup(2, { + startProverNode: true, + fundRewardDistributor: true, + coinbase: this.coinbase, + realProofs: this.realProofs, + }); + + // Initialize contracts and accounts + await this.applyBaseSnapshots(); // We don't wish to mark as proven automatically, so we set the flag to false - this.context.watcher.setIsMarkingAsProven(false); + this.context.watcher!.setIsMarkingAsProven(false); - this.simulatedProverNode = this.context.proverNode!; - ({ - aztecNode: this.aztecNode, - deployL1ContractsValues: this.l1Contracts, - cheatCodes: this.cheatCodes, - blobSink: this.blobSink, - } = this.context); - this.aztecNodeAdmin = this.context.aztecNode; + this.simulatedProverNode = this.proverNode!; - const blobSinkClient = createBlobSinkClient({ blobSinkUrl: `http://localhost:${this.blobSink.port}` }); + const blobSinkClient = createBlobSinkClient({ blobSinkUrl: `http://localhost:${this.blobSink!.port}` }); // Configure a full prover PXE let acvmConfig: Awaited> | undefined; @@ -191,14 +150,14 @@ export class FullProverTest { this.circuitProofVerifier = new QueuedIVCVerifier(bbConfig, verifier); this.logger.debug(`Configuring the node for real proofs...`); - await this.aztecNodeAdmin.setConfig({ + await this.aztecNodeAdmin!.setConfig({ realProofs: true, minTxsPerBlock: this.minNumberOfTxsPerBlock, }); } else { this.logger.debug(`Configuring the node min txs per block ${this.minNumberOfTxsPerBlock}...`); this.circuitProofVerifier = new TestCircuitVerifier(); - await this.aztecNodeAdmin.setConfig({ + await this.aztecNodeAdmin!.setConfig({ minTxsPerBlock: this.minNumberOfTxsPerBlock, }); } @@ -244,7 +203,7 @@ export class FullProverTest { // Creating temp store and archiver for fully proven prover node this.logger.verbose('Starting archiver for new prover node'); const archiver = await createArchiver( - { ...this.context.aztecNodeConfig, dataDirectory: undefined }, + { ...this.context.config, dataDirectory: undefined }, { blobSinkClient }, { blockUntilSync: true }, ); @@ -259,7 +218,7 @@ export class FullProverTest { this.logger.verbose('Starting prover node'); const proverConfig: ProverNodeConfig = { - ...this.context.aztecNodeConfig, + ...this.context.config, txCollectionNodeRpcUrls: [], dataDirectory: undefined, proverId: this.proverAddress, @@ -278,9 +237,9 @@ export class FullProverTest { }; const sponsoredFPCAddress = await getSponsoredFPCAddress(); const { prefilledPublicData } = await getGenesisValues( - this.context.initialFundedAccounts.map(a => a.address).concat(sponsoredFPCAddress), + this.initialFundedAccounts.map(a => a.address).concat(sponsoredFPCAddress), ); - this.proverNode = await createProverNode( + this.proverNodeInstance = await createProverNode( proverConfig, { aztecNodeTxProvider: this.aztecNode, @@ -289,86 +248,70 @@ export class FullProverTest { }, { prefilledPublicData }, ); - await this.proverNode.start(); + await this.proverNodeInstance.start(); this.logger.warn(`Proofs are now enabled`); return this; } private async mintFeeJuice(recipient: Hex) { - const handlerAddress = this.context.deployL1ContractsValues.l1ContractAddresses.feeAssetHandlerAddress!; + const handlerAddress = this.deployL1ContractsValues.l1ContractAddresses.feeAssetHandlerAddress!; this.logger.verbose(`Minting fee juice to ${recipient} using handler at ${handlerAddress}`); - const client = this.context.deployL1ContractsValues.l1Client; + const client = this.deployL1ContractsValues.l1Client; const handler = getContract({ abi: FeeAssetHandlerAbi, address: handlerAddress.toString(), client }); const hash = await handler.write.mint([recipient]); - await this.context.deployL1ContractsValues.l1Client.waitForTransactionReceipt({ hash }); + await this.deployL1ContractsValues.l1Client.waitForTransactionReceipt({ hash }); } - snapshot = ( - name: string, - apply: (context: SubsystemsContext) => Promise, - restore: (snapshotData: T, context: SubsystemsContext) => Promise = () => Promise.resolve(), - ): Promise => this.snapshotManager.snapshot(name, apply, restore); - - async teardown() { - await this.snapshotManager.teardown(); - + override async teardown() { // Cleanup related to the full prover PXEs for (let i = 0; i < this.provenComponents.length; i++) { await this.provenComponents[i].teardown(); } // clean up the full prover node - await this.proverNode.stop(); + await this.proverNodeInstance?.stop(); await this.bbConfigCleanup?.(); await this.acvmConfigCleanup?.(); + + await super.teardown(); } async applyMintSnapshot() { - await this.snapshotManager.snapshot( - 'mint', - async () => { - const { fakeProofsAsset: asset, accounts } = this; - const privateAmount = 10000n; - const publicAmount = 10000n; - - this.logger.verbose(`Minting ${privateAmount + publicAmount} publicly...`); - await asset.methods - .mint_to_public(accounts[0], privateAmount + publicAmount) - .send({ from: accounts[0] }) - .wait(); - - this.logger.verbose(`Transferring ${privateAmount} to private...`); - await asset.methods.transfer_to_private(accounts[0], privateAmount).send({ from: accounts[0] }).wait(); - - this.logger.verbose(`Minting complete.`); - - return { amount: publicAmount }; - }, - async ({ amount }) => { - const { - fakeProofsAsset: asset, - accounts: [address], - tokenSim, - } = this; - tokenSim.mintPublic(address, amount); - - const publicBalance = await asset.methods.balance_of_public(address).simulate({ from: address }); - this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`); - expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(address)); - - tokenSim.mintPrivate(address, amount); - const privateBalance = await asset.methods.balance_of_private(address).simulate({ from: address }); - this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`); - expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(address)); - - const totalSupply = await asset.methods.total_supply().simulate({ from: address }); - this.logger.verbose(`Total supply: ${totalSupply}`); - expect(totalSupply).toEqual(tokenSim.totalSupply); - - return Promise.resolve(); - }, - ); + const { fakeProofsAsset: asset, accounts } = this; + const privateAmount = 10000n; + const publicAmount = 10000n; + + this.logger.verbose(`Minting ${privateAmount + publicAmount} publicly...`); + await asset.methods + .mint_to_public(accounts[0], privateAmount + publicAmount) + .send({ from: accounts[0] }) + .wait(); + + this.logger.verbose(`Transferring ${privateAmount} to private...`); + await asset.methods.transfer_to_private(accounts[0], privateAmount).send({ from: accounts[0] }).wait(); + + this.logger.verbose(`Minting complete.`); + + const { + fakeProofsAsset, + accounts: [address], + tokenSim, + } = this; + tokenSim.mintPublic(address, publicAmount); + + const publicBalance = await fakeProofsAsset.methods.balance_of_public(address).simulate({ from: address }); + this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`); + expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(address)); + + tokenSim.mintPrivate(address, publicAmount); + const privateBalance = await fakeProofsAsset.methods.balance_of_private(address).simulate({ from: address }); + this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`); + expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(address)); + + const totalSupply = await fakeProofsAsset.methods.total_supply().simulate({ from: address }); + this.logger.verbose(`Total supply: ${totalSupply}`); + expect(totalSupply).toEqual(tokenSim.totalSupply); } } diff --git a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts deleted file mode 100644 index 69602ee18be9..000000000000 --- a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts +++ /dev/null @@ -1,665 +0,0 @@ -import { SchnorrAccountContractArtifact } from '@aztec/accounts/schnorr'; -import { type InitialAccountData, generateSchnorrAccounts } from '@aztec/accounts/testing'; -import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node'; -import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses'; -import { getContractClassFromArtifact } from '@aztec/aztec.js/contracts'; -import { BatchCall, type ContractFunctionInteraction, waitForProven } from '@aztec/aztec.js/contracts'; -import { publishContractClass, publishInstance } from '@aztec/aztec.js/deployment'; -import type { Logger } from '@aztec/aztec.js/log'; -import type { AztecNode } from '@aztec/aztec.js/node'; -import type { Wallet } from '@aztec/aztec.js/wallet'; -import { AnvilTestWatcher, CheatCodes } from '@aztec/aztec/testing'; -import { type BlobSinkServer, createBlobSinkServer } from '@aztec/blob-sink/server'; -import { - type DeployL1ContractsArgs, - type DeployL1ContractsReturnType, - createExtendedL1Client, - deployMulticall3, - getL1ContractsConfigEnvVars, -} from '@aztec/ethereum'; -import { EthCheatCodesWithState, startAnvil } from '@aztec/ethereum/test'; -import { asyncMap } from '@aztec/foundation/async-map'; -import { SecretValue } from '@aztec/foundation/config'; -import { randomBytes } from '@aztec/foundation/crypto'; -import { tryRmDir } from '@aztec/foundation/fs'; -import { createLogger } from '@aztec/foundation/log'; -import { resolver, reviver } from '@aztec/foundation/serialize'; -import { TestDateProvider } from '@aztec/foundation/timer'; -import type { ProverNode } from '@aztec/prover-node'; -import { getPXEConfig } from '@aztec/pxe/server'; -import type { SequencerClient } from '@aztec/sequencer-client'; -import { tryStop } from '@aztec/stdlib/interfaces/server'; -import { getConfigEnvVars as getTelemetryConfig, initTelemetryClient } from '@aztec/telemetry-client'; -import { TestWallet } from '@aztec/test-wallet/server'; -import { getGenesisValues } from '@aztec/world-state/testing'; - -import type { Anvil } from '@viem/anvil'; -import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'; -import { copySync, removeSync } from 'fs-extra/esm'; -import fs from 'fs/promises'; -import getPort from 'get-port'; -import { tmpdir } from 'os'; -import path, { join } from 'path'; -import type { Hex } from 'viem'; -import { mnemonicToAccount } from 'viem/accounts'; -import { foundry } from 'viem/chains'; - -import { MNEMONIC, TEST_MAX_TX_POOL_SIZE, TEST_PEER_CHECK_INTERVAL_MS } from './fixtures.js'; -import { getACVMConfig } from './get_acvm_config.js'; -import { getBBConfig } from './get_bb_config.js'; -import { setupL1Contracts } from './setup_l1_contracts.js'; -import { - type SetupOptions, - createAndSyncProverNode, - getLogger, - getPrivateKeyFromIndex, - getSponsoredFPCAddress, -} from './utils.js'; -import { getEndToEndTestTelemetryClient } from './with_telemetry_utils.js'; - -export type SubsystemsContext = { - anvil: Anvil; - acvmConfig: any; - bbConfig: any; - aztecNode: AztecNodeService; - aztecNodeConfig: AztecNodeConfig; - wallet: TestWallet; - deployL1ContractsValues: DeployL1ContractsReturnType; - proverNode?: ProverNode; - watcher: AnvilTestWatcher; - cheatCodes: CheatCodes; - sequencer: SequencerClient; - dateProvider: TestDateProvider; - blobSink: BlobSinkServer; - initialFundedAccounts: InitialAccountData[]; - directoryToCleanup?: string; -}; - -type SnapshotEntry = { - name: string; - apply: (context: SubsystemsContext) => Promise; - restore: (snapshotData: any, context: SubsystemsContext) => Promise; - snapshotPath: string; -}; - -export function createSnapshotManager( - testName: string, - dataPath?: string, - config: Partial = {}, - deployL1ContractsArgs: Partial = { - initialValidators: [], - }, -) { - return dataPath - ? new SnapshotManager(testName, dataPath, config, deployL1ContractsArgs) - : new MockSnapshotManager(testName, config, deployL1ContractsArgs); -} - -export interface ISnapshotManager { - snapshot( - name: string, - apply: (context: SubsystemsContext) => Promise, - restore?: (snapshotData: T, context: SubsystemsContext) => Promise, - ): Promise; - - setup(): Promise; - - teardown(): Promise; -} - -/** Snapshot manager that does not perform snapshotting, it just applies transition and restoration functions as it receives them. */ -class MockSnapshotManager implements ISnapshotManager { - private context?: SubsystemsContext; - private logger: Logger; - - constructor( - testName: string, - private config: Partial = {}, - private deployL1ContractsArgs: Partial = {}, - ) { - this.logger = createLogger(`e2e:snapshot_manager:${testName}`); - this.logger.warn(`No data path given, will not persist any snapshots.`); - } - - public async snapshot( - name: string, - apply: (context: SubsystemsContext) => Promise, - restore: (snapshotData: T, context: SubsystemsContext) => Promise = () => Promise.resolve(), - ) { - // We are running in disabled mode. Just apply the state. - const context = await this.setup(); - this.logger.verbose(`Applying state transition for ${name}...`); - const snapshotData = await apply(context); - this.logger.verbose(`State transition for ${name} complete.`); - // Execute the restoration function. - await restore(snapshotData, context); - return; - } - - public async setup() { - if (!this.context) { - this.context = await setupFromFresh(undefined, this.logger, this.config, this.deployL1ContractsArgs); - } - return this.context; - } - - public async teardown() { - await teardown(this.context); - this.context = undefined; - } -} - -/** - * Snapshot engine for local e2e tests. Read more: - * https://github.com/AztecProtocol/aztec-packages/pull/5526 - */ -class SnapshotManager implements ISnapshotManager { - private snapshotStack: SnapshotEntry[] = []; - private context?: SubsystemsContext; - private livePath: string; - private logger: Logger; - - constructor( - testName: string, - private dataPath: string, - private config: Partial = {}, - private deployL1ContractsArgs: Partial = {}, - ) { - this.livePath = join(this.dataPath, 'live', testName); - this.logger = createLogger(`e2e:snapshot_manager:${testName}`); - } - - public async snapshot( - name: string, - apply: (context: SubsystemsContext) => Promise, - restore: (snapshotData: T, context: SubsystemsContext) => Promise = () => Promise.resolve(), - ) { - const snapshotPath = join(this.dataPath, 'snapshots', ...this.snapshotStack.map(e => e.name), name, 'snapshot'); - - if (existsSync(snapshotPath)) { - // Snapshot exists. Record entry on stack but do nothing else as we're probably still descending the tree. - // It's the tests responsibility to call setup() before a test to ensure subsystems get created. - this.logger.verbose(`Snapshot exists at ${snapshotPath}. Continuing...`); - this.snapshotStack.push({ name, apply, restore, snapshotPath }); - return; - } - - // Snapshot didn't exist at snapshotPath, and by definition none of the child snapshots can exist. - // If we have no subsystem context yet, create it from the top of the snapshot stack (if it exists). - const context = await this.setup(); - - this.snapshotStack.push({ name, apply, restore, snapshotPath }); - - // Apply current state transition. - this.logger.verbose(`Applying state transition for ${name}...`); - const snapshotData = await apply(context); - this.logger.verbose(`State transition for ${name} complete.`); - - // Execute the restoration function. - await restore(snapshotData, context); - - // Save the snapshot data. - const ethCheatCodes = new EthCheatCodesWithState(context.aztecNodeConfig.l1RpcUrls, context.dateProvider); - const anvilStateFile = `${this.livePath}/anvil.dat`; - await ethCheatCodes.dumpChainState(anvilStateFile); - writeFileSync(`${this.livePath}/${name}.json`, JSON.stringify(snapshotData || {}, resolver)); - - // Copy everything to snapshot path. - // We want it to be atomic, in case multiple processes are racing to create the snapshot. - this.logger.verbose(`Saving snapshot to ${snapshotPath}...`); - if (mkdirSync(snapshotPath, { recursive: true })) { - copySync(this.livePath, snapshotPath); - this.logger.verbose(`Snapshot copied to ${snapshotPath}.`); - } else { - this.logger.verbose(`Snapshot already exists at ${snapshotPath}. Discarding our version.`); - await this.teardown(); - } - } - - /** - * Creates and returns the subsystem context based on the current snapshot stack. - * If the subsystem context already exists, just return it. - * If you want to be sure to get a clean snapshot, be sure to call teardown() before calling setup(). - */ - public async setup() { - // We have no subsystem context yet. - // If one exists on the snapshot stack, create one from that snapshot. - // Otherwise create a fresh one. - if (!this.context) { - removeSync(this.livePath); - mkdirSync(this.livePath, { recursive: true }); - const previousSnapshotPath = this.snapshotStack[this.snapshotStack.length - 1]?.snapshotPath; - if (previousSnapshotPath) { - this.logger.verbose(`Copying snapshot from ${previousSnapshotPath} to ${this.livePath}...`); - copySync(previousSnapshotPath, this.livePath); - this.context = await setupFromState(this.livePath, this.logger); - // Execute each of the previous snapshots restoration functions in turn. - await asyncMap(this.snapshotStack, async e => { - const snapshotData = JSON.parse(readFileSync(`${e.snapshotPath}/${e.name}.json`, 'utf-8'), reviver); - this.logger.verbose(`Executing restoration function for ${e.name}...`); - await e.restore(snapshotData, this.context!); - this.logger.verbose(`Restoration of ${e.name} complete.`); - }); - } else { - this.context = await setupFromFresh(this.livePath, this.logger, this.config, this.deployL1ContractsArgs); - } - } - return this.context; - } - - /** - * Destroys the current subsystem context. - */ - public async teardown() { - await teardown(this.context); - this.context = undefined; - removeSync(this.livePath); - } -} - -/** - * Destroys the current subsystem context. - */ -async function teardown(context: SubsystemsContext | undefined) { - if (!context) { - return; - } - const logger = getLogger(); - try { - logger.info('Tearing down subsystems'); - await tryStop(context.proverNode); - await tryStop(context.aztecNode); - await context.acvmConfig?.cleanup(); - await context.bbConfig?.cleanup(); - await tryStop(context.anvil); - await tryStop(context.watcher); - await tryStop(context.blobSink); - await tryRmDir(context.directoryToCleanup, logger); - } catch (err) { - logger.error('Error during teardown', err); - } -} - -/** - * Initializes a fresh set of subsystems. - * If given a statePath, the state will be written to the path. - * If there is no statePath, in-memory and temporary state locations will be used. - */ -async function setupFromFresh( - statePath: string | undefined, - logger: Logger, - { numberOfInitialFundedAccounts = 10, ...opts }: SetupOptions = {}, - deployL1ContractsArgs: Partial = { - initialValidators: [], - }, -): Promise { - logger.verbose(`Initializing state...`); - - const blobSinkPort = await getPort(); - - // Default to no slashing - opts.slasherFlavor ??= 'none'; - deployL1ContractsArgs.slasherFlavor ??= opts.slasherFlavor; - - // Fetch the AztecNode config. - // TODO: For some reason this is currently the union of a bunch of subsystems. That needs fixing. - const aztecNodeConfig: AztecNodeConfig & SetupOptions = { ...getConfigEnvVars(), ...opts }; - aztecNodeConfig.peerCheckIntervalMS = TEST_PEER_CHECK_INTERVAL_MS; - aztecNodeConfig.maxTxPoolSize = opts.maxTxPoolSize ?? TEST_MAX_TX_POOL_SIZE; - // Only enable proving if specifically requested. - aztecNodeConfig.realProofs = !!opts.realProofs; - // Only enforce the time table if requested - aztecNodeConfig.enforceTimeTable = !!opts.enforceTimeTable; - // Only set the target committee size if it is explicitly set - aztecNodeConfig.aztecTargetCommitteeSize = opts.aztecTargetCommitteeSize ?? 0; - aztecNodeConfig.listenAddress = '127.0.0.1'; - - deployL1ContractsArgs.aztecTargetCommitteeSize ??= aztecNodeConfig.aztecTargetCommitteeSize; - - // Create a temp directory for all ephemeral state and cleanup afterwards - const directoryToCleanup = path.join(tmpdir(), randomBytes(8).toString('hex')); - await fs.mkdir(directoryToCleanup, { recursive: true }); - if (statePath === undefined) { - aztecNodeConfig.dataDirectory = directoryToCleanup; - } else { - aztecNodeConfig.dataDirectory = statePath; - } - aztecNodeConfig.blobSinkUrl = `http://127.0.0.1:${blobSinkPort}`; - - const hdAccount = mnemonicToAccount(MNEMONIC, { addressIndex: 0 }); - const publisherPrivKeyRaw = hdAccount.getHdKey().privateKey; - const publisherPrivKey = publisherPrivKeyRaw === null ? null : Buffer.from(publisherPrivKeyRaw); - - const l1Client = createExtendedL1Client([aztecNodeConfig.l1RpcUrls[0]], hdAccount, foundry); - - const validatorPrivKey = getPrivateKeyFromIndex(0); - const proverNodePrivateKey = getPrivateKeyFromIndex(0); - - aztecNodeConfig.publisherPrivateKeys = [new SecretValue<`0x${string}`>(`0x${publisherPrivKey!.toString('hex')}`)]; - aztecNodeConfig.validatorPrivateKeys = new SecretValue([`0x${validatorPrivKey!.toString('hex')}`]); - aztecNodeConfig.coinbase = opts.coinbase ?? EthAddress.fromString(`${hdAccount.address}`); - - logger.info(`Setting up environment with config`, aztecNodeConfig); - - // Start anvil. We go via a wrapper script to ensure if the parent dies, anvil dies. - logger.verbose('Starting anvil...'); - const res = await startAnvil({ l1BlockTime: opts.ethereumSlotDuration }); - const anvil = res.anvil; - aztecNodeConfig.l1RpcUrls = [res.rpcUrl]; - - const dateProvider = new TestDateProvider(); - const ethCheatCodes = new EthCheatCodesWithState(aztecNodeConfig.l1RpcUrls, dateProvider); - - // Deploy our L1 contracts. - logger.verbose('Deploying L1 contracts...'); - if (opts.l1StartTime) { - await ethCheatCodes.warp(opts.l1StartTime, { resetBlockInterval: true }); - } - - const initialFundedAccounts = await generateSchnorrAccounts(numberOfInitialFundedAccounts); - const sponsoredFPCAddress = await getSponsoredFPCAddress(); - const { genesisArchiveRoot, prefilledPublicData, fundingNeeded } = await getGenesisValues( - initialFundedAccounts.map(a => a.address).concat(sponsoredFPCAddress), - opts.initialAccountFeeJuice, - ); - - await deployMulticall3(l1Client, logger); - - const deployL1ContractsValues = await setupL1Contracts(aztecNodeConfig.l1RpcUrls[0], hdAccount, logger, { - ...getL1ContractsConfigEnvVars(), - genesisArchiveRoot, - feeJuicePortalInitialBalance: fundingNeeded, - salt: opts.salt, - ...deployL1ContractsArgs, - initialValidators: opts.initialValidators, - }); - aztecNodeConfig.l1Contracts = deployL1ContractsValues.l1ContractAddresses; - aztecNodeConfig.rollupVersion = deployL1ContractsValues.rollupVersion; - - const watcher = new AnvilTestWatcher( - new EthCheatCodesWithState(aztecNodeConfig.l1RpcUrls, dateProvider), - deployL1ContractsValues.l1ContractAddresses.rollupAddress, - deployL1ContractsValues.l1Client, - dateProvider, - ); - await watcher.start(); - - const acvmConfig = await getACVMConfig(logger); - if (acvmConfig) { - aztecNodeConfig.acvmWorkingDirectory = acvmConfig.acvmWorkingDirectory; - aztecNodeConfig.acvmBinaryPath = acvmConfig.acvmBinaryPath; - } - - const bbConfig = await getBBConfig(logger); - if (bbConfig) { - aztecNodeConfig.bbBinaryPath = bbConfig.bbBinaryPath; - aztecNodeConfig.bbWorkingDirectory = bbConfig.bbWorkingDirectory; - } - - const telemetry = getEndToEndTestTelemetryClient(opts.metricsPort); - - // Setup blob sink service - const blobSink = await createBlobSinkServer( - { - l1ChainId: aztecNodeConfig.l1ChainId, - l1RpcUrls: aztecNodeConfig.l1RpcUrls, - l1Contracts: aztecNodeConfig.l1Contracts, - port: blobSinkPort, - dataDirectory: aztecNodeConfig.dataDirectory, - dataStoreMapSizeKb: aztecNodeConfig.dataStoreMapSizeKb, - }, - telemetry, - ); - await blobSink.start(); - - logger.info('Creating and synching an aztec node...'); - const aztecNode = await AztecNodeService.createAndSync( - aztecNodeConfig, - { telemetry, dateProvider }, - { prefilledPublicData }, - ); - - let proverNode: ProverNode | undefined = undefined; - if (opts.startProverNode) { - logger.verbose('Creating and syncing a simulated prover node with p2p disabled...'); - proverNode = await createAndSyncProverNode( - `0x${proverNodePrivateKey!.toString('hex')}`, - aztecNodeConfig, - { - ...aztecNodeConfig.proverNodeConfig, - dataDirectory: path.join(directoryToCleanup, randomBytes(8).toString('hex')), - p2pEnabled: false, - }, - aztecNode, - prefilledPublicData, - ); - } - - logger.verbose('Creating pxe...'); - const pxeConfig = getPXEConfig(); - pxeConfig.dataDirectory = statePath ?? path.join(directoryToCleanup, randomBytes(8).toString('hex')); - // Only enable proving if specifically requested. - pxeConfig.proverEnabled = !!opts.realProofs; - const wallet = await TestWallet.create(aztecNode, pxeConfig); - const cheatCodes = await CheatCodes.create(aztecNodeConfig.l1RpcUrls, aztecNode, dateProvider); - - if (statePath) { - writeFileSync(`${statePath}/aztec_node_config.json`, JSON.stringify(aztecNodeConfig, resolver)); - writeFileSync(`${statePath}/accounts.json`, JSON.stringify(initialFundedAccounts, resolver)); - } - - return { - aztecNodeConfig, - anvil, - aztecNode, - wallet, - sequencer: aztecNode.getSequencer()!, - acvmConfig, - bbConfig, - deployL1ContractsValues, - proverNode, - watcher, - cheatCodes, - dateProvider, - blobSink, - initialFundedAccounts, - directoryToCleanup, - }; -} - -/** - * Given a statePath, setup the system starting from that state. - */ -async function setupFromState(statePath: string, logger: Logger): Promise { - logger.verbose(`Initializing with saved state at ${statePath}...`); - - const directoryToCleanup = path.join(tmpdir(), randomBytes(8).toString('hex')); - await fs.mkdir(directoryToCleanup, { recursive: true }); - - // Run the blob sink on a random port - const blobSinkPort = await getPort(); - - // TODO: For some reason this is currently the union of a bunch of subsystems. That needs fixing. - const aztecNodeConfig: AztecNodeConfig & SetupOptions = JSON.parse( - readFileSync(`${statePath}/aztec_node_config.json`, 'utf-8'), - reviver, - ); - aztecNodeConfig.dataDirectory = statePath; - aztecNodeConfig.blobSinkUrl = `http://127.0.0.1:${blobSinkPort}`; - aztecNodeConfig.listenAddress = '127.0.0.1'; - - const initialFundedAccounts: InitialAccountData[] = - JSON.parse(readFileSync(`${statePath}/accounts.json`, 'utf-8'), reviver) || []; - const { prefilledPublicData } = await getGenesisValues(initialFundedAccounts.map(a => a.address)); - - // Start anvil. We go via a wrapper script to ensure if the parent dies, anvil dies. - const { anvil, rpcUrl } = await startAnvil(); - aztecNodeConfig.l1RpcUrls = [rpcUrl]; - // Load anvil state. - const anvilStateFile = `${statePath}/anvil.dat`; - - const dateProvider = new TestDateProvider(); - const ethCheatCodes = new EthCheatCodesWithState(aztecNodeConfig.l1RpcUrls, dateProvider); - await ethCheatCodes.loadChainState(anvilStateFile); - - // TODO: Encapsulate this in a NativeAcvm impl. - const acvmConfig = await getACVMConfig(logger); - if (acvmConfig) { - aztecNodeConfig.acvmWorkingDirectory = acvmConfig.acvmWorkingDirectory; - aztecNodeConfig.acvmBinaryPath = acvmConfig.acvmBinaryPath; - } - - const bbConfig = await getBBConfig(logger); - if (bbConfig) { - aztecNodeConfig.bbBinaryPath = bbConfig.bbBinaryPath; - aztecNodeConfig.bbWorkingDirectory = bbConfig.bbWorkingDirectory; - } - - logger.verbose('Creating ETH clients...'); - const l1Client = createExtendedL1Client(aztecNodeConfig.l1RpcUrls, mnemonicToAccount(MNEMONIC)); - - const watcher = new AnvilTestWatcher( - ethCheatCodes, - aztecNodeConfig.l1Contracts.rollupAddress, - l1Client, - dateProvider, - ); - await watcher.start(); - - const telemetry = initTelemetryClient(getTelemetryConfig()); - const blobSink = await createBlobSinkServer( - { - l1ChainId: aztecNodeConfig.l1ChainId, - l1RpcUrls: aztecNodeConfig.l1RpcUrls, - l1Contracts: aztecNodeConfig.l1Contracts, - port: blobSinkPort, - dataDirectory: statePath, - dataStoreMapSizeKb: aztecNodeConfig.dataStoreMapSizeKb, - }, - telemetry, - ); - await blobSink.start(); - - logger.verbose('Creating aztec node...'); - const aztecNode = await AztecNodeService.createAndSync( - aztecNodeConfig, - { telemetry, dateProvider }, - { prefilledPublicData }, - ); - - let proverNode: ProverNode | undefined = undefined; - if (aztecNodeConfig.startProverNode) { - logger.verbose('Creating and syncing a simulated prover node...'); - const proverNodePrivateKey = getPrivateKeyFromIndex(2); - const proverNodePrivateKeyHex: Hex = `0x${proverNodePrivateKey!.toString('hex')}`; - proverNode = await createAndSyncProverNode( - proverNodePrivateKeyHex, - aztecNodeConfig, - { - ...aztecNodeConfig.proverNodeConfig, - dataDirectory: path.join(directoryToCleanup, randomBytes(8).toString('hex')), - p2pEnabled: false, - }, - aztecNode, - prefilledPublicData, - ); - } - - logger.verbose('Creating pxe...'); - const pxeConfig = getPXEConfig(); - pxeConfig.dataDirectory = statePath; - const wallet = await TestWallet.create(aztecNode, pxeConfig); - const cheatCodes = await CheatCodes.create(aztecNodeConfig.l1RpcUrls, aztecNode, dateProvider); - - return { - aztecNodeConfig, - anvil, - aztecNode, - wallet, - sequencer: aztecNode.getSequencer()!, - acvmConfig, - bbConfig, - proverNode, - deployL1ContractsValues: { - l1Client, - l1ContractAddresses: aztecNodeConfig.l1Contracts, - rollupVersion: aztecNodeConfig.rollupVersion, - }, - watcher, - cheatCodes, - dateProvider, - blobSink, - initialFundedAccounts, - directoryToCleanup, - }; -} - -/** - * Snapshot 'apply' helper function to add accounts. - * The 'restore' function is not provided, as it must be a closure within the test context to capture the results. - */ -export const deployAccounts = - (numberOfAccounts: number, logger: Logger) => - async ({ wallet, initialFundedAccounts }: { wallet: TestWallet; initialFundedAccounts: InitialAccountData[] }) => { - if (initialFundedAccounts.length < numberOfAccounts) { - throw new Error(`Cannot deploy more than ${initialFundedAccounts.length} initial accounts.`); - } - - logger.verbose('Deploying accounts funded with fee juice...'); - const deployedAccounts = initialFundedAccounts.slice(0, numberOfAccounts); - // Serial due to https://github.com/AztecProtocol/aztec-packages/issues/12045 - for (let i = 0; i < deployedAccounts.length; i++) { - const accountManager = await wallet.createSchnorrAccount( - deployedAccounts[i].secret, - deployedAccounts[i].salt, - deployedAccounts[i].signingKey, - ); - const deployMethod = await accountManager.getDeployMethod(); - await deployMethod - .send({ - from: AztecAddress.ZERO, - skipClassPublication: i !== 0, // Publish the contract class at most once. - }) - .wait(); - } - - return { deployedAccounts }; - }; - -/** - * Registers the contract class used for test accounts and publicly deploys the instances requested. - * Use this when you need to make a public call to an account contract, such as for requesting a public authwit. - * @param sender - Wallet to send the deployment tx. - * @param accountsToDeploy - Which accounts to publicly deploy. - * @param waitUntilProven - Whether to wait for the tx to be proven. - * @param node - AztecNode used to wait for proven tx. - */ -export async function publicDeployAccounts( - wallet: Wallet, - accountsToDeploy: AztecAddress[], - waitUntilProven = false, - node?: AztecNode, -) { - const instances = (await Promise.all(accountsToDeploy.map(account => wallet.getContractMetadata(account)))).map( - metadata => metadata.contractInstance, - ); - - const contractClass = await getContractClassFromArtifact(SchnorrAccountContractArtifact); - const alreadyRegistered = (await wallet.getContractClassMetadata(contractClass.id)).isContractClassPubliclyRegistered; - - const calls: ContractFunctionInteraction[] = await Promise.all([ - ...(!alreadyRegistered ? [publishContractClass(wallet, SchnorrAccountContractArtifact)] : []), - ...instances.map(instance => publishInstance(wallet, instance!)), - ]); - - const batch = new BatchCall(wallet, calls); - - const txReceipt = await batch.send({ from: accountsToDeploy[0] }).wait(); - if (waitUntilProven) { - if (!node) { - throw new Error('Need to provide an AztecNode to wait for proven.'); - } else { - await waitForProven(node, txReceipt); - } - } -} diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index f545398ea60a..7ba361fbbd1f 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -190,12 +190,12 @@ export async function setupPXEAndGetWallet( * (will create extra accounts if the environment doesn't already have enough accounts) * @returns Private eXecution Environment (PXE) client, viem wallets, contract addresses etc. */ -async function setupWithRemoteEnvironment( +export async function setupWithRemoteEnvironment( account: HDAccount | PrivateKeyAccount, config: AztecNodeConfig, logger: Logger, numberOfAccounts: number, -): Promise { +): Promise { // we are setting up against a remote environment, l1 contracts are already deployed const aztecNodeUrl = getAztecUrl(); logger.verbose(`Creating Aztec Node client to remote host ${aztecNodeUrl}`); @@ -215,7 +215,6 @@ async function setupWithRemoteEnvironment( const ethCheatCodes = new EthCheatCodes(config.l1RpcUrls, new DateProvider()); const wallet = await TestWallet.create(aztecNode); const cheatCodes = await CheatCodes.create(config.l1RpcUrls, aztecNode, new DateProvider()); - const teardown = () => Promise.resolve(); logger.verbose('Populating wallet from already registered accounts...'); const initialFundedAccounts = await getInitialTestAccountsData(); @@ -234,9 +233,6 @@ async function setupWithRemoteEnvironment( return { aztecNode, - aztecNodeAdmin: undefined, - sequencer: undefined, - proverNode: undefined, deployL1ContractsValues, config, initialFundedAccounts, @@ -245,13 +241,6 @@ async function setupWithRemoteEnvironment( logger, cheatCodes, ethCheatCodes, - prefilledPublicData: undefined, - mockGossipSubNetwork: undefined, - watcher: undefined, - dateProvider: undefined, - blobSink: undefined, - telemetryClient: undefined, - teardown, }; } @@ -301,18 +290,14 @@ export type SetupOptions = { anvilPort?: number; /** Key to use for publishing L1 contracts */ l1PublisherKey?: SecretValue<`0x${string}`>; + /** Arguments for L1 contract deployment */ + deployL1ContractsArgs?: Partial; } & Partial; -/** Context for an end-to-end test as returned by the `setup` function */ -export type EndToEndContext = { +/** Context for an end-to-end test as returned by the `setupWithRemoteEnvironment` function */ +export type RemoteEndToEndContext = { /** The Aztec Node service or client a connected to it. */ aztecNode: AztecNode; - /** Client to the Aztec Node admin interface (undefined if connected to remote environment) */ - aztecNodeAdmin?: AztecNodeAdmin; - /** The prover node service (only set if startProverNode is true) */ - proverNode: ProverNode | undefined; - /** A client to the sequencer service (undefined if connected to remote environment) */ - sequencer: SequencerClient | undefined; /** Return values from deployL1Contracts function. */ deployL1ContractsValues: DeployL1ContractsReturnType; /** The Aztec Node configuration. */ @@ -329,18 +314,30 @@ export type EndToEndContext = { cheatCodes: CheatCodes; /** The cheat codes for L1 */ ethCheatCodes: EthCheatCodes; - /** The anvil test watcher (undefined if connected to remote environment) */ - watcher: AnvilTestWatcher | undefined; - /** Allows tweaking current system time, used by the epoch cache only (undefined if connected to remote environment) */ - dateProvider: TestDateProvider | undefined; - /** The blob sink (undefined if connected to remote environment) */ - blobSink: BlobSinkServer | undefined; +}; + +/** Context for an end-to-end test as returned by the `setup` function */ +export type EndToEndContext = RemoteEndToEndContext & { + /** Aztec Node service */ + aztecNode: AztecNodeService; + /** Client to the Aztec Node admin interface */ + aztecNodeAdmin?: AztecNodeAdmin; + /** The prover node service (only set if startProverNode is true) */ + proverNode: ProverNode | undefined; + /** A client to the sequencer service */ + sequencer: SequencerClient | undefined; + /** The anvil test watcher */ + watcher: AnvilTestWatcher; + /** Allows tweaking current system time */ + dateProvider: TestDateProvider; + /** The blob sink */ + blobSink: BlobSinkServer; /** Telemetry client */ - telemetryClient: TelemetryClient | undefined; + telemetryClient: TelemetryClient; /** Mock gossip sub network used for gossipping messages (only if mockGossipSubNetwork was set to true in opts) */ mockGossipSubNetwork: MockGossipSubNetwork | undefined; /** Prefilled public data used for setting up nodes. */ - prefilledPublicData: PublicDataTreeLeaf[] | undefined; + prefilledPublicData: PublicDataTreeLeaf[]; /** Function to stop the started services. */ teardown: () => Promise; }; @@ -374,6 +371,12 @@ export async function setup( const logger = getLogger(); + if (AZTEC_NODE_URL) { + throw new Error( + `Setting AZTEC_NODE_URL is not supported in this setup function. Use setupWithRemoteEnvironment instead.`, + ); + } + // Create a temp directory for any services that need it and cleanup later const directoryToCleanup = path.join(tmpdir(), randomBytes(8).toString('hex')); await fs.mkdir(directoryToCleanup, { recursive: true }); @@ -385,11 +388,6 @@ export async function setup( if (!isAnvilTestChain(chain.id)) { throw new Error(`No ETHEREUM_HOSTS set but non anvil chain requested`); } - if (AZTEC_NODE_URL) { - throw new Error( - `AZTEC_NODE_URL provided but no ETHEREUM_HOSTS set. Refusing to run, please set both variables so tests can deploy L1 contracts to the same Anvil instance`, - ); - } const res = await startAnvil({ l1BlockTime: opts.ethereumSlotDuration, @@ -440,11 +438,6 @@ export async function setup( config.coinbase = EthAddress.fromString(publisherHdAccount.address); - if (AZTEC_NODE_URL) { - // we are setting up against a remote environment, l1 contracts are assumed to already be deployed - return await setupWithRemoteEnvironment(publisherHdAccount!, config, logger, numberOfAccounts); - } - const initialFundedAccounts = opts.initialFundedAccounts ?? (await generateSchnorrAccounts(opts.numberOfInitialFundedAccounts ?? numberOfAccounts)); @@ -471,6 +464,7 @@ export async function setup( logger, { ...opts, + ...opts.deployL1ContractsArgs, genesisArchiveRoot, feeJuicePortalInitialBalance: fundingNeeded, initialValidators: opts.initialValidators, @@ -657,7 +651,7 @@ export async function setup( } // Now we restore the original minTxsPerBlock setting. - sequencerClient!.getSequencer().updateConfig({ minTxsPerBlock: originalMinTxsPerBlock }); + sequencerClient?.getSequencer().updateConfig({ minTxsPerBlock: originalMinTxsPerBlock }); if (initialFundedAccounts.length < numberOfAccounts) { // TODO: Create (numberOfAccounts - initialFundedAccounts.length) wallets without funds. diff --git a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts index f63e0f520ba9..3f7fd93c4ac2 100644 --- a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts +++ b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts @@ -40,7 +40,7 @@ class SchnorrHardcodedKeyAccountContract extends DefaultAccountContract { } } -describe('guides/writing_an_account_contract', () => { +describe.skip('guides/writing_an_account_contract', () => { let context: Awaited>; beforeEach(async () => { diff --git a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts index 2f20bdc6ab5b..8ad69ba9f110 100644 --- a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts @@ -1,3 +1,4 @@ +import type { AztecNodeService } from '@aztec/aztec-node'; import type { AztecAddress } from '@aztec/aztec.js/addresses'; import { EthAddress } from '@aztec/aztec.js/addresses'; import { AuthWitness } from '@aztec/aztec.js/authorization'; @@ -9,7 +10,6 @@ import { } from '@aztec/aztec.js/ethereum'; import { Fr } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; -import type { AztecNode } from '@aztec/aztec.js/node'; import type { SiblingPath } from '@aztec/aztec.js/trees'; import type { TxReceipt } from '@aztec/aztec.js/tx'; import type { Wallet } from '@aztec/aztec.js/wallet'; @@ -126,7 +126,7 @@ export type CrossChainContext = { */ export class CrossChainTestHarness { static async new( - aztecNode: AztecNode, + aztecNode: AztecNodeService, l1Client: ExtendedViemWalletClient, wallet: Wallet, ownerAddress: AztecAddress, @@ -167,7 +167,7 @@ export class CrossChainTestHarness { constructor( /** Aztec node instance. */ - public aztecNode: AztecNode, + public aztecNode: AztecNodeService, /** Logger. */ public logger: Logger, diff --git a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts index 119115660bf4..2264232e2144 100644 --- a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts +++ b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts @@ -1,9 +1,9 @@ +import type { AztecNodeService } from '@aztec/aztec-node'; import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses'; import { computeAuthWitMessageHash } from '@aztec/aztec.js/authorization'; import { generateClaimSecret } from '@aztec/aztec.js/ethereum'; import { Fr } from '@aztec/aztec.js/fields'; import type { Logger } from '@aztec/aztec.js/log'; -import type { AztecNode } from '@aztec/aztec.js/node'; import { CheatCodes } from '@aztec/aztec/testing'; import { type DeployL1ContractsReturnType, @@ -37,7 +37,7 @@ const TIMEOUT = 360_000; /** Objects to be returned by the uniswap setup function */ export type UniswapSetupContext = { /** Aztec Node instance */ - aztecNode: AztecNode; + aztecNode: AztecNodeService; /** Logger instance named as the current test. */ logger: Logger; /** The L1 wallet client, extended with public actions. */ @@ -65,7 +65,7 @@ export const uniswapL1L2TestSuite = ( const WETH9_ADDRESS: EthAddress = EthAddress.fromString('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'); const DAI_ADDRESS: EthAddress = EthAddress.fromString('0x6B175474E89094C44Da98b954EedeAC495271d0F'); - let aztecNode: AztecNode; + let aztecNode: AztecNodeService; let logger: Logger; let l1Client: ExtendedViemWalletClient;