@aztec/end-to-end 4.0.0-nightly.20250907 → 4.0.0-nightly.20260108

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/dest/bench/client_flows/benchmark.d.ts +4 -3
  2. package/dest/bench/client_flows/benchmark.d.ts.map +1 -1
  3. package/dest/bench/client_flows/benchmark.js +2 -2
  4. package/dest/bench/client_flows/client_flows_benchmark.d.ts +26 -15
  5. package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
  6. package/dest/bench/client_flows/client_flows_benchmark.js +111 -90
  7. package/dest/bench/client_flows/config.d.ts +1 -1
  8. package/dest/bench/client_flows/data_extractor.d.ts +1 -1
  9. package/dest/bench/client_flows/data_extractor.js +10 -30
  10. package/dest/bench/utils.d.ts +3 -12
  11. package/dest/bench/utils.d.ts.map +1 -1
  12. package/dest/bench/utils.js +17 -37
  13. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +8 -8
  14. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
  15. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +42 -42
  16. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +13 -10
  17. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts.map +1 -1
  18. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.js +35 -35
  19. package/dest/e2e_deploy_contract/deploy_test.d.ts +12 -6
  20. package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -1
  21. package/dest/e2e_deploy_contract/deploy_test.js +9 -18
  22. package/dest/e2e_epochs/epochs_test.d.ts +20 -12
  23. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  24. package/dest/e2e_epochs/epochs_test.js +36 -27
  25. package/dest/e2e_fees/bridging_race.notest.d.ts +1 -1
  26. package/dest/e2e_fees/bridging_race.notest.js +14 -11
  27. package/dest/e2e_fees/fees_test.d.ts +13 -9
  28. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  29. package/dest/e2e_fees/fees_test.js +39 -40
  30. package/dest/e2e_l1_publisher/write_json.d.ts +4 -2
  31. package/dest/e2e_l1_publisher/write_json.d.ts.map +1 -1
  32. package/dest/e2e_l1_publisher/write_json.js +9 -8
  33. package/dest/e2e_multi_validator/utils.d.ts +2 -2
  34. package/dest/e2e_multi_validator/utils.d.ts.map +1 -1
  35. package/dest/e2e_multi_validator/utils.js +4 -10
  36. package/dest/e2e_nested_contract/nested_contract_test.d.ts +7 -4
  37. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
  38. package/dest/e2e_nested_contract/nested_contract_test.js +11 -12
  39. package/dest/e2e_p2p/inactivity_slash_test.d.ts +31 -0
  40. package/dest/e2e_p2p/inactivity_slash_test.d.ts.map +1 -0
  41. package/dest/e2e_p2p/inactivity_slash_test.js +136 -0
  42. package/dest/e2e_p2p/p2p_network.d.ts +238 -18
  43. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  44. package/dest/e2e_p2p/p2p_network.js +50 -25
  45. package/dest/e2e_p2p/shared.d.ts +16 -17
  46. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  47. package/dest/e2e_p2p/shared.js +57 -56
  48. package/dest/e2e_token_contract/token_contract_test.d.ts +6 -5
  49. package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
  50. package/dest/e2e_token_contract/token_contract_test.js +14 -17
  51. package/dest/fixtures/e2e_prover_test.d.ts +13 -11
  52. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  53. package/dest/fixtures/e2e_prover_test.js +57 -66
  54. package/dest/fixtures/fixtures.d.ts +2 -3
  55. package/dest/fixtures/fixtures.d.ts.map +1 -1
  56. package/dest/fixtures/fixtures.js +2 -3
  57. package/dest/fixtures/get_acvm_config.d.ts +2 -2
  58. package/dest/fixtures/get_acvm_config.d.ts.map +1 -1
  59. package/dest/fixtures/get_acvm_config.js +1 -1
  60. package/dest/fixtures/get_bb_config.d.ts +2 -2
  61. package/dest/fixtures/get_bb_config.d.ts.map +1 -1
  62. package/dest/fixtures/get_bb_config.js +2 -2
  63. package/dest/fixtures/index.d.ts +1 -1
  64. package/dest/fixtures/l1_to_l2_messaging.d.ts +4 -3
  65. package/dest/fixtures/l1_to_l2_messaging.d.ts.map +1 -1
  66. package/dest/fixtures/l1_to_l2_messaging.js +2 -2
  67. package/dest/fixtures/logging.d.ts +1 -1
  68. package/dest/fixtures/setup_p2p_test.d.ts +12 -11
  69. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  70. package/dest/fixtures/setup_p2p_test.js +50 -24
  71. package/dest/fixtures/snapshot_manager.d.ts +16 -15
  72. package/dest/fixtures/snapshot_manager.d.ts.map +1 -1
  73. package/dest/fixtures/snapshot_manager.js +84 -88
  74. package/dest/fixtures/token_utils.d.ts +10 -5
  75. package/dest/fixtures/token_utils.d.ts.map +1 -1
  76. package/dest/fixtures/token_utils.js +17 -18
  77. package/dest/fixtures/utils.d.ts +44 -47
  78. package/dest/fixtures/utils.d.ts.map +1 -1
  79. package/dest/fixtures/utils.js +128 -185
  80. package/dest/fixtures/web3signer.d.ts +5 -0
  81. package/dest/fixtures/web3signer.d.ts.map +1 -0
  82. package/dest/fixtures/web3signer.js +53 -0
  83. package/dest/fixtures/with_telemetry_utils.d.ts +2 -2
  84. package/dest/fixtures/with_telemetry_utils.d.ts.map +1 -1
  85. package/dest/fixtures/with_telemetry_utils.js +2 -2
  86. package/dest/index.d.ts +1 -1
  87. package/dest/quality_of_service/alert_checker.d.ts +2 -2
  88. package/dest/quality_of_service/alert_checker.d.ts.map +1 -1
  89. package/dest/shared/cross_chain_test_harness.d.ts +20 -23
  90. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
  91. package/dest/shared/cross_chain_test_harness.js +14 -16
  92. package/dest/shared/gas_portal_test_harness.d.ts +10 -17
  93. package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
  94. package/dest/shared/gas_portal_test_harness.js +11 -8
  95. package/dest/shared/index.d.ts +1 -1
  96. package/dest/shared/jest_setup.d.ts +1 -1
  97. package/dest/shared/jest_setup.js +1 -1
  98. package/dest/shared/submit-transactions.d.ts +6 -4
  99. package/dest/shared/submit-transactions.d.ts.map +1 -1
  100. package/dest/shared/submit-transactions.js +8 -7
  101. package/dest/shared/uniswap_l1_l2.d.ts +13 -9
  102. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  103. package/dest/shared/uniswap_l1_l2.js +44 -58
  104. package/dest/simulators/index.d.ts +1 -1
  105. package/dest/simulators/lending_simulator.d.ts +4 -7
  106. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  107. package/dest/simulators/lending_simulator.js +8 -5
  108. package/dest/simulators/token_simulator.d.ts +4 -2
  109. package/dest/simulators/token_simulator.d.ts.map +1 -1
  110. package/dest/simulators/token_simulator.js +2 -2
  111. package/dest/spartan/setup_test_wallets.d.ts +22 -14
  112. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  113. package/dest/spartan/setup_test_wallets.js +144 -86
  114. package/dest/spartan/tx_metrics.d.ts +39 -0
  115. package/dest/spartan/tx_metrics.d.ts.map +1 -0
  116. package/dest/spartan/tx_metrics.js +95 -0
  117. package/dest/spartan/utils.d.ts +101 -16
  118. package/dest/spartan/utils.d.ts.map +1 -1
  119. package/dest/spartan/utils.js +414 -52
  120. package/package.json +43 -40
  121. package/src/bench/client_flows/benchmark.ts +8 -8
  122. package/src/bench/client_flows/client_flows_benchmark.ts +143 -115
  123. package/src/bench/client_flows/data_extractor.ts +9 -31
  124. package/src/bench/utils.ts +15 -39
  125. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +46 -63
  126. package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +46 -55
  127. package/src/e2e_deploy_contract/deploy_test.ts +18 -36
  128. package/src/e2e_epochs/epochs_test.ts +59 -42
  129. package/src/e2e_fees/bridging_race.notest.ts +16 -11
  130. package/src/e2e_fees/fees_test.ts +48 -52
  131. package/src/e2e_l1_publisher/write_json.ts +12 -9
  132. package/src/e2e_multi_validator/utils.ts +5 -11
  133. package/src/e2e_nested_contract/nested_contract_test.ts +15 -13
  134. package/src/e2e_p2p/inactivity_slash_test.ts +179 -0
  135. package/src/e2e_p2p/p2p_network.ts +125 -89
  136. package/src/e2e_p2p/shared.ts +69 -60
  137. package/src/e2e_token_contract/token_contract_test.ts +17 -17
  138. package/src/fixtures/e2e_prover_test.ts +65 -105
  139. package/src/fixtures/fixtures.ts +2 -5
  140. package/src/fixtures/get_acvm_config.ts +2 -2
  141. package/src/fixtures/get_bb_config.ts +3 -2
  142. package/src/fixtures/l1_to_l2_messaging.ts +4 -2
  143. package/src/fixtures/setup_p2p_test.ts +79 -32
  144. package/src/fixtures/snapshot_manager.ts +120 -131
  145. package/src/fixtures/token_utils.ts +16 -24
  146. package/src/fixtures/utils.ts +175 -269
  147. package/src/fixtures/web3signer.ts +63 -0
  148. package/src/fixtures/with_telemetry_utils.ts +2 -2
  149. package/src/guides/up_quick_start.sh +3 -11
  150. package/src/quality_of_service/alert_checker.ts +1 -1
  151. package/src/shared/cross_chain_test_harness.ts +23 -31
  152. package/src/shared/gas_portal_test_harness.ts +14 -21
  153. package/src/shared/jest_setup.ts +1 -1
  154. package/src/shared/submit-transactions.ts +12 -8
  155. package/src/shared/uniswap_l1_l2.ts +80 -88
  156. package/src/simulators/lending_simulator.ts +9 -6
  157. package/src/simulators/token_simulator.ts +5 -2
  158. package/src/spartan/DEVELOP.md +15 -3
  159. package/src/spartan/setup_test_wallets.ts +171 -127
  160. package/src/spartan/tx_metrics.ts +130 -0
  161. package/src/spartan/utils.ts +543 -45
  162. package/dest/fixtures/setup_l1_contracts.d.ts +0 -6
  163. package/dest/fixtures/setup_l1_contracts.d.ts.map +0 -1
  164. package/dest/fixtures/setup_l1_contracts.js +0 -17
  165. package/src/fixtures/setup_l1_contracts.ts +0 -26
@@ -1,23 +1,24 @@
1
- import { getSchnorrWalletWithSecretKey } from '@aztec/accounts/schnorr';
2
1
  import type { InitialAccountData } from '@aztec/accounts/testing';
3
2
  import type { AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
4
- import { type AccountWalletWithSecretKey, AztecAddress, EthAddress, Fr } from '@aztec/aztec.js';
3
+ import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
4
+ import { Fr } from '@aztec/aztec.js/fields';
5
+ import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
5
6
  import {
6
7
  type EmpireSlashingProposerContract,
7
- type ExtendedViemWalletClient,
8
8
  GSEContract,
9
- MultiAdderArtifact,
10
- type Operator,
11
9
  RollupContract,
12
10
  type TallySlashingProposerContract,
13
- type ViemClient,
14
- createL1TxUtilsFromViemWallet,
15
- deployL1Contract,
16
- getL1ContractsConfigEnvVars,
17
- } from '@aztec/ethereum';
11
+ } from '@aztec/ethereum/contracts';
12
+ import type { Operator } from '@aztec/ethereum/deploy-aztec-l1-contracts';
13
+ import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract';
14
+ import { MultiAdderArtifact } from '@aztec/ethereum/l1-artifacts';
15
+ import { createL1TxUtilsFromViemWallet } from '@aztec/ethereum/l1-tx-utils';
18
16
  import { ChainMonitor } from '@aztec/ethereum/test';
17
+ import type { ExtendedViemWalletClient, ViemClient } from '@aztec/ethereum/types';
18
+ import { EpochNumber } from '@aztec/foundation/branded-types';
19
19
  import { SecretValue } from '@aztec/foundation/config';
20
20
  import { type Logger, createLogger } from '@aztec/foundation/log';
21
+ import { retryUntil } from '@aztec/foundation/retry';
21
22
  import { RollupAbi, SlasherAbi, TestERC20Abi } from '@aztec/l1-artifacts';
22
23
  import { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
23
24
  import type { BootstrapNode } from '@aztec/p2p/bootstrap';
@@ -26,6 +27,7 @@ import { tryStop } from '@aztec/stdlib/interfaces/server';
26
27
  import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
27
28
  import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
28
29
  import { ZkPassportProofParams } from '@aztec/stdlib/zkpassport';
30
+ import type { TestWallet } from '@aztec/test-wallet/server';
29
31
  import { getGenesisValues } from '@aztec/world-state/testing';
30
32
 
31
33
  import getPort from 'get-port';
@@ -43,7 +45,7 @@ import {
43
45
  createSnapshotManager,
44
46
  deployAccounts,
45
47
  } from '../fixtures/snapshot_manager.js';
46
- import { getPrivateKeyFromIndex, getSponsoredFPCAddress } from '../fixtures/utils.js';
48
+ import { type SetupOptions, getPrivateKeyFromIndex, getSponsoredFPCAddress } from '../fixtures/utils.js';
47
49
  import { getEndToEndTestTelemetryClient } from '../fixtures/with_telemetry_utils.js';
48
50
 
49
51
  // Use a fixed bootstrap node private key so that we can re-use the same snapshot and the nodes can find each other
@@ -75,23 +77,22 @@ export class P2PNetworkTest {
75
77
  public prefilledPublicData: PublicDataTreeLeaf[] = [];
76
78
 
77
79
  // The re-execution test needs a wallet and a spam contract
78
- public wallet?: AccountWalletWithSecretKey;
80
+ public wallet?: TestWallet;
79
81
  public defaultAccountAddress?: AztecAddress;
80
82
  public spamContract?: SpamContract;
81
83
 
82
84
  public bootstrapNode?: BootstrapNode;
83
85
 
84
86
  constructor(
85
- testName: string,
87
+ public readonly testName: string,
86
88
  public bootstrapNodeEnr: string,
87
89
  public bootNodePort: number,
88
90
  public numberOfValidators: number,
89
- initialValidatorConfig: AztecNodeConfig,
91
+ initialValidatorConfig: SetupOptions,
90
92
  public numberOfNodes = 0,
91
93
  // If set enable metrics collection
92
94
  private metricsPort?: number,
93
95
  startProverNode?: boolean,
94
- mockZkPassportVerifier?: boolean,
95
96
  ) {
96
97
  this.logger = createLogger(`e2e:e2e_p2p:${testName}`);
97
98
 
@@ -120,7 +121,6 @@ export class P2PNetworkTest {
120
121
  initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs,
121
122
  slasherFlavor: initialValidatorConfig.slasherFlavor ?? 'tally',
122
123
  aztecTargetCommitteeSize: numberOfValidators,
123
- salt: 420,
124
124
  metricsPort: metricsPort,
125
125
  numberOfInitialFundedAccounts: 2,
126
126
  startProverNode,
@@ -139,7 +139,6 @@ export class P2PNetworkTest {
139
139
  aztecTargetCommitteeSize: numberOfValidators,
140
140
  initialValidators: [],
141
141
  zkPassportArgs: {
142
- mockZkPassportVerifier,
143
142
  zkPassportDomain: zkPassportParams.domain,
144
143
  zkPassportScope: zkPassportParams.scope,
145
144
  },
@@ -155,16 +154,14 @@ export class P2PNetworkTest {
155
154
  metricsPort,
156
155
  initialConfig,
157
156
  startProverNode,
158
- mockZkPassportVerifier,
159
157
  }: {
160
158
  testName: string;
161
159
  numberOfNodes: number;
162
160
  numberOfValidators: number;
163
161
  basePort?: number;
164
162
  metricsPort?: number;
165
- initialConfig?: Partial<AztecNodeConfig>;
163
+ initialConfig?: SetupOptions;
166
164
  startProverNode?: boolean;
167
- mockZkPassportVerifier?: boolean;
168
165
  }) {
169
166
  const port = basePort || (await getPort());
170
167
 
@@ -185,7 +182,6 @@ export class P2PNetworkTest {
185
182
  numberOfNodes,
186
183
  metricsPort,
187
184
  startProverNode,
188
- mockZkPassportVerifier,
189
185
  );
190
186
  }
191
187
 
@@ -198,7 +194,7 @@ export class P2PNetworkTest {
198
194
 
199
195
  async addBootstrapNode() {
200
196
  await this.snapshotManager.snapshot('add-bootstrap-node', async ({ aztecNodeConfig }) => {
201
- const telemetry = getEndToEndTestTelemetryClient(this.metricsPort);
197
+ const telemetry = await getEndToEndTestTelemetryClient(this.metricsPort);
202
198
  this.bootstrapNode = await createBootstrapNodeFromPrivateKey(
203
199
  BOOTSTRAP_NODE_PRIVATE_KEY,
204
200
  this.bootNodePort,
@@ -230,88 +226,85 @@ export class P2PNetworkTest {
230
226
 
231
227
  async applyBaseSnapshots() {
232
228
  await this.addBootstrapNode();
233
- await this.snapshotManager.snapshot(
234
- 'add-validators',
235
- async ({ deployL1ContractsValues, dateProvider, cheatCodes }) => {
236
- const rollup = getContract({
237
- address: deployL1ContractsValues.l1ContractAddresses.rollupAddress.toString(),
238
- abi: RollupAbi,
239
- client: deployL1ContractsValues.l1Client,
240
- });
229
+ await this.snapshotManager.snapshot('add-validators', async ({ deployL1ContractsValues, cheatCodes }) => {
230
+ const rollup = getContract({
231
+ address: deployL1ContractsValues.l1ContractAddresses.rollupAddress.toString(),
232
+ abi: RollupAbi,
233
+ client: deployL1ContractsValues.l1Client,
234
+ });
241
235
 
242
- this.logger.info(`Adding ${this.numberOfValidators} validators`);
236
+ this.logger.info(`Adding ${this.numberOfValidators} validators`);
243
237
 
244
- const stakingAsset = getContract({
245
- address: deployL1ContractsValues.l1ContractAddresses.stakingAssetAddress.toString(),
246
- abi: TestERC20Abi,
247
- client: deployL1ContractsValues.l1Client,
248
- });
238
+ const stakingAsset = getContract({
239
+ address: deployL1ContractsValues.l1ContractAddresses.stakingAssetAddress.toString(),
240
+ abi: TestERC20Abi,
241
+ client: deployL1ContractsValues.l1Client,
242
+ });
249
243
 
250
- const { address: multiAdderAddress } = await deployL1Contract(
251
- deployL1ContractsValues.l1Client,
252
- MultiAdderArtifact.contractAbi,
253
- MultiAdderArtifact.contractBytecode,
254
- [rollup.address, deployL1ContractsValues.l1Client.account.address],
255
- );
244
+ const { address: multiAdderAddress } = await deployL1Contract(
245
+ deployL1ContractsValues.l1Client,
246
+ MultiAdderArtifact.contractAbi,
247
+ MultiAdderArtifact.contractBytecode,
248
+ [rollup.address, deployL1ContractsValues.l1Client.account.address],
249
+ );
256
250
 
257
- const multiAdder = getContract({
258
- address: multiAdderAddress.toString(),
259
- abi: MultiAdderArtifact.contractAbi,
260
- client: deployL1ContractsValues.l1Client,
261
- });
251
+ const multiAdder = getContract({
252
+ address: multiAdderAddress.toString(),
253
+ abi: MultiAdderArtifact.contractAbi,
254
+ client: deployL1ContractsValues.l1Client,
255
+ });
262
256
 
263
- const stakeNeeded = l1ContractsConfig.activationThreshold * BigInt(this.numberOfValidators);
264
- await Promise.all(
265
- [await stakingAsset.write.mint([multiAdder.address, stakeNeeded], {} as any)].map(txHash =>
266
- deployL1ContractsValues.l1Client.waitForTransactionReceipt({ hash: txHash }),
267
- ),
268
- );
257
+ const stakeNeeded = (await rollup.read.getActivationThreshold()) * BigInt(this.numberOfValidators);
258
+ await Promise.all(
259
+ [await stakingAsset.write.mint([multiAdder.address, stakeNeeded], {} as any)].map(txHash =>
260
+ deployL1ContractsValues.l1Client.waitForTransactionReceipt({ hash: txHash }),
261
+ ),
262
+ );
269
263
 
270
- const { validators } = this.getValidators();
271
- this.validators = validators;
264
+ const { validators } = this.getValidators();
265
+ this.validators = validators;
272
266
 
273
- const gseAddress = deployL1ContractsValues.l1ContractAddresses.gseAddress!;
274
- if (!gseAddress) {
275
- throw new Error('GSE contract not deployed');
276
- }
267
+ const gseAddress = deployL1ContractsValues.l1ContractAddresses.gseAddress!;
268
+ if (!gseAddress) {
269
+ throw new Error('GSE contract not deployed');
270
+ }
277
271
 
278
- const gseContract = new GSEContract(deployL1ContractsValues.l1Client, gseAddress.toString());
272
+ const gseContract = new GSEContract(deployL1ContractsValues.l1Client, gseAddress.toString());
279
273
 
280
- const makeValidatorTuples = async (validator: Operator) => {
281
- const registrationTuple = await gseContract.makeRegistrationTuple(validator.bn254SecretKey.getValue());
282
- return {
283
- attester: validator.attester.toString() as `0x${string}`,
284
- withdrawer: validator.withdrawer.toString() as `0x${string}`,
285
- ...registrationTuple,
286
- };
274
+ const makeValidatorTuples = async (validator: Operator) => {
275
+ const registrationTuple = await gseContract.makeRegistrationTuple(validator.bn254SecretKey.getValue());
276
+ return {
277
+ attester: validator.attester.toString() as `0x${string}`,
278
+ withdrawer: validator.withdrawer.toString() as `0x${string}`,
279
+ ...registrationTuple,
287
280
  };
288
- const validatorTuples = await Promise.all(validators.map(makeValidatorTuples));
281
+ };
282
+ const validatorTuples = await Promise.all(validators.map(makeValidatorTuples));
289
283
 
290
- await deployL1ContractsValues.l1Client.waitForTransactionReceipt({
291
- hash: await multiAdder.write.addValidators([validatorTuples]),
292
- });
293
-
294
- const timestamp = await cheatCodes.rollup.advanceToEpoch(2n, { updateDateProvider: dateProvider });
284
+ await deployL1ContractsValues.l1Client.waitForTransactionReceipt({
285
+ hash: await multiAdder.write.addValidators([validatorTuples]),
286
+ });
295
287
 
296
- // Send and await a tx to make sure we mine a block for the warp to correctly progress.
297
- await this._sendDummyTx(deployL1ContractsValues.l1Client);
288
+ await cheatCodes.rollup.advanceToEpoch(
289
+ EpochNumber.fromBigInt(
290
+ BigInt(await cheatCodes.rollup.getEpoch()) + (await rollup.read.getLagInEpochsForValidatorSet()) + 1n,
291
+ ),
292
+ );
298
293
 
299
- // Set the system time in the node, only after we have warped the time and waited for a block
300
- // Time is only set in the NEXT block
301
- dateProvider.setTime(Number(timestamp) * 1000);
302
- },
303
- );
294
+ // Send and await a tx to make sure we mine a block for the warp to correctly progress.
295
+ await this._sendDummyTx(deployL1ContractsValues.l1Client);
296
+ });
304
297
  }
305
298
 
306
299
  async setupAccount() {
307
300
  await this.snapshotManager.snapshot(
308
301
  'setup-account',
309
- deployAccounts(1, this.logger, false),
310
- async ({ deployedAccounts }, { pxe }) => {
302
+ deployAccounts(1, this.logger),
303
+ ({ deployedAccounts }, { wallet }) => {
311
304
  this.deployedAccounts = deployedAccounts;
312
- const [account] = deployedAccounts;
313
- this.wallet = await getSchnorrWalletWithSecretKey(pxe, account.secret, account.signingKey, account.salt);
314
- this.defaultAccountAddress = this.wallet.getAddress();
305
+ [{ address: this.defaultAccountAddress }] = deployedAccounts;
306
+ this.wallet = wallet;
307
+ return Promise.resolve();
315
308
  },
316
309
  );
317
310
  }
@@ -329,11 +322,12 @@ export class P2PNetworkTest {
329
322
  .deployed();
330
323
  return { contractAddress: spamContract.address };
331
324
  },
332
- async ({ contractAddress }) => {
325
+ ({ contractAddress }) => {
333
326
  if (!this.wallet) {
334
327
  throw new Error('Call snapshot t.setupAccount before deploying account contract');
335
328
  }
336
- this.spamContract = await SpamContract.at(contractAddress, this.wallet);
329
+ this.spamContract = SpamContract.at(contractAddress, this.wallet);
330
+ return Promise.resolve();
337
331
  },
338
332
  );
339
333
  }
@@ -393,6 +387,48 @@ export class P2PNetworkTest {
393
387
  this.logger.info('Nodes stopped');
394
388
  }
395
389
 
390
+ /**
391
+ * Wait for P2P mesh to be fully formed across all nodes.
392
+ * This ensures that all nodes are connected to each other before proceeding,
393
+ * preventing race conditions where validators propose blocks before the network is ready.
394
+ *
395
+ * @param nodes - Array of nodes to check for P2P connectivity
396
+ * @param expectedNodeCount - Expected number of nodes in the network (defaults to nodes.length)
397
+ * @param timeoutSeconds - Maximum time to wait for connections (default: 30 seconds)
398
+ * @param checkIntervalSeconds - How often to check connectivity (default: 0.1 seconds)
399
+ */
400
+ async waitForP2PMeshConnectivity(
401
+ nodes: AztecNodeService[],
402
+ expectedNodeCount?: number,
403
+ timeoutSeconds = 30,
404
+ checkIntervalSeconds = 0.1,
405
+ ) {
406
+ const nodeCount = expectedNodeCount ?? nodes.length;
407
+ const minPeerCount = nodeCount - 1;
408
+
409
+ this.logger.warn(
410
+ `Waiting for all ${nodeCount} nodes to connect to P2P mesh (at least ${minPeerCount} peers each)...`,
411
+ );
412
+
413
+ await Promise.all(
414
+ nodes.map(async (node, index) => {
415
+ const p2p = node.getP2P();
416
+ await retryUntil(
417
+ async () => {
418
+ const peers = await p2p.getPeers();
419
+ // Each node should be connected to at least N-1 other nodes
420
+ return peers.length >= minPeerCount ? true : undefined;
421
+ },
422
+ `Node ${index} to connect to at least ${minPeerCount} peers`,
423
+ timeoutSeconds,
424
+ checkIntervalSeconds,
425
+ );
426
+ }),
427
+ );
428
+
429
+ this.logger.warn('All nodes connected to P2P mesh');
430
+ }
431
+
396
432
  async teardown() {
397
433
  await this.monitor.stop();
398
434
  await tryStop(this.bootstrapNode, this.logger);
@@ -406,7 +442,7 @@ export class P2PNetworkTest {
406
442
  slashFactory: SlashFactoryContract;
407
443
  }> {
408
444
  if (!this.ctx.deployL1ContractsValues) {
409
- throw new Error('DeployL1ContractsValues not set');
445
+ throw new Error('DeployAztecL1ContractsValues not set');
410
446
  }
411
447
 
412
448
  const rollup = new RollupContract(
@@ -415,7 +451,7 @@ export class P2PNetworkTest {
415
451
  );
416
452
 
417
453
  const slasherContract = getContract({
418
- address: getAddress(await rollup.getSlasher()),
454
+ address: getAddress((await rollup.getSlasherAddress()).toString()),
419
455
  abi: SlasherAbi,
420
456
  client: this.ctx.deployL1ContractsValues.l1Client,
421
457
  });
@@ -1,28 +1,29 @@
1
- import { getSchnorrAccount } from '@aztec/accounts/schnorr';
2
1
  import type { InitialAccountData } from '@aztec/accounts/testing';
3
2
  import type { AztecNodeService } from '@aztec/aztec-node';
4
- import {
5
- AztecAddress,
6
- Fr,
7
- type Logger,
8
- ProvenTx,
9
- type SentTx,
10
- TxStatus,
11
- getContractInstanceFromInstantiationParams,
12
- retryUntil,
13
- } from '@aztec/aztec.js';
3
+ import { AztecAddress } from '@aztec/aztec.js/addresses';
4
+ import { type SentTx, getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts';
5
+ import { Fr } from '@aztec/aztec.js/fields';
6
+ import type { Logger } from '@aztec/aztec.js/log';
7
+ import { Tx, TxStatus } from '@aztec/aztec.js/tx';
14
8
  import type { RollupCheatCodes } from '@aztec/aztec/testing';
15
- import type { EmpireSlashingProposerContract, RollupContract, TallySlashingProposerContract } from '@aztec/ethereum';
9
+ import type {
10
+ EmpireSlashingProposerContract,
11
+ RollupContract,
12
+ TallySlashingProposerContract,
13
+ } from '@aztec/ethereum/contracts';
14
+ import { EpochNumber } from '@aztec/foundation/branded-types';
16
15
  import { timesAsync, unique } from '@aztec/foundation/collection';
17
- import type { TestDateProvider } from '@aztec/foundation/timer';
16
+ import { EthAddress } from '@aztec/foundation/eth-address';
17
+ import { retryUntil } from '@aztec/foundation/retry';
18
+ import { pluralize } from '@aztec/foundation/string';
18
19
  import type { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
19
20
  import { TestContract, TestContractArtifact } from '@aztec/noir-test-contracts.js/Test';
20
- import { PXEService, createPXEService, getPXEServiceConfig as getRpcConfig } from '@aztec/pxe/server';
21
+ import { getPXEConfig, getPXEConfig as getRpcConfig } from '@aztec/pxe/server';
21
22
  import { getRoundForOffense } from '@aztec/slasher';
22
23
  import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
23
24
  import type { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
25
+ import { TestWallet, proveInteraction } from '@aztec/test-wallet/server';
24
26
 
25
- import type { NodeContext } from '../fixtures/setup_p2p_test.js';
26
27
  import { submitTxsTo } from '../shared/submit-transactions.js';
27
28
 
28
29
  // submits a set of transactions to the provided Private eXecution Environment (PXE)
@@ -55,56 +56,46 @@ export const submitComplexTxsTo = async (
55
56
  return txs;
56
57
  };
57
58
 
58
- // creates an instance of the PXE and submit a given number of transactions to it.
59
- export const createPXEServiceAndSubmitTransactions = async (
59
+ // creates a wallet and submit a given number of transactions through it.
60
+ export const submitTransactions = async (
60
61
  logger: Logger,
61
62
  node: AztecNodeService,
62
63
  numTxs: number,
63
64
  fundedAccount: InitialAccountData,
64
- ): Promise<NodeContext> => {
65
+ ): Promise<SentTx[]> => {
65
66
  const rpcConfig = getRpcConfig();
66
67
  rpcConfig.proverEnabled = false;
67
- const pxeService = await createPXEService(node, rpcConfig, { useLogSuffix: true });
68
-
69
- const account = await getSchnorrAccount(
70
- pxeService,
71
- fundedAccount.secret,
72
- fundedAccount.signingKey,
73
- fundedAccount.salt,
74
- );
75
- await account.register();
76
- const wallet = await account.getWallet();
77
-
78
- const txs = await submitTxsTo(pxeService, numTxs, wallet, logger);
79
- return { txs, pxeService, node };
68
+ const wallet = await TestWallet.create(node, { ...getPXEConfig(), proverEnabled: false }, { useLogSuffix: true });
69
+ const fundedAccountManager = await wallet.createSchnorrAccount(fundedAccount.secret, fundedAccount.salt);
70
+ return submitTxsTo(wallet, fundedAccountManager.address, numTxs, logger);
80
71
  };
81
72
 
82
- export async function createPXEServiceAndPrepareTransactions(
73
+ export async function prepareTransactions(
83
74
  logger: Logger,
84
75
  node: AztecNodeService,
85
76
  numTxs: number,
86
77
  fundedAccount: InitialAccountData,
87
- ): Promise<{ pxeService: PXEService; txs: ProvenTx[]; node: AztecNodeService }> {
78
+ ): Promise<Tx[]> {
88
79
  const rpcConfig = getRpcConfig();
89
80
  rpcConfig.proverEnabled = false;
90
- const pxe = await createPXEService(node, rpcConfig, { useLogSuffix: true });
91
81
 
92
- const account = await getSchnorrAccount(pxe, fundedAccount.secret, fundedAccount.signingKey, fundedAccount.salt);
93
- await account.register();
94
- const wallet = await account.getWallet();
82
+ const wallet = await TestWallet.create(node, { ...getPXEConfig(), proverEnabled: false }, { useLogSuffix: true });
83
+ const fundedAccountManager = await wallet.createSchnorrAccount(fundedAccount.secret, fundedAccount.salt);
95
84
 
96
- const testContractInstance = await getContractInstanceFromInstantiationParams(TestContractArtifact, {});
97
- await wallet.registerContract({ instance: testContractInstance, artifact: TestContractArtifact });
98
- const contract = await TestContract.at(testContractInstance.address, wallet);
85
+ const testContractInstance = await getContractInstanceFromInstantiationParams(TestContractArtifact, {
86
+ salt: Fr.random(),
87
+ });
88
+ await wallet.registerContract(testContractInstance, TestContractArtifact);
89
+ const contract = TestContract.at(testContractInstance.address, wallet);
99
90
 
100
- const txs = await timesAsync(numTxs, async () => {
101
- const tx = await contract.methods.emit_nullifier(Fr.random()).prove({ from: account.getAddress() });
91
+ return timesAsync(numTxs, async () => {
92
+ const tx = await proveInteraction(wallet, contract.methods.emit_nullifier(Fr.random()), {
93
+ from: fundedAccountManager.address,
94
+ });
102
95
  const txHash = tx.getTxHash();
103
96
  logger.info(`Tx prepared with hash ${txHash}`);
104
97
  return tx;
105
98
  });
106
-
107
- return { txs, pxeService: pxe, node };
108
99
  }
109
100
 
110
101
  export function awaitProposalExecution(
@@ -147,7 +138,7 @@ export async function awaitCommitteeExists({
147
138
  logger: Logger;
148
139
  }): Promise<readonly `0x${string}`[]> {
149
140
  logger.info(`Waiting for committee to be set`);
150
- let committee: readonly `0x${string}`[] | undefined;
141
+ let committee: EthAddress[] | undefined;
151
142
  await retryUntil(
152
143
  async () => {
153
144
  committee = await rollup.getCurrentEpochCommittee();
@@ -156,7 +147,7 @@ export async function awaitCommitteeExists({
156
147
  'non-empty committee',
157
148
  60,
158
149
  );
159
- return committee!;
150
+ return committee!.map(c => c.toString() as `0x${string}`);
160
151
  }
161
152
 
162
153
  export async function awaitOffenseDetected({
@@ -164,26 +155,31 @@ export async function awaitOffenseDetected({
164
155
  nodeAdmin,
165
156
  slashingRoundSize,
166
157
  epochDuration,
158
+ waitUntilOffenseCount,
159
+ timeoutSeconds = 120,
167
160
  }: {
168
161
  nodeAdmin: AztecNodeAdmin;
169
162
  logger: Logger;
170
163
  slashingRoundSize: number;
171
164
  epochDuration: number;
165
+ waitUntilOffenseCount?: number;
166
+ timeoutSeconds?: number;
172
167
  }) {
173
- logger.info(`Waiting for an offense to be detected`);
168
+ const targetOffenseCount = waitUntilOffenseCount ?? 1;
169
+ logger.warn(`Waiting for ${pluralize('offense', targetOffenseCount)} to be detected`);
174
170
  const offenses = await retryUntil(
175
171
  async () => {
176
172
  const offenses = await nodeAdmin.getSlashOffenses('all');
177
- if (offenses.length > 0) {
173
+ if (offenses.length >= targetOffenseCount) {
178
174
  return offenses;
179
175
  }
180
176
  },
181
177
  'non-empty offenses',
182
- 60,
178
+ timeoutSeconds,
183
179
  );
184
180
  logger.info(
185
181
  `Hit ${offenses.length} offenses on rounds ${unique(offenses.map(o => getRoundForOffense(o, { slashingRoundSize, epochDuration })))}`,
186
- offenses,
182
+ { offenses },
187
183
  );
188
184
  return offenses;
189
185
  }
@@ -200,8 +196,9 @@ export async function awaitCommitteeKicked({
200
196
  slashingProposer,
201
197
  slashingRoundSize,
202
198
  aztecSlotDuration,
199
+ aztecEpochDuration,
203
200
  logger,
204
- dateProvider,
201
+ offenseEpoch,
205
202
  }: {
206
203
  rollup: RollupContract;
207
204
  cheatCodes: RollupCheatCodes;
@@ -210,20 +207,22 @@ export async function awaitCommitteeKicked({
210
207
  slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract | undefined;
211
208
  slashingRoundSize: number;
212
209
  aztecSlotDuration: number;
213
- dateProvider: TestDateProvider;
210
+ aztecEpochDuration: number;
214
211
  logger: Logger;
212
+ offenseEpoch: number;
215
213
  }) {
216
214
  if (!slashingProposer) {
217
215
  throw new Error('No slashing proposer configured. Cannot test slashing.');
218
216
  }
219
217
 
220
- logger.info(`Advancing epochs so we start slashing`);
221
218
  await cheatCodes.debugRollup();
222
- await cheatCodes.advanceToNextEpoch({ updateDateProvider: dateProvider });
223
- await cheatCodes.advanceToNextEpoch({ updateDateProvider: dateProvider });
224
219
 
225
- // Await for the slash payload to be created if empire (no payload is created on tally until execution time)
226
220
  if (slashingProposer.type === 'empire') {
221
+ // Await for the slash payload to be created if empire (no payload is created on tally until execution time)
222
+ const targetEpoch = EpochNumber((await cheatCodes.getEpoch()) + (await rollup.getLagInEpochsForValidatorSet()) + 1);
223
+ logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
224
+ await cheatCodes.advanceToEpoch(targetEpoch);
225
+
227
226
  const slashPayloadEvents = await retryUntil(
228
227
  async () => {
229
228
  const events = await slashFactory.getSlashPayloadCreatedEvents();
@@ -238,6 +237,15 @@ export async function awaitCommitteeKicked({
238
237
  expect(unique(slashPayloadEvents[0].slashes.map(slash => slash.validator.toString()))).toHaveLength(
239
238
  committee.length,
240
239
  );
240
+ } else {
241
+ // Use the slash offset to ensure we are in the right epoch for tally
242
+ const slashOffsetInRounds = await slashingProposer.getSlashOffsetInRounds();
243
+ const slashingRoundSizeInEpochs = slashingRoundSize / aztecEpochDuration;
244
+ const slashingOffsetInEpochs = Number(slashOffsetInRounds) * slashingRoundSizeInEpochs;
245
+ const firstEpochInOffenseRound = offenseEpoch - (offenseEpoch % slashingRoundSizeInEpochs);
246
+ const targetEpoch = firstEpochInOffenseRound + slashingOffsetInEpochs;
247
+ logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
248
+ await cheatCodes.advanceToEpoch(EpochNumber(targetEpoch), { offset: -aztecSlotDuration / 2 });
241
249
  }
242
250
 
243
251
  const attestersPre = await rollup.getAttesters();
@@ -248,7 +256,7 @@ export async function awaitCommitteeKicked({
248
256
  expect(attesterInfo.status).toEqual(1); // Validating
249
257
  }
250
258
 
251
- const timeout = slashingRoundSize * 2 * aztecSlotDuration;
259
+ const timeout = slashingRoundSize * 2 * aztecSlotDuration + 30;
252
260
  logger.info(`Waiting for slash to be executed (timeout ${timeout}s)`);
253
261
  await awaitProposalExecution(slashingProposer, timeout, logger);
254
262
 
@@ -265,10 +273,11 @@ export async function awaitCommitteeKicked({
265
273
  expect(attesterInfo.status).toEqual(2); // Living
266
274
  }
267
275
 
268
- logger.info(`Advancing two epochs to check current committee`);
276
+ logger.info(`Advancing to check current committee`);
269
277
  await cheatCodes.debugRollup();
270
- await cheatCodes.advanceToNextEpoch({ updateDateProvider: dateProvider });
271
- await cheatCodes.advanceToNextEpoch({ updateDateProvider: dateProvider });
278
+ await cheatCodes.advanceToEpoch(
279
+ EpochNumber((await cheatCodes.getEpoch()) + (await rollup.getLagInEpochsForValidatorSet()) + 1),
280
+ );
272
281
  await cheatCodes.debugRollup();
273
282
 
274
283
  const committeeNextEpoch = await rollup.getCurrentEpochCommittee();