@aztec/end-to-end 0.0.1-commit.ef17749e1 → 0.0.1-commit.f103f88

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +27 -0
  2. package/dest/bench/client_flows/client_flows_benchmark.d.ts +1 -1
  3. package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
  4. package/dest/bench/client_flows/client_flows_benchmark.js +13 -28
  5. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +3 -2
  6. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
  7. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +1 -1
  8. package/dest/e2e_epochs/epochs_test.d.ts +3 -1
  9. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  10. package/dest/e2e_epochs/epochs_test.js +8 -5
  11. package/dest/e2e_fees/fees_test.js +1 -1
  12. package/dest/e2e_p2p/inactivity_slash_test.js +3 -3
  13. package/dest/e2e_p2p/p2p_network.d.ts +5 -7
  14. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  15. package/dest/e2e_p2p/p2p_network.js +14 -13
  16. package/dest/e2e_p2p/reqresp/utils.d.ts +1 -1
  17. package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -1
  18. package/dest/e2e_p2p/reqresp/utils.js +16 -3
  19. package/dest/e2e_p2p/shared.d.ts +16 -12
  20. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  21. package/dest/e2e_p2p/shared.js +33 -51
  22. package/dest/fixtures/authwit_proxy.d.ts +1 -1
  23. package/dest/fixtures/authwit_proxy.d.ts.map +1 -1
  24. package/dest/fixtures/authwit_proxy.js +4 -0
  25. package/dest/fixtures/e2e_prover_test.d.ts +4 -3
  26. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  27. package/dest/fixtures/e2e_prover_test.js +7 -12
  28. package/dest/fixtures/get_bb_config.d.ts +1 -1
  29. package/dest/fixtures/get_bb_config.d.ts.map +1 -1
  30. package/dest/fixtures/get_bb_config.js +5 -5
  31. package/dest/fixtures/setup.d.ts +16 -8
  32. package/dest/fixtures/setup.d.ts.map +1 -1
  33. package/dest/fixtures/setup.js +24 -18
  34. package/dest/fixtures/setup_p2p_test.d.ts +6 -6
  35. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  36. package/dest/fixtures/setup_p2p_test.js +8 -8
  37. package/dest/fixtures/token_utils.d.ts +1 -1
  38. package/dest/fixtures/token_utils.d.ts.map +1 -1
  39. package/dest/fixtures/token_utils.js +2 -5
  40. package/dest/legacy-jest-resolver.d.cts +3 -0
  41. package/dest/legacy-jest-resolver.d.cts.map +1 -0
  42. package/dest/shared/uniswap_l1_l2.d.ts +1 -1
  43. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  44. package/dest/shared/uniswap_l1_l2.js +9 -12
  45. package/dest/simulators/lending_simulator.d.ts +1 -1
  46. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  47. package/dest/simulators/lending_simulator.js +2 -2
  48. package/dest/simulators/token_simulator.js +1 -1
  49. package/dest/spartan/setup_test_wallets.d.ts +4 -2
  50. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  51. package/dest/spartan/setup_test_wallets.js +69 -39
  52. package/dest/spartan/utils/config.d.ts +4 -1
  53. package/dest/spartan/utils/config.d.ts.map +1 -1
  54. package/dest/spartan/utils/config.js +1 -0
  55. package/dest/spartan/utils/index.d.ts +2 -1
  56. package/dest/spartan/utils/index.d.ts.map +1 -1
  57. package/dest/spartan/utils/index.js +2 -0
  58. package/dest/spartan/utils/pod_logs.d.ts +25 -0
  59. package/dest/spartan/utils/pod_logs.d.ts.map +1 -0
  60. package/dest/spartan/utils/pod_logs.js +74 -0
  61. package/dest/test-wallet/test_wallet.d.ts +24 -23
  62. package/dest/test-wallet/test_wallet.d.ts.map +1 -1
  63. package/dest/test-wallet/test_wallet.js +115 -80
  64. package/dest/test-wallet/worker_wallet.d.ts +4 -4
  65. package/dest/test-wallet/worker_wallet.d.ts.map +1 -1
  66. package/dest/test-wallet/worker_wallet_schema.d.ts +9 -4
  67. package/dest/test-wallet/worker_wallet_schema.d.ts.map +1 -1
  68. package/package.json +40 -40
  69. package/src/bench/client_flows/client_flows_benchmark.ts +31 -22
  70. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +3 -6
  71. package/src/e2e_epochs/epochs_test.ts +17 -5
  72. package/src/e2e_fees/fees_test.ts +1 -1
  73. package/src/e2e_p2p/inactivity_slash_test.ts +3 -3
  74. package/src/e2e_p2p/p2p_network.ts +22 -27
  75. package/src/e2e_p2p/reqresp/utils.ts +24 -3
  76. package/src/e2e_p2p/shared.ts +36 -67
  77. package/src/fixtures/authwit_proxy.ts +4 -0
  78. package/src/fixtures/e2e_prover_test.ts +12 -17
  79. package/src/fixtures/get_bb_config.ts +7 -6
  80. package/src/fixtures/setup.ts +38 -25
  81. package/src/fixtures/setup_p2p_test.ts +9 -9
  82. package/src/fixtures/token_utils.ts +1 -4
  83. package/src/legacy-jest-resolver.cjs +135 -0
  84. package/src/shared/uniswap_l1_l2.ts +29 -24
  85. package/src/simulators/lending_simulator.ts +4 -2
  86. package/src/simulators/token_simulator.ts +1 -1
  87. package/src/spartan/setup_test_wallets.ts +96 -34
  88. package/src/spartan/utils/config.ts +1 -0
  89. package/src/spartan/utils/index.ts +3 -0
  90. package/src/spartan/utils/pod_logs.ts +99 -0
  91. package/src/test-wallet/test_wallet.ts +144 -99
  92. package/src/test-wallet/worker_wallet.ts +3 -2
@@ -4,12 +4,7 @@ import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
4
4
  import { type Logger, createLogger } from '@aztec/aztec.js/log';
5
5
  import type { AztecNode } from '@aztec/aztec.js/node';
6
6
  import { CheatCodes } from '@aztec/aztec/testing';
7
- import {
8
- BBCircuitVerifier,
9
- type ClientProtocolCircuitVerifier,
10
- QueuedIVCVerifier,
11
- TestCircuitVerifier,
12
- } from '@aztec/bb-prover';
7
+ import type { ClientProtocolCircuitVerifier } from '@aztec/bb-prover';
13
8
  import { BackendType, Barretenberg } from '@aztec/bb.js';
14
9
  import type { DeployAztecL1ContractsReturnType } from '@aztec/ethereum/deploy-aztec-l1-contracts';
15
10
  import { Buffer32 } from '@aztec/foundation/buffer';
@@ -68,7 +63,10 @@ export class FullProverTest {
68
63
  private provenComponents: ProvenSetup[] = [];
69
64
  private bbConfigCleanup?: () => Promise<void>;
70
65
  private acvmConfigCleanup?: () => Promise<void>;
71
- circuitProofVerifier?: ClientProtocolCircuitVerifier;
66
+ /** Returns the proof verifier from the prover node (for test assertions). */
67
+ get circuitProofVerifier(): ClientProtocolCircuitVerifier | undefined {
68
+ return this.proverAztecNode?.getProofVerifier();
69
+ }
72
70
  provenAsset!: TokenContract;
73
71
  context!: EndToEndContext;
74
72
  private proverAztecNode!: AztecNodeService;
@@ -106,15 +104,13 @@ export class FullProverTest {
106
104
  await publicDeployAccounts(this.wallet, this.accounts.slice(0, 2));
107
105
 
108
106
  this.logger.info('Applying base setup: deploying token contract');
109
- const {
110
- receipt: { contract: asset, instance },
111
- } = await TokenContract.deploy(
107
+ const { contract: asset, instance } = await TokenContract.deploy(
112
108
  this.wallet,
113
109
  this.accounts[0],
114
110
  FullProverTest.TOKEN_NAME,
115
111
  FullProverTest.TOKEN_SYMBOL,
116
112
  FullProverTest.TOKEN_DECIMALS,
117
- ).send({ from: this.accounts[0], wait: { returnReceipt: true } });
113
+ ).send({ from: this.accounts[0] });
118
114
  this.logger.verbose(`Token deployed to ${asset.address}`);
119
115
 
120
116
  this.fakeProofsAsset = asset;
@@ -170,9 +166,6 @@ export class FullProverTest {
170
166
 
171
167
  await Barretenberg.initSingleton({ backend: BackendType.NativeUnixSocket });
172
168
 
173
- const verifier = await BBCircuitVerifier.new(bbConfig);
174
- this.circuitProofVerifier = new QueuedIVCVerifier(bbConfig, verifier);
175
-
176
169
  this.logger.debug(`Configuring the node for real proofs...`);
177
170
  await this.aztecNodeAdmin.setConfig({
178
171
  realProofs: true,
@@ -180,7 +173,6 @@ export class FullProverTest {
180
173
  });
181
174
  } else {
182
175
  this.logger.debug(`Configuring the node min txs per block ${this.minNumberOfTxsPerBlock}...`);
183
- this.circuitProofVerifier = new TestCircuitVerifier();
184
176
  await this.aztecNodeAdmin.setConfig({
185
177
  minTxsPerBlock: this.minNumberOfTxsPerBlock,
186
178
  });
@@ -231,8 +223,11 @@ export class FullProverTest {
231
223
 
232
224
  this.logger.verbose('Starting prover node');
233
225
  const sponsoredFPCAddress = await getSponsoredFPCAddress();
234
- const { prefilledPublicData } = await getGenesisValues(
226
+ const { genesis } = await getGenesisValues(
235
227
  this.context.initialFundedAccounts.map(a => a.address).concat(sponsoredFPCAddress),
228
+ undefined,
229
+ undefined,
230
+ this.context.genesis!.genesisTimestamp,
236
231
  );
237
232
 
238
233
  const proverNodeConfig: Parameters<typeof AztecNodeService.createAndSync>[0] = {
@@ -260,7 +255,7 @@ export class FullProverTest {
260
255
  this.proverAztecNode = await AztecNodeService.createAndSync(
261
256
  proverNodeConfig,
262
257
  { dateProvider: this.context.dateProvider, p2pClientDeps: { rpcTxProviders: [this.aztecNode] } },
263
- { prefilledPublicData },
258
+ { genesis },
264
259
  );
265
260
  this.logger.warn(`Proofs are now enabled`, { realProofs: this.realProofs });
266
261
  return this;
@@ -13,8 +13,10 @@ const {
13
13
  BB_SKIP_CLEANUP = '',
14
14
  TEMP_DIR = tmpdir(),
15
15
  BB_WORKING_DIRECTORY = '',
16
- BB_NUM_IVC_VERIFIERS = '1',
16
+ BB_NUM_IVC_VERIFIERS = '8',
17
17
  BB_IVC_CONCURRENCY = '1',
18
+ BB_CHONK_VERIFY_MAX_BATCH = '16',
19
+ BB_CHONK_VERIFY_BATCH_CONCURRENCY = '6',
18
20
  } = process.env;
19
21
 
20
22
  export const getBBConfig = async (
@@ -41,16 +43,15 @@ export const getBBConfig = async (
41
43
  const bbSkipCleanup = ['1', 'true'].includes(BB_SKIP_CLEANUP);
42
44
  const cleanup = bbSkipCleanup ? () => Promise.resolve() : () => tryRmDir(directoryToCleanup);
43
45
 
44
- const numIvcVerifiers = Number(BB_NUM_IVC_VERIFIERS);
45
- const ivcConcurrency = Number(BB_IVC_CONCURRENCY);
46
-
47
46
  return {
48
47
  bbSkipCleanup,
49
48
  bbBinaryPath,
50
49
  bbWorkingDirectory,
51
50
  cleanup,
52
- numConcurrentIVCVerifiers: numIvcVerifiers,
53
- bbIVCConcurrency: ivcConcurrency,
51
+ numConcurrentIVCVerifiers: Number(BB_NUM_IVC_VERIFIERS),
52
+ bbIVCConcurrency: Number(BB_IVC_CONCURRENCY),
53
+ bbChonkVerifyMaxBatch: Number(BB_CHONK_VERIFY_MAX_BATCH),
54
+ bbChonkVerifyConcurrency: Number(BB_CHONK_VERIFY_BATCH_CONCURRENCY),
54
55
  };
55
56
  } catch (err) {
56
57
  logger.error(`Native BB not available, error: ${err}`);
@@ -1,11 +1,14 @@
1
1
  import { SchnorrAccountContractArtifact } from '@aztec/accounts/schnorr';
2
2
  import { type InitialAccountData, generateSchnorrAccounts } from '@aztec/accounts/testing';
3
3
  import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node';
4
+ import { NO_FROM } from '@aztec/aztec.js/account';
4
5
  import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
5
6
  import {
6
7
  BatchCall,
7
8
  type ContractFunctionInteraction,
8
9
  type ContractMethod,
10
+ type DeployInteractionWaitOptions,
11
+ type DeployOptions,
9
12
  getContractClassFromArtifact,
10
13
  waitForProven,
11
14
  } from '@aztec/aztec.js/contracts';
@@ -48,9 +51,10 @@ import type { ProverNodeConfig } from '@aztec/prover-node';
48
51
  import { type PXEConfig, getPXEConfig } from '@aztec/pxe/server';
49
52
  import type { SequencerClient } from '@aztec/sequencer-client';
50
53
  import { type ContractInstanceWithAddress, getContractInstanceFromInstantiationParams } from '@aztec/stdlib/contract';
51
- import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
54
+ import type { AztecNodeAdmin, AztecNodeDebug } from '@aztec/stdlib/interfaces/client';
52
55
  import { tryStop } from '@aztec/stdlib/interfaces/server';
53
56
  import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
57
+ import type { GenesisData } from '@aztec/stdlib/world-state';
54
58
  import {
55
59
  type TelemetryClient,
56
60
  type TelemetryClientConfig,
@@ -177,6 +181,8 @@ export type SetupOptions = {
177
181
  proverNodeConfig?: Partial<ProverNodeConfig>;
178
182
  /** Whether to use a mock gossip sub network for p2p clients. */
179
183
  mockGossipSubNetwork?: boolean;
184
+ /** Whether to add simulated latency to the mock gossipsub network (in ms) */
185
+ mockGossipSubNetworkLatency?: number;
180
186
  /** Whether to disable the anvil test watcher (can still be manually started) */
181
187
  disableAnvilTestWatcher?: boolean;
182
188
  /** Whether to enable anvil automine during deployment of L1 contracts (consider defaulting this to true). */
@@ -185,6 +191,11 @@ export type SetupOptions = {
185
191
  anvilAccounts?: number;
186
192
  /** Port to start anvil (defaults to 8545) */
187
193
  anvilPort?: number;
194
+ /**
195
+ * Number of slots per epoch for Anvil's finality simulation.
196
+ * Anvil reports `finalized = latest - slotsInAnEpoch * 2`.
197
+ */
198
+ anvilSlotsInAnEpoch?: number;
188
199
  /** Key to use for publishing L1 contracts */
189
200
  l1PublisherKey?: SecretValue<`0x${string}`>;
190
201
  /** ZkPassport configuration (domain, scope, mock verifier) */
@@ -204,7 +215,7 @@ export type EndToEndContext = {
204
215
  /** The Anvil instance (only set if anvil was started locally). */
205
216
  anvil: Anvil | undefined;
206
217
  /** The Aztec Node service or client a connected to it. */
207
- aztecNode: AztecNode;
218
+ aztecNode: AztecNode & AztecNodeDebug;
208
219
  /** The Aztec Node as a service. */
209
220
  aztecNodeService: AztecNodeService;
210
221
  /** Client to the Aztec Node admin interface. */
@@ -243,8 +254,8 @@ export type EndToEndContext = {
243
254
  sequencerDelayer: Delayer | undefined;
244
255
  /** Delayer for prover node L1 txs (only when enableDelayer and startProverNode are true). */
245
256
  proverDelayer: Delayer | undefined;
246
- /** Prefilled public data used for setting up nodes. */
247
- prefilledPublicData: PublicDataTreeLeaf[] | undefined;
257
+ /** Genesis data used for setting up nodes. */
258
+ genesis: GenesisData | undefined;
248
259
  /** ACVM config (only set if running locally). */
249
260
  acvmConfig: Awaited<ReturnType<typeof getACVMConfig>>;
250
261
  /** BB config (only set if running locally). */
@@ -270,7 +281,7 @@ export async function setup(
270
281
  let anvil: Anvil | undefined;
271
282
  try {
272
283
  opts.aztecTargetCommitteeSize ??= 0;
273
- opts.slasherFlavor ??= 'none';
284
+ opts.slasherEnabled ??= false;
274
285
 
275
286
  const config: AztecNodeConfig & SetupOptions = { ...getConfigEnvVars(), ...opts };
276
287
  // use initialValidators for the node config
@@ -297,6 +308,8 @@ export async function setup(
297
308
  config.dataDirectory = directoryToCleanup;
298
309
  }
299
310
 
311
+ const dateProvider = new TestDateProvider();
312
+
300
313
  if (!config.l1RpcUrls?.length) {
301
314
  if (!isAnvilTestChain(chain.id)) {
302
315
  throw new Error(`No ETHEREUM_HOSTS set but non anvil chain requested`);
@@ -305,6 +318,8 @@ export async function setup(
305
318
  l1BlockTime: opts.ethereumSlotDuration,
306
319
  accounts: opts.anvilAccounts,
307
320
  port: opts.anvilPort ?? (process.env.ANVIL_PORT ? parseInt(process.env.ANVIL_PORT) : undefined),
321
+ slotsInAnEpoch: opts.anvilSlotsInAnEpoch,
322
+ dateProvider,
308
323
  });
309
324
  anvil = res.anvil;
310
325
  config.l1RpcUrls = [res.rpcUrl];
@@ -316,8 +331,6 @@ export async function setup(
316
331
  logger.info(`Logging metrics to ${filename}`);
317
332
  setupMetricsLogger(filename);
318
333
  }
319
-
320
- const dateProvider = new TestDateProvider();
321
334
  const ethCheatCodes = new EthCheatCodesWithState(config.l1RpcUrls, dateProvider);
322
335
 
323
336
  if (opts.stateLoad) {
@@ -367,10 +380,12 @@ export async function setup(
367
380
  addressesToFund.push(sponsoredFPCAddress);
368
381
  }
369
382
 
370
- const { genesisArchiveRoot, prefilledPublicData, fundingNeeded } = await getGenesisValues(
383
+ const genesisTimestamp = BigInt(Math.floor(Date.now() / 1000));
384
+ const { genesisArchiveRoot, genesis, fundingNeeded } = await getGenesisValues(
371
385
  addressesToFund,
372
386
  opts.initialAccountFeeJuice,
373
387
  opts.genesisPublicData,
388
+ genesisTimestamp,
374
389
  );
375
390
 
376
391
  const wasAutomining = await ethCheatCodes.isAutoMining();
@@ -413,11 +428,12 @@ export async function setup(
413
428
  await ethCheatCodes.setIntervalMining(config.ethereumSlotDuration);
414
429
  }
415
430
 
416
- // Always sync dateProvider to L1 time after deploying L1 contracts, regardless of mining mode.
417
- // In compose mode, L1 time may have drifted ahead of system time due to the local-network watcher
418
- // warping time forward on each filled slot. Without this sync, the sequencer computes the wrong
419
- // slot from its dateProvider and cannot propose blocks.
420
- dateProvider.setTime((await ethCheatCodes.timestamp()) * 1000);
431
+ // In compose mode (no local anvil), sync dateProvider to L1 time since it may have drifted
432
+ // ahead of system time due to the local-network watcher warping time forward on each filled slot.
433
+ // When running with a local anvil, the dateProvider is kept in sync via the stdout listener.
434
+ if (!anvil) {
435
+ dateProvider.setTime((await ethCheatCodes.lastBlockTimestamp()) * 1000);
436
+ }
421
437
 
422
438
  if (opts.l2StartTime) {
423
439
  await ethCheatCodes.warp(opts.l2StartTime, { resetBlockInterval: true });
@@ -458,7 +474,7 @@ export async function setup(
458
474
  let p2pClientDeps: P2PClientDeps | undefined = undefined;
459
475
 
460
476
  if (opts.mockGossipSubNetwork) {
461
- mockGossipSubNetwork = new MockGossipSubNetwork();
477
+ mockGossipSubNetwork = new MockGossipSubNetwork(opts.mockGossipSubNetworkLatency);
462
478
  p2pClientDeps = { p2pServiceFactory: getMockPubSubP2PServiceFactory(mockGossipSubNetwork) };
463
479
  }
464
480
 
@@ -487,11 +503,7 @@ export async function setup(
487
503
  }
488
504
 
489
505
  const aztecNodeService = await withLoggerBindings({ actor: 'node-0' }, () =>
490
- AztecNodeService.createAndSync(
491
- config,
492
- { dateProvider, telemetry: telemetryClient, p2pClientDeps },
493
- { prefilledPublicData },
494
- ),
506
+ AztecNodeService.createAndSync(config, { dateProvider, telemetry: telemetryClient, p2pClientDeps }, { genesis }),
495
507
  );
496
508
  const sequencerClient = aztecNodeService.getSequencer();
497
509
 
@@ -515,7 +527,7 @@ export async function setup(
515
527
  dataDirectory: proverNodeDataDirectory,
516
528
  },
517
529
  { dateProvider, p2pClientDeps, telemetry: telemetryClient },
518
- { prefilledPublicData },
530
+ { genesis },
519
531
  ));
520
532
  }
521
533
 
@@ -620,7 +632,7 @@ export async function setup(
620
632
  initialFundedAccounts,
621
633
  logger,
622
634
  mockGossipSubNetwork,
623
- prefilledPublicData,
635
+ genesis,
624
636
  proverNode,
625
637
  sequencerDelayer,
626
638
  proverDelayer,
@@ -720,7 +732,7 @@ export function createAndSyncProverNode(
720
732
  dateProvider: DateProvider;
721
733
  p2pClientDeps?: P2PClientDeps;
722
734
  },
723
- options: { prefilledPublicData: PublicDataTreeLeaf[]; dontStart?: boolean },
735
+ options: { genesis?: GenesisData; dontStart?: boolean },
724
736
  ): Promise<{ proverNode: AztecNodeService }> {
725
737
  return withLoggerBindings({ actor: 'prover-0' }, async () => {
726
738
  const proverNode = await AztecNodeService.createAndSync(
@@ -733,7 +745,7 @@ export function createAndSyncProverNode(
733
745
  proverPublisherPrivateKeys: [new SecretValue(proverNodePrivateKey)],
734
746
  },
735
747
  deps,
736
- { ...options, dontStartProverNode: options.dontStart },
748
+ { genesis: options.genesis, dontStartProverNode: options.dontStart },
737
749
  );
738
750
 
739
751
  if (!proverNode.getProverNode()) {
@@ -824,7 +836,7 @@ export async function ensureAccountContractsPublished(wallet: Wallet, accountsTo
824
836
  * Returns deployed account data that can be used by tests.
825
837
  */
826
838
  export const deployAccounts =
827
- (numberOfAccounts: number, logger: Logger) =>
839
+ (numberOfAccounts: number, logger: Logger, deployOptions?: Partial<DeployOptions<DeployInteractionWaitOptions>>) =>
828
840
  async ({ wallet, initialFundedAccounts }: { wallet: TestWallet; initialFundedAccounts: InitialAccountData[] }) => {
829
841
  if (initialFundedAccounts.length < numberOfAccounts) {
830
842
  throw new Error(`Cannot deploy more than ${initialFundedAccounts.length} initial accounts.`);
@@ -841,8 +853,9 @@ export const deployAccounts =
841
853
  );
842
854
  const deployMethod = await accountManager.getDeployMethod();
843
855
  await deployMethod.send({
844
- from: AztecAddress.ZERO,
856
+ from: NO_FROM,
845
857
  skipClassPublication: i !== 0, // Publish the contract class at most once.
858
+ ...deployOptions,
846
859
  });
847
860
  }
848
861
 
@@ -7,7 +7,7 @@ import { SecretValue } from '@aztec/foundation/config';
7
7
  import { withLoggerBindings } from '@aztec/foundation/log/server';
8
8
  import { bufferToHex } from '@aztec/foundation/string';
9
9
  import type { DateProvider } from '@aztec/foundation/timer';
10
- import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
10
+ import type { GenesisData } from '@aztec/stdlib/world-state';
11
11
 
12
12
  import getPort from 'get-port';
13
13
 
@@ -40,7 +40,7 @@ export async function createNodes(
40
40
  bootstrapNodeEnr: string,
41
41
  numNodes: number,
42
42
  bootNodePort: number,
43
- prefilledPublicData?: PublicDataTreeLeaf[],
43
+ genesis?: GenesisData,
44
44
  dataDirectory?: string,
45
45
  metricsPort?: number,
46
46
  indexOffset = 0,
@@ -65,7 +65,7 @@ export async function createNodes(
65
65
  port,
66
66
  bootstrapNodeEnr,
67
67
  validatorIndices,
68
- prefilledPublicData,
68
+ genesis,
69
69
  dataDir,
70
70
  metricsPort,
71
71
  );
@@ -97,7 +97,7 @@ export async function createNode(
97
97
  tcpPort: number,
98
98
  bootstrapNode: string | undefined,
99
99
  addressIndex: number | number[],
100
- prefilledPublicData?: PublicDataTreeLeaf[],
100
+ genesis?: GenesisData,
101
101
  dataDirectory?: string,
102
102
  metricsPort?: number,
103
103
  ) {
@@ -108,7 +108,7 @@ export async function createNode(
108
108
  return await AztecNodeService.createAndSync(
109
109
  validatorConfig,
110
110
  { telemetry, dateProvider },
111
- { prefilledPublicData, dontStartSequencer: config.dontStartSequencer },
111
+ { genesis, dontStartSequencer: config.dontStartSequencer },
112
112
  );
113
113
  });
114
114
  }
@@ -119,7 +119,7 @@ export async function createNonValidatorNode(
119
119
  dateProvider: DateProvider,
120
120
  tcpPort: number,
121
121
  bootstrapNode: string | undefined,
122
- prefilledPublicData?: PublicDataTreeLeaf[],
122
+ genesis?: GenesisData,
123
123
  dataDirectory?: string,
124
124
  metricsPort?: number,
125
125
  ) {
@@ -133,7 +133,7 @@ export async function createNonValidatorNode(
133
133
  sequencerPublisherPrivateKeys: [],
134
134
  };
135
135
  const telemetry = await getEndToEndTestTelemetryClient(metricsPort);
136
- return await AztecNodeService.createAndSync(config, { telemetry, dateProvider }, { prefilledPublicData });
136
+ return await AztecNodeService.createAndSync(config, { telemetry, dateProvider }, { genesis });
137
137
  });
138
138
  }
139
139
 
@@ -143,7 +143,7 @@ export async function createProverNode(
143
143
  bootstrapNode: string | undefined,
144
144
  addressIndex: number,
145
145
  deps: { dateProvider: DateProvider },
146
- prefilledPublicData?: PublicDataTreeLeaf[],
146
+ genesis?: GenesisData,
147
147
  dataDirectory?: string,
148
148
  metricsPort?: number,
149
149
  ): Promise<{ proverNode: AztecNodeService }> {
@@ -159,7 +159,7 @@ export async function createProverNode(
159
159
  { ...config, ...p2pConfig },
160
160
  { dataDirectory },
161
161
  { ...deps, telemetry },
162
- { prefilledPublicData: prefilledPublicData ?? [] },
162
+ { genesis },
163
163
  );
164
164
  });
165
165
  }
@@ -6,11 +6,8 @@ import { TokenContract } from '@aztec/noir-contracts.js/Token';
6
6
 
7
7
  export async function deployToken(wallet: Wallet, admin: AztecAddress, initialAdminBalance: bigint, logger: Logger) {
8
8
  logger.info(`Deploying Token contract...`);
9
- const {
10
- receipt: { contract, instance },
11
- } = await TokenContract.deploy(wallet, admin, 'TokenName', 'TokenSymbol', 18).send({
9
+ const { contract, instance } = await TokenContract.deploy(wallet, admin, 'TokenName', 'TokenSymbol', 18).send({
12
10
  from: admin,
13
- wait: { returnReceipt: true },
14
11
  });
15
12
 
16
13
  if (initialAdminBalance > 0n) {
@@ -0,0 +1,135 @@
1
+ // Custom Jest resolver. When CONTRACT_ARTIFACTS_VERSION is set, redirects *only* JSON artifact files under
2
+ // @aztec/noir-contracts.js/artifacts/, @aztec/noir-test-contracts.js/artifacts/, and @aztec/accounts/artifacts/ to a local cache of the pinned
3
+ // legacy versions. TypeScript wrapper classes (e.g. Token.ts) continue to load from the current workspace and use the
4
+ // current @aztec/aztec.js — only the artifact JSON (the deployed-contract ABI / bytecode / notes surface) is swapped.
5
+ //
6
+ // Why JSON-only: the JSON artifact is the actual interchange surface a "deployed contract" exposes. The TS wrapper is
7
+ // generated client-side ergonomics that's tightly coupled to the current @aztec/aztec.js API. Redirecting the wrapper
8
+ // would couple this test to a moving aztec.js surface and break at import time on unrelated breaking changes; we want
9
+ // to fail only on actual artifact-compat regressions.
10
+ //
11
+ // The cache is populated on demand by running `npm install` into .legacy-contracts/<version>/.
12
+ //
13
+ // Activated by env var; passthrough otherwise.
14
+ /* eslint-disable @typescript-eslint/no-require-imports */
15
+
16
+ const path = require('path');
17
+ const fs = require('fs');
18
+ const { execSync } = require('child_process');
19
+
20
+ const version = process.env.CONTRACT_ARTIFACTS_VERSION;
21
+ const REDIRECTED = ['@aztec/noir-contracts.js', '@aztec/noir-test-contracts.js', '@aztec/accounts'];
22
+
23
+ // Jest sets rootDir to <e2e>/src; this file lives there too.
24
+ const e2eRoot = path.resolve(__dirname, '..');
25
+ const cacheRoot = version ? path.join(e2eRoot, '.legacy-contracts', version) : null;
26
+
27
+ function pkgJsonPath(name) {
28
+ return path.join(cacheRoot, 'node_modules', name, 'package.json');
29
+ }
30
+
31
+ function ensureCache() {
32
+ const missing = REDIRECTED.some(p => !fs.existsSync(pkgJsonPath(p)));
33
+ if (!missing) {
34
+ return;
35
+ }
36
+ fs.mkdirSync(cacheRoot, { recursive: true });
37
+ // Seed a standalone package.json so `npm install --prefix` treats cacheRoot as its own project. Without this, npm
38
+ // walks up and finds the yarn-project workspace root, which breaks on `workspace:` protocol deps and risks
39
+ // clobbering the monorepo's node_modules.
40
+ const seed = path.join(cacheRoot, 'package.json');
41
+ if (!fs.existsSync(seed)) {
42
+ fs.writeFileSync(seed, JSON.stringify({ name: 'legacy-contracts-cache', private: true }));
43
+ }
44
+
45
+ const specs = REDIRECTED.map(p => `${p}@${version}`).join(' ');
46
+ process.stderr.write(`[legacy-contracts] installing ${specs} into ${cacheRoot}\n`);
47
+ // --prefix: install into cacheRoot instead of cwd, so the cache is isolated from the monorepo.
48
+ // --no-save: don't write the installed packages back to the seeded package.json.
49
+ // --ignore-scripts: skip lifecycle scripts (preinstall/postinstall) of the legacy packages and their transitive
50
+ // deps; we only want the files on disk, not to run any build steps.
51
+ // --legacy-peer-deps: tolerate peer-dependency mismatches between the pinned legacy @aztec/* graph and whatever
52
+ // current versions npm would otherwise try to reconcile.
53
+ execSync(`npm install --prefix "${cacheRoot}" --no-save --ignore-scripts --legacy-peer-deps ${specs}`, {
54
+ stdio: 'inherit',
55
+ });
56
+
57
+ // Verify versions on disk match the requested version.
58
+ for (const p of REDIRECTED) {
59
+ const onDisk = JSON.parse(fs.readFileSync(pkgJsonPath(p), 'utf8')).version;
60
+ if (onDisk !== version) {
61
+ throw new Error(`[legacy-contracts] ${p} on disk is ${onDisk}, expected ${version}`);
62
+ }
63
+ }
64
+ }
65
+
66
+ if (version) {
67
+ ensureCache();
68
+ }
69
+
70
+ let bannerPrinted = false;
71
+ const seen = new Set();
72
+
73
+ function printBannerOnce() {
74
+ if (bannerPrinted || !version) {
75
+ return;
76
+ }
77
+ bannerPrinted = true;
78
+ const lines = ['='.repeat(60), `[legacy-contracts][jest] CONTRACT_ARTIFACTS_VERSION=${version}`];
79
+ for (const p of REDIRECTED) {
80
+ const v = JSON.parse(fs.readFileSync(pkgJsonPath(p), 'utf8')).version;
81
+ if (v !== version) {
82
+ throw new Error(`[legacy-contracts] ${p} on disk is ${v}, expected ${version}`);
83
+ }
84
+ lines.push(`[legacy-contracts][jest] redirecting ${p}/artifacts/*.json -> .legacy-contracts/${version}/...`);
85
+ }
86
+ lines.push('='.repeat(60));
87
+ process.stderr.write(lines.join('\n') + '\n');
88
+ }
89
+
90
+ // Match a resolved absolute path against the workspace artifacts dirs and return the legacy cache equivalent, or null
91
+ // if it's not an artifact path we should redirect.
92
+ function legacyArtifactPath(resolved) {
93
+ if (!resolved.endsWith('.json')) {
94
+ return null;
95
+ }
96
+ for (const pkg of REDIRECTED) {
97
+ // pkg = '@aztec/noir-contracts.js' -> match '/noir-contracts.js/artifacts/'
98
+ const dirName = pkg.split('/')[1];
99
+ const marker = `/${dirName}/artifacts/`;
100
+ const idx = resolved.indexOf(marker);
101
+ if (idx === -1) {
102
+ continue;
103
+ }
104
+ const basename = resolved.slice(idx + marker.length);
105
+ return path.join(cacheRoot, 'node_modules', pkg, 'artifacts', basename);
106
+ }
107
+ return null;
108
+ }
109
+
110
+ module.exports = function legacyResolver(request, options) {
111
+ // Always run the default resolver first. We only inspect (and possibly rewrite) the *result*; this catches both
112
+ // bare-specifier imports of `@aztec/noir-contracts.js/artifacts/foo.json` and the relative `../artifacts/foo.json`
113
+ // imports inside the workspace TS wrapper classes — both resolve to the same workspace artifact path that we then
114
+ // redirect.
115
+ const resolved = options.defaultResolver(request, options);
116
+ if (!version) {
117
+ return resolved;
118
+ }
119
+ printBannerOnce();
120
+ const legacy = legacyArtifactPath(resolved);
121
+ if (!legacy) {
122
+ return resolved;
123
+ }
124
+ if (!fs.existsSync(legacy)) {
125
+ throw new Error(
126
+ `[legacy-contracts] artifact ${path.basename(legacy)} not present in legacy cache @${version}; ` +
127
+ `the contract may have been added after that release. Pin a newer CONTRACT_ARTIFACTS_VERSION or skip this test.`,
128
+ );
129
+ }
130
+ if (!seen.has(resolved)) {
131
+ seen.add(resolved);
132
+ process.stderr.write(`[legacy-contracts][jest] redirected ${path.basename(legacy)} -> ${legacy}\n`);
133
+ }
134
+ return legacy;
135
+ };
@@ -252,8 +252,12 @@ export const uniswapL1L2TestSuite = (
252
252
  await wethCrossChainHarness.expectPublicBalanceOnL2(uniswapL2Contract.address, 0n);
253
253
 
254
254
  // Since the outbox is only consumable when the epoch is proven, we need to advance to the next epoch.
255
- const block = await aztecNode.getBlock(l2UniswapInteractionReceipt.blockNumber!);
256
- const epoch = await rollup.getEpochNumberForCheckpoint(block!.checkpointNumber);
255
+ const swapResult = (await computeL2ToL1MembershipWitness(
256
+ aztecNode,
257
+ swapPrivateLeaf,
258
+ l2UniswapInteractionReceipt.txHash,
259
+ ))!;
260
+ const { epochNumber: epoch } = swapResult;
257
261
  await cheatCodes.rollup.advanceToEpoch(EpochNumber(epoch + 1));
258
262
  await waitForProven(aztecNode, l2UniswapInteractionReceipt, { provenTimeout: 300 });
259
263
 
@@ -262,14 +266,17 @@ export const uniswapL1L2TestSuite = (
262
266
  const daiL1BalanceOfPortalBeforeSwap = await daiCrossChainHarness.getL1BalanceOf(
263
267
  daiCrossChainHarness.tokenPortalAddress,
264
268
  );
265
- const swapResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, swapPrivateLeaf);
266
- const withdrawResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, withdrawLeaf);
269
+ const withdrawResult = (await computeL2ToL1MembershipWitness(
270
+ aztecNode,
271
+ withdrawLeaf,
272
+ l2UniswapInteractionReceipt.txHash,
273
+ ))!;
267
274
 
268
- const swapPrivateL2MessageIndex = swapResult!.leafIndex;
269
- const swapPrivateSiblingPath = swapResult!.siblingPath;
275
+ const swapPrivateL2MessageIndex = swapResult.leafIndex;
276
+ const swapPrivateSiblingPath = swapResult.siblingPath;
270
277
 
271
- const withdrawL2MessageIndex = withdrawResult!.leafIndex;
272
- const withdrawSiblingPath = withdrawResult!.siblingPath;
278
+ const withdrawL2MessageIndex = withdrawResult.leafIndex;
279
+ const withdrawSiblingPath = withdrawResult.siblingPath;
273
280
 
274
281
  const withdrawMessageMetadata = {
275
282
  _epoch: BigInt(epoch),
@@ -840,16 +847,15 @@ export const uniswapL1L2TestSuite = (
840
847
  chainId: new Fr(l1Client.chain.id),
841
848
  });
842
849
 
843
- const block = await aztecNode.getBlock(withdrawReceipt.blockNumber!);
844
- const epoch = await rollup.getEpochNumberForCheckpoint(block!.checkpointNumber);
845
- const swapResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, swapPrivateLeaf);
846
- const withdrawResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, withdrawLeaf);
850
+ const swapResult = (await computeL2ToL1MembershipWitness(aztecNode, swapPrivateLeaf, withdrawReceipt.txHash))!;
851
+ const { epochNumber: epoch } = swapResult;
852
+ const withdrawResult = (await computeL2ToL1MembershipWitness(aztecNode, withdrawLeaf, withdrawReceipt.txHash))!;
847
853
 
848
- const swapPrivateL2MessageIndex = swapResult!.leafIndex;
849
- const swapPrivateSiblingPath = swapResult!.siblingPath;
854
+ const swapPrivateL2MessageIndex = swapResult.leafIndex;
855
+ const swapPrivateSiblingPath = swapResult.siblingPath;
850
856
 
851
- const withdrawL2MessageIndex = withdrawResult!.leafIndex;
852
- const withdrawSiblingPath = withdrawResult!.siblingPath;
857
+ const withdrawL2MessageIndex = withdrawResult.leafIndex;
858
+ const withdrawSiblingPath = withdrawResult.siblingPath;
853
859
 
854
860
  const withdrawMessageMetadata = {
855
861
  _epoch: BigInt(epoch),
@@ -973,16 +979,15 @@ export const uniswapL1L2TestSuite = (
973
979
  chainId: new Fr(l1Client.chain.id),
974
980
  });
975
981
 
976
- const block = await aztecNode.getBlock(withdrawReceipt.blockNumber!);
977
- const epoch = await rollup.getEpochNumberForCheckpoint(block!.checkpointNumber);
978
- const swapResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, swapPublicLeaf);
979
- const withdrawResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, withdrawLeaf);
982
+ const swapResult = (await computeL2ToL1MembershipWitness(aztecNode, swapPublicLeaf, withdrawReceipt.txHash))!;
983
+ const { epochNumber: epoch } = swapResult;
984
+ const withdrawResult = (await computeL2ToL1MembershipWitness(aztecNode, withdrawLeaf, withdrawReceipt.txHash))!;
980
985
 
981
- const swapPublicL2MessageIndex = swapResult!.leafIndex;
982
- const swapPublicSiblingPath = swapResult!.siblingPath;
986
+ const swapPublicL2MessageIndex = swapResult.leafIndex;
987
+ const swapPublicSiblingPath = swapResult.siblingPath;
983
988
 
984
- const withdrawL2MessageIndex = withdrawResult!.leafIndex;
985
- const withdrawSiblingPath = withdrawResult!.siblingPath;
989
+ const withdrawL2MessageIndex = withdrawResult.leafIndex;
990
+ const withdrawSiblingPath = withdrawResult.siblingPath;
986
991
 
987
992
  const withdrawMessageMetadata = {
988
993
  _epoch: BigInt(epoch),
@@ -94,7 +94,9 @@ export class LendingSimulator {
94
94
 
95
95
  async prepare() {
96
96
  this.accumulator = BASE;
97
- const slot = await this.rollup.getSlotAt(BigInt(await this.cc.eth.timestamp()) + BigInt(this.ethereumSlotDuration));
97
+ const slot = await this.rollup.getSlotAt(
98
+ BigInt(await this.cc.eth.lastBlockTimestamp()) + BigInt(this.ethereumSlotDuration),
99
+ );
98
100
  this.time = Number(await this.rollup.getTimestampForSlot(slot));
99
101
  }
100
102
 
@@ -103,7 +105,7 @@ export class LendingSimulator {
103
105
  return;
104
106
  }
105
107
 
106
- const slot = await this.rollup.getSlotAt(BigInt(await this.cc.eth.timestamp()));
108
+ const slot = await this.rollup.getSlotAt(BigInt(await this.cc.eth.lastBlockTimestamp()));
107
109
  const targetSlot = SlotNumber(slot + diff);
108
110
  const ts = Number(await this.rollup.getTimestampForSlot(targetSlot));
109
111
  const timeDiff = ts - this.time;
@@ -110,7 +110,7 @@ export class TokenSimulator {
110
110
  chunk(calls, 5).map(batch => new BatchCall(this.defaultWallet, batch).simulate({ from: this.defaultAddress })),
111
111
  )
112
112
  )
113
- .flat()
113
+ .flatMap(r => r.result)
114
114
  .map(r => r.result);
115
115
  expect(results[0]).toEqual(this.totalSupply);
116
116