@aztec/end-to-end 0.0.1-commit.e3c1de76 → 0.0.1-commit.e57c76e

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 (230) 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 +3 -3
  6. package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
  7. package/dest/bench/client_flows/client_flows_benchmark.js +36 -39
  8. package/dest/bench/client_flows/config.d.ts +2 -2
  9. package/dest/bench/client_flows/config.d.ts.map +1 -1
  10. package/dest/bench/client_flows/config.js +18 -0
  11. package/dest/bench/utils.d.ts +1 -1
  12. package/dest/bench/utils.d.ts.map +1 -1
  13. package/dest/bench/utils.js +8 -3
  14. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +8 -5
  15. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
  16. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +36 -17
  17. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +16 -5
  18. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts.map +1 -1
  19. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.js +42 -9
  20. package/dest/e2e_deploy_contract/deploy_test.d.ts +4 -4
  21. package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -1
  22. package/dest/e2e_deploy_contract/deploy_test.js +2 -1
  23. package/dest/e2e_epochs/epochs_test.d.ts +33 -8
  24. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  25. package/dest/e2e_epochs/epochs_test.js +143 -44
  26. package/dest/e2e_fees/fees_test.d.ts +6 -3
  27. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  28. package/dest/e2e_fees/fees_test.js +50 -17
  29. package/dest/e2e_nested_contract/nested_contract_test.d.ts +3 -3
  30. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
  31. package/dest/e2e_nested_contract/nested_contract_test.js +6 -7
  32. package/dest/e2e_p2p/inactivity_slash_test.d.ts +1 -1
  33. package/dest/e2e_p2p/inactivity_slash_test.d.ts.map +1 -1
  34. package/dest/e2e_p2p/inactivity_slash_test.js +4 -3
  35. package/dest/e2e_p2p/p2p_network.d.ts +14 -12
  36. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  37. package/dest/e2e_p2p/p2p_network.js +70 -34
  38. package/dest/e2e_p2p/reqresp/utils.d.ts +3 -3
  39. package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -1
  40. package/dest/e2e_p2p/reqresp/utils.js +67 -14
  41. package/dest/e2e_p2p/shared.d.ts +37 -8
  42. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  43. package/dest/e2e_p2p/shared.js +91 -51
  44. package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.d.ts +2 -0
  45. package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.d.ts.map +1 -0
  46. package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.js +184 -0
  47. package/dest/e2e_storage_proof/fixtures/storage_proof_fixture.d.ts +18 -0
  48. package/dest/e2e_storage_proof/fixtures/storage_proof_fixture.d.ts.map +1 -0
  49. package/dest/e2e_storage_proof/fixtures/storage_proof_fixture.js +120 -0
  50. package/dest/e2e_token_contract/token_contract_test.d.ts +6 -4
  51. package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
  52. package/dest/e2e_token_contract/token_contract_test.js +23 -11
  53. package/dest/fixtures/authwit_proxy.d.ts +15 -0
  54. package/dest/fixtures/authwit_proxy.d.ts.map +1 -0
  55. package/dest/fixtures/authwit_proxy.js +34 -0
  56. package/dest/fixtures/e2e_prover_test.d.ts +9 -8
  57. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  58. package/dest/fixtures/e2e_prover_test.js +39 -50
  59. package/dest/fixtures/elu_monitor.d.ts +21 -0
  60. package/dest/fixtures/elu_monitor.d.ts.map +1 -0
  61. package/dest/fixtures/elu_monitor.js +102 -0
  62. package/dest/fixtures/fixtures.d.ts +74 -1
  63. package/dest/fixtures/fixtures.d.ts.map +1 -1
  64. package/dest/fixtures/fixtures.js +71 -0
  65. package/dest/fixtures/get_bb_config.d.ts +1 -1
  66. package/dest/fixtures/get_bb_config.d.ts.map +1 -1
  67. package/dest/fixtures/get_bb_config.js +5 -5
  68. package/dest/fixtures/ha_setup.d.ts +71 -0
  69. package/dest/fixtures/ha_setup.d.ts.map +1 -0
  70. package/dest/fixtures/ha_setup.js +116 -0
  71. package/dest/fixtures/index.d.ts +2 -1
  72. package/dest/fixtures/index.d.ts.map +1 -1
  73. package/dest/fixtures/index.js +1 -0
  74. package/dest/fixtures/schnorr_hardcoded_account_contract.d.ts +25 -0
  75. package/dest/fixtures/schnorr_hardcoded_account_contract.d.ts.map +1 -0
  76. package/dest/fixtures/schnorr_hardcoded_account_contract.js +37 -0
  77. package/dest/fixtures/setup.d.ts +86 -32
  78. package/dest/fixtures/setup.d.ts.map +1 -1
  79. package/dest/fixtures/setup.js +209 -169
  80. package/dest/fixtures/setup_p2p_test.d.ts +22 -10
  81. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  82. package/dest/fixtures/setup_p2p_test.js +23 -17
  83. package/dest/fixtures/token_utils.d.ts +2 -2
  84. package/dest/fixtures/token_utils.d.ts.map +1 -1
  85. package/dest/fixtures/token_utils.js +5 -7
  86. package/dest/fixtures/utils.d.ts +2 -2
  87. package/dest/fixtures/utils.d.ts.map +1 -1
  88. package/dest/fixtures/utils.js +1 -1
  89. package/dest/forward-compatibility/wallet_rpc_client.d.ts +7 -0
  90. package/dest/forward-compatibility/wallet_rpc_client.d.ts.map +1 -0
  91. package/dest/forward-compatibility/wallet_rpc_client.js +15 -0
  92. package/dest/forward-compatibility/wallet_service.d.ts +3 -0
  93. package/dest/forward-compatibility/wallet_service.d.ts.map +1 -0
  94. package/dest/forward-compatibility/wallet_service.js +109 -0
  95. package/dest/install_legacy_contracts.d.cts +10 -0
  96. package/dest/install_legacy_contracts.d.cts.map +1 -0
  97. package/dest/legacy-jest-resolver.d.cts +3 -0
  98. package/dest/legacy-jest-resolver.d.cts.map +1 -0
  99. package/dest/shared/cross_chain_test_harness.d.ts +4 -2
  100. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
  101. package/dest/shared/cross_chain_test_harness.js +22 -18
  102. package/dest/shared/gas_portal_test_harness.d.ts +8 -5
  103. package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
  104. package/dest/shared/gas_portal_test_harness.js +19 -10
  105. package/dest/shared/index.d.ts +2 -1
  106. package/dest/shared/index.d.ts.map +1 -1
  107. package/dest/shared/index.js +1 -0
  108. package/dest/shared/jest_setup.js +41 -1
  109. package/dest/shared/mock_state_view.d.ts +86 -0
  110. package/dest/shared/mock_state_view.d.ts.map +1 -0
  111. package/dest/shared/mock_state_view.js +186 -0
  112. package/dest/shared/submit-transactions.d.ts +2 -2
  113. package/dest/shared/submit-transactions.d.ts.map +1 -1
  114. package/dest/shared/submit-transactions.js +1 -1
  115. package/dest/shared/uniswap_l1_l2.d.ts +1 -1
  116. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  117. package/dest/shared/uniswap_l1_l2.js +57 -40
  118. package/dest/shared/wait_for_l1_to_l2_message.d.ts +13 -0
  119. package/dest/shared/wait_for_l1_to_l2_message.d.ts.map +1 -0
  120. package/dest/shared/wait_for_l1_to_l2_message.js +10 -0
  121. package/dest/simulators/lending_simulator.d.ts +10 -3
  122. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  123. package/dest/simulators/lending_simulator.js +26 -14
  124. package/dest/simulators/token_simulator.d.ts +1 -1
  125. package/dest/simulators/token_simulator.d.ts.map +1 -1
  126. package/dest/simulators/token_simulator.js +3 -24
  127. package/dest/spartan/setup_test_wallets.d.ts +12 -3
  128. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  129. package/dest/spartan/setup_test_wallets.js +108 -41
  130. package/dest/spartan/tx_metrics.d.ts +18 -4
  131. package/dest/spartan/tx_metrics.d.ts.map +1 -1
  132. package/dest/spartan/tx_metrics.js +74 -21
  133. package/dest/spartan/utils/bot.d.ts +3 -2
  134. package/dest/spartan/utils/bot.d.ts.map +1 -1
  135. package/dest/spartan/utils/bot.js +2 -1
  136. package/dest/spartan/utils/config.d.ts +11 -28
  137. package/dest/spartan/utils/config.d.ts.map +1 -1
  138. package/dest/spartan/utils/config.js +4 -1
  139. package/dest/spartan/utils/index.d.ts +5 -3
  140. package/dest/spartan/utils/index.d.ts.map +1 -1
  141. package/dest/spartan/utils/index.js +5 -1
  142. package/dest/spartan/utils/k8s.d.ts +3 -1
  143. package/dest/spartan/utils/k8s.d.ts.map +1 -1
  144. package/dest/spartan/utils/k8s.js +6 -0
  145. package/dest/spartan/utils/nodes.d.ts +4 -5
  146. package/dest/spartan/utils/nodes.d.ts.map +1 -1
  147. package/dest/spartan/utils/nodes.js +11 -11
  148. package/dest/spartan/utils/pod_logs.d.ts +25 -0
  149. package/dest/spartan/utils/pod_logs.d.ts.map +1 -0
  150. package/dest/spartan/utils/pod_logs.js +74 -0
  151. package/dest/spartan/utils/scripts.d.ts +18 -4
  152. package/dest/spartan/utils/scripts.d.ts.map +1 -1
  153. package/dest/spartan/utils/scripts.js +19 -4
  154. package/dest/test-wallet/test_wallet.d.ts +85 -0
  155. package/dest/test-wallet/test_wallet.d.ts.map +1 -0
  156. package/dest/test-wallet/test_wallet.js +273 -0
  157. package/dest/test-wallet/utils.d.ts +41 -0
  158. package/dest/test-wallet/utils.d.ts.map +1 -0
  159. package/dest/test-wallet/utils.js +66 -0
  160. package/dest/test-wallet/wallet_worker_script.d.ts +2 -0
  161. package/dest/test-wallet/wallet_worker_script.d.ts.map +1 -0
  162. package/dest/test-wallet/wallet_worker_script.js +53 -0
  163. package/dest/test-wallet/worker_wallet.d.ts +53 -0
  164. package/dest/test-wallet/worker_wallet.d.ts.map +1 -0
  165. package/dest/test-wallet/worker_wallet.js +155 -0
  166. package/dest/test-wallet/worker_wallet_schema.d.ts +160 -0
  167. package/dest/test-wallet/worker_wallet_schema.d.ts.map +1 -0
  168. package/dest/test-wallet/worker_wallet_schema.js +22 -0
  169. package/package.json +52 -45
  170. package/src/bench/client_flows/benchmark.ts +19 -0
  171. package/src/bench/client_flows/client_flows_benchmark.ts +64 -49
  172. package/src/bench/client_flows/config.ts +9 -1
  173. package/src/bench/utils.ts +10 -4
  174. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +52 -25
  175. package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +56 -19
  176. package/src/e2e_deploy_contract/deploy_test.ts +6 -5
  177. package/src/e2e_epochs/epochs_test.ts +166 -68
  178. package/src/e2e_fees/bridging_race.notest.ts +1 -1
  179. package/src/e2e_fees/fees_test.ts +57 -32
  180. package/src/e2e_nested_contract/nested_contract_test.ts +10 -6
  181. package/src/e2e_p2p/inactivity_slash_test.ts +8 -7
  182. package/src/e2e_p2p/p2p_network.ts +93 -49
  183. package/src/e2e_p2p/reqresp/utils.ts +84 -17
  184. package/src/e2e_p2p/shared.ts +109 -65
  185. package/src/e2e_storage_proof/fixtures/storage_proof.json +915 -0
  186. package/src/e2e_storage_proof/fixtures/storage_proof_fetcher.ts +190 -0
  187. package/src/e2e_storage_proof/fixtures/storage_proof_fixture.ts +173 -0
  188. package/src/e2e_token_contract/token_contract_test.ts +38 -11
  189. package/src/fixtures/authwit_proxy.ts +54 -0
  190. package/src/fixtures/dumps/epoch_proof_result.json +1 -1
  191. package/src/fixtures/e2e_prover_test.ts +49 -56
  192. package/src/fixtures/elu_monitor.ts +126 -0
  193. package/src/fixtures/fixtures.ts +93 -0
  194. package/src/fixtures/get_bb_config.ts +7 -6
  195. package/src/fixtures/ha_setup.ts +188 -0
  196. package/src/fixtures/index.ts +1 -0
  197. package/src/fixtures/schnorr_hardcoded_account_contract.ts +49 -0
  198. package/src/fixtures/setup.ts +272 -233
  199. package/src/fixtures/setup_p2p_test.ts +37 -32
  200. package/src/fixtures/token_utils.ts +3 -3
  201. package/src/fixtures/utils.ts +2 -0
  202. package/src/forward-compatibility/wallet_rpc_client.ts +14 -0
  203. package/src/forward-compatibility/wallet_service.ts +104 -0
  204. package/src/guides/up_quick_start.sh +3 -5
  205. package/src/install_legacy_contracts.cjs +75 -0
  206. package/src/legacy-jest-resolver.cjs +112 -0
  207. package/src/shared/cross_chain_test_harness.ts +27 -13
  208. package/src/shared/gas_portal_test_harness.ts +21 -11
  209. package/src/shared/index.ts +1 -0
  210. package/src/shared/jest_setup.ts +51 -1
  211. package/src/shared/mock_state_view.ts +188 -0
  212. package/src/shared/submit-transactions.ts +3 -2
  213. package/src/shared/uniswap_l1_l2.ts +103 -54
  214. package/src/shared/wait_for_l1_to_l2_message.ts +23 -0
  215. package/src/simulators/lending_simulator.ts +32 -14
  216. package/src/simulators/token_simulator.ts +6 -30
  217. package/src/spartan/setup_test_wallets.ts +146 -35
  218. package/src/spartan/tx_metrics.ts +82 -24
  219. package/src/spartan/utils/bot.ts +4 -1
  220. package/src/spartan/utils/config.ts +3 -0
  221. package/src/spartan/utils/index.ts +8 -1
  222. package/src/spartan/utils/k8s.ts +8 -0
  223. package/src/spartan/utils/nodes.ts +17 -12
  224. package/src/spartan/utils/pod_logs.ts +99 -0
  225. package/src/spartan/utils/scripts.ts +43 -7
  226. package/src/test-wallet/test_wallet.ts +376 -0
  227. package/src/test-wallet/utils.ts +108 -0
  228. package/src/test-wallet/wallet_worker_script.ts +63 -0
  229. package/src/test-wallet/worker_wallet.ts +218 -0
  230. package/src/test-wallet/worker_wallet_schema.ts +13 -0
@@ -4,7 +4,7 @@ import { waitForProven } from '@aztec/aztec.js/contracts';
4
4
  import { type Logger, createLogger } from '@aztec/aztec.js/log';
5
5
  import type { AztecNode } from '@aztec/aztec.js/node';
6
6
  import type { TxReceipt } from '@aztec/aztec.js/tx';
7
- import { CheatCodes } from '@aztec/aztec/testing';
7
+ import { CheatCodes, EpochTestSettler } from '@aztec/aztec/testing';
8
8
  import { createExtendedL1Client } from '@aztec/ethereum/client';
9
9
  import { InboxContract, OutboxContract, RollupContract } from '@aztec/ethereum/contracts';
10
10
  import type {
@@ -12,30 +12,34 @@ import type {
12
12
  DeployAztecL1ContractsReturnType,
13
13
  } from '@aztec/ethereum/deploy-aztec-l1-contracts';
14
14
  import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract';
15
+ import { pickL1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
15
16
  import type { ExtendedViemWalletClient } from '@aztec/ethereum/types';
16
- import { CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
17
+ import { EpochNumber } from '@aztec/foundation/branded-types';
17
18
  import { sleep } from '@aztec/foundation/sleep';
18
19
  import { TestERC20Abi, TestERC20Bytecode } from '@aztec/l1-artifacts';
19
20
  import { TokenContract } from '@aztec/noir-contracts.js/Token';
20
21
  import { TokenBridgeContract } from '@aztec/noir-contracts.js/TokenBridge';
22
+ import type { PXEConfig } from '@aztec/pxe/server';
21
23
  import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
22
- import type { TestWallet } from '@aztec/test-wallet/server';
23
24
 
24
25
  import { MNEMONIC } from '../fixtures/fixtures.js';
25
26
  import {
26
27
  type EndToEndContext,
27
28
  type SetupOptions,
28
29
  deployAccounts,
30
+ ensureAuthRegistryPublished,
29
31
  publicDeployAccounts,
30
32
  setup,
31
33
  teardown,
32
34
  } from '../fixtures/setup.js';
33
35
  import { CrossChainTestHarness } from '../shared/cross_chain_test_harness.js';
36
+ import type { TestWallet } from '../test-wallet/test_wallet.js';
34
37
 
35
38
  export class CrossChainMessagingTest {
36
39
  private requireEpochProven: boolean;
37
40
  private setupOptions: SetupOptions;
38
41
  private deployL1ContractsArgs: Partial<DeployAztecL1ContractsArgs>;
42
+ private pxeOpts: Partial<PXEConfig>;
39
43
  logger: Logger;
40
44
  context!: EndToEndContext;
41
45
  aztecNode!: AztecNode;
@@ -58,12 +62,23 @@ export class CrossChainMessagingTest {
58
62
  outbox!: OutboxContract;
59
63
  cheatCodes!: CheatCodes;
60
64
 
65
+ /**
66
+ * Background loop that marks each completed epoch as proven on L1. Started in `applyBaseSetup`
67
+ * when the test runs without a real prover node, because the e2e fixture uses L1 interval mining
68
+ * and the AnvilTestWatcher's auto-prove loop only runs under L1 automine. Without this, L1's
69
+ * `aztecProofSubmissionEpochs` window expires mid-test and triggers a chain prune that drops
70
+ * in-flight wallet txs. Tests that intentionally pause proving (e.g. inbox drift tests) can
71
+ * stop it via `await t.epochTestSettler?.stop()`.
72
+ */
73
+ epochTestSettler?: EpochTestSettler;
74
+
61
75
  deployL1ContractsValues!: DeployAztecL1ContractsReturnType;
62
76
 
63
77
  constructor(
64
78
  testName: string,
65
79
  opts: SetupOptions = {},
66
80
  deployL1ContractsArgs: Partial<DeployAztecL1ContractsArgs> = {},
81
+ pxeOpts: Partial<PXEConfig> = {},
67
82
  ) {
68
83
  this.logger = createLogger(`e2e:e2e_cross_chain_messaging:${testName}`);
69
84
  this.setupOptions = opts;
@@ -71,24 +86,31 @@ export class CrossChainMessagingTest {
71
86
  initialValidators: [],
72
87
  ...deployL1ContractsArgs,
73
88
  };
89
+ this.pxeOpts = pxeOpts;
74
90
  this.requireEpochProven = opts.startProverNode ?? false;
75
91
  }
76
92
 
77
- async setup() {
93
+ async setup(opts: Partial<SetupOptions> = {}, pxeOpts: Partial<PXEConfig> = {}) {
78
94
  this.logger.info('Setting up cross chain messaging test');
79
- this.context = await setup(0, {
80
- ...this.setupOptions,
81
- fundSponsoredFPC: true,
82
- skipAccountDeployment: true,
83
- l1ContractsArgs: this.deployL1ContractsArgs,
84
- });
95
+ // Recompute requireEpochProven from the merged options so per-call startProverNode is honored.
96
+ this.requireEpochProven = opts.startProverNode ?? this.setupOptions.startProverNode ?? false;
97
+ this.context = await setup(
98
+ 0,
99
+ {
100
+ ...this.setupOptions,
101
+ ...opts,
102
+ fundSponsoredFPC: true,
103
+ skipAccountDeployment: true,
104
+ l1ContractsArgs: { ...this.deployL1ContractsArgs, ...opts.l1ContractsArgs },
105
+ },
106
+ { ...this.pxeOpts, ...pxeOpts },
107
+ );
85
108
  await this.applyBaseSetup();
86
109
  }
87
110
 
88
111
  async advanceToEpochProven(l2TxReceipt: TxReceipt): Promise<EpochNumber> {
89
- const epoch = await this.rollup.getEpochNumberForCheckpoint(
90
- CheckpointNumber.fromBlockNumber(l2TxReceipt.blockNumber!),
91
- );
112
+ const block = await this.aztecNode.getBlock(l2TxReceipt.blockNumber!);
113
+ const epoch = await this.rollup.getEpochNumberForCheckpoint(block!.checkpointNumber);
92
114
  // Warp to the next epoch.
93
115
  await this.cheatCodes.rollup.advanceToEpoch(EpochNumber(epoch + 1));
94
116
  // Wait for the tx to be proven.
@@ -99,27 +121,41 @@ export class CrossChainMessagingTest {
99
121
 
100
122
  async catchUpProvenChain() {
101
123
  const bn = await this.aztecNode.getBlockNumber();
102
- while ((await this.aztecNode.getProvenBlockNumber()) < bn) {
124
+ while ((await this.aztecNode.getBlockNumber('proven')) < bn) {
103
125
  await sleep(1000);
104
126
  }
105
127
  }
106
128
 
107
129
  async teardown() {
130
+ await this.epochTestSettler?.stop();
108
131
  await teardown(this.context);
109
132
  }
110
133
 
111
134
  async applyBaseSetup() {
112
135
  // Set up base context fields
113
- this.aztecNode = this.context.aztecNodeService!;
136
+ this.aztecNode = this.context.aztecNodeService;
114
137
  this.wallet = this.context.wallet;
115
138
  this.aztecNodeConfig = this.context.config;
116
139
  this.cheatCodes = this.context.cheatCodes;
117
140
  this.deployL1ContractsValues = this.context.deployL1ContractsValues;
118
- this.aztecNodeAdmin = this.context.aztecNodeService!;
141
+ this.aztecNodeAdmin = this.context.aztecNodeService;
119
142
 
120
143
  if (this.requireEpochProven) {
121
144
  // Turn off the watcher to prevent it from keep marking blocks as proven.
122
- this.context.watcher!.setIsMarkingAsProven(false);
145
+ this.context.watcher.setIsMarkingAsProven(false);
146
+ } else {
147
+ // When no real prover is running, the L1 proof window (aztecProofSubmissionEpochs) would
148
+ // otherwise expire mid-test and trigger a chain prune. The AnvilTestWatcher's auto-prove
149
+ // loop is dormant under L1 interval mining (it gates on `isAutoMining`), so start an
150
+ // EpochTestSettler to mark each completed epoch as proven on L1.
151
+ this.epochTestSettler = new EpochTestSettler(
152
+ this.context.ethCheatCodes,
153
+ this.context.deployL1ContractsValues.l1ContractAddresses.rollupAddress,
154
+ this.context.aztecNodeService.getBlockSource(),
155
+ this.logger.createChild('epoch-settler'),
156
+ { pollingIntervalMs: 500 },
157
+ );
158
+ await this.epochTestSettler.start();
123
159
  }
124
160
 
125
161
  // Deploy 3 accounts
@@ -136,6 +172,7 @@ export class CrossChainMessagingTest {
136
172
  // Set up cross chain messaging
137
173
  this.logger.info('Applying e2e_cross_chain_messaging setup');
138
174
 
175
+ await ensureAuthRegistryPublished(this.wallet, this.ownerAddress);
139
176
  // Create the token contract state.
140
177
  this.logger.verbose(`Public deploy accounts...`);
141
178
  await publicDeployAccounts(this.wallet, [this.ownerAddress, this.user1Address, this.user2Address]);
@@ -172,7 +209,7 @@ export class CrossChainMessagingTest {
172
209
  const l1Client = createExtendedL1Client(this.aztecNodeConfig.l1RpcUrls, MNEMONIC);
173
210
  this.l1Client = l1Client;
174
211
 
175
- const l1Contracts = this.aztecNodeConfig.l1Contracts;
212
+ const l1Contracts = pickL1ContractAddresses(this.aztecNodeConfig);
176
213
  this.rollup = new RollupContract(l1Client, l1Contracts.rollupAddress.toString());
177
214
  this.inbox = new InboxContract(l1Client, l1Contracts.inboxAddress.toString());
178
215
  this.outbox = new OutboxContract(l1Client, l1Contracts.outboxAddress.toString());
@@ -186,7 +223,7 @@ export class CrossChainMessagingTest {
186
223
  tokenPortalAddress,
187
224
  crossChainContext.underlying,
188
225
  l1Client,
189
- this.aztecNodeConfig.l1Contracts,
226
+ pickL1ContractAddresses(this.aztecNodeConfig),
190
227
  this.wallet,
191
228
  this.ownerAddress,
192
229
  );
@@ -8,9 +8,9 @@ import type { AztecNode } from '@aztec/aztec.js/node';
8
8
  import type { Wallet } from '@aztec/aztec.js/wallet';
9
9
  import type { StatefulTestContract } from '@aztec/noir-test-contracts.js/StatefulTest';
10
10
  import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
11
- import type { TestWallet } from '@aztec/test-wallet/server';
12
11
 
13
- import { type EndToEndContext, deployAccounts, setup, teardown } from '../fixtures/setup.js';
12
+ import { type EndToEndContext, type SetupOptions, deployAccounts, setup, teardown } from '../fixtures/setup.js';
13
+ import type { TestWallet } from '../test-wallet/test_wallet.js';
14
14
 
15
15
  export class DeployTest {
16
16
  public context!: EndToEndContext;
@@ -24,15 +24,16 @@ export class DeployTest {
24
24
  this.logger = createLogger(`e2e:e2e_deploy_contract:${testName}`);
25
25
  }
26
26
 
27
- async setup() {
27
+ async setup(opts: Partial<SetupOptions> = {}) {
28
28
  this.logger.info('Setting up test environment');
29
29
  this.context = await setup(0, {
30
+ ...opts,
30
31
  fundSponsoredFPC: true,
31
32
  skipAccountDeployment: true,
32
33
  });
33
- this.aztecNode = this.context.aztecNodeService!;
34
+ this.aztecNode = this.context.aztecNodeService;
34
35
  this.wallet = this.context.wallet;
35
- this.aztecNodeAdmin = this.context.aztecNodeService!;
36
+ this.aztecNodeAdmin = this.context.aztecNodeService;
36
37
  await this.applyInitialAccount();
37
38
  return this;
38
39
  }
@@ -1,4 +1,7 @@
1
+ import type { InitialAccountData } from '@aztec/accounts/testing';
2
+ import type { Archiver } from '@aztec/archiver';
1
3
  import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
4
+ import { getAccountContractAddress } from '@aztec/aztec.js/account';
2
5
  import { getTimestampRangeForEpoch } from '@aztec/aztec.js/block';
3
6
  import { getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts';
4
7
  import { Fr } from '@aztec/aztec.js/fields';
@@ -9,7 +12,8 @@ import { EpochCache } from '@aztec/epoch-cache';
9
12
  import { createExtendedL1Client } from '@aztec/ethereum/client';
10
13
  import { DefaultL1ContractsConfig } from '@aztec/ethereum/config';
11
14
  import { RollupContract } from '@aztec/ethereum/contracts';
12
- import { ChainMonitor, DelayedTxUtils, type Delayer, waitUntilL1Timestamp, withDelayer } from '@aztec/ethereum/test';
15
+ import { Delayer, createDelayer, waitUntilL1Timestamp, wrapClientWithDelayer } from '@aztec/ethereum/l1-tx-utils';
16
+ import { ChainMonitor } from '@aztec/ethereum/test';
13
17
  import type { ExtendedViemWalletClient } from '@aztec/ethereum/types';
14
18
  import { BlockNumber, CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
15
19
  import { SecretValue } from '@aztec/foundation/config';
@@ -20,24 +24,22 @@ import { sleep } from '@aztec/foundation/sleep';
20
24
  import { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
21
25
  import { TestContract } from '@aztec/noir-test-contracts.js/Test';
22
26
  import { getMockPubSubP2PServiceFactory } from '@aztec/p2p/test-helpers';
23
- import { ProverNode, type ProverNodeConfig, ProverNodePublisher } from '@aztec/prover-node';
24
- import type { TestProverNode } from '@aztec/prover-node/test';
27
+ import type { ProverNodeConfig } from '@aztec/prover-node';
25
28
  import type { PXEConfig } from '@aztec/pxe/config';
26
- import {
27
- type SequencerClient,
28
- type SequencerEvents,
29
- type SequencerPublisher,
30
- SequencerState,
31
- } from '@aztec/sequencer-client';
32
- import type { TestSequencerClient } from '@aztec/sequencer-client/test';
29
+ import { type SequencerClient, type SequencerEvents, SequencerState } from '@aztec/sequencer-client';
33
30
  import { type BlockParameter, EthAddress } from '@aztec/stdlib/block';
34
31
  import { type L1RollupConstants, getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers';
35
32
  import { tryStop } from '@aztec/stdlib/interfaces/server';
33
+ import type { SlashingProtectionDatabase } from '@aztec/validator-ha-signer/types';
36
34
 
37
35
  import { join } from 'path';
38
36
  import type { Hex } from 'viem';
39
37
  import { privateKeyToAccount } from 'viem/accounts';
40
38
 
39
+ import {
40
+ SCHNORR_HARDCODED_PRIVATE_KEY,
41
+ SchnorrHardcodedKeyAccountContract,
42
+ } from '../fixtures/schnorr_hardcoded_account_contract.js';
41
43
  import {
42
44
  type EndToEndContext,
43
45
  type SetupOptions,
@@ -45,8 +47,9 @@ import {
45
47
  getPrivateKeyFromIndex,
46
48
  setup,
47
49
  } from '../fixtures/utils.js';
50
+ import type { TestWallet } from '../test-wallet/test_wallet.js';
48
51
 
49
- export const WORLD_STATE_BLOCK_HISTORY = 2;
52
+ export const WORLD_STATE_CHECKPOINT_HISTORY = 2;
50
53
  export const WORLD_STATE_BLOCK_CHECK_INTERVAL = 50;
51
54
  export const ARCHIVER_POLL_INTERVAL = 50;
52
55
  export const DEFAULT_L1_BLOCK_TIME = process.env.CI ? 12 : 8;
@@ -55,6 +58,13 @@ export type EpochsTestOpts = Partial<SetupOptions> & {
55
58
  numberOfAccounts?: number;
56
59
  pxeOpts?: Partial<PXEConfig>;
57
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;
58
68
  };
59
69
 
60
70
  export type TrackedSequencerEvent = {
@@ -81,7 +91,7 @@ export class EpochsTestContext {
81
91
  public proverDelayer!: Delayer;
82
92
  public sequencerDelayer!: Delayer;
83
93
 
84
- public proverNodes: ProverNode[] = [];
94
+ public proverNodes: AztecNodeService[] = [];
85
95
  public nodes: AztecNodeService[] = [];
86
96
 
87
97
  public epochDuration!: number;
@@ -125,10 +135,20 @@ export class EpochsTestContext {
125
135
  this.L1_BLOCK_TIME_IN_S = ethereumSlotDuration;
126
136
  this.L2_SLOT_DURATION_IN_S = aztecSlotDuration;
127
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
+
128
148
  // Set up system without any account nor protocol contracts
129
149
  // and with faster block times and shorter epochs.
130
150
  const context = await setup(
131
- opts.numberOfAccounts ?? 0,
151
+ useHardcodedAccount ? 0 : (opts.numberOfAccounts ?? 0),
132
152
  {
133
153
  automineL1Setup: true,
134
154
  checkIntervalMs: 50,
@@ -143,15 +163,13 @@ export class EpochsTestContext {
143
163
  realProofs: false,
144
164
  startProverNode: true,
145
165
  proverTestDelayMs: opts.proverTestDelayMs ?? 0,
146
- // We use numeric incremental prover ids for simplicity, but we can switch to
147
- // using the prover's eth address if the proverId is used for something in the rollup contract
148
- // Use numeric EthAddress for deterministic prover id
149
166
  proverId: EthAddress.fromNumber(1),
150
- worldStateBlockHistory: WORLD_STATE_BLOCK_HISTORY,
167
+ worldStateCheckpointHistory: WORLD_STATE_CHECKPOINT_HISTORY,
151
168
  exitDelaySeconds: DefaultL1ContractsConfig.exitDelaySeconds,
152
- slasherFlavor: 'none',
169
+ slasherEnabled: false,
153
170
  l1PublishingTime,
154
171
  ...opts,
172
+ ...(hardcodedAccountData ? { initialFundedAccounts: [hardcodedAccountData], numberOfAccounts: 0 } : {}),
155
173
  },
156
174
  // Use checkpointed chain tip for PXE by default to avoid issues with blocks being dropped due to pruned anchor blocks.
157
175
  // Can be overridden via opts.pxeOpts.
@@ -159,6 +177,11 @@ export class EpochsTestContext {
159
177
  );
160
178
 
161
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
+ }
162
185
  this.proverNodes = context.proverNode ? [context.proverNode] : [];
163
186
  this.nodes = context.aztecNode ? [context.aztecNode as AztecNodeService] : [];
164
187
  this.logger = context.logger;
@@ -169,17 +192,8 @@ export class EpochsTestContext {
169
192
  // Loop that tracks L1 and L2 block numbers and logs whenever there's a new one.
170
193
  this.monitor = new ChainMonitor(this.rollup, context.dateProvider, this.logger).start();
171
194
 
172
- // This is hideous.
173
- // We ought to have a definite reference to the l1TxUtils that we're using in both places, provided by the test context.
174
- this.proverDelayer = context.proverNode
175
- ? (((context.proverNode as TestProverNode).publisher as ProverNodePublisher).l1TxUtils as DelayedTxUtils).delayer!
176
- : undefined!;
177
- this.sequencerDelayer = context.sequencer
178
- ? (
179
- ((context.sequencer as TestSequencerClient).sequencer.publisher as SequencerPublisher)
180
- .l1TxUtils as DelayedTxUtils
181
- ).delayer!
182
- : undefined!;
195
+ this.proverDelayer = context.proverDelayer!;
196
+ this.sequencerDelayer = context.sequencerDelayer!;
183
197
 
184
198
  if ((context.proverNode && !this.proverDelayer) || (context.sequencer && !this.sequencerDelayer)) {
185
199
  throw new Error(`Could not find prover or sequencer delayer`);
@@ -194,6 +208,8 @@ export class EpochsTestContext {
194
208
  l1GenesisTime: await this.rollup.getL1GenesisTime(),
195
209
  ethereumSlotDuration,
196
210
  proofSubmissionEpochs: Number(await this.rollup.getProofSubmissionEpochs()),
211
+ targetCommitteeSize: await this.rollup.getTargetCommitteeSize(),
212
+ rollupManaLimit: Number(await this.rollup.getManaLimit()),
197
213
  };
198
214
 
199
215
  this.logger.info(
@@ -208,23 +224,64 @@ export class EpochsTestContext {
208
224
  await this.context.teardown();
209
225
  }
210
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
+
211
256
  public async createProverNode(opts: { dontStart?: boolean } & Partial<ProverNodeConfig> = {}) {
212
257
  this.logger.warn('Creating and syncing a simulated prover node...');
213
258
  const proverNodePrivateKey = this.getNextPrivateKey();
214
259
  const proverIndex = this.proverNodes.length + 1;
215
- const proverNode = await withLoggerBindings({ actor: `prover-${proverIndex}` }, () =>
260
+ const { mockGossipSubNetwork } = this.context;
261
+ const { proverNode } = await withLoggerBindings({ actor: `prover-${proverIndex}` }, () =>
216
262
  createAndSyncProverNode(
217
263
  proverNodePrivateKey,
218
- { ...this.context.config },
219
264
  {
220
- dataDirectory: join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')),
265
+ ...this.context.config,
266
+ p2pEnabled: this.context.config.p2pEnabled || mockGossipSubNetwork !== undefined,
221
267
  proverId: EthAddress.fromNumber(proverIndex),
222
268
  dontStart: opts.dontStart,
223
269
  ...opts,
224
270
  },
225
- this.context.aztecNode,
226
- this.context.prefilledPublicData ?? [],
227
- { dateProvider: this.context.dateProvider },
271
+ {
272
+ dataDirectory: join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')),
273
+ },
274
+ {
275
+ dateProvider: this.context.dateProvider,
276
+ p2pClientDeps: {
277
+ p2pServiceFactory: mockGossipSubNetwork ? getMockPubSubP2PServiceFactory(mockGossipSubNetwork) : undefined,
278
+ rpcTxProviders: [this.context.aztecNode],
279
+ },
280
+ },
281
+ {
282
+ genesis: this.context.genesis,
283
+ dontStart: opts.dontStart,
284
+ },
228
285
  ),
229
286
  );
230
287
  this.proverNodes.push(proverNode);
@@ -238,14 +295,20 @@ export class EpochsTestContext {
238
295
 
239
296
  public createValidatorNode(
240
297
  privateKeys: `0x${string}`[],
241
- opts: Partial<AztecNodeConfig> & { txDelayerMaxInclusionTimeIntoSlot?: number; 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
307
  private async createNode(
248
- opts: Partial<AztecNodeConfig> & { txDelayerMaxInclusionTimeIntoSlot?: number; dontStartSequencer?: boolean } = {},
308
+ opts: Partial<AztecNodeConfig> & {
309
+ dontStartSequencer?: boolean;
310
+ slashingProtectionDb?: SlashingProtectionDatabase;
311
+ } = {},
249
312
  ) {
250
313
  const nodeIndex = this.nodes.length + 1;
251
314
  const actorPrefix = opts.disableValidator ? 'node' : 'validator';
@@ -259,6 +322,7 @@ export class EpochsTestContext {
259
322
  ...resolvedConfig,
260
323
  dataDirectory: join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')),
261
324
  validatorPrivateKeys: opts.validatorPrivateKeys ?? new SecretValue([]),
325
+ nodeId: resolvedConfig.nodeId || `${actorPrefix}-${nodeIndex}`,
262
326
  p2pEnabled,
263
327
  p2pIp,
264
328
  },
@@ -267,34 +331,15 @@ export class EpochsTestContext {
267
331
  p2pClientDeps: {
268
332
  p2pServiceFactory: mockGossipSubNetwork ? getMockPubSubP2PServiceFactory(mockGossipSubNetwork) : undefined,
269
333
  },
334
+ slashingProtectionDb: opts.slashingProtectionDb,
270
335
  },
271
336
  {
272
- prefilledPublicData: this.context.prefilledPublicData,
337
+ genesis: this.context.genesis,
273
338
  ...opts,
274
339
  },
275
340
  ),
276
341
  );
277
342
 
278
- // REFACTOR: We're getting too much into the internals of the sequencer here.
279
- // We should have a single method for constructing an aztec node that returns a TestAztecNodeService
280
- // which directly exposes the delayer and sets any test config.
281
- if (opts.txDelayerMaxInclusionTimeIntoSlot !== undefined) {
282
- this.logger.info(
283
- `Setting tx delayer max inclusion time into slot to ${opts.txDelayerMaxInclusionTimeIntoSlot} seconds`,
284
- );
285
- // Here we reach into the sequencer and hook in a tx delayer. The problem is that the sequencer's l1 utils only uses a public client, not a wallet.
286
- // The delayer needs a wallet (a client that can sign), so we have to create one here.
287
- const l1Client = createExtendedL1Client(
288
- resolvedConfig.l1RpcUrls!,
289
- resolvedConfig.publisherPrivateKeys![0]!.getValue(),
290
- );
291
- const sequencer = node.getSequencer() as TestSequencerClient;
292
- const publisher = sequencer.sequencer.publisher;
293
- const delayed = DelayedTxUtils.fromL1TxUtils(publisher.l1TxUtils, this.L1_BLOCK_TIME_IN_S, l1Client);
294
- delayed.delayer!.setMaxInclusionTimeIntoSlot(opts.txDelayerMaxInclusionTimeIntoSlot);
295
- publisher.l1TxUtils = delayed;
296
- }
297
-
298
343
  this.nodes.push(node);
299
344
  return node;
300
345
  }
@@ -346,7 +391,10 @@ export class EpochsTestContext {
346
391
  this.logger.info(`Waiting until last slot of submission window for epoch ${epochNumber} at ${date}`, {
347
392
  oneSlotBefore,
348
393
  });
349
- await waitUntilL1Timestamp(this.l1Client, oneSlotBefore);
394
+ // Use a timeout that accounts for the full proof submission window
395
+ const proofSubmissionWindowDuration =
396
+ this.constants.proofSubmissionEpochs * this.epochDuration * this.L2_SLOT_DURATION_IN_S;
397
+ await waitUntilL1Timestamp(this.l1Client, oneSlotBefore, undefined, proofSubmissionWindowDuration * 2);
350
398
  }
351
399
 
352
400
  /** Waits for the aztec node to sync to the target block number. */
@@ -357,7 +405,7 @@ export class EpochsTestContext {
357
405
  await sleep(waitTime);
358
406
  const [syncState, tips] = await Promise.all([
359
407
  this.context.aztecNode.getWorldStateSyncStatus(),
360
- await this.context.aztecNode.getL2Tips(),
408
+ await this.context.aztecNode.getChainTips(),
361
409
  ]);
362
410
  this.logger.info(`Wait for node synch ${blockNumber} ${type}`, { blockNumber, type, syncState, tips });
363
411
  if (type === 'proven') {
@@ -398,15 +446,13 @@ export class EpochsTestContext {
398
446
 
399
447
  /** Creates an L1 client using a fresh account with funds from anvil, with a tx delayer already set up. */
400
448
  public async createL1Client() {
401
- const { client, delayer } = withDelayer(
402
- createExtendedL1Client(
403
- [...this.l1Client.chain.rpcUrls.default.http],
404
- privateKeyToAccount(this.getNextPrivateKey()),
405
- this.l1Client.chain,
406
- ),
407
- this.context.dateProvider!,
408
- { ethereumSlotDuration: this.L1_BLOCK_TIME_IN_S },
449
+ const rawClient = createExtendedL1Client(
450
+ [...this.l1Client.chain.rpcUrls.default.http],
451
+ privateKeyToAccount(this.getNextPrivateKey()),
452
+ this.l1Client.chain,
409
453
  );
454
+ const delayer = createDelayer(this.context.dateProvider, { ethereumSlotDuration: this.L1_BLOCK_TIME_IN_S }, {});
455
+ const client = wrapClientWithDelayer(rawClient, delayer);
410
456
  expect(await client.getBalance({ address: client.account.address })).toBeGreaterThan(0n);
411
457
  return { client, delayer };
412
458
  }
@@ -423,9 +469,42 @@ export class EpochsTestContext {
423
469
  expect(result).toBe(expectedSuccess);
424
470
  }
425
471
 
472
+ /** Verifies at least one checkpoint has the target number of blocks (for MBPS validation). */
473
+ public async assertMultipleBlocksPerSlot(targetBlockCount: number) {
474
+ const archiver = (this.context.aztecNode as AztecNodeService).getBlockSource() as Archiver;
475
+ const checkpoints = await archiver.getCheckpoints({ from: CheckpointNumber(1), limit: 50 });
476
+
477
+ this.logger.warn(`Retrieved ${checkpoints.length} checkpoints from archiver`, {
478
+ checkpoints: checkpoints.map(pc => pc.checkpoint.getStats()),
479
+ });
480
+
481
+ let expectedBlockNumber = checkpoints[0].checkpoint.blocks[0].number;
482
+ let targetFound = false;
483
+
484
+ for (const checkpoint of checkpoints) {
485
+ const blockCount = checkpoint.checkpoint.blocks.length;
486
+ targetFound = targetFound || blockCount >= targetBlockCount;
487
+
488
+ this.logger.verbose(`Checkpoint ${checkpoint.checkpoint.number} has ${blockCount} blocks`, {
489
+ checkpoint: checkpoint.checkpoint.getStats(),
490
+ });
491
+
492
+ for (let i = 0; i < blockCount; i++) {
493
+ const block = checkpoint.checkpoint.blocks[i];
494
+ expect(block.indexWithinCheckpoint).toBe(i);
495
+ expect(block.checkpointNumber).toBe(checkpoint.checkpoint.number);
496
+ expect(block.number).toBe(expectedBlockNumber);
497
+ expectedBlockNumber++;
498
+ }
499
+ }
500
+
501
+ expect(targetFound).toBe(true);
502
+ }
503
+
426
504
  public watchSequencerEvents(
427
505
  sequencers: SequencerClient[],
428
506
  getMetadata: (i: number) => Record<string, any> = () => ({}),
507
+ additionalFailEventKeys: (keyof SequencerEvents)[] = [],
429
508
  ) {
430
509
  const stateChanges: TrackedSequencerEvent[] = [];
431
510
  const failEvents: TrackedSequencerEvent[] = [];
@@ -436,6 +515,11 @@ export class EpochsTestContext {
436
515
  'block-build-failed',
437
516
  'checkpoint-publish-failed',
438
517
  'proposer-rollup-check-failed',
518
+ 'checkpoint-error',
519
+ 'checkpoint-publish-failed',
520
+ 'header-validation-failed',
521
+ 'pipelined-checkpoint-discarded',
522
+ ...additionalFailEventKeys,
439
523
  ];
440
524
 
441
525
  const makeEvent = (
@@ -465,6 +549,13 @@ export class EpochsTestContext {
465
549
  });
466
550
  failEventsKeys.forEach(eventName => {
467
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
+ }
468
559
  const evt = makeEvent(i, eventName, args);
469
560
  failEvents.push(evt);
470
561
  this.logger.error(`Failed event ${eventName} from sequencer ${sequencerIndex}`, undefined, evt);
@@ -474,4 +565,11 @@ export class EpochsTestContext {
474
565
 
475
566
  return { failEvents, stateChanges };
476
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
+ }
477
575
  }
@@ -4,11 +4,11 @@ import type { Logger } from '@aztec/aztec.js/log';
4
4
  import { Fq } from '@aztec/foundation/curves/bn254';
5
5
  import { sleep } from '@aztec/foundation/sleep';
6
6
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
7
- import type { TestWallet } from '@aztec/test-wallet/server';
8
7
 
9
8
  import { jest } from '@jest/globals';
10
9
  import type { Hex } from 'viem';
11
10
 
11
+ import type { TestWallet } from '../test-wallet/test_wallet.js';
12
12
  import { FeesTest } from './fees_test.js';
13
13
 
14
14
  jest.setTimeout(300_000);