@aztec/end-to-end 0.0.1-commit.b655e406 → 0.0.1-commit.c7c42ec

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 (150) hide show
  1. package/dest/bench/client_flows/benchmark.d.ts +1 -1
  2. package/dest/bench/client_flows/benchmark.d.ts.map +1 -1
  3. package/dest/bench/client_flows/client_flows_benchmark.d.ts +10 -3
  4. package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
  5. package/dest/bench/client_flows/client_flows_benchmark.js +58 -33
  6. package/dest/bench/client_flows/config.d.ts +1 -1
  7. package/dest/bench/client_flows/data_extractor.d.ts +1 -1
  8. package/dest/bench/client_flows/data_extractor.js +5 -27
  9. package/dest/bench/utils.d.ts +3 -3
  10. package/dest/bench/utils.d.ts.map +1 -1
  11. package/dest/bench/utils.js +10 -6
  12. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +1 -1
  13. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
  14. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +2 -2
  15. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +5 -4
  16. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts.map +1 -1
  17. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.js +6 -4
  18. package/dest/e2e_deploy_contract/deploy_test.d.ts +2 -2
  19. package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -1
  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 +17 -14
  23. package/dest/e2e_fees/bridging_race.notest.d.ts +1 -1
  24. package/dest/e2e_fees/bridging_race.notest.js +2 -2
  25. package/dest/e2e_fees/fees_test.d.ts +8 -4
  26. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  27. package/dest/e2e_fees/fees_test.js +16 -10
  28. package/dest/e2e_l1_publisher/write_json.d.ts +1 -1
  29. package/dest/e2e_l1_publisher/write_json.d.ts.map +1 -1
  30. package/dest/e2e_l1_publisher/write_json.js +5 -4
  31. package/dest/e2e_multi_validator/utils.d.ts +1 -1
  32. package/dest/e2e_multi_validator/utils.js +1 -1
  33. package/dest/e2e_nested_contract/nested_contract_test.d.ts +1 -1
  34. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
  35. package/dest/e2e_nested_contract/nested_contract_test.js +4 -3
  36. package/dest/e2e_p2p/inactivity_slash_test.d.ts +3 -3
  37. package/dest/e2e_p2p/inactivity_slash_test.d.ts.map +1 -1
  38. package/dest/e2e_p2p/inactivity_slash_test.js +4 -3
  39. package/dest/e2e_p2p/p2p_network.d.ts +219 -13
  40. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  41. package/dest/e2e_p2p/p2p_network.js +15 -11
  42. package/dest/e2e_p2p/shared.d.ts +6 -6
  43. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  44. package/dest/e2e_p2p/shared.js +6 -5
  45. package/dest/e2e_token_contract/token_contract_test.d.ts +1 -1
  46. package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
  47. package/dest/e2e_token_contract/token_contract_test.js +2 -2
  48. package/dest/fixtures/e2e_prover_test.d.ts +5 -5
  49. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  50. package/dest/fixtures/e2e_prover_test.js +23 -22
  51. package/dest/fixtures/fixtures.d.ts +2 -3
  52. package/dest/fixtures/fixtures.d.ts.map +1 -1
  53. package/dest/fixtures/fixtures.js +2 -3
  54. package/dest/fixtures/get_acvm_config.d.ts +1 -1
  55. package/dest/fixtures/get_acvm_config.js +1 -1
  56. package/dest/fixtures/get_bb_config.d.ts +1 -1
  57. package/dest/fixtures/get_bb_config.d.ts.map +1 -1
  58. package/dest/fixtures/index.d.ts +1 -1
  59. package/dest/fixtures/l1_to_l2_messaging.d.ts +4 -3
  60. package/dest/fixtures/l1_to_l2_messaging.d.ts.map +1 -1
  61. package/dest/fixtures/l1_to_l2_messaging.js +2 -2
  62. package/dest/fixtures/logging.d.ts +1 -1
  63. package/dest/fixtures/setup_p2p_test.d.ts +4 -4
  64. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  65. package/dest/fixtures/setup_p2p_test.js +18 -10
  66. package/dest/fixtures/snapshot_manager.d.ts +6 -8
  67. package/dest/fixtures/snapshot_manager.d.ts.map +1 -1
  68. package/dest/fixtures/snapshot_manager.js +34 -46
  69. package/dest/fixtures/token_utils.d.ts +5 -2
  70. package/dest/fixtures/token_utils.d.ts.map +1 -1
  71. package/dest/fixtures/token_utils.js +7 -4
  72. package/dest/fixtures/utils.d.ts +21 -19
  73. package/dest/fixtures/utils.d.ts.map +1 -1
  74. package/dest/fixtures/utils.js +56 -85
  75. package/dest/fixtures/web3signer.d.ts +1 -1
  76. package/dest/fixtures/web3signer.js +1 -1
  77. package/dest/fixtures/with_telemetry_utils.d.ts +2 -2
  78. package/dest/fixtures/with_telemetry_utils.d.ts.map +1 -1
  79. package/dest/fixtures/with_telemetry_utils.js +2 -2
  80. package/dest/index.d.ts +1 -1
  81. package/dest/quality_of_service/alert_checker.d.ts +1 -1
  82. package/dest/quality_of_service/alert_checker.d.ts.map +1 -1
  83. package/dest/shared/cross_chain_test_harness.d.ts +5 -14
  84. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
  85. package/dest/shared/cross_chain_test_harness.js +1 -1
  86. package/dest/shared/gas_portal_test_harness.d.ts +2 -12
  87. package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
  88. package/dest/shared/gas_portal_test_harness.js +1 -1
  89. package/dest/shared/index.d.ts +1 -1
  90. package/dest/shared/jest_setup.d.ts +1 -1
  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/uniswap_l1_l2.d.ts +4 -3
  94. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  95. package/dest/shared/uniswap_l1_l2.js +15 -13
  96. package/dest/simulators/index.d.ts +1 -1
  97. package/dest/simulators/lending_simulator.d.ts +2 -6
  98. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  99. package/dest/simulators/lending_simulator.js +5 -3
  100. package/dest/simulators/token_simulator.d.ts +1 -1
  101. package/dest/simulators/token_simulator.d.ts.map +1 -1
  102. package/dest/spartan/setup_test_wallets.d.ts +5 -3
  103. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  104. package/dest/spartan/setup_test_wallets.js +45 -10
  105. package/dest/spartan/tx_metrics.d.ts +39 -0
  106. package/dest/spartan/tx_metrics.d.ts.map +1 -0
  107. package/dest/spartan/tx_metrics.js +95 -0
  108. package/dest/spartan/utils.d.ts +55 -20
  109. package/dest/spartan/utils.d.ts.map +1 -1
  110. package/dest/spartan/utils.js +203 -60
  111. package/package.json +42 -40
  112. package/src/bench/client_flows/client_flows_benchmark.ts +82 -34
  113. package/src/bench/client_flows/data_extractor.ts +6 -28
  114. package/src/bench/utils.ts +11 -7
  115. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +2 -2
  116. package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +17 -12
  117. package/src/e2e_deploy_contract/deploy_test.ts +1 -1
  118. package/src/e2e_epochs/epochs_test.ts +37 -23
  119. package/src/e2e_fees/bridging_race.notest.ts +2 -2
  120. package/src/e2e_fees/fees_test.ts +22 -13
  121. package/src/e2e_l1_publisher/write_json.ts +5 -4
  122. package/src/e2e_multi_validator/utils.ts +1 -1
  123. package/src/e2e_nested_contract/nested_contract_test.ts +4 -3
  124. package/src/e2e_p2p/inactivity_slash_test.ts +5 -4
  125. package/src/e2e_p2p/p2p_network.ts +16 -19
  126. package/src/e2e_p2p/shared.ts +13 -6
  127. package/src/e2e_token_contract/token_contract_test.ts +2 -2
  128. package/src/fixtures/e2e_prover_test.ts +22 -25
  129. package/src/fixtures/fixtures.ts +2 -5
  130. package/src/fixtures/get_acvm_config.ts +1 -1
  131. package/src/fixtures/l1_to_l2_messaging.ts +4 -2
  132. package/src/fixtures/setup_p2p_test.ts +23 -9
  133. package/src/fixtures/snapshot_manager.ts +51 -65
  134. package/src/fixtures/token_utils.ts +4 -4
  135. package/src/fixtures/utils.ts +91 -131
  136. package/src/fixtures/web3signer.ts +1 -1
  137. package/src/fixtures/with_telemetry_utils.ts +2 -2
  138. package/src/guides/up_quick_start.sh +1 -1
  139. package/src/shared/cross_chain_test_harness.ts +5 -2
  140. package/src/shared/gas_portal_test_harness.ts +2 -2
  141. package/src/shared/uniswap_l1_l2.ts +19 -21
  142. package/src/simulators/lending_simulator.ts +6 -4
  143. package/src/spartan/DEVELOP.md +7 -0
  144. package/src/spartan/setup_test_wallets.ts +49 -12
  145. package/src/spartan/tx_metrics.ts +130 -0
  146. package/src/spartan/utils.ts +267 -51
  147. package/dest/fixtures/setup_l1_contracts.d.ts +0 -6
  148. package/dest/fixtures/setup_l1_contracts.d.ts.map +0 -1
  149. package/dest/fixtures/setup_l1_contracts.js +0 -17
  150. package/src/fixtures/setup_l1_contracts.ts +0 -26
@@ -1,7 +1,10 @@
1
1
  import { createLogger } from '@aztec/aztec.js/log';
2
2
  import type { RollupCheatCodes } from '@aztec/aztec/testing';
3
- import type { L1ContractAddresses, ViemPublicClient } from '@aztec/ethereum';
3
+ import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
4
+ import type { ViemPublicClient } from '@aztec/ethereum/types';
5
+ import type { CheckpointNumber } from '@aztec/foundation/branded-types';
4
6
  import type { Logger } from '@aztec/foundation/log';
7
+ import { promiseWithResolvers } from '@aztec/foundation/promise';
5
8
  import { makeBackoff, retry } from '@aztec/foundation/retry';
6
9
  import { schemas } from '@aztec/foundation/schemas';
7
10
  import { sleep } from '@aztec/foundation/sleep';
@@ -29,6 +32,7 @@ const testConfigSchema = z.object({
29
32
  L1_RPC_URLS_JSON: z.string().optional(),
30
33
  L1_ACCOUNT_MNEMONIC: z.string().optional(),
31
34
  AZTEC_SLOT_DURATION: z.coerce.number().optional().default(24),
35
+ AZTEC_EPOCH_DURATION: z.coerce.number().optional().default(32),
32
36
  AZTEC_PROOF_SUBMISSION_WINDOW: z.coerce.number().optional().default(5),
33
37
  });
34
38
 
@@ -160,9 +164,42 @@ export async function startPortForward({
160
164
  return { process, port };
161
165
  }
162
166
 
163
- export function startPortForwardForRPC(namespace: string) {
167
+ export function getExternalIP(namespace: string, serviceName: string): Promise<string> {
168
+ const { promise, resolve, reject } = promiseWithResolvers<string>();
169
+ const process = spawn(
170
+ 'kubectl',
171
+ [
172
+ 'get',
173
+ 'service',
174
+ '-n',
175
+ namespace,
176
+ `${namespace}-${serviceName}`,
177
+ '--output',
178
+ "jsonpath='{.status.loadBalancer.ingress[0].ip}'",
179
+ ],
180
+ {
181
+ stdio: 'pipe',
182
+ },
183
+ );
184
+
185
+ let ip = '';
186
+ process.stdout.on('data', data => {
187
+ ip += data;
188
+ });
189
+ process.on('error', err => {
190
+ reject(err);
191
+ });
192
+ process.on('exit', () => {
193
+ // kubectl prints JSON. Remove the quotes
194
+ resolve(ip.replace(/"|'/g, ''));
195
+ });
196
+
197
+ return promise;
198
+ }
199
+
200
+ export function startPortForwardForRPC(namespace: string, index = 0) {
164
201
  return startPortForward({
165
- resource: `services/${namespace}-rpc-aztec-node`,
202
+ resource: `pod/${namespace}-rpc-aztec-node-${index}`,
166
203
  namespace,
167
204
  containerPort: 8080,
168
205
  });
@@ -208,11 +245,11 @@ export async function deleteResourceByLabel({
208
245
  timeout?: string;
209
246
  force?: boolean;
210
247
  }) {
211
- // Check if the resource type exists before attempting to delete
212
248
  try {
213
- await execAsync(
214
- `kubectl api-resources --api-group="" --no-headers -o name | grep -q "^${resource}$" || kubectl api-resources --no-headers -o name | grep -q "^${resource}$"`,
215
- );
249
+ // Match both plain and group-qualified names (e.g., "podchaos" or "podchaos.chaos-mesh.org")
250
+ const escaped = resource.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
251
+ const regex = `(^|\\.)${escaped}(\\.|$)`;
252
+ await execAsync(`kubectl api-resources --no-headers -o name | grep -Eq '${regex}'`);
216
253
  } catch (error) {
217
254
  logger.warn(`Resource type '${resource}' not found in cluster, skipping deletion ${error}`);
218
255
  return '';
@@ -245,6 +282,58 @@ export async function waitForResourceByLabel({
245
282
  return stdout;
246
283
  }
247
284
 
285
+ export async function waitForResourceByName({
286
+ resource,
287
+ name,
288
+ namespace,
289
+ condition = 'Ready',
290
+ timeout = '10m',
291
+ }: {
292
+ resource: string;
293
+ name: string;
294
+ namespace: string;
295
+ condition?: string;
296
+ timeout?: string;
297
+ }) {
298
+ const command = `kubectl wait ${resource}/${name} --for=condition=${condition} -n ${namespace} --timeout=${timeout}`;
299
+ logger.info(`command: ${command}`);
300
+ const { stdout } = await execAsync(command);
301
+ return stdout;
302
+ }
303
+
304
+ export async function waitForResourcesByName({
305
+ resource,
306
+ names,
307
+ namespace,
308
+ condition = 'Ready',
309
+ timeout = '10m',
310
+ }: {
311
+ resource: string;
312
+ names: string[];
313
+ namespace: string;
314
+ condition?: string;
315
+ timeout?: string;
316
+ }) {
317
+ if (!names.length) {
318
+ throw new Error(`No ${resource} names provided to waitForResourcesByName`);
319
+ }
320
+
321
+ // Wait all in parallel; if any fails, surface which one.
322
+ await Promise.all(
323
+ names.map(async name => {
324
+ try {
325
+ await waitForResourceByName({ resource, name, namespace, condition, timeout });
326
+ } catch (err) {
327
+ throw new Error(
328
+ `Failed waiting for ${resource}/${name} condition=${condition} timeout=${timeout} namespace=${namespace}: ${String(
329
+ err,
330
+ )}`,
331
+ );
332
+ }
333
+ }),
334
+ );
335
+ }
336
+
248
337
  export function getChartDir(spartanDir: string, chartName: string) {
249
338
  return path.join(spartanDir.trim(), chartName);
250
339
  }
@@ -295,6 +384,61 @@ async function execHelmCommand(args: Parameters<typeof createHelmCommand>[0]) {
295
384
  return stdout;
296
385
  }
297
386
 
387
+ async function getHelmReleaseStatus(instanceName: string, namespace: string): Promise<string | undefined> {
388
+ try {
389
+ const { stdout } = await execAsync(
390
+ `helm list --namespace ${namespace} --all --filter '^${instanceName}$' --output json | cat`,
391
+ );
392
+ const parsed = JSON.parse(stdout) as Array<{ name?: string; status?: string }>;
393
+ const row = parsed.find(r => r.name === instanceName);
394
+ return row?.status;
395
+ } catch {
396
+ return undefined;
397
+ }
398
+ }
399
+
400
+ async function forceDeleteHelmReleaseRecord(instanceName: string, namespace: string, logger: Logger) {
401
+ const labelSelector = `owner=helm,name=${instanceName}`;
402
+ const cmd = `kubectl delete secret -n ${namespace} -l ${labelSelector} --ignore-not-found=true`;
403
+ logger.warn(`Force deleting Helm release record: ${cmd}`);
404
+ await execAsync(cmd).catch(() => undefined);
405
+ }
406
+
407
+ async function hasDeployedHelmRelease(instanceName: string, namespace: string): Promise<boolean> {
408
+ try {
409
+ const status = await getHelmReleaseStatus(instanceName, namespace);
410
+ return status?.toLowerCase() === 'deployed';
411
+ } catch {
412
+ return false;
413
+ }
414
+ }
415
+
416
+ export async function uninstallChaosMesh(instanceName: string, namespace: string, logger: Logger) {
417
+ // uninstall the helm chart if it exists
418
+ logger.info(`Uninstalling helm chart ${instanceName}`);
419
+ await execAsync(`helm uninstall ${instanceName} --namespace ${namespace} --wait --ignore-not-found`);
420
+ // and delete the chaos-mesh resources created by this release
421
+ const deleteByLabel = async (resource: string) => {
422
+ const args = {
423
+ resource,
424
+ namespace: namespace,
425
+ label: `app.kubernetes.io/instance=${instanceName}`,
426
+ } as const;
427
+ logger.info(`Deleting ${resource} resources for release ${instanceName}`);
428
+ await deleteResourceByLabel(args).catch(e => {
429
+ logger.error(`Error deleting ${resource}: ${e}`);
430
+ logger.info(`Force deleting ${resource}`);
431
+ return deleteResourceByLabel({ ...args, force: true });
432
+ });
433
+ };
434
+
435
+ await deleteByLabel('podchaos');
436
+ await deleteByLabel('networkchaos');
437
+ await deleteByLabel('podnetworkchaos');
438
+ await deleteByLabel('workflows');
439
+ await deleteByLabel('workflownodes');
440
+ }
441
+
298
442
  /**
299
443
  * Installs a Helm chart with the given parameters.
300
444
  * @param instanceName - The name of the Helm chart instance.
@@ -317,7 +461,6 @@ export async function installChaosMeshChart({
317
461
  targetNamespace,
318
462
  valuesFile,
319
463
  helmChartDir,
320
- chaosMeshNamespace = 'chaos-mesh',
321
464
  timeout = '10m',
322
465
  clean = true,
323
466
  values = {},
@@ -334,32 +477,13 @@ export async function installChaosMeshChart({
334
477
  logger: Logger;
335
478
  }) {
336
479
  if (clean) {
337
- // uninstall the helm chart if it exists
338
- logger.info(`Uninstalling helm chart ${instanceName}`);
339
- await execAsync(`helm uninstall ${instanceName} --namespace ${chaosMeshNamespace} --wait --ignore-not-found`);
340
- // and delete the chaos-mesh resources created by this release
341
- const deleteByLabel = async (resource: string) => {
342
- const args = {
343
- resource,
344
- namespace: chaosMeshNamespace,
345
- label: `app.kubernetes.io/instance=${instanceName}`,
346
- } as const;
347
- logger.info(`Deleting ${resource} resources for release ${instanceName}`);
348
- await deleteResourceByLabel(args).catch(e => {
349
- logger.error(`Error deleting ${resource}: ${e}`);
350
- logger.info(`Force deleting ${resource}`);
351
- return deleteResourceByLabel({ ...args, force: true });
352
- });
353
- };
354
-
355
- await deleteByLabel('podchaos');
356
- await deleteByLabel('networkchaos');
480
+ await uninstallChaosMesh(instanceName, targetNamespace, logger);
357
481
  }
358
482
 
359
483
  return execHelmCommand({
360
484
  instanceName,
361
485
  helmChartDir,
362
- namespace: chaosMeshNamespace,
486
+ namespace: targetNamespace,
363
487
  valuesFile,
364
488
  timeout,
365
489
  values: { ...values, 'global.targetNamespace': targetNamespace },
@@ -389,22 +513,49 @@ export function applyProverFailure({
389
513
  });
390
514
  }
391
515
 
516
+ export function applyValidatorFailure({
517
+ namespace,
518
+ spartanDir,
519
+ logger,
520
+ values,
521
+ instanceName,
522
+ }: {
523
+ namespace: string;
524
+ spartanDir: string;
525
+ logger: Logger;
526
+ values?: Record<string, string | number>;
527
+ instanceName?: string;
528
+ }) {
529
+ return installChaosMeshChart({
530
+ instanceName: instanceName ?? 'validator-failure',
531
+ targetNamespace: namespace,
532
+ valuesFile: 'validator-failure.yaml',
533
+ helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
534
+ values,
535
+ logger,
536
+ });
537
+ }
538
+
392
539
  export function applyProverKill({
393
540
  namespace,
394
541
  spartanDir,
395
542
  logger,
543
+ values,
396
544
  }: {
397
545
  namespace: string;
398
546
  spartanDir: string;
399
547
  logger: Logger;
548
+ values?: Record<string, string | number>;
400
549
  }) {
401
550
  return installChaosMeshChart({
402
551
  instanceName: 'prover-kill',
403
552
  targetNamespace: namespace,
404
553
  valuesFile: 'prover-kill.yaml',
405
554
  helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
555
+ chaosMeshNamespace: namespace,
406
556
  clean: true,
407
557
  logger,
558
+ values,
408
559
  });
409
560
  }
410
561
 
@@ -412,10 +563,12 @@ export function applyProverBrokerKill({
412
563
  namespace,
413
564
  spartanDir,
414
565
  logger,
566
+ values,
415
567
  }: {
416
568
  namespace: string;
417
569
  spartanDir: string;
418
570
  logger: Logger;
571
+ values?: Record<string, string | number>;
419
572
  }) {
420
573
  return installChaosMeshChart({
421
574
  instanceName: 'prover-broker-kill',
@@ -424,66 +577,79 @@ export function applyProverBrokerKill({
424
577
  helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
425
578
  clean: true,
426
579
  logger,
580
+ values,
427
581
  });
428
582
  }
429
583
 
430
584
  export function applyBootNodeFailure({
585
+ instanceName = 'boot-node-failure',
431
586
  namespace,
432
587
  spartanDir,
433
588
  durationSeconds,
434
589
  logger,
590
+ values,
435
591
  }: {
592
+ instanceName?: string;
436
593
  namespace: string;
437
594
  spartanDir: string;
438
595
  durationSeconds: number;
439
596
  logger: Logger;
597
+ values?: Record<string, string | number>;
440
598
  }) {
441
599
  return installChaosMeshChart({
442
- instanceName: 'boot-node-failure',
600
+ instanceName,
443
601
  targetNamespace: namespace,
444
602
  valuesFile: 'boot-node-failure.yaml',
445
603
  helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
446
604
  values: {
447
605
  'bootNodeFailure.duration': `${durationSeconds}s`,
606
+ ...(values ?? {}),
448
607
  },
449
608
  logger,
450
609
  });
451
610
  }
452
611
 
453
612
  export function applyValidatorKill({
613
+ instanceName = 'validator-kill',
454
614
  namespace,
455
615
  spartanDir,
456
616
  logger,
457
617
  values,
618
+ clean = true,
458
619
  }: {
620
+ instanceName?: string;
459
621
  namespace: string;
460
622
  spartanDir: string;
461
623
  logger: Logger;
462
624
  values?: Record<string, string | number>;
625
+ clean?: boolean;
463
626
  }) {
464
627
  return installChaosMeshChart({
465
- instanceName: 'validator-kill',
628
+ instanceName: instanceName ?? 'validator-kill',
466
629
  targetNamespace: namespace,
467
630
  valuesFile: 'validator-kill.yaml',
468
631
  helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
632
+ clean,
469
633
  logger,
470
634
  values,
471
635
  });
472
636
  }
473
637
 
474
638
  export function applyNetworkShaping({
639
+ instanceName = 'network-shaping',
475
640
  valuesFile,
476
641
  namespace,
477
642
  spartanDir,
478
643
  logger,
479
644
  }: {
645
+ instanceName?: string;
480
646
  valuesFile: string;
481
647
  namespace: string;
482
648
  spartanDir: string;
483
649
  logger: Logger;
484
650
  }) {
485
651
  return installChaosMeshChart({
486
- instanceName: 'network-shaping',
652
+ instanceName,
487
653
  targetNamespace: namespace,
488
654
  valuesFile,
489
655
  helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
@@ -491,24 +657,24 @@ export function applyNetworkShaping({
491
657
  });
492
658
  }
493
659
 
494
- export async function awaitL2BlockNumber(
660
+ export async function awaitCheckpointNumber(
495
661
  rollupCheatCodes: RollupCheatCodes,
496
- blockNumber: bigint,
662
+ checkpointNumber: CheckpointNumber,
497
663
  timeoutSeconds: number,
498
664
  logger: Logger,
499
665
  ) {
500
- logger.info(`Waiting for L2 Block ${blockNumber}`);
666
+ logger.info(`Waiting for checkpoint ${checkpointNumber}`);
501
667
  let tips = await rollupCheatCodes.getTips();
502
668
  const endTime = Date.now() + timeoutSeconds * 1000;
503
- while (tips.pending < blockNumber && Date.now() < endTime) {
504
- logger.info(`At L2 Block ${tips.pending}`);
669
+ while (tips.pending < checkpointNumber && Date.now() < endTime) {
670
+ logger.info(`At checkpoint ${tips.pending}`);
505
671
  await sleep(1000);
506
672
  tips = await rollupCheatCodes.getTips();
507
673
  }
508
- if (tips.pending < blockNumber) {
509
- throw new Error(`Timeout waiting for L2 Block ${blockNumber}, only reached ${tips.pending}`);
674
+ if (tips.pending < checkpointNumber) {
675
+ throw new Error(`Timeout waiting for checkpoint ${checkpointNumber}, only reached ${tips.pending}`);
510
676
  } else {
511
- logger.info(`Reached L2 Block ${tips.pending}`);
677
+ logger.info(`Reached checkpoint ${tips.pending}`);
512
678
  }
513
679
  }
514
680
 
@@ -582,6 +748,12 @@ export async function installTransferBot({
582
748
  'bot.node.env.ETHEREUM_HOSTS': `http://${namespace}-eth-execution.${namespace}.svc.cluster.local:8545`,
583
749
  // Provide L1 mnemonic for bridging (falls back to labs mnemonic)
584
750
  'bot.node.env.BOT_L1_MNEMONIC': mnemonic,
751
+
752
+ // The bot does not need Kubernetes API access. Disable RBAC + ServiceAccount creation so the chart
753
+ // can be installed by users without cluster-scoped RBAC permissions.
754
+ 'bot.rbac.create': false,
755
+ 'bot.serviceAccount.create': false,
756
+ 'bot.serviceAccount.name': 'default',
585
757
  };
586
758
  // Ensure we derive a funded L1 key (index 0 is funded on anvil default mnemonic)
587
759
  if (mnemonicStartIndex === undefined) {
@@ -606,7 +778,7 @@ export async function installTransferBot({
606
778
  if (!repository || !tag) {
607
779
  try {
608
780
  const { stdout } = await execAsync(
609
- `kubectl get pods -l app.kubernetes.io/component=validator -n ${namespace} -o jsonpath='{.items[0].spec.containers[?(@.name=="aztec")].image}' | cat`,
781
+ `kubectl get pods -l app.kubernetes.io/name=validator -n ${namespace} -o jsonpath='{.items[0].spec.containers[?(@.name=="aztec")].image}' | cat`,
610
782
  );
611
783
  const image = stdout.trim().replace(/^'|'$/g, '');
612
784
  if (image && image.includes(':')) {
@@ -627,6 +799,26 @@ export async function installTransferBot({
627
799
  typeof mnemonicStartIndex === 'string' ? mnemonicStartIndex : Number(mnemonicStartIndex);
628
800
  }
629
801
 
802
+ // If a previous install attempt left the release in a non-deployed state (e.g. FAILED),
803
+ // `helm upgrade --install` can error with "has no deployed releases".
804
+ // In that case, clear the release record and do a clean install.
805
+ const existingStatus = await getHelmReleaseStatus(instanceName, namespace);
806
+ if (existingStatus && existingStatus.toLowerCase() !== 'deployed') {
807
+ logger.warn(`Transfer bot release ${instanceName} is in status '${existingStatus}'. Reinstalling cleanly.`);
808
+ await execAsync(`helm uninstall ${instanceName} --namespace ${namespace} --wait --ignore-not-found`).catch(
809
+ () => undefined,
810
+ );
811
+ // If helm left the release in `uninstalling`, force-delete the record so we can reinstall.
812
+ const afterUninstallStatus = await getHelmReleaseStatus(instanceName, namespace);
813
+ if (afterUninstallStatus?.toLowerCase() === 'uninstalling') {
814
+ await forceDeleteHelmReleaseRecord(instanceName, namespace, logger);
815
+ }
816
+ }
817
+
818
+ // `--reuse-values` fails if the release has never successfully deployed (e.g. first install, or a previous failed install).
819
+ // Only reuse values when we have a deployed release to reuse from.
820
+ const effectiveReuseValues = reuseValues && (await hasDeployedHelmRelease(instanceName, namespace));
821
+
630
822
  await execHelmCommand({
631
823
  instanceName,
632
824
  helmChartDir,
@@ -634,7 +826,7 @@ export async function installTransferBot({
634
826
  valuesFile: undefined,
635
827
  timeout,
636
828
  values: values as unknown as Record<string, string | number | boolean>,
637
- reuseValues,
829
+ reuseValues: effectiveReuseValues,
638
830
  });
639
831
 
640
832
  if (replicas > 0) {
@@ -679,7 +871,7 @@ export async function setValidatorTxDrop({
679
871
  const drop = enabled ? 'true' : 'false';
680
872
  const prob = String(probability);
681
873
 
682
- const selectors = ['app=validator', 'app.kubernetes.io/component=validator'];
874
+ const selectors = ['app.kubernetes.io/name=validator', 'app.kubernetes.io/component=validator', 'app=validator'];
683
875
  let updated = false;
684
876
  for (const selector of selectors) {
685
877
  try {
@@ -710,7 +902,7 @@ export async function setValidatorTxDrop({
710
902
  }
711
903
 
712
904
  export async function restartValidators(namespace: string, logger: Logger) {
713
- const selectors = ['app=validator', 'app.kubernetes.io/component=validator'];
905
+ const selectors = ['app.kubernetes.io/name=validator', 'app.kubernetes.io/component=validator', 'app=validator'];
714
906
  let any = false;
715
907
  for (const selector of selectors) {
716
908
  try {
@@ -765,11 +957,33 @@ export async function enableValidatorDynamicBootNode(
765
957
  }
766
958
 
767
959
  export async function getSequencers(namespace: string) {
768
- const command = `kubectl get pods -l app.kubernetes.io/component=validator -n ${namespace} -o jsonpath='{.items[*].metadata.name}'`;
769
- const { stdout } = await execAsync(command);
770
- const sequencers = stdout.split(' ');
771
- logger.verbose(`Found sequencer pods ${sequencers.join(', ')}`);
772
- return sequencers;
960
+ const selectors = [
961
+ 'app.kubernetes.io/name=validator',
962
+ 'app.kubernetes.io/component=validator',
963
+ 'app.kubernetes.io/component=sequencer-node',
964
+ 'app=validator',
965
+ ];
966
+ for (const selector of selectors) {
967
+ try {
968
+ const command = `kubectl get pods -l ${selector} -n ${namespace} -o jsonpath='{.items[*].metadata.name}'`;
969
+ const { stdout } = await execAsync(command);
970
+ const sequencers = stdout
971
+ .split(' ')
972
+ .map(s => s.trim())
973
+ .filter(Boolean);
974
+ if (sequencers.length > 0) {
975
+ logger.verbose(`Found sequencer pods ${sequencers.join(', ')} (selector=${selector})`);
976
+ return sequencers;
977
+ }
978
+ } catch {
979
+ // try next selector
980
+ }
981
+ }
982
+
983
+ // Fail fast instead of returning [''] which leads to attempts to port-forward `pod/`.
984
+ throw new Error(
985
+ `No sequencer/validator pods found in namespace ${namespace}. Tried selectors: ${selectors.join(', ')}`,
986
+ );
773
987
  }
774
988
 
775
989
  export function updateSequencersConfig(env: TestConfig, config: Partial<AztecNodeAdminConfig>) {
@@ -830,7 +1044,7 @@ export async function getPublicViemClient(
830
1044
  containerPort: 8545,
831
1045
  });
832
1046
  const url = `http://127.0.0.1:${port}`;
833
- const client: ViemPublicClient = createPublicClient({ transport: fallback([http(url)]) });
1047
+ const client: ViemPublicClient = createPublicClient({ transport: fallback([http(url, { batch: false })]) });
834
1048
  if (processes) {
835
1049
  processes.push(process);
836
1050
  }
@@ -840,7 +1054,9 @@ export async function getPublicViemClient(
840
1054
  if (!L1_RPC_URLS_JSON) {
841
1055
  throw new Error(`L1_RPC_URLS_JSON is not defined`);
842
1056
  }
843
- const client: ViemPublicClient = createPublicClient({ transport: fallback([http(L1_RPC_URLS_JSON)]) });
1057
+ const client: ViemPublicClient = createPublicClient({
1058
+ transport: fallback([http(L1_RPC_URLS_JSON, { batch: false })]),
1059
+ });
844
1060
  return { url: L1_RPC_URLS_JSON, client };
845
1061
  }
846
1062
  }
@@ -1,6 +0,0 @@
1
- import type { Logger } from '@aztec/aztec.js/log';
2
- import { type DeployL1ContractsArgs, type L1ContractsConfig } from '@aztec/ethereum';
3
- import type { HDAccount, PrivateKeyAccount } from 'viem';
4
- export { deployAndInitializeTokenAndBridgeContracts } from '../shared/cross_chain_test_harness.js';
5
- export declare const setupL1Contracts: (l1RpcUrl: string, account: HDAccount | PrivateKeyAccount, logger: Logger, args: Pick<DeployL1ContractsArgs, "genesisArchiveRoot" | "initialValidators"> & L1ContractsConfig) => Promise<import("@aztec/ethereum").DeployL1ContractsReturnType>;
6
- //# sourceMappingURL=setup_l1_contracts.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"setup_l1_contracts.d.ts","sourceRoot":"","sources":["../../src/fixtures/setup_l1_contracts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,iBAAiB,EAAqB,MAAM,iBAAiB,CAAC;AAIxG,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAGzD,OAAO,EAAE,0CAA0C,EAAE,MAAM,uCAAuC,CAAC;AAEnG,eAAO,MAAM,gBAAgB,GAC3B,UAAU,MAAM,EAChB,SAAS,SAAS,GAAG,iBAAiB,EACtC,QAAQ,MAAM,EACd,MAAM,IAAI,CAAC,qBAAqB,EAAE,oBAAoB,GAAG,mBAAmB,CAAC,GAAG,iBAAiB,mEAWlG,CAAC"}
@@ -1,17 +0,0 @@
1
- import { deployL1Contracts } from '@aztec/ethereum';
2
- import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
3
- import { protocolContractsHash } from '@aztec/protocol-contracts';
4
- import { foundry } from 'viem/chains';
5
- export { deployAndInitializeTokenAndBridgeContracts } from '../shared/cross_chain_test_harness.js';
6
- export const setupL1Contracts = async (l1RpcUrl, account, logger, args)=>{
7
- const l1Data = await deployL1Contracts([
8
- l1RpcUrl
9
- ], account, foundry, logger, {
10
- vkTreeRoot: getVKTreeRoot(),
11
- protocolContractsHash,
12
- salt: undefined,
13
- realVerifier: false,
14
- ...args
15
- });
16
- return l1Data;
17
- };
@@ -1,26 +0,0 @@
1
- import type { Logger } from '@aztec/aztec.js/log';
2
- import { type DeployL1ContractsArgs, type L1ContractsConfig, deployL1Contracts } from '@aztec/ethereum';
3
- import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
4
- import { protocolContractsHash } from '@aztec/protocol-contracts';
5
-
6
- import type { HDAccount, PrivateKeyAccount } from 'viem';
7
- import { foundry } from 'viem/chains';
8
-
9
- export { deployAndInitializeTokenAndBridgeContracts } from '../shared/cross_chain_test_harness.js';
10
-
11
- export const setupL1Contracts = async (
12
- l1RpcUrl: string,
13
- account: HDAccount | PrivateKeyAccount,
14
- logger: Logger,
15
- args: Pick<DeployL1ContractsArgs, 'genesisArchiveRoot' | 'initialValidators'> & L1ContractsConfig,
16
- ) => {
17
- const l1Data = await deployL1Contracts([l1RpcUrl], account, foundry, logger, {
18
- vkTreeRoot: getVKTreeRoot(),
19
- protocolContractsHash,
20
- salt: undefined,
21
- realVerifier: false,
22
- ...args,
23
- });
24
-
25
- return l1Data;
26
- };