@aztec/prover-node 0.0.0-test.1 → 0.0.1-commit.017a351

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dest/actions/download-epoch-proving-job.d.ts +18 -0
  2. package/dest/actions/download-epoch-proving-job.d.ts.map +1 -0
  3. package/dest/actions/download-epoch-proving-job.js +37 -0
  4. package/dest/actions/index.d.ts +3 -0
  5. package/dest/actions/index.d.ts.map +1 -0
  6. package/dest/actions/index.js +2 -0
  7. package/dest/actions/rerun-epoch-proving-job.d.ts +13 -0
  8. package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -0
  9. package/dest/actions/rerun-epoch-proving-job.js +120 -0
  10. package/dest/actions/upload-epoch-proof-failure.d.ts +15 -0
  11. package/dest/actions/upload-epoch-proof-failure.d.ts.map +1 -0
  12. package/dest/actions/upload-epoch-proof-failure.js +78 -0
  13. package/dest/bin/run-failed-epoch.d.ts +2 -0
  14. package/dest/bin/run-failed-epoch.d.ts.map +1 -0
  15. package/dest/bin/run-failed-epoch.js +68 -0
  16. package/dest/config.d.ts +17 -16
  17. package/dest/config.d.ts.map +1 -1
  18. package/dest/config.js +93 -28
  19. package/dest/factory.d.ts +26 -18
  20. package/dest/factory.d.ts.map +1 -1
  21. package/dest/factory.js +92 -43
  22. package/dest/index.d.ts +3 -2
  23. package/dest/index.d.ts.map +1 -1
  24. package/dest/index.js +2 -1
  25. package/dest/job/epoch-proving-job-data.d.ts +18 -0
  26. package/dest/job/epoch-proving-job-data.d.ts.map +1 -0
  27. package/dest/job/epoch-proving-job-data.js +59 -0
  28. package/dest/job/epoch-proving-job.d.ts +31 -18
  29. package/dest/job/epoch-proving-job.d.ts.map +1 -1
  30. package/dest/job/epoch-proving-job.js +756 -99
  31. package/dest/metrics.d.ts +50 -5
  32. package/dest/metrics.d.ts.map +1 -1
  33. package/dest/metrics.js +157 -72
  34. package/dest/monitors/epoch-monitor.d.ts +5 -2
  35. package/dest/monitors/epoch-monitor.d.ts.map +1 -1
  36. package/dest/monitors/epoch-monitor.js +24 -17
  37. package/dest/monitors/index.d.ts +1 -1
  38. package/dest/prover-node-publisher.d.ts +38 -19
  39. package/dest/prover-node-publisher.d.ts.map +1 -1
  40. package/dest/prover-node-publisher.js +288 -87
  41. package/dest/prover-node.d.ts +64 -49
  42. package/dest/prover-node.d.ts.map +1 -1
  43. package/dest/prover-node.js +650 -148
  44. package/dest/prover-publisher-factory.d.ts +25 -0
  45. package/dest/prover-publisher-factory.d.ts.map +1 -0
  46. package/dest/prover-publisher-factory.js +28 -0
  47. package/dest/test/index.d.ts +5 -3
  48. package/dest/test/index.d.ts.map +1 -1
  49. package/dest/test/index.js +1 -3
  50. package/package.json +40 -33
  51. package/src/actions/download-epoch-proving-job.ts +44 -0
  52. package/src/actions/index.ts +2 -0
  53. package/src/actions/rerun-epoch-proving-job.ts +74 -0
  54. package/src/actions/upload-epoch-proof-failure.ts +88 -0
  55. package/src/bin/run-failed-epoch.ts +79 -0
  56. package/src/config.ts +123 -45
  57. package/src/factory.ts +163 -67
  58. package/src/index.ts +2 -1
  59. package/src/job/epoch-proving-job-data.ts +82 -0
  60. package/src/job/epoch-proving-job.ts +364 -88
  61. package/src/metrics.ts +188 -70
  62. package/src/monitors/epoch-monitor.ts +23 -19
  63. package/src/prover-node-publisher.ts +368 -125
  64. package/src/prover-node.ts +292 -166
  65. package/src/prover-publisher-factory.ts +45 -0
  66. package/src/test/index.ts +7 -4
  67. package/dest/http.d.ts +0 -8
  68. package/dest/http.d.ts.map +0 -1
  69. package/dest/http.js +0 -9
  70. package/dest/prover-coordination/config.d.ts +0 -7
  71. package/dest/prover-coordination/config.d.ts.map +0 -1
  72. package/dest/prover-coordination/config.js +0 -11
  73. package/dest/prover-coordination/factory.d.ts +0 -22
  74. package/dest/prover-coordination/factory.d.ts.map +0 -1
  75. package/dest/prover-coordination/factory.js +0 -42
  76. package/dest/prover-coordination/index.d.ts +0 -3
  77. package/dest/prover-coordination/index.d.ts.map +0 -1
  78. package/dest/prover-coordination/index.js +0 -2
  79. package/src/http.ts +0 -13
  80. package/src/prover-coordination/config.ts +0 -17
  81. package/src/prover-coordination/factory.ts +0 -72
  82. package/src/prover-coordination/index.ts +0 -2
package/src/metrics.ts CHANGED
@@ -1,23 +1,153 @@
1
+ import type { RollupContract } from '@aztec/ethereum/contracts';
2
+ import type { EthAddress } from '@aztec/foundation/eth-address';
1
3
  import { createLogger } from '@aztec/foundation/log';
2
4
  import type { L1PublishProofStats, L1PublishStats } from '@aztec/stdlib/stats';
3
5
  import {
4
6
  Attributes,
7
+ type BatchObservableResult,
5
8
  type Gauge,
6
9
  type Histogram,
10
+ type Meter,
7
11
  Metrics,
12
+ type ObservableGauge,
8
13
  type TelemetryClient,
14
+ type Tracer,
9
15
  type UpDownCounter,
10
- ValueType,
16
+ createUpDownCounterWithDefault,
11
17
  } from '@aztec/telemetry-client';
12
18
 
13
- import { formatEther } from 'viem';
19
+ import { formatEther, formatUnits } from 'viem';
14
20
 
15
- export class ProverNodeMetrics {
21
+ export class ProverNodeJobMetrics {
16
22
  proverEpochExecutionDuration: Histogram;
17
23
  provingJobDuration: Histogram;
24
+ provingJobCheckpoints: Gauge;
18
25
  provingJobBlocks: Gauge;
19
26
  provingJobTransactions: Gauge;
20
27
 
28
+ private blobProcessingDuration: Gauge;
29
+ private chonkVerifierDuration: Gauge;
30
+ private blockProcessingDuration: Histogram;
31
+ private checkpointProcessingDuration: Histogram;
32
+ private allCheckpointsProcessingDuration: Gauge;
33
+
34
+ constructor(
35
+ private meter: Meter,
36
+ public readonly tracer: Tracer,
37
+ private logger = createLogger('prover-node:publisher:metrics'),
38
+ ) {
39
+ this.proverEpochExecutionDuration = this.meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION);
40
+ this.provingJobDuration = this.meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION);
41
+ this.provingJobCheckpoints = this.meter.createGauge(Metrics.PROVER_NODE_JOB_CHECKPOINTS);
42
+ this.provingJobBlocks = this.meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS);
43
+ this.provingJobTransactions = this.meter.createGauge(Metrics.PROVER_NODE_JOB_TRANSACTIONS);
44
+
45
+ this.blobProcessingDuration = this.meter.createGauge(Metrics.PROVER_NODE_BLOB_PROCESSING_LAST_DURATION);
46
+ this.chonkVerifierDuration = this.meter.createGauge(Metrics.PROVER_NODE_CHONK_VERIFIER_LAST_DURATION);
47
+ this.blockProcessingDuration = this.meter.createHistogram(Metrics.PROVER_NODE_BLOCK_PROCESSING_DURATION);
48
+ this.checkpointProcessingDuration = this.meter.createHistogram(Metrics.PROVER_NODE_CHECKPOINT_PROCESSING_DURATION);
49
+ this.allCheckpointsProcessingDuration = this.meter.createGauge(
50
+ Metrics.PROVER_NODE_ALL_CHECKPOINTS_PROCESSING_LAST_DURATION,
51
+ );
52
+ }
53
+
54
+ public recordProvingJob(
55
+ executionTimeMs: number,
56
+ totalTimeMs: number,
57
+ numCheckpoints: number,
58
+ numBlocks: number,
59
+ numTxs: number,
60
+ ) {
61
+ this.proverEpochExecutionDuration.record(Math.ceil(executionTimeMs));
62
+ this.provingJobDuration.record(totalTimeMs / 1000);
63
+ this.provingJobCheckpoints.record(Math.floor(numCheckpoints));
64
+ this.provingJobBlocks.record(Math.floor(numBlocks));
65
+ this.provingJobTransactions.record(Math.floor(numTxs));
66
+ }
67
+
68
+ public recordBlobProcessing(durationMs: number) {
69
+ this.blobProcessingDuration.record(Math.ceil(durationMs));
70
+ }
71
+
72
+ public recordChonkVerifier(durationMs: number) {
73
+ this.chonkVerifierDuration.record(Math.ceil(durationMs));
74
+ }
75
+
76
+ public recordBlockProcessing(durationMs: number) {
77
+ this.blockProcessingDuration.record(Math.ceil(durationMs));
78
+ }
79
+
80
+ public recordCheckpointProcessing(durationMs: number) {
81
+ this.checkpointProcessingDuration.record(Math.ceil(durationMs));
82
+ }
83
+
84
+ public recordAllCheckpointsProcessing(durationMs: number) {
85
+ this.allCheckpointsProcessingDuration.record(Math.ceil(durationMs));
86
+ }
87
+ }
88
+
89
+ export class ProverNodeRewardsMetrics {
90
+ private rewards: ObservableGauge;
91
+ private accumulatedRewards: UpDownCounter;
92
+ private prevEpoch = -1n;
93
+ private proofSubmissionEpochs = 0;
94
+
95
+ constructor(
96
+ private meter: Meter,
97
+ private coinbase: EthAddress,
98
+ private rollup: RollupContract,
99
+ private logger = createLogger('prover-node:publisher:metrics'),
100
+ ) {
101
+ this.rewards = this.meter.createObservableGauge(Metrics.PROVER_NODE_REWARDS_PER_EPOCH);
102
+
103
+ this.accumulatedRewards = createUpDownCounterWithDefault(this.meter, Metrics.PROVER_NODE_REWARDS_TOTAL);
104
+ }
105
+
106
+ public async start() {
107
+ const proofSubmissionEpochs = await this.rollup.getProofSubmissionEpochs();
108
+ this.proofSubmissionEpochs = Number(proofSubmissionEpochs);
109
+ this.meter.addBatchObservableCallback(this.observe, [this.rewards]);
110
+ }
111
+
112
+ public stop() {
113
+ this.meter.removeBatchObservableCallback(this.observe, [this.rewards]);
114
+ }
115
+
116
+ private observe = async (observer: BatchObservableResult): Promise<void> => {
117
+ const epoch = await this.rollup.getCurrentEpochNumber();
118
+
119
+ if (epoch > this.proofSubmissionEpochs) {
120
+ // look at the prev epoch so that we get an accurate value, after proof submission window has closed
121
+ // For example, if proof submission window is 1 epoch, and we are in epoch 2, we should be looking at epoch 0.
122
+ // Similarly, if the proof submission window is 0, and we are in epoch 1, we should be looking at epoch 0.
123
+ const closedEpoch = BigInt(epoch) - BigInt(this.proofSubmissionEpochs) - 1n;
124
+ const rewards = await this.rollup.getSpecificProverRewardsForEpoch(closedEpoch, this.coinbase);
125
+
126
+ const fmt = parseFloat(formatUnits(rewards, 18));
127
+
128
+ observer.observe(this.rewards, fmt, {
129
+ [Attributes.COINBASE]: this.coinbase.toString(),
130
+ });
131
+
132
+ // only accumulate once per epoch
133
+ if (closedEpoch > this.prevEpoch) {
134
+ this.prevEpoch = closedEpoch;
135
+ this.accumulatedRewards.add(fmt, {
136
+ [Attributes.COINBASE]: this.coinbase.toString(),
137
+ });
138
+ }
139
+ }
140
+ };
141
+ }
142
+
143
+ export type EstimatedSubmitProofStats = {
144
+ gasLimit: bigint;
145
+ baseFeePerGas: bigint;
146
+ maxPriorityFeePerGas: bigint;
147
+ estimatedTotalFee: bigint;
148
+ };
149
+
150
+ export class ProverNodePublisherMetrics {
21
151
  gasPrice: Histogram;
22
152
  txCount: UpDownCounter;
23
153
  txDuration: Histogram;
@@ -26,85 +156,50 @@ export class ProverNodeMetrics {
26
156
  txCalldataGas: Histogram;
27
157
  txBlobDataGasUsed: Histogram;
28
158
  txBlobDataGasCost: Histogram;
159
+ txTotalFee: Histogram;
160
+
161
+ private txGasEstimated: Histogram;
162
+ private gasPriceEstimated: Histogram;
163
+ private txTotalFeeEstimated: Histogram;
29
164
 
30
165
  private senderBalance: Gauge;
166
+ private meter: Meter;
31
167
 
32
168
  constructor(
33
169
  public readonly client: TelemetryClient,
34
170
  name = 'ProverNode',
35
171
  private logger = createLogger('prover-node:publisher:metrics'),
36
172
  ) {
37
- const meter = client.getMeter(name);
38
- this.proverEpochExecutionDuration = meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION, {
39
- description: 'Duration of execution of an epoch by the prover',
40
- unit: 'ms',
41
- valueType: ValueType.INT,
42
- });
43
- this.provingJobDuration = meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION, {
44
- description: 'Duration of proving job',
45
- unit: 's',
46
- valueType: ValueType.DOUBLE,
47
- });
48
- this.provingJobBlocks = meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS, {
49
- description: 'Number of blocks in a proven epoch',
50
- valueType: ValueType.INT,
51
- });
52
- this.provingJobTransactions = meter.createGauge(Metrics.PROVER_NODE_JOB_TRANSACTIONS, {
53
- description: 'Number of transactions in a proven epoch',
54
- valueType: ValueType.INT,
55
- });
173
+ this.meter = client.getMeter(name);
56
174
 
57
- this.gasPrice = meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE, {
58
- description: 'The gas price used for transactions',
59
- unit: 'gwei',
60
- valueType: ValueType.DOUBLE,
61
- });
175
+ this.gasPrice = this.meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE);
62
176
 
63
- this.txCount = meter.createUpDownCounter(Metrics.L1_PUBLISHER_TX_COUNT, {
64
- description: 'The number of transactions processed',
177
+ this.txCount = createUpDownCounterWithDefault(this.meter, Metrics.L1_PUBLISHER_TX_COUNT, {
178
+ [Attributes.L1_TX_TYPE]: ['submitProof'],
179
+ [Attributes.OK]: [true, false],
65
180
  });
66
181
 
67
- this.txDuration = meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION, {
68
- description: 'The duration of transaction processing',
69
- unit: 'ms',
70
- valueType: ValueType.INT,
71
- });
182
+ this.txDuration = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION);
72
183
 
73
- this.txGas = meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS, {
74
- description: 'The gas consumed by transactions',
75
- unit: 'gas',
76
- valueType: ValueType.INT,
77
- });
184
+ this.txGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS);
78
185
 
79
- this.txCalldataSize = meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE, {
80
- description: 'The size of the calldata in transactions',
81
- unit: 'By',
82
- valueType: ValueType.INT,
83
- });
186
+ this.txCalldataSize = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE);
84
187
 
85
- this.txCalldataGas = meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS, {
86
- description: 'The gas consumed by the calldata in transactions',
87
- unit: 'gas',
88
- valueType: ValueType.INT,
89
- });
188
+ this.txCalldataGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS);
90
189
 
91
- this.txBlobDataGasUsed = meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED, {
92
- description: 'The amount of blob gas used in transactions',
93
- unit: 'gas',
94
- valueType: ValueType.INT,
95
- });
190
+ this.txBlobDataGasUsed = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED);
96
191
 
97
- this.txBlobDataGasCost = meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST, {
98
- description: 'The gas cost of blobs in transactions',
99
- unit: 'gwei',
100
- valueType: ValueType.INT,
101
- });
192
+ this.txBlobDataGasCost = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST);
102
193
 
103
- this.senderBalance = meter.createGauge(Metrics.L1_PUBLISHER_BALANCE, {
104
- unit: 'eth',
105
- description: 'The balance of the sender address',
106
- valueType: ValueType.DOUBLE,
107
- });
194
+ this.txTotalFee = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_TOTAL_FEE);
195
+
196
+ this.txGasEstimated = this.meter.createHistogram(Metrics.PROVER_NODE_ESTIMATED_SUBMISSION_GAS);
197
+
198
+ this.gasPriceEstimated = this.meter.createHistogram(Metrics.PROVER_NODE_ESTIMATED_SUBMISSION_GAS_PRICE);
199
+
200
+ this.txTotalFeeEstimated = this.meter.createHistogram(Metrics.PROVER_NODE_ESTIMATED_SUBMISSION_TOTAL_FEE);
201
+
202
+ this.senderBalance = this.meter.createGauge(Metrics.L1_PUBLISHER_BALANCE);
108
203
  }
109
204
 
110
205
  recordFailedTx() {
@@ -118,11 +213,24 @@ export class ProverNodeMetrics {
118
213
  this.recordTx(durationMs, stats);
119
214
  }
120
215
 
121
- public recordProvingJob(executionTimeMs: number, totalTimeMs: number, numBlocks: number, numTxs: number) {
122
- this.proverEpochExecutionDuration.record(Math.ceil(executionTimeMs));
123
- this.provingJobDuration.record(totalTimeMs / 1000);
124
- this.provingJobBlocks.record(Math.floor(numBlocks));
125
- this.provingJobTransactions.record(Math.floor(numTxs));
216
+ public recordEstimatedSubmitProof(stats: EstimatedSubmitProofStats) {
217
+ const attributes = { [Attributes.L1_TX_TYPE]: 'submitProof' } as const;
218
+
219
+ this.txGasEstimated.record(Number(stats.gasLimit), attributes);
220
+
221
+ try {
222
+ this.gasPriceEstimated.record(
223
+ parseInt(formatEther(stats.baseFeePerGas + stats.maxPriorityFeePerGas, 'gwei'), 10),
224
+ );
225
+ } catch {
226
+ // ignore
227
+ }
228
+
229
+ try {
230
+ this.txTotalFeeEstimated.record(parseFloat(formatEther(stats.estimatedTotalFee)));
231
+ } catch {
232
+ // ignore
233
+ }
126
234
  }
127
235
 
128
236
  public recordSenderBalance(wei: bigint, senderAddress: string) {
@@ -157,7 +265,17 @@ export class ProverNodeMetrics {
157
265
 
158
266
  try {
159
267
  this.gasPrice.record(parseInt(formatEther(stats.gasPrice, 'gwei'), 10));
160
- } catch (e) {
268
+ } catch {
269
+ // ignore
270
+ }
271
+
272
+ const executionFee = stats.gasUsed * stats.gasPrice;
273
+ const blobFee = stats.blobGasUsed * stats.blobDataGas;
274
+ const totalFee = executionFee + blobFee;
275
+
276
+ try {
277
+ this.txTotalFee.record(parseFloat(formatEther(totalFee)));
278
+ } catch {
161
279
  // ignore
162
280
  }
163
281
  }
@@ -1,17 +1,13 @@
1
+ import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
1
2
  import { createLogger } from '@aztec/foundation/log';
2
3
  import { RunningPromise } from '@aztec/foundation/running-promise';
4
+ import { sleep } from '@aztec/foundation/sleep';
3
5
  import type { L2BlockSource } from '@aztec/stdlib/block';
4
6
  import { type L1RollupConstants, getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
5
- import {
6
- type TelemetryClient,
7
- type Traceable,
8
- type Tracer,
9
- getTelemetryClient,
10
- trackSpan,
11
- } from '@aztec/telemetry-client';
7
+ import { type TelemetryClient, type Traceable, type Tracer, getTelemetryClient } from '@aztec/telemetry-client';
12
8
 
13
9
  export interface EpochMonitorHandler {
14
- handleEpochReadyToProve(epochNumber: bigint): Promise<void>;
10
+ handleEpochReadyToProve(epochNumber: EpochNumber): Promise<boolean>;
15
11
  }
16
12
 
17
13
  /**
@@ -31,21 +27,24 @@ export class EpochMonitor implements Traceable {
31
27
  public readonly tracer: Tracer;
32
28
 
33
29
  private handler: EpochMonitorHandler | undefined;
34
- private latestEpochNumber: bigint | undefined;
30
+ private latestEpochNumber: EpochNumber | undefined;
35
31
 
36
32
  constructor(
37
33
  private readonly l2BlockSource: L2BlockSource,
38
34
  private readonly l1Constants: Pick<L1RollupConstants, 'epochDuration'>,
39
- private options: { pollingIntervalMs: number },
35
+ private options: { pollingIntervalMs: number; provingDelayMs?: number },
40
36
  telemetry: TelemetryClient = getTelemetryClient(),
41
37
  ) {
42
38
  this.tracer = telemetry.getTracer('EpochMonitor');
43
39
  this.runningPromise = new RunningPromise(this.work.bind(this), this.log, this.options.pollingIntervalMs);
40
+ if (this.options.provingDelayMs) {
41
+ this.log.warn(`Prover node epoch monitor running with delay of ${this.options.provingDelayMs}ms`);
42
+ }
44
43
  }
45
44
 
46
45
  public static async create(
47
46
  l2BlockSource: L2BlockSource,
48
- options: { pollingIntervalMs: number },
47
+ options: { pollingIntervalMs: number; provingDelayMs?: number },
49
48
  telemetry: TelemetryClient = getTelemetryClient(),
50
49
  ): Promise<EpochMonitor> {
51
50
  const l1Constants = await l2BlockSource.getL1Constants();
@@ -68,11 +67,10 @@ export class EpochMonitor implements Traceable {
68
67
  this.log.info('Stopped EpochMonitor');
69
68
  }
70
69
 
71
- @trackSpan('EpochMonitor.work')
72
70
  public async work() {
73
71
  const { epochToProve, blockNumber, slotNumber } = await this.getEpochNumberToProve();
74
72
  if (epochToProve === undefined) {
75
- this.log.trace(`Next block to prove ${blockNumber} not yet mined`, { blockNumber });
73
+ this.log.trace(`Next block to prove ${blockNumber} not yet mined`, { epochToProve, blockNumber, slotNumber });
76
74
  return;
77
75
  }
78
76
  if (this.latestEpochNumber !== undefined && epochToProve <= this.latestEpochNumber) {
@@ -86,15 +84,21 @@ export class EpochMonitor implements Traceable {
86
84
  return;
87
85
  }
88
86
 
89
- this.log.debug(`Epoch ${epochToProve} is ready to be proven`);
90
- await this.handler?.handleEpochReadyToProve(epochToProve);
91
- this.latestEpochNumber = epochToProve;
87
+ if (this.options.provingDelayMs) {
88
+ this.log.warn(`Waiting ${this.options.provingDelayMs}ms before proving epoch ${epochToProve}`);
89
+ await sleep(this.options.provingDelayMs);
90
+ }
91
+
92
+ this.log.verbose(`Epoch ${epochToProve} is ready to be proven`);
93
+ if (await this.handler?.handleEpochReadyToProve(epochToProve)) {
94
+ this.latestEpochNumber = epochToProve;
95
+ }
92
96
  }
93
97
 
94
98
  private async getEpochNumberToProve() {
95
- const lastBlockProven = await this.l2BlockSource.getProvenBlockNumber();
96
- const firstBlockToProve = lastBlockProven + 1;
97
- const firstBlockHeaderToProve = await this.l2BlockSource.getBlockHeader(firstBlockToProve);
99
+ const lastBlockProven = (await this.l2BlockSource.getBlockNumber({ tag: 'proven' })) ?? BlockNumber.ZERO;
100
+ const firstBlockToProve = BlockNumber(lastBlockProven + 1);
101
+ const firstBlockHeaderToProve = (await this.l2BlockSource.getBlockData({ number: firstBlockToProve }))?.header;
98
102
  if (!firstBlockHeaderToProve) {
99
103
  return { epochToProve: undefined, blockNumber: firstBlockToProve };
100
104
  }