@aztec/end-to-end 0.0.1-commit.c0b82b2 → 0.0.1-commit.c2eed6949

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 (104) hide show
  1. package/dest/bench/client_flows/client_flows_benchmark.d.ts +1 -1
  2. package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
  3. package/dest/bench/client_flows/client_flows_benchmark.js +17 -10
  4. package/dest/bench/utils.d.ts +1 -1
  5. package/dest/bench/utils.d.ts.map +1 -1
  6. package/dest/bench/utils.js +6 -3
  7. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +1 -1
  8. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
  9. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +14 -14
  10. package/dest/e2e_epochs/epochs_test.d.ts +3 -1
  11. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  12. package/dest/e2e_epochs/epochs_test.js +5 -2
  13. package/dest/e2e_fees/fees_test.d.ts +1 -1
  14. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  15. package/dest/e2e_fees/fees_test.js +12 -5
  16. package/dest/e2e_nested_contract/nested_contract_test.d.ts +1 -1
  17. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
  18. package/dest/e2e_nested_contract/nested_contract_test.js +4 -6
  19. package/dest/e2e_p2p/p2p_network.d.ts +4 -3
  20. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  21. package/dest/e2e_p2p/p2p_network.js +19 -16
  22. package/dest/e2e_p2p/reqresp/utils.d.ts +1 -1
  23. package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -1
  24. package/dest/e2e_p2p/reqresp/utils.js +15 -2
  25. package/dest/e2e_p2p/shared.d.ts +21 -1
  26. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  27. package/dest/e2e_p2p/shared.js +33 -2
  28. package/dest/e2e_token_contract/token_contract_test.d.ts +1 -1
  29. package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
  30. package/dest/e2e_token_contract/token_contract_test.js +11 -11
  31. package/dest/fixtures/authwit_proxy.d.ts +3 -3
  32. package/dest/fixtures/authwit_proxy.d.ts.map +1 -1
  33. package/dest/fixtures/e2e_prover_test.d.ts +4 -3
  34. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  35. package/dest/fixtures/e2e_prover_test.js +9 -11
  36. package/dest/fixtures/get_bb_config.d.ts +1 -1
  37. package/dest/fixtures/get_bb_config.d.ts.map +1 -1
  38. package/dest/fixtures/get_bb_config.js +5 -5
  39. package/dest/fixtures/setup.d.ts +6 -1
  40. package/dest/fixtures/setup.d.ts.map +1 -1
  41. package/dest/fixtures/setup.js +16 -12
  42. package/dest/fixtures/token_utils.d.ts +1 -1
  43. package/dest/fixtures/token_utils.d.ts.map +1 -1
  44. package/dest/fixtures/token_utils.js +2 -2
  45. package/dest/shared/cross_chain_test_harness.d.ts +1 -1
  46. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
  47. package/dest/shared/cross_chain_test_harness.js +13 -13
  48. package/dest/shared/gas_portal_test_harness.js +2 -2
  49. package/dest/shared/submit-transactions.d.ts +1 -1
  50. package/dest/shared/submit-transactions.d.ts.map +1 -1
  51. package/dest/shared/submit-transactions.js +1 -1
  52. package/dest/shared/uniswap_l1_l2.d.ts +1 -1
  53. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  54. package/dest/shared/uniswap_l1_l2.js +14 -17
  55. package/dest/simulators/lending_simulator.d.ts +1 -1
  56. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  57. package/dest/simulators/lending_simulator.js +4 -4
  58. package/dest/simulators/token_simulator.d.ts +1 -1
  59. package/dest/simulators/token_simulator.d.ts.map +1 -1
  60. package/dest/simulators/token_simulator.js +2 -2
  61. package/dest/spartan/setup_test_wallets.d.ts +4 -2
  62. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  63. package/dest/spartan/setup_test_wallets.js +28 -15
  64. package/dest/spartan/tx_metrics.js +1 -1
  65. package/dest/spartan/utils/config.d.ts +4 -1
  66. package/dest/spartan/utils/config.d.ts.map +1 -1
  67. package/dest/spartan/utils/config.js +1 -0
  68. package/dest/spartan/utils/index.d.ts +2 -1
  69. package/dest/spartan/utils/index.d.ts.map +1 -1
  70. package/dest/spartan/utils/index.js +2 -0
  71. package/dest/spartan/utils/pod_logs.d.ts +25 -0
  72. package/dest/spartan/utils/pod_logs.d.ts.map +1 -0
  73. package/dest/spartan/utils/pod_logs.js +74 -0
  74. package/dest/test-wallet/test_wallet.d.ts +10 -17
  75. package/dest/test-wallet/test_wallet.d.ts.map +1 -1
  76. package/dest/test-wallet/test_wallet.js +47 -48
  77. package/dest/test-wallet/worker_wallet_schema.d.ts +3 -3
  78. package/package.json +39 -40
  79. package/src/bench/client_flows/client_flows_benchmark.ts +39 -31
  80. package/src/bench/utils.ts +7 -2
  81. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +18 -14
  82. package/src/e2e_epochs/epochs_test.ts +14 -2
  83. package/src/e2e_fees/fees_test.ts +12 -5
  84. package/src/e2e_nested_contract/nested_contract_test.ts +6 -4
  85. package/src/e2e_p2p/p2p_network.ts +25 -21
  86. package/src/e2e_p2p/reqresp/utils.ts +23 -2
  87. package/src/e2e_p2p/shared.ts +55 -2
  88. package/src/e2e_token_contract/token_contract_test.ts +16 -8
  89. package/src/fixtures/e2e_prover_test.ts +16 -16
  90. package/src/fixtures/get_bb_config.ts +7 -6
  91. package/src/fixtures/setup.ts +21 -10
  92. package/src/fixtures/token_utils.ts +4 -2
  93. package/src/shared/cross_chain_test_harness.ts +13 -9
  94. package/src/shared/gas_portal_test_harness.ts +1 -1
  95. package/src/shared/submit-transactions.ts +1 -4
  96. package/src/shared/uniswap_l1_l2.ts +35 -28
  97. package/src/simulators/lending_simulator.ts +8 -4
  98. package/src/simulators/token_simulator.ts +6 -2
  99. package/src/spartan/setup_test_wallets.ts +51 -19
  100. package/src/spartan/tx_metrics.ts +1 -1
  101. package/src/spartan/utils/config.ts +1 -0
  102. package/src/spartan/utils/index.ts +3 -0
  103. package/src/spartan/utils/pod_logs.ts +99 -0
  104. package/src/test-wallet/test_wallet.ts +60 -65
@@ -6,12 +6,13 @@ import { Fr } from '@aztec/aztec.js/fields';
6
6
  import type { Logger } from '@aztec/aztec.js/log';
7
7
  import { TxHash } from '@aztec/aztec.js/tx';
8
8
  import type { RollupCheatCodes } from '@aztec/aztec/testing';
9
+ import type { EpochCacheInterface } from '@aztec/epoch-cache';
9
10
  import type {
10
11
  EmpireSlashingProposerContract,
11
12
  RollupContract,
12
13
  TallySlashingProposerContract,
13
14
  } from '@aztec/ethereum/contracts';
14
- import { EpochNumber } from '@aztec/foundation/branded-types';
15
+ import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
15
16
  import { timesAsync, unique } from '@aztec/foundation/collection';
16
17
  import { EthAddress } from '@aztec/foundation/eth-address';
17
18
  import { retryUntil } from '@aztec/foundation/retry';
@@ -41,7 +42,7 @@ export const submitComplexTxsTo = async (
41
42
  const spamCount = 15;
42
43
  for (let i = 0; i < numTxs; i++) {
43
44
  const method = spamContract.methods.spam(seed + BigInt(i * spamCount), spamCount, !!opts.callPublic);
44
- const txHash = await method.send({ from, wait: NO_WAIT });
45
+ const { txHash } = await method.send({ from, wait: NO_WAIT });
45
46
  logger.info(`Tx sent with hash ${txHash.toString()}`);
46
47
  txs.push(txHash);
47
48
  }
@@ -150,6 +151,58 @@ export async function awaitCommitteeExists({
150
151
  return committee!.map(c => c.toString() as `0x${string}`);
151
152
  }
152
153
 
154
+ /**
155
+ * Advance epochs until we find one where the target proposer is selected for at least one slot,
156
+ * then stop one epoch before it. This leaves time for the caller to start sequencers before
157
+ * warping to the target epoch, avoiding the race where the target epoch passes before sequencers
158
+ * are ready.
159
+ *
160
+ * Returns the target epoch number so the caller can warp to it after starting sequencers.
161
+ */
162
+ export async function advanceToEpochBeforeProposer({
163
+ epochCache,
164
+ cheatCodes,
165
+ targetProposer,
166
+ logger,
167
+ maxAttempts = 20,
168
+ }: {
169
+ epochCache: EpochCacheInterface;
170
+ cheatCodes: RollupCheatCodes;
171
+ targetProposer: EthAddress;
172
+ logger: Logger;
173
+ maxAttempts?: number;
174
+ }): Promise<{ targetEpoch: EpochNumber }> {
175
+ const { epochDuration } = await cheatCodes.getConfig();
176
+
177
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
178
+ const currentEpoch = await cheatCodes.getEpoch();
179
+ // Check the NEXT epoch's slots so we stay one epoch before the target,
180
+ // giving the caller time to start sequencers before the target epoch arrives.
181
+ const nextEpoch = Number(currentEpoch) + 1;
182
+ const startSlot = nextEpoch * Number(epochDuration);
183
+ const endSlot = startSlot + Number(epochDuration);
184
+
185
+ logger.info(
186
+ `Checking next epoch ${nextEpoch} (slots ${startSlot}-${endSlot - 1}) for proposer ${targetProposer} (current epoch: ${currentEpoch})`,
187
+ );
188
+
189
+ for (let s = startSlot; s < endSlot; s++) {
190
+ const proposer = await epochCache.getProposerAttesterAddressInSlot(SlotNumber(s));
191
+ if (proposer && proposer.equals(targetProposer)) {
192
+ logger.warn(
193
+ `Found target proposer ${targetProposer} in slot ${s} of epoch ${nextEpoch}. Staying at epoch ${currentEpoch} to allow sequencer startup.`,
194
+ );
195
+ return { targetEpoch: EpochNumber(nextEpoch) };
196
+ }
197
+ }
198
+
199
+ logger.info(`Target proposer not found in epoch ${nextEpoch}, advancing to next epoch`);
200
+ await cheatCodes.advanceToNextEpoch();
201
+ }
202
+
203
+ throw new Error(`Target proposer ${targetProposer} not found in any slot after ${maxAttempts} epoch attempts`);
204
+ }
205
+
153
206
  export async function awaitOffenseDetected({
154
207
  logger,
155
208
  nodeAdmin,
@@ -81,24 +81,28 @@ export class TokenContractTest {
81
81
  await publicDeployAccounts(this.wallet, [this.adminAddress, this.account1Address]);
82
82
 
83
83
  this.logger.verbose(`Deploying TokenContract...`);
84
- this.asset = await TokenContract.deploy(
84
+ ({ contract: this.asset } = await TokenContract.deploy(
85
85
  this.wallet,
86
86
  this.adminAddress,
87
87
  TokenContractTest.TOKEN_NAME,
88
88
  TokenContractTest.TOKEN_SYMBOL,
89
89
  TokenContractTest.TOKEN_DECIMALS,
90
- ).send({ from: this.adminAddress });
90
+ ).send({ from: this.adminAddress }));
91
91
  this.logger.verbose(`Token deployed to ${this.asset.address}`);
92
92
 
93
93
  this.logger.verbose(`Deploying bad account...`);
94
- this.badAccount = await InvalidAccountContract.deploy(this.wallet).send({ from: this.adminAddress });
94
+ ({ contract: this.badAccount } = await InvalidAccountContract.deploy(this.wallet).send({
95
+ from: this.adminAddress,
96
+ }));
95
97
  this.logger.verbose(`Deployed to ${this.badAccount.address}.`);
96
98
 
97
99
  // Deploy a proxy contract for "on behalf of other" tests. The note owner must be the tx sender
98
100
  // (so their notes are in scope), but msg_sender in the target must differ from the note owner
99
101
  // to trigger authwit validation. The proxy forwards calls so that msg_sender != tx sender.
100
102
  this.logger.verbose(`Deploying generic proxy...`);
101
- this.authwitProxy = await GenericProxyContract.deploy(this.wallet).send({ from: this.adminAddress });
103
+ ({ contract: this.authwitProxy } = await GenericProxyContract.deploy(this.wallet).send({
104
+ from: this.adminAddress,
105
+ }));
102
106
  this.logger.verbose(`Deployed to ${this.authwitProxy.address}.`);
103
107
 
104
108
  this.tokenSim = new TokenSimulator(this.asset, this.wallet, this.adminAddress, this.logger, [
@@ -106,7 +110,7 @@ export class TokenContractTest {
106
110
  this.account1Address,
107
111
  ]);
108
112
 
109
- expect(await this.asset.methods.get_admin().simulate({ from: this.adminAddress })).toBe(
113
+ expect((await this.asset.methods.get_admin().simulate({ from: this.adminAddress })).result).toBe(
110
114
  this.adminAddress.toBigInt(),
111
115
  );
112
116
  }
@@ -140,7 +144,9 @@ export class TokenContractTest {
140
144
  await asset.methods.mint_to_public(adminAddress, amount).send({ from: adminAddress });
141
145
  tokenSim.mintPublic(adminAddress, amount);
142
146
 
143
- const publicBalance = await asset.methods.balance_of_public(adminAddress).simulate({ from: adminAddress });
147
+ const { result: publicBalance } = await asset.methods
148
+ .balance_of_public(adminAddress)
149
+ .simulate({ from: adminAddress });
144
150
  this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`);
145
151
  expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(adminAddress));
146
152
 
@@ -148,11 +154,13 @@ export class TokenContractTest {
148
154
  await mintTokensToPrivate(asset, adminAddress, adminAddress, amount);
149
155
  tokenSim.mintPrivate(adminAddress, amount);
150
156
 
151
- const privateBalance = await asset.methods.balance_of_private(adminAddress).simulate({ from: adminAddress });
157
+ const { result: privateBalance } = await asset.methods
158
+ .balance_of_private(adminAddress)
159
+ .simulate({ from: adminAddress });
152
160
  this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`);
153
161
  expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(adminAddress));
154
162
 
155
- const totalSupply = await asset.methods.total_supply().simulate({ from: adminAddress });
163
+ const { result: totalSupply } = await asset.methods.total_supply().simulate({ from: adminAddress });
156
164
  this.logger.verbose(`Total supply: ${totalSupply}`);
157
165
  expect(totalSupply).toEqual(tokenSim.totalSupply);
158
166
 
@@ -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,7 +104,9 @@ 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 { contract: asset, instance } = await TokenContract.deploy(
107
+ const {
108
+ receipt: { contract: asset, instance },
109
+ } = await TokenContract.deploy(
110
110
  this.wallet,
111
111
  this.accounts[0],
112
112
  FullProverTest.TOKEN_NAME,
@@ -121,7 +121,7 @@ export class FullProverTest {
121
121
 
122
122
  this.tokenSim = new TokenSimulator(this.fakeProofsAsset, this.wallet, this.accounts[0], this.logger, this.accounts);
123
123
 
124
- expect(await this.fakeProofsAsset.methods.get_admin().simulate({ from: this.accounts[0] })).toBe(
124
+ expect((await this.fakeProofsAsset.methods.get_admin().simulate({ from: this.accounts[0] })).result).toBe(
125
125
  this.accounts[0].toBigInt(),
126
126
  );
127
127
  }
@@ -168,9 +168,6 @@ export class FullProverTest {
168
168
 
169
169
  await Barretenberg.initSingleton({ backend: BackendType.NativeUnixSocket });
170
170
 
171
- const verifier = await BBCircuitVerifier.new(bbConfig);
172
- this.circuitProofVerifier = new QueuedIVCVerifier(bbConfig, verifier);
173
-
174
171
  this.logger.debug(`Configuring the node for real proofs...`);
175
172
  await this.aztecNodeAdmin.setConfig({
176
173
  realProofs: true,
@@ -178,7 +175,6 @@ export class FullProverTest {
178
175
  });
179
176
  } else {
180
177
  this.logger.debug(`Configuring the node min txs per block ${this.minNumberOfTxsPerBlock}...`);
181
- this.circuitProofVerifier = new TestCircuitVerifier();
182
178
  await this.aztecNodeAdmin.setConfig({
183
179
  minTxsPerBlock: this.minNumberOfTxsPerBlock,
184
180
  });
@@ -310,16 +306,20 @@ export class FullProverTest {
310
306
  } = this;
311
307
  tokenSim.mintPublic(address, publicAmount);
312
308
 
313
- const publicBalance = await fakeProofsAsset.methods.balance_of_public(address).simulate({ from: address });
309
+ const { result: publicBalance } = await fakeProofsAsset.methods
310
+ .balance_of_public(address)
311
+ .simulate({ from: address });
314
312
  this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`);
315
313
  expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(address));
316
314
 
317
315
  tokenSim.mintPrivate(address, publicAmount);
318
- const privateBalance = await fakeProofsAsset.methods.balance_of_private(address).simulate({ from: address });
316
+ const { result: privateBalance } = await fakeProofsAsset.methods
317
+ .balance_of_private(address)
318
+ .simulate({ from: address });
319
319
  this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`);
320
320
  expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(address));
321
321
 
322
- const totalSupply = await fakeProofsAsset.methods.total_supply().simulate({ from: address });
322
+ const { result: totalSupply } = await fakeProofsAsset.methods.total_supply().simulate({ from: address });
323
323
  this.logger.verbose(`Total supply: ${totalSupply}`);
324
324
  expect(totalSupply).toEqual(tokenSim.totalSupply);
325
325
  }
@@ -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,6 +1,7 @@
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,
@@ -185,6 +186,11 @@ export type SetupOptions = {
185
186
  anvilAccounts?: number;
186
187
  /** Port to start anvil (defaults to 8545) */
187
188
  anvilPort?: number;
189
+ /**
190
+ * Number of slots per epoch for Anvil's finality simulation.
191
+ * Anvil reports `finalized = latest - slotsInAnEpoch * 2`.
192
+ */
193
+ anvilSlotsInAnEpoch?: number;
188
194
  /** Key to use for publishing L1 contracts */
189
195
  l1PublisherKey?: SecretValue<`0x${string}`>;
190
196
  /** ZkPassport configuration (domain, scope, mock verifier) */
@@ -297,6 +303,8 @@ export async function setup(
297
303
  config.dataDirectory = directoryToCleanup;
298
304
  }
299
305
 
306
+ const dateProvider = new TestDateProvider();
307
+
300
308
  if (!config.l1RpcUrls?.length) {
301
309
  if (!isAnvilTestChain(chain.id)) {
302
310
  throw new Error(`No ETHEREUM_HOSTS set but non anvil chain requested`);
@@ -305,6 +313,8 @@ export async function setup(
305
313
  l1BlockTime: opts.ethereumSlotDuration,
306
314
  accounts: opts.anvilAccounts,
307
315
  port: opts.anvilPort ?? (process.env.ANVIL_PORT ? parseInt(process.env.ANVIL_PORT) : undefined),
316
+ slotsInAnEpoch: opts.anvilSlotsInAnEpoch,
317
+ dateProvider,
308
318
  });
309
319
  anvil = res.anvil;
310
320
  config.l1RpcUrls = [res.rpcUrl];
@@ -316,8 +326,6 @@ export async function setup(
316
326
  logger.info(`Logging metrics to ${filename}`);
317
327
  setupMetricsLogger(filename);
318
328
  }
319
-
320
- const dateProvider = new TestDateProvider();
321
329
  const ethCheatCodes = new EthCheatCodesWithState(config.l1RpcUrls, dateProvider);
322
330
 
323
331
  if (opts.stateLoad) {
@@ -413,11 +421,12 @@ export async function setup(
413
421
  await ethCheatCodes.setIntervalMining(config.ethereumSlotDuration);
414
422
  }
415
423
 
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);
424
+ // In compose mode (no local anvil), sync dateProvider to L1 time since it may have drifted
425
+ // ahead of system time due to the local-network watcher warping time forward on each filled slot.
426
+ // When running with a local anvil, the dateProvider is kept in sync via the stdout listener.
427
+ if (!anvil) {
428
+ dateProvider.setTime((await ethCheatCodes.lastBlockTimestamp()) * 1000);
429
+ }
421
430
 
422
431
  if (opts.l2StartTime) {
423
432
  await ethCheatCodes.warp(opts.l2StartTime, { resetBlockInterval: true });
@@ -753,7 +762,9 @@ export function getBalancesFn(
753
762
  ): (...addresses: (AztecAddress | { address: AztecAddress })[]) => Promise<bigint[]> {
754
763
  const balances = async (...addressLikes: (AztecAddress | { address: AztecAddress })[]) => {
755
764
  const addresses = addressLikes.map(addressLike => ('address' in addressLike ? addressLike.address : addressLike));
756
- const b = await Promise.all(addresses.map(address => method(address).simulate({ from: address })));
765
+ const b = await Promise.all(
766
+ addresses.map(async address => (await method(address).simulate({ from: address })).result),
767
+ );
757
768
  const debugString = `${symbol} balances: ${addresses.map((address, i) => `${address}: ${b[i]}`).join(', ')}`;
758
769
  logger.verbose(debugString);
759
770
  return b;
@@ -839,7 +850,7 @@ export const deployAccounts =
839
850
  );
840
851
  const deployMethod = await accountManager.getDeployMethod();
841
852
  await deployMethod.send({
842
- from: AztecAddress.ZERO,
853
+ from: NO_FROM,
843
854
  skipClassPublication: i !== 0, // Publish the contract class at most once.
844
855
  });
845
856
  }
@@ -871,7 +882,7 @@ export async function publicDeployAccounts(
871
882
 
872
883
  const batch = new BatchCall(wallet, calls);
873
884
 
874
- const txReceipt = await batch.send({ from: accountsToDeploy[0] });
885
+ const { receipt: txReceipt } = await batch.send({ from: accountsToDeploy[0] });
875
886
  if (waitUntilProven) {
876
887
  if (!node) {
877
888
  throw new Error('Need to provide an AztecNode to wait for proven.');
@@ -6,7 +6,9 @@ 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 { contract, instance } = await TokenContract.deploy(wallet, admin, 'TokenName', 'TokenSymbol', 18).send({
9
+ const {
10
+ receipt: { contract, instance },
11
+ } = await TokenContract.deploy(wallet, admin, 'TokenName', 'TokenSymbol', 18).send({
10
12
  from: admin,
11
13
  wait: { returnReceipt: true },
12
14
  });
@@ -39,7 +41,7 @@ export async function expectTokenBalance(
39
41
  ) {
40
42
  // Then check the balance
41
43
  const contractWithWallet = TokenContract.at(token.address, wallet);
42
- const balance = await contractWithWallet.methods.balance_of_private(owner).simulate({ from: owner });
44
+ const { result: balance } = await contractWithWallet.methods.balance_of_private(owner).simulate({ from: owner });
43
45
  logger.info(`Account ${owner} balance: ${balance}`);
44
46
  expect(balance).toBe(expectedBalance);
45
47
  }
@@ -73,22 +73,26 @@ export async function deployAndInitializeTokenAndBridgeContracts(
73
73
  });
74
74
 
75
75
  // deploy l2 token
76
- const token = await TokenContract.deploy(wallet, owner, 'TokenName', 'TokenSymbol', 18).send({ from: owner });
76
+ const { contract: token } = await TokenContract.deploy(wallet, owner, 'TokenName', 'TokenSymbol', 18).send({
77
+ from: owner,
78
+ });
77
79
 
78
80
  // deploy l2 token bridge and attach to the portal
79
- const bridge = await TokenBridgeContract.deploy(wallet, token.address, tokenPortalAddress).send({ from: owner });
81
+ const { contract: bridge } = await TokenBridgeContract.deploy(wallet, token.address, tokenPortalAddress).send({
82
+ from: owner,
83
+ });
80
84
 
81
- if ((await token.methods.get_admin().simulate({ from: owner })) !== owner.toBigInt()) {
85
+ if ((await token.methods.get_admin().simulate({ from: owner })).result !== owner.toBigInt()) {
82
86
  throw new Error(`Token admin is not ${owner}`);
83
87
  }
84
88
 
85
- if (!(await bridge.methods.get_config().simulate({ from: owner })).token.equals(token.address)) {
89
+ if (!(await bridge.methods.get_config().simulate({ from: owner })).result.token.equals(token.address)) {
86
90
  throw new Error(`Bridge token is not ${token.address}`);
87
91
  }
88
92
 
89
93
  // make the bridge a minter on the token:
90
94
  await token.methods.set_minter(bridge.address, true).send({ from: owner });
91
- if ((await token.methods.is_minter(bridge.address).simulate({ from: owner })) === 1n) {
95
+ if ((await token.methods.is_minter(bridge.address).simulate({ from: owner })).result === 1n) {
92
96
  throw new Error(`Bridge is not a minter`);
93
97
  }
94
98
 
@@ -269,7 +273,7 @@ export class CrossChainTestHarness {
269
273
  authwitNonce: Fr = Fr.ZERO,
270
274
  authWitness: AuthWitness,
271
275
  ): Promise<TxReceipt> {
272
- const withdrawReceipt = await this.l2Bridge.methods
276
+ const { receipt: withdrawReceipt } = await this.l2Bridge.methods
273
277
  .exit_to_l1_private(this.l2Token.address, this.ethAccount, withdrawAmount, EthAddress.ZERO, authwitNonce)
274
278
  .send({ authWitnesses: [authWitness], from: this.ownerAddress });
275
279
 
@@ -277,7 +281,7 @@ export class CrossChainTestHarness {
277
281
  }
278
282
 
279
283
  async withdrawPublicFromAztecToL1(withdrawAmount: bigint, authwitNonce: Fr = Fr.ZERO): Promise<TxReceipt> {
280
- const withdrawReceipt = await this.l2Bridge.methods
284
+ const { receipt: withdrawReceipt } = await this.l2Bridge.methods
281
285
  .exit_to_l1_public(this.ethAccount, withdrawAmount, EthAddress.ZERO, authwitNonce)
282
286
  .send({ from: this.ownerAddress });
283
287
 
@@ -285,7 +289,7 @@ export class CrossChainTestHarness {
285
289
  }
286
290
 
287
291
  async getL2PrivateBalanceOf(owner: AztecAddress) {
288
- return await this.l2Token.methods.balance_of_private(owner).simulate({ from: owner });
292
+ return (await this.l2Token.methods.balance_of_private(owner).simulate({ from: owner })).result;
289
293
  }
290
294
 
291
295
  async expectPrivateBalanceOnL2(owner: AztecAddress, expectedBalance: bigint) {
@@ -295,7 +299,7 @@ export class CrossChainTestHarness {
295
299
  }
296
300
 
297
301
  async getL2PublicBalanceOf(owner: AztecAddress) {
298
- return await this.l2Token.methods.balance_of_public(owner).simulate({ from: this.ownerAddress });
302
+ return (await this.l2Token.methods.balance_of_public(owner).simulate({ from: this.ownerAddress })).result;
299
303
  }
300
304
 
301
305
  async expectPublicBalanceOnL2(owner: AztecAddress, expectedBalance: bigint) {
@@ -131,7 +131,7 @@ export class GasBridgingTestHarness implements IGasBridgingTestHarness {
131
131
  }
132
132
 
133
133
  async getL2PublicBalanceOf(owner: AztecAddress) {
134
- return await this.feeJuice.methods.balance_of_public(owner).simulate({ from: owner });
134
+ return (await this.feeJuice.methods.balance_of_public(owner).simulate({ from: owner })).result;
135
135
  }
136
136
 
137
137
  async expectPublicBalanceOnL2(owner: AztecAddress, expectedBalance: bigint) {
@@ -19,10 +19,7 @@ export const submitTxsTo = async (
19
19
  times(numTxs, async () => {
20
20
  const accountManager = await wallet.createSchnorrAccount(Fr.random(), Fr.random(), GrumpkinScalar.random());
21
21
  const deployMethod = await accountManager.getDeployMethod();
22
- const txHash = await deployMethod.send({
23
- from: submitter,
24
- wait: NO_WAIT,
25
- });
22
+ const { txHash } = await deployMethod.send({ from: submitter, wait: NO_WAIT });
26
23
 
27
24
  logger.info(`Tx sent with hash ${txHash}`);
28
25
  const receipt: TxReceipt = await wallet.getTxReceipt(txHash);
@@ -130,7 +130,9 @@ export const uniswapL1L2TestSuite = (
130
130
  client: l1Client,
131
131
  });
132
132
  // deploy l2 uniswap contract and attach to portal
133
- uniswapL2Contract = await UniswapContract.deploy(wallet, uniswapPortalAddress).send({ from: ownerAddress });
133
+ ({ contract: uniswapL2Contract } = await UniswapContract.deploy(wallet, uniswapPortalAddress).send({
134
+ from: ownerAddress,
135
+ }));
134
136
 
135
137
  const registryAddress = (await aztecNode.getNodeInfo()).l1ContractAddresses.registryAddress;
136
138
 
@@ -195,7 +197,7 @@ export const uniswapL1L2TestSuite = (
195
197
  logger.info('Withdrawing weth to L1 and sending message to swap to dai');
196
198
  const [secretForDepositingSwappedDai, secretHashForDepositingSwappedDai] = await generateClaimSecret();
197
199
 
198
- const l2UniswapInteractionReceipt = await uniswapL2Contract.methods
200
+ const { receipt: l2UniswapInteractionReceipt } = await uniswapL2Contract.methods
199
201
  .swap_private(
200
202
  wethCrossChainHarness.l2Token.address,
201
203
  wethCrossChainHarness.l2Bridge.address,
@@ -250,8 +252,12 @@ export const uniswapL1L2TestSuite = (
250
252
  await wethCrossChainHarness.expectPublicBalanceOnL2(uniswapL2Contract.address, 0n);
251
253
 
252
254
  // Since the outbox is only consumable when the epoch is proven, we need to advance to the next epoch.
253
- const block = await aztecNode.getBlock(l2UniswapInteractionReceipt.blockNumber!);
254
- 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;
255
261
  await cheatCodes.rollup.advanceToEpoch(EpochNumber(epoch + 1));
256
262
  await waitForProven(aztecNode, l2UniswapInteractionReceipt, { provenTimeout: 300 });
257
263
 
@@ -260,14 +266,17 @@ export const uniswapL1L2TestSuite = (
260
266
  const daiL1BalanceOfPortalBeforeSwap = await daiCrossChainHarness.getL1BalanceOf(
261
267
  daiCrossChainHarness.tokenPortalAddress,
262
268
  );
263
- const swapResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, swapPrivateLeaf);
264
- const withdrawResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, withdrawLeaf);
269
+ const withdrawResult = (await computeL2ToL1MembershipWitness(
270
+ aztecNode,
271
+ withdrawLeaf,
272
+ l2UniswapInteractionReceipt.txHash,
273
+ ))!;
265
274
 
266
- const swapPrivateL2MessageIndex = swapResult!.leafIndex;
267
- const swapPrivateSiblingPath = swapResult!.siblingPath;
275
+ const swapPrivateL2MessageIndex = swapResult.leafIndex;
276
+ const swapPrivateSiblingPath = swapResult.siblingPath;
268
277
 
269
- const withdrawL2MessageIndex = withdrawResult!.leafIndex;
270
- const withdrawSiblingPath = withdrawResult!.siblingPath;
278
+ const withdrawL2MessageIndex = withdrawResult.leafIndex;
279
+ const withdrawSiblingPath = withdrawResult.siblingPath;
271
280
 
272
281
  const withdrawMessageMetadata = {
273
282
  _epoch: BigInt(epoch),
@@ -787,7 +796,7 @@ export const uniswapL1L2TestSuite = (
787
796
  logger.info('Withdrawing weth to L1 and sending message to swap to dai');
788
797
 
789
798
  const [, secretHashForDepositingSwappedDai] = await generateClaimSecret();
790
- const withdrawReceipt = await uniswapL2Contract.methods
799
+ const { receipt: withdrawReceipt } = await uniswapL2Contract.methods
791
800
  .swap_private(
792
801
  wethCrossChainHarness.l2Token.address,
793
802
  wethCrossChainHarness.l2Bridge.address,
@@ -838,16 +847,15 @@ export const uniswapL1L2TestSuite = (
838
847
  chainId: new Fr(l1Client.chain.id),
839
848
  });
840
849
 
841
- const block = await aztecNode.getBlock(withdrawReceipt.blockNumber!);
842
- const epoch = await rollup.getEpochNumberForCheckpoint(block!.checkpointNumber);
843
- const swapResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, swapPrivateLeaf);
844
- 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))!;
845
853
 
846
- const swapPrivateL2MessageIndex = swapResult!.leafIndex;
847
- const swapPrivateSiblingPath = swapResult!.siblingPath;
854
+ const swapPrivateL2MessageIndex = swapResult.leafIndex;
855
+ const swapPrivateSiblingPath = swapResult.siblingPath;
848
856
 
849
- const withdrawL2MessageIndex = withdrawResult!.leafIndex;
850
- const withdrawSiblingPath = withdrawResult!.siblingPath;
857
+ const withdrawL2MessageIndex = withdrawResult.leafIndex;
858
+ const withdrawSiblingPath = withdrawResult.siblingPath;
851
859
 
852
860
  const withdrawMessageMetadata = {
853
861
  _epoch: BigInt(epoch),
@@ -915,7 +923,7 @@ export const uniswapL1L2TestSuite = (
915
923
 
916
924
  // Call swap_public on L2
917
925
  const secretHashForDepositingSwappedDai = Fr.random();
918
- const withdrawReceipt = await uniswapL2Contract.methods
926
+ const { receipt: withdrawReceipt } = await uniswapL2Contract.methods
919
927
  .swap_public(
920
928
  ownerAddress,
921
929
  wethCrossChainHarness.l2Bridge.address,
@@ -971,16 +979,15 @@ export const uniswapL1L2TestSuite = (
971
979
  chainId: new Fr(l1Client.chain.id),
972
980
  });
973
981
 
974
- const block = await aztecNode.getBlock(withdrawReceipt.blockNumber!);
975
- const epoch = await rollup.getEpochNumberForCheckpoint(block!.checkpointNumber);
976
- const swapResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, swapPublicLeaf);
977
- 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))!;
978
985
 
979
- const swapPublicL2MessageIndex = swapResult!.leafIndex;
980
- const swapPublicSiblingPath = swapResult!.siblingPath;
986
+ const swapPublicL2MessageIndex = swapResult.leafIndex;
987
+ const swapPublicSiblingPath = swapResult.siblingPath;
981
988
 
982
- const withdrawL2MessageIndex = withdrawResult!.leafIndex;
983
- const withdrawSiblingPath = withdrawResult!.siblingPath;
989
+ const withdrawL2MessageIndex = withdrawResult.leafIndex;
990
+ const withdrawSiblingPath = withdrawResult.siblingPath;
984
991
 
985
992
  const withdrawMessageMetadata = {
986
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;
@@ -186,14 +188,16 @@ export class LendingSimulator {
186
188
 
187
189
  expect(this.borrowed).toEqual(this.stableCoin.totalSupply - this.mintedOutside);
188
190
 
189
- const asset = await this.lendingContract.methods.get_asset(0).simulate({ from: this.account.address });
191
+ const { result: asset } = await this.lendingContract.methods.get_asset(0).simulate({ from: this.account.address });
190
192
 
191
193
  const interestAccumulator = asset['interest_accumulator'];
192
194
  expect(interestAccumulator).toEqual(this.accumulator);
193
195
  expect(asset['last_updated_ts']).toEqual(BigInt(this.time));
194
196
 
195
197
  for (const key of [this.account.address, AztecAddress.fromField(await this.account.key())]) {
196
- const privatePos = await this.lendingContract.methods.get_position(key).simulate({ from: this.account.address });
198
+ const { result: privatePos } = await this.lendingContract.methods
199
+ .get_position(key)
200
+ .simulate({ from: this.account.address });
197
201
  expect(new Fr(privatePos['collateral'])).toEqual(this.collateral[key.toString()] ?? Fr.ZERO);
198
202
  expect(new Fr(privatePos['static_debt'])).toEqual(this.staticDebt[key.toString()] ?? Fr.ZERO);
199
203
  expect(privatePos['debt']).toEqual(
@@ -109,7 +109,9 @@ export class TokenSimulator {
109
109
  await Promise.all(
110
110
  chunk(calls, 5).map(batch => new BatchCall(this.defaultWallet, batch).simulate({ from: this.defaultAddress })),
111
111
  )
112
- ).flat();
112
+ )
113
+ .flatMap(r => r.result)
114
+ .map(r => r.result);
113
115
  expect(results[0]).toEqual(this.totalSupply);
114
116
 
115
117
  // Check that all our balances match
@@ -123,7 +125,9 @@ export class TokenSimulator {
123
125
  const wallet = this.lookupProvider.get(address.toString());
124
126
  const asset = wallet ? this.token.withWallet(wallet) : this.token;
125
127
 
126
- const actualPrivateBalance = await asset.methods.balance_of_private(address).simulate({ from: address });
128
+ const { result: actualPrivateBalance } = await asset.methods
129
+ .balance_of_private(address)
130
+ .simulate({ from: address });
127
131
  expect(actualPrivateBalance).toEqual(this.balanceOfPrivate(address));
128
132
  }
129
133
  }