@aztec/end-to-end 3.0.0-canary.a9708bd → 3.0.0-devnet.2

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 (137) 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/client_flows_benchmark.d.ts +16 -12
  4. package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
  5. package/dest/bench/client_flows/client_flows_benchmark.js +54 -58
  6. package/dest/bench/utils.d.ts +2 -11
  7. package/dest/bench/utils.d.ts.map +1 -1
  8. package/dest/bench/utils.js +10 -34
  9. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +7 -7
  10. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
  11. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +42 -42
  12. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +10 -8
  13. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts.map +1 -1
  14. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.js +31 -33
  15. package/dest/e2e_deploy_contract/deploy_test.d.ts +10 -4
  16. package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -1
  17. package/dest/e2e_deploy_contract/deploy_test.js +9 -18
  18. package/dest/e2e_epochs/epochs_test.d.ts +9 -3
  19. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  20. package/dest/e2e_epochs/epochs_test.js +19 -13
  21. package/dest/e2e_fees/bridging_race.notest.js +12 -9
  22. package/dest/e2e_fees/fees_test.d.ts +5 -5
  23. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  24. package/dest/e2e_fees/fees_test.js +26 -33
  25. package/dest/e2e_l1_publisher/write_json.d.ts +3 -1
  26. package/dest/e2e_l1_publisher/write_json.d.ts.map +1 -1
  27. package/dest/e2e_l1_publisher/write_json.js +5 -5
  28. package/dest/e2e_multi_validator/utils.d.ts +1 -1
  29. package/dest/e2e_multi_validator/utils.d.ts.map +1 -1
  30. package/dest/e2e_multi_validator/utils.js +3 -9
  31. package/dest/e2e_nested_contract/nested_contract_test.d.ts +6 -3
  32. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
  33. package/dest/e2e_nested_contract/nested_contract_test.js +7 -9
  34. package/dest/e2e_p2p/inactivity_slash_test.d.ts +31 -0
  35. package/dest/e2e_p2p/inactivity_slash_test.d.ts.map +1 -0
  36. package/dest/e2e_p2p/inactivity_slash_test.js +135 -0
  37. package/dest/e2e_p2p/p2p_network.d.ts +22 -8
  38. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  39. package/dest/e2e_p2p/p2p_network.js +36 -15
  40. package/dest/e2e_p2p/shared.d.ts +12 -13
  41. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  42. package/dest/e2e_p2p/shared.js +54 -54
  43. package/dest/e2e_token_contract/token_contract_test.d.ts +5 -4
  44. package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
  45. package/dest/e2e_token_contract/token_contract_test.js +14 -17
  46. package/dest/fixtures/e2e_prover_test.d.ts +8 -6
  47. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  48. package/dest/fixtures/e2e_prover_test.js +42 -51
  49. package/dest/fixtures/get_acvm_config.d.ts +1 -1
  50. package/dest/fixtures/get_acvm_config.d.ts.map +1 -1
  51. package/dest/fixtures/get_bb_config.d.ts +1 -1
  52. package/dest/fixtures/get_bb_config.d.ts.map +1 -1
  53. package/dest/fixtures/get_bb_config.js +2 -2
  54. package/dest/fixtures/setup_l1_contracts.d.ts +1 -1
  55. package/dest/fixtures/setup_l1_contracts.d.ts.map +1 -1
  56. package/dest/fixtures/setup_l1_contracts.js +2 -2
  57. package/dest/fixtures/setup_p2p_test.d.ts +10 -9
  58. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  59. package/dest/fixtures/setup_p2p_test.js +38 -20
  60. package/dest/fixtures/snapshot_manager.d.ts +10 -7
  61. package/dest/fixtures/snapshot_manager.d.ts.map +1 -1
  62. package/dest/fixtures/snapshot_manager.js +60 -47
  63. package/dest/fixtures/token_utils.d.ts +6 -4
  64. package/dest/fixtures/token_utils.d.ts.map +1 -1
  65. package/dest/fixtures/token_utils.js +11 -15
  66. package/dest/fixtures/utils.d.ts +26 -28
  67. package/dest/fixtures/utils.d.ts.map +1 -1
  68. package/dest/fixtures/utils.js +83 -109
  69. package/dest/fixtures/web3signer.d.ts +5 -0
  70. package/dest/fixtures/web3signer.d.ts.map +1 -0
  71. package/dest/fixtures/web3signer.js +53 -0
  72. package/dest/quality_of_service/alert_checker.d.ts +1 -1
  73. package/dest/quality_of_service/alert_checker.d.ts.map +1 -1
  74. package/dest/shared/cross_chain_test_harness.d.ts +16 -10
  75. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
  76. package/dest/shared/cross_chain_test_harness.js +13 -15
  77. package/dest/shared/gas_portal_test_harness.d.ts +9 -6
  78. package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
  79. package/dest/shared/gas_portal_test_harness.js +10 -7
  80. package/dest/shared/jest_setup.js +1 -1
  81. package/dest/shared/submit-transactions.d.ts +5 -3
  82. package/dest/shared/submit-transactions.d.ts.map +1 -1
  83. package/dest/shared/submit-transactions.js +8 -7
  84. package/dest/shared/uniswap_l1_l2.d.ts +9 -6
  85. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  86. package/dest/shared/uniswap_l1_l2.js +29 -45
  87. package/dest/simulators/lending_simulator.d.ts +2 -1
  88. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  89. package/dest/simulators/lending_simulator.js +3 -2
  90. package/dest/simulators/token_simulator.d.ts +3 -1
  91. package/dest/simulators/token_simulator.d.ts.map +1 -1
  92. package/dest/simulators/token_simulator.js +2 -2
  93. package/dest/spartan/setup_test_wallets.d.ts +19 -13
  94. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  95. package/dest/spartan/setup_test_wallets.js +108 -85
  96. package/dest/spartan/utils.d.ts +68 -3
  97. package/dest/spartan/utils.d.ts.map +1 -1
  98. package/dest/spartan/utils.js +312 -49
  99. package/package.json +39 -38
  100. package/src/bench/client_flows/benchmark.ts +6 -6
  101. package/src/bench/client_flows/client_flows_benchmark.ts +62 -82
  102. package/src/bench/client_flows/data_extractor.ts +1 -1
  103. package/src/bench/utils.ts +9 -37
  104. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +46 -63
  105. package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +33 -47
  106. package/src/e2e_deploy_contract/deploy_test.ts +17 -35
  107. package/src/e2e_epochs/epochs_test.ts +22 -19
  108. package/src/e2e_fees/bridging_race.notest.ts +14 -9
  109. package/src/e2e_fees/fees_test.ts +29 -40
  110. package/src/e2e_l1_publisher/write_json.ts +8 -6
  111. package/src/e2e_multi_validator/utils.ts +4 -10
  112. package/src/e2e_nested_contract/nested_contract_test.ts +11 -10
  113. package/src/e2e_p2p/inactivity_slash_test.ts +178 -0
  114. package/src/e2e_p2p/p2p_network.ts +110 -71
  115. package/src/e2e_p2p/shared.ts +57 -56
  116. package/src/e2e_token_contract/token_contract_test.ts +17 -17
  117. package/src/fixtures/e2e_prover_test.ts +52 -88
  118. package/src/fixtures/get_acvm_config.ts +1 -1
  119. package/src/fixtures/get_bb_config.ts +3 -2
  120. package/src/fixtures/setup_l1_contracts.ts +3 -3
  121. package/src/fixtures/setup_p2p_test.ts +60 -27
  122. package/src/fixtures/snapshot_manager.ts +80 -72
  123. package/src/fixtures/token_utils.ts +13 -21
  124. package/src/fixtures/utils.ts +95 -145
  125. package/src/fixtures/web3signer.ts +63 -0
  126. package/src/guides/up_quick_start.sh +2 -10
  127. package/src/quality_of_service/alert_checker.ts +1 -1
  128. package/src/shared/cross_chain_test_harness.ts +18 -29
  129. package/src/shared/gas_portal_test_harness.ts +12 -19
  130. package/src/shared/jest_setup.ts +1 -1
  131. package/src/shared/submit-transactions.ts +12 -8
  132. package/src/shared/uniswap_l1_l2.ts +61 -67
  133. package/src/simulators/lending_simulator.ts +3 -2
  134. package/src/simulators/token_simulator.ts +5 -2
  135. package/src/spartan/DEVELOP.md +8 -3
  136. package/src/spartan/setup_test_wallets.ts +133 -126
  137. package/src/spartan/utils.ts +373 -48
@@ -1,16 +1,23 @@
1
- import { createLogger, sleep } from '@aztec/aztec.js';
1
+ import { createLogger } from '@aztec/aztec.js/log';
2
2
  import { makeBackoff, retry } from '@aztec/foundation/retry';
3
3
  import { schemas } from '@aztec/foundation/schemas';
4
- import { createAztecNodeAdminClient } from '@aztec/stdlib/interfaces/client';
4
+ import { sleep } from '@aztec/foundation/sleep';
5
+ import { createAztecNodeAdminClient, createAztecNodeClient } from '@aztec/stdlib/interfaces/client';
5
6
  import { exec, execSync, spawn } from 'child_process';
6
7
  import path from 'path';
7
8
  import { promisify } from 'util';
9
+ import { createPublicClient, fallback, http } from 'viem';
8
10
  import { z } from 'zod';
9
11
  const execAsync = promisify(exec);
10
12
  const logger = createLogger('e2e:k8s-utils');
11
13
  const testConfigSchema = z.object({
12
14
  NAMESPACE: z.string().default('scenario'),
13
- REAL_VERIFIER: schemas.Boolean.optional().default(true)
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)
14
21
  });
15
22
  export function setupEnvironment(env) {
16
23
  const config = testConfigSchema.parse(env);
@@ -66,7 +73,7 @@ export function runProjectScript(script, args, logger, env) {
66
73
  }
67
74
  export async function startPortForward({ resource, namespace, containerPort, hostPort }) {
68
75
  const hostPortAsString = hostPort ? hostPort.toString() : '';
69
- logger.info(`kubectl port-forward -n ${namespace} ${resource} ${hostPortAsString}:${containerPort}`);
76
+ logger.debug(`kubectl port-forward -n ${namespace} ${resource} ${hostPortAsString}:${containerPort}`);
70
77
  const process1 = spawn('kubectl', [
71
78
  'port-forward',
72
79
  '-n',
@@ -88,20 +95,20 @@ export async function startPortForward({ resource, namespace, containerPort, hos
88
95
  const str = data.toString();
89
96
  if (!isResolved && str.includes('Forwarding from')) {
90
97
  isResolved = true;
91
- logger.info(str);
98
+ logger.debug(`Port forward for ${resource}: ${str}`);
92
99
  const port = str.search(/:\d+/);
93
100
  if (port === -1) {
94
101
  throw new Error('Port not found in port forward output');
95
102
  }
96
103
  const portNumber = parseInt(str.slice(port + 1));
97
- logger.info(`Port forward connected: ${portNumber}`);
104
+ logger.verbose(`Port forwarded for ${resource} at ${portNumber}:${containerPort}`);
98
105
  resolve(portNumber);
99
106
  } else {
100
107
  logger.silent(str);
101
108
  }
102
109
  });
103
110
  process1.stderr?.on('data', (data)=>{
104
- logger.info(data.toString());
111
+ logger.verbose(`Port forward for ${resource}: ${data.toString()}`);
105
112
  // It's a strange thing:
106
113
  // If we don't pipe stderr, then the port forwarding does not work.
107
114
  // Log to silent because this doesn't actually report errors,
@@ -111,16 +118,16 @@ export async function startPortForward({ resource, namespace, containerPort, hos
111
118
  process1.on('close', ()=>{
112
119
  if (!isResolved) {
113
120
  isResolved = true;
114
- logger.warn('Port forward closed before connection established');
121
+ logger.warn(`Port forward for ${resource} closed before connection established`);
115
122
  resolve(0);
116
123
  }
117
124
  });
118
125
  process1.on('error', (error)=>{
119
- logger.error(`Port forward error: ${error}`);
126
+ logger.error(`Port forward for ${resource} error: ${error}`);
120
127
  resolve(0);
121
128
  });
122
129
  process1.on('exit', (code)=>{
123
- logger.info(`Port forward exited with code ${code}`);
130
+ logger.verbose(`Port forward for ${resource} exited with code ${code}`);
124
131
  resolve(0);
125
132
  });
126
133
  });
@@ -151,6 +158,13 @@ export async function deleteResourceByName({ resource, namespace, name, force =
151
158
  return stdout;
152
159
  }
153
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
+ }
154
168
  const command = `kubectl delete ${resource} -l ${label} -n ${namespace} --ignore-not-found=true --wait=true --timeout=${timeout} ${force ? '--force' : ''}`;
155
169
  logger.info(`command: ${command}`);
156
170
  const { stdout } = await execAsync(command);
@@ -165,8 +179,12 @@ export async function waitForResourceByLabel({ resource, label, namespace, condi
165
179
  export function getChartDir(spartanDir, chartName) {
166
180
  return path.join(spartanDir.trim(), chartName);
167
181
  }
182
+ function shellQuote(value) {
183
+ // Single-quote safe shell escaping: ' -> '\''
184
+ return `'${value.replace(/'/g, "'\\''")}'`;
185
+ }
168
186
  function valuesToArgs(values) {
169
- return Object.entries(values).map(([key, value])=>`--set ${key}=${value}`).join(' ');
187
+ return Object.entries(values).map(([key, value])=>typeof value === 'number' || typeof value === 'boolean' ? `--set ${key}=${value}` : `--set-string ${key}=${shellQuote(String(value))}`).join(' ');
170
188
  }
171
189
  function createHelmCommand({ instanceName, helmChartDir, namespace, valuesFile, timeout, values, reuseValues = false }) {
172
190
  const valuesFileArgs = valuesFile ? `--values ${helmChartDir}/values/${valuesFile}` : '';
@@ -195,26 +213,30 @@ async function execHelmCommand(args) {
195
213
  * const stdout = await installChaosMeshChart({ instanceName: 'force-reorg', targetNamespace: 'smoke', valuesFile: 'prover-failure.yaml'});
196
214
  * console.log(stdout);
197
215
  * ```
198
- */ export async function installChaosMeshChart({ instanceName, targetNamespace, valuesFile, helmChartDir, chaosMeshNamespace = 'chaos-mesh', timeout = '5m', clean = true, values = {}, logger }) {
216
+ */ export async function installChaosMeshChart({ instanceName, targetNamespace, valuesFile, helmChartDir, chaosMeshNamespace = 'chaos-mesh', timeout = '10m', clean = true, values = {}, logger }) {
199
217
  if (clean) {
200
218
  // uninstall the helm chart if it exists
201
219
  logger.info(`Uninstalling helm chart ${instanceName}`);
202
220
  await execAsync(`helm uninstall ${instanceName} --namespace ${chaosMeshNamespace} --wait --ignore-not-found`);
203
- // and delete the podchaos resource
204
- const deleteArgs = {
205
- resource: 'podchaos',
206
- namespace: chaosMeshNamespace,
207
- label: `app.kubernetes.io/instance=${instanceName}`
208
- };
209
- logger.info(`Deleting podchaos resource`);
210
- await deleteResourceByLabel(deleteArgs).catch((e)=>{
211
- logger.error(`Error deleting podchaos resource: ${e}`);
212
- logger.info(`Force deleting podchaos resource`);
213
- return deleteResourceByLabel({
214
- ...deleteArgs,
215
- force: true
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
+ });
216
236
  });
217
- });
237
+ };
238
+ await deleteByLabel('podchaos');
239
+ await deleteByLabel('networkchaos');
218
240
  }
219
241
  return execHelmCommand({
220
242
  instanceName,
@@ -311,16 +333,189 @@ export async function restartBot(namespace, logger) {
311
333
  await deleteResourceByLabel({
312
334
  resource: 'pods',
313
335
  namespace,
314
- label: 'app=bot'
336
+ label: 'app.kubernetes.io/name=bot'
315
337
  });
316
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.
317
341
  await waitForResourceByLabel({
318
342
  resource: 'pods',
319
343
  namespace,
320
- label: 'app=bot'
344
+ label: 'app.kubernetes.io/name=bot',
345
+ condition: 'PodReadyToStartContainers'
321
346
  });
322
347
  logger.info(`Bot restarted`);
323
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
+ }
324
519
  export async function enableValidatorDynamicBootNode(instanceName, namespace, spartanDir, logger) {
325
520
  logger.info(`Enabling validator dynamic boot node`);
326
521
  await execHelmCommand({
@@ -336,40 +531,108 @@ export async function enableValidatorDynamicBootNode(instanceName, namespace, sp
336
531
  });
337
532
  logger.info(`Validator dynamic boot node enabled`);
338
533
  }
339
- export async function updateSequencerConfig(url, config) {
340
- const node = createAztecNodeAdminClient(url);
341
- // Retry incase the port forward is not ready yet
342
- await retry(()=>node.setConfig(config), 'Update sequencer config', makeBackoff([
343
- 1,
344
- 3,
345
- 6
346
- ]), logger);
347
- }
348
534
  export async function getSequencers(namespace) {
349
- const command = `kubectl get pods -l app=validator -n ${namespace} -o jsonpath='{.items[*].metadata.name}'`;
535
+ const command = `kubectl get pods -l app.kubernetes.io/component=validator -n ${namespace} -o jsonpath='{.items[*].metadata.name}'`;
350
536
  const { stdout } = await execAsync(command);
351
- return stdout.split(' ');
537
+ const sequencers = stdout.split(' ');
538
+ logger.verbose(`Found sequencer pods ${sequencers.join(', ')}`);
539
+ return sequencers;
352
540
  }
353
- async function updateK8sSequencersConfig(args) {
354
- const { containerPort, namespace, config } = args;
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;
355
553
  const sequencers = await getSequencers(namespace);
554
+ const results = [];
356
555
  for (const sequencer of sequencers){
357
556
  const { process: process1, port } = await startPortForward({
358
557
  resource: `pod/${sequencer}`,
359
558
  namespace,
360
- containerPort
559
+ containerPort: adminContainerPort
361
560
  });
362
561
  const url = `http://localhost:${port}`;
363
- await updateSequencerConfig(url, config);
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));
364
570
  process1.kill();
365
571
  }
572
+ return results;
366
573
  }
367
- export async function updateSequencersConfig(env, config) {
368
- await updateK8sSequencersConfig({
369
- containerPort: 8880,
370
- namespace: env.NAMESPACE,
371
- config
372
- });
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
+ }
373
636
  }
374
637
  /**
375
638
  * Rolls the Aztec pods in the given namespace.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/end-to-end",
3
- "version": "3.0.0-canary.a9708bd",
3
+ "version": "3.0.0-devnet.2",
4
4
  "type": "module",
5
5
  "exports": "./dest/index.js",
6
6
  "inherits": [
@@ -25,41 +25,42 @@
25
25
  "formatting": "run -T prettier --check ./src && run -T eslint ./src"
26
26
  },
27
27
  "dependencies": {
28
- "@aztec/accounts": "3.0.0-canary.a9708bd",
29
- "@aztec/archiver": "3.0.0-canary.a9708bd",
30
- "@aztec/aztec": "3.0.0-canary.a9708bd",
31
- "@aztec/aztec-node": "3.0.0-canary.a9708bd",
32
- "@aztec/aztec.js": "3.0.0-canary.a9708bd",
33
- "@aztec/bb-prover": "3.0.0-canary.a9708bd",
34
- "@aztec/blob-lib": "3.0.0-canary.a9708bd",
35
- "@aztec/blob-sink": "3.0.0-canary.a9708bd",
36
- "@aztec/bot": "3.0.0-canary.a9708bd",
37
- "@aztec/cli": "3.0.0-canary.a9708bd",
38
- "@aztec/constants": "3.0.0-canary.a9708bd",
39
- "@aztec/entrypoints": "3.0.0-canary.a9708bd",
40
- "@aztec/epoch-cache": "3.0.0-canary.a9708bd",
41
- "@aztec/ethereum": "3.0.0-canary.a9708bd",
42
- "@aztec/foundation": "3.0.0-canary.a9708bd",
43
- "@aztec/kv-store": "3.0.0-canary.a9708bd",
44
- "@aztec/l1-artifacts": "3.0.0-canary.a9708bd",
45
- "@aztec/merkle-tree": "3.0.0-canary.a9708bd",
46
- "@aztec/node-keystore": "3.0.0-canary.a9708bd",
47
- "@aztec/noir-contracts.js": "3.0.0-canary.a9708bd",
48
- "@aztec/noir-noirc_abi": "3.0.0-canary.a9708bd",
49
- "@aztec/noir-protocol-circuits-types": "3.0.0-canary.a9708bd",
50
- "@aztec/noir-test-contracts.js": "3.0.0-canary.a9708bd",
51
- "@aztec/p2p": "3.0.0-canary.a9708bd",
52
- "@aztec/protocol-contracts": "3.0.0-canary.a9708bd",
53
- "@aztec/prover-client": "3.0.0-canary.a9708bd",
54
- "@aztec/prover-node": "3.0.0-canary.a9708bd",
55
- "@aztec/pxe": "3.0.0-canary.a9708bd",
56
- "@aztec/sequencer-client": "3.0.0-canary.a9708bd",
57
- "@aztec/simulator": "3.0.0-canary.a9708bd",
58
- "@aztec/slasher": "3.0.0-canary.a9708bd",
59
- "@aztec/stdlib": "3.0.0-canary.a9708bd",
60
- "@aztec/telemetry-client": "3.0.0-canary.a9708bd",
61
- "@aztec/validator-client": "3.0.0-canary.a9708bd",
62
- "@aztec/world-state": "3.0.0-canary.a9708bd",
28
+ "@aztec/accounts": "3.0.0-devnet.2",
29
+ "@aztec/archiver": "3.0.0-devnet.2",
30
+ "@aztec/aztec": "3.0.0-devnet.2",
31
+ "@aztec/aztec-node": "3.0.0-devnet.2",
32
+ "@aztec/aztec.js": "3.0.0-devnet.2",
33
+ "@aztec/bb-prover": "3.0.0-devnet.2",
34
+ "@aztec/blob-lib": "3.0.0-devnet.2",
35
+ "@aztec/blob-sink": "3.0.0-devnet.2",
36
+ "@aztec/bot": "3.0.0-devnet.2",
37
+ "@aztec/cli": "3.0.0-devnet.2",
38
+ "@aztec/constants": "3.0.0-devnet.2",
39
+ "@aztec/entrypoints": "3.0.0-devnet.2",
40
+ "@aztec/epoch-cache": "3.0.0-devnet.2",
41
+ "@aztec/ethereum": "3.0.0-devnet.2",
42
+ "@aztec/foundation": "3.0.0-devnet.2",
43
+ "@aztec/kv-store": "3.0.0-devnet.2",
44
+ "@aztec/l1-artifacts": "3.0.0-devnet.2",
45
+ "@aztec/merkle-tree": "3.0.0-devnet.2",
46
+ "@aztec/node-keystore": "3.0.0-devnet.2",
47
+ "@aztec/noir-contracts.js": "3.0.0-devnet.2",
48
+ "@aztec/noir-noirc_abi": "3.0.0-devnet.2",
49
+ "@aztec/noir-protocol-circuits-types": "3.0.0-devnet.2",
50
+ "@aztec/noir-test-contracts.js": "3.0.0-devnet.2",
51
+ "@aztec/p2p": "3.0.0-devnet.2",
52
+ "@aztec/protocol-contracts": "3.0.0-devnet.2",
53
+ "@aztec/prover-client": "3.0.0-devnet.2",
54
+ "@aztec/prover-node": "3.0.0-devnet.2",
55
+ "@aztec/pxe": "3.0.0-devnet.2",
56
+ "@aztec/sequencer-client": "3.0.0-devnet.2",
57
+ "@aztec/simulator": "3.0.0-devnet.2",
58
+ "@aztec/slasher": "3.0.0-devnet.2",
59
+ "@aztec/stdlib": "3.0.0-devnet.2",
60
+ "@aztec/telemetry-client": "3.0.0-devnet.2",
61
+ "@aztec/test-wallet": "3.0.0-devnet.2",
62
+ "@aztec/validator-client": "3.0.0-devnet.2",
63
+ "@aztec/world-state": "3.0.0-devnet.2",
63
64
  "@iarna/toml": "^2.2.5",
64
65
  "@jest/globals": "^30.0.0",
65
66
  "@noble/curves": "=1.0.0",
@@ -91,12 +92,12 @@
91
92
  "snappy": "^7.2.2",
92
93
  "stream-browserify": "^3.0.0",
93
94
  "string-argv": "^0.3.2",
94
- "ts-loader": "^9.4.4",
95
+ "ts-loader": "^9.5.4",
95
96
  "ts-node": "^10.9.1",
96
97
  "tslib": "^2.4.0",
97
98
  "typescript": "^5.3.3",
98
99
  "util": "^0.12.5",
99
- "viem": "2.23.7",
100
+ "viem": "npm:@spalladino/viem@2.38.2-eip7594.0",
100
101
  "zod": "^3.23.8"
101
102
  },
102
103
  "devDependencies": {
@@ -1,10 +1,10 @@
1
- import type {
1
+ import {
2
2
  ContractFunctionInteraction,
3
3
  DeployMethod,
4
- DeployOptions,
5
- Logger,
6
- ProfileMethodOptions,
7
- } from '@aztec/aztec.js';
4
+ type DeployOptions,
5
+ type ProfileInteractionOptions,
6
+ } from '@aztec/aztec.js/contracts';
7
+ import type { Logger } from '@aztec/aztec.js/log';
8
8
  import { createLogger } from '@aztec/foundation/log';
9
9
  import { type PrivateExecutionStep, serializePrivateExecutionSteps } from '@aztec/stdlib/kernel';
10
10
  import type { ProvingStats, ProvingTimings, SimulationStats, SimulationTimings } from '@aztec/stdlib/tx';
@@ -301,7 +301,7 @@ export function convertProfileToGHBenchmark(benchmark: ClientFlowBenchmark): Git
301
301
  export async function captureProfile(
302
302
  label: string,
303
303
  interaction: ContractFunctionInteraction | DeployMethod,
304
- opts: Omit<ProfileMethodOptions & DeployOptions, 'profileMode'>,
304
+ opts: Omit<ProfileInteractionOptions & DeployOptions, 'profileMode'>,
305
305
  expectedSteps?: number,
306
306
  ) {
307
307
  // Make sure the proxy logger starts from a clean slate