@aztec/end-to-end 5.0.0-rc.2 → 5.0.1

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 (246) hide show
  1. package/README.md +215 -27
  2. package/dest/automine/automine_test_context.d.ts +85 -0
  3. package/dest/automine/automine_test_context.d.ts.map +1 -0
  4. package/dest/automine/automine_test_context.js +98 -0
  5. package/dest/automine/contracts/fixtures/storage_proof_fetcher.d.ts +2 -0
  6. package/dest/automine/contracts/fixtures/storage_proof_fetcher.d.ts.map +1 -0
  7. package/dest/{e2e_storage_proof → automine/contracts}/fixtures/storage_proof_fixture.d.ts +1 -1
  8. package/dest/automine/contracts/fixtures/storage_proof_fixture.d.ts.map +1 -0
  9. package/dest/automine/delivery/interactive_handshake_responder.d.ts +48 -0
  10. package/dest/automine/delivery/interactive_handshake_responder.d.ts.map +1 -0
  11. package/dest/automine/delivery/interactive_handshake_responder.js +76 -0
  12. package/dest/automine/delivery/onchain_delivery_harness.d.ts +19 -0
  13. package/dest/automine/delivery/onchain_delivery_harness.d.ts.map +1 -0
  14. package/dest/automine/delivery/onchain_delivery_harness.js +141 -0
  15. package/dest/automine/token/blacklist_token_contract_test.d.ts +49 -0
  16. package/dest/automine/token/blacklist_token_contract_test.d.ts.map +1 -0
  17. package/dest/{e2e_blacklist_token_contract → automine/token}/blacklist_token_contract_test.js +17 -24
  18. package/dest/automine/token/token_contract_test.d.ts +40 -0
  19. package/dest/automine/token/token_contract_test.d.ts.map +1 -0
  20. package/dest/{e2e_token_contract → automine/token}/token_contract_test.js +22 -28
  21. package/dest/automine/token/token_test_helpers.d.ts +73 -0
  22. package/dest/automine/token/token_test_helpers.d.ts.map +1 -0
  23. package/dest/automine/token/token_test_helpers.js +97 -0
  24. package/dest/bench/client_flows/benchmark.d.ts +1 -1
  25. package/dest/bench/client_flows/benchmark.d.ts.map +1 -1
  26. package/dest/bench/client_flows/benchmark.js +3 -1
  27. package/dest/bench/client_flows/client_flows_benchmark.d.ts +1 -1
  28. package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
  29. package/dest/bench/client_flows/client_flows_benchmark.js +16 -4
  30. package/dest/bench/utils.d.ts +1 -1
  31. package/dest/composed/ha/ha_full_setup.d.ts +77 -0
  32. package/dest/composed/ha/ha_full_setup.d.ts.map +1 -0
  33. package/dest/composed/ha/ha_full_setup.js +383 -0
  34. package/dest/composed/web3signer/multi_validator_keystore_utils.d.ts +12 -0
  35. package/dest/composed/web3signer/multi_validator_keystore_utils.d.ts.map +1 -0
  36. package/dest/fixtures/e2e_prover_test.d.ts +10 -7
  37. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  38. package/dest/fixtures/e2e_prover_test.js +30 -11
  39. package/dest/fixtures/fixtures.d.ts +9 -6
  40. package/dest/fixtures/fixtures.d.ts.map +1 -1
  41. package/dest/fixtures/fixtures.js +11 -7
  42. package/dest/fixtures/ha_setup.d.ts +3 -3
  43. package/dest/fixtures/ha_setup.d.ts.map +1 -1
  44. package/dest/fixtures/ha_setup.js +4 -1
  45. package/dest/fixtures/index.d.ts +2 -1
  46. package/dest/fixtures/index.d.ts.map +1 -1
  47. package/dest/fixtures/index.js +1 -0
  48. package/dest/fixtures/setup.d.ts +34 -9
  49. package/dest/fixtures/setup.d.ts.map +1 -1
  50. package/dest/fixtures/setup.js +165 -160
  51. package/dest/fixtures/standard_contracts_genesis.d.ts +16 -0
  52. package/dest/fixtures/standard_contracts_genesis.d.ts.map +1 -0
  53. package/dest/fixtures/standard_contracts_genesis.js +25 -0
  54. package/dest/fixtures/timing.d.ts +42 -0
  55. package/dest/fixtures/timing.d.ts.map +1 -0
  56. package/dest/fixtures/timing.js +72 -0
  57. package/dest/fixtures/wait_helpers.d.ts +135 -0
  58. package/dest/fixtures/wait_helpers.d.ts.map +1 -0
  59. package/dest/fixtures/wait_helpers.js +154 -0
  60. package/dest/forward-compatibility/wallet_service.js +1 -1
  61. package/dest/multi-node/block-production/setup.d.ts +97 -0
  62. package/dest/multi-node/block-production/setup.d.ts.map +1 -0
  63. package/dest/multi-node/block-production/setup.js +158 -0
  64. package/dest/multi-node/governance/setup.d.ts +67 -0
  65. package/dest/multi-node/governance/setup.d.ts.map +1 -0
  66. package/dest/multi-node/governance/setup.js +126 -0
  67. package/dest/multi-node/multi_node_test_context.d.ts +212 -0
  68. package/dest/multi-node/multi_node_test_context.d.ts.map +1 -0
  69. package/dest/multi-node/multi_node_test_context.js +347 -0
  70. package/dest/multi-node/slashing/inactivity_setup.d.ts +27 -0
  71. package/dest/multi-node/slashing/inactivity_setup.d.ts.map +1 -0
  72. package/dest/multi-node/slashing/inactivity_setup.js +111 -0
  73. package/dest/multi-node/slashing/setup.d.ts +167 -0
  74. package/dest/multi-node/slashing/setup.d.ts.map +1 -0
  75. package/dest/multi-node/slashing/setup.js +275 -0
  76. package/dest/{e2e_p2p → p2p}/p2p_network.d.ts +9 -1
  77. package/dest/p2p/p2p_network.d.ts.map +1 -0
  78. package/dest/{e2e_p2p → p2p}/p2p_network.js +26 -1
  79. package/dest/p2p/reqresp/utils.d.ts +19 -0
  80. package/dest/p2p/reqresp/utils.d.ts.map +1 -0
  81. package/dest/{e2e_p2p → p2p}/reqresp/utils.js +4 -15
  82. package/dest/p2p/shared.d.ts +72 -0
  83. package/dest/p2p/shared.d.ts.map +1 -0
  84. package/dest/p2p/shared.js +212 -0
  85. package/dest/shared/cross_chain_test_harness.d.ts +3 -3
  86. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
  87. package/dest/shared/cross_chain_test_harness.js +24 -16
  88. package/dest/shared/gas_portal_test_harness.d.ts +1 -1
  89. package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
  90. package/dest/shared/gas_portal_test_harness.js +8 -5
  91. package/dest/shared/submit-transactions.d.ts +1 -1
  92. package/dest/shared/submit-transactions.d.ts.map +1 -1
  93. package/dest/shared/submit-transactions.js +12 -5
  94. package/dest/shared/timing_env.d.js +5 -0
  95. package/dest/shared/timing_env.js +158 -47
  96. package/dest/shared/wait_for_l1_to_l2_message.js +1 -1
  97. package/dest/single-node/cross-chain/cross_chain_messaging_test.d.ts +75 -0
  98. package/dest/single-node/cross-chain/cross_chain_messaging_test.d.ts.map +1 -0
  99. package/dest/{e2e_cross_chain_messaging → single-node/cross-chain}/cross_chain_messaging_test.js +74 -26
  100. package/dest/single-node/cross-chain/message_test_helpers.d.ts +38 -0
  101. package/dest/single-node/cross-chain/message_test_helpers.d.ts.map +1 -0
  102. package/dest/single-node/cross-chain/message_test_helpers.js +70 -0
  103. package/dest/{e2e_fees → single-node/fees}/bridging_race.notest.d.ts +1 -1
  104. package/dest/single-node/fees/bridging_race.notest.d.ts.map +1 -0
  105. package/dest/{e2e_fees → single-node/fees}/bridging_race.notest.js +9 -6
  106. package/dest/single-node/fees/fees_test.d.ts +95 -0
  107. package/dest/single-node/fees/fees_test.d.ts.map +1 -0
  108. package/dest/{e2e_fees → single-node/fees}/fees_test.js +121 -45
  109. package/dest/single-node/l1-reorgs/setup.d.ts +42 -0
  110. package/dest/single-node/l1-reorgs/setup.d.ts.map +1 -0
  111. package/dest/single-node/l1-reorgs/setup.js +57 -0
  112. package/dest/single-node/partial-proofs/setup.d.ts +5 -0
  113. package/dest/single-node/partial-proofs/setup.d.ts.map +1 -0
  114. package/dest/single-node/partial-proofs/setup.js +5 -0
  115. package/dest/single-node/proving/setup.d.ts +5 -0
  116. package/dest/single-node/proving/setup.d.ts.map +1 -0
  117. package/dest/single-node/proving/setup.js +5 -0
  118. package/dest/single-node/recovery/setup.d.ts +5 -0
  119. package/dest/single-node/recovery/setup.d.ts.map +1 -0
  120. package/dest/single-node/recovery/setup.js +5 -0
  121. package/dest/single-node/setup.d.ts +49 -0
  122. package/dest/single-node/setup.d.ts.map +1 -0
  123. package/dest/single-node/setup.js +56 -0
  124. package/dest/single-node/single_node_test_context.d.ts +374 -0
  125. package/dest/single-node/single_node_test_context.d.ts.map +1 -0
  126. package/dest/single-node/single_node_test_context.js +847 -0
  127. package/dest/spartan/setup_test_wallets.d.ts +1 -1
  128. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  129. package/dest/spartan/setup_test_wallets.js +13 -7
  130. package/dest/spartan/tx_metrics.d.ts +10 -1
  131. package/dest/spartan/tx_metrics.d.ts.map +1 -1
  132. package/dest/spartan/tx_metrics.js +32 -0
  133. package/dest/test-wallet/test_wallet.d.ts +23 -4
  134. package/dest/test-wallet/test_wallet.d.ts.map +1 -1
  135. package/dest/test-wallet/test_wallet.js +20 -4
  136. package/dest/test-wallet/utils.d.ts +36 -1
  137. package/dest/test-wallet/utils.d.ts.map +1 -1
  138. package/dest/test-wallet/utils.js +64 -4
  139. package/dest/test-wallet/wallet_worker_script.js +5 -2
  140. package/dest/test-wallet/worker_wallet.d.ts +5 -5
  141. package/dest/test-wallet/worker_wallet.d.ts.map +1 -1
  142. package/dest/test-wallet/worker_wallet.js +2 -2
  143. package/dest/test-wallet/worker_wallet_schema.js +2 -1
  144. package/package.json +40 -40
  145. package/src/automine/README.md +60 -0
  146. package/src/automine/automine_test_context.ts +153 -0
  147. package/src/automine/delivery/interactive_handshake_responder.ts +125 -0
  148. package/src/automine/delivery/onchain_delivery_harness.ts +213 -0
  149. package/src/{e2e_blacklist_token_contract → automine/token}/blacklist_token_contract_test.ts +19 -39
  150. package/src/{e2e_token_contract → automine/token}/token_contract_test.ts +24 -43
  151. package/src/automine/token/token_test_helpers.ts +138 -0
  152. package/src/bench/client_flows/benchmark.ts +3 -1
  153. package/src/bench/client_flows/client_flows_benchmark.ts +17 -4
  154. package/src/composed/ha/ha_full_setup.ts +466 -0
  155. package/src/fixtures/e2e_prover_test.ts +36 -20
  156. package/src/fixtures/fixtures.ts +11 -7
  157. package/src/fixtures/ha_setup.ts +7 -3
  158. package/src/fixtures/index.ts +1 -0
  159. package/src/fixtures/setup.ts +204 -162
  160. package/src/fixtures/standard_contracts_genesis.ts +28 -0
  161. package/src/fixtures/timing.ts +97 -0
  162. package/src/fixtures/wait_helpers.ts +333 -0
  163. package/src/forward-compatibility/wallet_service.ts +2 -2
  164. package/src/infra/README.md +12 -0
  165. package/src/multi-node/README.md +96 -0
  166. package/src/multi-node/block-production/setup.ts +272 -0
  167. package/src/multi-node/governance/setup.ts +172 -0
  168. package/src/multi-node/multi_node_test_context.ts +447 -0
  169. package/src/multi-node/slashing/inactivity_setup.ts +139 -0
  170. package/src/multi-node/slashing/setup.ts +433 -0
  171. package/src/p2p/README.md +78 -0
  172. package/src/{e2e_p2p → p2p}/p2p_network.ts +26 -0
  173. package/src/{e2e_p2p → p2p}/reqresp/utils.ts +5 -14
  174. package/src/p2p/shared.ts +329 -0
  175. package/src/shared/cross_chain_test_harness.ts +22 -13
  176. package/src/shared/gas_portal_test_harness.ts +13 -5
  177. package/src/shared/submit-transactions.ts +13 -5
  178. package/src/shared/timing_env.d.mts +39 -0
  179. package/src/shared/timing_env.mjs +152 -48
  180. package/src/shared/wait_for_l1_to_l2_message.ts +1 -1
  181. package/src/single-node/README.md +66 -0
  182. package/src/{e2e_cross_chain_messaging → single-node/cross-chain}/cross_chain_messaging_test.ts +100 -38
  183. package/src/single-node/cross-chain/message_test_helpers.ts +125 -0
  184. package/src/{e2e_fees → single-node/fees}/bridging_race.notest.ts +11 -7
  185. package/src/{e2e_fees → single-node/fees}/fees_test.ts +132 -47
  186. package/src/single-node/l1-reorgs/setup.ts +93 -0
  187. package/src/single-node/partial-proofs/setup.ts +8 -0
  188. package/src/single-node/proving/setup.ts +15 -0
  189. package/src/single-node/recovery/setup.ts +8 -0
  190. package/src/single-node/setup.ts +63 -0
  191. package/src/single-node/single_node_test_context.ts +1058 -0
  192. package/src/spartan/setup_test_wallets.ts +19 -7
  193. package/src/spartan/tx_metrics.ts +26 -0
  194. package/src/test-wallet/test_wallet.ts +28 -6
  195. package/src/test-wallet/utils.ts +102 -5
  196. package/src/test-wallet/wallet_worker_script.ts +6 -3
  197. package/src/test-wallet/worker_wallet.ts +5 -9
  198. package/src/test-wallet/worker_wallet_schema.ts +1 -1
  199. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +0 -56
  200. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +0 -1
  201. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +0 -59
  202. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts.map +0 -1
  203. package/dest/e2e_deploy_contract/deploy_test.d.ts +0 -36
  204. package/dest/e2e_deploy_contract/deploy_test.d.ts.map +0 -1
  205. package/dest/e2e_deploy_contract/deploy_test.js +0 -42
  206. package/dest/e2e_epochs/epochs_test.d.ts +0 -137
  207. package/dest/e2e_epochs/epochs_test.d.ts.map +0 -1
  208. package/dest/e2e_epochs/epochs_test.js +0 -485
  209. package/dest/e2e_fees/bridging_race.notest.d.ts.map +0 -1
  210. package/dest/e2e_fees/fees_test.d.ts +0 -89
  211. package/dest/e2e_fees/fees_test.d.ts.map +0 -1
  212. package/dest/e2e_l1_publisher/write_json.d.ts +0 -11
  213. package/dest/e2e_l1_publisher/write_json.d.ts.map +0 -1
  214. package/dest/e2e_l1_publisher/write_json.js +0 -57
  215. package/dest/e2e_multi_validator/utils.d.ts +0 -12
  216. package/dest/e2e_multi_validator/utils.d.ts.map +0 -1
  217. package/dest/e2e_nested_contract/nested_contract_test.d.ts +0 -22
  218. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +0 -1
  219. package/dest/e2e_nested_contract/nested_contract_test.js +0 -40
  220. package/dest/e2e_p2p/inactivity_slash_test.d.ts +0 -31
  221. package/dest/e2e_p2p/inactivity_slash_test.d.ts.map +0 -1
  222. package/dest/e2e_p2p/inactivity_slash_test.js +0 -138
  223. package/dest/e2e_p2p/p2p_network.d.ts.map +0 -1
  224. package/dest/e2e_p2p/reqresp/utils.d.ts +0 -22
  225. package/dest/e2e_p2p/reqresp/utils.d.ts.map +0 -1
  226. package/dest/e2e_p2p/shared.d.ts +0 -100
  227. package/dest/e2e_p2p/shared.d.ts.map +0 -1
  228. package/dest/e2e_p2p/shared.js +0 -257
  229. package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.d.ts +0 -2
  230. package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.d.ts.map +0 -1
  231. package/dest/e2e_storage_proof/fixtures/storage_proof_fixture.d.ts.map +0 -1
  232. package/dest/e2e_token_contract/token_contract_test.d.ts +0 -44
  233. package/dest/e2e_token_contract/token_contract_test.d.ts.map +0 -1
  234. package/src/e2e_deploy_contract/deploy_test.ts +0 -73
  235. package/src/e2e_epochs/epochs_test.ts +0 -596
  236. package/src/e2e_l1_publisher/write_json.ts +0 -78
  237. package/src/e2e_nested_contract/nested_contract_test.ts +0 -51
  238. package/src/e2e_p2p/inactivity_slash_test.ts +0 -181
  239. package/src/e2e_p2p/shared.ts +0 -391
  240. /package/dest/{e2e_storage_proof → automine/contracts}/fixtures/storage_proof_fetcher.js +0 -0
  241. /package/dest/{e2e_storage_proof → automine/contracts}/fixtures/storage_proof_fixture.js +0 -0
  242. /package/dest/{e2e_multi_validator/utils.js → composed/web3signer/multi_validator_keystore_utils.js} +0 -0
  243. /package/src/{e2e_storage_proof → automine/contracts}/fixtures/storage_proof.json +0 -0
  244. /package/src/{e2e_storage_proof → automine/contracts}/fixtures/storage_proof_fetcher.ts +0 -0
  245. /package/src/{e2e_storage_proof → automine/contracts}/fixtures/storage_proof_fixture.ts +0 -0
  246. /package/src/{e2e_multi_validator/utils.ts → composed/web3signer/multi_validator_keystore_utils.ts} +0 -0
@@ -0,0 +1,466 @@
1
+ /**
2
+ * Shared setup for the docker-compose HA full suite.
3
+ *
4
+ * Stands up the complete HA cluster used by `e2e_ha_full.parallel.test.ts` and
5
+ * `e2e_ha_distribute_work.test.ts`: a bootstrap RPC/P2P node plus NODE_COUNT in-proc
6
+ * `AztecNodeService` HA peers that share one PostgreSQL slashing-protection DB and a Web3Signer keystore.
7
+ * Requires the docker-compose HA suite (run_test.sh ha): live Postgres (DATABASE_URL) and Web3Signer
8
+ * sidecar.
9
+ *
10
+ * The suite is split across two files because the "distribute work" test kills nodes as it runs, leaving
11
+ * the cluster unusable; giving it its own file (its own cluster) removes the previous "must run last"
12
+ * ordering contract without changing what any test asserts.
13
+ */
14
+ import { type AztecNodeConfig, AztecNodeService, createAztecNodeService } from '@aztec/aztec-node';
15
+ import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
16
+ import { NO_WAIT, getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts';
17
+ import { Fr } from '@aztec/aztec.js/fields';
18
+ import type { Logger } from '@aztec/aztec.js/log';
19
+ import { type AztecNode, waitForTx } from '@aztec/aztec.js/node';
20
+ import { GovernanceProposerContract } from '@aztec/ethereum/contracts';
21
+ import type { DeployAztecL1ContractsReturnType } from '@aztec/ethereum/deploy-aztec-l1-contracts';
22
+ import { SecretValue } from '@aztec/foundation/config';
23
+ import { withLoggerBindings } from '@aztec/foundation/log/server';
24
+ import { retryUntil } from '@aztec/foundation/retry';
25
+ import type { TestDateProvider } from '@aztec/foundation/timer';
26
+ import { TestContract } from '@aztec/noir-test-contracts.js/Test';
27
+ import { TopicType } from '@aztec/stdlib/p2p';
28
+ import { TxHash, type TxReceipt, TxStatus } from '@aztec/stdlib/tx';
29
+ import type { GenesisData } from '@aztec/stdlib/world-state';
30
+
31
+ import getPort, { portNumbers } from 'get-port';
32
+ import { mkdtemp, rm, writeFile } from 'node:fs/promises';
33
+ import { tmpdir } from 'node:os';
34
+ import { join } from 'node:path';
35
+ import { Pool } from 'pg';
36
+
37
+ import { PIPELINING_SETUP_OPTS } from '../../fixtures/fixtures.js';
38
+ import {
39
+ type HADatabaseConfig,
40
+ cleanupHADatabase,
41
+ createHADatabaseConfig,
42
+ createInitialValidatorsFromPrivateKeys,
43
+ getAddressesFromPrivateKeys,
44
+ setupHADatabase,
45
+ } from '../../fixtures/ha_setup.js';
46
+ import { getPrivateKeyFromIndex, setup } from '../../fixtures/utils.js';
47
+ import {
48
+ createWeb3SignerKeystore,
49
+ getWeb3SignerTestKeystoreDir,
50
+ getWeb3SignerUrl,
51
+ refreshWeb3Signer,
52
+ } from '../../fixtures/web3signer.js';
53
+ import type { TestWallet } from '../../test-wallet/test_wallet.js';
54
+ import { proveInteraction } from '../../test-wallet/utils.js';
55
+
56
+ export const NODE_COUNT = 5;
57
+ export const VALIDATOR_COUNT = 4;
58
+ export const COMMITTEE_SIZE = 4;
59
+
60
+ // Allocate p2p listen ports from above the OS ephemeral range (Linux default tops out at 60999) so they
61
+ // never collide with an ephemeral socket the OS may already have handed out -- e.g. the in-process prover
62
+ // node (which listens on p2pPort 0) or any outbound connection. The previous fixed 4040x ports sat inside
63
+ // the ephemeral range, so an ephemeral socket occasionally held a node's port at bind time, surfacing as
64
+ // libp2p ERR_NO_VALID_ADDRESSES and aborting beforeAll. get-port also locks each returned port briefly, so
65
+ // concurrent calls within this process never hand back the same one.
66
+ const getFreeP2PPort = () => getPort({ port: portNumbers(61000, 65535) });
67
+
68
+ export async function registerTestContract(wallet: TestWallet): Promise<TestContract> {
69
+ const instance = await getContractInstanceFromInstantiationParams(TestContract.artifact, {
70
+ constructorArgs: [],
71
+ constructorArtifact: undefined,
72
+ salt: Fr.ZERO,
73
+ publicKeys: undefined,
74
+ deployer: undefined,
75
+ });
76
+ await wallet.registerContract(instance, TestContract.artifact);
77
+ return TestContract.at(instance.address, wallet);
78
+ }
79
+
80
+ export async function submitTriggerTx(
81
+ wallet: TestWallet,
82
+ testContract: TestContract,
83
+ from: AztecAddress,
84
+ ): Promise<TxHash> {
85
+ const tx = await proveInteraction(wallet, testContract.methods.emit_nullifier(Fr.random()), { from });
86
+ return await tx.send({ wait: NO_WAIT });
87
+ }
88
+
89
+ export async function waitForTriggerTx(node: AztecNode, txHash: TxHash): Promise<TxReceipt> {
90
+ const receipt = await waitForTx(node, txHash, { waitForStatus: TxStatus.CHECKPOINTED });
91
+ if (!receipt.blockNumber) {
92
+ throw new Error('Trigger tx was checkpointed without a block number');
93
+ }
94
+ return receipt;
95
+ }
96
+
97
+ /**
98
+ * Owns the full HA cluster lifecycle and the shared helpers the two HA test files drive it with. Each
99
+ * test file constructs one instance and calls {@link setup} in `beforeAll` / {@link teardown} in
100
+ * `afterAll`; state fields are populated by {@link setup} and read directly by the tests.
101
+ */
102
+ export class HaFullTestContext {
103
+ logger!: Logger;
104
+ wallet!: TestWallet;
105
+ ownerAddress!: AztecAddress;
106
+ testContract!: TestContract;
107
+ aztecNode!: AztecNode;
108
+ config!: AztecNodeConfig;
109
+ accounts!: AztecAddress[];
110
+ dateProvider!: TestDateProvider;
111
+ genesis: GenesisData | undefined;
112
+
113
+ haNodePools!: Pool[]; // Database pools for HA nodes (for cleanup)
114
+ haNodeServices!: AztecNodeService[]; // All N HA peer nodes
115
+ haKeystoreDirs!: string[];
116
+ mainPool!: Pool;
117
+ databaseConfig!: HADatabaseConfig;
118
+ attesterPrivateKeys!: `0x${string}`[];
119
+ attesterAddresses!: string[];
120
+ publisherPrivateKeys!: `0x${string}`[];
121
+ publisherAddresses!: string[];
122
+ web3SignerUrl!: string;
123
+ deployL1ContractsValues!: DeployAztecL1ContractsReturnType;
124
+ governanceProposer!: GovernanceProposerContract;
125
+ /** Per-node initial keystore JSON (all 4 attesters, node's own publisher) for restore after reload test */
126
+ initialKeystoreJsons!: string[];
127
+
128
+ private teardownBootstrap: () => Promise<void> = async () => {};
129
+ private haSequencersStarted = false;
130
+ private readonly stoppedHANodeIndexes = new Set<number>();
131
+
132
+ getSignatureContext = () => ({
133
+ chainId: this.config.l1ChainId,
134
+ rollupAddress: this.deployL1ContractsValues.l1ContractAddresses.rollupAddress,
135
+ });
136
+
137
+ startHASequencers = async () => {
138
+ if (this.haSequencersStarted) {
139
+ return;
140
+ }
141
+
142
+ await Promise.all(
143
+ this.haNodeServices.map(async (service, i) => {
144
+ this.logger.info(`Starting HA peer node ${i} sequencer`);
145
+ await service.getSequencer()?.start();
146
+ }),
147
+ );
148
+ this.haSequencersStarted = true;
149
+ this.logger.info('All HA peer sequencers started');
150
+ };
151
+
152
+ sendTriggerTx = async (): Promise<TxReceipt> => {
153
+ await this.startHASequencers();
154
+ const txHash = await submitTriggerTx(this.wallet, this.testContract, this.ownerAddress);
155
+ return await waitForTriggerTx(this.aztecNode, txHash);
156
+ };
157
+
158
+ stopHANode = async (nodeIndex: number) => {
159
+ if (this.stoppedHANodeIndexes.has(nodeIndex)) {
160
+ return;
161
+ }
162
+
163
+ this.logger.info(`Stopping HA peer node ${nodeIndex}`);
164
+ await this.haNodeServices[nodeIndex].stop();
165
+ this.stoppedHANodeIndexes.add(nodeIndex);
166
+ };
167
+
168
+ async setup(): Promise<void> {
169
+ // Check required environment variables
170
+ if (!process.env.DATABASE_URL) {
171
+ throw new Error('DATABASE_URL environment variable must be set for HA tests');
172
+ }
173
+
174
+ this.web3SignerUrl = getWeb3SignerUrl();
175
+ if (!this.web3SignerUrl) {
176
+ throw new Error('WEB3_SIGNER_URL environment variable must be set for HA tests');
177
+ }
178
+
179
+ // Setup database configuration
180
+ this.databaseConfig = createHADatabaseConfig('ha-full-test');
181
+
182
+ // Connect to database (migrations already run by docker-compose entrypoint)
183
+ this.mainPool = setupHADatabase(this.databaseConfig.databaseUrl.getValue()!);
184
+
185
+ this.attesterPrivateKeys = Array.from(
186
+ { length: VALIDATOR_COUNT },
187
+ (_, i) => `0x${getPrivateKeyFromIndex(i)!.toString('hex')}` as `0x${string}`,
188
+ );
189
+
190
+ this.publisherPrivateKeys = Array.from(
191
+ { length: NODE_COUNT },
192
+ (_, i) => `0x${getPrivateKeyFromIndex(i + VALIDATOR_COUNT)!.toString('hex')}` as `0x${string}`,
193
+ );
194
+
195
+ const web3SignerDir = getWeb3SignerTestKeystoreDir();
196
+ const allKeys = [...this.attesterPrivateKeys, ...this.publisherPrivateKeys];
197
+ for (const key of allKeys) {
198
+ await createWeb3SignerKeystore(web3SignerDir, key);
199
+ }
200
+
201
+ this.attesterAddresses = getAddressesFromPrivateKeys(this.attesterPrivateKeys);
202
+
203
+ this.publisherAddresses = getAddressesFromPrivateKeys(this.publisherPrivateKeys);
204
+
205
+ // Refresh Web3Signer to load all the keys (attesters + publishers)
206
+ await refreshWeb3Signer(this.web3SignerUrl, ...this.attesterAddresses, ...this.publisherAddresses);
207
+
208
+ // Create database pools for HA nodes
209
+ this.haNodePools = Array.from({ length: NODE_COUNT }, () => {
210
+ const pool = new Pool({ connectionString: this.databaseConfig.databaseUrl.getValue()! });
211
+ // pg-pool re-emits idle-client errors on the pool; with no listener the emit throws - in production this
212
+ // crashes the validator process.
213
+ pool.on('error', (err: Error) => this.logger?.warn(`HA node pool error: ${err.message}`));
214
+ return pool;
215
+ });
216
+
217
+ const initialValidators = createInitialValidatorsFromPrivateKeys(this.attesterPrivateKeys);
218
+
219
+ const bootstrapP2PPort = await getFreeP2PPort();
220
+
221
+ ({
222
+ teardown: this.teardownBootstrap,
223
+ logger: this.logger,
224
+ wallet: this.wallet,
225
+ aztecNode: this.aztecNode,
226
+ config: this.config,
227
+ accounts: this.accounts,
228
+ dateProvider: this.dateProvider,
229
+ deployL1ContractsValues: this.deployL1ContractsValues,
230
+ genesis: this.genesis,
231
+ } = await setup(
232
+ // A single default initializerless account, created/funded/registered by setup with no on-chain
233
+ // deploy tx -- the bootstrap node can't build blocks (disableValidator), so the owner must be usable
234
+ // without one.
235
+ 1,
236
+ {
237
+ ...PIPELINING_SETUP_OPTS,
238
+ automineL1Setup: true,
239
+ initialValidators,
240
+ sequencerPublisherPrivateKeys: [new SecretValue(this.publisherPrivateKeys[0])],
241
+ aztecTargetCommitteeSize: COMMITTEE_SIZE,
242
+ // The full HA docker/Web3Signer stack can still be joining and syncing after the shared
243
+ // 12s pipelining preset's 2.5s start window has closed. Keep real sequencing, but give
244
+ // HA validators enough time to pass the enforced build-start gate in CI.
245
+ aztecSlotDuration: 16,
246
+ // This suite validates HA coordination on tx-bearing checkpoints. Requiring one tx avoids a startup empty
247
+ // checkpoint from occupying the shared HA publisher while the trigger tx is still being prepared.
248
+ minTxsPerBlock: 1,
249
+ archiverPollingIntervalMS: 200,
250
+ sequencerPollingIntervalMS: 200,
251
+ worldStateBlockCheckIntervalMS: 200,
252
+ blockCheckIntervalMS: 200,
253
+ startProverNode: true,
254
+ // The bootstrap node is only an RPC/P2P anchor. HA validators are the first block producers in this suite.
255
+ disableValidator: true,
256
+ // Enable P2P for transaction gossip
257
+ p2pEnabled: true,
258
+ // Bind the bootstrap node above the ephemeral range too (see getFreeP2PPort), so it can't lose
259
+ // its port to an ephemeral socket and abort the whole suite before any HA node is created. Set
260
+ // the broadcast port explicitly to the same value: discv5 otherwise defaults p2pBroadcastPort to
261
+ // p2pPort by mutating this config object in place, and that mutated value would then leak into the
262
+ // HA nodes' configs below (built by spreading `config`), making them advertise the wrong port.
263
+ p2pPort: bootstrapP2PPort,
264
+ p2pBroadcastPort: bootstrapP2PPort,
265
+ // Enable slashing for testing governance + slashing vote coordination
266
+ slasherEnabled: true,
267
+ slashingRoundSizeInEpochs: 1, // 32 slots (1 epoch)
268
+ slashingQuorum: 17, // >50% of 32 slots for tally quorum,
269
+ },
270
+ { syncChainTip: 'proven' },
271
+ ));
272
+
273
+ this.ownerAddress = this.accounts[0];
274
+ this.testContract = await registerTestContract(this.wallet);
275
+
276
+ if (!this.dateProvider) {
277
+ throw new Error('dateProvider must be provided by setup for HA tests');
278
+ }
279
+
280
+ this.logger.info(
281
+ 'Bootstrap node setup complete; funded initializerless account and test contract registered locally',
282
+ );
283
+
284
+ // Get bootstrap node's P2P ENR for HA nodes to connect to
285
+ const bootstrapNodeEnr = await this.aztecNode.getEncodedEnr();
286
+ if (!bootstrapNodeEnr) {
287
+ throw new Error('Failed to get bootstrap node ENR - P2P may not be enabled');
288
+ }
289
+ this.logger.info(`Bootstrap node ENR: ${bootstrapNodeEnr}`);
290
+
291
+ // L1 contract wrappers for querying votes
292
+ this.governanceProposer = new GovernanceProposerContract(
293
+ this.deployL1ContractsValues.l1Client,
294
+ this.deployL1ContractsValues.l1ContractAddresses.governanceProposerAddress.toString(),
295
+ );
296
+ this.logger.info('L1 contract wrappers initialized');
297
+
298
+ this.haNodeServices = [];
299
+ this.haKeystoreDirs = [];
300
+ this.logger.info(`Starting ${NODE_COUNT} HA peer nodes...`);
301
+
302
+ // Per-node keystore: all attesters but only this node's publisher to avoid nonce conflicts.
303
+ // When keyStoreDirectory is set the node loads validators/publishers from file only, so we omit them from config.
304
+ this.initialKeystoreJsons = [];
305
+
306
+ for (let i = 0; i < NODE_COUNT; i++) {
307
+ const nodeId = `${this.databaseConfig.nodeId}-${i + 1}`;
308
+ this.logger.info(`Starting HA peer node ${i} with nodeId: ${nodeId}`);
309
+
310
+ const keystoreContent = {
311
+ schemaVersion: 1,
312
+ validators: [
313
+ {
314
+ attester: this.attesterAddresses,
315
+ feeRecipient: AztecAddress.ZERO.toString(),
316
+ coinbase: EthAddress.fromString(this.attesterAddresses[0]).toChecksumString(),
317
+ remoteSigner: this.web3SignerUrl,
318
+ publisher: [this.publisherAddresses[i]],
319
+ },
320
+ ],
321
+ };
322
+ const keystoreJson = JSON.stringify(keystoreContent, null, 2);
323
+ this.initialKeystoreJsons.push(keystoreJson);
324
+
325
+ const keystoreDir = await mkdtemp(join(tmpdir(), `ha-keystore-${i}-`));
326
+ this.haKeystoreDirs.push(keystoreDir);
327
+ await writeFile(join(keystoreDir, 'keystore.json'), keystoreJson);
328
+
329
+ const dataDirectory = this.config.dataDirectory ? `${this.config.dataDirectory}-${i}` : undefined;
330
+
331
+ const nodeP2PPort = await getFreeP2PPort();
332
+ const nodeConfig: AztecNodeConfig = {
333
+ ...this.config,
334
+ nodeId,
335
+ keyStoreDirectory: keystoreDir,
336
+ // Ensure txs are included in proposals to test full signing path
337
+ publishTxsWithProposals: true,
338
+ dataDirectory,
339
+ databaseUrl: this.databaseConfig.databaseUrl,
340
+ pollingIntervalMs: this.databaseConfig.pollingIntervalMs,
341
+ peerSigningTimeoutMs: this.databaseConfig.peerSigningTimeoutMs,
342
+ maxStuckDutiesAgeMs: this.databaseConfig.maxStuckDutiesAgeMs,
343
+ haSigningEnabled: true,
344
+ disableValidator: false,
345
+ // Enable P2P for transaction and block gossip
346
+ p2pEnabled: true,
347
+ // Each HA node gets its own free port above the ephemeral range. Override the broadcast port too:
348
+ // `...config` carries the bootstrap node's broadcast port (discv5 sets it in place), which would
349
+ // otherwise make every HA node advertise the bootstrap's port instead of its own.
350
+ p2pPort: nodeP2PPort,
351
+ p2pBroadcastPort: nodeP2PPort,
352
+ // Connect to bootstrap node for tx gossip
353
+ bootstrapNodes: [bootstrapNodeEnr],
354
+ web3SignerUrl: this.web3SignerUrl,
355
+ };
356
+
357
+ const nodeService = await withLoggerBindings({ actor: `HA-${i}` }, async () => {
358
+ return await createAztecNodeService(
359
+ nodeConfig,
360
+ { dateProvider: this.dateProvider },
361
+ { genesis: this.genesis, dontStartSequencer: true },
362
+ );
363
+ });
364
+
365
+ this.haNodeServices.push(nodeService);
366
+ this.logger.info(`HA peer node ${i} started successfully`);
367
+ }
368
+
369
+ this.logger.info(`All ${NODE_COUNT} HA peer nodes started and coordinating via PostgreSQL database`);
370
+ this.logger.info('Waiting for HA peer nodes to join the tx gossip mesh');
371
+ await retryUntil(
372
+ async () => {
373
+ const meshStates = await Promise.all(
374
+ this.haNodeServices.map(async (service, nodeIndex) => {
375
+ const p2p = service.getP2P();
376
+ const [peers, txMeshPeerCount] = await Promise.all([
377
+ p2p.getPeers(),
378
+ p2p.getGossipMeshPeerCount(TopicType.tx),
379
+ ]);
380
+
381
+ return { nodeIndex, peerCount: peers.length, txMeshPeerCount };
382
+ }),
383
+ );
384
+
385
+ this.logger.debug('HA tx gossip mesh status', { meshStates });
386
+ return meshStates.every(({ peerCount, txMeshPeerCount }) => peerCount > 0 && txMeshPeerCount > 0)
387
+ ? true
388
+ : undefined;
389
+ },
390
+ 'HA tx gossip mesh readiness',
391
+ 60,
392
+ 1,
393
+ );
394
+
395
+ // The owner is an initializerless account, so it needs no deployment tx -- it was funded at genesis
396
+ // and registered during setup, and is ready to transact as soon as the HA nodes start building blocks.
397
+ this.logger.info(`Test account ready at ${this.ownerAddress}`);
398
+ }
399
+
400
+ async teardown(): Promise<void> {
401
+ // Stop all sequencers before tearing down the nodes: a sequencer stop awaits its in-flight
402
+ // iteration, which can spend tens of seconds finishing a vote or checkpoint publish on L1.
403
+ // Stops must be awaited fully — jest runs without forceExit, so a node abandoned mid-stop
404
+ // outlives the test environment and keeps the worker process alive until the CI job timeout.
405
+ // The dateProvider reset must wait until nodes are stopped: it rewinds the shared clock from
406
+ // chain time to wall time (minutes apart after the automine deploy burst), and any publisher
407
+ // deadline armed against the rewound clock would block shutdown until wall time catches up.
408
+ if (this.haNodeServices) {
409
+ await Promise.allSettled(
410
+ this.haNodeServices.map(async (service, i) => {
411
+ try {
412
+ await service.getSequencer()?.stop();
413
+ } catch (error) {
414
+ this.logger.error(`Failed to stop sequencer of HA peer node ${i}: ${error}`);
415
+ }
416
+ }),
417
+ );
418
+ await Promise.allSettled(
419
+ this.haNodeServices.map((_, i) =>
420
+ this.stopHANode(i).catch(error => {
421
+ this.logger.error(`Failed to stop HA peer node ${i}: ${error}`);
422
+ }),
423
+ ),
424
+ );
425
+ }
426
+
427
+ this.dateProvider?.reset();
428
+
429
+ // Cleanup HA keystore temp directories
430
+ if (this.haKeystoreDirs) {
431
+ for (let i = 0; i < this.haKeystoreDirs.length; i++) {
432
+ try {
433
+ await rm(this.haKeystoreDirs[i], { recursive: true });
434
+ } catch (error) {
435
+ this.logger.error(`Failed to remove HA keystore dir ${i}: ${error}`);
436
+ }
437
+ }
438
+ }
439
+
440
+ // Cleanup HA resources (database pools, etc.)
441
+ if (this.haNodePools) {
442
+ for (const pool of this.haNodePools) {
443
+ try {
444
+ await pool.end();
445
+ } catch (error) {
446
+ this.logger.error(`Failed to close HA node pool: ${error}`);
447
+ }
448
+ }
449
+ }
450
+ await cleanupHADatabase(this.mainPool, this.logger);
451
+ await this.mainPool.end();
452
+
453
+ // Cleanup bootstrap node and test infrastructure (this cleans up the shared data directory)
454
+ await this.teardownBootstrap();
455
+ }
456
+
457
+ /** Clean up database state between tests. */
458
+ async resetDutiesTable(): Promise<void> {
459
+ try {
460
+ await this.mainPool.query('DELETE FROM validator_duties');
461
+ } catch (error) {
462
+ // Ignore cleanup errors (table might not exist on first run failure)
463
+ this.logger?.warn(`Failed to clean up validator_duties: ${error}`);
464
+ }
465
+ }
466
+ }
@@ -1,7 +1,7 @@
1
1
  import { type InitialAccountData, generateSchnorrAccounts } from '@aztec/accounts/testing';
2
2
  import { AztecNodeService, createAztecNodeService } from '@aztec/aztec-node';
3
3
  import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
4
- import { type Logger, createLogger } from '@aztec/aztec.js/log';
4
+ import { createLogger } from '@aztec/aztec.js/log';
5
5
  import type { AztecNode } from '@aztec/aztec.js/node';
6
6
  import { CheatCodes } from '@aztec/aztec/testing';
7
7
  import type { ClientProtocolCircuitVerifier } from '@aztec/bb-prover';
@@ -19,18 +19,12 @@ import { type Hex, getContract } from 'viem';
19
19
  import { privateKeyToAddress } from 'viem/accounts';
20
20
 
21
21
  import { TokenSimulator } from '../simulators/token_simulator.js';
22
+ import { SingleNodeTestContext, type SingleNodeTestOpts } from '../single-node/single_node_test_context.js';
22
23
  import { TestWallet } from '../test-wallet/test_wallet.js';
23
24
  import { getACVMConfig } from './get_acvm_config.js';
24
25
  import { getBBConfig } from './get_bb_config.js';
25
- import {
26
- type EndToEndContext,
27
- type SetupOptions,
28
- getPrivateKeyFromIndex,
29
- getSponsoredFPCAddress,
30
- setup,
31
- setupPXEAndGetWallet,
32
- teardown,
33
- } from './setup.js';
26
+ import { getPrivateKeyFromIndex, getSponsoredFPCAddress, setup, setupPXEAndGetWallet } from './setup.js';
27
+ import { getStandardContractGenesisNullifiers } from './standard_contracts_genesis.js';
34
28
 
35
29
  type ProvenSetup = {
36
30
  wallet: TestWallet;
@@ -42,13 +36,17 @@ type ProvenSetup = {
42
36
  * However, we then setup a second PXE with a full prover instance.
43
37
  * We configure this instance with all of the accounts and contracts.
44
38
  * We then prove and verify transactions created via this full prover PXE.
39
+ *
40
+ * The real-prover sub-base of the single-node topology: extends {@link SingleNodeTestContext} so it
41
+ * reuses the base node tracking / chain monitor / teardown machinery, but builds its environment with
42
+ * the bespoke prover opts below (real BB, `realVerifier` L1, the snapshot/account + TokenSimulator
43
+ * harness, and a hand-built prover node) rather than the base's default fake-prover config.
45
44
  */
46
45
 
47
- export class FullProverTest {
46
+ export class FullProverTest extends SingleNodeTestContext {
48
47
  static TOKEN_NAME = 'USDC';
49
48
  static TOKEN_SYMBOL = 'USD';
50
49
  static TOKEN_DECIMALS = 18n;
51
- logger: Logger;
52
50
  wallet!: TestWallet;
53
51
  provenWallet!: TestWallet;
54
52
  accounts: AztecAddress[] = [];
@@ -67,16 +65,18 @@ export class FullProverTest {
67
65
  return this.proverAztecNode?.getProofVerifier();
68
66
  }
69
67
  provenAsset!: TokenContract;
70
- context!: EndToEndContext;
71
68
  private proverAztecNode!: AztecNodeService;
72
69
  private simulatedProverAztecNode!: AztecNodeService;
73
70
  public l1Contracts!: DeployAztecL1ContractsReturnType;
74
71
  public proverAddress!: EthAddress;
72
+ private testName: string;
75
73
  private minNumberOfTxsPerBlock: number;
76
74
  private coinbase: EthAddress;
77
75
  private realProofs: boolean;
78
76
 
79
77
  constructor(testName: string, minNumberOfTxsPerBlock: number, coinbase: EthAddress, realProofs = true) {
78
+ super();
79
+ this.testName = testName;
80
80
  this.logger = createLogger(`e2e:full_prover_test:${testName}`);
81
81
  this.minNumberOfTxsPerBlock = minNumberOfTxsPerBlock;
82
82
  this.coinbase = coinbase;
@@ -116,9 +116,9 @@ export class FullProverTest {
116
116
  );
117
117
  }
118
118
 
119
- async setup(opts: Partial<SetupOptions> = {}) {
119
+ override async setup(opts: SingleNodeTestOpts = {}) {
120
120
  this.logger.info('Setting up subsystems from fresh');
121
- this.context = await setup(0, {
121
+ const context = await setup(0, {
122
122
  ...opts,
123
123
  startProverNode: true,
124
124
  coinbase: this.coinbase,
@@ -127,6 +127,12 @@ export class FullProverTest {
127
127
  l1ContractsArgs: { realVerifier: this.realProofs },
128
128
  });
129
129
 
130
+ // Reuse the base context machinery (rollup, epoch cache, chain monitor, node tracking, teardown)
131
+ // over the environment built above. Restore the FullProverTest-named logger afterwards, since
132
+ // hydrateFromContext repoints `this.logger` at the context logger.
133
+ await this.hydrateFromContext(context);
134
+ this.logger = createLogger(`e2e:full_prover_test:${this.testName}`);
135
+
130
136
  await this.applyBaseSetup();
131
137
  await this.applyMint();
132
138
 
@@ -191,8 +197,13 @@ export class FullProverTest {
191
197
  await provenWallet.createSchnorrInitializerlessAccount(
192
198
  this.fundedAccounts[i].secret,
193
199
  this.fundedAccounts[i].salt,
200
+ this.fundedAccounts[i].signingKey,
201
+ );
202
+ await this.wallet.createSchnorrInitializerlessAccount(
203
+ this.fundedAccounts[i].secret,
204
+ this.fundedAccounts[i].salt,
205
+ this.fundedAccounts[i].signingKey,
194
206
  );
195
- await this.wallet.createSchnorrInitializerlessAccount(this.fundedAccounts[i].secret, this.fundedAccounts[i].salt);
196
207
  }
197
208
 
198
209
  const asset = TokenContract.at(this.fakeProofsAsset.address, provenWallet);
@@ -224,6 +235,7 @@ export class FullProverTest {
224
235
  undefined,
225
236
  undefined,
226
237
  this.context.genesis!.genesisTimestamp,
238
+ await getStandardContractGenesisNullifiers(),
227
239
  );
228
240
 
229
241
  const proverNodeConfig: Parameters<typeof createAztecNodeService>[0] = {
@@ -256,8 +268,10 @@ export class FullProverTest {
256
268
  { dateProvider: this.context.dateProvider, p2pClientDeps: { rpcTxProviders: [this.aztecNode] } },
257
269
  { genesis },
258
270
  );
271
+ // Track the real prover node so the base teardown stops it (the simulated one created by `setup`
272
+ // was already stopped above).
273
+ this.proverNodes = [this.proverAztecNode];
259
274
  this.logger.warn(`Proofs are now enabled`, { realProofs: this.realProofs });
260
- return this;
261
275
  }
262
276
 
263
277
  private async mintFeeJuice(recipient: Hex) {
@@ -269,20 +283,22 @@ export class FullProverTest {
269
283
  await this.context.deployL1ContractsValues.l1Client.waitForTransactionReceipt({ hash });
270
284
  }
271
285
 
272
- async teardown() {
286
+ override async teardown() {
273
287
  // Cleanup related to the full prover PXEs
274
288
  for (let i = 0; i < this.provenComponents.length; i++) {
275
289
  await this.provenComponents[i].teardown();
276
290
  }
277
291
 
278
- // clean up the full prover node (by stopping its hosting aztec node)
292
+ // Stop the prover node before destroying the BB singleton it proves with.
279
293
  await this.proverAztecNode.stop();
280
294
 
281
295
  await Barretenberg.destroySingleton();
282
296
  await this.bbConfigCleanup?.();
283
297
  await this.acvmConfigCleanup?.();
284
298
 
285
- await teardown(this.context);
299
+ // Stops the chain monitor, the tracked nodes (main node + the already-stopped prover node, a
300
+ // safe no-op), and the context.
301
+ await super.teardown();
286
302
  }
287
303
 
288
304
  private async applyMint() {
@@ -1,4 +1,5 @@
1
1
  import type { AztecNode } from '@aztec/aztec.js/node';
2
+ import { TEST_FEE_PADDING } from '@aztec/aztec/testing';
2
3
  import type { GasFees } from '@aztec/stdlib/gas';
3
4
 
4
5
  export const METRICS_PORT = 4318;
@@ -17,9 +18,10 @@ export const LARGE_MIN_FEE_PADDING = 15;
17
18
  * price modifier evolves faster across the build/publish gap, so client-set maxFeesPerGas (sized
18
19
  * for the default 5x padding) was getting bumped past by the time the tx mined a few slots later.
19
20
  * Observed worst case in CI: fee evolved ~20x between PXE snapshot and inclusion, exceeding even
20
- * LARGE_MIN_FEE_PADDING (15x).
21
+ * LARGE_MIN_FEE_PADDING (15x). Same multiplier and same class of problem as the published
22
+ * {@link TEST_FEE_PADDING}, re-exported under a name that captures the pipelining rationale.
21
23
  */
22
- export const PIPELINED_FEE_PADDING = 30;
24
+ export const PIPELINED_FEE_PADDING = TEST_FEE_PADDING;
23
25
 
24
26
  /**
25
27
  * Setup option preset that opts a test into proposer pipelining. Use with `setup()`:
@@ -53,8 +55,8 @@ export const PIPELINING_SETUP_OPTS = {
53
55
  /**
54
56
  * Setup option preset that opts a test into the deterministic AutomineSequencer path.
55
57
  * Use only for single-sequencer tests that don't exercise block-building or consensus
56
- * (e.g. e2e_token, e2e_amm, e2e_authwit). Not compatible with `e2e_p2p/*`,
57
- * `e2e_epochs/*`, `e2e_slashing/*`, `e2e_block_building`, or any multi-validator suite.
58
+ * (e.g. e2e_token, e2e_amm, e2e_authwit). Not compatible with `p2p/*`,
59
+ * `multi-node/*`, `e2e_block_building`, or any multi-validator suite.
58
60
  *
59
61
  * await setup(N, { ...AUTOMINE_E2E_OPTS, ...otherOpts });
60
62
  *
@@ -64,8 +66,10 @@ export const PIPELINING_SETUP_OPTS = {
64
66
  * serial queue (see `sequencer-client/src/sequencer/automine/automine_sequencer.ts`).
65
67
  * - Disables the validator client (the AutomineSequencer needs none).
66
68
  * - Uses `inboxLag: 1` (synchronous) since the AutomineSequencer publishes one block per tx.
67
- * - Switches anvil into automine mode at setup time (no interval mining); each L1 tx
68
- * mines an L1 block immediately.
69
+ * - Runs anvil at a 4s interval (`ethereumSlotDuration: 4`); at runtime the AutomineSequencer
70
+ * flips anvil into automine so each submitted tx mines its L1 block immediately. Initial L1
71
+ * contract deployment (which runs before the sequencer starts) is mined immediately too via the
72
+ * global `automineL1Setup` default in `setup()`, instead of stalling on the 4s interval.
69
73
  *
70
74
  * Requires `aztecTargetCommitteeSize: 0`, which is the e2e default at `setup.ts:317`.
71
75
  */
@@ -75,7 +79,7 @@ export const AUTOMINE_E2E_OPTS = {
75
79
  minTxsPerBlock: 0,
76
80
  aztecSlotDuration: 12,
77
81
  ethereumSlotDuration: 4,
78
- walletMinFeePadding: PIPELINED_FEE_PADDING,
82
+ walletMinFeePadding: TEST_FEE_PADDING,
79
83
  } as const;
80
84
 
81
85
  /** Returns worst-case predicted min fees with padding applied, mirroring the BaseWallet pattern. */