@aztec/aztec 0.0.1-commit.f295ac2 → 0.0.1-commit.f504929

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 (100) hide show
  1. package/dest/bin/index.js +5 -1
  2. package/dest/cli/admin_api_key_store.d.ts +45 -0
  3. package/dest/cli/admin_api_key_store.d.ts.map +1 -0
  4. package/dest/cli/admin_api_key_store.js +98 -0
  5. package/dest/cli/aztec_start_action.d.ts +1 -1
  6. package/dest/cli/aztec_start_action.d.ts.map +1 -1
  7. package/dest/cli/aztec_start_action.js +46 -10
  8. package/dest/cli/aztec_start_options.d.ts +1 -1
  9. package/dest/cli/aztec_start_options.d.ts.map +1 -1
  10. package/dest/cli/aztec_start_options.js +27 -8
  11. package/dest/cli/cli.d.ts +1 -1
  12. package/dest/cli/cli.d.ts.map +1 -1
  13. package/dest/cli/cli.js +3 -4
  14. package/dest/cli/cmds/compile.d.ts +4 -0
  15. package/dest/cli/cmds/compile.d.ts.map +1 -0
  16. package/dest/cli/cmds/compile.js +160 -0
  17. package/dest/cli/cmds/profile.d.ts +4 -0
  18. package/dest/cli/cmds/profile.d.ts.map +1 -0
  19. package/dest/cli/cmds/profile.js +8 -0
  20. package/dest/cli/cmds/profile_flamegraph.d.ts +4 -0
  21. package/dest/cli/cmds/profile_flamegraph.d.ts.map +1 -0
  22. package/dest/cli/cmds/profile_flamegraph.js +51 -0
  23. package/dest/cli/cmds/profile_gates.d.ts +4 -0
  24. package/dest/cli/cmds/profile_gates.d.ts.map +1 -0
  25. package/dest/cli/cmds/profile_gates.js +57 -0
  26. package/dest/cli/cmds/profile_utils.d.ts +18 -0
  27. package/dest/cli/cmds/profile_utils.d.ts.map +1 -0
  28. package/dest/cli/cmds/profile_utils.js +50 -0
  29. package/dest/cli/cmds/start_bot.d.ts +3 -3
  30. package/dest/cli/cmds/start_bot.d.ts.map +1 -1
  31. package/dest/cli/cmds/start_bot.js +9 -5
  32. package/dest/cli/cmds/start_node.d.ts +1 -1
  33. package/dest/cli/cmds/start_node.d.ts.map +1 -1
  34. package/dest/cli/cmds/start_node.js +118 -10
  35. package/dest/cli/cmds/start_p2p_bootstrap.d.ts +2 -2
  36. package/dest/cli/cmds/start_p2p_bootstrap.d.ts.map +1 -1
  37. package/dest/cli/cmds/start_p2p_bootstrap.js +1 -2
  38. package/dest/cli/cmds/start_prover_agent.js +2 -2
  39. package/dest/cli/cmds/start_prover_broker.d.ts +1 -1
  40. package/dest/cli/cmds/start_prover_broker.d.ts.map +1 -1
  41. package/dest/cli/cmds/start_prover_broker.js +2 -2
  42. package/dest/cli/cmds/utils/artifacts.d.ts +21 -0
  43. package/dest/cli/cmds/utils/artifacts.d.ts.map +1 -0
  44. package/dest/cli/cmds/utils/artifacts.js +24 -0
  45. package/dest/cli/cmds/utils/spawn.d.ts +3 -0
  46. package/dest/cli/cmds/utils/spawn.d.ts.map +1 -0
  47. package/dest/cli/cmds/utils/spawn.js +16 -0
  48. package/dest/cli/util.d.ts +5 -14
  49. package/dest/cli/util.d.ts.map +1 -1
  50. package/dest/cli/util.js +13 -8
  51. package/dest/examples/token.js +9 -9
  52. package/dest/local-network/banana_fpc.d.ts +1 -1
  53. package/dest/local-network/banana_fpc.d.ts.map +1 -1
  54. package/dest/local-network/banana_fpc.js +3 -3
  55. package/dest/local-network/local-network.d.ts +4 -3
  56. package/dest/local-network/local-network.d.ts.map +1 -1
  57. package/dest/local-network/local-network.js +43 -20
  58. package/dest/testing/anvil_test_watcher.d.ts +9 -1
  59. package/dest/testing/anvil_test_watcher.d.ts.map +1 -1
  60. package/dest/testing/anvil_test_watcher.js +52 -15
  61. package/dest/testing/epoch_test_settler.d.ts +4 -2
  62. package/dest/testing/epoch_test_settler.d.ts.map +1 -1
  63. package/dest/testing/epoch_test_settler.js +15 -5
  64. package/package.json +34 -34
  65. package/scripts/add_crate.sh +102 -0
  66. package/scripts/aztec.sh +8 -5
  67. package/scripts/init.sh +23 -19
  68. package/scripts/new.sh +48 -24
  69. package/scripts/setup_workspace.sh +68 -0
  70. package/src/bin/index.ts +5 -1
  71. package/src/cli/admin_api_key_store.ts +128 -0
  72. package/src/cli/aztec_start_action.ts +50 -6
  73. package/src/cli/aztec_start_options.ts +28 -6
  74. package/src/cli/cli.ts +3 -4
  75. package/src/cli/cmds/compile.ts +184 -0
  76. package/src/cli/cmds/profile.ts +25 -0
  77. package/src/cli/cmds/profile_flamegraph.ts +63 -0
  78. package/src/cli/cmds/profile_gates.ts +67 -0
  79. package/src/cli/cmds/profile_utils.ts +58 -0
  80. package/src/cli/cmds/start_bot.ts +8 -5
  81. package/src/cli/cmds/start_node.ts +137 -9
  82. package/src/cli/cmds/start_p2p_bootstrap.ts +2 -2
  83. package/src/cli/cmds/start_prover_agent.ts +2 -2
  84. package/src/cli/cmds/start_prover_broker.ts +5 -1
  85. package/src/cli/cmds/utils/artifacts.ts +44 -0
  86. package/src/cli/cmds/utils/spawn.ts +16 -0
  87. package/src/cli/util.ts +16 -21
  88. package/src/examples/token.ts +10 -10
  89. package/src/local-network/banana_fpc.ts +11 -7
  90. package/src/local-network/local-network.ts +56 -23
  91. package/src/testing/anvil_test_watcher.ts +59 -15
  92. package/src/testing/epoch_test_settler.ts +16 -4
  93. package/dest/cli/cmds/start_prover_node.d.ts +0 -7
  94. package/dest/cli/cmds/start_prover_node.d.ts.map +0 -1
  95. package/dest/cli/cmds/start_prover_node.js +0 -108
  96. package/scripts/compile.sh +0 -44
  97. package/scripts/extract_function.js +0 -47
  98. package/scripts/flamegraph.sh +0 -59
  99. package/scripts/setup_project.sh +0 -31
  100. package/src/cli/cmds/start_prover_node.ts +0 -124
@@ -4,20 +4,29 @@ import { Fr } from '@aztec/aztec.js/fields';
4
4
  import { getSponsoredFPCAddress } from '@aztec/cli/cli-utils';
5
5
  import { getL1Config } from '@aztec/cli/config';
6
6
  import { getPublicClient } from '@aztec/ethereum/client';
7
+ import { RegistryContract, RollupContract } from '@aztec/ethereum/contracts';
7
8
  import { SecretValue } from '@aztec/foundation/config';
9
+ import { EthAddress } from '@aztec/foundation/eth-address';
8
10
  import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server';
11
+ import { startHttpRpcServer } from '@aztec/foundation/json-rpc/server';
12
+ import { Agent, makeUndiciFetch } from '@aztec/foundation/json-rpc/undici';
9
13
  import type { LogFn } from '@aztec/foundation/log';
14
+ import { sleep } from '@aztec/foundation/sleep';
15
+ import { ProvingJobConsumerSchema, createProvingJobBrokerClient } from '@aztec/prover-client/broker';
10
16
  import { type CliPXEOptions, type PXEConfig, allPxeConfigMappings } from '@aztec/pxe/config';
11
17
  import { AztecNodeAdminApiSchema, AztecNodeApiSchema } from '@aztec/stdlib/interfaces/client';
12
- import { P2PApiSchema } from '@aztec/stdlib/interfaces/server';
18
+ import { P2PApiSchema, ProverNodeApiSchema, type ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
13
19
  import {
14
20
  type TelemetryClientConfig,
15
21
  initTelemetryClient,
22
+ makeTracedFetch,
16
23
  telemetryClientConfigMappings,
17
24
  } from '@aztec/telemetry-client';
18
- import { TestWallet } from '@aztec/test-wallet/server';
25
+ import { EmbeddedWallet } from '@aztec/wallets/embedded';
19
26
  import { getGenesisValues } from '@aztec/world-state/testing';
20
27
 
28
+ import Koa from 'koa';
29
+
21
30
  import { createAztecNode } from '../../local-network/index.js';
22
31
  import {
23
32
  extractNamespacedOptions,
@@ -25,6 +34,74 @@ import {
25
34
  preloadCrsDataForVerifying,
26
35
  setupUpdateMonitor,
27
36
  } from '../util.js';
37
+ import { getVersions } from '../versioning.js';
38
+ import { startProverBroker } from './start_prover_broker.js';
39
+
40
+ const ROLLUP_POLL_INTERVAL_MS = 600_000;
41
+
42
+ /**
43
+ * Waits until the canonical rollup's genesis archive root matches the expected local genesis root.
44
+ * If the rollup is not yet compatible (e.g. during L1 contract upgrades), enters standby mode:
45
+ * starts a lightweight HTTP server for K8s liveness probes and polls until a compatible rollup appears.
46
+ */
47
+ async function waitForCompatibleRollup(
48
+ publicClient: ReturnType<typeof getPublicClient>,
49
+ registryAddress: EthAddress,
50
+ rollupVersion: number | 'canonical',
51
+ expectedGenesisRoot: Fr,
52
+ port: number | undefined,
53
+ userLog: LogFn,
54
+ ): Promise<void> {
55
+ const registry = new RegistryContract(publicClient, registryAddress);
56
+ const rollupAddress = await registry.getRollupAddress(rollupVersion);
57
+ const rollup = new RollupContract(publicClient, rollupAddress.toString());
58
+
59
+ let l1GenesisRoot: Fr;
60
+ try {
61
+ l1GenesisRoot = await rollup.getGenesisArchiveTreeRoot();
62
+ } catch (err: any) {
63
+ throw new Error(
64
+ `Could not retrieve genesis archive root from canonical rollup at ${rollupAddress}: ${err.message}`,
65
+ );
66
+ }
67
+
68
+ if (l1GenesisRoot.equals(expectedGenesisRoot)) {
69
+ return;
70
+ }
71
+
72
+ userLog(
73
+ `Genesis root mismatch: expected ${expectedGenesisRoot}, got ${l1GenesisRoot} from rollup at ${rollupAddress}. ` +
74
+ `Entering standby mode. Will poll every ${ROLLUP_POLL_INTERVAL_MS / 1000}s for a compatible rollup...`,
75
+ );
76
+
77
+ const standbyServer = await startHttpRpcServer({ getApp: () => new Koa(), isHealthy: () => true }, { port });
78
+ userLog(`Standby status server listening on port ${standbyServer.port}`);
79
+
80
+ try {
81
+ while (true) {
82
+ await sleep(ROLLUP_POLL_INTERVAL_MS);
83
+
84
+ const currentRollupAddress = await registry.getRollupAddress(rollupVersion);
85
+ const currentRollup = new RollupContract(publicClient, currentRollupAddress.toString());
86
+
87
+ try {
88
+ l1GenesisRoot = await currentRollup.getGenesisArchiveTreeRoot();
89
+ } catch {
90
+ userLog(`Failed to fetch genesis root from rollup at ${currentRollupAddress}. Retrying...`);
91
+ continue;
92
+ }
93
+
94
+ if (l1GenesisRoot.equals(expectedGenesisRoot)) {
95
+ userLog(`Compatible rollup found at ${currentRollupAddress}. Exiting standby mode.`);
96
+ return;
97
+ }
98
+
99
+ userLog(`Still waiting. Rollup at ${currentRollupAddress} has genesis root ${l1GenesisRoot}.`);
100
+ }
101
+ } finally {
102
+ await new Promise<void>((resolve, reject) => standbyServer.close(err => (err ? reject(err) : resolve())));
103
+ }
104
+ }
28
105
 
29
106
  export async function startNode(
30
107
  options: any,
@@ -45,9 +122,32 @@ export async function startNode(
45
122
  ...relevantOptions,
46
123
  };
47
124
 
125
+ // Prover node configuration and broker setup
126
+ // REFACTOR: Move the broker setup out of here and into the prover-node factory
127
+ let broker: ProvingJobBroker | undefined = undefined;
48
128
  if (options.proverNode) {
49
- userLog(`Running a Prover Node within a Node is not yet supported`);
50
- process.exit(1);
129
+ nodeConfig.enableProverNode = true;
130
+ if (nodeConfig.proverAgentCount === 0) {
131
+ userLog(
132
+ `Running prover node without local prover agent. Connect prover agents or pass --proverAgent.proverAgentCount`,
133
+ );
134
+ }
135
+ if (nodeConfig.proverBrokerUrl) {
136
+ // at 1TPS we'd enqueue ~1k chonk verifier proofs and ~1k AVM proofs immediately
137
+ // set a lower connection limit such that we don't overload the server
138
+ // Keep retrying up to 30s
139
+ const fetch = makeTracedFetch(
140
+ [1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3],
141
+ false,
142
+ makeUndiciFetch(new Agent({ connections: 100 })),
143
+ );
144
+ broker = createProvingJobBrokerClient(nodeConfig.proverBrokerUrl, getVersions(nodeConfig), fetch);
145
+ } else if (options.proverBroker) {
146
+ ({ broker } = await startProverBroker(options, signalHandlers, services, userLog));
147
+ } else {
148
+ userLog(`--prover-broker-url or --prover-broker is required to start a Prover Node`);
149
+ process.exit(1);
150
+ }
51
151
  }
52
152
 
53
153
  await preloadCrsDataForVerifying(nodeConfig, userLog);
@@ -68,6 +168,20 @@ export async function startNode(
68
168
  if (!nodeConfig.l1Contracts.registryAddress || nodeConfig.l1Contracts.registryAddress.isZero()) {
69
169
  throw new Error('L1 registry address is required to start Aztec Node');
70
170
  }
171
+
172
+ // Wait for a compatible rollup before proceeding with full L1 config fetch.
173
+ // This prevents crashes when the canonical rollup hasn't been upgraded yet.
174
+ const publicClient = getPublicClient(nodeConfig);
175
+ const rollupVersion: number | 'canonical' = nodeConfig.rollupVersion ?? 'canonical';
176
+ await waitForCompatibleRollup(
177
+ publicClient,
178
+ nodeConfig.l1Contracts.registryAddress,
179
+ rollupVersion,
180
+ genesisArchiveRoot,
181
+ options.port,
182
+ userLog,
183
+ );
184
+
71
185
  const { addresses, config } = await getL1Config(
72
186
  nodeConfig.l1Contracts.registryAddress,
73
187
  nodeConfig.l1RpcUrls,
@@ -101,12 +215,17 @@ export async function startNode(
101
215
  ...extractNamespacedOptions(options, 'sequencer'),
102
216
  };
103
217
  // If no publisher private keys have been given, use the first validator key
104
- if (sequencerConfig.publisherPrivateKeys === undefined || !sequencerConfig.publisherPrivateKeys.length) {
218
+ if (
219
+ sequencerConfig.sequencerPublisherPrivateKeys === undefined ||
220
+ !sequencerConfig.sequencerPublisherPrivateKeys.length
221
+ ) {
105
222
  if (sequencerConfig.validatorPrivateKeys?.getValue().length) {
106
- sequencerConfig.publisherPrivateKeys = [new SecretValue(sequencerConfig.validatorPrivateKeys.getValue()[0])];
223
+ sequencerConfig.sequencerPublisherPrivateKeys = [
224
+ new SecretValue(sequencerConfig.validatorPrivateKeys.getValue()[0]),
225
+ ];
107
226
  }
108
227
  }
109
- nodeConfig.publisherPrivateKeys = sequencerConfig.publisherPrivateKeys;
228
+ nodeConfig.sequencerPublisherPrivateKeys = sequencerConfig.sequencerPublisherPrivateKeys;
110
229
  }
111
230
 
112
231
  if (nodeConfig.p2pEnabled) {
@@ -120,13 +239,22 @@ export async function startNode(
120
239
  const telemetry = await initTelemetryClient(telemetryConfig);
121
240
 
122
241
  // Create and start Aztec Node
123
- const node = await createAztecNode(nodeConfig, { telemetry }, { prefilledPublicData });
242
+ const node = await createAztecNode(nodeConfig, { telemetry, proverBroker: broker }, { prefilledPublicData });
124
243
 
125
244
  // Add node and p2p to services list
126
245
  services.node = [node, AztecNodeApiSchema];
127
246
  services.p2p = [node.getP2P(), P2PApiSchema];
128
247
  adminServices.nodeAdmin = [node, AztecNodeAdminApiSchema];
129
248
 
249
+ // Register prover-node services if the prover node subsystem is running
250
+ const proverNode = node.getProverNode();
251
+ if (proverNode) {
252
+ services.prover = [proverNode, ProverNodeApiSchema];
253
+ if (!nodeConfig.proverBrokerUrl) {
254
+ services.provingJobSource = [proverNode.getProver().getProvingJobSource(), ProvingJobConsumerSchema];
255
+ }
256
+ }
257
+
130
258
  // Add node stop function to signal handlers
131
259
  signalHandlers.push(node.stop.bind(node));
132
260
 
@@ -135,7 +263,7 @@ export async function startNode(
135
263
  const { addBot } = await import('./start_bot.js');
136
264
 
137
265
  const pxeConfig = extractRelevantOptions<PXEConfig & CliPXEOptions>(options, allPxeConfigMappings, 'pxe');
138
- const wallet = await TestWallet.create(node, pxeConfig);
266
+ const wallet = await EmbeddedWallet.create(node, { pxeConfig });
139
267
 
140
268
  await addBot(options, signalHandlers, services, wallet, node, telemetry, undefined);
141
269
  }
@@ -1,6 +1,6 @@
1
1
  import { jsonStringify } from '@aztec/foundation/json-rpc';
2
2
  import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server';
3
- import { type LogFn, createLogger } from '@aztec/foundation/log';
3
+ import type { LogFn } from '@aztec/foundation/log';
4
4
  import { createStore } from '@aztec/kv-store/lmdb-v2';
5
5
  import { type BootnodeConfig, BootstrapNode, bootnodeConfigMappings } from '@aztec/p2p';
6
6
  import { emptyChainConfig } from '@aztec/stdlib/config';
@@ -27,7 +27,7 @@ export async function startP2PBootstrap(
27
27
  const telemetryConfig = extractRelevantOptions<TelemetryClientConfig>(options, telemetryClientConfigMappings, 'tel');
28
28
  const telemetryClient = await initTelemetryClient(telemetryConfig);
29
29
 
30
- const store = await createStore('p2p-bootstrap', 1, config, createLogger('p2p:bootstrap:store'));
30
+ const store = await createStore('p2p-bootstrap', 1, config);
31
31
  const node = new BootstrapNode(store, telemetryClient);
32
32
  await node.start(config);
33
33
  signalHandlers.push(() => node.stop());
@@ -4,9 +4,9 @@ import { Agent, makeUndiciFetch } from '@aztec/foundation/json-rpc/undici';
4
4
  import type { LogFn } from '@aztec/foundation/log';
5
5
  import { buildServerCircuitProver } from '@aztec/prover-client';
6
6
  import {
7
- InlineProofStore,
8
7
  type ProverAgentConfig,
9
8
  ProvingAgent,
9
+ createProofStore,
10
10
  createProvingJobBrokerClient,
11
11
  proverAgentConfigMappings,
12
12
  } from '@aztec/prover-client/broker';
@@ -55,7 +55,7 @@ export async function startProverAgent(
55
55
 
56
56
  const telemetry = await initTelemetryClient(extractRelevantOptions(options, telemetryClientConfigMappings, 'tel'));
57
57
  const prover = await buildServerCircuitProver(config, telemetry);
58
- const proofStore = new InlineProofStore();
58
+ const proofStore = await createProofStore(config.proofStore);
59
59
  const agents = times(
60
60
  config.proverAgentCount,
61
61
  () => new ProvingAgent(broker, proofStore, prover, config.proverAgentProofTypes, config.proverAgentPollIntervalMs),
@@ -5,6 +5,7 @@ import type { LogFn } from '@aztec/foundation/log';
5
5
  import {
6
6
  type ProverBrokerConfig,
7
7
  ProvingJobBrokerSchema,
8
+ ProvingJobBrokerSchemaWithDebug,
8
9
  createAndStartProvingBroker,
9
10
  proverBrokerConfigMappings,
10
11
  } from '@aztec/prover-client/broker';
@@ -59,7 +60,10 @@ export async function startProverBroker(
59
60
  );
60
61
  }
61
62
 
62
- services.proverBroker = [broker, ProvingJobBrokerSchema];
63
+ services.proverBroker = [
64
+ broker,
65
+ config.proverBrokerDebugReplayEnabled ? ProvingJobBrokerSchemaWithDebug : ProvingJobBrokerSchema,
66
+ ];
63
67
  signalHandlers.push(() => broker.stop());
64
68
 
65
69
  return { broker, config };
@@ -0,0 +1,44 @@
1
+ import { readFile, readdir } from 'fs/promises';
2
+ import { join } from 'path';
3
+
4
+ export interface CompiledArtifact {
5
+ noir_version: string;
6
+ file_map: unknown;
7
+ functions: ContractFunction[];
8
+ bytecode?: string;
9
+ }
10
+
11
+ export interface ContractFunction {
12
+ name: string;
13
+ abi: unknown;
14
+ bytecode: string;
15
+ debug_symbols: unknown;
16
+ is_unconstrained?: boolean;
17
+ }
18
+
19
+ export interface ArtifactFile {
20
+ name: string;
21
+ filePath: string;
22
+ content: CompiledArtifact;
23
+ }
24
+
25
+ /** Reads all JSON artifact files from a target directory and returns their parsed contents. */
26
+ export async function readArtifactFiles(targetDir: string): Promise<ArtifactFile[]> {
27
+ let entries: string[];
28
+ try {
29
+ entries = (await readdir(targetDir)).filter(f => f.endsWith('.json'));
30
+ } catch (err: any) {
31
+ if (err?.code === 'ENOENT') {
32
+ throw new Error(`Target directory '${targetDir}' does not exist. Compile first with 'aztec compile'.`);
33
+ }
34
+ throw err;
35
+ }
36
+
37
+ const artifacts: ArtifactFile[] = [];
38
+ for (const file of entries) {
39
+ const filePath = join(targetDir, file);
40
+ const content = JSON.parse(await readFile(filePath, 'utf-8')) as CompiledArtifact;
41
+ artifacts.push({ name: file.replace('.json', ''), filePath, content });
42
+ }
43
+ return artifacts;
44
+ }
@@ -0,0 +1,16 @@
1
+ import { spawn } from 'child_process';
2
+
3
+ /** Spawns a command with inherited stdio and rejects on non-zero exit. */
4
+ export function run(cmd: string, args: string[]): Promise<void> {
5
+ return new Promise((resolve, reject) => {
6
+ const child = spawn(cmd, args, { stdio: 'inherit' });
7
+ child.on('error', reject);
8
+ child.on('close', code => {
9
+ if (code !== 0) {
10
+ reject(new Error(`${cmd} exited with code ${code}`));
11
+ } else {
12
+ resolve();
13
+ }
14
+ });
15
+ });
16
+ }
package/src/cli/util.ts CHANGED
@@ -2,13 +2,13 @@ import type { AztecNodeConfig } from '@aztec/aztec-node';
2
2
  import type { AccountManager } from '@aztec/aztec.js/wallet';
3
3
  import type { ViemClient } from '@aztec/ethereum/types';
4
4
  import type { ConfigMappingsType } from '@aztec/foundation/config';
5
- import { Fr } from '@aztec/foundation/curves/bn254';
6
5
  import { EthAddress } from '@aztec/foundation/eth-address';
6
+ import { jsonStringify } from '@aztec/foundation/json-rpc';
7
7
  import { type LogFn, createLogger } from '@aztec/foundation/log';
8
8
  import type { SharedNodeConfig } from '@aztec/node-lib/config';
9
9
  import type { ProverConfig } from '@aztec/stdlib/interfaces/server';
10
10
  import { getTelemetryClient } from '@aztec/telemetry-client/start';
11
- import type { TestWallet } from '@aztec/test-wallet/server';
11
+ import type { EmbeddedWallet } from '@aztec/wallets/embedded';
12
12
 
13
13
  import chalk from 'chalk';
14
14
  import type { Command } from 'commander';
@@ -68,30 +68,19 @@ export const installSignalHandlers = (logFn: LogFn, cb?: Array<() => Promise<voi
68
68
  /**
69
69
  * Creates logs for the initial accounts
70
70
  * @param accounts - The initial accounts
71
- * @param wallet - A TestWallet instance to get the registered accounts
71
+ * @param wallet - A EmbeddedWallet instance to get the registered accounts
72
72
  * @returns A string array containing the initial accounts details
73
73
  */
74
- export async function createAccountLogs(
75
- accountsWithSecretKeys: {
76
- /**
77
- * The account object
78
- */
79
- account: AccountManager;
80
- /**
81
- * The secret key of the account
82
- */
83
- secretKey: Fr;
84
- }[],
85
- wallet: TestWallet,
86
- ) {
74
+ export async function createAccountLogs(accountManagers: AccountManager[], wallet: EmbeddedWallet) {
87
75
  const registeredAccounts = await wallet.getAccounts();
88
76
  const accountLogStrings = [`Initial Accounts:\n\n`];
89
- for (const accountWithSecretKey of accountsWithSecretKeys) {
90
- const completeAddress = await accountWithSecretKey.account.getCompleteAddress();
77
+ for (const accountManager of accountManagers) {
78
+ const account = await accountManager.getAccount();
79
+ const completeAddress = account.getCompleteAddress();
91
80
  if (registeredAccounts.find(a => a.item.equals(completeAddress.address))) {
92
81
  accountLogStrings.push(` Address: ${completeAddress.address.toString()}\n`);
93
82
  accountLogStrings.push(` Partial Address: ${completeAddress.partialAddress.toString()}\n`);
94
- accountLogStrings.push(` Secret Key: ${accountWithSecretKey.secretKey.toString()}\n`);
83
+ accountLogStrings.push(` Secret Key: ${account.getSecretKey().toString()}\n`);
95
84
  accountLogStrings.push(
96
85
  ` Master nullifier public key: ${completeAddress.publicKeys.masterNullifierPublicKey.toString()}\n`,
97
86
  );
@@ -282,7 +271,7 @@ export async function preloadCrsDataForVerifying(
282
271
  ): Promise<void> {
283
272
  if (realProofs) {
284
273
  const { Crs, GrumpkinCrs } = await import('@aztec/bb.js');
285
- await Promise.all([Crs.new(2 ** 1, undefined, log), GrumpkinCrs.new(2 ** 16 + 1, undefined, log)]);
274
+ await Promise.all([Crs.new(2 ** 1, undefined, log), GrumpkinCrs.new(2 ** 16, undefined, log)]);
286
275
  }
287
276
  }
288
277
 
@@ -297,7 +286,7 @@ export async function preloadCrsDataForServerSideProving(
297
286
  ): Promise<void> {
298
287
  if (realProofs) {
299
288
  const { Crs, GrumpkinCrs } = await import('@aztec/bb.js');
300
- await Promise.all([Crs.new(2 ** 25 + 1, undefined, log), GrumpkinCrs.new(2 ** 18 + 1, undefined, log)]);
289
+ await Promise.all([Crs.new(2 ** 25, undefined, log), GrumpkinCrs.new(2 ** 18, undefined, log)]);
301
290
  }
302
291
  }
303
292
 
@@ -388,3 +377,9 @@ export async function setupUpdateMonitor(
388
377
 
389
378
  checker.start();
390
379
  }
380
+
381
+ export function stringifyConfig(config: object): string {
382
+ return Object.entries(config)
383
+ .map(([key, value]) => `${key}=${jsonStringify(value)}`)
384
+ .join(' ');
385
+ }
@@ -2,7 +2,7 @@ import { getInitialTestAccountsData } from '@aztec/accounts/testing';
2
2
  import { createAztecNodeClient } from '@aztec/aztec.js/node';
3
3
  import { createLogger } from '@aztec/foundation/log';
4
4
  import { TokenContract } from '@aztec/noir-contracts.js/Token';
5
- import { TestWallet } from '@aztec/test-wallet/server';
5
+ import { EmbeddedWallet } from '@aztec/wallets/embedded';
6
6
 
7
7
  const logger = createLogger('example:token');
8
8
 
@@ -19,7 +19,7 @@ const TRANSFER_AMOUNT = 33n;
19
19
  async function main() {
20
20
  logger.info('Running token contract test on HTTP interface.');
21
21
 
22
- const wallet = await TestWallet.create(node);
22
+ const wallet = await EmbeddedWallet.create(node);
23
23
 
24
24
  // During local network setup we deploy a few accounts. Below we add them to our wallet.
25
25
  const [aliceInitialAccountData, bobInitialAccountData] = await getInitialTestAccountsData();
@@ -32,29 +32,29 @@ async function main() {
32
32
  logger.info(`Fetched Alice and Bob accounts: ${alice.toString()}, ${bob.toString()}`);
33
33
 
34
34
  logger.info('Deploying Token...');
35
- const token = await TokenContract.deploy(wallet, alice, 'TokenName', 'TokenSymbol', 18)
36
- .send({ from: alice })
37
- .deployed();
35
+ const { contract: token } = await TokenContract.deploy(wallet, alice, 'TokenName', 'TokenSymbol', 18).send({
36
+ from: alice,
37
+ });
38
38
  logger.info('Token deployed');
39
39
 
40
40
  // Mint tokens to Alice
41
41
  logger.info(`Minting ${ALICE_MINT_BALANCE} more coins to Alice...`);
42
- await token.methods.mint_to_private(alice, ALICE_MINT_BALANCE).send({ from: alice }).wait();
42
+ await token.methods.mint_to_private(alice, ALICE_MINT_BALANCE).send({ from: alice });
43
43
 
44
44
  logger.info(`${ALICE_MINT_BALANCE} tokens were successfully minted by Alice and transferred to private`);
45
45
 
46
- const balanceAfterMint = await token.methods.balance_of_private(alice).simulate({ from: alice });
46
+ const { result: balanceAfterMint } = await token.methods.balance_of_private(alice).simulate({ from: alice });
47
47
  logger.info(`Tokens successfully minted. New Alice's balance: ${balanceAfterMint}`);
48
48
 
49
49
  // We will now transfer tokens from Alice to Bob
50
50
  logger.info(`Transferring ${TRANSFER_AMOUNT} tokens from Alice to Bob...`);
51
- await token.methods.transfer(bob, TRANSFER_AMOUNT).send({ from: alice }).wait();
51
+ await token.methods.transfer(bob, TRANSFER_AMOUNT).send({ from: alice });
52
52
 
53
53
  // Check the new balances
54
- const aliceBalance = await token.methods.balance_of_private(alice).simulate({ from: alice });
54
+ const { result: aliceBalance } = await token.methods.balance_of_private(alice).simulate({ from: alice });
55
55
  logger.info(`Alice's balance ${aliceBalance}`);
56
56
 
57
- const bobBalance = await token.methods.balance_of_private(bob).simulate({ from: bob });
57
+ const { result: bobBalance } = await token.methods.balance_of_private(bob).simulate({ from: bob });
58
58
  logger.info(`Bob's balance ${bobBalance}`);
59
59
  }
60
60
 
@@ -48,13 +48,17 @@ export async function getBananaFPCAddress(initialAccounts: InitialAccountData[])
48
48
  export async function setupBananaFPC(initialAccounts: InitialAccountData[], wallet: Wallet, log: LogFn) {
49
49
  const bananaCoinAddress = await getBananaCoinAddress(initialAccounts);
50
50
  const admin = getBananaAdmin(initialAccounts);
51
- const [bananaCoin, fpc] = await Promise.all([
52
- TokenContract.deploy(wallet, admin, bananaCoinArgs.name, bananaCoinArgs.symbol, bananaCoinArgs.decimal)
53
- .send({ from: admin, contractAddressSalt: BANANA_COIN_SALT, universalDeploy: true })
54
- .deployed(),
55
- FPCContract.deploy(wallet, bananaCoinAddress, admin)
56
- .send({ from: admin, contractAddressSalt: BANANA_FPC_SALT, universalDeploy: true })
57
- .deployed(),
51
+ const [{ contract: bananaCoin }, { contract: fpc }] = await Promise.all([
52
+ TokenContract.deploy(wallet, admin, bananaCoinArgs.name, bananaCoinArgs.symbol, bananaCoinArgs.decimal).send({
53
+ from: admin,
54
+ contractAddressSalt: BANANA_COIN_SALT,
55
+ universalDeploy: true,
56
+ }),
57
+ FPCContract.deploy(wallet, bananaCoinAddress, admin).send({
58
+ from: admin,
59
+ contractAddressSalt: BANANA_FPC_SALT,
60
+ universalDeploy: true,
61
+ }),
58
62
  ]);
59
63
 
60
64
  log(`BananaCoin: ${bananaCoin.address}`);
@@ -18,13 +18,17 @@ import type { LogFn } from '@aztec/foundation/log';
18
18
  import { DateProvider, TestDateProvider } from '@aztec/foundation/timer';
19
19
  import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
20
20
  import { protocolContractsHash } from '@aztec/protocol-contracts';
21
+ import { SequencerState } from '@aztec/sequencer-client';
22
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
23
+ import type { ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
21
24
  import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
22
25
  import {
23
26
  type TelemetryClient,
24
27
  getConfigEnvVars as getTelemetryClientConfig,
25
28
  initTelemetryClient,
26
29
  } from '@aztec/telemetry-client';
27
- import { TestWallet, deployFundedSchnorrAccounts } from '@aztec/test-wallet/server';
30
+ import { EmbeddedWallet } from '@aztec/wallets/embedded';
31
+ import { deployFundedSchnorrAccounts } from '@aztec/wallets/testing';
28
32
  import { getGenesisValues } from '@aztec/world-state/testing';
29
33
 
30
34
  import { type Hex, createPublicClient, fallback, http as httpViemTransport } from 'viem';
@@ -51,7 +55,6 @@ export async function deployContractsToL1(
51
55
  aztecNodeConfig: AztecNodeConfig,
52
56
  privateKey: Hex,
53
57
  opts: {
54
- assumeProvenThroughBlockNumber?: number;
55
58
  genesisArchiveRoot?: Fr;
56
59
  feeJuicePortalInitialBalance?: bigint;
57
60
  } = {},
@@ -105,12 +108,14 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
105
108
  };
106
109
  const hdAccount = mnemonicToAccount(config.l1Mnemonic || DefaultMnemonic);
107
110
  if (
108
- aztecNodeConfig.publisherPrivateKeys == undefined ||
109
- !aztecNodeConfig.publisherPrivateKeys.length ||
110
- aztecNodeConfig.publisherPrivateKeys[0].getValue() === NULL_KEY
111
+ aztecNodeConfig.sequencerPublisherPrivateKeys == undefined ||
112
+ !aztecNodeConfig.sequencerPublisherPrivateKeys.length ||
113
+ aztecNodeConfig.sequencerPublisherPrivateKeys[0].getValue() === NULL_KEY
111
114
  ) {
112
115
  const privKey = hdAccount.getHdKey().privateKey;
113
- aztecNodeConfig.publisherPrivateKeys = [new SecretValue(`0x${Buffer.from(privKey!).toString('hex')}` as const)];
116
+ aztecNodeConfig.sequencerPublisherPrivateKeys = [
117
+ new SecretValue(`0x${Buffer.from(privKey!).toString('hex')}` as const),
118
+ ];
114
119
  }
115
120
  if (!aztecNodeConfig.validatorPrivateKeys?.getValue().length) {
116
121
  const privKey = hdAccount.getHdKey().privateKey;
@@ -134,9 +139,12 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
134
139
 
135
140
  const bananaFPC = await getBananaFPCAddress(initialAccounts);
136
141
  const sponsoredFPC = await getSponsoredFPCAddress();
137
- const fundedAddresses = initialAccounts.length
138
- ? [...initialAccounts.map(a => a.address), bananaFPC, sponsoredFPC]
139
- : [];
142
+ const prefundAddresses = (aztecNodeConfig.prefundAddresses ?? []).map(a => AztecAddress.fromString(a));
143
+ const fundedAddresses = [
144
+ ...initialAccounts.map(a => a.address),
145
+ ...(initialAccounts.length ? [bananaFPC, sponsoredFPC] : []),
146
+ ...prefundAddresses,
147
+ ];
140
148
  const { genesisArchiveRoot, prefilledPublicData, fundingNeeded } = await getGenesisValues(fundedAddresses);
141
149
 
142
150
  const dateProvider = new TestDateProvider();
@@ -149,7 +157,6 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
149
157
  aztecNodeConfig,
150
158
  aztecNodeConfig.validatorPrivateKeys.getValue()[0],
151
159
  {
152
- assumeProvenThroughBlockNumber: Number.MAX_SAFE_INTEGER,
153
160
  genesisArchiveRoot,
154
161
  feeJuicePortalInitialBalance: fundingNeeded,
155
162
  },
@@ -179,25 +186,42 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
179
186
  const blobClient = createBlobClient();
180
187
  const node = await createAztecNode(aztecNodeConfig, { telemetry, blobClient, dateProvider }, { prefilledPublicData });
181
188
 
189
+ // Now that the node is up, let the watcher check for pending txs so it can skip unfilled slots faster when
190
+ // transactions are waiting in the mempool. Also let it check if the sequencer is actively building, to avoid
191
+ // warping time out from under an in-progress block.
192
+ watcher?.setGetPendingTxCount(() => node.getPendingTxCount());
193
+ const sequencer = node.getSequencer()?.getSequencer();
194
+ if (sequencer) {
195
+ const idleStates: Set<string> = new Set([
196
+ SequencerState.STOPPED,
197
+ SequencerState.STOPPING,
198
+ SequencerState.IDLE,
199
+ SequencerState.SYNCHRONIZING,
200
+ ]);
201
+ watcher?.setIsSequencerBuilding(() => !idleStates.has(sequencer.getState()));
202
+ }
203
+
182
204
  let epochTestSettler: EpochTestSettler | undefined;
183
205
  if (!aztecNodeConfig.p2pEnabled) {
184
- epochTestSettler = new EpochTestSettler(cheatcodes!, rollupAddress!, node.getBlockSource(), {
185
- pollingIntervalMs: 200,
186
- });
206
+ epochTestSettler = new EpochTestSettler(
207
+ cheatcodes!,
208
+ rollupAddress!,
209
+ node.getBlockSource(),
210
+ logger.createChild('epoch-settler'),
211
+ { pollingIntervalMs: 200 },
212
+ );
187
213
  await epochTestSettler.start();
188
214
  }
189
215
 
190
216
  if (initialAccounts.length) {
191
- const PXEConfig = { proverEnabled: aztecNodeConfig.realProofs };
192
- const wallet = await TestWallet.create(node, PXEConfig);
217
+ const wallet = await EmbeddedWallet.create(node, {
218
+ pxeConfig: { proverEnabled: aztecNodeConfig.realProofs },
219
+ ephemeral: true,
220
+ });
193
221
 
194
222
  userLog('Setting up funded test accounts...');
195
- const accountManagers = await deployFundedSchnorrAccounts(wallet, node, initialAccounts);
196
- const accountsWithSecrets = accountManagers.map((manager, i) => ({
197
- account: manager,
198
- secretKey: initialAccounts[i].secret,
199
- }));
200
- const accLogs = await createAccountLogs(accountsWithSecrets, wallet);
223
+ const accountManagers = await deployFundedSchnorrAccounts(wallet, initialAccounts);
224
+ const accLogs = await createAccountLogs(accountManagers, wallet);
201
225
  userLog(accLogs.join(''));
202
226
 
203
227
  await setupBananaFPC(initialAccounts, wallet, userLog);
@@ -223,7 +247,12 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
223
247
  */
224
248
  export async function createAztecNode(
225
249
  config: Partial<AztecNodeConfig> = {},
226
- deps: { telemetry?: TelemetryClient; blobClient?: BlobClientInterface; dateProvider?: DateProvider } = {},
250
+ deps: {
251
+ telemetry?: TelemetryClient;
252
+ blobClient?: BlobClientInterface;
253
+ dateProvider?: DateProvider;
254
+ proverBroker?: ProvingJobBroker;
255
+ } = {},
227
256
  options: { prefilledPublicData?: PublicDataTreeLeaf[] } = {},
228
257
  ) {
229
258
  // TODO(#12272): will clean this up. This is criminal.
@@ -233,6 +262,10 @@ export async function createAztecNode(
233
262
  ...config,
234
263
  l1Contracts: { ...l1Contracts, ...config.l1Contracts },
235
264
  };
236
- const node = await AztecNodeService.createAndSync(aztecNodeConfig, deps, options);
265
+ const node = await AztecNodeService.createAndSync(
266
+ aztecNodeConfig,
267
+ { ...deps, proverNodeDeps: { broker: deps.proverBroker } },
268
+ options,
269
+ );
237
270
  return node;
238
271
  }