@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.
Files changed (58) hide show
  1. package/dest/actions/download-epoch-proving-job.d.ts +4 -4
  2. package/dest/actions/download-epoch-proving-job.js +1 -1
  3. package/dest/actions/index.d.ts +1 -1
  4. package/dest/actions/rerun-epoch-proving-job.d.ts +5 -3
  5. package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -1
  6. package/dest/actions/rerun-epoch-proving-job.js +9 -7
  7. package/dest/actions/upload-epoch-proof-failure.d.ts +2 -2
  8. package/dest/actions/upload-epoch-proof-failure.d.ts.map +1 -1
  9. package/dest/bin/run-failed-epoch.d.ts +1 -1
  10. package/dest/bin/run-failed-epoch.js +6 -5
  11. package/dest/config.d.ts +8 -10
  12. package/dest/config.d.ts.map +1 -1
  13. package/dest/config.js +19 -21
  14. package/dest/factory.d.ts +20 -16
  15. package/dest/factory.d.ts.map +1 -1
  16. package/dest/factory.js +48 -63
  17. package/dest/index.d.ts +2 -1
  18. package/dest/index.d.ts.map +1 -1
  19. package/dest/index.js +1 -0
  20. package/dest/job/epoch-proving-job-data.d.ts +8 -6
  21. package/dest/job/epoch-proving-job-data.d.ts.map +1 -1
  22. package/dest/job/epoch-proving-job-data.js +25 -18
  23. package/dest/job/epoch-proving-job.d.ts +11 -13
  24. package/dest/job/epoch-proving-job.d.ts.map +1 -1
  25. package/dest/job/epoch-proving-job.js +669 -111
  26. package/dest/metrics.d.ts +24 -3
  27. package/dest/metrics.d.ts.map +1 -1
  28. package/dest/metrics.js +77 -98
  29. package/dest/monitors/epoch-monitor.d.ts +3 -2
  30. package/dest/monitors/epoch-monitor.d.ts.map +1 -1
  31. package/dest/monitors/epoch-monitor.js +14 -20
  32. package/dest/monitors/index.d.ts +1 -1
  33. package/dest/prover-node-publisher.d.ts +33 -11
  34. package/dest/prover-node-publisher.d.ts.map +1 -1
  35. package/dest/prover-node-publisher.js +248 -46
  36. package/dest/prover-node.d.ts +30 -19
  37. package/dest/prover-node.d.ts.map +1 -1
  38. package/dest/prover-node.js +512 -81
  39. package/dest/prover-publisher-factory.d.ts +10 -6
  40. package/dest/prover-publisher-factory.d.ts.map +1 -1
  41. package/dest/prover-publisher-factory.js +7 -5
  42. package/dest/test/index.d.ts +1 -1
  43. package/dest/test/index.d.ts.map +1 -1
  44. package/package.json +27 -25
  45. package/src/actions/download-epoch-proving-job.ts +1 -1
  46. package/src/actions/rerun-epoch-proving-job.ts +20 -7
  47. package/src/actions/upload-epoch-proof-failure.ts +1 -1
  48. package/src/bin/run-failed-epoch.ts +5 -3
  49. package/src/config.ts +27 -33
  50. package/src/factory.ts +81 -103
  51. package/src/index.ts +1 -0
  52. package/src/job/epoch-proving-job-data.ts +31 -25
  53. package/src/job/epoch-proving-job.ts +228 -117
  54. package/src/metrics.ts +102 -82
  55. package/src/monitors/epoch-monitor.ts +10 -17
  56. package/src/prover-node-publisher.ts +302 -66
  57. package/src/prover-node.ts +135 -86
  58. package/src/prover-publisher-factory.ts +19 -11
@@ -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 { L2Block, L2BlockSource } from '@aztec/stdlib/block';
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
- EpochProvingJobTerminalState,
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: Pick<P2PClient<P2PClientType.Prover>, 'getTxProvider'> & Partial<Service>,
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: 32,
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: bigint): Promise<boolean> {
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
- const activeJobs = await this.getActiveJobsForEpoch(epochNumber);
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.worldState.stop();
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: number | bigint) {
188
- const job = await this.createProvingJob(BigInt(epochNumber), { skipEpochCheck: true });
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: number }[]> {
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
- protected async getActiveJobsForEpoch(
252
- epochBigInt: bigint,
253
- ): Promise<{ uuid: string; status: EpochProvingJobState }[]> {
254
- const jobs = await this.getJobs();
255
- const epochNumber = Number(epochBigInt);
256
- return jobs.filter(job => job.epochNumber === epochNumber && !EpochProvingJobTerminalState.includes(job.status));
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]: Number(epochNumber) }))
267
- private async createProvingJob(epochNumber: bigint, opts: { skipEpochCheck?: boolean } = {}) {
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 fromBlock = epochData.blocks[0].number;
276
- const toBlock = epochData.blocks.at(-1)!.number;
277
- this.log.verbose(`Creating proving job for epoch ${epochNumber} for block range ${fromBlock} to ${toBlock}`);
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 this.worldState.syncImmediate(toBlock);
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]: Number(epochNumber) }))
304
- private async gatherEpochData(epochNumber: bigint): Promise<EpochProvingJobData> {
305
- const blocks = await this.gatherBlocks(epochNumber);
306
- const txArray = await this.gatherTxs(epochNumber, blocks);
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
- return blocks;
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: bigint, blocks: L2Block[]) {
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: bigint, blocks: L2Block[]) {
340
- const messages = await Promise.all(blocks.map(b => this.l1ToL2MessageSource.getL1ToL2Messages(b.number)));
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 messagesByBlock: Record<number, Fr[]> = {};
344
- for (let i = 0; i < blocks.length; i++) {
345
- messagesByBlock[blocks[i].number] = messages[i];
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 messagesByBlock;
399
+ return messagesByCheckpoint;
348
400
  }
349
401
 
350
- private async gatherPreviousBlockHeader(epochNumber: bigint, initialBlock: L2Block) {
351
- const previousBlockNumber = initialBlock.number - 1;
352
- const header = await (previousBlockNumber === 0
353
- ? this.worldState.getCommitted().getInitialHeader()
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 || !this.config.rollupVersion)
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: bigint) {
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 { L1TxUtils, PublisherManager, RollupContract } from '@aztec/ethereum';
2
- import type { PublisherConfig, TxSenderConfig } from '@aztec/sequencer-client';
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: TxSenderConfig & PublisherConfig,
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.loadState();
22
+ await this.deps.publisherManager.start();
19
23
  }
20
24
 
21
- public stop() {
22
- this.deps.publisherManager.interrupt();
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(this.config, {
32
- rollupContract: this.deps.rollupContract,
33
- l1TxUtils: l1Publisher,
34
- telemetry: this.deps.telemetry,
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
  }