@aztec/prover-node 0.0.0-test.1 → 0.0.1-commit.03f7ef2

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 +11 -0
  8. package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -0
  9. package/dest/actions/rerun-epoch-proving-job.js +40 -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 +67 -0
  16. package/dest/config.d.ts +15 -11
  17. package/dest/config.d.ts.map +1 -1
  18. package/dest/config.js +83 -15
  19. package/dest/factory.d.ts +16 -12
  20. package/dest/factory.d.ts.map +1 -1
  21. package/dest/factory.js +100 -32
  22. package/dest/index.d.ts +2 -2
  23. package/dest/index.d.ts.map +1 -1
  24. package/dest/index.js +1 -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 +26 -18
  29. package/dest/job/epoch-proving-job.d.ts.map +1 -1
  30. package/dest/job/epoch-proving-job.js +193 -84
  31. package/dest/metrics.d.ts +30 -5
  32. package/dest/metrics.d.ts.map +1 -1
  33. package/dest/metrics.js +147 -35
  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 +17 -3
  37. package/dest/monitors/index.d.ts +1 -1
  38. package/dest/prover-node-publisher.d.ts +14 -15
  39. package/dest/prover-node-publisher.d.ts.map +1 -1
  40. package/dest/prover-node-publisher.js +86 -81
  41. package/dest/prover-node.d.ts +49 -44
  42. package/dest/prover-node.d.ts.map +1 -1
  43. package/dest/prover-node.js +186 -112
  44. package/dest/prover-publisher-factory.d.ts +23 -0
  45. package/dest/prover-publisher-factory.d.ts.map +1 -0
  46. package/dest/prover-publisher-factory.js +26 -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 +39 -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 +61 -0
  54. package/src/actions/upload-epoch-proof-failure.ts +88 -0
  55. package/src/bin/run-failed-epoch.ts +77 -0
  56. package/src/config.ts +111 -25
  57. package/src/factory.ts +167 -44
  58. package/src/index.ts +1 -1
  59. package/src/job/epoch-proving-job-data.ts +82 -0
  60. package/src/job/epoch-proving-job.ts +255 -83
  61. package/src/metrics.ts +147 -37
  62. package/src/monitors/epoch-monitor.ts +19 -7
  63. package/src/prover-node-publisher.ts +132 -115
  64. package/src/prover-node.ts +223 -142
  65. package/src/prover-publisher-factory.ts +39 -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,106 +1,213 @@
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
16
  ValueType,
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
 
21
- gasPrice: Histogram;
22
- txCount: UpDownCounter;
23
- txDuration: Histogram;
24
- txGas: Histogram;
25
- txCalldataSize: Histogram;
26
- txCalldataGas: Histogram;
27
- txBlobDataGasUsed: Histogram;
28
- txBlobDataGasCost: Histogram;
29
-
30
- private senderBalance: Gauge;
31
-
32
28
  constructor(
33
- public readonly client: TelemetryClient,
34
- name = 'ProverNode',
29
+ private meter: Meter,
30
+ public readonly tracer: Tracer,
35
31
  private logger = createLogger('prover-node:publisher:metrics'),
36
32
  ) {
37
- const meter = client.getMeter(name);
38
- this.proverEpochExecutionDuration = meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION, {
33
+ this.proverEpochExecutionDuration = this.meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION, {
39
34
  description: 'Duration of execution of an epoch by the prover',
40
35
  unit: 'ms',
41
36
  valueType: ValueType.INT,
42
37
  });
43
- this.provingJobDuration = meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION, {
38
+ this.provingJobDuration = this.meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION, {
44
39
  description: 'Duration of proving job',
45
40
  unit: 's',
46
41
  valueType: ValueType.DOUBLE,
47
42
  });
48
- this.provingJobBlocks = meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS, {
43
+ this.provingJobCheckpoints = this.meter.createGauge(Metrics.PROVER_NODE_JOB_CHECKPOINTS, {
44
+ description: 'Number of checkpoints in a proven epoch',
45
+ valueType: ValueType.INT,
46
+ });
47
+ this.provingJobBlocks = this.meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS, {
49
48
  description: 'Number of blocks in a proven epoch',
50
49
  valueType: ValueType.INT,
51
50
  });
52
- this.provingJobTransactions = meter.createGauge(Metrics.PROVER_NODE_JOB_TRANSACTIONS, {
51
+ this.provingJobTransactions = this.meter.createGauge(Metrics.PROVER_NODE_JOB_TRANSACTIONS, {
53
52
  description: 'Number of transactions in a proven epoch',
54
53
  valueType: ValueType.INT,
55
54
  });
55
+ }
56
+
57
+ public recordProvingJob(
58
+ executionTimeMs: number,
59
+ totalTimeMs: number,
60
+ numCheckpoints: number,
61
+ numBlocks: number,
62
+ numTxs: number,
63
+ ) {
64
+ this.proverEpochExecutionDuration.record(Math.ceil(executionTimeMs));
65
+ this.provingJobDuration.record(totalTimeMs / 1000);
66
+ this.provingJobCheckpoints.record(Math.floor(numCheckpoints));
67
+ this.provingJobBlocks.record(Math.floor(numBlocks));
68
+ this.provingJobTransactions.record(Math.floor(numTxs));
69
+ }
70
+ }
71
+
72
+ export class ProverNodeRewardsMetrics {
73
+ private rewards: ObservableGauge;
74
+ private accumulatedRewards: UpDownCounter;
75
+ private prevEpoch = -1n;
76
+ private proofSubmissionEpochs = 0;
77
+
78
+ constructor(
79
+ private meter: Meter,
80
+ private coinbase: EthAddress,
81
+ private rollup: RollupContract,
82
+ private logger = createLogger('prover-node:publisher:metrics'),
83
+ ) {
84
+ this.rewards = this.meter.createObservableGauge(Metrics.PROVER_NODE_REWARDS_PER_EPOCH, {
85
+ valueType: ValueType.DOUBLE,
86
+ description: 'The rewards earned',
87
+ });
88
+
89
+ this.accumulatedRewards = this.meter.createUpDownCounter(Metrics.PROVER_NODE_REWARDS_TOTAL, {
90
+ valueType: ValueType.DOUBLE,
91
+ description: 'The rewards earned (total)',
92
+ });
93
+ }
94
+
95
+ public async start() {
96
+ const proofSubmissionEpochs = await this.rollup.getProofSubmissionEpochs();
97
+ this.proofSubmissionEpochs = Number(proofSubmissionEpochs);
98
+ this.meter.addBatchObservableCallback(this.observe, [this.rewards]);
99
+ }
100
+
101
+ public stop() {
102
+ this.meter.removeBatchObservableCallback(this.observe, [this.rewards]);
103
+ }
56
104
 
57
- this.gasPrice = meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE, {
105
+ private observe = async (observer: BatchObservableResult): Promise<void> => {
106
+ const epoch = await this.rollup.getCurrentEpochNumber();
107
+
108
+ if (epoch > this.proofSubmissionEpochs) {
109
+ // look at the prev epoch so that we get an accurate value, after proof submission window has closed
110
+ // For example, if proof submission window is 1 epoch, and we are in epoch 2, we should be looking at epoch 0.
111
+ // Similarly, if the proof submission window is 0, and we are in epoch 1, we should be looking at epoch 0.
112
+ const closedEpoch = BigInt(epoch) - BigInt(this.proofSubmissionEpochs) - 1n;
113
+ const rewards = await this.rollup.getSpecificProverRewardsForEpoch(closedEpoch, this.coinbase);
114
+
115
+ const fmt = parseFloat(formatUnits(rewards, 18));
116
+
117
+ observer.observe(this.rewards, fmt, {
118
+ [Attributes.COINBASE]: this.coinbase.toString(),
119
+ });
120
+
121
+ // only accumulate once per epoch
122
+ if (closedEpoch > this.prevEpoch) {
123
+ this.prevEpoch = closedEpoch;
124
+ this.accumulatedRewards.add(fmt, {
125
+ [Attributes.COINBASE]: this.coinbase.toString(),
126
+ });
127
+ }
128
+ }
129
+ };
130
+ }
131
+
132
+ export class ProverNodePublisherMetrics {
133
+ gasPrice: Histogram;
134
+ txCount: UpDownCounter;
135
+ txDuration: Histogram;
136
+ txGas: Histogram;
137
+ txCalldataSize: Histogram;
138
+ txCalldataGas: Histogram;
139
+ txBlobDataGasUsed: Histogram;
140
+ txBlobDataGasCost: Histogram;
141
+ txTotalFee: Histogram;
142
+
143
+ private senderBalance: Gauge;
144
+ private meter: Meter;
145
+
146
+ constructor(
147
+ public readonly client: TelemetryClient,
148
+ name = 'ProverNode',
149
+ private logger = createLogger('prover-node:publisher:metrics'),
150
+ ) {
151
+ this.meter = client.getMeter(name);
152
+
153
+ this.gasPrice = this.meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE, {
58
154
  description: 'The gas price used for transactions',
59
155
  unit: 'gwei',
60
156
  valueType: ValueType.DOUBLE,
61
157
  });
62
158
 
63
- this.txCount = meter.createUpDownCounter(Metrics.L1_PUBLISHER_TX_COUNT, {
159
+ this.txCount = this.meter.createUpDownCounter(Metrics.L1_PUBLISHER_TX_COUNT, {
64
160
  description: 'The number of transactions processed',
65
161
  });
66
162
 
67
- this.txDuration = meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION, {
163
+ this.txDuration = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION, {
68
164
  description: 'The duration of transaction processing',
69
165
  unit: 'ms',
70
166
  valueType: ValueType.INT,
71
167
  });
72
168
 
73
- this.txGas = meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS, {
169
+ this.txGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS, {
74
170
  description: 'The gas consumed by transactions',
75
171
  unit: 'gas',
76
172
  valueType: ValueType.INT,
77
173
  });
78
174
 
79
- this.txCalldataSize = meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE, {
175
+ this.txCalldataSize = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE, {
80
176
  description: 'The size of the calldata in transactions',
81
177
  unit: 'By',
82
178
  valueType: ValueType.INT,
83
179
  });
84
180
 
85
- this.txCalldataGas = meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS, {
181
+ this.txCalldataGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS, {
86
182
  description: 'The gas consumed by the calldata in transactions',
87
183
  unit: 'gas',
88
184
  valueType: ValueType.INT,
89
185
  });
90
186
 
91
- this.txBlobDataGasUsed = meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED, {
187
+ this.txBlobDataGasUsed = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED, {
92
188
  description: 'The amount of blob gas used in transactions',
93
189
  unit: 'gas',
94
190
  valueType: ValueType.INT,
95
191
  });
96
192
 
97
- this.txBlobDataGasCost = meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST, {
193
+ this.txBlobDataGasCost = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST, {
98
194
  description: 'The gas cost of blobs in transactions',
99
195
  unit: 'gwei',
100
196
  valueType: ValueType.INT,
101
197
  });
102
198
 
103
- this.senderBalance = meter.createGauge(Metrics.L1_PUBLISHER_BALANCE, {
199
+ this.txTotalFee = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_TOTAL_FEE, {
200
+ description: 'How much L1 tx costs',
201
+ unit: 'gwei',
202
+ valueType: ValueType.DOUBLE,
203
+ advice: {
204
+ explicitBucketBoundaries: [
205
+ 0.001, 0.002, 0.004, 0.008, 0.01, 0.02, 0.04, 0.08, 0.1, 0.2, 0.4, 0.8, 1, 1.2, 1.4, 1.8, 2,
206
+ ],
207
+ },
208
+ });
209
+
210
+ this.senderBalance = this.meter.createGauge(Metrics.L1_PUBLISHER_BALANCE, {
104
211
  unit: 'eth',
105
212
  description: 'The balance of the sender address',
106
213
  valueType: ValueType.DOUBLE,
@@ -118,13 +225,6 @@ export class ProverNodeMetrics {
118
225
  this.recordTx(durationMs, stats);
119
226
  }
120
227
 
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));
126
- }
127
-
128
228
  public recordSenderBalance(wei: bigint, senderAddress: string) {
129
229
  const eth = parseFloat(formatEther(wei, 'wei'));
130
230
  this.senderBalance.record(eth, {
@@ -157,7 +257,17 @@ export class ProverNodeMetrics {
157
257
 
158
258
  try {
159
259
  this.gasPrice.record(parseInt(formatEther(stats.gasPrice, 'gwei'), 10));
160
- } catch (e) {
260
+ } catch {
261
+ // ignore
262
+ }
263
+
264
+ const executionFee = stats.gasUsed * stats.gasPrice;
265
+ const blobFee = stats.blobGasUsed * stats.blobDataGas;
266
+ const totalFee = executionFee + blobFee;
267
+
268
+ try {
269
+ this.txTotalFee.record(parseFloat(formatEther(totalFee)));
270
+ } catch {
161
271
  // ignore
162
272
  }
163
273
  }
@@ -1,5 +1,7 @@
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
7
  import {
@@ -11,7 +13,7 @@ import {
11
13
  } from '@aztec/telemetry-client';
12
14
 
13
15
  export interface EpochMonitorHandler {
14
- handleEpochReadyToProve(epochNumber: bigint): Promise<void>;
16
+ handleEpochReadyToProve(epochNumber: EpochNumber): Promise<boolean>;
15
17
  }
16
18
 
17
19
  /**
@@ -31,21 +33,24 @@ export class EpochMonitor implements Traceable {
31
33
  public readonly tracer: Tracer;
32
34
 
33
35
  private handler: EpochMonitorHandler | undefined;
34
- private latestEpochNumber: bigint | undefined;
36
+ private latestEpochNumber: EpochNumber | undefined;
35
37
 
36
38
  constructor(
37
39
  private readonly l2BlockSource: L2BlockSource,
38
40
  private readonly l1Constants: Pick<L1RollupConstants, 'epochDuration'>,
39
- private options: { pollingIntervalMs: number },
41
+ private options: { pollingIntervalMs: number; provingDelayMs?: number },
40
42
  telemetry: TelemetryClient = getTelemetryClient(),
41
43
  ) {
42
44
  this.tracer = telemetry.getTracer('EpochMonitor');
43
45
  this.runningPromise = new RunningPromise(this.work.bind(this), this.log, this.options.pollingIntervalMs);
46
+ if (this.options.provingDelayMs) {
47
+ this.log.warn(`Prover node epoch monitor running with delay of ${this.options.provingDelayMs}ms`);
48
+ }
44
49
  }
45
50
 
46
51
  public static async create(
47
52
  l2BlockSource: L2BlockSource,
48
- options: { pollingIntervalMs: number },
53
+ options: { pollingIntervalMs: number; provingDelayMs?: number },
49
54
  telemetry: TelemetryClient = getTelemetryClient(),
50
55
  ): Promise<EpochMonitor> {
51
56
  const l1Constants = await l2BlockSource.getL1Constants();
@@ -71,6 +76,7 @@ export class EpochMonitor implements Traceable {
71
76
  @trackSpan('EpochMonitor.work')
72
77
  public async work() {
73
78
  const { epochToProve, blockNumber, slotNumber } = await this.getEpochNumberToProve();
79
+ this.log.debug(`Epoch to prove: ${epochToProve}`, { blockNumber, slotNumber });
74
80
  if (epochToProve === undefined) {
75
81
  this.log.trace(`Next block to prove ${blockNumber} not yet mined`, { blockNumber });
76
82
  return;
@@ -86,14 +92,20 @@ export class EpochMonitor implements Traceable {
86
92
  return;
87
93
  }
88
94
 
95
+ if (this.options.provingDelayMs) {
96
+ this.log.debug(`Waiting ${this.options.provingDelayMs}ms before proving epoch ${epochToProve}`);
97
+ await sleep(this.options.provingDelayMs);
98
+ }
99
+
89
100
  this.log.debug(`Epoch ${epochToProve} is ready to be proven`);
90
- await this.handler?.handleEpochReadyToProve(epochToProve);
91
- this.latestEpochNumber = epochToProve;
101
+ if (await this.handler?.handleEpochReadyToProve(epochToProve)) {
102
+ this.latestEpochNumber = epochToProve;
103
+ }
92
104
  }
93
105
 
94
106
  private async getEpochNumberToProve() {
95
107
  const lastBlockProven = await this.l2BlockSource.getProvenBlockNumber();
96
- const firstBlockToProve = lastBlockProven + 1;
108
+ const firstBlockToProve = BlockNumber(lastBlockProven + 1);
97
109
  const firstBlockHeaderToProve = await this.l2BlockSource.getBlockHeader(firstBlockToProve);
98
110
  if (!firstBlockHeaderToProve) {
99
111
  return { epochToProve: undefined, blockNumber: firstBlockToProve };