@aztec/prover-node 0.0.0-test.0 → 0.0.1-commit.03f7ef2

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