@aztec/aztec 0.0.0-test.1 → 0.0.1-commit.b655e406

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 (111) hide show
  1. package/dest/bin/index.js +20 -12
  2. package/dest/cli/aztec_start_action.d.ts.map +1 -1
  3. package/dest/cli/aztec_start_action.js +32 -33
  4. package/dest/cli/aztec_start_options.d.ts +4 -2
  5. package/dest/cli/aztec_start_options.d.ts.map +1 -1
  6. package/dest/cli/aztec_start_options.js +137 -207
  7. package/dest/cli/cli.d.ts.map +1 -1
  8. package/dest/cli/cli.js +4 -0
  9. package/dest/cli/cmds/start_archiver.d.ts.map +1 -1
  10. package/dest/cli/cmds/start_archiver.js +18 -10
  11. package/dest/cli/cmds/start_blob_sink.d.ts.map +1 -1
  12. package/dest/cli/cmds/start_blob_sink.js +17 -1
  13. package/dest/cli/cmds/start_bot.d.ts +3 -6
  14. package/dest/cli/cmds/start_bot.d.ts.map +1 -1
  15. package/dest/cli/cmds/start_bot.js +24 -13
  16. package/dest/cli/cmds/start_node.d.ts +1 -1
  17. package/dest/cli/cmds/start_node.d.ts.map +1 -1
  18. package/dest/cli/cmds/start_node.js +66 -79
  19. package/dest/cli/cmds/start_p2p_bootstrap.d.ts.map +1 -1
  20. package/dest/cli/cmds/start_p2p_bootstrap.js +9 -4
  21. package/dest/cli/cmds/start_prover_agent.d.ts.map +1 -1
  22. package/dest/cli/cmds/start_prover_agent.js +31 -2
  23. package/dest/cli/cmds/start_prover_broker.d.ts.map +1 -1
  24. package/dest/cli/cmds/start_prover_broker.js +9 -3
  25. package/dest/cli/cmds/start_prover_node.d.ts.map +1 -1
  26. package/dest/cli/cmds/start_prover_node.js +43 -45
  27. package/dest/cli/preload_crs.d.ts +3 -0
  28. package/dest/cli/preload_crs.d.ts.map +1 -0
  29. package/dest/cli/preload_crs.js +6 -0
  30. package/dest/cli/release_version.d.ts +2 -0
  31. package/dest/cli/release_version.d.ts.map +1 -0
  32. package/dest/cli/release_version.js +14 -0
  33. package/dest/cli/util.d.ts +36 -5
  34. package/dest/cli/util.d.ts.map +1 -1
  35. package/dest/cli/util.js +198 -28
  36. package/dest/cli/versioning.js +3 -3
  37. package/dest/examples/token.js +31 -18
  38. package/dest/examples/util.d.ts +4 -5
  39. package/dest/examples/util.d.ts.map +1 -1
  40. package/dest/examples/util.js +5 -6
  41. package/dest/index.d.ts +1 -1
  42. package/dest/index.d.ts.map +1 -1
  43. package/dest/index.js +1 -1
  44. package/dest/sandbox/banana_fpc.d.ts +4 -5
  45. package/dest/sandbox/banana_fpc.d.ts.map +1 -1
  46. package/dest/sandbox/banana_fpc.js +19 -21
  47. package/dest/sandbox/index.d.ts +2 -3
  48. package/dest/sandbox/index.d.ts.map +1 -1
  49. package/dest/sandbox/index.js +2 -3
  50. package/dest/sandbox/sandbox.d.ts +25 -27
  51. package/dest/sandbox/sandbox.d.ts.map +1 -1
  52. package/dest/sandbox/sandbox.js +51 -49
  53. package/dest/sandbox/sponsored_fpc.d.ts +3 -5
  54. package/dest/sandbox/sponsored_fpc.d.ts.map +1 -1
  55. package/dest/sandbox/sponsored_fpc.js +10 -18
  56. package/dest/testing/anvil_test_watcher.d.ts +34 -0
  57. package/dest/testing/anvil_test_watcher.d.ts.map +1 -0
  58. package/dest/testing/anvil_test_watcher.js +142 -0
  59. package/dest/testing/cheat_codes.d.ts +43 -0
  60. package/dest/testing/cheat_codes.d.ts.map +1 -0
  61. package/dest/testing/cheat_codes.js +62 -0
  62. package/dest/testing/index.d.ts +4 -0
  63. package/dest/testing/index.d.ts.map +1 -0
  64. package/dest/testing/index.js +3 -0
  65. package/package.json +47 -41
  66. package/src/bin/index.ts +24 -12
  67. package/src/cli/aztec_start_action.ts +27 -30
  68. package/src/cli/aztec_start_options.ts +155 -207
  69. package/src/cli/cli.ts +8 -0
  70. package/src/cli/cmds/start_archiver.ts +19 -13
  71. package/src/cli/cmds/start_blob_sink.ts +27 -1
  72. package/src/cli/cmds/start_bot.ts +35 -12
  73. package/src/cli/cmds/start_node.ts +89 -84
  74. package/src/cli/cmds/start_p2p_bootstrap.ts +12 -4
  75. package/src/cli/cmds/start_prover_agent.ts +22 -2
  76. package/src/cli/cmds/start_prover_broker.ts +23 -3
  77. package/src/cli/cmds/start_prover_node.ts +53 -50
  78. package/src/cli/preload_crs.ts +7 -0
  79. package/src/cli/release_version.ts +21 -0
  80. package/src/cli/util.ts +208 -34
  81. package/src/cli/versioning.ts +3 -3
  82. package/src/examples/token.ts +23 -19
  83. package/src/examples/util.ts +6 -8
  84. package/src/index.ts +3 -4
  85. package/src/sandbox/banana_fpc.ts +20 -25
  86. package/src/sandbox/index.ts +5 -3
  87. package/src/sandbox/sandbox.ts +70 -57
  88. package/src/sandbox/sponsored_fpc.ts +12 -25
  89. package/src/testing/anvil_test_watcher.ts +164 -0
  90. package/src/testing/cheat_codes.ts +78 -0
  91. package/src/testing/index.ts +3 -0
  92. package/dest/cli/chain_l2_config.d.ts +0 -19
  93. package/dest/cli/chain_l2_config.d.ts.map +0 -1
  94. package/dest/cli/chain_l2_config.js +0 -56
  95. package/dest/cli/cmds/start_faucet.d.ts +0 -4
  96. package/dest/cli/cmds/start_faucet.d.ts.map +0 -1
  97. package/dest/cli/cmds/start_faucet.js +0 -20
  98. package/dest/cli/cmds/start_pxe.d.ts +0 -16
  99. package/dest/cli/cmds/start_pxe.d.ts.map +0 -1
  100. package/dest/cli/cmds/start_pxe.js +0 -95
  101. package/dest/cli/get_l1_config.d.ts +0 -7
  102. package/dest/cli/get_l1_config.d.ts.map +0 -1
  103. package/dest/cli/get_l1_config.js +0 -13
  104. package/dest/sandbox/sponsored_fee_payment_method.d.ts +0 -23
  105. package/dest/sandbox/sponsored_fee_payment_method.d.ts.map +0 -1
  106. package/dest/sandbox/sponsored_fee_payment_method.js +0 -36
  107. package/src/cli/chain_l2_config.ts +0 -74
  108. package/src/cli/cmds/start_faucet.ts +0 -34
  109. package/src/cli/cmds/start_pxe.ts +0 -129
  110. package/src/cli/get_l1_config.ts +0 -18
  111. package/src/sandbox/sponsored_fee_payment_method.ts +0 -46
@@ -1,11 +1,19 @@
1
- import { type BotConfig, BotRunner, botConfigMappings, getBotRunnerApiHandler } from '@aztec/bot';
1
+ import { type BotConfig, BotRunner, BotStore, botConfigMappings, getBotRunnerApiHandler } from '@aztec/bot';
2
2
  import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server';
3
3
  import type { LogFn } from '@aztec/foundation/log';
4
- import type { AztecNode, PXE } from '@aztec/stdlib/interfaces/client';
4
+ import { createStore, openTmpStore } from '@aztec/kv-store/lmdb-v2';
5
+ import { type CliPXEOptions, type PXEConfig, allPxeConfigMappings } from '@aztec/pxe/config';
6
+ import { type AztecNode, type AztecNodeAdmin, createAztecNodeClient } from '@aztec/stdlib/interfaces/client';
5
7
  import type { TelemetryClient } from '@aztec/telemetry-client';
6
- import { getConfigEnvVars as getTelemetryClientConfig, initTelemetryClient } from '@aztec/telemetry-client';
8
+ import {
9
+ getConfigEnvVars as getTelemetryClientConfig,
10
+ initTelemetryClient,
11
+ makeTracedFetch,
12
+ } from '@aztec/telemetry-client';
13
+ import { TestWallet } from '@aztec/test-wallet/server';
7
14
 
8
15
  import { extractRelevantOptions } from '../util.js';
16
+ import { getVersions } from '../versioning.js';
9
17
 
10
18
  export async function startBot(
11
19
  options: any,
@@ -20,26 +28,41 @@ export async function startBot(
20
28
  );
21
29
  process.exit(1);
22
30
  }
23
- // Start a PXE client that is used by the bot if required
24
- let pxe: PXE | undefined;
25
- if (options.pxe) {
26
- const { addPXE } = await import('./start_pxe.js');
27
- ({ pxe } = await addPXE(options, signalHandlers, services, userLog));
31
+
32
+ const fetch = makeTracedFetch([1, 2, 3], true);
33
+ const config = extractRelevantOptions<BotConfig>(options, botConfigMappings, 'bot');
34
+ if (!config.nodeUrl) {
35
+ throw new Error('The bot requires access to a Node');
28
36
  }
29
37
 
38
+ const aztecNode = createAztecNodeClient(config.nodeUrl, getVersions(), fetch);
39
+
40
+ const pxeConfig = extractRelevantOptions<PXEConfig & CliPXEOptions>(options, allPxeConfigMappings, 'pxe');
41
+ const wallet = await TestWallet.create(aztecNode, pxeConfig);
42
+
30
43
  const telemetry = initTelemetryClient(getTelemetryClientConfig());
31
- await addBot(options, signalHandlers, services, { pxe, telemetry });
44
+ await addBot(options, signalHandlers, services, wallet, aztecNode, telemetry, undefined);
32
45
  }
33
46
 
34
- export function addBot(
47
+ export async function addBot(
35
48
  options: any,
36
49
  signalHandlers: (() => Promise<void>)[],
37
50
  services: NamespacedApiHandlers,
38
- deps: { pxe?: PXE; node?: AztecNode; telemetry: TelemetryClient },
51
+ wallet: TestWallet,
52
+ aztecNode: AztecNode,
53
+ telemetry: TelemetryClient,
54
+ aztecNodeAdmin?: AztecNodeAdmin,
39
55
  ) {
40
56
  const config = extractRelevantOptions<BotConfig>(options, botConfigMappings, 'bot');
41
57
 
42
- const botRunner = new BotRunner(config, deps);
58
+ const db = await (config.dataDirectory
59
+ ? createStore('bot', BotStore.SCHEMA_VERSION, config)
60
+ : openTmpStore('bot', true, config.dataStoreMapSizeKb));
61
+
62
+ const store = new BotStore(db);
63
+ await store.cleanupOldClaims();
64
+
65
+ const botRunner = new BotRunner(config, wallet, aztecNode, telemetry, aztecNodeAdmin, store);
43
66
  if (!config.noStart) {
44
67
  void botRunner.start(); // Do not block since bot setup takes time
45
68
  }
@@ -1,35 +1,48 @@
1
- import { getInitialTestAccounts } from '@aztec/accounts/testing';
1
+ import { getInitialTestAccountsData } from '@aztec/accounts/testing';
2
2
  import { type AztecNodeConfig, aztecNodeConfigMappings, getConfigEnvVars } from '@aztec/aztec-node';
3
- import { NULL_KEY } from '@aztec/ethereum';
3
+ import { Fr } from '@aztec/aztec.js/fields';
4
+ import { getSponsoredFPCAddress } from '@aztec/cli/cli-utils';
5
+ import { getL1Config } from '@aztec/cli/config';
6
+ import { getPublicClient } from '@aztec/ethereum';
7
+ import { SecretValue } from '@aztec/foundation/config';
4
8
  import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server';
5
9
  import type { LogFn } from '@aztec/foundation/log';
6
- import { AztecNodeApiSchema, type PXE } from '@aztec/stdlib/interfaces/client';
10
+ import { type CliPXEOptions, type PXEConfig, allPxeConfigMappings } from '@aztec/pxe/config';
11
+ import { AztecNodeAdminApiSchema, AztecNodeApiSchema } from '@aztec/stdlib/interfaces/client';
7
12
  import { P2PApiSchema } from '@aztec/stdlib/interfaces/server';
8
13
  import {
9
14
  type TelemetryClientConfig,
10
15
  initTelemetryClient,
11
16
  telemetryClientConfigMappings,
12
17
  } from '@aztec/telemetry-client';
18
+ import { TestWallet } from '@aztec/test-wallet/server';
13
19
  import { getGenesisValues } from '@aztec/world-state/testing';
14
20
 
15
- import { mnemonicToAccount, privateKeyToAccount } from 'viem/accounts';
16
-
17
- import { createAztecNode, deployContractsToL1 } from '../../sandbox/index.js';
18
- import { getL1Config } from '../get_l1_config.js';
19
- import { extractNamespacedOptions, extractRelevantOptions } from '../util.js';
21
+ import { createAztecNode } from '../../sandbox/index.js';
22
+ import {
23
+ extractNamespacedOptions,
24
+ extractRelevantOptions,
25
+ preloadCrsDataForVerifying,
26
+ setupUpdateMonitor,
27
+ } from '../util.js';
20
28
 
21
29
  export async function startNode(
22
30
  options: any,
23
31
  signalHandlers: (() => Promise<void>)[],
24
32
  services: NamespacedApiHandlers,
33
+ adminServices: NamespacedApiHandlers,
25
34
  userLog: LogFn,
26
35
  ): Promise<{ config: AztecNodeConfig }> {
27
- // options specifically namespaced with --node.<option>
28
- const nodeSpecificOptions = extractNamespacedOptions(options, 'node');
36
+ // All options set from environment variables
37
+ const configFromEnvVars = getConfigEnvVars();
38
+
39
+ // Extract relevant options from command line arguments
40
+ const relevantOptions = extractRelevantOptions(options, aztecNodeConfigMappings, 'node');
41
+
29
42
  // All options that are relevant to the Aztec Node
30
43
  let nodeConfig: AztecNodeConfig = {
31
- ...getConfigEnvVars(),
32
- ...extractRelevantOptions(options, aztecNodeConfigMappings, 'node'),
44
+ ...configFromEnvVars,
45
+ ...relevantOptions,
33
46
  };
34
47
 
35
48
  if (options.proverNode) {
@@ -37,81 +50,63 @@ export async function startNode(
37
50
  process.exit(1);
38
51
  }
39
52
 
40
- const initialFundedAccounts = nodeConfig.testAccounts ? await getInitialTestAccounts() : [];
41
- const { genesisBlockHash, genesisArchiveRoot, prefilledPublicData } = await getGenesisValues(
42
- initialFundedAccounts.map(a => a.address),
43
- );
53
+ await preloadCrsDataForVerifying(nodeConfig, userLog);
44
54
 
45
- // Deploy contracts if needed
46
- if (nodeSpecificOptions.deployAztecContracts || nodeSpecificOptions.deployAztecContractsSalt) {
47
- let account;
48
- if (nodeSpecificOptions.publisherPrivateKey) {
49
- account = privateKeyToAccount(nodeSpecificOptions.publisherPrivateKey);
50
- } else if (options.l1Mnemonic) {
51
- account = mnemonicToAccount(options.l1Mnemonic);
52
- } else {
53
- throw new Error('--node.publisherPrivateKey or --l1-mnemonic is required to deploy L1 contracts');
54
- }
55
- // REFACTOR: We should not be calling a method from sandbox on the prod start flow
56
- await deployContractsToL1(nodeConfig, account!, undefined, {
57
- assumeProvenThroughBlockNumber: nodeSpecificOptions.assumeProvenThroughBlockNumber,
58
- salt: nodeSpecificOptions.deployAztecContractsSalt,
59
- genesisBlockHash,
60
- genesisArchiveRoot,
61
- });
62
- }
63
- // If not deploying, validate that any addresses and config provided are correct.
64
- else {
65
- if (!nodeConfig.l1Contracts.registryAddress || nodeConfig.l1Contracts.registryAddress.isZero()) {
66
- throw new Error('L1 registry address is required to start Aztec Node without --deploy-aztec-contracts option');
67
- }
68
- const { addresses, config } = await getL1Config(
69
- nodeConfig.l1Contracts.registryAddress,
70
- nodeConfig.l1RpcUrls,
71
- nodeConfig.l1ChainId,
72
- );
55
+ const testAccounts = nodeConfig.testAccounts ? (await getInitialTestAccountsData()).map(a => a.address) : [];
56
+ const sponsoredFPCAccounts = nodeConfig.sponsoredFPC ? [await getSponsoredFPCAddress()] : [];
57
+ const initialFundedAccounts = testAccounts.concat(sponsoredFPCAccounts);
73
58
 
74
- // TODO(#12272): will clean this up.
75
- nodeConfig = {
76
- ...nodeConfig,
77
- l1Contracts: {
78
- ...addresses,
79
- slashFactoryAddress: nodeConfig.l1Contracts.slashFactoryAddress,
80
- },
81
- ...config,
82
- };
59
+ userLog(`Initial funded accounts: ${initialFundedAccounts.map(a => a.toString()).join(', ')}`);
60
+
61
+ const { genesisArchiveRoot, prefilledPublicData } = await getGenesisValues(initialFundedAccounts);
62
+
63
+ userLog(`Genesis archive root: ${genesisArchiveRoot.toString()}`);
64
+
65
+ const followsCanonicalRollup =
66
+ typeof nodeConfig.rollupVersion !== 'number' || (nodeConfig.rollupVersion as unknown as string) === 'canonical';
67
+
68
+ if (!nodeConfig.l1Contracts.registryAddress || nodeConfig.l1Contracts.registryAddress.isZero()) {
69
+ throw new Error('L1 registry address is required to start Aztec Node');
83
70
  }
71
+ const { addresses, config } = await getL1Config(
72
+ nodeConfig.l1Contracts.registryAddress,
73
+ nodeConfig.l1RpcUrls,
74
+ nodeConfig.l1ChainId,
75
+ nodeConfig.rollupVersion,
76
+ );
84
77
 
85
- // if no publisher private key, then use l1Mnemonic
86
- if (!options.archiver) {
87
- // expect archiver url in node config
88
- const archiverUrl = nodeConfig.archiverUrl;
89
- if (!archiverUrl) {
90
- userLog('Archiver Service URL is required to start Aztec Node without --archiver option');
91
- throw new Error('Archiver Service URL is required to start Aztec Node without --archiver option');
92
- }
93
- nodeConfig.archiverUrl = archiverUrl;
78
+ process.env.ROLLUP_CONTRACT_ADDRESS ??= addresses.rollupAddress.toString();
79
+
80
+ if (!Fr.fromHexString(config.genesisArchiveTreeRoot).equals(genesisArchiveRoot)) {
81
+ throw new Error(
82
+ `The computed genesis archive tree root ${genesisArchiveRoot} does not match the expected genesis archive tree root ${config.genesisArchiveTreeRoot} for the rollup deployed at ${addresses.rollupAddress}`,
83
+ );
94
84
  }
95
85
 
86
+ // TODO(#12272): will clean this up.
87
+ nodeConfig = {
88
+ ...nodeConfig,
89
+ l1Contracts: {
90
+ ...addresses,
91
+ slashFactoryAddress: nodeConfig.l1Contracts.slashFactoryAddress,
92
+ },
93
+ ...config,
94
+ };
95
+
96
96
  if (!options.sequencer) {
97
97
  nodeConfig.disableValidator = true;
98
98
  } else {
99
- const sequencerConfig = extractNamespacedOptions(options, 'sequencer');
100
- let account;
101
- if (!sequencerConfig.publisherPrivateKey || sequencerConfig.publisherPrivateKey === NULL_KEY) {
102
- if (!options.l1Mnemonic) {
103
- userLog(
104
- '--sequencer.publisherPrivateKey or --l1-mnemonic is required to start Aztec Node with --sequencer option',
105
- );
106
- throw new Error('Private key or Mnemonic is required to start Aztec Node with --sequencer option');
107
- } else {
108
- account = mnemonicToAccount(options.l1Mnemonic);
109
- const privKey = account.getHdKey().privateKey;
110
- nodeConfig.publisherPrivateKey = `0x${Buffer.from(privKey!).toString('hex')}`;
99
+ const sequencerConfig = {
100
+ ...configFromEnvVars,
101
+ ...extractNamespacedOptions(options, 'sequencer'),
102
+ };
103
+ // If no publisher private keys have been given, use the first validator key
104
+ if (sequencerConfig.publisherPrivateKeys === undefined || !sequencerConfig.publisherPrivateKeys.length) {
105
+ if (sequencerConfig.validatorPrivateKeys?.getValue().length) {
106
+ sequencerConfig.publisherPrivateKeys = [new SecretValue(sequencerConfig.validatorPrivateKeys.getValue()[0])];
111
107
  }
112
- } else {
113
- nodeConfig.publisherPrivateKey = sequencerConfig.publisherPrivateKey;
114
108
  }
109
+ nodeConfig.publisherPrivateKeys = sequencerConfig.publisherPrivateKeys;
115
110
  }
116
111
 
117
112
  if (nodeConfig.p2pEnabled) {
@@ -130,21 +125,31 @@ export async function startNode(
130
125
  // Add node and p2p to services list
131
126
  services.node = [node, AztecNodeApiSchema];
132
127
  services.p2p = [node.getP2P(), P2PApiSchema];
128
+ adminServices.nodeAdmin = [node, AztecNodeAdminApiSchema];
133
129
 
134
130
  // Add node stop function to signal handlers
135
131
  signalHandlers.push(node.stop.bind(node));
136
132
 
137
- // Add a PXE client that connects to this node if requested
138
- let pxe: PXE | undefined;
139
- if (options.pxe) {
140
- const { addPXE } = await import('./start_pxe.js');
141
- ({ pxe } = await addPXE(options, signalHandlers, services, userLog, { node }));
142
- }
143
-
144
133
  // Add a txs bot if requested
145
134
  if (options.bot) {
146
135
  const { addBot } = await import('./start_bot.js');
147
- await addBot(options, signalHandlers, services, { pxe, node, telemetry });
136
+
137
+ const pxeConfig = extractRelevantOptions<PXEConfig & CliPXEOptions>(options, allPxeConfigMappings, 'pxe');
138
+ const wallet = await TestWallet.create(node, pxeConfig);
139
+
140
+ await addBot(options, signalHandlers, services, wallet, node, telemetry, undefined);
141
+ }
142
+
143
+ if (nodeConfig.autoUpdate !== 'disabled' && nodeConfig.autoUpdateUrl) {
144
+ await setupUpdateMonitor(
145
+ nodeConfig.autoUpdate,
146
+ new URL(nodeConfig.autoUpdateUrl),
147
+ followsCanonicalRollup,
148
+ getPublicClient(nodeConfig!),
149
+ nodeConfig.l1Contracts.registryAddress,
150
+ signalHandlers,
151
+ async config => node.setConfig((await AztecNodeAdminApiSchema.setConfig.parameters().parseAsync([config]))[0]),
152
+ );
148
153
  }
149
154
 
150
155
  return { config: nodeConfig };
@@ -5,7 +5,11 @@ 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';
7
7
  import { P2PBootstrapApiSchema } from '@aztec/stdlib/interfaces/server';
8
- import { getConfigEnvVars as getTelemetryClientConfig, initTelemetryClient } from '@aztec/telemetry-client';
8
+ import {
9
+ type TelemetryClientConfig,
10
+ initTelemetryClient,
11
+ telemetryClientConfigMappings,
12
+ } from '@aztec/telemetry-client';
9
13
 
10
14
  import { extractRelevantOptions } from '../util.js';
11
15
 
@@ -17,13 +21,17 @@ export async function startP2PBootstrap(
17
21
  ) {
18
22
  // Start a P2P bootstrap node.
19
23
  const config = extractRelevantOptions<BootnodeConfig>(options, bootnodeConfigMappings, 'p2p');
20
- userLog(`Starting P2P bootstrap node with config: ${jsonStringify(config)}`);
21
- const telemetryClient = initTelemetryClient(getTelemetryClientConfig());
24
+ const safeConfig = { ...config, peerIdPrivateKey: '<redacted>' };
25
+ userLog(`Starting P2P bootstrap node with config: ${jsonStringify(safeConfig)}`);
26
+
27
+ const telemetryConfig = extractRelevantOptions<TelemetryClientConfig>(options, telemetryClientConfigMappings, 'tel');
28
+ const telemetryClient = initTelemetryClient(telemetryConfig);
29
+
22
30
  const store = await createStore('p2p-bootstrap', 1, config, createLogger('p2p:bootstrap:store'));
23
31
  const node = new BootstrapNode(store, telemetryClient);
24
32
  await node.start(config);
25
33
  signalHandlers.push(() => node.stop());
26
34
  services.bootstrap = [node, P2PBootstrapApiSchema];
27
- userLog(`P2P bootstrap node started on ${config.udpListenAddress}`);
35
+ userLog(`P2P bootstrap node started on ${config.p2pIp}:${config.p2pPort}`);
28
36
  return { config: emptyChainConfig };
29
37
  }
@@ -11,9 +11,10 @@ import {
11
11
  proverAgentConfigMappings,
12
12
  } from '@aztec/prover-client/broker';
13
13
  import { getProverNodeAgentConfigFromEnv } from '@aztec/prover-node';
14
+ import { ProverAgentApiSchema } from '@aztec/stdlib/interfaces/server';
14
15
  import { initTelemetryClient, makeTracedFetch, telemetryClientConfigMappings } from '@aztec/telemetry-client';
15
16
 
16
- import { extractRelevantOptions } from '../util.js';
17
+ import { extractRelevantOptions, preloadCrsDataForServerSideProving } from '../util.js';
17
18
  import { getVersions } from '../versioning.js';
18
19
 
19
20
  export async function startProverAgent(
@@ -33,14 +34,23 @@ export async function startProverAgent(
33
34
  };
34
35
 
35
36
  if (config.realProofs && (!config.bbBinaryPath || !config.acvmBinaryPath)) {
37
+ userLog(`Requested real proving but no path to bb or acvm binaries provided`);
36
38
  process.exit(1);
37
39
  }
38
40
 
39
41
  if (!config.proverBrokerUrl) {
42
+ userLog(`Missing prover broker URL. Pass --proverAgent.proverBrokerUrl <value>`);
40
43
  process.exit(1);
41
44
  }
42
45
 
43
- const fetch = makeTracedFetch([1, 2, 3], false, makeUndiciFetch(new Agent({ connections: 10 })));
46
+ await preloadCrsDataForServerSideProving(config, userLog);
47
+
48
+ const fetch = makeTracedFetch(
49
+ // retry connections every 3s, up to 30s before giving up
50
+ [1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3],
51
+ false,
52
+ makeUndiciFetch(new Agent({ connections: 10 })),
53
+ );
44
54
  const broker = createProvingJobBrokerClient(config.proverBrokerUrl, getVersions(), fetch);
45
55
 
46
56
  const telemetry = initTelemetryClient(extractRelevantOptions(options, telemetryClientConfigMappings, 'tel'));
@@ -59,6 +69,16 @@ export async function startProverAgent(
59
69
  ),
60
70
  );
61
71
 
72
+ // expose all agents as individual services
73
+ for (let i = 0; i < agents.length; i++) {
74
+ services[`agent${i}`] = [agents[i], ProverAgentApiSchema, () => agents[i].getStatus().status !== 'stopped'];
75
+ }
76
+
77
+ // shortcut in the most common case of having a single running agent
78
+ if (agents.length === 1) {
79
+ services[`agent`] = [agents[0], ProverAgentApiSchema, () => agents[0].getStatus().status !== 'stopped'];
80
+ }
81
+
62
82
  await Promise.all(agents.map(agent => agent.start()));
63
83
 
64
84
  signalHandlers.push(async () => {
@@ -1,3 +1,5 @@
1
+ import { getL1Config } from '@aztec/cli/config';
2
+ import { getPublicClient } from '@aztec/ethereum';
1
3
  import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server';
2
4
  import type { LogFn } from '@aztec/foundation/log';
3
5
  import {
@@ -10,8 +12,7 @@ import { getProverNodeBrokerConfigFromEnv } from '@aztec/prover-node';
10
12
  import type { ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
11
13
  import { getConfigEnvVars as getTelemetryClientConfig, initTelemetryClient } from '@aztec/telemetry-client';
12
14
 
13
- import { getL1Config } from '../get_l1_config.js';
14
- import { extractRelevantOptions } from '../util.js';
15
+ import { extractRelevantOptions, setupUpdateMonitor } from '../util.js';
15
16
 
16
17
  export async function startProverBroker(
17
18
  options: any,
@@ -33,12 +34,31 @@ export async function startProverBroker(
33
34
  throw new Error('L1 registry address is required to start Aztec Node without --deploy-aztec-contracts option');
34
35
  }
35
36
 
36
- const { addresses } = await getL1Config(config.l1Contracts.registryAddress, config.l1RpcUrls, config.l1ChainId);
37
+ const followsCanonicalRollup = typeof config.rollupVersion !== 'number';
38
+ const { addresses, config: rollupConfig } = await getL1Config(
39
+ config.l1Contracts.registryAddress,
40
+ config.l1RpcUrls,
41
+ config.l1ChainId,
42
+ config.rollupVersion,
43
+ );
37
44
 
38
45
  config.l1Contracts = addresses;
46
+ config.rollupVersion = rollupConfig.rollupVersion;
39
47
 
40
48
  const client = initTelemetryClient(getTelemetryClientConfig());
41
49
  const broker = await createAndStartProvingBroker(config, client);
50
+
51
+ if (options.autoUpdate !== 'disabled' && options.autoUpdateUrl) {
52
+ await setupUpdateMonitor(
53
+ options.autoUpdate,
54
+ new URL(options.autoUpdateUrl),
55
+ followsCanonicalRollup,
56
+ getPublicClient(config),
57
+ config.l1Contracts.registryAddress,
58
+ signalHandlers,
59
+ );
60
+ }
61
+
42
62
  services.proverBroker = [broker, ProvingJobBrokerSchema];
43
63
  signalHandlers.push(() => broker.stop());
44
64
 
@@ -1,5 +1,8 @@
1
- import { getInitialTestAccounts } from '@aztec/accounts/testing';
2
- import { NULL_KEY } from '@aztec/ethereum';
1
+ import { getInitialTestAccountsData } from '@aztec/accounts/testing';
2
+ import { Fr } from '@aztec/aztec.js/fields';
3
+ import { getSponsoredFPCAddress } from '@aztec/cli/cli-utils';
4
+ import { getL1Config } from '@aztec/cli/config';
5
+ import { getPublicClient } from '@aztec/ethereum';
3
6
  import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server';
4
7
  import { Agent, makeUndiciFetch } from '@aztec/foundation/json-rpc/undici';
5
8
  import type { LogFn } from '@aztec/foundation/log';
@@ -10,15 +13,11 @@ import {
10
13
  getProverNodeConfigFromEnv,
11
14
  proverNodeConfigMappings,
12
15
  } from '@aztec/prover-node';
13
- import { createAztecNodeClient } from '@aztec/stdlib/interfaces/client';
14
16
  import { P2PApiSchema, ProverNodeApiSchema, type ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
15
17
  import { initTelemetryClient, makeTracedFetch, telemetryClientConfigMappings } from '@aztec/telemetry-client';
16
18
  import { getGenesisValues } from '@aztec/world-state/testing';
17
19
 
18
- import { mnemonicToAccount } from 'viem/accounts';
19
-
20
- import { getL1Config } from '../get_l1_config.js';
21
- import { extractRelevantOptions } from '../util.js';
20
+ import { extractRelevantOptions, preloadCrsDataForVerifying, setupUpdateMonitor } from '../util.js';
22
21
  import { getVersions } from '../versioning.js';
23
22
  import { startProverBroker } from './start_prover_broker.js';
24
23
 
@@ -38,53 +37,48 @@ export async function startProverNode(
38
37
  ...extractRelevantOptions<ProverNodeConfig>(options, proverNodeConfigMappings, 'proverNode'), // override with command line options
39
38
  };
40
39
 
41
- if (!options.archiver && !proverConfig.archiverUrl) {
42
- userLog('--archiver.archiverUrl is required to start a Prover Node without --archiver option');
43
- process.exit(1);
44
- }
45
-
46
- if (!proverConfig.publisherPrivateKey || proverConfig.publisherPrivateKey === NULL_KEY) {
47
- if (!options.l1Mnemonic) {
48
- userLog(`--l1-mnemonic is required to start a Prover Node without --node.publisherPrivateKey`);
49
- process.exit(1);
50
- }
51
- const hdAccount = mnemonicToAccount(options.l1Mnemonic);
52
- const privKey = hdAccount.getHdKey().privateKey;
53
- proverConfig.publisherPrivateKey = `0x${Buffer.from(privKey!).toString('hex')}`;
54
- }
55
-
56
- // TODO(palla/prover-node) L1 contract addresses should not silently default to zero,
57
- // they should be undefined if not set and fail loudly.
58
- // Load l1 contract addresses from aztec node if not set.
59
- const isRollupAddressSet =
60
- proverConfig.l1Contracts?.rollupAddress && !proverConfig.l1Contracts.rollupAddress.isZero();
61
- const nodeUrl = proverConfig.nodeUrl ?? proverConfig.proverCoordinationNodeUrl;
62
- if (nodeUrl && !isRollupAddressSet) {
63
- userLog(`Loading L1 contract addresses from aztec node at ${nodeUrl}`);
64
- proverConfig.l1Contracts = await createAztecNodeClient(nodeUrl).getL1ContractAddresses();
40
+ if (!proverConfig.l1Contracts.registryAddress || proverConfig.l1Contracts.registryAddress.isZero()) {
41
+ throw new Error('L1 registry address is required to start a Prover Node');
65
42
  }
66
43
 
67
- // If we create an archiver here, validate the L1 config
68
- if (options.archiver) {
69
- if (!proverConfig.l1Contracts.registryAddress || proverConfig.l1Contracts.registryAddress.isZero()) {
70
- throw new Error('L1 registry address is required to start a Prover Node with --archiver option');
71
- }
72
- const { addresses, config } = await getL1Config(
73
- proverConfig.l1Contracts.registryAddress,
74
- proverConfig.l1RpcUrls,
75
- proverConfig.l1ChainId,
44
+ const followsCanonicalRollup = typeof proverConfig.rollupVersion !== 'number';
45
+ const { addresses, config } = await getL1Config(
46
+ proverConfig.l1Contracts.registryAddress,
47
+ proverConfig.l1RpcUrls,
48
+ proverConfig.l1ChainId,
49
+ proverConfig.rollupVersion,
50
+ );
51
+ process.env.ROLLUP_CONTRACT_ADDRESS ??= addresses.rollupAddress.toString();
52
+ proverConfig.l1Contracts = addresses;
53
+ proverConfig = { ...proverConfig, ...config };
54
+
55
+ const testAccounts = proverConfig.testAccounts ? (await getInitialTestAccountsData()).map(a => a.address) : [];
56
+ const sponsoredFPCAccounts = proverConfig.sponsoredFPC ? [await getSponsoredFPCAddress()] : [];
57
+ const initialFundedAccounts = testAccounts.concat(sponsoredFPCAccounts);
58
+
59
+ userLog(`Initial funded accounts: ${initialFundedAccounts.map(a => a.toString()).join(', ')}`);
60
+ const { genesisArchiveRoot, prefilledPublicData } = await getGenesisValues(initialFundedAccounts);
61
+
62
+ userLog(`Genesis archive root: ${genesisArchiveRoot.toString()}`);
63
+
64
+ if (!Fr.fromHexString(config.genesisArchiveTreeRoot).equals(genesisArchiveRoot)) {
65
+ throw new Error(
66
+ `The computed genesis archive tree root ${genesisArchiveRoot} does not match the expected genesis archive tree root ${config.genesisArchiveTreeRoot} for the rollup deployed at ${addresses.rollupAddress}`,
76
67
  );
77
- proverConfig.l1Contracts = addresses;
78
- proverConfig = { ...proverConfig, ...config };
79
68
  }
80
69
 
81
70
  const telemetry = initTelemetryClient(extractRelevantOptions(options, telemetryClientConfigMappings, 'tel'));
82
71
 
83
72
  let broker: ProvingJobBroker;
84
73
  if (proverConfig.proverBrokerUrl) {
85
- // at 1TPS we'd enqueue ~1k tube proofs and ~1k AVM proofs immediately
86
- // set a lower connectio limit such that we don't overload the server
87
- const fetch = makeTracedFetch([1, 2, 3], false, makeUndiciFetch(new Agent({ connections: 100 })));
74
+ // at 1TPS we'd enqueue ~1k chonk verifier proofs and ~1k AVM proofs immediately
75
+ // set a lower connection limit such that we don't overload the server
76
+ // Keep retrying up to 30s
77
+ const fetch = makeTracedFetch(
78
+ [1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3],
79
+ false,
80
+ makeUndiciFetch(new Agent({ connections: 100 })),
81
+ );
88
82
  broker = createProvingJobBrokerClient(proverConfig.proverBrokerUrl, getVersions(proverConfig), fetch);
89
83
  } else if (options.proverBroker) {
90
84
  ({ broker } = await startProverBroker(options, signalHandlers, services, userLog));
@@ -99,14 +93,12 @@ export async function startProverNode(
99
93
  );
100
94
  }
101
95
 
102
- const initialFundedAccounts = proverConfig.testAccounts ? await getInitialTestAccounts() : [];
103
- const { prefilledPublicData } = await getGenesisValues(initialFundedAccounts.map(a => a.address));
96
+ await preloadCrsDataForVerifying(proverConfig, userLog);
104
97
 
105
98
  const proverNode = await createProverNode(proverConfig, { telemetry, broker }, { prefilledPublicData });
106
99
  services.proverNode = [proverNode, ProverNodeApiSchema];
107
100
 
108
- const p2p = proverNode.getP2P();
109
- if (p2p) {
101
+ if (proverNode.getP2P()) {
110
102
  services.p2p = [proverNode.getP2P(), P2PApiSchema];
111
103
  }
112
104
 
@@ -116,6 +108,17 @@ export async function startProverNode(
116
108
 
117
109
  signalHandlers.push(proverNode.stop.bind(proverNode));
118
110
 
119
- proverNode.start();
111
+ await proverNode.start();
112
+
113
+ if (proverConfig.autoUpdate !== 'disabled' && proverConfig.autoUpdateUrl) {
114
+ await setupUpdateMonitor(
115
+ proverConfig.autoUpdate,
116
+ new URL(proverConfig.autoUpdateUrl),
117
+ followsCanonicalRollup,
118
+ getPublicClient(proverConfig),
119
+ proverConfig.l1Contracts.registryAddress,
120
+ signalHandlers,
121
+ );
122
+ }
120
123
  return { config: proverConfig };
121
124
  }
@@ -0,0 +1,7 @@
1
+ import type { LogFn, Logger } from '@aztec/foundation/log';
2
+
3
+ import { preloadCrsDataForServerSideProving } from './util.js';
4
+
5
+ export async function preloadCrs(_options: any, userLog: LogFn, _debugLogger: Logger) {
6
+ await preloadCrsDataForServerSideProving({ realProofs: true }, userLog);
7
+ }
@@ -0,0 +1,21 @@
1
+ import { fileURLToPath } from '@aztec/foundation/url';
2
+
3
+ import { readFileSync } from 'fs';
4
+ import { dirname, resolve } from 'path';
5
+
6
+ export const getCliVersion = () => {
7
+ const packageJsonPath = resolve(dirname(fileURLToPath(import.meta.url)), '../../package.json');
8
+ const cliVersion: string = JSON.parse(readFileSync(packageJsonPath).toString()).version;
9
+
10
+ // If the version is 0.1.0, this is a placeholder version and we are in a docker container; query release please for the latest version
11
+ if (cliVersion === '0.1.0') {
12
+ const releasePleasePath = resolve(
13
+ dirname(fileURLToPath(import.meta.url)),
14
+ '../../../../.release-please-manifest.json',
15
+ );
16
+ const releaseVersion = JSON.parse(readFileSync(releasePleasePath).toString())['.'];
17
+ return releaseVersion;
18
+ }
19
+
20
+ return cliVersion;
21
+ };