@aztec/end-to-end 0.0.1-commit.fce3e4f → 0.0.1-commit.fffb133c

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 (191) hide show
  1. package/dest/bench/client_flows/benchmark.d.ts +3 -2
  2. package/dest/bench/client_flows/benchmark.d.ts.map +1 -1
  3. package/dest/bench/client_flows/benchmark.js +21 -1
  4. package/dest/bench/client_flows/client_flows_benchmark.d.ts +14 -15
  5. package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
  6. package/dest/bench/client_flows/client_flows_benchmark.js +123 -136
  7. package/dest/bench/client_flows/data_extractor.js +3 -1
  8. package/dest/bench/utils.d.ts +9 -8
  9. package/dest/bench/utils.d.ts.map +1 -1
  10. package/dest/bench/utils.js +27 -18
  11. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +6 -7
  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 +96 -112
  14. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +19 -13
  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 +91 -71
  17. package/dest/e2e_deploy_contract/deploy_test.d.ts +4 -3
  18. package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -1
  19. package/dest/e2e_deploy_contract/deploy_test.js +18 -13
  20. package/dest/e2e_epochs/epochs_test.d.ts +11 -9
  21. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  22. package/dest/e2e_epochs/epochs_test.js +18 -13
  23. package/dest/e2e_fees/bridging_race.notest.js +4 -6
  24. package/dest/e2e_fees/fees_test.d.ts +20 -16
  25. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  26. package/dest/e2e_fees/fees_test.js +126 -141
  27. package/dest/e2e_l1_publisher/write_json.d.ts +2 -2
  28. package/dest/e2e_l1_publisher/write_json.d.ts.map +1 -1
  29. package/dest/e2e_l1_publisher/write_json.js +19 -15
  30. package/dest/e2e_multi_validator/utils.js +1 -1
  31. package/dest/e2e_nested_contract/nested_contract_test.d.ts +6 -9
  32. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
  33. package/dest/e2e_nested_contract/nested_contract_test.js +31 -39
  34. package/dest/e2e_p2p/inactivity_slash_test.d.ts +4 -4
  35. package/dest/e2e_p2p/inactivity_slash_test.d.ts.map +1 -1
  36. package/dest/e2e_p2p/inactivity_slash_test.js +6 -9
  37. package/dest/e2e_p2p/p2p_network.d.ts +13 -11
  38. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  39. package/dest/e2e_p2p/p2p_network.js +120 -111
  40. package/dest/e2e_p2p/shared.d.ts +7 -7
  41. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  42. package/dest/e2e_p2p/shared.js +11 -18
  43. package/dest/e2e_token_contract/token_contract_test.d.ts +16 -9
  44. package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
  45. package/dest/e2e_token_contract/token_contract_test.js +89 -91
  46. package/dest/fixtures/e2e_prover_test.d.ts +10 -18
  47. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  48. package/dest/fixtures/e2e_prover_test.js +90 -102
  49. package/dest/fixtures/fixtures.d.ts +2 -3
  50. package/dest/fixtures/fixtures.d.ts.map +1 -1
  51. package/dest/fixtures/fixtures.js +2 -3
  52. package/dest/fixtures/get_acvm_config.js +1 -1
  53. package/dest/fixtures/l1_to_l2_messaging.d.ts +4 -3
  54. package/dest/fixtures/l1_to_l2_messaging.d.ts.map +1 -1
  55. package/dest/fixtures/l1_to_l2_messaging.js +2 -2
  56. package/dest/fixtures/setup.d.ts +218 -0
  57. package/dest/fixtures/setup.d.ts.map +1 -0
  58. package/dest/fixtures/setup.js +690 -0
  59. package/dest/fixtures/setup_p2p_test.js +3 -3
  60. package/dest/fixtures/token_utils.d.ts +1 -1
  61. package/dest/fixtures/token_utils.d.ts.map +1 -1
  62. package/dest/fixtures/token_utils.js +7 -4
  63. package/dest/fixtures/utils.d.ts +5 -637
  64. package/dest/fixtures/utils.d.ts.map +1 -1
  65. package/dest/fixtures/utils.js +4 -647
  66. package/dest/fixtures/web3signer.js +1 -1
  67. package/dest/fixtures/with_telemetry_utils.d.ts +2 -2
  68. package/dest/fixtures/with_telemetry_utils.d.ts.map +1 -1
  69. package/dest/fixtures/with_telemetry_utils.js +2 -2
  70. package/dest/quality_of_service/grafana_client.d.ts +41 -0
  71. package/dest/quality_of_service/grafana_client.d.ts.map +1 -0
  72. package/dest/quality_of_service/{alert_checker.js → grafana_client.js} +1 -1
  73. package/dest/quality_of_service/prometheus_client.d.ts +38 -0
  74. package/dest/quality_of_service/prometheus_client.d.ts.map +1 -0
  75. package/dest/quality_of_service/prometheus_client.js +67 -0
  76. package/dest/shared/cross_chain_test_harness.d.ts +18 -6
  77. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
  78. package/dest/shared/cross_chain_test_harness.js +14 -14
  79. package/dest/shared/gas_portal_test_harness.d.ts +12 -2
  80. package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
  81. package/dest/shared/gas_portal_test_harness.js +1 -1
  82. package/dest/shared/index.d.ts +2 -2
  83. package/dest/shared/index.d.ts.map +1 -1
  84. package/dest/shared/submit-transactions.d.ts +3 -3
  85. package/dest/shared/submit-transactions.d.ts.map +1 -1
  86. package/dest/shared/submit-transactions.js +9 -11
  87. package/dest/shared/uniswap_l1_l2.d.ts +3 -27
  88. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  89. package/dest/shared/uniswap_l1_l2.js +55 -35
  90. package/dest/simulators/lending_simulator.d.ts +6 -2
  91. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  92. package/dest/simulators/lending_simulator.js +2 -2
  93. package/dest/spartan/setup_test_wallets.d.ts +4 -3
  94. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  95. package/dest/spartan/setup_test_wallets.js +63 -35
  96. package/dest/spartan/tx_metrics.d.ts +54 -0
  97. package/dest/spartan/tx_metrics.d.ts.map +1 -0
  98. package/dest/spartan/tx_metrics.js +272 -0
  99. package/dest/spartan/utils/bot.d.ts +27 -0
  100. package/dest/spartan/utils/bot.d.ts.map +1 -0
  101. package/dest/spartan/utils/bot.js +141 -0
  102. package/dest/spartan/utils/chaos.d.ts +79 -0
  103. package/dest/spartan/utils/chaos.d.ts.map +1 -0
  104. package/dest/spartan/utils/chaos.js +142 -0
  105. package/dest/spartan/utils/clients.d.ts +39 -0
  106. package/dest/spartan/utils/clients.d.ts.map +1 -0
  107. package/dest/spartan/utils/clients.js +90 -0
  108. package/dest/spartan/utils/config.d.ts +36 -0
  109. package/dest/spartan/utils/config.d.ts.map +1 -0
  110. package/dest/spartan/utils/config.js +20 -0
  111. package/dest/spartan/utils/health.d.ts +63 -0
  112. package/dest/spartan/utils/health.d.ts.map +1 -0
  113. package/dest/spartan/utils/health.js +202 -0
  114. package/dest/spartan/utils/helm.d.ts +15 -0
  115. package/dest/spartan/utils/helm.d.ts.map +1 -0
  116. package/dest/spartan/utils/helm.js +47 -0
  117. package/dest/spartan/utils/index.d.ts +9 -0
  118. package/dest/spartan/utils/index.d.ts.map +1 -0
  119. package/dest/spartan/utils/index.js +18 -0
  120. package/dest/spartan/utils/k8s.d.ts +98 -0
  121. package/dest/spartan/utils/k8s.d.ts.map +1 -0
  122. package/dest/spartan/utils/k8s.js +257 -0
  123. package/dest/spartan/utils/nodes.d.ts +31 -0
  124. package/dest/spartan/utils/nodes.d.ts.map +1 -0
  125. package/dest/spartan/utils/nodes.js +290 -0
  126. package/dest/spartan/utils/scripts.d.ts +16 -0
  127. package/dest/spartan/utils/scripts.d.ts.map +1 -0
  128. package/dest/spartan/utils/scripts.js +66 -0
  129. package/dest/spartan/utils.d.ts +2 -218
  130. package/dest/spartan/utils.d.ts.map +1 -1
  131. package/dest/spartan/utils.js +1 -749
  132. package/package.json +42 -41
  133. package/src/bench/client_flows/benchmark.ts +24 -2
  134. package/src/bench/client_flows/client_flows_benchmark.ts +145 -208
  135. package/src/bench/client_flows/data_extractor.ts +1 -1
  136. package/src/bench/utils.ts +30 -20
  137. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +104 -142
  138. package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +140 -125
  139. package/src/e2e_deploy_contract/deploy_test.ts +21 -14
  140. package/src/e2e_epochs/epochs_test.ts +63 -45
  141. package/src/e2e_fees/bridging_race.notest.ts +4 -10
  142. package/src/e2e_fees/fees_test.ts +179 -221
  143. package/src/e2e_l1_publisher/write_json.ts +21 -16
  144. package/src/e2e_multi_validator/utils.ts +1 -1
  145. package/src/e2e_nested_contract/nested_contract_test.ts +33 -56
  146. package/src/e2e_p2p/inactivity_slash_test.ts +9 -12
  147. package/src/e2e_p2p/p2p_network.ts +180 -183
  148. package/src/e2e_p2p/shared.ts +21 -26
  149. package/src/e2e_token_contract/token_contract_test.ts +103 -118
  150. package/src/fixtures/e2e_prover_test.ts +103 -140
  151. package/src/fixtures/fixtures.ts +2 -5
  152. package/src/fixtures/get_acvm_config.ts +1 -1
  153. package/src/fixtures/l1_to_l2_messaging.ts +4 -2
  154. package/src/fixtures/setup.ts +1017 -0
  155. package/src/fixtures/setup_p2p_test.ts +3 -3
  156. package/src/fixtures/token_utils.ts +6 -5
  157. package/src/fixtures/utils.ts +27 -966
  158. package/src/fixtures/web3signer.ts +1 -1
  159. package/src/fixtures/with_telemetry_utils.ts +2 -2
  160. package/src/quality_of_service/{alert_checker.ts → grafana_client.ts} +1 -1
  161. package/src/quality_of_service/prometheus_client.ts +113 -0
  162. package/src/shared/cross_chain_test_harness.ts +19 -36
  163. package/src/shared/gas_portal_test_harness.ts +2 -2
  164. package/src/shared/index.ts +1 -1
  165. package/src/shared/submit-transactions.ts +9 -15
  166. package/src/shared/uniswap_l1_l2.ts +65 -86
  167. package/src/simulators/lending_simulator.ts +3 -3
  168. package/src/spartan/DEVELOP.md +7 -0
  169. package/src/spartan/setup_test_wallets.ts +81 -26
  170. package/src/spartan/tx_metrics.ts +250 -0
  171. package/src/spartan/utils/bot.ts +185 -0
  172. package/src/spartan/utils/chaos.ts +253 -0
  173. package/src/spartan/utils/clients.ts +100 -0
  174. package/src/spartan/utils/config.ts +26 -0
  175. package/src/spartan/utils/health.ts +255 -0
  176. package/src/spartan/utils/helm.ts +84 -0
  177. package/src/spartan/utils/index.ts +62 -0
  178. package/src/spartan/utils/k8s.ts +375 -0
  179. package/src/spartan/utils/nodes.ts +323 -0
  180. package/src/spartan/utils/scripts.ts +63 -0
  181. package/src/spartan/utils.ts +1 -942
  182. package/dest/fixtures/setup_l1_contracts.d.ts +0 -477
  183. package/dest/fixtures/setup_l1_contracts.d.ts.map +0 -1
  184. package/dest/fixtures/setup_l1_contracts.js +0 -17
  185. package/dest/fixtures/snapshot_manager.d.ts +0 -95
  186. package/dest/fixtures/snapshot_manager.d.ts.map +0 -1
  187. package/dest/fixtures/snapshot_manager.js +0 -505
  188. package/dest/quality_of_service/alert_checker.d.ts +0 -41
  189. package/dest/quality_of_service/alert_checker.d.ts.map +0 -1
  190. package/src/fixtures/setup_l1_contracts.ts +0 -26
  191. package/src/fixtures/snapshot_manager.ts +0 -665
@@ -1,749 +1 @@
1
- import { createLogger } from '@aztec/aztec.js/log';
2
- import { makeBackoff, retry } from '@aztec/foundation/retry';
3
- import { schemas } from '@aztec/foundation/schemas';
4
- import { sleep } from '@aztec/foundation/sleep';
5
- import { createAztecNodeAdminClient, createAztecNodeClient } from '@aztec/stdlib/interfaces/client';
6
- import { exec, execSync, spawn } from 'child_process';
7
- import path from 'path';
8
- import { promisify } from 'util';
9
- import { createPublicClient, fallback, http } from 'viem';
10
- import { z } from 'zod';
11
- const execAsync = promisify(exec);
12
- const logger = createLogger('e2e:k8s-utils');
13
- const testConfigSchema = z.object({
14
- NAMESPACE: z.string().default('scenario'),
15
- REAL_VERIFIER: schemas.Boolean.optional().default(true),
16
- CREATE_ETH_DEVNET: schemas.Boolean.optional().default(false),
17
- L1_RPC_URLS_JSON: z.string().optional(),
18
- L1_ACCOUNT_MNEMONIC: z.string().optional(),
19
- AZTEC_SLOT_DURATION: z.coerce.number().optional().default(24),
20
- AZTEC_PROOF_SUBMISSION_WINDOW: z.coerce.number().optional().default(5)
21
- });
22
- export function setupEnvironment(env) {
23
- const config = testConfigSchema.parse(env);
24
- logger.warn(`Loaded env config`, config);
25
- return config;
26
- }
27
- /**
28
- * @param path - The path to the script, relative to the project root
29
- * @param args - The arguments to pass to the script
30
- * @param logger - The logger to use
31
- * @returns The exit code of the script
32
- */ function runScript(path, args, logger, env) {
33
- const childProcess = spawn(path, args, {
34
- stdio: [
35
- 'ignore',
36
- 'pipe',
37
- 'pipe'
38
- ],
39
- env: env ? {
40
- ...process.env,
41
- ...env
42
- } : process.env
43
- });
44
- return new Promise((resolve, reject)=>{
45
- childProcess.on('close', (code)=>resolve(code ?? 0));
46
- childProcess.on('error', reject);
47
- childProcess.stdout?.on('data', (data)=>{
48
- logger.info(data.toString());
49
- });
50
- childProcess.stderr?.on('data', (data)=>{
51
- logger.error(data.toString());
52
- });
53
- });
54
- }
55
- export function getAztecBin() {
56
- return path.join(getGitProjectRoot(), 'yarn-project/aztec/dest/bin/index.js');
57
- }
58
- /**
59
- * Runs the Aztec binary
60
- * @param args - The arguments to pass to the Aztec binary
61
- * @param logger - The logger to use
62
- * @param env - Optional environment variables to set for the process
63
- * @returns The exit code of the Aztec binary
64
- */ export function runAztecBin(args, logger, env) {
65
- return runScript('node', [
66
- getAztecBin(),
67
- ...args
68
- ], logger, env);
69
- }
70
- export function runProjectScript(script, args, logger, env) {
71
- const scriptPath = script.startsWith('/') ? script : path.join(getGitProjectRoot(), script);
72
- return runScript(scriptPath, args, logger, env);
73
- }
74
- export async function startPortForward({ resource, namespace, containerPort, hostPort }) {
75
- const hostPortAsString = hostPort ? hostPort.toString() : '';
76
- logger.debug(`kubectl port-forward -n ${namespace} ${resource} ${hostPortAsString}:${containerPort}`);
77
- const process1 = spawn('kubectl', [
78
- 'port-forward',
79
- '-n',
80
- namespace,
81
- resource,
82
- `${hostPortAsString}:${containerPort}`
83
- ], {
84
- detached: true,
85
- windowsHide: true,
86
- stdio: [
87
- 'ignore',
88
- 'pipe',
89
- 'pipe'
90
- ]
91
- });
92
- let isResolved = false;
93
- const connected = new Promise((resolve)=>{
94
- process1.stdout?.on('data', (data)=>{
95
- const str = data.toString();
96
- if (!isResolved && str.includes('Forwarding from')) {
97
- isResolved = true;
98
- logger.debug(`Port forward for ${resource}: ${str}`);
99
- const port = str.search(/:\d+/);
100
- if (port === -1) {
101
- throw new Error('Port not found in port forward output');
102
- }
103
- const portNumber = parseInt(str.slice(port + 1));
104
- logger.verbose(`Port forwarded for ${resource} at ${portNumber}:${containerPort}`);
105
- resolve(portNumber);
106
- } else {
107
- logger.silent(str);
108
- }
109
- });
110
- process1.stderr?.on('data', (data)=>{
111
- logger.verbose(`Port forward for ${resource}: ${data.toString()}`);
112
- // It's a strange thing:
113
- // If we don't pipe stderr, then the port forwarding does not work.
114
- // Log to silent because this doesn't actually report errors,
115
- // just extremely verbose debug logs.
116
- logger.silent(data.toString());
117
- });
118
- process1.on('close', ()=>{
119
- if (!isResolved) {
120
- isResolved = true;
121
- logger.warn(`Port forward for ${resource} closed before connection established`);
122
- resolve(0);
123
- }
124
- });
125
- process1.on('error', (error)=>{
126
- logger.error(`Port forward for ${resource} error: ${error}`);
127
- resolve(0);
128
- });
129
- process1.on('exit', (code)=>{
130
- logger.verbose(`Port forward for ${resource} exited with code ${code}`);
131
- resolve(0);
132
- });
133
- });
134
- const port = await connected;
135
- return {
136
- process: process1,
137
- port
138
- };
139
- }
140
- export function startPortForwardForRPC(namespace, resourceType = 'services', index = 0) {
141
- return startPortForward({
142
- resource: `${resourceType}/${namespace}-rpc-aztec-node-${index}`,
143
- namespace,
144
- containerPort: 8080
145
- });
146
- }
147
- export function startPortForwardForEthereum(namespace) {
148
- return startPortForward({
149
- resource: `services/${namespace}-eth-execution`,
150
- namespace,
151
- containerPort: 8545
152
- });
153
- }
154
- export async function deleteResourceByName({ resource, namespace, name, force = false }) {
155
- const command = `kubectl delete ${resource} ${name} -n ${namespace} --ignore-not-found=true --wait=true ${force ? '--force' : ''}`;
156
- logger.info(`command: ${command}`);
157
- const { stdout } = await execAsync(command);
158
- return stdout;
159
- }
160
- export async function deleteResourceByLabel({ resource, namespace, label, timeout = '5m', force = false }) {
161
- // Check if the resource type exists before attempting to delete
162
- try {
163
- await execAsync(`kubectl api-resources --api-group="" --no-headers -o name | grep -q "^${resource}$" || kubectl api-resources --no-headers -o name | grep -q "^${resource}$"`);
164
- } catch (error) {
165
- logger.warn(`Resource type '${resource}' not found in cluster, skipping deletion ${error}`);
166
- return '';
167
- }
168
- const command = `kubectl delete ${resource} -l ${label} -n ${namespace} --ignore-not-found=true --wait=true --timeout=${timeout} ${force ? '--force' : ''}`;
169
- logger.info(`command: ${command}`);
170
- const { stdout } = await execAsync(command);
171
- return stdout;
172
- }
173
- export async function waitForResourceByLabel({ resource, label, namespace, condition = 'Ready', timeout = '10m' }) {
174
- const command = `kubectl wait ${resource} -l ${label} --for=condition=${condition} -n ${namespace} --timeout=${timeout}`;
175
- logger.info(`command: ${command}`);
176
- const { stdout } = await execAsync(command);
177
- return stdout;
178
- }
179
- export function getChartDir(spartanDir, chartName) {
180
- return path.join(spartanDir.trim(), chartName);
181
- }
182
- function shellQuote(value) {
183
- // Single-quote safe shell escaping: ' -> '\''
184
- return `'${value.replace(/'/g, "'\\''")}'`;
185
- }
186
- function valuesToArgs(values) {
187
- return Object.entries(values).map(([key, value])=>typeof value === 'number' || typeof value === 'boolean' ? `--set ${key}=${value}` : `--set-string ${key}=${shellQuote(String(value))}`).join(' ');
188
- }
189
- function createHelmCommand({ instanceName, helmChartDir, namespace, valuesFile, timeout, values, reuseValues = false }) {
190
- const valuesFileArgs = valuesFile ? `--values ${helmChartDir}/values/${valuesFile}` : '';
191
- const reuseValuesArgs = reuseValues ? '--reuse-values' : '';
192
- return `helm upgrade --install ${instanceName} ${helmChartDir} --namespace ${namespace} ${valuesFileArgs} ${reuseValuesArgs} --wait --timeout=${timeout} ${valuesToArgs(values)}`;
193
- }
194
- async function execHelmCommand(args) {
195
- const helmCommand = createHelmCommand(args);
196
- logger.info(`helm command: ${helmCommand}`);
197
- const { stdout } = await execAsync(helmCommand);
198
- return stdout;
199
- }
200
- /**
201
- * Installs a Helm chart with the given parameters.
202
- * @param instanceName - The name of the Helm chart instance.
203
- * @param targetNamespace - The namespace with the resources to be affected by the Helm chart.
204
- * @param valuesFile - The values file to use for the Helm chart.
205
- * @param chaosMeshNamespace - The namespace to install the Helm chart in.
206
- * @param timeout - The timeout for the Helm command.
207
- * @param clean - Whether to clean up the Helm chart before installing it.
208
- * @returns The stdout of the Helm command.
209
- * @throws If the Helm command fails.
210
- *
211
- * Example usage:
212
- * ```typescript
213
- * const stdout = await installChaosMeshChart({ instanceName: 'force-reorg', targetNamespace: 'smoke', valuesFile: 'prover-failure.yaml'});
214
- * console.log(stdout);
215
- * ```
216
- */ export async function installChaosMeshChart({ instanceName, targetNamespace, valuesFile, helmChartDir, chaosMeshNamespace = 'chaos-mesh', timeout = '10m', clean = true, values = {}, logger }) {
217
- if (clean) {
218
- // uninstall the helm chart if it exists
219
- logger.info(`Uninstalling helm chart ${instanceName}`);
220
- await execAsync(`helm uninstall ${instanceName} --namespace ${chaosMeshNamespace} --wait --ignore-not-found`);
221
- // and delete the chaos-mesh resources created by this release
222
- const deleteByLabel = async (resource)=>{
223
- const args = {
224
- resource,
225
- namespace: chaosMeshNamespace,
226
- label: `app.kubernetes.io/instance=${instanceName}`
227
- };
228
- logger.info(`Deleting ${resource} resources for release ${instanceName}`);
229
- await deleteResourceByLabel(args).catch((e)=>{
230
- logger.error(`Error deleting ${resource}: ${e}`);
231
- logger.info(`Force deleting ${resource}`);
232
- return deleteResourceByLabel({
233
- ...args,
234
- force: true
235
- });
236
- });
237
- };
238
- await deleteByLabel('podchaos');
239
- await deleteByLabel('networkchaos');
240
- }
241
- return execHelmCommand({
242
- instanceName,
243
- helmChartDir,
244
- namespace: chaosMeshNamespace,
245
- valuesFile,
246
- timeout,
247
- values: {
248
- ...values,
249
- 'global.targetNamespace': targetNamespace
250
- }
251
- });
252
- }
253
- export function applyProverFailure({ namespace, spartanDir, durationSeconds, logger }) {
254
- return installChaosMeshChart({
255
- instanceName: 'prover-failure',
256
- targetNamespace: namespace,
257
- valuesFile: 'prover-failure.yaml',
258
- helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
259
- values: {
260
- 'proverFailure.duration': `${durationSeconds}s`
261
- },
262
- logger
263
- });
264
- }
265
- export function applyProverKill({ namespace, spartanDir, logger }) {
266
- return installChaosMeshChart({
267
- instanceName: 'prover-kill',
268
- targetNamespace: namespace,
269
- valuesFile: 'prover-kill.yaml',
270
- helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
271
- clean: true,
272
- logger
273
- });
274
- }
275
- export function applyProverBrokerKill({ namespace, spartanDir, logger }) {
276
- return installChaosMeshChart({
277
- instanceName: 'prover-broker-kill',
278
- targetNamespace: namespace,
279
- valuesFile: 'prover-broker-kill.yaml',
280
- helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
281
- clean: true,
282
- logger
283
- });
284
- }
285
- export function applyBootNodeFailure({ namespace, spartanDir, durationSeconds, logger }) {
286
- return installChaosMeshChart({
287
- instanceName: 'boot-node-failure',
288
- targetNamespace: namespace,
289
- valuesFile: 'boot-node-failure.yaml',
290
- helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
291
- values: {
292
- 'bootNodeFailure.duration': `${durationSeconds}s`
293
- },
294
- logger
295
- });
296
- }
297
- export function applyValidatorKill({ namespace, spartanDir, logger, values }) {
298
- return installChaosMeshChart({
299
- instanceName: 'validator-kill',
300
- targetNamespace: namespace,
301
- valuesFile: 'validator-kill.yaml',
302
- helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
303
- logger,
304
- values
305
- });
306
- }
307
- export function applyNetworkShaping({ valuesFile, namespace, spartanDir, logger }) {
308
- return installChaosMeshChart({
309
- instanceName: 'network-shaping',
310
- targetNamespace: namespace,
311
- valuesFile,
312
- helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
313
- logger
314
- });
315
- }
316
- export async function awaitL2BlockNumber(rollupCheatCodes, blockNumber, timeoutSeconds, logger) {
317
- logger.info(`Waiting for L2 Block ${blockNumber}`);
318
- let tips = await rollupCheatCodes.getTips();
319
- const endTime = Date.now() + timeoutSeconds * 1000;
320
- while(tips.pending < blockNumber && Date.now() < endTime){
321
- logger.info(`At L2 Block ${tips.pending}`);
322
- await sleep(1000);
323
- tips = await rollupCheatCodes.getTips();
324
- }
325
- if (tips.pending < blockNumber) {
326
- throw new Error(`Timeout waiting for L2 Block ${blockNumber}, only reached ${tips.pending}`);
327
- } else {
328
- logger.info(`Reached L2 Block ${tips.pending}`);
329
- }
330
- }
331
- export async function restartBot(namespace, logger) {
332
- logger.info(`Restarting bot`);
333
- await deleteResourceByLabel({
334
- resource: 'pods',
335
- namespace,
336
- label: 'app.kubernetes.io/name=bot'
337
- });
338
- await sleep(10 * 1000);
339
- // Some bot images may take time to report Ready due to heavy boot-time proving.
340
- // Waiting for PodReadyToStartContainers ensures the pod is scheduled and starting without blocking on full readiness.
341
- await waitForResourceByLabel({
342
- resource: 'pods',
343
- namespace,
344
- label: 'app.kubernetes.io/name=bot',
345
- condition: 'PodReadyToStartContainers'
346
- });
347
- logger.info(`Bot restarted`);
348
- }
349
- /**
350
- * Installs or upgrades the transfer bot Helm release for the given namespace.
351
- * Intended for test setup to enable L2 traffic generation only when needed.
352
- */ export async function installTransferBot({ namespace, spartanDir, logger, replicas = 1, txIntervalSeconds = 10, followChain = 'PENDING', mnemonic = process.env.LABS_INFRA_MNEMONIC ?? 'test test test test test test test test test test test junk', mnemonicStartIndex, botPrivateKey = process.env.BOT_TRANSFERS_L2_PRIVATE_KEY ?? '0xcafe01', nodeUrl, timeout = '15m', reuseValues = true, aztecSlotDuration = Number(process.env.AZTEC_SLOT_DURATION ?? 12) }) {
353
- const instanceName = `${namespace}-bot-transfers`;
354
- const helmChartDir = getChartDir(spartanDir, 'aztec-bot');
355
- const resolvedNodeUrl = nodeUrl ?? `http://${namespace}-rpc-aztec-node.${namespace}.svc.cluster.local:8080`;
356
- logger.info(`Installing/upgrading transfer bot: replicas=${replicas}, followChain=${followChain}`);
357
- const values = {
358
- 'bot.replicaCount': replicas,
359
- 'bot.txIntervalSeconds': txIntervalSeconds,
360
- 'bot.followChain': followChain,
361
- 'bot.botPrivateKey': botPrivateKey,
362
- 'bot.nodeUrl': resolvedNodeUrl,
363
- 'bot.mnemonic': mnemonic,
364
- 'bot.feePaymentMethod': 'fee_juice',
365
- 'aztec.slotDuration': aztecSlotDuration,
366
- // Ensure bot can reach its own PXE started in-process (default rpc.port is 8080)
367
- // Note: since aztec-bot depends on aztec-node with alias `bot`, env vars go under `bot.node.env`.
368
- 'bot.node.env.BOT_PXE_URL': 'http://127.0.0.1:8080',
369
- // Provide L1 execution RPC for bridging fee juice
370
- 'bot.node.env.ETHEREUM_HOSTS': `http://${namespace}-eth-execution.${namespace}.svc.cluster.local:8545`,
371
- // Provide L1 mnemonic for bridging (falls back to labs mnemonic)
372
- 'bot.node.env.BOT_L1_MNEMONIC': mnemonic
373
- };
374
- // Ensure we derive a funded L1 key (index 0 is funded on anvil default mnemonic)
375
- if (mnemonicStartIndex === undefined) {
376
- values['bot.mnemonicStartIndex'] = 0;
377
- }
378
- // Also pass a funded private key directly if available
379
- if (process.env.FUNDING_PRIVATE_KEY) {
380
- values['bot.node.env.BOT_L1_PRIVATE_KEY'] = process.env.FUNDING_PRIVATE_KEY;
381
- }
382
- // Align bot image with the running network image: prefer env var, else detect from a validator pod
383
- let repositoryFromEnv;
384
- let tagFromEnv;
385
- const aztecDockerImage = process.env.AZTEC_DOCKER_IMAGE;
386
- if (aztecDockerImage && aztecDockerImage.includes(':')) {
387
- const lastColon = aztecDockerImage.lastIndexOf(':');
388
- repositoryFromEnv = aztecDockerImage.slice(0, lastColon);
389
- tagFromEnv = aztecDockerImage.slice(lastColon + 1);
390
- }
391
- let repository = repositoryFromEnv;
392
- let tag = tagFromEnv;
393
- if (!repository || !tag) {
394
- try {
395
- const { stdout } = await execAsync(`kubectl get pods -l app.kubernetes.io/component=validator -n ${namespace} -o jsonpath='{.items[0].spec.containers[?(@.name=="aztec")].image}' | cat`);
396
- const image = stdout.trim().replace(/^'|'$/g, '');
397
- if (image && image.includes(':')) {
398
- const lastColon = image.lastIndexOf(':');
399
- repository = image.slice(0, lastColon);
400
- tag = image.slice(lastColon + 1);
401
- }
402
- } catch (err) {
403
- logger.warn(`Could not detect aztec image from validator pod: ${String(err)}`);
404
- }
405
- }
406
- if (repository && tag) {
407
- values['global.aztecImage.repository'] = repository;
408
- values['global.aztecImage.tag'] = tag;
409
- }
410
- if (mnemonicStartIndex !== undefined) {
411
- values['bot.mnemonicStartIndex'] = typeof mnemonicStartIndex === 'string' ? mnemonicStartIndex : Number(mnemonicStartIndex);
412
- }
413
- await execHelmCommand({
414
- instanceName,
415
- helmChartDir,
416
- namespace,
417
- valuesFile: undefined,
418
- timeout,
419
- values: values,
420
- reuseValues
421
- });
422
- if (replicas > 0) {
423
- await waitForResourceByLabel({
424
- resource: 'pods',
425
- namespace,
426
- label: 'app.kubernetes.io/name=bot',
427
- condition: 'PodReadyToStartContainers'
428
- });
429
- }
430
- }
431
- /**
432
- * Uninstalls the transfer bot Helm release from the given namespace.
433
- * Intended for test teardown to clean up bot resources.
434
- */ export async function uninstallTransferBot(namespace, logger) {
435
- const instanceName = `${namespace}-bot-transfers`;
436
- logger.info(`Uninstalling transfer bot release ${instanceName}`);
437
- await execAsync(`helm uninstall ${instanceName} --namespace ${namespace} --wait --ignore-not-found`);
438
- // Ensure any leftover pods are removed
439
- await deleteResourceByLabel({
440
- resource: 'pods',
441
- namespace,
442
- label: 'app.kubernetes.io/name=bot'
443
- }).catch(()=>undefined);
444
- }
445
- /**
446
- * Enables or disables probabilistic transaction dropping on validators and waits for rollout.
447
- * Wired to env vars P2P_DROP_TX and P2P_DROP_TX_CHANCE via Helm values.
448
- */ export async function setValidatorTxDrop({ namespace, enabled, probability, logger }) {
449
- const drop = enabled ? 'true' : 'false';
450
- const prob = String(probability);
451
- const selectors = [
452
- 'app=validator',
453
- 'app.kubernetes.io/component=validator'
454
- ];
455
- let updated = false;
456
- for (const selector of selectors){
457
- try {
458
- const list = await execAsync(`kubectl get statefulset -l ${selector} -n ${namespace} --no-headers -o name | cat`);
459
- const names = list.stdout.split('\n').map((s)=>s.trim()).filter(Boolean);
460
- if (names.length === 0) {
461
- continue;
462
- }
463
- const cmd = `kubectl set env statefulset -l ${selector} -n ${namespace} P2P_DROP_TX=${drop} P2P_DROP_TX_CHANCE=${prob}`;
464
- logger.info(`command: ${cmd}`);
465
- await execAsync(cmd);
466
- updated = true;
467
- } catch (e) {
468
- logger.warn(`Failed to update validators with selector ${selector}: ${String(e)}`);
469
- }
470
- }
471
- if (!updated) {
472
- logger.warn(`No validator StatefulSets found in ${namespace}. Skipping tx drop toggle.`);
473
- return;
474
- }
475
- // Restart validator pods to ensure env vars take effect and wait for readiness
476
- await restartValidators(namespace, logger);
477
- }
478
- export async function restartValidators(namespace, logger) {
479
- const selectors = [
480
- 'app=validator',
481
- 'app.kubernetes.io/component=validator'
482
- ];
483
- let any = false;
484
- for (const selector of selectors){
485
- try {
486
- const { stdout } = await execAsync(`kubectl get pods -l ${selector} -n ${namespace} --no-headers -o name | cat`);
487
- if (!stdout || stdout.trim().length === 0) {
488
- continue;
489
- }
490
- any = true;
491
- await deleteResourceByLabel({
492
- resource: 'pods',
493
- namespace,
494
- label: selector
495
- });
496
- } catch (e) {
497
- logger.warn(`Error restarting validator pods with selector ${selector}: ${String(e)}`);
498
- }
499
- }
500
- if (!any) {
501
- logger.warn(`No validator pods found to restart in ${namespace}.`);
502
- return;
503
- }
504
- // Wait for either label to be Ready
505
- for (const selector of selectors){
506
- try {
507
- await waitForResourceByLabel({
508
- resource: 'pods',
509
- namespace,
510
- label: selector
511
- });
512
- return;
513
- } catch {
514
- // try next
515
- }
516
- }
517
- logger.warn(`Validator pods did not report Ready; continuing.`);
518
- }
519
- export async function enableValidatorDynamicBootNode(instanceName, namespace, spartanDir, logger) {
520
- logger.info(`Enabling validator dynamic boot node`);
521
- await execHelmCommand({
522
- instanceName,
523
- namespace,
524
- helmChartDir: getChartDir(spartanDir, 'aztec-network'),
525
- values: {
526
- 'validator.dynamicBootNode': 'true'
527
- },
528
- valuesFile: undefined,
529
- timeout: '15m',
530
- reuseValues: true
531
- });
532
- logger.info(`Validator dynamic boot node enabled`);
533
- }
534
- export async function getSequencers(namespace) {
535
- const command = `kubectl get pods -l app.kubernetes.io/component=validator -n ${namespace} -o jsonpath='{.items[*].metadata.name}'`;
536
- const { stdout } = await execAsync(command);
537
- const sequencers = stdout.split(' ');
538
- logger.verbose(`Found sequencer pods ${sequencers.join(', ')}`);
539
- return sequencers;
540
- }
541
- export function updateSequencersConfig(env, config) {
542
- return withSequencersAdmin(env, async (client)=>{
543
- await client.setConfig(config);
544
- return client.getConfig();
545
- });
546
- }
547
- export function getSequencersConfig(env) {
548
- return withSequencersAdmin(env, (client)=>client.getConfig());
549
- }
550
- export async function withSequencersAdmin(env, fn) {
551
- const adminContainerPort = 8880;
552
- const namespace = env.NAMESPACE;
553
- const sequencers = await getSequencers(namespace);
554
- const results = [];
555
- for (const sequencer of sequencers){
556
- const { process: process1, port } = await startPortForward({
557
- resource: `pod/${sequencer}`,
558
- namespace,
559
- containerPort: adminContainerPort
560
- });
561
- const url = `http://localhost:${port}`;
562
- await retry(()=>fetch(`${url}/status`).then((res)=>res.status === 200), 'forward node admin port', makeBackoff([
563
- 1,
564
- 1,
565
- 2,
566
- 6
567
- ]), logger, true);
568
- const client = createAztecNodeAdminClient(url);
569
- results.push(await fn(client));
570
- process1.kill();
571
- }
572
- return results;
573
- }
574
- /**
575
- * Returns a public viem client to the eth execution node. If it was part of a local eth devnet,
576
- * it first port-forwards the service and points to it. Otherwise, just uses the external RPC url.
577
- */ export async function getPublicViemClient(env, /** If set, will push the new process into it */ processes) {
578
- const { NAMESPACE, CREATE_ETH_DEVNET, L1_RPC_URLS_JSON } = env;
579
- if (CREATE_ETH_DEVNET) {
580
- logger.info(`Creating port forward to eth execution node`);
581
- const { process: process1, port } = await startPortForward({
582
- resource: `svc/${NAMESPACE}-eth-execution`,
583
- namespace: NAMESPACE,
584
- containerPort: 8545
585
- });
586
- const url = `http://127.0.0.1:${port}`;
587
- const client = createPublicClient({
588
- transport: fallback([
589
- http(url)
590
- ])
591
- });
592
- if (processes) {
593
- processes.push(process1);
594
- }
595
- return {
596
- url,
597
- client,
598
- process: process1
599
- };
600
- } else {
601
- logger.info(`Connecting to the eth execution node at ${L1_RPC_URLS_JSON}`);
602
- if (!L1_RPC_URLS_JSON) {
603
- throw new Error(`L1_RPC_URLS_JSON is not defined`);
604
- }
605
- const client = createPublicClient({
606
- transport: fallback([
607
- http(L1_RPC_URLS_JSON)
608
- ])
609
- });
610
- return {
611
- url: L1_RPC_URLS_JSON,
612
- client
613
- };
614
- }
615
- }
616
- /** Queries an Aztec node for the L1 deployment addresses */ export async function getL1DeploymentAddresses(env) {
617
- let forwardProcess;
618
- try {
619
- const [sequencer] = await getSequencers(env.NAMESPACE);
620
- const { process: process1, port } = await startPortForward({
621
- resource: `pod/${sequencer}`,
622
- namespace: env.NAMESPACE,
623
- containerPort: 8080
624
- });
625
- forwardProcess = process1;
626
- const url = `http://127.0.0.1:${port}`;
627
- const node = createAztecNodeClient(url);
628
- return await retry(()=>node.getNodeInfo().then((i)=>i.l1ContractAddresses), 'get node info', makeBackoff([
629
- 1,
630
- 3,
631
- 6
632
- ]), logger);
633
- } finally{
634
- forwardProcess?.kill();
635
- }
636
- }
637
- /**
638
- * Rolls the Aztec pods in the given namespace.
639
- * @param namespace - The namespace to roll the Aztec pods in.
640
- * @dev - IMPORTANT: This function DOES NOT delete the underlying PVCs.
641
- * This means that the pods will be restarted with the same persistent storage.
642
- * This is useful for testing, but you should be aware of the implications.
643
- */ export async function rollAztecPods(namespace) {
644
- await deleteResourceByLabel({
645
- resource: 'pods',
646
- namespace: namespace,
647
- label: 'app=boot-node'
648
- });
649
- await deleteResourceByLabel({
650
- resource: 'pods',
651
- namespace: namespace,
652
- label: 'app=prover-node'
653
- });
654
- await deleteResourceByLabel({
655
- resource: 'pods',
656
- namespace: namespace,
657
- label: 'app=prover-broker'
658
- });
659
- await deleteResourceByLabel({
660
- resource: 'pods',
661
- namespace: namespace,
662
- label: 'app=prover-agent'
663
- });
664
- await deleteResourceByLabel({
665
- resource: 'pods',
666
- namespace: namespace,
667
- label: 'app=validator'
668
- });
669
- await deleteResourceByLabel({
670
- resource: 'pods',
671
- namespace: namespace,
672
- label: 'app=pxe'
673
- });
674
- await sleep(10 * 1000);
675
- await waitForResourceByLabel({
676
- resource: 'pods',
677
- namespace: namespace,
678
- label: 'app=boot-node'
679
- });
680
- await waitForResourceByLabel({
681
- resource: 'pods',
682
- namespace: namespace,
683
- label: 'app=prover-node'
684
- });
685
- await waitForResourceByLabel({
686
- resource: 'pods',
687
- namespace: namespace,
688
- label: 'app=prover-broker'
689
- });
690
- await waitForResourceByLabel({
691
- resource: 'pods',
692
- namespace: namespace,
693
- label: 'app=prover-agent'
694
- });
695
- await waitForResourceByLabel({
696
- resource: 'pods',
697
- namespace: namespace,
698
- label: 'app=validator'
699
- });
700
- await waitForResourceByLabel({
701
- resource: 'pods',
702
- namespace: namespace,
703
- label: 'app=pxe'
704
- });
705
- }
706
- /**
707
- * Returns the absolute path to the git repository root
708
- */ export function getGitProjectRoot() {
709
- try {
710
- const rootDir = execSync('git rev-parse --show-toplevel', {
711
- encoding: 'utf-8',
712
- stdio: [
713
- 'ignore',
714
- 'pipe',
715
- 'ignore'
716
- ]
717
- }).trim();
718
- return rootDir;
719
- } catch (error) {
720
- throw new Error(`Failed to determine git project root: ${error}`);
721
- }
722
- }
723
- /** Returns a client to the RPC of the given sequencer (defaults to first) */ export async function getNodeClient(env, index = 0) {
724
- const namespace = env.NAMESPACE;
725
- const containerPort = 8080;
726
- const sequencers = await getSequencers(namespace);
727
- const sequencer = sequencers[index];
728
- if (!sequencer) {
729
- throw new Error(`No sequencer found at index ${index} in namespace ${namespace}`);
730
- }
731
- const { process: process1, port } = await startPortForward({
732
- resource: `pod/${sequencer}`,
733
- namespace,
734
- containerPort
735
- });
736
- const url = `http://localhost:${port}`;
737
- await retry(()=>fetch(`${url}/status`).then((res)=>res.status === 200), 'forward port', makeBackoff([
738
- 1,
739
- 1,
740
- 2,
741
- 6
742
- ]), logger, true);
743
- const client = createAztecNodeClient(url);
744
- return {
745
- node: client,
746
- port,
747
- process: process1
748
- };
749
- }
1
+ export * from './utils/index.js';