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