@aztec/prover-node 0.0.1-commit.24de95ac → 0.0.1-commit.2606882
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 +4 -4
- package/dest/actions/download-epoch-proving-job.js +1 -1
- package/dest/actions/index.d.ts +1 -1
- package/dest/actions/rerun-epoch-proving-job.d.ts +5 -3
- package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -1
- package/dest/actions/rerun-epoch-proving-job.js +9 -7
- package/dest/actions/upload-epoch-proof-failure.d.ts +2 -2
- package/dest/actions/upload-epoch-proof-failure.d.ts.map +1 -1
- package/dest/bin/run-failed-epoch.d.ts +1 -1
- package/dest/bin/run-failed-epoch.js +6 -5
- package/dest/config.d.ts +8 -10
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +19 -21
- package/dest/factory.d.ts +20 -16
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +48 -63
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/job/epoch-proving-job-data.d.ts +8 -6
- package/dest/job/epoch-proving-job-data.d.ts.map +1 -1
- package/dest/job/epoch-proving-job-data.js +25 -18
- package/dest/job/epoch-proving-job.d.ts +11 -13
- package/dest/job/epoch-proving-job.d.ts.map +1 -1
- package/dest/job/epoch-proving-job.js +669 -111
- package/dest/metrics.d.ts +24 -3
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +77 -98
- package/dest/monitors/epoch-monitor.d.ts +3 -2
- package/dest/monitors/epoch-monitor.d.ts.map +1 -1
- package/dest/monitors/epoch-monitor.js +14 -20
- package/dest/monitors/index.d.ts +1 -1
- package/dest/prover-node-publisher.d.ts +33 -11
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +248 -46
- package/dest/prover-node.d.ts +30 -19
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +512 -81
- package/dest/prover-publisher-factory.d.ts +10 -6
- package/dest/prover-publisher-factory.d.ts.map +1 -1
- package/dest/prover-publisher-factory.js +7 -5
- package/dest/test/index.d.ts +1 -1
- package/dest/test/index.d.ts.map +1 -1
- package/package.json +27 -25
- package/src/actions/download-epoch-proving-job.ts +1 -1
- package/src/actions/rerun-epoch-proving-job.ts +20 -7
- package/src/actions/upload-epoch-proof-failure.ts +1 -1
- package/src/bin/run-failed-epoch.ts +5 -3
- package/src/config.ts +27 -33
- package/src/factory.ts +81 -103
- package/src/index.ts +1 -0
- package/src/job/epoch-proving-job-data.ts +31 -25
- package/src/job/epoch-proving-job.ts +228 -117
- package/src/metrics.ts +102 -82
- package/src/monitors/epoch-monitor.ts +10 -17
- package/src/prover-node-publisher.ts +302 -66
- package/src/prover-node.ts +135 -86
- package/src/prover-publisher-factory.ts +19 -11
package/src/prover-node.ts
CHANGED
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
import type { Archiver } from '@aztec/archiver';
|
|
2
|
-
import type { RollupContract } from '@aztec/ethereum';
|
|
2
|
+
import type { RollupContract } from '@aztec/ethereum/contracts';
|
|
3
|
+
import type { Delayer } from '@aztec/ethereum/l1-tx-utils';
|
|
4
|
+
import { BlockNumber, CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
3
5
|
import { assertRequired, compact, pick, sum } from '@aztec/foundation/collection';
|
|
6
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
7
|
import { memoize } from '@aztec/foundation/decorators';
|
|
5
|
-
import type { Fr } from '@aztec/foundation/fields';
|
|
6
8
|
import { createLogger } from '@aztec/foundation/log';
|
|
7
9
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
8
|
-
import type { DataStoreConfig } from '@aztec/kv-store/config';
|
|
9
|
-
import type { P2PClient } from '@aztec/p2p';
|
|
10
10
|
import { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
11
|
-
import type {
|
|
11
|
+
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
12
|
+
import type { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
12
13
|
import type { ChainConfig } from '@aztec/stdlib/config';
|
|
13
14
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
14
15
|
import { getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
15
16
|
import {
|
|
16
17
|
type EpochProverManager,
|
|
17
|
-
|
|
18
|
+
type ITxProvider,
|
|
18
19
|
type ProverNodeApi,
|
|
19
20
|
type Service,
|
|
20
21
|
type WorldStateSyncStatus,
|
|
21
22
|
type WorldStateSynchronizer,
|
|
22
23
|
tryStop,
|
|
23
24
|
} from '@aztec/stdlib/interfaces/server';
|
|
25
|
+
import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
|
|
24
26
|
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
25
|
-
import type { P2PClientType } from '@aztec/stdlib/p2p';
|
|
26
27
|
import type { Tx } from '@aztec/stdlib/tx';
|
|
27
28
|
import {
|
|
28
29
|
Attributes,
|
|
@@ -37,7 +38,7 @@ import {
|
|
|
37
38
|
import { uploadEpochProofFailure } from './actions/upload-epoch-proof-failure.js';
|
|
38
39
|
import type { SpecificProverNodeConfig } from './config.js';
|
|
39
40
|
import type { EpochProvingJobData } from './job/epoch-proving-job-data.js';
|
|
40
|
-
import { EpochProvingJob, type EpochProvingJobState } from './job/epoch-proving-job.js';
|
|
41
|
+
import { EpochProvingJob, type EpochProvingJobOptions, type EpochProvingJobState } from './job/epoch-proving-job.js';
|
|
41
42
|
import { ProverNodeJobMetrics, ProverNodeRewardsMetrics } from './metrics.js';
|
|
42
43
|
import type { EpochMonitor, EpochMonitorHandler } from './monitors/epoch-monitor.js';
|
|
43
44
|
import type { ProverNodePublisher } from './prover-node-publisher.js';
|
|
@@ -53,12 +54,12 @@ type DataStoreOptions = Pick<DataStoreConfig, 'dataDirectory'> & Pick<ChainConfi
|
|
|
53
54
|
*/
|
|
54
55
|
export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable {
|
|
55
56
|
private log = createLogger('prover-node');
|
|
56
|
-
private dateProvider = new DateProvider();
|
|
57
57
|
|
|
58
58
|
private jobs: Map<string, EpochProvingJob> = new Map();
|
|
59
59
|
private config: ProverNodeOptions;
|
|
60
60
|
private jobMetrics: ProverNodeJobMetrics;
|
|
61
61
|
private rewardsMetrics: ProverNodeRewardsMetrics;
|
|
62
|
+
private startingProofEpochs: Set<EpochNumber> = new Set();
|
|
62
63
|
|
|
63
64
|
public readonly tracer: Tracer;
|
|
64
65
|
|
|
@@ -71,17 +72,19 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
71
72
|
protected readonly l1ToL2MessageSource: L1ToL2MessageSource,
|
|
72
73
|
protected readonly contractDataSource: ContractDataSource,
|
|
73
74
|
protected readonly worldState: WorldStateSynchronizer,
|
|
74
|
-
protected readonly p2pClient:
|
|
75
|
+
protected readonly p2pClient: { getTxProvider(): ITxProvider } & Partial<Service>,
|
|
75
76
|
protected readonly epochsMonitor: EpochMonitor,
|
|
76
77
|
protected readonly rollupContract: RollupContract,
|
|
77
78
|
protected readonly l1Metrics: L1Metrics,
|
|
78
79
|
config: Partial<ProverNodeOptions> = {},
|
|
79
80
|
protected readonly telemetryClient: TelemetryClient = getTelemetryClient(),
|
|
81
|
+
private delayer?: Delayer,
|
|
82
|
+
private readonly dateProvider: DateProvider = new DateProvider(),
|
|
80
83
|
) {
|
|
81
84
|
this.config = {
|
|
82
85
|
proverNodePollingIntervalMs: 1_000,
|
|
83
86
|
proverNodeMaxPendingJobs: 100,
|
|
84
|
-
proverNodeMaxParallelBlocksPerEpoch:
|
|
87
|
+
proverNodeMaxParallelBlocksPerEpoch: 0,
|
|
85
88
|
txGatheringIntervalMs: 1_000,
|
|
86
89
|
txGatheringBatchSize: 10,
|
|
87
90
|
txGatheringMaxParallelRequestsPerNode: 100,
|
|
@@ -109,25 +112,22 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
109
112
|
return this.p2pClient;
|
|
110
113
|
}
|
|
111
114
|
|
|
115
|
+
/** Returns the shared tx delayer for prover L1 txs, if enabled. Test-only. */
|
|
116
|
+
public getDelayer(): Delayer | undefined {
|
|
117
|
+
return this.delayer;
|
|
118
|
+
}
|
|
119
|
+
|
|
112
120
|
/**
|
|
113
121
|
* Handles an epoch being completed by starting a proof for it if there are no active jobs for it.
|
|
114
122
|
* @param epochNumber - The epoch number that was just completed.
|
|
115
123
|
* @returns false if there is an error, true otherwise
|
|
116
124
|
*/
|
|
117
|
-
async handleEpochReadyToProve(epochNumber:
|
|
125
|
+
async handleEpochReadyToProve(epochNumber: EpochNumber): Promise<boolean> {
|
|
118
126
|
try {
|
|
119
127
|
this.log.debug(`Running jobs as ${epochNumber} is ready to prove`, {
|
|
120
128
|
jobs: Array.from(this.jobs.values()).map(job => `${job.getEpochNumber()}:${job.getId()}`),
|
|
121
129
|
});
|
|
122
|
-
|
|
123
|
-
if (activeJobs.length > 0) {
|
|
124
|
-
this.log.warn(`Not starting proof for ${epochNumber} since there are active jobs for the epoch`, {
|
|
125
|
-
activeJobs: activeJobs.map(job => job.uuid),
|
|
126
|
-
});
|
|
127
|
-
return true;
|
|
128
|
-
}
|
|
129
|
-
await this.startProof(epochNumber);
|
|
130
|
-
return true;
|
|
130
|
+
return await this.startProofIfNeeded(epochNumber);
|
|
131
131
|
} catch (err) {
|
|
132
132
|
if (err instanceof EmptyEpochError) {
|
|
133
133
|
this.log.info(`Not starting proof for ${epochNumber} since no blocks were found`);
|
|
@@ -153,17 +153,15 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
153
153
|
|
|
154
154
|
/**
|
|
155
155
|
* Stops the prover node and all its dependencies.
|
|
156
|
+
* Resources not owned by this node (shared with the parent aztec-node) are skipped.
|
|
156
157
|
*/
|
|
157
158
|
async stop() {
|
|
158
159
|
this.log.info('Stopping ProverNode');
|
|
159
160
|
await this.epochsMonitor.stop();
|
|
160
|
-
await this.prover.stop();
|
|
161
|
-
await tryStop(this.p2pClient);
|
|
162
|
-
await tryStop(this.l2BlockSource);
|
|
163
|
-
await tryStop(this.publisherFactory);
|
|
164
161
|
this.publisher?.interrupt();
|
|
165
162
|
await Promise.all(Array.from(this.jobs.values()).map(job => job.stop()));
|
|
166
|
-
await this.
|
|
163
|
+
await this.prover.stop();
|
|
164
|
+
await tryStop(this.publisherFactory);
|
|
167
165
|
this.rewardsMetrics.stop();
|
|
168
166
|
this.l1Metrics.stop();
|
|
169
167
|
await this.telemetryClient.stop();
|
|
@@ -184,8 +182,39 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
184
182
|
/**
|
|
185
183
|
* Starts a proving process and returns immediately.
|
|
186
184
|
*/
|
|
187
|
-
public async startProof(epochNumber:
|
|
188
|
-
|
|
185
|
+
public async startProof(epochNumber: EpochNumber) {
|
|
186
|
+
await this.startProofIfNeeded(epochNumber, { skipEpochCheck: true });
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private async startProofIfNeeded(epochNumber: EpochNumber, opts: EpochProvingJobOptions = {}): Promise<boolean> {
|
|
190
|
+
if (this.startingProofEpochs.has(epochNumber)) {
|
|
191
|
+
this.log.warn(`Not starting proof for ${epochNumber} since a proof is already being started for the epoch`, {
|
|
192
|
+
epochNumber,
|
|
193
|
+
});
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
this.startingProofEpochs.add(epochNumber);
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
const activeJobs = await this.activeJobsCoverEpoch(epochNumber);
|
|
201
|
+
if (activeJobs.length > 0) {
|
|
202
|
+
this.log.warn(`Not starting proof for ${epochNumber} since an active job already covers the epoch`, {
|
|
203
|
+
epochNumber,
|
|
204
|
+
activeJobs,
|
|
205
|
+
});
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
await this.startProofInternal(epochNumber, opts);
|
|
210
|
+
return true;
|
|
211
|
+
} finally {
|
|
212
|
+
this.startingProofEpochs.delete(epochNumber);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private async startProofInternal(epochNumber: EpochNumber, opts: EpochProvingJobOptions = {}) {
|
|
217
|
+
const job = await this.createProvingJob(epochNumber, opts);
|
|
189
218
|
void this.runJob(job);
|
|
190
219
|
}
|
|
191
220
|
|
|
@@ -238,22 +267,43 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
238
267
|
/**
|
|
239
268
|
* Returns an array of jobs being processed.
|
|
240
269
|
*/
|
|
241
|
-
public getJobs(): Promise<{ uuid: string; status: EpochProvingJobState; epochNumber:
|
|
242
|
-
return Promise.resolve(
|
|
243
|
-
Array.from(this.jobs.entries()).map(([uuid, job]) => ({
|
|
244
|
-
uuid,
|
|
245
|
-
status: job.getState(),
|
|
246
|
-
epochNumber: Number(job.getEpochNumber()),
|
|
247
|
-
})),
|
|
248
|
-
);
|
|
270
|
+
public getJobs(): Promise<{ uuid: string; status: EpochProvingJobState; epochNumber: EpochNumber }[]> {
|
|
271
|
+
return Promise.resolve(this.getJobsInternal());
|
|
249
272
|
}
|
|
250
273
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
274
|
+
private getJobsInternal(): { uuid: string; status: EpochProvingJobState; epochNumber: EpochNumber }[] {
|
|
275
|
+
return Array.from(this.jobs.entries()).map(([uuid, job]) => ({
|
|
276
|
+
uuid,
|
|
277
|
+
status: job.getState(),
|
|
278
|
+
epochNumber: job.getEpochNumber(),
|
|
279
|
+
}));
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private async activeJobsCoverEpoch(epochNumber: EpochNumber): Promise<string[]> {
|
|
283
|
+
const checkpoints = await this.l2BlockSource.getCheckpointsData({ epoch: epochNumber });
|
|
284
|
+
if (checkpoints.length === 0) {
|
|
285
|
+
return [];
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const firstCheckpoint = checkpoints.at(0)!.checkpointNumber;
|
|
289
|
+
const latestCheckpoint = checkpoints.at(-1)!.checkpointNumber;
|
|
290
|
+
|
|
291
|
+
const jobs: string[] = [];
|
|
292
|
+
for (const job of this.jobs.values()) {
|
|
293
|
+
if (job.getEpochNumber() !== epochNumber) {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const jobCheckpoints = job.getProvingData().checkpoints;
|
|
298
|
+
const checkpointOverlap =
|
|
299
|
+
jobCheckpoints.at(0)!.number <= firstCheckpoint && jobCheckpoints.at(-1)!.number >= latestCheckpoint;
|
|
300
|
+
|
|
301
|
+
if (checkpointOverlap && !['failed', 'stopped', 'timed-out'].includes(job.getState())) {
|
|
302
|
+
jobs.push(job.getId());
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return jobs;
|
|
257
307
|
}
|
|
258
308
|
|
|
259
309
|
private checkMaximumPendingJobs() {
|
|
@@ -263,33 +313,38 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
263
313
|
}
|
|
264
314
|
}
|
|
265
315
|
|
|
266
|
-
@trackSpan('ProverNode.createProvingJob', epochNumber => ({ [Attributes.EPOCH_NUMBER]:
|
|
267
|
-
private async createProvingJob(epochNumber:
|
|
316
|
+
@trackSpan('ProverNode.createProvingJob', epochNumber => ({ [Attributes.EPOCH_NUMBER]: epochNumber }))
|
|
317
|
+
private async createProvingJob(epochNumber: EpochNumber, opts: { skipEpochCheck?: boolean } = {}) {
|
|
268
318
|
this.checkMaximumPendingJobs();
|
|
269
319
|
|
|
270
320
|
this.publisher = await this.publisherFactory.create();
|
|
271
321
|
|
|
272
322
|
// Gather all data for this epoch
|
|
273
323
|
const epochData = await this.gatherEpochData(epochNumber);
|
|
274
|
-
|
|
275
|
-
const
|
|
276
|
-
const
|
|
277
|
-
|
|
324
|
+
const fromCheckpoint = epochData.checkpoints[0].number;
|
|
325
|
+
const toCheckpoint = epochData.checkpoints.at(-1)!.number;
|
|
326
|
+
const fromBlock = epochData.checkpoints[0].blocks[0].number;
|
|
327
|
+
const lastBlock = epochData.checkpoints.at(-1)!.blocks.at(-1)!;
|
|
328
|
+
const toBlock = lastBlock.number;
|
|
329
|
+
this.log.verbose(
|
|
330
|
+
`Creating proving job for epoch ${epochNumber} for checkpoint range ${fromCheckpoint} to ${toCheckpoint} and block range ${fromBlock} to ${toBlock}`,
|
|
331
|
+
);
|
|
278
332
|
|
|
279
333
|
// Fast forward world state to right before the target block and get a fork
|
|
280
|
-
await
|
|
334
|
+
const lastBlockHash = await lastBlock.header.hash();
|
|
335
|
+
await this.worldState.syncImmediate(toBlock, lastBlockHash);
|
|
281
336
|
|
|
282
337
|
// Create a processor factory
|
|
283
338
|
const publicProcessorFactory = new PublicProcessorFactory(
|
|
284
339
|
this.contractDataSource,
|
|
285
340
|
this.dateProvider,
|
|
286
341
|
this.telemetryClient,
|
|
342
|
+
this.log.getBindings(),
|
|
287
343
|
);
|
|
288
344
|
|
|
289
345
|
// Set deadline for this job to run. It will abort if it takes too long.
|
|
290
346
|
const deadlineTs = getProofSubmissionDeadlineTimestamp(epochNumber, await this.getL1Constants());
|
|
291
347
|
const deadline = new Date(Number(deadlineTs) * 1000);
|
|
292
|
-
|
|
293
348
|
const job = this.doCreateEpochProvingJob(epochData, deadline, publicProcessorFactory, this.publisher, opts);
|
|
294
349
|
this.jobs.set(job.getId(), job);
|
|
295
350
|
return job;
|
|
@@ -300,30 +355,27 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
300
355
|
return this.l2BlockSource.getL1Constants();
|
|
301
356
|
}
|
|
302
357
|
|
|
303
|
-
@trackSpan('ProverNode.gatherEpochData', epochNumber => ({ [Attributes.EPOCH_NUMBER]:
|
|
304
|
-
private async gatherEpochData(epochNumber:
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
const txs = new Map<string, Tx>(txArray.map(tx => [tx.getTxHash().toString(), tx]));
|
|
308
|
-
const l1ToL2Messages = await this.gatherMessages(epochNumber, blocks);
|
|
309
|
-
const previousBlockHeader = await this.gatherPreviousBlockHeader(epochNumber, blocks[0]);
|
|
310
|
-
const [lastBlock] = await this.l2BlockSource.getPublishedBlocks(blocks.at(-1)!.number, 1);
|
|
311
|
-
const attestations = lastBlock?.attestations ?? [];
|
|
312
|
-
|
|
313
|
-
return { blocks, txs, l1ToL2Messages, epochNumber, previousBlockHeader, attestations };
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
private async gatherBlocks(epochNumber: bigint) {
|
|
317
|
-
const blocks = await this.l2BlockSource.getBlocksForEpoch(epochNumber);
|
|
318
|
-
if (blocks.length === 0) {
|
|
358
|
+
@trackSpan('ProverNode.gatherEpochData', epochNumber => ({ [Attributes.EPOCH_NUMBER]: epochNumber }))
|
|
359
|
+
private async gatherEpochData(epochNumber: EpochNumber): Promise<EpochProvingJobData> {
|
|
360
|
+
const publishedCheckpoints = await this.l2BlockSource.getCheckpoints({ epoch: epochNumber });
|
|
361
|
+
if (publishedCheckpoints.length === 0) {
|
|
319
362
|
throw new EmptyEpochError(epochNumber);
|
|
320
363
|
}
|
|
321
|
-
|
|
364
|
+
const checkpoints = publishedCheckpoints.map(p => p.checkpoint);
|
|
365
|
+
const attestations = publishedCheckpoints.at(-1)?.attestations ?? [];
|
|
366
|
+
const txArray = await this.gatherTxs(epochNumber, checkpoints);
|
|
367
|
+
const txs = new Map<string, Tx>(txArray.map(tx => [tx.getTxHash().toString(), tx]));
|
|
368
|
+
const l1ToL2Messages = await this.gatherMessages(epochNumber, checkpoints);
|
|
369
|
+
const [firstBlock] = checkpoints[0].blocks;
|
|
370
|
+
const previousBlockHeader = await this.gatherPreviousBlockHeader(epochNumber, firstBlock.number - 1);
|
|
371
|
+
|
|
372
|
+
return { checkpoints, txs, l1ToL2Messages, epochNumber, previousBlockHeader, attestations };
|
|
322
373
|
}
|
|
323
374
|
|
|
324
|
-
private async gatherTxs(epochNumber:
|
|
375
|
+
private async gatherTxs(epochNumber: EpochNumber, checkpoints: Checkpoint[]) {
|
|
325
376
|
const deadline = new Date(this.dateProvider.now() + this.config.txGatheringTimeoutMs);
|
|
326
377
|
const txProvider = this.p2pClient.getTxProvider();
|
|
378
|
+
const blocks = checkpoints.flatMap(checkpoint => checkpoint.blocks);
|
|
327
379
|
const txsByBlock = await Promise.all(blocks.map(block => txProvider.getTxsForBlock(block, { deadline })));
|
|
328
380
|
const txs = txsByBlock.map(({ txs }) => txs).flat();
|
|
329
381
|
const missingTxs = txsByBlock.map(({ missingTxs }) => missingTxs).flat();
|
|
@@ -336,29 +388,25 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
336
388
|
throw new Error(`Txs not found for epoch ${epochNumber}: ${missingTxs.map(hash => hash.toString()).join(', ')}`);
|
|
337
389
|
}
|
|
338
390
|
|
|
339
|
-
private async gatherMessages(epochNumber:
|
|
340
|
-
const messages = await Promise.all(
|
|
391
|
+
private async gatherMessages(epochNumber: EpochNumber, checkpoints: Checkpoint[]) {
|
|
392
|
+
const messages = await Promise.all(checkpoints.map(c => this.l1ToL2MessageSource.getL1ToL2Messages(c.number)));
|
|
341
393
|
const messageCount = sum(messages.map(m => m.length));
|
|
342
394
|
this.log.verbose(`Gathered all ${messageCount} messages for epoch ${epochNumber}`, { epochNumber });
|
|
343
|
-
const
|
|
344
|
-
for (let i = 0; i <
|
|
345
|
-
|
|
395
|
+
const messagesByCheckpoint: Record<CheckpointNumber, Fr[]> = {};
|
|
396
|
+
for (let i = 0; i < checkpoints.length; i++) {
|
|
397
|
+
messagesByCheckpoint[checkpoints[i].number] = messages[i];
|
|
346
398
|
}
|
|
347
|
-
return
|
|
399
|
+
return messagesByCheckpoint;
|
|
348
400
|
}
|
|
349
401
|
|
|
350
|
-
private async gatherPreviousBlockHeader(epochNumber:
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
: this.l2BlockSource.getBlockHeader(previousBlockNumber));
|
|
355
|
-
|
|
356
|
-
if (!header) {
|
|
357
|
-
throw new Error(`Previous block header ${initialBlock.number} not found for proving epoch ${epochNumber}`);
|
|
402
|
+
private async gatherPreviousBlockHeader(epochNumber: EpochNumber, previousBlockNumber: number) {
|
|
403
|
+
const data = await this.l2BlockSource.getBlockData({ number: BlockNumber(previousBlockNumber) });
|
|
404
|
+
if (!data?.header) {
|
|
405
|
+
throw new Error(`Previous block header ${previousBlockNumber} not found for proving epoch ${epochNumber}`);
|
|
358
406
|
}
|
|
359
407
|
|
|
360
|
-
this.log.verbose(`Gathered previous block header ${header.getBlockNumber()} for epoch ${epochNumber}`);
|
|
361
|
-
return header;
|
|
408
|
+
this.log.verbose(`Gathered previous block header ${data.header.getBlockNumber()} for epoch ${epochNumber}`);
|
|
409
|
+
return data.header;
|
|
362
410
|
}
|
|
363
411
|
|
|
364
412
|
/** Extracted for testing purposes. */
|
|
@@ -380,6 +428,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
380
428
|
this.jobMetrics,
|
|
381
429
|
deadline,
|
|
382
430
|
{ parallelBlockLimit, skipSubmitProof: proverNodeDisableProofPublish, ...opts },
|
|
431
|
+
this.log.getBindings(),
|
|
383
432
|
);
|
|
384
433
|
}
|
|
385
434
|
|
|
@@ -391,7 +440,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
391
440
|
private validateConfig() {
|
|
392
441
|
if (
|
|
393
442
|
this.config.proverNodeFailedEpochStore &&
|
|
394
|
-
(!this.config.dataDirectory || !this.config.l1ChainId ||
|
|
443
|
+
(!this.config.dataDirectory || !this.config.l1ChainId || this.config.rollupVersion === undefined)
|
|
395
444
|
) {
|
|
396
445
|
this.log.warn(
|
|
397
446
|
`Invalid prover-node config (missing dataDirectory, l1ChainId, or rollupVersion)`,
|
|
@@ -405,7 +454,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
405
454
|
}
|
|
406
455
|
|
|
407
456
|
class EmptyEpochError extends Error {
|
|
408
|
-
constructor(epochNumber:
|
|
457
|
+
constructor(epochNumber: EpochNumber) {
|
|
409
458
|
super(`No blocks found for epoch ${epochNumber}`);
|
|
410
459
|
this.name = 'EmptyEpochError';
|
|
411
460
|
}
|
|
@@ -1,25 +1,29 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { RollupContract } from '@aztec/ethereum/contracts';
|
|
2
|
+
import type { L1TxUtils } from '@aztec/ethereum/l1-tx-utils';
|
|
3
|
+
import type { PublisherManager } from '@aztec/ethereum/publisher-manager';
|
|
4
|
+
import type { LoggerBindings } from '@aztec/foundation/log';
|
|
5
|
+
import type { ProverPublisherConfig, ProverTxSenderConfig } from '@aztec/sequencer-client';
|
|
3
6
|
import type { TelemetryClient } from '@aztec/telemetry-client';
|
|
4
7
|
|
|
5
8
|
import { ProverNodePublisher } from './prover-node-publisher.js';
|
|
6
9
|
|
|
7
10
|
export class ProverPublisherFactory {
|
|
8
11
|
constructor(
|
|
9
|
-
private config:
|
|
12
|
+
private config: ProverTxSenderConfig & ProverPublisherConfig,
|
|
10
13
|
private deps: {
|
|
11
14
|
rollupContract: RollupContract;
|
|
12
15
|
publisherManager: PublisherManager<L1TxUtils>;
|
|
13
16
|
telemetry?: TelemetryClient;
|
|
14
17
|
},
|
|
18
|
+
private bindings?: LoggerBindings,
|
|
15
19
|
) {}
|
|
16
20
|
|
|
17
21
|
public async start() {
|
|
18
|
-
await this.deps.publisherManager.
|
|
22
|
+
await this.deps.publisherManager.start();
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
public stop() {
|
|
22
|
-
this.deps.publisherManager.
|
|
25
|
+
public async stop() {
|
|
26
|
+
await this.deps.publisherManager.stop();
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
/**
|
|
@@ -28,10 +32,14 @@ export class ProverPublisherFactory {
|
|
|
28
32
|
*/
|
|
29
33
|
public async create(): Promise<ProverNodePublisher> {
|
|
30
34
|
const l1Publisher = await this.deps.publisherManager.getAvailablePublisher();
|
|
31
|
-
return new ProverNodePublisher(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
return new ProverNodePublisher(
|
|
36
|
+
this.config,
|
|
37
|
+
{
|
|
38
|
+
rollupContract: this.deps.rollupContract,
|
|
39
|
+
l1TxUtils: l1Publisher,
|
|
40
|
+
telemetry: this.deps.telemetry,
|
|
41
|
+
},
|
|
42
|
+
this.bindings,
|
|
43
|
+
);
|
|
36
44
|
}
|
|
37
45
|
}
|