@aztec/prover-node 0.0.0-test.1 → 0.0.1-commit.5daedc8

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 (82) hide show
  1. package/dest/actions/download-epoch-proving-job.d.ts +18 -0
  2. package/dest/actions/download-epoch-proving-job.d.ts.map +1 -0
  3. package/dest/actions/download-epoch-proving-job.js +37 -0
  4. package/dest/actions/index.d.ts +3 -0
  5. package/dest/actions/index.d.ts.map +1 -0
  6. package/dest/actions/index.js +2 -0
  7. package/dest/actions/rerun-epoch-proving-job.d.ts +11 -0
  8. package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -0
  9. package/dest/actions/rerun-epoch-proving-job.js +40 -0
  10. package/dest/actions/upload-epoch-proof-failure.d.ts +15 -0
  11. package/dest/actions/upload-epoch-proof-failure.d.ts.map +1 -0
  12. package/dest/actions/upload-epoch-proof-failure.js +78 -0
  13. package/dest/bin/run-failed-epoch.d.ts +2 -0
  14. package/dest/bin/run-failed-epoch.d.ts.map +1 -0
  15. package/dest/bin/run-failed-epoch.js +67 -0
  16. package/dest/config.d.ts +13 -10
  17. package/dest/config.d.ts.map +1 -1
  18. package/dest/config.js +81 -14
  19. package/dest/factory.d.ts +13 -9
  20. package/dest/factory.d.ts.map +1 -1
  21. package/dest/factory.js +95 -31
  22. package/dest/index.d.ts +2 -2
  23. package/dest/index.d.ts.map +1 -1
  24. package/dest/index.js +1 -1
  25. package/dest/job/epoch-proving-job-data.d.ts +17 -0
  26. package/dest/job/epoch-proving-job-data.d.ts.map +1 -0
  27. package/dest/job/epoch-proving-job-data.js +53 -0
  28. package/dest/job/epoch-proving-job.d.ts +25 -17
  29. package/dest/job/epoch-proving-job.d.ts.map +1 -1
  30. package/dest/job/epoch-proving-job.js +155 -51
  31. package/dest/metrics.d.ts +29 -5
  32. package/dest/metrics.d.ts.map +1 -1
  33. package/dest/metrics.js +141 -35
  34. package/dest/monitors/epoch-monitor.d.ts +5 -2
  35. package/dest/monitors/epoch-monitor.d.ts.map +1 -1
  36. package/dest/monitors/epoch-monitor.js +15 -2
  37. package/dest/monitors/index.d.ts +1 -1
  38. package/dest/prover-node-publisher.d.ts +10 -12
  39. package/dest/prover-node-publisher.d.ts.map +1 -1
  40. package/dest/prover-node-publisher.js +62 -62
  41. package/dest/prover-node.d.ts +48 -43
  42. package/dest/prover-node.d.ts.map +1 -1
  43. package/dest/prover-node.js +175 -105
  44. package/dest/prover-publisher-factory.d.ts +21 -0
  45. package/dest/prover-publisher-factory.d.ts.map +1 -0
  46. package/dest/prover-publisher-factory.js +26 -0
  47. package/dest/test/index.d.ts +5 -3
  48. package/dest/test/index.d.ts.map +1 -1
  49. package/dest/test/index.js +1 -3
  50. package/package.json +39 -33
  51. package/src/actions/download-epoch-proving-job.ts +44 -0
  52. package/src/actions/index.ts +2 -0
  53. package/src/actions/rerun-epoch-proving-job.ts +61 -0
  54. package/src/actions/upload-epoch-proof-failure.ts +88 -0
  55. package/src/bin/run-failed-epoch.ts +77 -0
  56. package/src/config.ts +108 -24
  57. package/src/factory.ts +163 -43
  58. package/src/index.ts +1 -1
  59. package/src/job/epoch-proving-job-data.ts +77 -0
  60. package/src/job/epoch-proving-job.ts +222 -52
  61. package/src/metrics.ts +135 -37
  62. package/src/monitors/epoch-monitor.ts +18 -6
  63. package/src/prover-node-publisher.ts +96 -88
  64. package/src/prover-node.ts +213 -136
  65. package/src/prover-publisher-factory.ts +37 -0
  66. package/src/test/index.ts +7 -4
  67. package/dest/http.d.ts +0 -8
  68. package/dest/http.d.ts.map +0 -1
  69. package/dest/http.js +0 -9
  70. package/dest/prover-coordination/config.d.ts +0 -7
  71. package/dest/prover-coordination/config.d.ts.map +0 -1
  72. package/dest/prover-coordination/config.js +0 -11
  73. package/dest/prover-coordination/factory.d.ts +0 -22
  74. package/dest/prover-coordination/factory.d.ts.map +0 -1
  75. package/dest/prover-coordination/factory.js +0 -42
  76. package/dest/prover-coordination/index.d.ts +0 -3
  77. package/dest/prover-coordination/index.d.ts.map +0 -1
  78. package/dest/prover-coordination/index.js +0 -2
  79. package/src/http.ts +0 -13
  80. package/src/prover-coordination/config.ts +0 -17
  81. package/src/prover-coordination/factory.ts +0 -72
  82. package/src/prover-coordination/index.ts +0 -2
package/src/factory.ts CHANGED
@@ -1,43 +1,108 @@
1
1
  import { type Archiver, createArchiver } from '@aztec/archiver';
2
+ import { BBCircuitVerifier, QueuedIVCVerifier, TestCircuitVerifier } from '@aztec/bb-prover';
2
3
  import { type BlobSinkClientInterface, createBlobSinkClient } from '@aztec/blob-sink/client';
3
4
  import { EpochCache } from '@aztec/epoch-cache';
4
- import { L1TxUtils, RollupContract, createEthereumChain, createL1Clients } from '@aztec/ethereum';
5
+ import { L1TxUtils, PublisherManager, RollupContract, createEthereumChain } from '@aztec/ethereum';
6
+ import { pick } from '@aztec/foundation/collection';
5
7
  import { type Logger, createLogger } from '@aztec/foundation/log';
8
+ import { DateProvider } from '@aztec/foundation/timer';
6
9
  import type { DataStoreConfig } from '@aztec/kv-store/config';
7
- import { createProverClient } from '@aztec/prover-client';
10
+ import { type KeyStoreConfig, KeystoreManager, loadKeystores, mergeKeystores } from '@aztec/node-keystore';
11
+ import { trySnapshotSync } from '@aztec/node-lib/actions';
12
+ import { createL1TxUtilsFromEthSignerWithStore } from '@aztec/node-lib/factories';
13
+ import { NodeRpcTxSource, createP2PClient } from '@aztec/p2p';
14
+ import { type ProverClientConfig, createProverClient } from '@aztec/prover-client';
8
15
  import { createAndStartProvingBroker } from '@aztec/prover-client/broker';
9
- import type { ProverCoordination, ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
16
+ import type { AztecNode, ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
17
+ import { P2PClientType } from '@aztec/stdlib/p2p';
10
18
  import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
11
- import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
19
+ import { getPackageVersion } from '@aztec/stdlib/update-checker';
20
+ import { L1Metrics, type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
12
21
  import { createWorldStateSynchronizer } from '@aztec/world-state';
13
22
 
14
- import type { ProverNodeConfig } from './config.js';
23
+ import { createPublicClient, fallback, http } from 'viem';
24
+
25
+ import { type ProverNodeConfig, createKeyStoreForProver } from './config.js';
15
26
  import { EpochMonitor } from './monitors/epoch-monitor.js';
16
- import { createProverCoordination } from './prover-coordination/factory.js';
17
- import { ProverNodePublisher } from './prover-node-publisher.js';
18
- import { ProverNode, type ProverNodeOptions } from './prover-node.js';
27
+ import { ProverNode } from './prover-node.js';
28
+ import { ProverPublisherFactory } from './prover-publisher-factory.js';
29
+
30
+ export type ProverNodeDeps = {
31
+ telemetry?: TelemetryClient;
32
+ log?: Logger;
33
+ aztecNodeTxProvider?: Pick<AztecNode, 'getTxsByHash'>;
34
+ archiver?: Archiver;
35
+ publisherFactory?: ProverPublisherFactory;
36
+ blobSinkClient?: BlobSinkClientInterface;
37
+ broker?: ProvingJobBroker;
38
+ l1TxUtils?: L1TxUtils;
39
+ dateProvider?: DateProvider;
40
+ };
19
41
 
20
42
  /** Creates a new prover node given a config. */
21
43
  export async function createProverNode(
22
- config: ProverNodeConfig & DataStoreConfig,
23
- deps: {
24
- telemetry?: TelemetryClient;
25
- log?: Logger;
26
- aztecNodeTxProvider?: ProverCoordination;
27
- archiver?: Archiver;
28
- publisher?: ProverNodePublisher;
29
- blobSinkClient?: BlobSinkClientInterface;
30
- broker?: ProvingJobBroker;
31
- l1TxUtils?: L1TxUtils;
32
- } = {},
44
+ userConfig: ProverNodeConfig & DataStoreConfig & KeyStoreConfig,
45
+ deps: ProverNodeDeps = {},
33
46
  options: {
34
47
  prefilledPublicData?: PublicDataTreeLeaf[];
35
48
  } = {},
36
49
  ) {
50
+ const config = { ...userConfig };
37
51
  const telemetry = deps.telemetry ?? getTelemetryClient();
38
- const blobSinkClient = deps.blobSinkClient ?? createBlobSinkClient(config);
52
+ const dateProvider = deps.dateProvider ?? new DateProvider();
53
+ const blobSinkClient =
54
+ deps.blobSinkClient ?? createBlobSinkClient(config, { logger: createLogger('prover-node:blob-sink:client') });
39
55
  const log = deps.log ?? createLogger('prover-node');
40
- const archiver = deps.archiver ?? (await createArchiver(config, blobSinkClient, { blockUntilSync: true }, telemetry));
56
+
57
+ // Build a key store from file if given or from environment otherwise
58
+ let keyStoreManager: KeystoreManager | undefined;
59
+ const keyStoreProvided = config.keyStoreDirectory !== undefined && config.keyStoreDirectory.length > 0;
60
+ if (keyStoreProvided) {
61
+ const keyStores = loadKeystores(config.keyStoreDirectory!);
62
+ keyStoreManager = new KeystoreManager(mergeKeystores(keyStores));
63
+ } else {
64
+ const keyStore = createKeyStoreForProver(config);
65
+ if (keyStore) {
66
+ keyStoreManager = new KeystoreManager(keyStore);
67
+ }
68
+ }
69
+
70
+ await keyStoreManager?.validateSigners();
71
+
72
+ // Extract the prover signers from the key store and verify that we have one.
73
+ const proverSigners = keyStoreManager?.createProverSigners();
74
+
75
+ if (proverSigners === undefined) {
76
+ throw new Error('Failed to create prover key store configuration');
77
+ } else if (proverSigners.signers.length === 0) {
78
+ throw new Error('No prover signers found in the key store');
79
+ } else if (!keyStoreProvided) {
80
+ log.warn(
81
+ 'KEY STORE CREATED FROM ENVIRONMENT, IT IS RECOMMENDED TO USE A FILE-BASED KEY STORE IN PRODUCTION ENVIRONMENTS',
82
+ );
83
+ }
84
+
85
+ log.info(`Creating prover with publishers ${proverSigners.signers.map(signer => signer.address.toString()).join()}`);
86
+
87
+ // Only consider user provided config if it is valid
88
+ const proverIdInUserConfig = config.proverId === undefined || config.proverId.isZero() ? undefined : config.proverId;
89
+
90
+ // ProverId: Take from key store if provided, otherwise from user config if valid, otherwise address of first signer
91
+ const proverId = proverSigners.id ?? proverIdInUserConfig ?? proverSigners.signers[0].address;
92
+
93
+ // Now create the prover client configuration from this.
94
+ const proverClientConfig: ProverClientConfig = {
95
+ ...config,
96
+ proverId,
97
+ };
98
+
99
+ await trySnapshotSync(config, log);
100
+
101
+ const epochCache = await EpochCache.create(config.l1Contracts.rollupAddress, config);
102
+
103
+ const archiver =
104
+ deps.archiver ??
105
+ (await createArchiver(config, { blobSinkClient, epochCache, telemetry, dateProvider }, { blockUntilSync: true }));
41
106
  log.verbose(`Created archiver and synced to block ${await archiver.getBlockNumber()}`);
42
107
 
43
108
  const worldStateConfig = { ...config, worldStateProvenBlocksOnly: false };
@@ -50,49 +115,104 @@ export async function createProverNode(
50
115
  await worldStateSynchronizer.start();
51
116
 
52
117
  const broker = deps.broker ?? (await createAndStartProvingBroker(config, telemetry));
53
- const prover = await createProverClient(config, worldStateSynchronizer, broker, telemetry);
54
118
 
55
- const { l1RpcUrls: rpcUrls, l1ChainId: chainId, publisherPrivateKey } = config;
119
+ const prover = await createProverClient(proverClientConfig, worldStateSynchronizer, broker, telemetry);
120
+
121
+ const { l1RpcUrls: rpcUrls, l1ChainId: chainId } = config;
56
122
  const chain = createEthereumChain(rpcUrls, chainId);
57
- const { publicClient, walletClient } = createL1Clients(rpcUrls, publisherPrivateKey, chain.chainInfo);
123
+
124
+ const publicClient = createPublicClient({
125
+ chain: chain.chainInfo,
126
+ transport: fallback(config.l1RpcUrls.map((url: string) => http(url))),
127
+ pollingInterval: config.viemPollingIntervalMS,
128
+ });
58
129
 
59
130
  const rollupContract = new RollupContract(publicClient, config.l1Contracts.rollupAddress.toString());
60
131
 
61
- const l1TxUtils = deps.l1TxUtils ?? new L1TxUtils(publicClient, walletClient, log, config);
62
- const publisher = deps.publisher ?? new ProverNodePublisher(config, { telemetry, rollupContract, l1TxUtils });
132
+ const l1TxUtils = deps.l1TxUtils
133
+ ? [deps.l1TxUtils]
134
+ : await createL1TxUtilsFromEthSignerWithStore(
135
+ publicClient,
136
+ proverSigners.signers,
137
+ { ...config, scope: 'prover' },
138
+ { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
139
+ );
63
140
 
64
- const epochCache = await EpochCache.create(config.l1Contracts.rollupAddress, config);
141
+ const publisherFactory =
142
+ deps.publisherFactory ??
143
+ new ProverPublisherFactory(config, {
144
+ rollupContract,
145
+ publisherManager: new PublisherManager(l1TxUtils, config),
146
+ telemetry,
147
+ });
65
148
 
66
- // If config.p2pEnabled is true, createProverCoordination will create a p2p client where txs are requested
67
- // If config.p2pEnabled is false, createProverCoordination request information from the AztecNode
68
- const proverCoordination = await createProverCoordination(config, {
69
- aztecNodeTxProvider: deps.aztecNodeTxProvider,
70
- worldStateSynchronizer,
149
+ const proofVerifier = new QueuedIVCVerifier(
150
+ config,
151
+ config.realProofs
152
+ ? await BBCircuitVerifier.new(config)
153
+ : new TestCircuitVerifier(config.proverTestVerificationDelayMs),
154
+ );
155
+
156
+ const p2pClient = await createP2PClient(
157
+ P2PClientType.Prover,
158
+ config,
71
159
  archiver,
160
+ proofVerifier,
161
+ worldStateSynchronizer,
72
162
  epochCache,
163
+ getPackageVersion() ?? '',
164
+ dateProvider,
73
165
  telemetry,
74
- });
166
+ {
167
+ txCollectionNodeSources: deps.aztecNodeTxProvider
168
+ ? [new NodeRpcTxSource(deps.aztecNodeTxProvider, 'TestNode')]
169
+ : [],
170
+ },
171
+ );
75
172
 
76
- const proverNodeConfig: ProverNodeOptions = {
77
- maxPendingJobs: config.proverNodeMaxPendingJobs,
78
- pollingIntervalMs: config.proverNodePollingIntervalMs,
79
- maxParallelBlocksPerEpoch: config.proverNodeMaxParallelBlocksPerEpoch,
80
- txGatheringMaxParallelRequests: config.txGatheringMaxParallelRequests,
81
- txGatheringIntervalMs: config.txGatheringIntervalMs,
82
- txGatheringTimeoutMs: config.txGatheringTimeoutMs,
173
+ await p2pClient.start();
174
+
175
+ const proverNodeConfig = {
176
+ ...pick(
177
+ config,
178
+ 'proverNodeMaxPendingJobs',
179
+ 'proverNodeMaxParallelBlocksPerEpoch',
180
+ 'proverNodePollingIntervalMs',
181
+ 'proverNodeEpochProvingDelayMs',
182
+ 'txGatheringMaxParallelRequests',
183
+ 'txGatheringIntervalMs',
184
+ 'txGatheringTimeoutMs',
185
+ 'proverNodeFailedEpochStore',
186
+ 'proverNodeDisableProofPublish',
187
+ 'dataDirectory',
188
+ 'l1ChainId',
189
+ 'rollupVersion',
190
+ ),
83
191
  };
84
192
 
85
- const epochMonitor = await EpochMonitor.create(archiver, proverNodeConfig, telemetry);
193
+ const epochMonitor = await EpochMonitor.create(
194
+ archiver,
195
+ { pollingIntervalMs: config.proverNodePollingIntervalMs, provingDelayMs: config.proverNodeEpochProvingDelayMs },
196
+ telemetry,
197
+ );
198
+
199
+ const l1Metrics = new L1Metrics(
200
+ telemetry.getMeter('ProverNodeL1Metrics'),
201
+ publicClient,
202
+ l1TxUtils.map(utils => utils.getSenderAddress()),
203
+ );
86
204
 
87
205
  return new ProverNode(
88
206
  prover,
89
- publisher,
207
+ publisherFactory,
90
208
  archiver,
91
209
  archiver,
92
210
  archiver,
93
211
  worldStateSynchronizer,
94
- proverCoordination,
212
+ p2pClient,
95
213
  epochMonitor,
214
+ rollupContract,
215
+ l1Metrics,
96
216
  proverNodeConfig,
97
217
  telemetry,
98
218
  );
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
+ export * from './actions/index.js';
1
2
  export * from './config.js';
2
3
  export * from './factory.js';
3
- export * from './http.js';
4
4
  export * from './prover-node-publisher.js';
5
5
  export * from './prover-node.js';
@@ -0,0 +1,77 @@
1
+ import { EpochNumber } from '@aztec/foundation/branded-types';
2
+ import { Fr } from '@aztec/foundation/fields';
3
+ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
4
+ import { CommitteeAttestation, L2Block } from '@aztec/stdlib/block';
5
+ import { BlockHeader, Tx } from '@aztec/stdlib/tx';
6
+
7
+ /** All data from an epoch used in proving. */
8
+ export type EpochProvingJobData = {
9
+ epochNumber: EpochNumber;
10
+ blocks: L2Block[];
11
+ txs: Map<string, Tx>;
12
+ l1ToL2Messages: Record<number, Fr[]>;
13
+ previousBlockHeader: BlockHeader;
14
+ attestations: CommitteeAttestation[];
15
+ };
16
+
17
+ export function validateEpochProvingJobData(data: EpochProvingJobData) {
18
+ if (data.blocks.length > 0 && data.previousBlockHeader.getBlockNumber() + 1 !== data.blocks[0].number) {
19
+ throw new Error(
20
+ `Initial block number ${
21
+ data.blocks[0].number
22
+ } does not match previous block header ${data.previousBlockHeader.getBlockNumber()}`,
23
+ );
24
+ }
25
+
26
+ for (const blockNumber of data.blocks.map(block => block.number)) {
27
+ if (!(blockNumber in data.l1ToL2Messages)) {
28
+ throw new Error(`Missing L1 to L2 messages for block number ${blockNumber}`);
29
+ }
30
+ }
31
+ }
32
+
33
+ export function serializeEpochProvingJobData(data: EpochProvingJobData): Buffer {
34
+ const blocks = data.blocks.map(block => block.toBuffer());
35
+ const txs = Array.from(data.txs.values()).map(tx => tx.toBuffer());
36
+ const l1ToL2Messages = Object.entries(data.l1ToL2Messages).map(([blockNumber, messages]) => [
37
+ Number(blockNumber),
38
+ messages.length,
39
+ ...messages,
40
+ ]);
41
+ const attestations = data.attestations.map(attestation => attestation.toBuffer());
42
+
43
+ return serializeToBuffer(
44
+ data.epochNumber,
45
+ data.previousBlockHeader,
46
+ blocks.length,
47
+ ...blocks,
48
+ txs.length,
49
+ ...txs,
50
+ l1ToL2Messages.length,
51
+ ...l1ToL2Messages,
52
+ attestations.length,
53
+ ...attestations,
54
+ );
55
+ }
56
+
57
+ export function deserializeEpochProvingJobData(buf: Buffer): EpochProvingJobData {
58
+ const reader = BufferReader.asReader(buf);
59
+ const epochNumber = EpochNumber(reader.readNumber());
60
+ const previousBlockHeader = reader.readObject(BlockHeader);
61
+ const blocks = reader.readVector(L2Block);
62
+ const txArray = reader.readVector(Tx);
63
+
64
+ const l1ToL2MessageBlockCount = reader.readNumber();
65
+ const l1ToL2Messages: Record<number, Fr[]> = {};
66
+ for (let i = 0; i < l1ToL2MessageBlockCount; i++) {
67
+ const blockNumber = reader.readNumber();
68
+ const messages = reader.readVector(Fr);
69
+ l1ToL2Messages[blockNumber] = messages;
70
+ }
71
+
72
+ const attestations = reader.readVector(CommitteeAttestation);
73
+
74
+ const txs = new Map<string, Tx>(txArray.map(tx => [tx.getTxHash().toString(), tx]));
75
+
76
+ return { epochNumber, previousBlockHeader, blocks, txs, l1ToL2Messages, attestations };
77
+ }