@aztec/prover-node 0.85.0 → 0.86.0-nightly.20250425
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.
- package/dest/actions/download-epoch-proving-job.d.ts +15 -0
- package/dest/actions/download-epoch-proving-job.d.ts.map +1 -0
- package/dest/actions/download-epoch-proving-job.js +35 -0
- package/dest/actions/index.d.ts +3 -0
- package/dest/actions/index.d.ts.map +1 -0
- package/dest/actions/index.js +2 -0
- package/dest/actions/rerun-epoch-proving-job.d.ts +11 -0
- package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -0
- package/dest/actions/rerun-epoch-proving-job.js +37 -0
- package/dest/actions/upload-epoch-proof-failure.d.ts +15 -0
- package/dest/actions/upload-epoch-proof-failure.d.ts.map +1 -0
- package/dest/actions/upload-epoch-proof-failure.js +78 -0
- package/dest/config.d.ts +4 -4
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +12 -7
- package/dest/factory.d.ts +3 -2
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +13 -13
- package/dest/index.d.ts +1 -0
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/job/epoch-proving-job-data.d.ts +17 -0
- package/dest/job/epoch-proving-job-data.d.ts.map +1 -0
- package/dest/job/epoch-proving-job-data.js +45 -0
- package/dest/job/epoch-proving-job.d.ts +9 -9
- package/dest/job/epoch-proving-job.d.ts.map +1 -1
- package/dest/job/epoch-proving-job.js +38 -21
- package/dest/metrics.d.ts +27 -4
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +104 -36
- package/dest/monitors/epoch-monitor.d.ts +1 -1
- package/dest/monitors/epoch-monitor.d.ts.map +1 -1
- package/dest/monitors/epoch-monitor.js +7 -2
- package/dest/prover-coordination/combined-prover-coordination.d.ts +22 -0
- package/dest/prover-coordination/combined-prover-coordination.d.ts.map +1 -0
- package/dest/prover-coordination/combined-prover-coordination.js +136 -0
- package/dest/prover-coordination/config.d.ts +1 -1
- package/dest/prover-coordination/config.d.ts.map +1 -1
- package/dest/prover-coordination/config.js +5 -4
- package/dest/prover-coordination/factory.d.ts +5 -4
- package/dest/prover-coordination/factory.d.ts.map +1 -1
- package/dest/prover-coordination/factory.js +20 -14
- package/dest/prover-node-publisher.d.ts +1 -2
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +7 -13
- package/dest/prover-node.d.ts +26 -24
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +103 -51
- package/dest/test/index.d.ts +4 -2
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +1 -1
- package/package.json +20 -22
- package/src/actions/download-epoch-proving-job.ts +46 -0
- package/src/actions/index.ts +2 -0
- package/src/actions/rerun-epoch-proving-job.ts +59 -0
- package/src/actions/upload-epoch-proof-failure.ts +88 -0
- package/src/config.ts +16 -10
- package/src/factory.ts +31 -17
- package/src/index.ts +1 -0
- package/src/job/epoch-proving-job-data.ts +68 -0
- package/src/job/epoch-proving-job.ts +53 -23
- package/src/metrics.ts +111 -38
- package/src/monitors/epoch-monitor.ts +5 -3
- package/src/prover-coordination/combined-prover-coordination.ts +160 -0
- package/src/prover-coordination/config.ts +6 -5
- package/src/prover-coordination/factory.ts +36 -25
- package/src/prover-node-publisher.ts +9 -18
- package/src/prover-node.ts +151 -74
- package/src/test/index.ts +5 -2
package/src/prover-node.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Archiver } from '@aztec/archiver';
|
|
2
|
+
import type { ViemPublicClient } from '@aztec/ethereum';
|
|
3
|
+
import { assertRequired, compact, pick, sum } from '@aztec/foundation/collection';
|
|
2
4
|
import { memoize } from '@aztec/foundation/decorators';
|
|
5
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
|
+
import type { Fr } from '@aztec/foundation/fields';
|
|
3
7
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
8
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
5
9
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
6
10
|
import type { Maybe } from '@aztec/foundation/types';
|
|
7
|
-
import type {
|
|
11
|
+
import type { DataStoreConfig } from '@aztec/kv-store/config';
|
|
8
12
|
import { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
9
13
|
import type { L2Block, L2BlockSource } from '@aztec/stdlib/block';
|
|
14
|
+
import type { ChainConfig } from '@aztec/stdlib/config';
|
|
10
15
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
11
16
|
import { getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
12
17
|
import {
|
|
@@ -20,8 +25,7 @@ import {
|
|
|
20
25
|
tryStop,
|
|
21
26
|
} from '@aztec/stdlib/interfaces/server';
|
|
22
27
|
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
23
|
-
import type {
|
|
24
|
-
import type { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
28
|
+
import type { TxHash } from '@aztec/stdlib/tx';
|
|
25
29
|
import {
|
|
26
30
|
Attributes,
|
|
27
31
|
L1Metrics,
|
|
@@ -32,24 +36,20 @@ import {
|
|
|
32
36
|
trackSpan,
|
|
33
37
|
} from '@aztec/telemetry-client';
|
|
34
38
|
|
|
39
|
+
import { uploadEpochProofFailure } from './actions/upload-epoch-proof-failure.js';
|
|
40
|
+
import type { SpecificProverNodeConfig } from './config.js';
|
|
41
|
+
import type { EpochProvingJobData } from './job/epoch-proving-job-data.js';
|
|
35
42
|
import { EpochProvingJob, type EpochProvingJobState } from './job/epoch-proving-job.js';
|
|
36
|
-
import {
|
|
43
|
+
import { ProverNodeJobMetrics, ProverNodeRewardsMetrics } from './metrics.js';
|
|
37
44
|
import type { EpochMonitor, EpochMonitorHandler } from './monitors/epoch-monitor.js';
|
|
38
45
|
import type { ProverNodePublisher } from './prover-node-publisher.js';
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
maxPendingJobs: number;
|
|
43
|
-
maxParallelBlocksPerEpoch: number;
|
|
44
|
-
txGatheringTimeoutMs: number;
|
|
45
|
-
txGatheringIntervalMs: number;
|
|
46
|
-
txGatheringMaxParallelRequests: number;
|
|
47
|
-
};
|
|
47
|
+
type ProverNodeOptions = SpecificProverNodeConfig & Partial<DataStoreOptions>;
|
|
48
|
+
type DataStoreOptions = Pick<DataStoreConfig, 'dataDirectory'> & Pick<ChainConfig, 'l1ChainId' | 'rollupVersion'>;
|
|
48
49
|
|
|
49
50
|
/**
|
|
50
|
-
* An Aztec Prover Node is a standalone process that monitors the unfinalised chain on L1 for unproven
|
|
51
|
-
*
|
|
52
|
-
* from a tx source in the p2p network or an external node, re-executes their public functions, creates a rollup
|
|
51
|
+
* An Aztec Prover Node is a standalone process that monitors the unfinalised chain on L1 for unproven epochs,
|
|
52
|
+
* fetches their txs from the p2p network or external nodes, re-executes their public functions, creates a rollup
|
|
53
53
|
* proof for the epoch, and submits it to L1.
|
|
54
54
|
*/
|
|
55
55
|
export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable {
|
|
@@ -57,8 +57,9 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
57
57
|
private dateProvider = new DateProvider();
|
|
58
58
|
|
|
59
59
|
private jobs: Map<string, EpochProvingJob> = new Map();
|
|
60
|
-
private
|
|
61
|
-
private
|
|
60
|
+
private config: ProverNodeOptions;
|
|
61
|
+
private jobMetrics: ProverNodeJobMetrics;
|
|
62
|
+
private rewardsMetrics: ProverNodeRewardsMetrics;
|
|
62
63
|
private l1Metrics: L1Metrics;
|
|
63
64
|
|
|
64
65
|
private txFetcher: RunningPromise;
|
|
@@ -73,28 +74,42 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
73
74
|
protected readonly l1ToL2MessageSource: L1ToL2MessageSource,
|
|
74
75
|
protected readonly contractDataSource: ContractDataSource,
|
|
75
76
|
protected readonly worldState: WorldStateSynchronizer,
|
|
76
|
-
protected readonly coordination: ProverCoordination
|
|
77
|
+
protected readonly coordination: ProverCoordination,
|
|
77
78
|
protected readonly epochsMonitor: EpochMonitor,
|
|
78
|
-
|
|
79
|
+
config: Partial<ProverNodeOptions> = {},
|
|
79
80
|
protected readonly telemetryClient: TelemetryClient = getTelemetryClient(),
|
|
80
81
|
) {
|
|
81
|
-
this.l1Metrics = new L1Metrics(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
82
|
+
this.l1Metrics = new L1Metrics(
|
|
83
|
+
telemetryClient.getMeter('ProverNodeL1Metrics'),
|
|
84
|
+
publisher.l1TxUtils.client as unknown as ViemPublicClient,
|
|
85
|
+
[publisher.getSenderAddress()],
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
this.config = {
|
|
89
|
+
proverNodePollingIntervalMs: 1_000,
|
|
90
|
+
proverNodeMaxPendingJobs: 100,
|
|
91
|
+
proverNodeMaxParallelBlocksPerEpoch: 32,
|
|
90
92
|
txGatheringIntervalMs: 1_000,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
+
txGatheringBatchSize: 10,
|
|
94
|
+
txGatheringMaxParallelRequestsPerNode: 100,
|
|
95
|
+
proverNodeFailedEpochStore: undefined,
|
|
96
|
+
...compact(config),
|
|
93
97
|
};
|
|
94
98
|
|
|
95
|
-
this.
|
|
99
|
+
this.validateConfig();
|
|
100
|
+
|
|
101
|
+
const meter = telemetryClient.getMeter('ProverNode');
|
|
96
102
|
this.tracer = telemetryClient.getTracer('ProverNode');
|
|
97
|
-
|
|
103
|
+
|
|
104
|
+
this.jobMetrics = new ProverNodeJobMetrics(meter, telemetryClient.getTracer('EpochProvingJob'));
|
|
105
|
+
|
|
106
|
+
this.rewardsMetrics = new ProverNodeRewardsMetrics(
|
|
107
|
+
meter,
|
|
108
|
+
EthAddress.fromField(this.prover.getProverId()),
|
|
109
|
+
this.publisher.getRollupContract(),
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
this.txFetcher = new RunningPromise(() => this.checkForTxs(), this.log, this.config.txGatheringIntervalMs);
|
|
98
113
|
}
|
|
99
114
|
|
|
100
115
|
public getProverId() {
|
|
@@ -102,18 +117,15 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
102
117
|
}
|
|
103
118
|
|
|
104
119
|
public getP2P() {
|
|
105
|
-
|
|
106
|
-
if (typeof asP2PClient.isP2PClient === 'function' && asP2PClient.isP2PClient()) {
|
|
107
|
-
return asP2PClient;
|
|
108
|
-
}
|
|
109
|
-
return undefined;
|
|
120
|
+
return this.coordination.getP2PClient();
|
|
110
121
|
}
|
|
111
122
|
|
|
112
123
|
/**
|
|
113
124
|
* Handles an epoch being completed by starting a proof for it if there are no active jobs for it.
|
|
114
125
|
* @param epochNumber - The epoch number that was just completed.
|
|
126
|
+
* @returns false if there is an error, true otherwise
|
|
115
127
|
*/
|
|
116
|
-
async handleEpochReadyToProve(epochNumber: bigint): Promise<
|
|
128
|
+
async handleEpochReadyToProve(epochNumber: bigint): Promise<boolean> {
|
|
117
129
|
try {
|
|
118
130
|
this.log.debug(`Running jobs as ${epochNumber} is ready to prove`, {
|
|
119
131
|
jobs: Array.from(this.jobs.values()).map(job => `${job.getEpochNumber()}:${job.getId()}`),
|
|
@@ -123,15 +135,17 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
123
135
|
this.log.warn(`Not starting proof for ${epochNumber} since there are active jobs for the epoch`, {
|
|
124
136
|
activeJobs: activeJobs.map(job => job.uuid),
|
|
125
137
|
});
|
|
126
|
-
return;
|
|
138
|
+
return true;
|
|
127
139
|
}
|
|
128
140
|
await this.startProof(epochNumber);
|
|
141
|
+
return true;
|
|
129
142
|
} catch (err) {
|
|
130
143
|
if (err instanceof EmptyEpochError) {
|
|
131
144
|
this.log.info(`Not starting proof for ${epochNumber} since no blocks were found`);
|
|
132
145
|
} else {
|
|
133
146
|
this.log.error(`Error handling epoch completed`, err);
|
|
134
147
|
}
|
|
148
|
+
return false;
|
|
135
149
|
}
|
|
136
150
|
}
|
|
137
151
|
|
|
@@ -139,11 +153,12 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
139
153
|
* Starts the prover node so it periodically checks for unproven epochs in the unfinalised chain from L1 and
|
|
140
154
|
* starts proving jobs for them.
|
|
141
155
|
*/
|
|
142
|
-
start() {
|
|
156
|
+
async start() {
|
|
143
157
|
this.txFetcher.start();
|
|
144
158
|
this.epochsMonitor.start(this);
|
|
145
159
|
this.l1Metrics.start();
|
|
146
|
-
|
|
160
|
+
await this.rewardsMetrics.start();
|
|
161
|
+
this.log.info(`Started Prover Node with prover id ${this.prover.getProverId().toString()}`, this.config);
|
|
147
162
|
}
|
|
148
163
|
|
|
149
164
|
/**
|
|
@@ -160,13 +175,15 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
160
175
|
await this.worldState.stop();
|
|
161
176
|
await tryStop(this.coordination);
|
|
162
177
|
this.l1Metrics.stop();
|
|
178
|
+
this.rewardsMetrics.stop();
|
|
163
179
|
await this.telemetryClient.stop();
|
|
164
180
|
this.log.info('Stopped ProverNode');
|
|
165
181
|
}
|
|
166
182
|
|
|
167
183
|
/** Returns world state status. */
|
|
168
|
-
public getWorldStateSyncStatus(): Promise<WorldStateSyncStatus> {
|
|
169
|
-
|
|
184
|
+
public async getWorldStateSyncStatus(): Promise<WorldStateSyncStatus> {
|
|
185
|
+
const { syncSummary } = await this.worldState.status();
|
|
186
|
+
return syncSummary;
|
|
170
187
|
}
|
|
171
188
|
|
|
172
189
|
/** Returns archiver status. */
|
|
@@ -183,23 +200,44 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
183
200
|
}
|
|
184
201
|
|
|
185
202
|
private async runJob(job: EpochProvingJob) {
|
|
186
|
-
const
|
|
203
|
+
const epochNumber = job.getEpochNumber();
|
|
204
|
+
const ctx = { id: job.getId(), epochNumber, state: undefined as EpochProvingJobState | undefined };
|
|
205
|
+
|
|
187
206
|
try {
|
|
188
207
|
await job.run();
|
|
189
208
|
const state = job.getState();
|
|
209
|
+
ctx.state = state;
|
|
210
|
+
|
|
190
211
|
if (state === 'reorg') {
|
|
191
|
-
this.log.warn(`Running new job for epoch ${
|
|
192
|
-
await this.createProvingJob(
|
|
212
|
+
this.log.warn(`Running new job for epoch ${epochNumber} due to reorg`, ctx);
|
|
213
|
+
await this.createProvingJob(epochNumber);
|
|
214
|
+
} else if (state === 'failed') {
|
|
215
|
+
this.log.error(`Job for ${epochNumber} exited with state ${state}`, ctx);
|
|
216
|
+
await this.tryUploadEpochFailure(job);
|
|
193
217
|
} else {
|
|
194
|
-
this.log.verbose(`Job for ${
|
|
218
|
+
this.log.verbose(`Job for ${epochNumber} exited with state ${state}`, ctx);
|
|
195
219
|
}
|
|
196
220
|
} catch (err) {
|
|
197
|
-
this.log.error(`Error proving epoch ${
|
|
221
|
+
this.log.error(`Error proving epoch ${epochNumber}`, err, ctx);
|
|
198
222
|
} finally {
|
|
199
223
|
this.jobs.delete(job.getId());
|
|
200
224
|
}
|
|
201
225
|
}
|
|
202
226
|
|
|
227
|
+
protected async tryUploadEpochFailure(job: EpochProvingJob) {
|
|
228
|
+
if (this.config.proverNodeFailedEpochStore) {
|
|
229
|
+
return await uploadEpochProofFailure(
|
|
230
|
+
this.config.proverNodeFailedEpochStore,
|
|
231
|
+
job.getId(),
|
|
232
|
+
job.getProvingData(),
|
|
233
|
+
this.l2BlockSource as Archiver,
|
|
234
|
+
this.worldState,
|
|
235
|
+
assertRequired(pick(this.config, 'l1ChainId', 'rollupVersion', 'dataDirectory')),
|
|
236
|
+
this.log,
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
203
241
|
/**
|
|
204
242
|
* Returns the prover instance.
|
|
205
243
|
*/
|
|
@@ -229,36 +267,38 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
229
267
|
}
|
|
230
268
|
|
|
231
269
|
private checkMaximumPendingJobs() {
|
|
232
|
-
const { maxPendingJobs } = this.
|
|
233
|
-
|
|
270
|
+
const { proverNodeMaxPendingJobs: maxPendingJobs } = this.config;
|
|
271
|
+
if (maxPendingJobs > 0 && this.jobs.size >= maxPendingJobs) {
|
|
272
|
+
throw new Error(`Maximum pending proving jobs ${maxPendingJobs} reached. Cannot create new job.`);
|
|
273
|
+
}
|
|
234
274
|
}
|
|
235
275
|
|
|
236
276
|
@trackSpan('ProverNode.createProvingJob', epochNumber => ({ [Attributes.EPOCH_NUMBER]: Number(epochNumber) }))
|
|
237
277
|
private async createProvingJob(epochNumber: bigint) {
|
|
238
|
-
|
|
239
|
-
throw new Error(`Maximum pending proving jobs ${this.options.maxPendingJobs} reached. Cannot create new job.`);
|
|
240
|
-
}
|
|
278
|
+
this.checkMaximumPendingJobs();
|
|
241
279
|
|
|
242
|
-
// Gather
|
|
243
|
-
const
|
|
280
|
+
// Gather all data for this epoch
|
|
281
|
+
const epochData = await this.gatherEpochData(epochNumber);
|
|
244
282
|
|
|
245
|
-
const fromBlock = blocks[0].number;
|
|
246
|
-
const toBlock = blocks.at(-1)!.number;
|
|
283
|
+
const fromBlock = epochData.blocks[0].number;
|
|
284
|
+
const toBlock = epochData.blocks.at(-1)!.number;
|
|
285
|
+
this.log.verbose(`Creating proving job for epoch ${epochNumber} for block range ${fromBlock} to ${toBlock}`);
|
|
247
286
|
|
|
248
287
|
// Fast forward world state to right before the target block and get a fork
|
|
249
|
-
this.log.verbose(`Creating proving job for epoch ${epochNumber} for block range ${fromBlock} to ${toBlock}`);
|
|
250
288
|
await this.worldState.syncImmediate(toBlock);
|
|
251
289
|
|
|
252
|
-
// Create a processor
|
|
290
|
+
// Create a processor factory
|
|
253
291
|
const publicProcessorFactory = new PublicProcessorFactory(
|
|
254
292
|
this.contractDataSource,
|
|
255
293
|
this.dateProvider,
|
|
256
294
|
this.telemetryClient,
|
|
257
295
|
);
|
|
258
296
|
|
|
297
|
+
// Set deadline for this job to run. It will abort if it takes too long.
|
|
259
298
|
const deadlineTs = getProofSubmissionDeadlineTimestamp(epochNumber, await this.getL1Constants());
|
|
260
299
|
const deadline = new Date(Number(deadlineTs) * 1000);
|
|
261
|
-
|
|
300
|
+
|
|
301
|
+
const job = this.doCreateEpochProvingJob(epochData, deadline, publicProcessorFactory);
|
|
262
302
|
this.jobs.set(job.getId(), job);
|
|
263
303
|
return job;
|
|
264
304
|
}
|
|
@@ -279,18 +319,19 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
279
319
|
}
|
|
280
320
|
const txHashes = block.body.txEffects.map(tx => tx.txHash);
|
|
281
321
|
this.log.verbose(`Fetching ${txHashes.length} tx hashes for block number ${blockNumber} from coordination`);
|
|
282
|
-
await this.coordination.
|
|
322
|
+
await this.coordination.gatherTxs(txHashes); // This stores the txs in the tx pool, no need to persist them here
|
|
283
323
|
this.lastBlockNumber = blockNumber;
|
|
284
324
|
}
|
|
285
325
|
}
|
|
286
326
|
|
|
287
327
|
@trackSpan('ProverNode.gatherEpochData', epochNumber => ({ [Attributes.EPOCH_NUMBER]: Number(epochNumber) }))
|
|
288
|
-
private async gatherEpochData(epochNumber: bigint) {
|
|
289
|
-
// Gather blocks for this epoch and their txs
|
|
328
|
+
private async gatherEpochData(epochNumber: bigint): Promise<EpochProvingJobData> {
|
|
290
329
|
const blocks = await this.gatherBlocks(epochNumber);
|
|
291
330
|
const txs = await this.gatherTxs(epochNumber, blocks);
|
|
331
|
+
const l1ToL2Messages = await this.gatherMessages(epochNumber, blocks);
|
|
332
|
+
const previousBlockHeader = await this.gatherPreviousBlockHeader(epochNumber, blocks[0]);
|
|
292
333
|
|
|
293
|
-
return { blocks, txs };
|
|
334
|
+
return { blocks, txs, l1ToL2Messages, epochNumber, previousBlockHeader };
|
|
294
335
|
}
|
|
295
336
|
|
|
296
337
|
private async gatherBlocks(epochNumber: bigint) {
|
|
@@ -318,27 +359,48 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
318
359
|
throw new Error(`Txs not found for epoch ${epochNumber}: ${missingTxHashes}`);
|
|
319
360
|
}
|
|
320
361
|
|
|
362
|
+
private async gatherMessages(epochNumber: bigint, blocks: L2Block[]) {
|
|
363
|
+
const messages = await Promise.all(blocks.map(b => this.l1ToL2MessageSource.getL1ToL2Messages(BigInt(b.number))));
|
|
364
|
+
const messageCount = sum(messages.map(m => m.length));
|
|
365
|
+
this.log.verbose(`Gathered all ${messageCount} messages for epoch ${epochNumber}`, { epochNumber });
|
|
366
|
+
const messagesByBlock: Record<number, Fr[]> = {};
|
|
367
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
368
|
+
messagesByBlock[blocks[i].number] = messages[i];
|
|
369
|
+
}
|
|
370
|
+
return messagesByBlock;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
private async gatherPreviousBlockHeader(epochNumber: bigint, initialBlock: L2Block) {
|
|
374
|
+
const previousBlockNumber = initialBlock.number - 1;
|
|
375
|
+
const header = await (previousBlockNumber === 0
|
|
376
|
+
? this.worldState.getCommitted().getInitialHeader()
|
|
377
|
+
: this.l2BlockSource.getBlockHeader(previousBlockNumber));
|
|
378
|
+
|
|
379
|
+
if (!header) {
|
|
380
|
+
throw new Error(`Previous block header ${initialBlock.number} not found for proving epoch ${epochNumber}`);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
this.log.verbose(`Gathered previous block header ${header.getBlockNumber()} for epoch ${epochNumber}`);
|
|
384
|
+
return header;
|
|
385
|
+
}
|
|
386
|
+
|
|
321
387
|
/** Extracted for testing purposes. */
|
|
322
388
|
protected doCreateEpochProvingJob(
|
|
323
|
-
|
|
389
|
+
data: EpochProvingJobData,
|
|
324
390
|
deadline: Date | undefined,
|
|
325
|
-
blocks: L2Block[],
|
|
326
|
-
txs: Tx[],
|
|
327
391
|
publicProcessorFactory: PublicProcessorFactory,
|
|
328
392
|
) {
|
|
393
|
+
const { proverNodeMaxParallelBlocksPerEpoch: parallelBlockLimit } = this.config;
|
|
329
394
|
return new EpochProvingJob(
|
|
395
|
+
data,
|
|
330
396
|
this.worldState,
|
|
331
|
-
epochNumber,
|
|
332
|
-
blocks,
|
|
333
|
-
txs,
|
|
334
397
|
this.prover.createEpochProver(),
|
|
335
398
|
publicProcessorFactory,
|
|
336
399
|
this.publisher,
|
|
337
400
|
this.l2BlockSource,
|
|
338
|
-
this.
|
|
339
|
-
this.metrics,
|
|
401
|
+
this.jobMetrics,
|
|
340
402
|
deadline,
|
|
341
|
-
{ parallelBlockLimit
|
|
403
|
+
{ parallelBlockLimit },
|
|
342
404
|
);
|
|
343
405
|
}
|
|
344
406
|
|
|
@@ -346,6 +408,21 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
346
408
|
protected async triggerMonitors() {
|
|
347
409
|
await this.epochsMonitor.work();
|
|
348
410
|
}
|
|
411
|
+
|
|
412
|
+
private validateConfig() {
|
|
413
|
+
if (
|
|
414
|
+
this.config.proverNodeFailedEpochStore &&
|
|
415
|
+
(!this.config.dataDirectory || !this.config.l1ChainId || !this.config.rollupVersion)
|
|
416
|
+
) {
|
|
417
|
+
this.log.warn(
|
|
418
|
+
`Invalid prover-node config (missing dataDirectory, l1ChainId, or rollupVersion)`,
|
|
419
|
+
pick(this.config, 'proverNodeFailedEpochStore', 'dataDirectory', 'l1ChainId', 'rollupVersion'),
|
|
420
|
+
);
|
|
421
|
+
throw new Error(
|
|
422
|
+
'All of dataDirectory, l1ChainId, and rollupVersion are required if proverNodeFailedEpochStore is set.',
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
349
426
|
}
|
|
350
427
|
|
|
351
428
|
class EmptyEpochError extends Error {
|
package/src/test/index.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { EpochProverManager } from '@aztec/stdlib/interfaces/server';
|
|
2
2
|
|
|
3
|
+
import type { EpochProvingJob } from '../job/epoch-proving-job.js';
|
|
3
4
|
import type { ProverNodePublisher } from '../prover-node-publisher.js';
|
|
4
5
|
import { ProverNode } from '../prover-node.js';
|
|
5
6
|
|
|
6
|
-
class
|
|
7
|
+
abstract class TestProverNodeClass extends ProverNode {
|
|
7
8
|
public declare prover: EpochProverManager;
|
|
8
9
|
public declare publisher: ProverNodePublisher;
|
|
10
|
+
|
|
11
|
+
public abstract override tryUploadEpochFailure(job: EpochProvingJob): Promise<string | undefined>;
|
|
9
12
|
}
|
|
10
13
|
|
|
11
|
-
export type TestProverNode =
|
|
14
|
+
export type TestProverNode = TestProverNodeClass;
|