@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
@@ -1,5 +1,7 @@
1
+ import type { InitialAccountData } from '@aztec/accounts/testing';
1
2
  import type { Archiver } from '@aztec/archiver';
2
3
  import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
4
+ import { getAccountContractAddress } from '@aztec/aztec.js/account';
3
5
  import { getTimestampRangeForEpoch } from '@aztec/aztec.js/block';
4
6
  import { getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts';
5
7
  import { Fr } from '@aztec/aztec.js/fields';
@@ -28,11 +30,16 @@ import { type SequencerClient, type SequencerEvents, SequencerState } from '@azt
28
30
  import { type BlockParameter, EthAddress } from '@aztec/stdlib/block';
29
31
  import { type L1RollupConstants, getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers';
30
32
  import { tryStop } from '@aztec/stdlib/interfaces/server';
33
+ import type { SlashingProtectionDatabase } from '@aztec/validator-ha-signer/types';
31
34
 
32
35
  import { join } from 'path';
33
36
  import type { Hex } from 'viem';
34
37
  import { privateKeyToAccount } from 'viem/accounts';
35
38
 
39
+ import {
40
+ SCHNORR_HARDCODED_PRIVATE_KEY,
41
+ SchnorrHardcodedKeyAccountContract,
42
+ } from '../fixtures/schnorr_hardcoded_account_contract.js';
36
43
  import {
37
44
  type EndToEndContext,
38
45
  type SetupOptions,
@@ -40,6 +47,7 @@ import {
40
47
  getPrivateKeyFromIndex,
41
48
  setup,
42
49
  } from '../fixtures/utils.js';
50
+ import type { TestWallet } from '../test-wallet/test_wallet.js';
43
51
 
44
52
  export const WORLD_STATE_CHECKPOINT_HISTORY = 2;
45
53
  export const WORLD_STATE_BLOCK_CHECK_INTERVAL = 50;
@@ -50,6 +58,13 @@ export type EpochsTestOpts = Partial<SetupOptions> & {
50
58
  numberOfAccounts?: number;
51
59
  pxeOpts?: Partial<PXEConfig>;
52
60
  aztecSlotDurationInL1Slots?: number;
61
+ /** Skip creating/registering the hardcoded account during setup (for tests that handle accounts themselves). */
62
+ skipHardcodedAccount?: boolean;
63
+ /**
64
+ * Force the hardcoded-account fast-path even when an initial sequencer is running. Useful for
65
+ * tests with tight per-block gas budgets that can't fit a full account-deploy tx.
66
+ */
67
+ useHardcodedAccount?: boolean;
53
68
  };
54
69
 
55
70
  export type TrackedSequencerEvent = {
@@ -120,10 +135,20 @@ export class EpochsTestContext {
120
135
  this.L1_BLOCK_TIME_IN_S = ethereumSlotDuration;
121
136
  this.L2_SLOT_DURATION_IN_S = aztecSlotDuration;
122
137
 
138
+ // Auto-create a hardcoded account funded via genesis when:
139
+ // - skipInitialSequencer is set (no sequencer to deploy on-chain), or
140
+ // - useHardcodedAccount is explicitly requested (e.g. tight per-block gas budgets that
141
+ // can't fit a full account-deploy tx).
142
+ const useHardcodedAccount = (opts.skipInitialSequencer || opts.useHardcodedAccount) && !opts.skipHardcodedAccount;
143
+ let hardcodedAccountData: InitialAccountData | undefined;
144
+ if (useHardcodedAccount) {
145
+ hardcodedAccountData = await EpochsTestContext.getHardcodedAccountData(Fr.random(), Fr.random());
146
+ }
147
+
123
148
  // Set up system without any account nor protocol contracts
124
149
  // and with faster block times and shorter epochs.
125
150
  const context = await setup(
126
- opts.numberOfAccounts ?? 0,
151
+ useHardcodedAccount ? 0 : (opts.numberOfAccounts ?? 0),
127
152
  {
128
153
  automineL1Setup: true,
129
154
  checkIntervalMs: 50,
@@ -138,15 +163,13 @@ export class EpochsTestContext {
138
163
  realProofs: false,
139
164
  startProverNode: true,
140
165
  proverTestDelayMs: opts.proverTestDelayMs ?? 0,
141
- // We use numeric incremental prover ids for simplicity, but we can switch to
142
- // using the prover's eth address if the proverId is used for something in the rollup contract
143
- // Use numeric EthAddress for deterministic prover id
144
166
  proverId: EthAddress.fromNumber(1),
145
167
  worldStateCheckpointHistory: WORLD_STATE_CHECKPOINT_HISTORY,
146
168
  exitDelaySeconds: DefaultL1ContractsConfig.exitDelaySeconds,
147
- slasherFlavor: 'none',
169
+ slasherEnabled: false,
148
170
  l1PublishingTime,
149
171
  ...opts,
172
+ ...(hardcodedAccountData ? { initialFundedAccounts: [hardcodedAccountData], numberOfAccounts: 0 } : {}),
150
173
  },
151
174
  // Use checkpointed chain tip for PXE by default to avoid issues with blocks being dropped due to pruned anchor blocks.
152
175
  // Can be overridden via opts.pxeOpts.
@@ -154,6 +177,11 @@ export class EpochsTestContext {
154
177
  );
155
178
 
156
179
  this.context = context;
180
+
181
+ // Register the hardcoded account in PXE (local only, no on-chain deployment needed).
182
+ if (hardcodedAccountData) {
183
+ await this.registerHardcodedAccount(hardcodedAccountData);
184
+ }
157
185
  this.proverNodes = context.proverNode ? [context.proverNode] : [];
158
186
  this.nodes = context.aztecNode ? [context.aztecNode as AztecNodeService] : [];
159
187
  this.logger = context.logger;
@@ -196,6 +224,35 @@ export class EpochsTestContext {
196
224
  await this.context.teardown();
197
225
  }
198
226
 
227
+ /**
228
+ * Computes InitialAccountData for a SchnorrHardcodedKeyAccountContract.
229
+ * This contract has a hardcoded signing key and no initializer, so it can be used without
230
+ * on-chain deployment. Pass the returned data in `initialFundedAccounts` so the address
231
+ * gets funded with fee juice in genesis.
232
+ */
233
+ public static async getHardcodedAccountData(secret: Fr, salt: Fr): Promise<InitialAccountData> {
234
+ const contract = new SchnorrHardcodedKeyAccountContract();
235
+ const address = await getAccountContractAddress(contract, secret, salt);
236
+ const signingKey = SCHNORR_HARDCODED_PRIVATE_KEY;
237
+ return { secret, salt, signingKey, address };
238
+ }
239
+
240
+ /**
241
+ * Registers a SchnorrHardcodedKeyAccountContract in PXE. The account must have been funded
242
+ * at genesis (via getHardcodedAccountData). No on-chain deployment or block mining needed.
243
+ */
244
+ public async registerHardcodedAccount(accountData: InitialAccountData) {
245
+ const contract = new SchnorrHardcodedKeyAccountContract();
246
+ const wallet = this.context.wallet;
247
+ const accountManager = await (wallet as TestWallet).createAccount({
248
+ secret: accountData.secret,
249
+ salt: accountData.salt,
250
+ contract,
251
+ });
252
+ this.context.accounts = [accountManager.address];
253
+ return accountManager.address;
254
+ }
255
+
199
256
  public async createProverNode(opts: { dontStart?: boolean } & Partial<ProverNodeConfig> = {}) {
200
257
  this.logger.warn('Creating and syncing a simulated prover node...');
201
258
  const proverNodePrivateKey = this.getNextPrivateKey();
@@ -222,7 +279,7 @@ export class EpochsTestContext {
222
279
  },
223
280
  },
224
281
  {
225
- prefilledPublicData: this.context.prefilledPublicData ?? [],
282
+ genesis: this.context.genesis,
226
283
  dontStart: opts.dontStart,
227
284
  },
228
285
  ),
@@ -238,13 +295,21 @@ export class EpochsTestContext {
238
295
 
239
296
  public createValidatorNode(
240
297
  privateKeys: `0x${string}`[],
241
- opts: Partial<AztecNodeConfig> & { dontStartSequencer?: boolean } = {},
298
+ opts: Partial<AztecNodeConfig> & {
299
+ dontStartSequencer?: boolean;
300
+ slashingProtectionDb?: SlashingProtectionDatabase;
301
+ } = {},
242
302
  ) {
243
303
  this.logger.warn('Creating and syncing a validator node...');
244
304
  return this.createNode({ ...opts, disableValidator: false, validatorPrivateKeys: new SecretValue(privateKeys) });
245
305
  }
246
306
 
247
- private async createNode(opts: Partial<AztecNodeConfig> & { dontStartSequencer?: boolean } = {}) {
307
+ private async createNode(
308
+ opts: Partial<AztecNodeConfig> & {
309
+ dontStartSequencer?: boolean;
310
+ slashingProtectionDb?: SlashingProtectionDatabase;
311
+ } = {},
312
+ ) {
248
313
  const nodeIndex = this.nodes.length + 1;
249
314
  const actorPrefix = opts.disableValidator ? 'node' : 'validator';
250
315
  const { mockGossipSubNetwork } = this.context;
@@ -257,6 +322,7 @@ export class EpochsTestContext {
257
322
  ...resolvedConfig,
258
323
  dataDirectory: join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')),
259
324
  validatorPrivateKeys: opts.validatorPrivateKeys ?? new SecretValue([]),
325
+ nodeId: resolvedConfig.nodeId || `${actorPrefix}-${nodeIndex}`,
260
326
  p2pEnabled,
261
327
  p2pIp,
262
328
  },
@@ -265,9 +331,10 @@ export class EpochsTestContext {
265
331
  p2pClientDeps: {
266
332
  p2pServiceFactory: mockGossipSubNetwork ? getMockPubSubP2PServiceFactory(mockGossipSubNetwork) : undefined,
267
333
  },
334
+ slashingProtectionDb: opts.slashingProtectionDb,
268
335
  },
269
336
  {
270
- prefilledPublicData: this.context.prefilledPublicData,
337
+ genesis: this.context.genesis,
271
338
  ...opts,
272
339
  },
273
340
  ),
@@ -338,7 +405,7 @@ export class EpochsTestContext {
338
405
  await sleep(waitTime);
339
406
  const [syncState, tips] = await Promise.all([
340
407
  this.context.aztecNode.getWorldStateSyncStatus(),
341
- await this.context.aztecNode.getL2Tips(),
408
+ await this.context.aztecNode.getChainTips(),
342
409
  ]);
343
410
  this.logger.info(`Wait for node synch ${blockNumber} ${type}`, { blockNumber, type, syncState, tips });
344
411
  if (type === 'proven') {
@@ -405,7 +472,7 @@ export class EpochsTestContext {
405
472
  /** Verifies at least one checkpoint has the target number of blocks (for MBPS validation). */
406
473
  public async assertMultipleBlocksPerSlot(targetBlockCount: number) {
407
474
  const archiver = (this.context.aztecNode as AztecNodeService).getBlockSource() as Archiver;
408
- const checkpoints = await archiver.getCheckpoints(CheckpointNumber(1), 50);
475
+ const checkpoints = await archiver.getCheckpoints({ from: CheckpointNumber(1), limit: 50 });
409
476
 
410
477
  this.logger.warn(`Retrieved ${checkpoints.length} checkpoints from archiver`, {
411
478
  checkpoints: checkpoints.map(pc => pc.checkpoint.getStats()),
@@ -437,6 +504,7 @@ export class EpochsTestContext {
437
504
  public watchSequencerEvents(
438
505
  sequencers: SequencerClient[],
439
506
  getMetadata: (i: number) => Record<string, any> = () => ({}),
507
+ additionalFailEventKeys: (keyof SequencerEvents)[] = [],
440
508
  ) {
441
509
  const stateChanges: TrackedSequencerEvent[] = [];
442
510
  const failEvents: TrackedSequencerEvent[] = [];
@@ -447,6 +515,11 @@ export class EpochsTestContext {
447
515
  'block-build-failed',
448
516
  'checkpoint-publish-failed',
449
517
  'proposer-rollup-check-failed',
518
+ 'checkpoint-error',
519
+ 'checkpoint-publish-failed',
520
+ 'header-validation-failed',
521
+ 'pipelined-checkpoint-discarded',
522
+ ...additionalFailEventKeys,
450
523
  ];
451
524
 
452
525
  const makeEvent = (
@@ -476,6 +549,13 @@ export class EpochsTestContext {
476
549
  });
477
550
  failEventsKeys.forEach(eventName => {
478
551
  sequencer.getSequencer().on(eventName, (args: Parameters<SequencerEvents[typeof eventName]>[0]) => {
552
+ // Skip benign block-build-failed events where the builder rejected the block because it
553
+ // could not collect enough valid txs. This is the same "not enough txs" case as
554
+ // block-tx-count-check-failed (which is already excluded above), just detected after we
555
+ // started processing txs rather than before.
556
+ if (eventName === 'block-build-failed' && (args as { reason?: string }).reason === 'Insufficient valid txs') {
557
+ return;
558
+ }
479
559
  const evt = makeEvent(i, eventName, args);
480
560
  failEvents.push(evt);
481
561
  this.logger.error(`Failed event ${eventName} from sequencer ${sequencerIndex}`, undefined, evt);
@@ -485,4 +565,11 @@ export class EpochsTestContext {
485
565
 
486
566
  return { failEvents, stateChanges };
487
567
  }
568
+
569
+ public assertNoFailuresFromSequencers(failEvents: TrackedSequencerEvent[]) {
570
+ if (failEvents.length > 0) {
571
+ this.logger.error(`Failed events from sequencers`, failEvents);
572
+ }
573
+ expect(failEvents).toEqual([]);
574
+ }
488
575
  }
@@ -23,11 +23,12 @@ import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
23
23
 
24
24
  import { getContract } from 'viem';
25
25
 
26
- import { MNEMONIC } from '../fixtures/fixtures.js';
26
+ import { MNEMONIC, getPaddedMaxFeesPerGas } from '../fixtures/fixtures.js';
27
27
  import {
28
28
  type EndToEndContext,
29
29
  type SetupOptions,
30
30
  deployAccounts,
31
+ ensureAuthRegistryPublished,
31
32
  publicDeployAccounts,
32
33
  setup,
33
34
  teardown,
@@ -84,6 +85,8 @@ export class FeesTest {
84
85
  public getBananaPublicBalanceFn!: BalancesFn;
85
86
  public getBananaPrivateBalanceFn!: BalancesFn;
86
87
  public getProverFee!: (blockNumber: BlockNumber) => Promise<bigint>;
88
+ public getCommittedProverFee!: (blockNumber: BlockNumber) => Promise<bigint>;
89
+ public getCommittedBurn!: (blockNumber: BlockNumber) => Promise<bigint>;
87
90
 
88
91
  public readonly ALICE_INITIAL_BANANAS = BigInt(1e22);
89
92
  public readonly SUBSCRIPTION_AMOUNT = BigInt(1e19);
@@ -102,13 +105,14 @@ export class FeesTest {
102
105
  this.logger = createLogger(`e2e:e2e_fees:${testName}`);
103
106
  }
104
107
 
105
- async setup() {
108
+ async setup(opts: Partial<SetupOptions> = {}) {
106
109
  this.logger.verbose('Setting up fresh context...');
107
110
  // Token allowlist entries are test-only: FPC-based fee payment with custom tokens won't work on mainnet alpha.
108
111
  const tokenAllowList = await getTokenAllowedSetupFunctions();
109
112
  this.context = await setup(0, {
110
113
  startProverNode: true,
111
114
  ...this.setupOptions,
115
+ ...opts,
112
116
  fundSponsoredFPC: true,
113
117
  skipAccountDeployment: true,
114
118
  l1ContractsArgs: { ...this.setupOptions },
@@ -134,7 +138,7 @@ export class FeesTest {
134
138
 
135
139
  async catchUpProvenChain() {
136
140
  const bn = await this.aztecNode.getBlockNumber();
137
- while ((await this.aztecNode.getProvenBlockNumber()) < bn) {
141
+ while ((await this.aztecNode.getBlockNumber('proven')) < bn) {
138
142
  await sleep(1000);
139
143
  }
140
144
  }
@@ -174,11 +178,17 @@ export class FeesTest {
174
178
 
175
179
  public async applyBaseSetup() {
176
180
  await this.applyInitialAccounts();
181
+ await this.applyEnsureAuthRegistryPublished();
177
182
  await this.applyPublicDeployAccounts();
178
183
  await this.applySetupFeeJuice();
179
184
  await this.applyDeployBananaToken();
180
185
  }
181
186
 
187
+ async applyEnsureAuthRegistryPublished() {
188
+ this.logger.info('Ensuring AuthRegistry published');
189
+ await ensureAuthRegistryPublished(this.wallet, this.aliceAddress);
190
+ }
191
+
182
192
  async applyInitialAccounts() {
183
193
  this.logger.info('Applying initial accounts setup');
184
194
 
@@ -193,7 +203,9 @@ export class FeesTest {
193
203
  this.wallet = this.context.wallet;
194
204
  this.aztecNode = this.context.aztecNodeService;
195
205
  this.aztecNodeAdmin = this.context.aztecNodeService;
196
- this.gasSettings = GasSettings.default({ maxFeesPerGas: (await this.aztecNode.getCurrentMinFees()).mul(2) });
206
+ this.gasSettings = GasSettings.fallback({
207
+ maxFeesPerGas: await getPaddedMaxFeesPerGas(this.aztecNode),
208
+ });
197
209
  this.cheatCodes = this.context.cheatCodes;
198
210
  this.accounts = deployedAccounts.map(a => a.address);
199
211
  this.accounts.forEach((a, i) => this.logger.verbose(`Account ${i} address: ${a}`));
@@ -300,6 +312,27 @@ export class FeesTest {
300
312
  const mana = block!.header.totalManaUsed.toBigInt();
301
313
  return mulDiv(mana * proverCost, 10n ** 12n, price);
302
314
  };
315
+
316
+ /**
317
+ * Reads the prover fee that the rollup actually committed for the block's checkpoint, which is what
318
+ * RewardLib uses to pay prover rewards. Unlike `getProverFee`, this does not re-derive the value
319
+ * from current L1 fees or current eth-per-fee-asset price, so it is robust to pipelined fee-asset-price
320
+ * drift between propose-time and reward-payout-time.
321
+ */
322
+ this.getCommittedProverFee = async (blockNumber: BlockNumber) => {
323
+ const block = await this.aztecNode.getBlock(blockNumber);
324
+ const feeHeader = await this.rollupContract.getFeeHeader(BigInt(block!.checkpointNumber));
325
+ return feeHeader.manaUsed * feeHeader.proverCost;
326
+ };
327
+
328
+ // RewardLib computes sequencerFee = checkpointFee - burn - proverFee where burn = manaUsed * congestionCost.
329
+ // The fixture's typical case keeps congestionCost at zero, but reading it explicitly avoids latent bugs
330
+ // when test load changes excess mana.
331
+ this.getCommittedBurn = async (blockNumber: BlockNumber) => {
332
+ const block = await this.aztecNode.getBlock(blockNumber);
333
+ const feeHeader = await this.rollupContract.getFeeHeader(BigInt(block!.checkpointNumber));
334
+ return feeHeader.manaUsed * feeHeader.congestionCost;
335
+ };
303
336
  }
304
337
 
305
338
  public async applySponsoredFPCSetup() {
@@ -7,6 +7,7 @@ import { ParentContract } from '@aztec/noir-test-contracts.js/Parent';
7
7
 
8
8
  import {
9
9
  type EndToEndContext,
10
+ type SetupOptions,
10
11
  deployAccounts,
11
12
  publicDeployAccounts,
12
13
  setup,
@@ -50,9 +51,10 @@ export class NestedContractTest {
50
51
  await publicDeployAccounts(this.wallet, [this.defaultAccountAddress]);
51
52
  }
52
53
 
53
- async setup() {
54
+ async setup(opts: Partial<SetupOptions> = {}) {
54
55
  this.logger.info('Setting up fresh subsystems');
55
56
  this.context = await setup(0, {
57
+ ...opts,
56
58
  fundSponsoredFPC: true,
57
59
  skipAccountDeployment: true,
58
60
  });
@@ -58,6 +58,8 @@ export class P2PInactivityTest {
58
58
  basePort: BOOT_NODE_UDP_PORT,
59
59
  startProverNode: true,
60
60
  initialConfig: {
61
+ inboxLag: 2,
62
+ anvilSlotsInAnEpoch: 4,
61
63
  proverNodeConfig: { proverNodeEpochProvingDelayMs: AZTEC_SLOT_DURATION * 1000 },
62
64
  aztecTargetCommitteeSize: COMMITTEE_SIZE,
63
65
  aztecSlotDuration: AZTEC_SLOT_DURATION,
@@ -66,7 +68,6 @@ export class P2PInactivityTest {
66
68
  listenAddress: '127.0.0.1',
67
69
  minTxsPerBlock: 0,
68
70
  aztecEpochDuration: EPOCH_DURATION,
69
- validatorReexecute: false,
70
71
  sentinelEnabled: true,
71
72
  slashingQuorum: SLASHING_QUORUM,
72
73
  slashingRoundSizeInEpochs: SLASHING_ROUND_SIZE_IN_EPOCHS,
@@ -108,7 +109,7 @@ export class P2PInactivityTest {
108
109
  this.test.bootstrapNodeEnr,
109
110
  NUM_NODES - this.inactiveNodeCount - Number(this.keepInitialNode),
110
111
  BOOT_NODE_UDP_PORT,
111
- this.test.prefilledPublicData,
112
+ this.test.genesis,
112
113
  this.dataDir,
113
114
  undefined,
114
115
  Number(this.keepInitialNode),
@@ -122,7 +123,7 @@ export class P2PInactivityTest {
122
123
  this.test.bootstrapNodeEnr,
123
124
  this.inactiveNodeCount,
124
125
  BOOT_NODE_UDP_PORT,
125
- this.test.prefilledPublicData,
126
+ this.test.genesis,
126
127
  this.dataDir,
127
128
  undefined,
128
129
  NUM_NODES - this.inactiveNodeCount,
@@ -1,14 +1,10 @@
1
- import type { InitialAccountData } from '@aztec/accounts/testing';
1
+ import { type InitialAccountData, generateSchnorrAccounts } from '@aztec/accounts/testing';
2
2
  import type { AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
3
+ import { getAccountContractAddress } from '@aztec/aztec.js/account';
3
4
  import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
4
5
  import { Fr } from '@aztec/aztec.js/fields';
5
6
  import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
6
- import {
7
- type EmpireSlashingProposerContract,
8
- GSEContract,
9
- RollupContract,
10
- type TallySlashingProposerContract,
11
- } from '@aztec/ethereum/contracts';
7
+ import { GSEContract, RollupContract, type SlashingProposerContract } from '@aztec/ethereum/contracts';
12
8
  import type { Operator } from '@aztec/ethereum/deploy-aztec-l1-contracts';
13
9
  import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract';
14
10
  import { MultiAdderArtifact } from '@aztec/ethereum/l1-artifacts';
@@ -24,9 +20,8 @@ import { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
24
20
  import type { BootstrapNode } from '@aztec/p2p/bootstrap';
25
21
  import { createBootstrapNodeFromPrivateKey, getBootstrapNodeEnr } from '@aztec/p2p/test-helpers';
26
22
  import { tryStop } from '@aztec/stdlib/interfaces/server';
27
- import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
28
23
  import { TopicType } from '@aztec/stdlib/p2p';
29
- import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
24
+ import type { GenesisData } from '@aztec/stdlib/world-state';
30
25
  import { ZkPassportProofParams } from '@aztec/stdlib/zkpassport';
31
26
  import { getGenesisValues } from '@aztec/world-state/testing';
32
27
 
@@ -34,10 +29,13 @@ import getPort from 'get-port';
34
29
  import { type GetContractReturnType, getAddress, getContract } from 'viem';
35
30
  import { privateKeyToAccount } from 'viem/accounts';
36
31
 
32
+ import {
33
+ SCHNORR_HARDCODED_PRIVATE_KEY,
34
+ SchnorrHardcodedKeyAccountContract,
35
+ } from '../fixtures/schnorr_hardcoded_account_contract.js';
37
36
  import {
38
37
  type EndToEndContext,
39
38
  type SetupOptions,
40
- deployAccounts,
41
39
  getPrivateKeyFromIndex,
42
40
  getSponsoredFPCAddress,
43
41
  setup,
@@ -76,8 +74,8 @@ export class P2PNetworkTest {
76
74
  public peerIdPrivateKeys: string[] = [];
77
75
  public validators: Operator[] = [];
78
76
 
79
- public deployedAccounts: InitialAccountData[] = [];
80
- public prefilledPublicData: PublicDataTreeLeaf[] = [];
77
+ public hardcodedAccountData!: InitialAccountData;
78
+ public genesis: GenesisData | undefined;
81
79
 
82
80
  // The re-execution test needs a wallet and a spam contract
83
81
  public wallet?: TestWallet;
@@ -124,12 +122,11 @@ export class P2PNetworkTest {
124
122
  initialValidatorConfig.aztecProofSubmissionEpochs ?? l1ContractsConfig.aztecProofSubmissionEpochs,
125
123
  slashingRoundSizeInEpochs:
126
124
  initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs,
127
- slasherFlavor: initialValidatorConfig.slasherFlavor ?? 'tally',
125
+ slasherEnabled: initialValidatorConfig.slasherEnabled ?? true,
128
126
  aztecTargetCommitteeSize: numberOfValidators,
129
127
  metricsPort: metricsPort,
130
128
  numberOfInitialFundedAccounts: 2,
131
129
  startProverNode,
132
- walletMinFeePadding: 2.0,
133
130
  };
134
131
 
135
132
  this.deployL1ContractsArgs = {
@@ -137,7 +134,7 @@ export class P2PNetworkTest {
137
134
  aztecEpochDuration: initialValidatorConfig.aztecEpochDuration ?? l1ContractsConfig.aztecEpochDuration,
138
135
  slashingRoundSizeInEpochs:
139
136
  initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs,
140
- slasherFlavor: initialValidatorConfig.slasherFlavor ?? 'tally',
137
+ slasherEnabled: initialValidatorConfig.slasherEnabled ?? true,
141
138
 
142
139
  ethereumSlotDuration: initialValidatorConfig.ethereumSlotDuration ?? l1ContractsConfig.ethereumSlotDuration,
143
140
  aztecSlotDuration: initialValidatorConfig.aztecSlotDuration ?? l1ContractsConfig.aztecSlotDuration,
@@ -192,10 +189,10 @@ export class P2PNetworkTest {
192
189
  }
193
190
 
194
191
  get fundedAccount() {
195
- if (!this.deployedAccounts[0]) {
196
- throw new Error('Call setupAccount to create a funded account.');
192
+ if (!this.hardcodedAccountData) {
193
+ throw new Error('Call setup to initialize the hardcoded account.');
197
194
  }
198
- return this.deployedAccounts[0];
195
+ return this.hardcodedAccountData;
199
196
  }
200
197
 
201
198
  async addBootstrapNode() {
@@ -303,17 +300,22 @@ export class P2PNetworkTest {
303
300
  await this._sendDummyTx(this.context.deployL1ContractsValues.l1Client);
304
301
  }
305
302
 
303
+ /** Points the wallet to a P2P-enabled node so transactions can propagate through the network. */
304
+ setupWalletOnNode(node: AztecNodeService) {
305
+ this.logger.info('Pointing wallet to a P2P-enabled node');
306
+ this.context.wallet.updateNode(node);
307
+ }
308
+
309
+ /** Registers the hardcoded account in PXE without on-chain deployment. No sequencer needed. */
306
310
  async setupAccount() {
307
- this.logger.info('Setting up account');
308
- const { deployedAccounts } = await deployAccounts(
309
- 1,
310
- this.logger,
311
- )({
312
- wallet: this.context.wallet,
313
- initialFundedAccounts: this.context.initialFundedAccounts,
311
+ this.logger.info('Registering hardcoded account (no deployment)');
312
+ const contract = new SchnorrHardcodedKeyAccountContract();
313
+ const accountManager = await (this.context.wallet as TestWallet).createAccount({
314
+ secret: this.hardcodedAccountData.secret,
315
+ salt: this.hardcodedAccountData.salt,
316
+ contract,
314
317
  });
315
- this.deployedAccounts = deployedAccounts;
316
- [{ address: this.defaultAccountAddress }] = deployedAccounts;
318
+ this.defaultAccountAddress = accountManager.address;
317
319
  this.wallet = this.context.wallet;
318
320
  }
319
321
 
@@ -354,13 +356,30 @@ export class P2PNetworkTest {
354
356
 
355
357
  async setup() {
356
358
  this.logger.info('Setting up subsystems from fresh');
359
+
360
+ // Pre-compute hardcoded account data so it gets funded in genesis.
361
+ const contract = new SchnorrHardcodedKeyAccountContract();
362
+ const secret = Fr.random();
363
+ const salt = Fr.random();
364
+ this.hardcodedAccountData = {
365
+ secret,
366
+ salt,
367
+ signingKey: SCHNORR_HARDCODED_PRIVATE_KEY,
368
+ address: await getAccountContractAddress(contract, secret, salt),
369
+ };
370
+
371
+ // Generate regular Schnorr accounts for tests that need deployable accounts (e.g. add_rollup).
372
+ const regularAccounts = await generateSchnorrAccounts(this.setupOptions.numberOfInitialFundedAccounts ?? 2);
373
+
357
374
  this.context = await setup(
358
375
  0,
359
376
  {
360
377
  ...this.setupOptions,
361
378
  fundSponsoredFPC: true,
362
379
  skipAccountDeployment: true,
363
- slasherFlavor: this.setupOptions.slasherFlavor ?? this.deployL1ContractsArgs.slasherFlavor ?? 'none',
380
+ skipInitialSequencer: true,
381
+ initialFundedAccounts: [...regularAccounts, this.hardcodedAccountData],
382
+ slasherEnabled: this.setupOptions.slasherEnabled ?? this.deployL1ContractsArgs.slasherEnabled ?? false,
364
383
  aztecTargetCommitteeSize: 0,
365
384
  l1ContractsArgs: this.deployL1ContractsArgs,
366
385
  },
@@ -372,8 +391,13 @@ export class P2PNetworkTest {
372
391
  const sponsoredFPCAddress = await getSponsoredFPCAddress();
373
392
  const initialFundedAccounts = [...this.context.initialFundedAccounts.map(a => a.address), sponsoredFPCAddress];
374
393
 
375
- const { prefilledPublicData } = await getGenesisValues(initialFundedAccounts);
376
- this.prefilledPublicData = prefilledPublicData;
394
+ const { genesis } = await getGenesisValues(
395
+ initialFundedAccounts,
396
+ undefined,
397
+ undefined,
398
+ this.context.genesis!.genesisTimestamp,
399
+ );
400
+ this.genesis = genesis;
377
401
 
378
402
  const rollupContract = RollupContract.getFromL1ContractsValues(this.context.deployL1ContractsValues);
379
403
  this.monitor = new ChainMonitor(rollupContract, this.context.dateProvider).start();
@@ -468,8 +492,7 @@ export class P2PNetworkTest {
468
492
  async getContracts(): Promise<{
469
493
  rollup: RollupContract;
470
494
  slasherContract: GetContractReturnType<typeof SlasherAbi, ViemClient>;
471
- slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract | undefined;
472
- slashFactory: SlashFactoryContract;
495
+ slashingProposer: SlashingProposerContract | undefined;
473
496
  }> {
474
497
  if (!this.ctx.deployL1ContractsValues) {
475
498
  throw new Error('DeployAztecL1ContractsValues not set');
@@ -486,14 +509,9 @@ export class P2PNetworkTest {
486
509
  client: this.ctx.deployL1ContractsValues.l1Client,
487
510
  });
488
511
 
489
- // Get the actual slashing proposer from rollup (which handles both empire and tally)
512
+ // Get the actual slashing proposer from rollup
490
513
  const slashingProposer = await rollup.getSlashingProposer();
491
514
 
492
- const slashFactory = new SlashFactoryContract(
493
- this.ctx.deployL1ContractsValues.l1Client,
494
- getAddress(this.ctx.deployL1ContractsValues.l1ContractAddresses.slashFactoryAddress!.toString()),
495
- );
496
-
497
- return { rollup, slasherContract, slashingProposer, slashFactory };
515
+ return { rollup, slasherContract, slashingProposer };
498
516
  }
499
517
  }