@aztec/end-to-end 0.0.1-commit.f295ac2 → 0.0.1-commit.f2ce05ee

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 (157) hide show
  1. package/dest/bench/client_flows/client_flows_benchmark.d.ts +1 -1
  2. package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
  3. package/dest/bench/client_flows/client_flows_benchmark.js +28 -13
  4. package/dest/bench/client_flows/config.d.ts +2 -2
  5. package/dest/bench/client_flows/config.d.ts.map +1 -1
  6. package/dest/bench/client_flows/config.js +18 -0
  7. package/dest/bench/utils.d.ts +5 -4
  8. package/dest/bench/utils.d.ts.map +1 -1
  9. package/dest/bench/utils.js +9 -7
  10. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +1 -1
  11. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
  12. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +7 -8
  13. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +1 -1
  14. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts.map +1 -1
  15. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.js +3 -2
  16. package/dest/e2e_epochs/epochs_test.d.ts +7 -1
  17. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  18. package/dest/e2e_epochs/epochs_test.js +31 -8
  19. package/dest/e2e_fees/bridging_race.notest.js +1 -1
  20. package/dest/e2e_fees/fees_test.d.ts +1 -1
  21. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  22. package/dest/e2e_fees/fees_test.js +6 -6
  23. package/dest/e2e_l1_publisher/write_json.d.ts +4 -3
  24. package/dest/e2e_l1_publisher/write_json.d.ts.map +1 -1
  25. package/dest/e2e_l1_publisher/write_json.js +1 -7
  26. package/dest/e2e_nested_contract/nested_contract_test.d.ts +1 -1
  27. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
  28. package/dest/e2e_nested_contract/nested_contract_test.js +2 -2
  29. package/dest/e2e_p2p/p2p_network.d.ts +1 -1
  30. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  31. package/dest/e2e_p2p/p2p_network.js +6 -2
  32. package/dest/e2e_p2p/reqresp/utils.d.ts +22 -0
  33. package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -0
  34. package/dest/e2e_p2p/reqresp/utils.js +153 -0
  35. package/dest/e2e_p2p/shared.d.ts +6 -6
  36. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  37. package/dest/e2e_p2p/shared.js +12 -16
  38. package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.d.ts +2 -0
  39. package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.d.ts.map +1 -0
  40. package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.js +184 -0
  41. package/dest/e2e_storage_proof/fixtures/storage_proof_fixture.d.ts +18 -0
  42. package/dest/e2e_storage_proof/fixtures/storage_proof_fixture.d.ts.map +1 -0
  43. package/dest/e2e_storage_proof/fixtures/storage_proof_fixture.js +120 -0
  44. package/dest/e2e_token_contract/token_contract_test.d.ts +1 -1
  45. package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
  46. package/dest/e2e_token_contract/token_contract_test.js +3 -3
  47. package/dest/fixtures/e2e_prover_test.d.ts +1 -1
  48. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  49. package/dest/fixtures/e2e_prover_test.js +8 -5
  50. package/dest/fixtures/ha_setup.d.ts +71 -0
  51. package/dest/fixtures/ha_setup.d.ts.map +1 -0
  52. package/dest/fixtures/ha_setup.js +114 -0
  53. package/dest/fixtures/index.d.ts +2 -1
  54. package/dest/fixtures/index.d.ts.map +1 -1
  55. package/dest/fixtures/index.js +1 -0
  56. package/dest/fixtures/setup.d.ts +5 -3
  57. package/dest/fixtures/setup.d.ts.map +1 -1
  58. package/dest/fixtures/setup.js +31 -20
  59. package/dest/fixtures/setup_p2p_test.d.ts +12 -8
  60. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  61. package/dest/fixtures/setup_p2p_test.js +29 -21
  62. package/dest/fixtures/token_utils.d.ts +1 -1
  63. package/dest/fixtures/token_utils.d.ts.map +1 -1
  64. package/dest/fixtures/token_utils.js +7 -4
  65. package/dest/shared/cross_chain_test_harness.d.ts +3 -4
  66. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
  67. package/dest/shared/cross_chain_test_harness.js +11 -11
  68. package/dest/shared/gas_portal_test_harness.js +1 -1
  69. package/dest/shared/submit-transactions.d.ts +3 -3
  70. package/dest/shared/submit-transactions.d.ts.map +1 -1
  71. package/dest/shared/submit-transactions.js +9 -11
  72. package/dest/shared/uniswap_l1_l2.d.ts +1 -1
  73. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  74. package/dest/shared/uniswap_l1_l2.js +19 -17
  75. package/dest/simulators/lending_simulator.js +2 -2
  76. package/dest/spartan/setup_test_wallets.d.ts +1 -1
  77. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  78. package/dest/spartan/setup_test_wallets.js +61 -34
  79. package/dest/spartan/tx_metrics.d.ts +48 -2
  80. package/dest/spartan/tx_metrics.d.ts.map +1 -1
  81. package/dest/spartan/tx_metrics.js +309 -5
  82. package/dest/spartan/utils/bot.d.ts +27 -0
  83. package/dest/spartan/utils/bot.d.ts.map +1 -0
  84. package/dest/spartan/utils/bot.js +141 -0
  85. package/dest/spartan/utils/chaos.d.ts +79 -0
  86. package/dest/spartan/utils/chaos.d.ts.map +1 -0
  87. package/dest/spartan/utils/chaos.js +142 -0
  88. package/dest/spartan/utils/clients.d.ts +39 -0
  89. package/dest/spartan/utils/clients.d.ts.map +1 -0
  90. package/dest/spartan/utils/clients.js +90 -0
  91. package/dest/spartan/utils/config.d.ts +39 -0
  92. package/dest/spartan/utils/config.d.ts.map +1 -0
  93. package/dest/spartan/utils/config.js +21 -0
  94. package/dest/spartan/utils/health.d.ts +63 -0
  95. package/dest/spartan/utils/health.d.ts.map +1 -0
  96. package/dest/spartan/utils/health.js +202 -0
  97. package/dest/spartan/utils/helm.d.ts +15 -0
  98. package/dest/spartan/utils/helm.d.ts.map +1 -0
  99. package/dest/spartan/utils/helm.js +47 -0
  100. package/dest/spartan/utils/index.d.ts +9 -0
  101. package/dest/spartan/utils/index.d.ts.map +1 -0
  102. package/dest/spartan/utils/index.js +18 -0
  103. package/dest/spartan/utils/k8s.d.ts +126 -0
  104. package/dest/spartan/utils/k8s.d.ts.map +1 -0
  105. package/dest/spartan/utils/k8s.js +375 -0
  106. package/dest/spartan/utils/nodes.d.ts +41 -0
  107. package/dest/spartan/utils/nodes.d.ts.map +1 -0
  108. package/dest/spartan/utils/nodes.js +461 -0
  109. package/dest/spartan/utils/scripts.d.ts +30 -0
  110. package/dest/spartan/utils/scripts.d.ts.map +1 -0
  111. package/dest/spartan/utils/scripts.js +81 -0
  112. package/dest/spartan/utils.d.ts +2 -260
  113. package/dest/spartan/utils.d.ts.map +1 -1
  114. package/dest/spartan/utils.js +1 -942
  115. package/package.json +42 -39
  116. package/src/bench/client_flows/client_flows_benchmark.ts +11 -24
  117. package/src/bench/client_flows/config.ts +9 -1
  118. package/src/bench/utils.ts +9 -7
  119. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +9 -12
  120. package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +3 -4
  121. package/src/e2e_epochs/epochs_test.ts +59 -32
  122. package/src/e2e_fees/bridging_race.notest.ts +1 -4
  123. package/src/e2e_fees/fees_test.ts +10 -14
  124. package/src/e2e_l1_publisher/write_json.ts +3 -8
  125. package/src/e2e_nested_contract/nested_contract_test.ts +2 -4
  126. package/src/e2e_p2p/p2p_network.ts +15 -9
  127. package/src/e2e_p2p/reqresp/utils.ts +207 -0
  128. package/src/e2e_p2p/shared.ts +21 -22
  129. package/src/e2e_storage_proof/fixtures/storage_proof.json +915 -0
  130. package/src/e2e_storage_proof/fixtures/storage_proof_fetcher.ts +190 -0
  131. package/src/e2e_storage_proof/fixtures/storage_proof_fixture.ts +173 -0
  132. package/src/e2e_token_contract/token_contract_test.ts +3 -5
  133. package/src/fixtures/dumps/epoch_proof_result.json +1 -1
  134. package/src/fixtures/e2e_prover_test.ts +4 -9
  135. package/src/fixtures/ha_setup.ts +184 -0
  136. package/src/fixtures/index.ts +1 -0
  137. package/src/fixtures/setup.ts +33 -26
  138. package/src/fixtures/setup_p2p_test.ts +31 -27
  139. package/src/fixtures/token_utils.ts +6 -5
  140. package/src/shared/cross_chain_test_harness.ts +13 -27
  141. package/src/shared/gas_portal_test_harness.ts +1 -1
  142. package/src/shared/submit-transactions.ts +9 -15
  143. package/src/shared/uniswap_l1_l2.ts +19 -28
  144. package/src/simulators/lending_simulator.ts +2 -2
  145. package/src/spartan/setup_test_wallets.ts +72 -24
  146. package/src/spartan/tx_metrics.ts +231 -8
  147. package/src/spartan/utils/bot.ts +185 -0
  148. package/src/spartan/utils/chaos.ts +253 -0
  149. package/src/spartan/utils/clients.ts +100 -0
  150. package/src/spartan/utils/config.ts +27 -0
  151. package/src/spartan/utils/health.ts +255 -0
  152. package/src/spartan/utils/helm.ts +84 -0
  153. package/src/spartan/utils/index.ts +64 -0
  154. package/src/spartan/utils/k8s.ts +527 -0
  155. package/src/spartan/utils/nodes.ts +538 -0
  156. package/src/spartan/utils/scripts.ts +99 -0
  157. package/src/spartan/utils.ts +1 -1246
@@ -0,0 +1,184 @@
1
+ import { EthAddress } from '@aztec/aztec.js/addresses';
2
+ import { Fr } from '@aztec/aztec.js/fields';
3
+ import type { Logger } from '@aztec/aztec.js/log';
4
+ import { SecretValue } from '@aztec/foundation/config';
5
+
6
+ import { Pool } from 'pg';
7
+ import { privateKeyToAccount } from 'viem/accounts';
8
+
9
+ /**
10
+ * Configuration for HA database connection
11
+ */
12
+ export interface HADatabaseConfig {
13
+ /** PostgreSQL connection URL */
14
+ databaseUrl: string;
15
+ /** Node ID for HA coordination */
16
+ nodeId: string;
17
+ /** Enable HA signing */
18
+ haSigningEnabled: boolean;
19
+ /** Polling interval in ms */
20
+ pollingIntervalMs: number;
21
+ /** Signing timeout in ms */
22
+ signingTimeoutMs: number;
23
+ /** Max stuck duties age in ms */
24
+ maxStuckDutiesAgeMs: number;
25
+ }
26
+
27
+ /**
28
+ * Get database configuration from environment variables
29
+ */
30
+ export function createHADatabaseConfig(nodeId: string): HADatabaseConfig {
31
+ const databaseUrl = process.env.DATABASE_URL || 'postgresql://aztec:aztec@localhost:5432/aztec_ha_test';
32
+
33
+ return {
34
+ databaseUrl,
35
+ nodeId,
36
+ haSigningEnabled: true,
37
+ pollingIntervalMs: 100,
38
+ signingTimeoutMs: 3000,
39
+ maxStuckDutiesAgeMs: 72000,
40
+ };
41
+ }
42
+
43
+ /**
44
+ * Setup PostgreSQL database connection pool for HA tests
45
+ *
46
+ * Note: Database migrations should be run separately before starting tests,
47
+ * either via docker-compose entrypoint or manually with: aztec migrate-ha-db up
48
+ */
49
+ export function setupHADatabase(databaseUrl: string, logger?: Logger): Pool {
50
+ try {
51
+ // Create connection pool for test usage
52
+ // Migrations are already run by docker-compose entrypoint before tests start
53
+ const pool = new Pool({ connectionString: databaseUrl });
54
+
55
+ logger?.info('Connected to HA database (migrations should already be applied)');
56
+
57
+ return pool;
58
+ } catch (error) {
59
+ logger?.error(`Failed to connect to HA database: ${error}`);
60
+ throw error;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Clean up HA database - drop all tables
66
+ * Use this between tests to ensure clean state
67
+ */
68
+ export async function cleanupHADatabase(pool: Pool, logger?: Logger): Promise<void> {
69
+ try {
70
+ // Drop all HA tables
71
+ await pool.query('DROP TABLE IF EXISTS validator_duties CASCADE');
72
+ await pool.query('DROP TABLE IF EXISTS slashing_protection CASCADE');
73
+ await pool.query('DROP TABLE IF EXISTS schema_version CASCADE');
74
+
75
+ logger?.info('HA database cleaned up successfully');
76
+ } catch (error) {
77
+ logger?.error(`Failed to cleanup HA database: ${error}`);
78
+ throw error;
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Query validator duties from the database
84
+ */
85
+ export async function getValidatorDuties(
86
+ pool: Pool,
87
+ slot: bigint,
88
+ dutyType?: 'ATTESTATION' | 'BLOCK_PROPOSAL' | 'GOVERNANCE_VOTE' | 'SLASHING_VOTE',
89
+ ): Promise<
90
+ Array<{
91
+ slot: string;
92
+ dutyType: string;
93
+ validatorAddress: string;
94
+ nodeId: string;
95
+ startedAt: Date;
96
+ completedAt: Date | undefined;
97
+ }>
98
+ > {
99
+ const query = dutyType
100
+ ? 'SELECT slot, duty_type, validator_address, node_id, started_at, completed_at FROM validator_duties WHERE slot = $1 AND duty_type = $2 ORDER BY started_at'
101
+ : 'SELECT slot, duty_type, validator_address, node_id, started_at, completed_at FROM validator_duties WHERE slot = $1 ORDER BY started_at';
102
+
103
+ const params = dutyType ? [slot.toString(), dutyType] : [slot.toString()];
104
+
105
+ const result = await pool.query<{
106
+ slot: string;
107
+ duty_type: string;
108
+ validator_address: string;
109
+ node_id: string;
110
+ started_at: Date;
111
+ completed_at: Date | undefined;
112
+ }>(query, params);
113
+
114
+ return result.rows.map(row => ({
115
+ slot: row.slot,
116
+ dutyType: row.duty_type,
117
+ validatorAddress: row.validator_address,
118
+ nodeId: row.node_id,
119
+ startedAt: row.started_at,
120
+ completedAt: row.completed_at,
121
+ }));
122
+ }
123
+
124
+ /**
125
+ * Convert private keys to Ethereum addresses
126
+ */
127
+ export function getAddressesFromPrivateKeys(privateKeys: `0x${string}`[]): string[] {
128
+ return privateKeys.map(pk => {
129
+ const account = privateKeyToAccount(pk);
130
+ return account.address;
131
+ });
132
+ }
133
+
134
+ /**
135
+ * Create initial validators from private keys for L1 contract deployment
136
+ */
137
+ export function createInitialValidatorsFromPrivateKeys(attesterPrivateKeys: `0x${string}`[]): Array<{
138
+ attester: EthAddress;
139
+ withdrawer: EthAddress;
140
+ privateKey: `0x${string}`;
141
+ bn254SecretKey: SecretValue<bigint>;
142
+ }> {
143
+ return attesterPrivateKeys.map(pk => {
144
+ const account = privateKeyToAccount(pk);
145
+ return {
146
+ attester: EthAddress.fromString(account.address),
147
+ withdrawer: EthAddress.fromString(account.address),
148
+ privateKey: pk,
149
+ bn254SecretKey: new SecretValue(Fr.random().toBigInt()),
150
+ };
151
+ });
152
+ }
153
+
154
+ /**
155
+ * Verify no duplicate attestations per validator (HA coordination check)
156
+ * Groups duties by validator address and verifies each validator attested exactly once
157
+ */
158
+ export function verifyNoDuplicateAttestations(
159
+ attestationDuties: Array<{
160
+ validatorAddress: string;
161
+ nodeId: string;
162
+ completedAt: Date | undefined;
163
+ }>,
164
+ logger?: Logger,
165
+ ): Map<string, typeof attestationDuties> {
166
+ const dutiesByValidator = new Map<string, typeof attestationDuties>();
167
+ for (const duty of attestationDuties) {
168
+ const existing = dutiesByValidator.get(duty.validatorAddress) || [];
169
+ existing.push(duty);
170
+ dutiesByValidator.set(duty.validatorAddress, existing);
171
+ }
172
+
173
+ for (const [validatorAddress, validatorDuties] of dutiesByValidator.entries()) {
174
+ if (validatorDuties.length !== 1) {
175
+ throw new Error(`Validator ${validatorAddress} attested ${validatorDuties.length} times (expected exactly once)`);
176
+ }
177
+ if (!validatorDuties[0].completedAt) {
178
+ throw new Error(`Validator ${validatorAddress} attestation duty not completed`);
179
+ }
180
+ logger?.info(`Validator ${validatorAddress} attested once via node ${validatorDuties[0].nodeId}`);
181
+ }
182
+
183
+ return dutiesByValidator;
184
+ }
@@ -1,4 +1,5 @@
1
1
  export * from './fixtures.js';
2
+ export * from './ha_setup.js';
2
3
  export * from './logging.js';
3
4
  export * from './utils.js';
4
5
  export * from './token_utils.js';
@@ -41,7 +41,7 @@ import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
41
41
  import { SecretValue } from '@aztec/foundation/config';
42
42
  import { randomBytes } from '@aztec/foundation/crypto/random';
43
43
  import { tryRmDir } from '@aztec/foundation/fs';
44
- import { withLogNameSuffix } from '@aztec/foundation/log';
44
+ import { withLoggerBindings } from '@aztec/foundation/log/server';
45
45
  import { retryUntil } from '@aztec/foundation/retry';
46
46
  import { sleep } from '@aztec/foundation/sleep';
47
47
  import { DateProvider, TestDateProvider } from '@aztec/foundation/timer';
@@ -125,14 +125,14 @@ export async function setupSharedBlobStorage(config: { dataDirectory?: string }
125
125
  * @param aztecNode - An instance of Aztec Node.
126
126
  * @param opts - Partial configuration for the PXE.
127
127
  * @param logger - The logger to be used.
128
- * @param useLogSuffix - Whether to add a randomly generated suffix to the PXE debug logs.
128
+ * @param actor - Actor label to include in log output (e.g., 'pxe-test').
129
129
  * @returns A test wallet, logger and teardown function.
130
130
  */
131
131
  export async function setupPXEAndGetWallet(
132
132
  aztecNode: AztecNode,
133
133
  opts: Partial<PXEConfig> = {},
134
134
  logger = getLogger(),
135
- useLogSuffix = false,
135
+ actor?: string,
136
136
  ): Promise<{
137
137
  wallet: TestWallet;
138
138
  logger: Logger;
@@ -150,9 +150,7 @@ export async function setupPXEAndGetWallet(
150
150
 
151
151
  const teardown = configuredDataDirectory ? () => Promise.resolve() : () => tryRmDir(PXEConfig.dataDirectory!);
152
152
 
153
- const wallet = await TestWallet.create(aztecNode, PXEConfig, {
154
- useLogSuffix,
155
- });
153
+ const wallet = await TestWallet.create(aztecNode, PXEConfig, { loggerActorLabel: actor });
156
154
 
157
155
  return {
158
156
  wallet,
@@ -209,6 +207,8 @@ export type SetupOptions = {
209
207
  skipAccountDeployment?: boolean;
210
208
  /** L1 contracts deployment arguments. */
211
209
  l1ContractsArgs?: Partial<DeployAztecL1ContractsArgs>;
210
+ /** Wallet minimum fee padding multiplier (defaults to 0.5, which is 50% padding). */
211
+ walletMinFeePadding?: number;
212
212
  } & Partial<AztecNodeConfig>;
213
213
 
214
214
  /** Context for an end-to-end test as returned by the `setup` function */
@@ -268,7 +268,7 @@ export type EndToEndContext = {
268
268
  */
269
269
  async function setupWithRemoteEnvironment(
270
270
  account: HDAccount | PrivateKeyAccount,
271
- config: AztecNodeConfig,
271
+ config: AztecNodeConfig & SetupOptions,
272
272
  logger: Logger,
273
273
  numberOfAccounts: number,
274
274
  ): Promise<EndToEndContext> {
@@ -289,6 +289,11 @@ async function setupWithRemoteEnvironment(
289
289
  };
290
290
  const ethCheatCodes = new EthCheatCodes(config.l1RpcUrls, new DateProvider());
291
291
  const wallet = await TestWallet.create(aztecNode);
292
+
293
+ if (config.walletMinFeePadding !== undefined) {
294
+ wallet.setMinFeePadding(config.walletMinFeePadding);
295
+ }
296
+
292
297
  const cheatCodes = await CheatCodes.create(config.l1RpcUrls, aztecNode, new DateProvider());
293
298
  const teardown = () => Promise.resolve();
294
299
 
@@ -385,7 +390,7 @@ export async function setup(
385
390
  const res = await startAnvil({
386
391
  l1BlockTime: opts.ethereumSlotDuration,
387
392
  accounts: opts.anvilAccounts,
388
- port: opts.anvilPort,
393
+ port: opts.anvilPort ?? (process.env.ANVIL_PORT ? parseInt(process.env.ANVIL_PORT) : undefined),
389
394
  });
390
395
  anvil = res.anvil;
391
396
  config.l1RpcUrls = [res.rpcUrl];
@@ -567,10 +572,12 @@ export async function setup(
567
572
  }
568
573
  }
569
574
 
570
- const aztecNodeService = await AztecNodeService.createAndSync(
571
- config,
572
- { dateProvider, telemetry: telemetryClient, p2pClientDeps, logger: createLogger('node:MAIN-aztec-node') },
573
- { prefilledPublicData },
575
+ const aztecNodeService = await withLoggerBindings({ actor: 'node-0' }, () =>
576
+ AztecNodeService.createAndSync(
577
+ config,
578
+ { dateProvider, telemetry: telemetryClient, p2pClientDeps },
579
+ { prefilledPublicData },
580
+ ),
574
581
  );
575
582
  const sequencerClient = aztecNodeService.getSequencer();
576
583
 
@@ -604,7 +611,11 @@ export async function setup(
604
611
  pxeConfig.dataDirectory = path.join(directoryToCleanup, randomBytes(8).toString('hex'));
605
612
  // For tests we only want proving enabled if specifically requested
606
613
  pxeConfig.proverEnabled = !!pxeOpts.proverEnabled;
607
- const wallet = await TestWallet.create(aztecNodeService, pxeConfig);
614
+ const wallet = await TestWallet.create(aztecNodeService, pxeConfig, { loggerActorLabel: 'pxe-0' });
615
+
616
+ if (opts.walletMinFeePadding !== undefined) {
617
+ wallet.setMinFeePadding(opts.walletMinFeePadding);
618
+ }
608
619
 
609
620
  const cheatCodes = await CheatCodes.create(config.l1RpcUrls, aztecNodeService, dateProvider);
610
621
 
@@ -629,7 +640,7 @@ export async function setup(
629
640
  `${numberOfAccounts} accounts are being deployed. Reliably progressing past genesis by setting minTxsPerBlock to 1 and waiting for the accounts to be deployed`,
630
641
  );
631
642
  const accountsData = initialFundedAccounts.slice(0, numberOfAccounts);
632
- const accountManagers = await deployFundedSchnorrAccounts(wallet, aztecNodeService, accountsData);
643
+ const accountManagers = await deployFundedSchnorrAccounts(wallet, accountsData);
633
644
  accounts = accountManagers.map(accountManager => accountManager.address);
634
645
  } else if (needsEmptyBlock) {
635
646
  logger.info('No accounts are being deployed, waiting for an empty block 1 to be mined');
@@ -786,7 +797,7 @@ export function createAndSyncProverNode(
786
797
  prefilledPublicData: PublicDataTreeLeaf[] = [],
787
798
  proverNodeDeps: ProverNodeDeps = {},
788
799
  ) {
789
- return withLogNameSuffix('prover-node', async () => {
800
+ return withLoggerBindings({ actor: 'prover-0' }, async () => {
790
801
  const aztecNodeTxProvider = aztecNode && {
791
802
  getTxByHash: aztecNode.getTxByHash.bind(aztecNode),
792
803
  getTxsByHash: aztecNode.getTxsByHash.bind(aztecNode),
@@ -921,13 +932,11 @@ export async function ensureAccountContractsPublished(wallet: Wallet, accountsTo
921
932
  ).map(contractMetadata => contractMetadata.instance);
922
933
  const contractClass = await getContractClassFromArtifact(SchnorrAccountContractArtifact);
923
934
  if (!(await wallet.getContractClassMetadata(contractClass.id)).isContractClassPubliclyRegistered) {
924
- await (await publishContractClass(wallet, SchnorrAccountContractArtifact))
925
- .send({ from: accountsToDeploy[0] })
926
- .wait();
935
+ await (await publishContractClass(wallet, SchnorrAccountContractArtifact)).send({ from: accountsToDeploy[0] });
927
936
  }
928
937
  const requests = instances.map(instance => publishInstance(wallet, instance!));
929
938
  const batch = new BatchCall(wallet, requests);
930
- await batch.send({ from: accountsToDeploy[0] }).wait();
939
+ await batch.send({ from: accountsToDeploy[0] });
931
940
  }
932
941
 
933
942
  /**
@@ -951,12 +960,10 @@ export const deployAccounts =
951
960
  deployedAccounts[i].signingKey,
952
961
  );
953
962
  const deployMethod = await accountManager.getDeployMethod();
954
- await deployMethod
955
- .send({
956
- from: AztecAddress.ZERO,
957
- skipClassPublication: i !== 0, // Publish the contract class at most once.
958
- })
959
- .wait();
963
+ await deployMethod.send({
964
+ from: AztecAddress.ZERO,
965
+ skipClassPublication: i !== 0, // Publish the contract class at most once.
966
+ });
960
967
  }
961
968
 
962
969
  return { deployedAccounts };
@@ -986,7 +993,7 @@ export async function publicDeployAccounts(
986
993
 
987
994
  const batch = new BatchCall(wallet, calls);
988
995
 
989
- const txReceipt = await batch.send({ from: accountsToDeploy[0] }).wait();
996
+ const txReceipt = await batch.send({ from: accountsToDeploy[0] });
990
997
  if (waitUntilProven) {
991
998
  if (!node) {
992
999
  throw new Error('Need to provide an AztecNode to wait for proven.');
@@ -4,14 +4,13 @@
4
4
  import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
5
5
  import { range } from '@aztec/foundation/array';
6
6
  import { SecretValue } from '@aztec/foundation/config';
7
- import { addLogNameHandler, removeLogNameHandler } from '@aztec/foundation/log';
7
+ import { withLoggerBindings } from '@aztec/foundation/log/server';
8
8
  import { bufferToHex } from '@aztec/foundation/string';
9
9
  import type { DateProvider } from '@aztec/foundation/timer';
10
10
  import type { ProverNodeConfig, ProverNodeDeps } from '@aztec/prover-node';
11
11
  import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
12
12
 
13
13
  import getPort from 'get-port';
14
- import { AsyncLocalStorage } from 'node:async_hooks';
15
14
 
16
15
  import { TEST_PEER_CHECK_INTERVAL_MS } from './fixtures.js';
17
16
  import { createAndSyncProverNode, getPrivateKeyFromIndex } from './utils.js';
@@ -22,6 +21,11 @@ import { getEndToEndTestTelemetryClient } from './with_telemetry_utils.js';
22
21
  // to avoid running validators with the same key
23
22
  export const ATTESTER_PRIVATE_KEYS_START_INDEX = 3;
24
23
 
24
+ // Global counters for actor naming (start at 1)
25
+ let validatorCounter = 1;
26
+ let nodeCounter = 1;
27
+ let proverCounter = 1;
28
+
25
29
  export function generatePrivateKeys(startIndex: number, numberOfKeys: number): `0x${string}`[] {
26
30
  const privateKeys: `0x${string}`[] = [];
27
31
  // Do not start from 0 as it is used during setup
@@ -44,10 +48,6 @@ export async function createNodes(
44
48
  validatorsPerNode = 1,
45
49
  ): Promise<AztecNodeService[]> {
46
50
  const nodePromises: Promise<AztecNodeService>[] = [];
47
- const loggerIdStorage = new AsyncLocalStorage<string>();
48
- const logNameHandler = (module: string) =>
49
- loggerIdStorage.getStore() ? `${module}:${loggerIdStorage.getStore()}` : module;
50
- addLogNameHandler(logNameHandler);
51
51
 
52
52
  for (let i = 0; i < numNodes; i++) {
53
53
  const index = indexOffset + i;
@@ -69,7 +69,6 @@ export async function createNodes(
69
69
  prefilledPublicData,
70
70
  dataDir,
71
71
  metricsPort,
72
- loggerIdStorage,
73
72
  );
74
73
  nodePromises.push(nodePromise);
75
74
  }
@@ -81,13 +80,20 @@ export async function createNodes(
81
80
  throw new Error('Sequencer not found');
82
81
  }
83
82
 
84
- removeLogNameHandler(logNameHandler);
85
83
  return nodes;
86
84
  }
87
85
 
88
- /** Creates a P2P enabled instance of Aztec Node Service with a validator */
86
+ /** Extended config type for createNode with test-specific overrides. */
87
+ export type CreateNodeConfig = AztecNodeConfig & {
88
+ /** Whether to skip starting the sequencer. */
89
+ dontStartSequencer?: boolean;
90
+ /** Override the private key (instead of deriving from addressIndex). */
91
+ validatorPrivateKey?: `0x${string}`;
92
+ };
93
+
94
+ /** Creates a P2P enabled instance of Aztec Node Service with a validator. */
89
95
  export async function createNode(
90
- config: AztecNodeConfig & { dontStartSequencer?: boolean },
96
+ config: CreateNodeConfig,
91
97
  dateProvider: DateProvider,
92
98
  tcpPort: number,
93
99
  bootstrapNode: string | undefined,
@@ -95,9 +101,9 @@ export async function createNode(
95
101
  prefilledPublicData?: PublicDataTreeLeaf[],
96
102
  dataDirectory?: string,
97
103
  metricsPort?: number,
98
- loggerIdStorage?: AsyncLocalStorage<string>,
99
104
  ) {
100
- const createNode = async () => {
105
+ const actorIndex = validatorCounter++;
106
+ return await withLoggerBindings({ actor: `validator-${actorIndex}` }, async () => {
101
107
  const validatorConfig = await createValidatorConfig(config, bootstrapNode, tcpPort, addressIndex, dataDirectory);
102
108
  const telemetry = await getEndToEndTestTelemetryClient(metricsPort);
103
109
  return await AztecNodeService.createAndSync(
@@ -105,8 +111,7 @@ export async function createNode(
105
111
  { telemetry, dateProvider },
106
112
  { prefilledPublicData, dontStartSequencer: config.dontStartSequencer },
107
113
  );
108
- };
109
- return loggerIdStorage ? await loggerIdStorage.run(tcpPort.toString(), createNode) : createNode();
114
+ });
110
115
  }
111
116
 
112
117
  /** Creates a P2P enabled instance of Aztec Node Service without a validator */
@@ -118,9 +123,9 @@ export async function createNonValidatorNode(
118
123
  prefilledPublicData?: PublicDataTreeLeaf[],
119
124
  dataDirectory?: string,
120
125
  metricsPort?: number,
121
- loggerIdStorage?: AsyncLocalStorage<string>,
122
126
  ) {
123
- const createNode = async () => {
127
+ const actorIndex = nodeCounter++;
128
+ return await withLoggerBindings({ actor: `node-${actorIndex}` }, async () => {
124
129
  const p2pConfig = await createP2PConfig(baseConfig, bootstrapNode, tcpPort, dataDirectory);
125
130
  const config: AztecNodeConfig = {
126
131
  ...p2pConfig,
@@ -130,8 +135,7 @@ export async function createNonValidatorNode(
130
135
  };
131
136
  const telemetry = await getEndToEndTestTelemetryClient(metricsPort);
132
137
  return await AztecNodeService.createAndSync(config, { telemetry, dateProvider }, { prefilledPublicData });
133
- };
134
- return loggerIdStorage ? await loggerIdStorage.run(tcpPort.toString(), createNode) : createNode();
138
+ });
135
139
  }
136
140
 
137
141
  export async function createProverNode(
@@ -143,9 +147,9 @@ export async function createProverNode(
143
147
  prefilledPublicData?: PublicDataTreeLeaf[],
144
148
  dataDirectory?: string,
145
149
  metricsPort?: number,
146
- loggerIdStorage?: AsyncLocalStorage<string>,
147
150
  ) {
148
- const createProverNode = async () => {
151
+ const actorIndex = proverCounter++;
152
+ return await withLoggerBindings({ actor: `prover-${actorIndex}` }, async () => {
149
153
  const proverNodePrivateKey = getPrivateKeyFromIndex(ATTESTER_PRIVATE_KEYS_START_INDEX + addressIndex)!;
150
154
  const telemetry = await getEndToEndTestTelemetryClient(metricsPort);
151
155
 
@@ -165,8 +169,7 @@ export async function createProverNode(
165
169
  prefilledPublicData,
166
170
  { ...proverNodeDeps, telemetry },
167
171
  );
168
- };
169
- return loggerIdStorage ? await loggerIdStorage.run(tcpPort.toString(), createProverNode) : createProverNode();
172
+ });
170
173
  }
171
174
 
172
175
  export async function createP2PConfig(
@@ -192,20 +195,21 @@ export async function createP2PConfig(
192
195
  }
193
196
 
194
197
  export async function createValidatorConfig(
195
- config: AztecNodeConfig,
198
+ config: CreateNodeConfig,
196
199
  bootstrapNodeEnr?: string,
197
200
  port?: number,
198
201
  addressIndex: number | number[] = 1,
199
202
  dataDirectory?: string,
200
203
  ) {
201
204
  const addressIndices = Array.isArray(addressIndex) ? addressIndex : [addressIndex];
202
- if (addressIndices.length === 0) {
205
+ if (addressIndices.length === 0 && !config.validatorPrivateKey) {
203
206
  throw new Error('At least one address index must be provided to create a validator config');
204
207
  }
205
208
 
206
- const attesterPrivateKeys = addressIndices.map(index =>
207
- bufferToHex(getPrivateKeyFromIndex(ATTESTER_PRIVATE_KEYS_START_INDEX + index)!),
208
- );
209
+ // Use override private key if provided, otherwise derive from address indices
210
+ const attesterPrivateKeys = config.validatorPrivateKey
211
+ ? [config.validatorPrivateKey]
212
+ : addressIndices.map(index => bufferToHex(getPrivateKeyFromIndex(ATTESTER_PRIVATE_KEYS_START_INDEX + index)!));
209
213
  const p2pConfig = await createP2PConfig(config, bootstrapNodeEnr, port, dataDirectory);
210
214
  const nodeConfig: AztecNodeConfig = {
211
215
  ...config,
@@ -6,9 +6,10 @@ import { TokenContract } from '@aztec/noir-contracts.js/Token';
6
6
 
7
7
  export async function deployToken(wallet: Wallet, admin: AztecAddress, initialAdminBalance: bigint, logger: Logger) {
8
8
  logger.info(`Deploying Token contract...`);
9
- const { contract, instance } = await TokenContract.deploy(wallet, admin, 'TokenName', 'TokenSymbol', 18)
10
- .send({ from: admin })
11
- .wait();
9
+ const { contract, instance } = await TokenContract.deploy(wallet, admin, 'TokenName', 'TokenSymbol', 18).send({
10
+ from: admin,
11
+ wait: { returnReceipt: true },
12
+ });
12
13
 
13
14
  if (initialAdminBalance > 0n) {
14
15
  await mintTokensToPrivate(contract, admin, admin, initialAdminBalance);
@@ -25,7 +26,7 @@ export async function mintTokensToPrivate(
25
26
  recipient: AztecAddress,
26
27
  amount: bigint,
27
28
  ) {
28
- await token.methods.mint_to_private(recipient, amount).send({ from: minter }).wait();
29
+ await token.methods.mint_to_private(recipient, amount).send({ from: minter });
29
30
  }
30
31
 
31
32
  export async function expectTokenBalance(
@@ -55,7 +56,7 @@ export async function mintNotes(
55
56
  for (let mintedNotes = 0; mintedNotes < noteAmounts.length; mintedNotes += notesPerIteration) {
56
57
  const toMint = noteAmounts.slice(mintedNotes, mintedNotes + notesPerIteration);
57
58
  const actions = toMint.map(amt => asset.methods.mint_to_private(recipient, amt));
58
- await new BatchCall(wallet, actions).send({ from: minter }).wait();
59
+ await new BatchCall(wallet, actions).send({ from: minter });
59
60
  }
60
61
 
61
62
  return noteAmounts.reduce((prev, curr) => prev + curr, 0n);
@@ -18,7 +18,6 @@ import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses'
18
18
  import type { ExtendedViemWalletClient } from '@aztec/ethereum/types';
19
19
  import { EpochNumber } from '@aztec/foundation/branded-types';
20
20
  import { retryUntil } from '@aztec/foundation/retry';
21
- import type { FieldsOf } from '@aztec/foundation/types';
22
21
  import { TestERC20Abi, TokenPortalAbi, TokenPortalBytecode } from '@aztec/l1-artifacts';
23
22
  import { TokenContract } from '@aztec/noir-contracts.js/Token';
24
23
  import { TokenBridgeContract } from '@aztec/noir-contracts.js/TokenBridge';
@@ -74,14 +73,10 @@ export async function deployAndInitializeTokenAndBridgeContracts(
74
73
  });
75
74
 
76
75
  // deploy l2 token
77
- const token = await TokenContract.deploy(wallet, owner, 'TokenName', 'TokenSymbol', 18)
78
- .send({ from: owner })
79
- .deployed();
76
+ const token = await TokenContract.deploy(wallet, owner, 'TokenName', 'TokenSymbol', 18).send({ from: owner });
80
77
 
81
78
  // deploy l2 token bridge and attach to the portal
82
- const bridge = await TokenBridgeContract.deploy(wallet, token.address, tokenPortalAddress)
83
- .send({ from: owner })
84
- .deployed();
79
+ const bridge = await TokenBridgeContract.deploy(wallet, token.address, tokenPortalAddress).send({ from: owner });
85
80
 
86
81
  if ((await token.methods.get_admin().simulate({ from: owner })) !== owner.toBigInt()) {
87
82
  throw new Error(`Token admin is not ${owner}`);
@@ -92,7 +87,7 @@ export async function deployAndInitializeTokenAndBridgeContracts(
92
87
  }
93
88
 
94
89
  // make the bridge a minter on the token:
95
- await token.methods.set_minter(bridge.address, true).send({ from: owner }).wait();
90
+ await token.methods.set_minter(bridge.address, true).send({ from: owner });
96
91
  if ((await token.methods.is_minter(bridge.address).simulate({ from: owner })) === 1n) {
97
92
  throw new Error(`Bridge is not a minter`);
98
93
  }
@@ -235,7 +230,7 @@ export class CrossChainTestHarness {
235
230
 
236
231
  async mintTokensPublicOnL2(amount: bigint) {
237
232
  this.logger.info('Minting tokens on L2 publicly');
238
- await this.l2Token.methods.mint_to_public(this.ownerAddress, amount).send({ from: this.ownerAddress }).wait();
233
+ await this.l2Token.methods.mint_to_public(this.ownerAddress, amount).send({ from: this.ownerAddress });
239
234
  }
240
235
 
241
236
  async mintTokensPrivateOnL2(amount: bigint) {
@@ -246,8 +241,7 @@ export class CrossChainTestHarness {
246
241
  // send a transfer tx to force through rollup with the message included
247
242
  await this.l2Token.methods
248
243
  .transfer_in_public(this.ownerAddress, receiverAddress, transferAmount, 0)
249
- .send({ from: this.ownerAddress })
250
- .wait();
244
+ .send({ from: this.ownerAddress });
251
245
  }
252
246
 
253
247
  async consumeMessageOnAztecAndMintPrivately(
@@ -257,8 +251,7 @@ export class CrossChainTestHarness {
257
251
  const { recipient, claimAmount, claimSecret: secretForL2MessageConsumption, messageLeafIndex } = claim;
258
252
  await this.l2Bridge.methods
259
253
  .claim_private(recipient, claimAmount, secretForL2MessageConsumption, messageLeafIndex)
260
- .send({ from: this.ownerAddress })
261
- .wait();
254
+ .send({ from: this.ownerAddress });
262
255
  }
263
256
 
264
257
  async consumeMessageOnAztecAndMintPublicly(
@@ -268,28 +261,25 @@ export class CrossChainTestHarness {
268
261
  const { claimAmount, claimSecret, messageLeafIndex } = claim;
269
262
  await this.l2Bridge.methods
270
263
  .claim_public(this.ownerAddress, claimAmount, claimSecret, messageLeafIndex)
271
- .send({ from: this.ownerAddress })
272
- .wait();
264
+ .send({ from: this.ownerAddress });
273
265
  }
274
266
 
275
267
  async withdrawPrivateFromAztecToL1(
276
268
  withdrawAmount: bigint,
277
269
  authwitNonce: Fr = Fr.ZERO,
278
270
  authWitness: AuthWitness,
279
- ): Promise<FieldsOf<TxReceipt>> {
271
+ ): Promise<TxReceipt> {
280
272
  const withdrawReceipt = await this.l2Bridge.methods
281
273
  .exit_to_l1_private(this.l2Token.address, this.ethAccount, withdrawAmount, EthAddress.ZERO, authwitNonce)
282
- .send({ authWitnesses: [authWitness], from: this.ownerAddress })
283
- .wait();
274
+ .send({ authWitnesses: [authWitness], from: this.ownerAddress });
284
275
 
285
276
  return withdrawReceipt;
286
277
  }
287
278
 
288
- async withdrawPublicFromAztecToL1(withdrawAmount: bigint, authwitNonce: Fr = Fr.ZERO): Promise<FieldsOf<TxReceipt>> {
279
+ async withdrawPublicFromAztecToL1(withdrawAmount: bigint, authwitNonce: Fr = Fr.ZERO): Promise<TxReceipt> {
289
280
  const withdrawReceipt = await this.l2Bridge.methods
290
281
  .exit_to_l1_public(this.ethAccount, withdrawAmount, EthAddress.ZERO, authwitNonce)
291
- .send({ from: this.ownerAddress })
292
- .wait();
282
+ .send({ from: this.ownerAddress });
293
283
 
294
284
  return withdrawReceipt;
295
285
  }
@@ -333,18 +323,14 @@ export class CrossChainTestHarness {
333
323
 
334
324
  async transferToPrivateOnL2(shieldAmount: bigint) {
335
325
  this.logger.info('Transferring to private on L2');
336
- await this.l2Token.methods
337
- .transfer_to_private(this.ownerAddress, shieldAmount)
338
- .send({ from: this.ownerAddress })
339
- .wait();
326
+ await this.l2Token.methods.transfer_to_private(this.ownerAddress, shieldAmount).send({ from: this.ownerAddress });
340
327
  }
341
328
 
342
329
  async transferToPublicOnL2(amount: bigint, authwitNonce = Fr.ZERO) {
343
330
  this.logger.info('Transferring tokens to public');
344
331
  await this.l2Token.methods
345
332
  .transfer_to_public(this.ownerAddress, this.ownerAddress, amount, authwitNonce)
346
- .send({ from: this.ownerAddress })
347
- .wait();
333
+ .send({ from: this.ownerAddress });
348
334
  }
349
335
 
350
336
  /**
@@ -127,7 +127,7 @@ export class GasBridgingTestHarness implements IGasBridgingTestHarness {
127
127
  async consumeMessageOnAztecAndClaimPrivately(owner: AztecAddress, claimer: AztecAddress, claim: L2AmountClaim) {
128
128
  this.logger.info('Consuming messages on L2 Privately');
129
129
  const { claimAmount, claimSecret, messageLeafIndex } = claim;
130
- await this.feeJuice.methods.claim(owner, claimAmount, claimSecret, messageLeafIndex).send({ from: claimer }).wait();
130
+ await this.feeJuice.methods.claim(owner, claimAmount, claimSecret, messageLeafIndex).send({ from: claimer });
131
131
  }
132
132
 
133
133
  async getL2PublicBalanceOf(owner: AztecAddress) {