@aztec/end-to-end 0.0.1-commit.b33fc05d0 → 0.0.1-commit.b3d3157a

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 (165) hide show
  1. package/README.md +27 -0
  2. package/dest/bench/client_flows/benchmark.d.ts +15 -1
  3. package/dest/bench/client_flows/benchmark.d.ts.map +1 -1
  4. package/dest/bench/client_flows/benchmark.js +17 -0
  5. package/dest/bench/client_flows/client_flows_benchmark.d.ts +2 -2
  6. package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
  7. package/dest/bench/client_flows/client_flows_benchmark.js +27 -38
  8. package/dest/bench/utils.d.ts +1 -1
  9. package/dest/bench/utils.d.ts.map +1 -1
  10. package/dest/bench/utils.js +2 -0
  11. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +5 -4
  12. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
  13. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +14 -5
  14. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +15 -4
  15. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts.map +1 -1
  16. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.js +39 -7
  17. package/dest/e2e_deploy_contract/deploy_test.d.ts +3 -3
  18. package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -1
  19. package/dest/e2e_deploy_contract/deploy_test.js +2 -1
  20. package/dest/e2e_epochs/epochs_test.d.ts +25 -2
  21. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  22. package/dest/e2e_epochs/epochs_test.js +86 -13
  23. package/dest/e2e_fees/fees_test.d.ts +5 -2
  24. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  25. package/dest/e2e_fees/fees_test.js +32 -6
  26. package/dest/e2e_nested_contract/nested_contract_test.d.ts +3 -3
  27. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
  28. package/dest/e2e_nested_contract/nested_contract_test.js +2 -1
  29. package/dest/e2e_p2p/inactivity_slash_test.d.ts +1 -1
  30. package/dest/e2e_p2p/inactivity_slash_test.d.ts.map +1 -1
  31. package/dest/e2e_p2p/inactivity_slash_test.js +4 -3
  32. package/dest/e2e_p2p/p2p_network.d.ts +10 -9
  33. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  34. package/dest/e2e_p2p/p2p_network.js +46 -27
  35. package/dest/e2e_p2p/reqresp/utils.d.ts +1 -1
  36. package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -1
  37. package/dest/e2e_p2p/reqresp/utils.js +29 -13
  38. package/dest/e2e_p2p/shared.d.ts +23 -14
  39. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  40. package/dest/e2e_p2p/shared.js +62 -57
  41. package/dest/e2e_token_contract/token_contract_test.d.ts +3 -3
  42. package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
  43. package/dest/e2e_token_contract/token_contract_test.js +4 -2
  44. package/dest/fixtures/authwit_proxy.d.ts +1 -1
  45. package/dest/fixtures/authwit_proxy.d.ts.map +1 -1
  46. package/dest/fixtures/authwit_proxy.js +4 -0
  47. package/dest/fixtures/e2e_prover_test.d.ts +6 -5
  48. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  49. package/dest/fixtures/e2e_prover_test.js +9 -13
  50. package/dest/fixtures/fixtures.d.ts +70 -1
  51. package/dest/fixtures/fixtures.d.ts.map +1 -1
  52. package/dest/fixtures/fixtures.js +65 -0
  53. package/dest/fixtures/get_bb_config.d.ts +1 -1
  54. package/dest/fixtures/get_bb_config.d.ts.map +1 -1
  55. package/dest/fixtures/get_bb_config.js +5 -5
  56. package/dest/fixtures/ha_setup.d.ts +2 -2
  57. package/dest/fixtures/ha_setup.d.ts.map +1 -1
  58. package/dest/fixtures/ha_setup.js +1 -1
  59. package/dest/fixtures/schnorr_hardcoded_account_contract.d.ts +25 -0
  60. package/dest/fixtures/schnorr_hardcoded_account_contract.d.ts.map +1 -0
  61. package/dest/fixtures/schnorr_hardcoded_account_contract.js +37 -0
  62. package/dest/fixtures/setup.d.ts +44 -11
  63. package/dest/fixtures/setup.d.ts.map +1 -1
  64. package/dest/fixtures/setup.js +157 -28
  65. package/dest/fixtures/setup_p2p_test.d.ts +10 -6
  66. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  67. package/dest/fixtures/setup_p2p_test.js +8 -8
  68. package/dest/fixtures/token_utils.d.ts +1 -1
  69. package/dest/fixtures/token_utils.d.ts.map +1 -1
  70. package/dest/fixtures/token_utils.js +2 -5
  71. package/dest/fixtures/utils.d.ts +2 -2
  72. package/dest/fixtures/utils.d.ts.map +1 -1
  73. package/dest/fixtures/utils.js +1 -1
  74. package/dest/forward-compatibility/wallet_rpc_client.d.ts +7 -0
  75. package/dest/forward-compatibility/wallet_rpc_client.d.ts.map +1 -0
  76. package/dest/forward-compatibility/wallet_rpc_client.js +15 -0
  77. package/dest/forward-compatibility/wallet_service.d.ts +3 -0
  78. package/dest/forward-compatibility/wallet_service.d.ts.map +1 -0
  79. package/dest/forward-compatibility/wallet_service.js +109 -0
  80. package/dest/install_legacy_contracts.d.cts +10 -0
  81. package/dest/install_legacy_contracts.d.cts.map +1 -0
  82. package/dest/legacy-jest-resolver.d.cts +3 -0
  83. package/dest/legacy-jest-resolver.d.cts.map +1 -0
  84. package/dest/shared/cross_chain_test_harness.d.ts +4 -2
  85. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
  86. package/dest/shared/cross_chain_test_harness.js +9 -5
  87. package/dest/shared/gas_portal_test_harness.d.ts +8 -5
  88. package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
  89. package/dest/shared/gas_portal_test_harness.js +17 -8
  90. package/dest/shared/uniswap_l1_l2.d.ts +1 -1
  91. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  92. package/dest/shared/uniswap_l1_l2.js +50 -32
  93. package/dest/shared/wait_for_l1_to_l2_message.d.ts +13 -0
  94. package/dest/shared/wait_for_l1_to_l2_message.d.ts.map +1 -0
  95. package/dest/shared/wait_for_l1_to_l2_message.js +10 -0
  96. package/dest/simulators/lending_simulator.d.ts +10 -3
  97. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  98. package/dest/simulators/lending_simulator.js +24 -12
  99. package/dest/simulators/token_simulator.js +1 -1
  100. package/dest/spartan/setup_test_wallets.d.ts +1 -1
  101. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  102. package/dest/spartan/setup_test_wallets.js +72 -48
  103. package/dest/spartan/tx_metrics.d.ts +18 -4
  104. package/dest/spartan/tx_metrics.d.ts.map +1 -1
  105. package/dest/spartan/tx_metrics.js +73 -20
  106. package/dest/spartan/utils/config.d.ts +9 -35
  107. package/dest/spartan/utils/config.d.ts.map +1 -1
  108. package/dest/spartan/utils/nodes.js +2 -2
  109. package/dest/test-wallet/test_wallet.d.ts +25 -23
  110. package/dest/test-wallet/test_wallet.d.ts.map +1 -1
  111. package/dest/test-wallet/test_wallet.js +146 -87
  112. package/dest/test-wallet/utils.d.ts +3 -3
  113. package/dest/test-wallet/utils.d.ts.map +1 -1
  114. package/dest/test-wallet/utils.js +2 -7
  115. package/dest/test-wallet/wallet_worker_script.js +7 -2
  116. package/dest/test-wallet/worker_wallet.d.ts +5 -4
  117. package/dest/test-wallet/worker_wallet.d.ts.map +1 -1
  118. package/dest/test-wallet/worker_wallet.js +6 -2
  119. package/dest/test-wallet/worker_wallet_schema.d.ts +110 -224
  120. package/dest/test-wallet/worker_wallet_schema.d.ts.map +1 -1
  121. package/dest/test-wallet/worker_wallet_schema.js +14 -2
  122. package/package.json +46 -42
  123. package/src/bench/client_flows/benchmark.ts +19 -0
  124. package/src/bench/client_flows/client_flows_benchmark.ts +64 -53
  125. package/src/bench/utils.ts +2 -1
  126. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +24 -10
  127. package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +49 -11
  128. package/src/e2e_deploy_contract/deploy_test.ts +3 -2
  129. package/src/e2e_epochs/epochs_test.ts +98 -11
  130. package/src/e2e_fees/fees_test.ts +37 -4
  131. package/src/e2e_nested_contract/nested_contract_test.ts +3 -1
  132. package/src/e2e_p2p/inactivity_slash_test.ts +4 -3
  133. package/src/e2e_p2p/p2p_network.ts +57 -39
  134. package/src/e2e_p2p/reqresp/utils.ts +30 -12
  135. package/src/e2e_p2p/shared.ts +60 -71
  136. package/src/e2e_token_contract/token_contract_test.ts +12 -2
  137. package/src/fixtures/authwit_proxy.ts +4 -0
  138. package/src/fixtures/e2e_prover_test.ts +15 -18
  139. package/src/fixtures/fixtures.ts +83 -0
  140. package/src/fixtures/get_bb_config.ts +7 -6
  141. package/src/fixtures/ha_setup.ts +4 -2
  142. package/src/fixtures/schnorr_hardcoded_account_contract.ts +49 -0
  143. package/src/fixtures/setup.ts +186 -33
  144. package/src/fixtures/setup_p2p_test.ts +13 -9
  145. package/src/fixtures/token_utils.ts +1 -4
  146. package/src/fixtures/utils.ts +2 -0
  147. package/src/forward-compatibility/wallet_rpc_client.ts +14 -0
  148. package/src/forward-compatibility/wallet_service.ts +104 -0
  149. package/src/guides/up_quick_start.sh +0 -2
  150. package/src/install_legacy_contracts.cjs +75 -0
  151. package/src/legacy-jest-resolver.cjs +112 -0
  152. package/src/shared/cross_chain_test_harness.ts +14 -4
  153. package/src/shared/gas_portal_test_harness.ts +20 -10
  154. package/src/shared/uniswap_l1_l2.ts +84 -40
  155. package/src/shared/wait_for_l1_to_l2_message.ts +23 -0
  156. package/src/simulators/lending_simulator.ts +28 -12
  157. package/src/simulators/token_simulator.ts +1 -1
  158. package/src/spartan/setup_test_wallets.ts +69 -43
  159. package/src/spartan/tx_metrics.ts +81 -23
  160. package/src/spartan/utils/nodes.ts +2 -2
  161. package/src/test-wallet/test_wallet.ts +174 -104
  162. package/src/test-wallet/utils.ts +3 -7
  163. package/src/test-wallet/wallet_worker_script.ts +5 -2
  164. package/src/test-wallet/worker_wallet.ts +10 -5
  165. package/src/test-wallet/worker_wallet_schema.ts +2 -2
@@ -0,0 +1,49 @@
1
+ import { DefaultAccountContract } from '@aztec/accounts/defaults';
2
+ import type { ContractArtifact } from '@aztec/aztec.js/abi';
3
+ import type { AuthWitnessProvider } from '@aztec/aztec.js/account';
4
+ import type { CompleteAddress } from '@aztec/aztec.js/addresses';
5
+ import { AuthWitness } from '@aztec/aztec.js/authorization';
6
+ import type { Fr } from '@aztec/aztec.js/fields';
7
+ import { Schnorr } from '@aztec/foundation/crypto/schnorr';
8
+ import { GrumpkinScalar } from '@aztec/foundation/curves/grumpkin';
9
+ import { SchnorrHardcodedAccountContractArtifact } from '@aztec/noir-contracts.js/SchnorrHardcodedAccount';
10
+
11
+ /**
12
+ * The private key that matches the hardcoded public key in the SchnorrHardcodedAccountContract.
13
+ * The corresponding public key is baked into the Noir contract as a global constant.
14
+ */
15
+ export const SCHNORR_HARDCODED_PRIVATE_KEY = GrumpkinScalar.fromHexString(
16
+ '0xd35d743ac0dfe3d6dbe6be8c877cb524a00ab1e3d52d7bada095dfc8894ccfa',
17
+ );
18
+
19
+ /**
20
+ * Account contract backed by the SchnorrHardcodedAccount Noir contract.
21
+ * This contract verifies Schnorr signatures against a public key that is hardcoded
22
+ * in the contract artifact (not stored in a note), so it does not require on-chain
23
+ * deployment or initialization. Useful for tests that need a working account without
24
+ * mining any blocks.
25
+ */
26
+ export class SchnorrHardcodedKeyAccountContract extends DefaultAccountContract {
27
+ constructor(private privateKey: GrumpkinScalar = SCHNORR_HARDCODED_PRIVATE_KEY) {
28
+ super();
29
+ }
30
+
31
+ override getContractArtifact(): Promise<ContractArtifact> {
32
+ return Promise.resolve(SchnorrHardcodedAccountContractArtifact);
33
+ }
34
+
35
+ getInitializationFunctionAndArgs() {
36
+ return Promise.resolve(undefined);
37
+ }
38
+
39
+ getAuthWitnessProvider(_address: CompleteAddress): AuthWitnessProvider {
40
+ const privateKey = this.privateKey;
41
+ return {
42
+ async createAuthWit(messageHash: Fr): Promise<AuthWitness> {
43
+ const signer = new Schnorr();
44
+ const signature = await signer.constructSignature(messageHash, privateKey);
45
+ return new AuthWitness(messageHash, signature.toLimbFields());
46
+ },
47
+ };
48
+ }
49
+ }
@@ -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 DeployOptions,
11
+ type InteractionWaitOptions,
9
12
  getContractClassFromArtifact,
10
13
  waitForProven,
11
14
  } from '@aztec/aztec.js/contracts';
@@ -14,7 +17,7 @@ import { Fr } from '@aztec/aztec.js/fields';
14
17
  import { type Logger, createLogger } from '@aztec/aztec.js/log';
15
18
  import type { AztecNode } from '@aztec/aztec.js/node';
16
19
  import type { Wallet } from '@aztec/aztec.js/wallet';
17
- import { AnvilTestWatcher, CheatCodes } from '@aztec/aztec/testing';
20
+ import { AnvilTestWatcher, type AnvilTestWatcherOpts, CheatCodes } from '@aztec/aztec/testing';
18
21
  import { SPONSORED_FPC_SALT } from '@aztec/constants';
19
22
  import { isAnvilTestChain } from '@aztec/ethereum/chain';
20
23
  import { createExtendedL1Client } from '@aztec/ethereum/client';
@@ -45,12 +48,17 @@ import type { P2PClientDeps } from '@aztec/p2p';
45
48
  import { MockGossipSubNetwork, getMockPubSubP2PServiceFactory } from '@aztec/p2p/test-helpers';
46
49
  import { protocolContractsHash } from '@aztec/protocol-contracts';
47
50
  import type { ProverNodeConfig } from '@aztec/prover-node';
48
- import { type PXEConfig, getPXEConfig } from '@aztec/pxe/server';
51
+ import { type PXEConfig, type PXECreationOptions, getPXEConfig } from '@aztec/pxe/server';
49
52
  import type { SequencerClient } from '@aztec/sequencer-client';
53
+ import { AuthRegistryArtifact, getStandardAuthRegistry } from '@aztec/standard-contracts/auth-registry';
54
+ import { HandshakeRegistryArtifact, getStandardHandshakeRegistry } from '@aztec/standard-contracts/handshake-registry';
55
+ import { PublicChecksArtifact, getStandardPublicChecks } from '@aztec/standard-contracts/public-checks';
56
+ import { ARTIFACT_VERSION_BEFORE_INJECTION } from '@aztec/stdlib/abi';
50
57
  import { type ContractInstanceWithAddress, getContractInstanceFromInstantiationParams } from '@aztec/stdlib/contract';
51
- import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
58
+ import type { AztecNodeAdmin, AztecNodeDebug } from '@aztec/stdlib/interfaces/client';
52
59
  import { tryStop } from '@aztec/stdlib/interfaces/server';
53
60
  import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
61
+ import type { GenesisData } from '@aztec/stdlib/world-state';
54
62
  import {
55
63
  type TelemetryClient,
56
64
  type TelemetryClientConfig,
@@ -177,8 +185,11 @@ export type SetupOptions = {
177
185
  proverNodeConfig?: Partial<ProverNodeConfig>;
178
186
  /** Whether to use a mock gossip sub network for p2p clients. */
179
187
  mockGossipSubNetwork?: boolean;
188
+ /** Whether to add simulated latency to the mock gossipsub network (in ms) */
189
+ mockGossipSubNetworkLatency?: number;
180
190
  /** Whether to disable the anvil test watcher (can still be manually started) */
181
191
  disableAnvilTestWatcher?: boolean;
192
+ anvilTestWatcherOpts?: AnvilTestWatcherOpts;
182
193
  /** Whether to enable anvil automine during deployment of L1 contracts (consider defaulting this to true). */
183
194
  automineL1Setup?: boolean;
184
195
  /** How many accounts to seed and unlock in anvil. */
@@ -200,8 +211,16 @@ export type SetupOptions = {
200
211
  skipAccountDeployment?: boolean;
201
212
  /** L1 contracts deployment arguments. */
202
213
  l1ContractsArgs?: Partial<DeployAztecL1ContractsArgs>;
203
- /** Wallet minimum fee padding multiplier (defaults to 0.5, which is 50% padding). */
214
+ /** Wallet minimum fee padding multiplier */
204
215
  walletMinFeePadding?: number;
216
+ /** Whether the initial node should be a lightweight RPC-only node (no sequencer, no validator).
217
+ * Use for tests that create their own validator nodes and don't need the initial sequencer. */
218
+ skipInitialSequencer?: boolean;
219
+ /** Whether to swap the production Sequencer for the minimal AutomineSequencer.
220
+ * Use only for single-sequencer non-block-building tests. See AUTOMINE_E2E_OPTS in `fixtures.ts`. */
221
+ useAutomineSequencer?: boolean;
222
+ /** Options forwarded to PXE creation (e.g. execution hooks). */
223
+ pxeCreationOptions?: PXECreationOptions;
205
224
  } & Partial<AztecNodeConfig>;
206
225
 
207
226
  /** Context for an end-to-end test as returned by the `setup` function */
@@ -209,7 +228,7 @@ export type EndToEndContext = {
209
228
  /** The Anvil instance (only set if anvil was started locally). */
210
229
  anvil: Anvil | undefined;
211
230
  /** The Aztec Node service or client a connected to it. */
212
- aztecNode: AztecNode;
231
+ aztecNode: AztecNode & AztecNodeDebug;
213
232
  /** The Aztec Node as a service. */
214
233
  aztecNodeService: AztecNodeService;
215
234
  /** Client to the Aztec Node admin interface. */
@@ -248,8 +267,8 @@ export type EndToEndContext = {
248
267
  sequencerDelayer: Delayer | undefined;
249
268
  /** Delayer for prover node L1 txs (only when enableDelayer and startProverNode are true). */
250
269
  proverDelayer: Delayer | undefined;
251
- /** Prefilled public data used for setting up nodes. */
252
- prefilledPublicData: PublicDataTreeLeaf[] | undefined;
270
+ /** Genesis data used for setting up nodes. */
271
+ genesis: GenesisData | undefined;
253
272
  /** ACVM config (only set if running locally). */
254
273
  acvmConfig: Awaited<ReturnType<typeof getACVMConfig>>;
255
274
  /** BB config (only set if running locally). */
@@ -260,6 +279,32 @@ export type EndToEndContext = {
260
279
  teardown: () => Promise<void>;
261
280
  };
262
281
 
282
+ /**
283
+ * When CONTRACT_ARTIFACTS_VERSION is set (backwards compatibility testing), asserts that the loaded artifact's
284
+ * aztecVersion matches the expected version. This is a sanity check verifying that the legacy artifact resolver
285
+ * actually swapped in the correct version.
286
+ */
287
+ function assertContractArtifactsVersion() {
288
+ const expected = process.env.CONTRACT_ARTIFACTS_VERSION;
289
+ if (!expected) {
290
+ return;
291
+ }
292
+ const { aztecVersion } = SponsoredFPCContract.artifact;
293
+ // TODO(F-557): Remove this bypass once pre-version artifacts are no longer tested.
294
+ if (aztecVersion === ARTIFACT_VERSION_BEFORE_INJECTION) {
295
+ createLogger('e2e:setup').info(
296
+ `Skipping artifact version check: artifact predates version injection (CONTRACT_ARTIFACTS_VERSION=${expected})`,
297
+ );
298
+ return;
299
+ }
300
+ if (aztecVersion !== expected) {
301
+ throw new Error(
302
+ `Artifact version mismatch: expected ${expected} but got ${aztecVersion}. ` +
303
+ `The legacy artifact resolver may not have swapped in the correct version.`,
304
+ );
305
+ }
306
+ }
307
+
263
308
  /**
264
309
  * Sets up the environment for the end-to-end tests.
265
310
  * @param numberOfAccounts - The number of new accounts to be created once the PXE is initiated.
@@ -272,10 +317,11 @@ export async function setup(
272
317
  pxeOpts: Partial<PXEConfig> = {},
273
318
  chain: Chain = foundry,
274
319
  ): Promise<EndToEndContext> {
320
+ assertContractArtifactsVersion();
275
321
  let anvil: Anvil | undefined;
276
322
  try {
277
323
  opts.aztecTargetCommitteeSize ??= 0;
278
- opts.slasherFlavor ??= 'none';
324
+ opts.slasherEnabled ??= false;
279
325
 
280
326
  const config: AztecNodeConfig & SetupOptions = { ...getConfigEnvVars(), ...opts };
281
327
  // use initialValidators for the node config
@@ -302,6 +348,8 @@ export async function setup(
302
348
  config.dataDirectory = directoryToCleanup;
303
349
  }
304
350
 
351
+ const dateProvider = new TestDateProvider();
352
+
305
353
  if (!config.l1RpcUrls?.length) {
306
354
  if (!isAnvilTestChain(chain.id)) {
307
355
  throw new Error(`No ETHEREUM_HOSTS set but non anvil chain requested`);
@@ -311,6 +359,7 @@ export async function setup(
311
359
  accounts: opts.anvilAccounts,
312
360
  port: opts.anvilPort ?? (process.env.ANVIL_PORT ? parseInt(process.env.ANVIL_PORT) : undefined),
313
361
  slotsInAnEpoch: opts.anvilSlotsInAnEpoch,
362
+ dateProvider,
314
363
  });
315
364
  anvil = res.anvil;
316
365
  config.l1RpcUrls = [res.rpcUrl];
@@ -322,8 +371,6 @@ export async function setup(
322
371
  logger.info(`Logging metrics to ${filename}`);
323
372
  setupMetricsLogger(filename);
324
373
  }
325
-
326
- const dateProvider = new TestDateProvider();
327
374
  const ethCheatCodes = new EthCheatCodesWithState(config.l1RpcUrls, dateProvider);
328
375
 
329
376
  if (opts.stateLoad) {
@@ -373,10 +420,12 @@ export async function setup(
373
420
  addressesToFund.push(sponsoredFPCAddress);
374
421
  }
375
422
 
376
- const { genesisArchiveRoot, prefilledPublicData, fundingNeeded } = await getGenesisValues(
423
+ const genesisTimestamp = BigInt(Math.floor(Date.now() / 1000));
424
+ const { genesisArchiveRoot, genesis, fundingNeeded } = await getGenesisValues(
377
425
  addressesToFund,
378
426
  opts.initialAccountFeeJuice,
379
427
  opts.genesisPublicData,
428
+ genesisTimestamp,
380
429
  );
381
430
 
382
431
  const wasAutomining = await ethCheatCodes.isAutoMining();
@@ -411,19 +460,38 @@ export async function setup(
411
460
  },
412
461
  );
413
462
 
414
- config.l1Contracts = deployL1ContractsValues.l1ContractAddresses;
463
+ Object.assign(config, deployL1ContractsValues.l1ContractAddresses);
415
464
  config.rollupVersion = deployL1ContractsValues.rollupVersion;
416
465
 
466
+ // Propagate L1-contracts-config overrides back to the node config so the archiver's
467
+ // `l1Constants` (and any other node-side consumer) agrees with what was actually deployed.
468
+ // Without this, a per-test override like `aztecEpochDuration: 4` lands on the rollup contract
469
+ // but the node config keeps the default (32), so `archiver.isEpochComplete(0)` computes
470
+ // `endSlot=31` and `EpochTestSettler`/`EpochMonitor` never fires — letting the
471
+ // `aztecProofSubmissionEpochs` window expire mid-test and prune the pending chain.
472
+ // Skip undefined values: callers (e.g. `P2PNetworkTest`) sometimes build `l1ContractsArgs`
473
+ // by spreading a partial `AztecNodeConfig`, which leaves unset fields (notably `dataDirectory`)
474
+ // as `undefined`. A blind Object.assign would then clobber the temp `dataDirectory` set earlier
475
+ // in this function and crash `setupSharedBlobStorage`.
476
+ if (opts.l1ContractsArgs) {
477
+ for (const [key, value] of Object.entries(opts.l1ContractsArgs)) {
478
+ if (value !== undefined) {
479
+ (config as unknown as Record<string, unknown>)[key] = value;
480
+ }
481
+ }
482
+ }
483
+
417
484
  if (enableAutomine) {
418
485
  await ethCheatCodes.setAutomine(false);
419
486
  await ethCheatCodes.setIntervalMining(config.ethereumSlotDuration);
420
487
  }
421
488
 
422
- // Always sync dateProvider to L1 time after deploying L1 contracts, regardless of mining mode.
423
- // In compose mode, L1 time may have drifted ahead of system time due to the local-network watcher
424
- // warping time forward on each filled slot. Without this sync, the sequencer computes the wrong
425
- // slot from its dateProvider and cannot propose blocks.
426
- dateProvider.setTime((await ethCheatCodes.timestamp()) * 1000);
489
+ // In compose mode (no local anvil), sync dateProvider to L1 time since it may have drifted
490
+ // ahead of system time due to the local-network watcher warping time forward on each filled slot.
491
+ // When running with a local anvil, the dateProvider is kept in sync via the stdout listener.
492
+ if (!anvil) {
493
+ dateProvider.setTime((await ethCheatCodes.lastBlockTimestamp()) * 1000);
494
+ }
427
495
 
428
496
  if (opts.l2StartTime) {
429
497
  await ethCheatCodes.warp(opts.l2StartTime, { resetBlockInterval: true });
@@ -434,6 +502,7 @@ export async function setup(
434
502
  deployL1ContractsValues.l1ContractAddresses.rollupAddress,
435
503
  deployL1ContractsValues.l1Client,
436
504
  dateProvider,
505
+ opts.anvilTestWatcherOpts,
437
506
  );
438
507
  if (!opts.disableAnvilTestWatcher) {
439
508
  await watcher.start();
@@ -464,7 +533,7 @@ export async function setup(
464
533
  let p2pClientDeps: P2PClientDeps | undefined = undefined;
465
534
 
466
535
  if (opts.mockGossipSubNetwork) {
467
- mockGossipSubNetwork = new MockGossipSubNetwork();
536
+ mockGossipSubNetwork = new MockGossipSubNetwork(opts.mockGossipSubNetworkLatency);
468
537
  p2pClientDeps = { p2pServiceFactory: getMockPubSubP2PServiceFactory(mockGossipSubNetwork) };
469
538
  }
470
539
 
@@ -477,11 +546,17 @@ export async function setup(
477
546
  throw new Error('minTxsPerBlock is undefined in e2e test setup');
478
547
  }
479
548
 
480
- // Only set minTxsPerBlock=1 if we're going to deploy accounts and need reliable block inclusion
549
+ // Whether we're deploying accounts (and therefore need reliable block inclusion past genesis)
481
550
  const shouldDeployAccounts = numberOfAccounts > 0 && !opts.skipAccountDeployment;
482
551
  // Only set minTxsPerBlock=0 if we need an empty block (no accounts at all, not skipped deployment)
483
552
  const needsEmptyBlock = numberOfAccounts === 0 && !opts.skipAccountDeployment;
484
- config.minTxsPerBlock = shouldDeployAccounts ? 1 : needsEmptyBlock ? 0 : originalMinTxsPerBlock;
553
+ // Pipelining is always on: the proposer builds during slot N-1 for slot N. A tx submitted at
554
+ // slot N start arrives after that build, so forcing minTxsPerBlock=1 would stall the chain on
555
+ // alternating slots -- hence empty checkpoints are allowed (minTxsPerBlock=0) for account
556
+ // deployment. Automine is unaffected: its runBuild clamps mempool builds to
557
+ // Math.max(minTxsPerBlock ?? 1, 1) and still requires minValidTxs: 1.
558
+ const accountsDeployMinTxs = 0;
559
+ config.minTxsPerBlock = shouldDeployAccounts ? accountsDeployMinTxs : needsEmptyBlock ? 0 : originalMinTxsPerBlock;
485
560
 
486
561
  config.p2pEnabled = opts.mockGossipSubNetwork || config.p2pEnabled;
487
562
  config.p2pIp = opts.p2pIp ?? config.p2pIp ?? '127.0.0.1';
@@ -492,11 +567,22 @@ export async function setup(
492
567
  }
493
568
  }
494
569
 
570
+ // When skipInitialSequencer is set, the initial node is a lightweight RPC-only node.
571
+ // We apply these overrides to a copy so they don't leak into the returned config.
572
+ // Keep P2P enabled if mockGossipSubNetwork is used (needed for tx propagation to validators).
573
+ const initialNodeConfig = opts.skipInitialSequencer
574
+ ? {
575
+ ...config,
576
+ disableValidator: true,
577
+ ...(opts.mockGossipSubNetwork ? {} : { p2pEnabled: false, bootstrapNodes: [] as string[] }),
578
+ }
579
+ : config;
580
+
495
581
  const aztecNodeService = await withLoggerBindings({ actor: 'node-0' }, () =>
496
582
  AztecNodeService.createAndSync(
497
- config,
583
+ initialNodeConfig,
498
584
  { dateProvider, telemetry: telemetryClient, p2pClientDeps },
499
- { prefilledPublicData },
585
+ { genesis, dontStartSequencer: opts.skipInitialSequencer },
500
586
  ),
501
587
  );
502
588
  const sequencerClient = aztecNodeService.getSequencer();
@@ -521,7 +607,7 @@ export async function setup(
521
607
  dataDirectory: proverNodeDataDirectory,
522
608
  },
523
609
  { dateProvider, p2pClientDeps, telemetry: telemetryClient },
524
- { prefilledPublicData },
610
+ { genesis },
525
611
  ));
526
612
  }
527
613
 
@@ -533,13 +619,21 @@ export async function setup(
533
619
  pxeConfig.dataDirectory = path.join(directoryToCleanup, randomBytes(8).toString('hex'));
534
620
  // For tests we only want proving enabled if specifically requested
535
621
  pxeConfig.proverEnabled = !!pxeOpts.proverEnabled;
536
- const wallet = await TestWallet.create(aztecNodeService, pxeConfig, { loggerActorLabel: 'pxe-0' });
622
+ const wallet = await TestWallet.create(aztecNodeService, pxeConfig, {
623
+ loggerActorLabel: 'pxe-0',
624
+ ...opts.pxeCreationOptions,
625
+ });
537
626
 
538
627
  if (opts.walletMinFeePadding !== undefined) {
539
628
  wallet.setMinFeePadding(opts.walletMinFeePadding);
540
629
  }
541
630
 
542
- const cheatCodes = await CheatCodes.create(config.l1RpcUrls, aztecNodeService, dateProvider);
631
+ const cheatCodes = await CheatCodes.create(
632
+ config.l1RpcUrls,
633
+ aztecNodeService,
634
+ dateProvider,
635
+ aztecNodeService.getAutomineSequencer(),
636
+ );
543
637
 
544
638
  if (
545
639
  (opts.aztecTargetCommitteeSize && opts.aztecTargetCommitteeSize > 0) ||
@@ -557,15 +651,22 @@ export async function setup(
557
651
 
558
652
  let accounts: AztecAddress[] = [];
559
653
 
560
- if (shouldDeployAccounts) {
654
+ if (opts.skipInitialSequencer) {
655
+ logger.info('Sequencer not started on initial node, skipping block progression');
656
+ } else if (shouldDeployAccounts) {
561
657
  logger.info(
562
- `${numberOfAccounts} accounts are being deployed. Reliably progressing past genesis by setting minTxsPerBlock to 1 and waiting for the accounts to be deployed`,
658
+ `${numberOfAccounts} accounts are being deployed. Reliably progressing past genesis by waiting for the accounts to be deployed`,
563
659
  );
564
660
  const accountsData = initialFundedAccounts.slice(0, numberOfAccounts);
565
661
  const accountManagers = await deployFundedSchnorrAccounts(wallet, accountsData);
566
662
  accounts = accountManagers.map(accountManager => accountManager.address);
567
663
  } else if (needsEmptyBlock) {
568
664
  logger.info('No accounts are being deployed, waiting for an empty block 1 to be mined');
665
+ // AutomineSequencer only builds on tx arrival; explicitly request an empty block.
666
+ const automine = aztecNodeService.getAutomineSequencer();
667
+ if (automine) {
668
+ await automine.buildEmptyBlock();
669
+ }
569
670
  while ((await aztecNodeService.getBlockNumber()) === 0) {
570
671
  await sleep(2000);
571
672
  }
@@ -626,7 +727,7 @@ export async function setup(
626
727
  initialFundedAccounts,
627
728
  logger,
628
729
  mockGossipSubNetwork,
629
- prefilledPublicData,
730
+ genesis,
630
731
  proverNode,
631
732
  sequencerDelayer,
632
733
  proverDelayer,
@@ -706,7 +807,7 @@ export async function waitForProvenChain(node: AztecNode, targetBlock?: BlockNum
706
807
  targetBlock ??= await node.getBlockNumber();
707
808
 
708
809
  await retryUntil(
709
- async () => (await node.getProvenBlockNumber()) >= targetBlock,
810
+ async () => (await node.getBlockNumber('proven')) >= targetBlock,
710
811
  'proven chain status',
711
812
  timeoutSec,
712
813
  intervalSec,
@@ -726,7 +827,7 @@ export function createAndSyncProverNode(
726
827
  dateProvider: DateProvider;
727
828
  p2pClientDeps?: P2PClientDeps;
728
829
  },
729
- options: { prefilledPublicData: PublicDataTreeLeaf[]; dontStart?: boolean },
830
+ options: { genesis?: GenesisData; dontStart?: boolean },
730
831
  ): Promise<{ proverNode: AztecNodeService }> {
731
832
  return withLoggerBindings({ actor: 'prover-0' }, async () => {
732
833
  const proverNode = await AztecNodeService.createAndSync(
@@ -739,7 +840,7 @@ export function createAndSyncProverNode(
739
840
  proverPublisherPrivateKeys: [new SecretValue(proverNodePrivateKey)],
740
841
  },
741
842
  deps,
742
- { ...options, dontStartProverNode: options.dontStart },
843
+ { genesis: options.genesis, dontStartProverNode: options.dontStart },
743
844
  );
744
845
 
745
846
  if (!proverNode.getProverNode()) {
@@ -796,6 +897,57 @@ export async function expectMappingDelta<K, V extends number | bigint>(
796
897
  expect(diffs).toEqual(expectedDiffs);
797
898
  }
798
899
 
900
+ /**
901
+ * Registers the auth_registry contract class and publishes its standard instance if not already
902
+ * present, and registers the artifact with PXE. Publishing is required before exercising the public
903
+ * authwit path (which relies on the AVM's deployment-nullifier check); the PXE-side registration is
904
+ * required so revert messages from AuthRegistry calls can be enriched (otherwise assertion strings
905
+ * surface as generic "Assertion failed:" and tests that match on the real message fail).
906
+ */
907
+ export async function ensureAuthRegistryPublished(wallet: Wallet, from: AztecAddress) {
908
+ const { instance, contractClass } = await getStandardAuthRegistry();
909
+ if (!(await wallet.getContractClassMetadata(contractClass.id)).isContractClassPubliclyRegistered) {
910
+ await (await publishContractClass(wallet, AuthRegistryArtifact)).send({ from });
911
+ }
912
+ if (!(await wallet.getContractMetadata(instance.address)).isContractPublished) {
913
+ await publishInstance(wallet, instance).send({ from });
914
+ }
915
+ await wallet.registerContract(instance, AuthRegistryArtifact);
916
+ }
917
+
918
+ /**
919
+ * Registers the public_checks contract class and publishes its standard instance if not already
920
+ * present, and registers the artifact with PXE. Required for any contract that calls
921
+ * `privately_check_timestamp` / `privately_check_block_number` (which dispatch into the
922
+ * deployed PublicChecks contract via an enqueued public call).
923
+ */
924
+ export async function ensurePublicChecksPublished(wallet: Wallet, from: AztecAddress) {
925
+ const { instance, contractClass } = await getStandardPublicChecks();
926
+ if (!(await wallet.getContractClassMetadata(contractClass.id)).isContractClassPubliclyRegistered) {
927
+ await (await publishContractClass(wallet, PublicChecksArtifact)).send({ from });
928
+ }
929
+ if (!(await wallet.getContractMetadata(instance.address)).isContractPublished) {
930
+ await publishInstance(wallet, instance).send({ from });
931
+ }
932
+ await wallet.registerContract(instance, PublicChecksArtifact);
933
+ }
934
+
935
+ /**
936
+ * Registers the handshake_registry contract class and publishes its standard instance if not
937
+ * already present, and registers the artifact with PXE. Required for constrained-delivery flows
938
+ * that call into the HandshakeRegistry at its well-known address.
939
+ */
940
+ export async function ensureHandshakeRegistryPublished(wallet: Wallet, from: AztecAddress) {
941
+ const { instance, contractClass } = await getStandardHandshakeRegistry();
942
+ if (!(await wallet.getContractClassMetadata(contractClass.id)).isContractClassPubliclyRegistered) {
943
+ await (await publishContractClass(wallet, HandshakeRegistryArtifact)).send({ from });
944
+ }
945
+ if (!(await wallet.getContractMetadata(instance.address)).isContractPublished) {
946
+ await publishInstance(wallet, instance).send({ from });
947
+ }
948
+ await wallet.registerContract(instance, HandshakeRegistryArtifact);
949
+ }
950
+
799
951
  /**
800
952
  * Registers the contract class used for test accounts and publicly deploys the instances requested.
801
953
  * Use this when you need to make a public call to an account contract, such as for requesting a public authwit.
@@ -830,7 +982,7 @@ export async function ensureAccountContractsPublished(wallet: Wallet, accountsTo
830
982
  * Returns deployed account data that can be used by tests.
831
983
  */
832
984
  export const deployAccounts =
833
- (numberOfAccounts: number, logger: Logger) =>
985
+ (numberOfAccounts: number, logger: Logger, deployOptions?: Partial<DeployOptions<InteractionWaitOptions>>) =>
834
986
  async ({ wallet, initialFundedAccounts }: { wallet: TestWallet; initialFundedAccounts: InitialAccountData[] }) => {
835
987
  if (initialFundedAccounts.length < numberOfAccounts) {
836
988
  throw new Error(`Cannot deploy more than ${initialFundedAccounts.length} initial accounts.`);
@@ -847,8 +999,9 @@ export const deployAccounts =
847
999
  );
848
1000
  const deployMethod = await accountManager.getDeployMethod();
849
1001
  await deployMethod.send({
850
- from: AztecAddress.ZERO,
1002
+ from: NO_FROM,
851
1003
  skipClassPublication: i !== 0, // Publish the contract class at most once.
1004
+ ...deployOptions,
852
1005
  });
853
1006
  }
854
1007
 
@@ -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
  );
@@ -88,6 +88,10 @@ export type CreateNodeConfig = AztecNodeConfig & {
88
88
  dontStartSequencer?: boolean;
89
89
  /** Override the private key (instead of deriving from addressIndex). */
90
90
  validatorPrivateKey?: `0x${string}`;
91
+ /** Corrupt only the block proposal at this indexWithinCheckpoint (testing only). */
92
+ invalidBlockProposalIndexWithinCheckpoint?: number;
93
+ /** Accept proposal gossip regardless of slot timing (testing only). */
94
+ skipProposalSlotValidation?: boolean;
91
95
  };
92
96
 
93
97
  /** Creates a P2P enabled instance of Aztec Node Service with a validator. */
@@ -97,7 +101,7 @@ export async function createNode(
97
101
  tcpPort: number,
98
102
  bootstrapNode: string | undefined,
99
103
  addressIndex: number | number[],
100
- prefilledPublicData?: PublicDataTreeLeaf[],
104
+ genesis?: GenesisData,
101
105
  dataDirectory?: string,
102
106
  metricsPort?: number,
103
107
  ) {
@@ -108,7 +112,7 @@ export async function createNode(
108
112
  return await AztecNodeService.createAndSync(
109
113
  validatorConfig,
110
114
  { telemetry, dateProvider },
111
- { prefilledPublicData, dontStartSequencer: config.dontStartSequencer },
115
+ { genesis, dontStartSequencer: config.dontStartSequencer },
112
116
  );
113
117
  });
114
118
  }
@@ -119,7 +123,7 @@ export async function createNonValidatorNode(
119
123
  dateProvider: DateProvider,
120
124
  tcpPort: number,
121
125
  bootstrapNode: string | undefined,
122
- prefilledPublicData?: PublicDataTreeLeaf[],
126
+ genesis?: GenesisData,
123
127
  dataDirectory?: string,
124
128
  metricsPort?: number,
125
129
  ) {
@@ -133,7 +137,7 @@ export async function createNonValidatorNode(
133
137
  sequencerPublisherPrivateKeys: [],
134
138
  };
135
139
  const telemetry = await getEndToEndTestTelemetryClient(metricsPort);
136
- return await AztecNodeService.createAndSync(config, { telemetry, dateProvider }, { prefilledPublicData });
140
+ return await AztecNodeService.createAndSync(config, { telemetry, dateProvider }, { genesis });
137
141
  });
138
142
  }
139
143
 
@@ -143,7 +147,7 @@ export async function createProverNode(
143
147
  bootstrapNode: string | undefined,
144
148
  addressIndex: number,
145
149
  deps: { dateProvider: DateProvider },
146
- prefilledPublicData?: PublicDataTreeLeaf[],
150
+ genesis?: GenesisData,
147
151
  dataDirectory?: string,
148
152
  metricsPort?: number,
149
153
  ): Promise<{ proverNode: AztecNodeService }> {
@@ -159,7 +163,7 @@ export async function createProverNode(
159
163
  { ...config, ...p2pConfig },
160
164
  { dataDirectory },
161
165
  { ...deps, telemetry },
162
- { prefilledPublicData: prefilledPublicData ?? [] },
166
+ { genesis },
163
167
  );
164
168
  });
165
169
  }
@@ -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) {
@@ -9,6 +9,8 @@ export {
9
9
  createAndSyncProverNode,
10
10
  deployAccounts,
11
11
  ensureAccountContractsPublished,
12
+ ensureAuthRegistryPublished,
13
+ ensurePublicChecksPublished,
12
14
  expectMapping,
13
15
  expectMappingDelta,
14
16
  getBalancesFn,
@@ -0,0 +1,14 @@
1
+ import type { Wallet } from '@aztec/aztec.js/wallet';
2
+ import { WalletSchema } from '@aztec/aztec.js/wallet';
3
+ import { createSafeJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/client';
4
+
5
+ /**
6
+ * Creates a JSON-RPC client that connects to a remote wallet service.
7
+ * The returned object implements the {@link Wallet} interface, proxying all calls over HTTP to the specified URL.
8
+ */
9
+ export function createWalletClient(url: string): Wallet {
10
+ return createSafeJsonRpcClient<Wallet>(url, WalletSchema, {
11
+ namespaceMethods: 'wallet',
12
+ fetch: makeFetch([1, 2, 3], false),
13
+ });
14
+ }