@aztec/prover-node 0.0.0-test.0 → 0.0.1-commit.21caa21

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 +13 -10
  17. package/dest/config.d.ts.map +1 -1
  18. package/dest/config.js +81 -14
  19. package/dest/factory.d.ts +13 -9
  20. package/dest/factory.d.ts.map +1 -1
  21. package/dest/factory.js +95 -31
  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 +17 -0
  26. package/dest/job/epoch-proving-job-data.d.ts.map +1 -0
  27. package/dest/job/epoch-proving-job-data.js +53 -0
  28. package/dest/job/epoch-proving-job.d.ts +25 -17
  29. package/dest/job/epoch-proving-job.d.ts.map +1 -1
  30. package/dest/job/epoch-proving-job.js +155 -51
  31. package/dest/metrics.d.ts +29 -5
  32. package/dest/metrics.d.ts.map +1 -1
  33. package/dest/metrics.js +141 -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 +15 -2
  37. package/dest/monitors/index.d.ts +1 -1
  38. package/dest/prover-node-publisher.d.ts +10 -12
  39. package/dest/prover-node-publisher.d.ts.map +1 -1
  40. package/dest/prover-node-publisher.js +62 -62
  41. package/dest/prover-node.d.ts +48 -43
  42. package/dest/prover-node.d.ts.map +1 -1
  43. package/dest/prover-node.js +175 -105
  44. package/dest/prover-publisher-factory.d.ts +21 -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 +108 -24
  57. package/src/factory.ts +163 -43
  58. package/src/index.ts +1 -1
  59. package/src/job/epoch-proving-job-data.ts +77 -0
  60. package/src/job/epoch-proving-job.ts +222 -52
  61. package/src/metrics.ts +135 -37
  62. package/src/monitors/epoch-monitor.ts +18 -6
  63. package/src/prover-node-publisher.ts +96 -88
  64. package/src/prover-node.ts +213 -136
  65. package/src/prover-publisher-factory.ts +37 -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/dest/metrics.js CHANGED
@@ -1,83 +1,187 @@
1
1
  import { createLogger } from '@aztec/foundation/log';
2
2
  import { Attributes, Metrics, ValueType } from '@aztec/telemetry-client';
3
- import { formatEther } from 'viem';
4
- export class ProverNodeMetrics {
5
- client;
3
+ import { formatEther, formatUnits } from 'viem';
4
+ export class ProverNodeJobMetrics {
5
+ meter;
6
+ tracer;
6
7
  logger;
7
8
  proverEpochExecutionDuration;
8
9
  provingJobDuration;
9
10
  provingJobBlocks;
10
11
  provingJobTransactions;
11
- gasPrice;
12
- txCount;
13
- txDuration;
14
- txGas;
15
- txCalldataSize;
16
- txCalldataGas;
17
- txBlobDataGasUsed;
18
- txBlobDataGasCost;
19
- senderBalance;
20
- constructor(client, name = 'ProverNode', logger = createLogger('prover-node:publisher:metrics')){
21
- this.client = client;
12
+ constructor(meter, tracer, logger = createLogger('prover-node:publisher:metrics')){
13
+ this.meter = meter;
14
+ this.tracer = tracer;
22
15
  this.logger = logger;
23
- const meter = client.getMeter(name);
24
- this.proverEpochExecutionDuration = meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION, {
16
+ this.proverEpochExecutionDuration = this.meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION, {
25
17
  description: 'Duration of execution of an epoch by the prover',
26
18
  unit: 'ms',
27
19
  valueType: ValueType.INT
28
20
  });
29
- this.provingJobDuration = meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION, {
21
+ this.provingJobDuration = this.meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION, {
30
22
  description: 'Duration of proving job',
31
23
  unit: 's',
32
24
  valueType: ValueType.DOUBLE
33
25
  });
34
- this.provingJobBlocks = meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS, {
26
+ this.provingJobBlocks = this.meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS, {
35
27
  description: 'Number of blocks in a proven epoch',
36
28
  valueType: ValueType.INT
37
29
  });
38
- this.provingJobTransactions = meter.createGauge(Metrics.PROVER_NODE_JOB_TRANSACTIONS, {
30
+ this.provingJobTransactions = this.meter.createGauge(Metrics.PROVER_NODE_JOB_TRANSACTIONS, {
39
31
  description: 'Number of transactions in a proven epoch',
40
32
  valueType: ValueType.INT
41
33
  });
42
- this.gasPrice = meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE, {
34
+ }
35
+ recordProvingJob(executionTimeMs, totalTimeMs, numBlocks, numTxs) {
36
+ this.proverEpochExecutionDuration.record(Math.ceil(executionTimeMs));
37
+ this.provingJobDuration.record(totalTimeMs / 1000);
38
+ this.provingJobBlocks.record(Math.floor(numBlocks));
39
+ this.provingJobTransactions.record(Math.floor(numTxs));
40
+ }
41
+ }
42
+ export class ProverNodeRewardsMetrics {
43
+ meter;
44
+ coinbase;
45
+ rollup;
46
+ logger;
47
+ rewards;
48
+ accumulatedRewards;
49
+ prevEpoch;
50
+ proofSubmissionEpochs;
51
+ constructor(meter, coinbase, rollup, logger = createLogger('prover-node:publisher:metrics')){
52
+ this.meter = meter;
53
+ this.coinbase = coinbase;
54
+ this.rollup = rollup;
55
+ this.logger = logger;
56
+ this.prevEpoch = -1n;
57
+ this.proofSubmissionEpochs = 0;
58
+ this.observe = async (observer)=>{
59
+ const epoch = await this.rollup.getCurrentEpochNumber();
60
+ if (epoch > this.proofSubmissionEpochs) {
61
+ // look at the prev epoch so that we get an accurate value, after proof submission window has closed
62
+ // For example, if proof submission window is 1 epoch, and we are in epoch 2, we should be looking at epoch 0.
63
+ // Similarly, if the proof submission window is 0, and we are in epoch 1, we should be looking at epoch 0.
64
+ const closedEpoch = BigInt(epoch) - BigInt(this.proofSubmissionEpochs) - 1n;
65
+ const rewards = await this.rollup.getSpecificProverRewardsForEpoch(closedEpoch, this.coinbase);
66
+ const fmt = parseFloat(formatUnits(rewards, 18));
67
+ observer.observe(this.rewards, fmt, {
68
+ [Attributes.COINBASE]: this.coinbase.toString()
69
+ });
70
+ // only accumulate once per epoch
71
+ if (closedEpoch > this.prevEpoch) {
72
+ this.prevEpoch = closedEpoch;
73
+ this.accumulatedRewards.add(fmt, {
74
+ [Attributes.COINBASE]: this.coinbase.toString()
75
+ });
76
+ }
77
+ }
78
+ };
79
+ this.rewards = this.meter.createObservableGauge(Metrics.PROVER_NODE_REWARDS_PER_EPOCH, {
80
+ valueType: ValueType.DOUBLE,
81
+ description: 'The rewards earned'
82
+ });
83
+ this.accumulatedRewards = this.meter.createUpDownCounter(Metrics.PROVER_NODE_REWARDS_TOTAL, {
84
+ valueType: ValueType.DOUBLE,
85
+ description: 'The rewards earned (total)'
86
+ });
87
+ }
88
+ async start() {
89
+ const proofSubmissionEpochs = await this.rollup.getProofSubmissionEpochs();
90
+ this.proofSubmissionEpochs = Number(proofSubmissionEpochs);
91
+ this.meter.addBatchObservableCallback(this.observe, [
92
+ this.rewards
93
+ ]);
94
+ }
95
+ stop() {
96
+ this.meter.removeBatchObservableCallback(this.observe, [
97
+ this.rewards
98
+ ]);
99
+ }
100
+ observe;
101
+ }
102
+ export class ProverNodePublisherMetrics {
103
+ client;
104
+ logger;
105
+ gasPrice;
106
+ txCount;
107
+ txDuration;
108
+ txGas;
109
+ txCalldataSize;
110
+ txCalldataGas;
111
+ txBlobDataGasUsed;
112
+ txBlobDataGasCost;
113
+ txTotalFee;
114
+ senderBalance;
115
+ meter;
116
+ constructor(client, name = 'ProverNode', logger = createLogger('prover-node:publisher:metrics')){
117
+ this.client = client;
118
+ this.logger = logger;
119
+ this.meter = client.getMeter(name);
120
+ this.gasPrice = this.meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE, {
43
121
  description: 'The gas price used for transactions',
44
122
  unit: 'gwei',
45
123
  valueType: ValueType.DOUBLE
46
124
  });
47
- this.txCount = meter.createUpDownCounter(Metrics.L1_PUBLISHER_TX_COUNT, {
125
+ this.txCount = this.meter.createUpDownCounter(Metrics.L1_PUBLISHER_TX_COUNT, {
48
126
  description: 'The number of transactions processed'
49
127
  });
50
- this.txDuration = meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION, {
128
+ this.txDuration = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION, {
51
129
  description: 'The duration of transaction processing',
52
130
  unit: 'ms',
53
131
  valueType: ValueType.INT
54
132
  });
55
- this.txGas = meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS, {
133
+ this.txGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS, {
56
134
  description: 'The gas consumed by transactions',
57
135
  unit: 'gas',
58
136
  valueType: ValueType.INT
59
137
  });
60
- this.txCalldataSize = meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE, {
138
+ this.txCalldataSize = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE, {
61
139
  description: 'The size of the calldata in transactions',
62
140
  unit: 'By',
63
141
  valueType: ValueType.INT
64
142
  });
65
- this.txCalldataGas = meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS, {
143
+ this.txCalldataGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS, {
66
144
  description: 'The gas consumed by the calldata in transactions',
67
145
  unit: 'gas',
68
146
  valueType: ValueType.INT
69
147
  });
70
- this.txBlobDataGasUsed = meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED, {
148
+ this.txBlobDataGasUsed = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED, {
71
149
  description: 'The amount of blob gas used in transactions',
72
150
  unit: 'gas',
73
151
  valueType: ValueType.INT
74
152
  });
75
- this.txBlobDataGasCost = meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST, {
153
+ this.txBlobDataGasCost = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST, {
76
154
  description: 'The gas cost of blobs in transactions',
77
155
  unit: 'gwei',
78
156
  valueType: ValueType.INT
79
157
  });
80
- this.senderBalance = meter.createGauge(Metrics.L1_PUBLISHER_BALANCE, {
158
+ this.txTotalFee = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_TOTAL_FEE, {
159
+ description: 'How much L1 tx costs',
160
+ unit: 'gwei',
161
+ valueType: ValueType.DOUBLE,
162
+ advice: {
163
+ explicitBucketBoundaries: [
164
+ 0.001,
165
+ 0.002,
166
+ 0.004,
167
+ 0.008,
168
+ 0.01,
169
+ 0.02,
170
+ 0.04,
171
+ 0.08,
172
+ 0.1,
173
+ 0.2,
174
+ 0.4,
175
+ 0.8,
176
+ 1,
177
+ 1.2,
178
+ 1.4,
179
+ 1.8,
180
+ 2
181
+ ]
182
+ }
183
+ });
184
+ this.senderBalance = this.meter.createGauge(Metrics.L1_PUBLISHER_BALANCE, {
81
185
  unit: 'eth',
82
186
  description: 'The balance of the sender address',
83
187
  valueType: ValueType.DOUBLE
@@ -92,12 +196,6 @@ export class ProverNodeMetrics {
92
196
  recordSubmitProof(durationMs, stats) {
93
197
  this.recordTx(durationMs, stats);
94
198
  }
95
- recordProvingJob(executionTimeMs, totalTimeMs, numBlocks, numTxs) {
96
- this.proverEpochExecutionDuration.record(Math.ceil(executionTimeMs));
97
- this.provingJobDuration.record(totalTimeMs / 1000);
98
- this.provingJobBlocks.record(Math.floor(numBlocks));
99
- this.provingJobTransactions.record(Math.floor(numTxs));
100
- }
101
199
  recordSenderBalance(wei, senderAddress) {
102
200
  const eth = parseFloat(formatEther(wei, 'wei'));
103
201
  this.senderBalance.record(eth, {
@@ -122,7 +220,15 @@ export class ProverNodeMetrics {
122
220
  this.txBlobDataGasUsed.record(Number(stats.blobGasUsed), attributes);
123
221
  try {
124
222
  this.gasPrice.record(parseInt(formatEther(stats.gasPrice, 'gwei'), 10));
125
- } catch (e) {
223
+ } catch {
224
+ // ignore
225
+ }
226
+ const executionFee = stats.gasUsed * stats.gasPrice;
227
+ const blobFee = stats.blobGasUsed * stats.blobDataGas;
228
+ const totalFee = executionFee + blobFee;
229
+ try {
230
+ this.txTotalFee.record(parseFloat(formatEther(totalFee)));
231
+ } catch {
126
232
  // ignore
127
233
  }
128
234
  }
@@ -1,8 +1,9 @@
1
+ import { EpochNumber } from '@aztec/foundation/branded-types';
1
2
  import type { L2BlockSource } from '@aztec/stdlib/block';
2
3
  import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
3
4
  import { type TelemetryClient, type Traceable, type Tracer } from '@aztec/telemetry-client';
4
5
  export interface EpochMonitorHandler {
5
- handleEpochReadyToProve(epochNumber: bigint): Promise<void>;
6
+ handleEpochReadyToProve(epochNumber: EpochNumber): Promise<boolean>;
6
7
  }
7
8
  /**
8
9
  * Fires an event when a new epoch ready to prove is detected.
@@ -26,9 +27,11 @@ export declare class EpochMonitor implements Traceable {
26
27
  private latestEpochNumber;
27
28
  constructor(l2BlockSource: L2BlockSource, l1Constants: Pick<L1RollupConstants, 'epochDuration'>, options: {
28
29
  pollingIntervalMs: number;
30
+ provingDelayMs?: number;
29
31
  }, telemetry?: TelemetryClient);
30
32
  static create(l2BlockSource: L2BlockSource, options: {
31
33
  pollingIntervalMs: number;
34
+ provingDelayMs?: number;
32
35
  }, telemetry?: TelemetryClient): Promise<EpochMonitor>;
33
36
  start(handler: EpochMonitorHandler): void;
34
37
  /** Exposed for testing */
@@ -37,4 +40,4 @@ export declare class EpochMonitor implements Traceable {
37
40
  work(): Promise<void>;
38
41
  private getEpochNumberToProve;
39
42
  }
40
- //# sourceMappingURL=epoch-monitor.d.ts.map
43
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2gtbW9uaXRvci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21vbml0b3JzL2Vwb2NoLW1vbml0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBSTlELE9BQU8sS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUFrQixNQUFNLDZCQUE2QixDQUFDO0FBQ3JGLE9BQU8sRUFDTCxLQUFLLGVBQWUsRUFDcEIsS0FBSyxTQUFTLEVBQ2QsS0FBSyxNQUFNLEVBR1osTUFBTSx5QkFBeUIsQ0FBQztBQUVqQyxNQUFNLFdBQVcsbUJBQW1CO0lBQ2xDLHVCQUF1QixDQUFDLFdBQVcsRUFBRSxXQUFXLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0NBQ3JFO0FBRUQ7Ozs7Ozs7Ozs7R0FVRztBQUNILHFCQUFhLFlBQWEsWUFBVyxTQUFTO0lBUzFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsYUFBYTtJQUM5QixPQUFPLENBQUMsUUFBUSxDQUFDLFdBQVc7SUFDNUIsT0FBTyxDQUFDLE9BQU87SUFWakIsT0FBTyxDQUFDLGNBQWMsQ0FBaUI7SUFDdkMsT0FBTyxDQUFDLEdBQUcsQ0FBNkM7SUFDeEQsU0FBZ0IsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUUvQixPQUFPLENBQUMsT0FBTyxDQUFrQztJQUNqRCxPQUFPLENBQUMsaUJBQWlCLENBQTBCO0lBRW5ELFlBQ21CLGFBQWEsRUFBRSxhQUFhLEVBQzVCLFdBQVcsRUFBRSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsZUFBZSxDQUFDLEVBQzlELE9BQU8sRUFBRTtRQUFFLGlCQUFpQixFQUFFLE1BQU0sQ0FBQztRQUFDLGNBQWMsQ0FBQyxFQUFFLE1BQU0sQ0FBQTtLQUFFLEVBQ3ZFLFNBQVMsR0FBRSxlQUFzQyxFQU9sRDtJQUVELE9BQW9CLE1BQU0sQ0FDeEIsYUFBYSxFQUFFLGFBQWEsRUFDNUIsT0FBTyxFQUFFO1FBQUUsaUJBQWlCLEVBQUUsTUFBTSxDQUFDO1FBQUMsY0FBYyxDQUFDLEVBQUUsTUFBTSxDQUFBO0tBQUUsRUFDL0QsU0FBUyxHQUFFLGVBQXNDLEdBQ2hELE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FHdkI7SUFFTSxLQUFLLENBQUMsT0FBTyxFQUFFLG1CQUFtQixRQUl4QztJQUVELDBCQUEwQjtJQUNuQixVQUFVLENBQUMsT0FBTyxFQUFFLG1CQUFtQixRQUU3QztJQUVZLElBQUksa0JBR2hCO0lBR1ksSUFBSSxrQkEyQmhCO1lBRWEscUJBQXFCO0NBWXBDIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"epoch-monitor.d.ts","sourceRoot":"","sources":["../../src/monitors/epoch-monitor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,KAAK,iBAAiB,EAAkB,MAAM,6BAA6B,CAAC;AACrF,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,MAAM,EAGZ,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,mBAAmB;IAClC,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAED;;;;;;;;;;GAUG;AACH,qBAAa,YAAa,YAAW,SAAS;IAS1C,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,OAAO;IAVjB,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,GAAG,CAA6C;IACxD,SAAgB,MAAM,EAAE,MAAM,CAAC;IAE/B,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,iBAAiB,CAAqB;gBAG3B,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,EAC9D,OAAO,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAA;KAAE,EAC9C,SAAS,GAAE,eAAsC;WAM/B,MAAM,CACxB,aAAa,EAAE,aAAa,EAC5B,OAAO,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAA;KAAE,EACtC,SAAS,GAAE,eAAsC,GAChD,OAAO,CAAC,YAAY,CAAC;IAKjB,KAAK,CAAC,OAAO,EAAE,mBAAmB;IAMzC,0BAA0B;IACnB,UAAU,CAAC,OAAO,EAAE,mBAAmB;IAIjC,IAAI;IAMJ,IAAI;YAsBH,qBAAqB;CAYpC"}
1
+ {"version":3,"file":"epoch-monitor.d.ts","sourceRoot":"","sources":["../../src/monitors/epoch-monitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAI9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,KAAK,iBAAiB,EAAkB,MAAM,6BAA6B,CAAC;AACrF,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,MAAM,EAGZ,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,mBAAmB;IAClC,uBAAuB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACrE;AAED;;;;;;;;;;GAUG;AACH,qBAAa,YAAa,YAAW,SAAS;IAS1C,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,OAAO;IAVjB,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,GAAG,CAA6C;IACxD,SAAgB,MAAM,EAAE,MAAM,CAAC;IAE/B,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,iBAAiB,CAA0B;IAEnD,YACmB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,EAC9D,OAAO,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,EACvE,SAAS,GAAE,eAAsC,EAOlD;IAED,OAAoB,MAAM,CACxB,aAAa,EAAE,aAAa,EAC5B,OAAO,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,EAC/D,SAAS,GAAE,eAAsC,GAChD,OAAO,CAAC,YAAY,CAAC,CAGvB;IAEM,KAAK,CAAC,OAAO,EAAE,mBAAmB,QAIxC;IAED,0BAA0B;IACnB,UAAU,CAAC,OAAO,EAAE,mBAAmB,QAE7C;IAEY,IAAI,kBAGhB;IAGY,IAAI,kBA2BhB;YAEa,qBAAqB;CAYpC"}
@@ -6,6 +6,7 @@ function _ts_decorate(decorators, target, key, desc) {
6
6
  }
7
7
  import { createLogger } from '@aztec/foundation/log';
8
8
  import { RunningPromise } from '@aztec/foundation/running-promise';
9
+ import { sleep } from '@aztec/foundation/sleep';
9
10
  import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
10
11
  import { getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
11
12
  /**
@@ -34,6 +35,9 @@ import { getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
34
35
  this.log = createLogger('prover-node:epoch-monitor');
35
36
  this.tracer = telemetry.getTracer('EpochMonitor');
36
37
  this.runningPromise = new RunningPromise(this.work.bind(this), this.log, this.options.pollingIntervalMs);
38
+ if (this.options.provingDelayMs) {
39
+ this.log.warn(`Prover node epoch monitor running with delay of ${this.options.provingDelayMs}ms`);
40
+ }
37
41
  }
38
42
  static async create(l2BlockSource, options, telemetry = getTelemetryClient()) {
39
43
  const l1Constants = await l2BlockSource.getL1Constants();
@@ -53,6 +57,10 @@ import { getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
53
57
  }
54
58
  async work() {
55
59
  const { epochToProve, blockNumber, slotNumber } = await this.getEpochNumberToProve();
60
+ this.log.debug(`Epoch to prove: ${epochToProve}`, {
61
+ blockNumber,
62
+ slotNumber
63
+ });
56
64
  if (epochToProve === undefined) {
57
65
  this.log.trace(`Next block to prove ${blockNumber} not yet mined`, {
58
66
  blockNumber
@@ -76,9 +84,14 @@ import { getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
76
84
  });
77
85
  return;
78
86
  }
87
+ if (this.options.provingDelayMs) {
88
+ this.log.debug(`Waiting ${this.options.provingDelayMs}ms before proving epoch ${epochToProve}`);
89
+ await sleep(this.options.provingDelayMs);
90
+ }
79
91
  this.log.debug(`Epoch ${epochToProve} is ready to be proven`);
80
- await this.handler?.handleEpochReadyToProve(epochToProve);
81
- this.latestEpochNumber = epochToProve;
92
+ if (await this.handler?.handleEpochReadyToProve(epochToProve)) {
93
+ this.latestEpochNumber = epochToProve;
94
+ }
82
95
  }
83
96
  async getEpochNumberToProve() {
84
97
  const lastBlockProven = await this.l2BlockSource.getProvenBlockNumber();
@@ -1,2 +1,2 @@
1
1
  export * from './epoch-monitor.js';
2
- //# sourceMappingURL=index.d.ts.map
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tb25pdG9ycy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLG9CQUFvQixDQUFDIn0=
@@ -1,22 +1,19 @@
1
+ import { BatchedBlob } from '@aztec/blob-lib';
1
2
  import { AZTEC_MAX_EPOCH_DURATION } from '@aztec/constants';
2
- import type { L1TxUtils, RollupContract } from '@aztec/ethereum';
3
+ import type { L1TxUtils, RollupContract, ViemCommitteeAttestation } from '@aztec/ethereum';
4
+ import { EpochNumber } from '@aztec/foundation/branded-types';
3
5
  import { EthAddress } from '@aztec/foundation/eth-address';
4
6
  import { Fr } from '@aztec/foundation/fields';
5
- import { type Tuple } from '@aztec/foundation/serialize';
7
+ import type { Tuple } from '@aztec/foundation/serialize';
6
8
  import type { PublisherConfig, TxSenderConfig } from '@aztec/sequencer-client';
7
9
  import type { Proof } from '@aztec/stdlib/proofs';
8
10
  import type { FeeRecipient, RootRollupPublicInputs } from '@aztec/stdlib/rollup';
9
11
  import { type TelemetryClient } from '@aztec/telemetry-client';
10
- /**
11
- * Stats for a sent transaction.
12
- */
13
12
  /** Arguments to the submitEpochProof method of the rollup contract */
14
13
  export type L1SubmitEpochProofArgs = {
15
14
  epochSize: number;
16
15
  previousArchive: Fr;
17
16
  endArchive: Fr;
18
- previousBlockHash: Fr;
19
- endBlockHash: Fr;
20
17
  endTimestamp: Fr;
21
18
  outHash: Fr;
22
19
  proverId: Fr;
@@ -24,8 +21,6 @@ export type L1SubmitEpochProofArgs = {
24
21
  proof: Proof;
25
22
  };
26
23
  export declare class ProverNodePublisher {
27
- private interruptibleSleep;
28
- private sleepTimeMs;
29
24
  private interrupted;
30
25
  private metrics;
31
26
  protected log: import("@aztec/foundation/log").Logger;
@@ -36,6 +31,7 @@ export declare class ProverNodePublisher {
36
31
  l1TxUtils: L1TxUtils;
37
32
  telemetry?: TelemetryClient;
38
33
  });
34
+ getRollupContract(): RollupContract;
39
35
  /**
40
36
  * Calling `interrupt` will cause any in progress call to `publishRollup` to return `false` asap.
41
37
  * Be warned, the call may return false even if the tx subsequently gets successfully mined.
@@ -47,15 +43,17 @@ export declare class ProverNodePublisher {
47
43
  restart(): void;
48
44
  getSenderAddress(): EthAddress;
49
45
  submitEpochProof(args: {
50
- epochNumber: number;
46
+ epochNumber: EpochNumber;
51
47
  fromBlock: number;
52
48
  toBlock: number;
53
49
  publicInputs: RootRollupPublicInputs;
54
50
  proof: Proof;
51
+ batchedBlobInputs: BatchedBlob;
52
+ attestations: ViemCommitteeAttestation[];
55
53
  }): Promise<boolean>;
56
54
  private validateEpochProofSubmission;
57
55
  private sendSubmitEpochProofTx;
56
+ private getEpochProofPublicInputsArgs;
58
57
  private getSubmitEpochProofArgs;
59
- protected sleepOrInterrupted(): Promise<void>;
60
58
  }
61
- //# sourceMappingURL=prover-node-publisher.d.ts.map
59
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmVyLW5vZGUtcHVibGlzaGVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcHJvdmVyLW5vZGUtcHVibGlzaGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQThCLE1BQU0saUJBQWlCLENBQUM7QUFDMUUsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDNUQsT0FBTyxLQUFLLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRTNGLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUU5RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDM0QsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRTlDLE9BQU8sS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBR3pELE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUvRSxPQUFPLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUVqRixPQUFPLEVBQUUsS0FBSyxlQUFlLEVBQXNCLE1BQU0seUJBQXlCLENBQUM7QUFPbkYsc0VBQXNFO0FBQ3RFLE1BQU0sTUFBTSxzQkFBc0IsR0FBRztJQUNuQyxTQUFTLEVBQUUsTUFBTSxDQUFDO0lBQ2xCLGVBQWUsRUFBRSxFQUFFLENBQUM7SUFDcEIsVUFBVSxFQUFFLEVBQUUsQ0FBQztJQUNmLFlBQVksRUFBRSxFQUFFLENBQUM7SUFDakIsT0FBTyxFQUFFLEVBQUUsQ0FBQztJQUNaLFFBQVEsRUFBRSxFQUFFLENBQUM7SUFDYixJQUFJLEVBQUUsS0FBSyxDQUFDLFlBQVksRUFBRSxPQUFPLHdCQUF3QixDQUFDLENBQUM7SUFDM0QsS0FBSyxFQUFFLEtBQUssQ0FBQztDQUNkLENBQUM7QUFFRixxQkFBYSxtQkFBbUI7SUFDOUIsT0FBTyxDQUFDLFdBQVcsQ0FBUztJQUM1QixPQUFPLENBQUMsT0FBTyxDQUE2QjtJQUU1QyxTQUFTLENBQUMsR0FBRyx5Q0FBK0M7SUFFNUQsU0FBUyxDQUFDLGNBQWMsRUFBRSxjQUFjLENBQUM7SUFFekMsU0FBZ0IsU0FBUyxFQUFFLFNBQVMsQ0FBQztJQUVyQyxZQUNFLE1BQU0sRUFBRSxjQUFjLEdBQUcsZUFBZSxFQUN4QyxJQUFJLEVBQUU7UUFDSixjQUFjLEVBQUUsY0FBYyxDQUFDO1FBQy9CLFNBQVMsRUFBRSxTQUFTLENBQUM7UUFDckIsU0FBUyxDQUFDLEVBQUUsZUFBZSxDQUFDO0tBQzdCLEVBUUY7SUFFTSxpQkFBaUIsbUJBRXZCO0lBRUQ7Ozs7O09BS0c7SUFDSSxTQUFTLFNBR2Y7SUFFRCx3REFBd0Q7SUFDakQsT0FBTyxTQUdiO0lBRU0sZ0JBQWdCLGVBRXRCO0lBRVksZ0JBQWdCLENBQUMsSUFBSSxFQUFFO1FBQ2xDLFdBQVcsRUFBRSxXQUFXLENBQUM7UUFDekIsU0FBUyxFQUFFLE1BQU0sQ0FBQztRQUNsQixPQUFPLEVBQUUsTUFBTSxDQUFDO1FBQ2hCLFlBQVksRUFBRSxzQkFBc0IsQ0FBQztRQUNyQyxLQUFLLEVBQUUsS0FBSyxDQUFDO1FBQ2IsaUJBQWlCLEVBQUUsV0FBVyxDQUFDO1FBQy9CLFlBQVksRUFBRSx3QkFBd0IsRUFBRSxDQUFDO0tBQzFDLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQWdEbkI7WUFFYSw0QkFBNEI7WUEyRDVCLHNCQUFzQjtJQXlDcEMsT0FBTyxDQUFDLDZCQUE2QjtJQXlCckMsT0FBTyxDQUFDLHVCQUF1QjtDQXVCaEMifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"prover-node-publisher.d.ts","sourceRoot":"","sources":["../src/prover-node-publisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AACvF,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAE9C,OAAO,EAAE,KAAK,KAAK,EAAqB,MAAM,6BAA6B,CAAC;AAI5E,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEjF,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAMnF;;GAEG;AACH,sEAAsE;AACtE,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,EAAE,CAAC;IACpB,UAAU,EAAE,EAAE,CAAC;IACf,iBAAiB,EAAE,EAAE,CAAC;IACtB,YAAY,EAAE,EAAE,CAAC;IACjB,YAAY,EAAE,EAAE,CAAC;IACjB,OAAO,EAAE,EAAE,CAAC;IACZ,QAAQ,EAAE,EAAE,CAAC;IACb,IAAI,EAAE,KAAK,CAAC,YAAY,EAAE,OAAO,wBAAwB,CAAC,CAAC;IAC3D,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,kBAAkB,CAA4B;IACtD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAoB;IAEnC,SAAS,CAAC,GAAG,yCAA+C;IAE5D,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC;IAEzC,SAAgB,SAAS,EAAE,SAAS,CAAC;gBAGnC,MAAM,EAAE,cAAc,GAAG,eAAe,EACxC,IAAI,EAAE;QACJ,cAAc,EAAE,cAAc,CAAC;QAC/B,SAAS,EAAE,SAAS,CAAC;QACrB,SAAS,CAAC,EAAE,eAAe,CAAC;KAC7B;IAYH;;;;;OAKG;IACI,SAAS;IAKhB,wDAAwD;IACjD,OAAO;IAIP,gBAAgB;IAIV,gBAAgB,CAAC,IAAI,EAAE;QAClC,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,sBAAsB,CAAC;QACrC,KAAK,EAAE,KAAK,CAAC;KACd,GAAG,OAAO,CAAC,OAAO,CAAC;YAgDN,4BAA4B;YAyD5B,sBAAsB;IAoDpC,OAAO,CAAC,uBAAuB;cA+Bf,kBAAkB;CAGnC"}
1
+ {"version":3,"file":"prover-node-publisher.d.ts","sourceRoot":"","sources":["../src/prover-node-publisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA8B,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE3F,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAE9C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAGzD,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE/E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEjF,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAOnF,sEAAsE;AACtE,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,EAAE,CAAC;IACpB,UAAU,EAAE,EAAE,CAAC;IACf,YAAY,EAAE,EAAE,CAAC;IACjB,OAAO,EAAE,EAAE,CAAC;IACZ,QAAQ,EAAE,EAAE,CAAC;IACb,IAAI,EAAE,KAAK,CAAC,YAAY,EAAE,OAAO,wBAAwB,CAAC,CAAC;IAC3D,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAA6B;IAE5C,SAAS,CAAC,GAAG,yCAA+C;IAE5D,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC;IAEzC,SAAgB,SAAS,EAAE,SAAS,CAAC;IAErC,YACE,MAAM,EAAE,cAAc,GAAG,eAAe,EACxC,IAAI,EAAE;QACJ,cAAc,EAAE,cAAc,CAAC;QAC/B,SAAS,EAAE,SAAS,CAAC;QACrB,SAAS,CAAC,EAAE,eAAe,CAAC;KAC7B,EAQF;IAEM,iBAAiB,mBAEvB;IAED;;;;;OAKG;IACI,SAAS,SAGf;IAED,wDAAwD;IACjD,OAAO,SAGb;IAEM,gBAAgB,eAEtB;IAEY,gBAAgB,CAAC,IAAI,EAAE;QAClC,WAAW,EAAE,WAAW,CAAC;QACzB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,sBAAsB,CAAC;QACrC,KAAK,EAAE,KAAK,CAAC;QACb,iBAAiB,EAAE,WAAW,CAAC;QAC/B,YAAY,EAAE,wBAAwB,EAAE,CAAC;KAC1C,GAAG,OAAO,CAAC,OAAO,CAAC,CAgDnB;YAEa,4BAA4B;YA2D5B,sBAAsB;IAyCpC,OAAO,CAAC,6BAA6B;IAyBrC,OAAO,CAAC,uBAAuB;CAuBhC"}
@@ -1,31 +1,32 @@
1
- import { AGGREGATION_OBJECT_LENGTH, AZTEC_MAX_EPOCH_DURATION } from '@aztec/constants';
1
+ import { getEthBlobEvaluationInputs } from '@aztec/blob-lib';
2
+ import { AZTEC_MAX_EPOCH_DURATION } from '@aztec/constants';
2
3
  import { makeTuple } from '@aztec/foundation/array';
3
- import { areArraysEqual, times } from '@aztec/foundation/collection';
4
+ import { areArraysEqual } from '@aztec/foundation/collection';
4
5
  import { EthAddress } from '@aztec/foundation/eth-address';
5
6
  import { Fr } from '@aztec/foundation/fields';
6
7
  import { createLogger } from '@aztec/foundation/log';
7
- import { serializeToBuffer } from '@aztec/foundation/serialize';
8
- import { InterruptibleSleep } from '@aztec/foundation/sleep';
9
8
  import { Timer } from '@aztec/foundation/timer';
10
9
  import { RollupAbi } from '@aztec/l1-artifacts';
10
+ import { CommitteeAttestation, CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
11
11
  import { getTelemetryClient } from '@aztec/telemetry-client';
12
+ import { inspect } from 'util';
12
13
  import { encodeFunctionData } from 'viem';
13
- import { ProverNodeMetrics } from './metrics.js';
14
+ import { ProverNodePublisherMetrics } from './metrics.js';
14
15
  export class ProverNodePublisher {
15
- interruptibleSleep = new InterruptibleSleep();
16
- sleepTimeMs;
17
16
  interrupted = false;
18
17
  metrics;
19
18
  log = createLogger('prover-node:l1-tx-publisher');
20
19
  rollupContract;
21
20
  l1TxUtils;
22
21
  constructor(config, deps){
23
- this.sleepTimeMs = config?.l1PublishRetryIntervalMS ?? 60_000;
24
22
  const telemetry = deps.telemetry ?? getTelemetryClient();
25
- this.metrics = new ProverNodeMetrics(telemetry, 'ProverNode');
23
+ this.metrics = new ProverNodePublisherMetrics(telemetry, 'ProverNode');
26
24
  this.rollupContract = deps.rollupContract;
27
25
  this.l1TxUtils = deps.l1TxUtils;
28
26
  }
27
+ getRollupContract() {
28
+ return this.rollupContract;
29
+ }
29
30
  /**
30
31
  * Calling `interrupt` will cause any in progress call to `publishRollup` to return `false` asap.
31
32
  * Be warned, the call may return false even if the tx subsequently gets successfully mined.
@@ -33,13 +34,14 @@ export class ProverNodePublisher {
33
34
  * A call to `restart` is required before you can continue publishing.
34
35
  */ interrupt() {
35
36
  this.interrupted = true;
36
- this.interruptibleSleep.interrupt();
37
+ this.l1TxUtils.interrupt();
37
38
  }
38
39
  /** Restarts the publisher after calling `interrupt`. */ restart() {
39
40
  this.interrupted = false;
41
+ this.l1TxUtils.restart();
40
42
  }
41
43
  getSenderAddress() {
42
- return EthAddress.fromString(this.l1TxUtils.getSenderAddress());
44
+ return this.l1TxUtils.getSenderAddress();
43
45
  }
44
46
  async submitEpochProof(args) {
45
47
  const { epochNumber, fromBlock, toBlock } = args;
@@ -57,12 +59,12 @@ export class ProverNodePublisher {
57
59
  return false;
58
60
  }
59
61
  try {
60
- this.metrics.recordSenderBalance(await this.l1TxUtils.getSenderBalance(), this.l1TxUtils.getSenderAddress());
62
+ this.metrics.recordSenderBalance(await this.l1TxUtils.getSenderBalance(), this.l1TxUtils.getSenderAddress().toString());
61
63
  } catch (err) {
62
64
  this.log.warn(`Failed to record the ETH balance of the prover node: ${err}`);
63
65
  }
64
66
  // Tx was mined successfully
65
- if (txReceipt.status) {
67
+ if (txReceipt.status === 'success') {
66
68
  const tx = await this.l1TxUtils.getTransactionStats(txReceipt.transactionHash);
67
69
  const stats = {
68
70
  gasPrice: txReceipt.effectiveGasPrice,
@@ -83,45 +85,42 @@ export class ProverNodePublisher {
83
85
  return true;
84
86
  }
85
87
  this.metrics.recordFailedTx();
86
- this.log.error(`Rollup.submitEpochProof tx status failed: ${txReceipt.transactionHash}`, ctx);
87
- await this.sleepOrInterrupted();
88
+ this.log.error(`Rollup.submitEpochProof tx status failed ${txReceipt.transactionHash}`, undefined, ctx);
88
89
  }
89
- this.log.verbose('L2 block data syncing interrupted while processing blocks.', ctx);
90
+ this.log.verbose('L2 block data syncing interrupted', ctx);
90
91
  return false;
91
92
  }
92
93
  async validateEpochProofSubmission(args) {
93
- const { fromBlock, toBlock, publicInputs, proof } = args;
94
+ const { fromBlock, toBlock, publicInputs, batchedBlobInputs } = args;
94
95
  // Check that the block numbers match the expected epoch to be proven
95
- const { pendingBlockNumber: pending, provenBlockNumber: proven } = await this.rollupContract.getTips();
96
- if (proven !== BigInt(fromBlock) - 1n) {
96
+ const { pending, proven } = await this.rollupContract.getTips();
97
+ // Don't publish if proven is beyond our toBlock, pointless to do so
98
+ if (proven > BigInt(toBlock)) {
97
99
  throw new Error(`Cannot submit epoch proof for ${fromBlock}-${toBlock} as proven block is ${proven}`);
98
100
  }
101
+ // toBlock can't be greater than pending
99
102
  if (toBlock > pending) {
100
103
  throw new Error(`Cannot submit epoch proof for ${fromBlock}-${toBlock} as pending block is ${pending}`);
101
104
  }
102
- // Check the block hash and archive for the immediate block before the epoch
103
- const blockLog = await this.rollupContract.getBlock(proven);
104
- if (publicInputs.previousArchive.root.toString() !== blockLog.archive) {
105
- throw new Error(`Previous archive root mismatch: ${publicInputs.previousArchive.root.toString()} !== ${blockLog.archive}`);
106
- }
107
- // TODO: Remove zero check once we inject the proper zero blockhash
108
- if (blockLog.blockHash !== Fr.ZERO.toString() && publicInputs.previousBlockHash.toString() !== blockLog.blockHash) {
109
- throw new Error(`Previous block hash mismatch: ${publicInputs.previousBlockHash.toString()} !== ${blockLog.blockHash}`);
105
+ // Check the archive for the immediate block before the epoch
106
+ const blockLog = await this.rollupContract.getCheckpoint(BigInt(fromBlock - 1));
107
+ if (publicInputs.previousArchiveRoot.toString() !== blockLog.archive) {
108
+ throw new Error(`Previous archive root mismatch: ${publicInputs.previousArchiveRoot.toString()} !== ${blockLog.archive}`);
110
109
  }
111
- // Check the block hash and archive for the last block in the epoch
112
- const endBlockLog = await this.rollupContract.getBlock(BigInt(toBlock));
113
- if (publicInputs.endArchive.root.toString() !== endBlockLog.archive) {
114
- throw new Error(`End archive root mismatch: ${publicInputs.endArchive.root.toString()} !== ${endBlockLog.archive}`);
110
+ // Check the archive for the last block in the epoch
111
+ const endBlockLog = await this.rollupContract.getCheckpoint(BigInt(toBlock));
112
+ if (publicInputs.endArchiveRoot.toString() !== endBlockLog.archive) {
113
+ throw new Error(`End archive root mismatch: ${publicInputs.endArchiveRoot.toString()} !== ${endBlockLog.archive}`);
115
114
  }
116
- if (publicInputs.endBlockHash.toString() !== endBlockLog.blockHash) {
117
- throw new Error(`End block hash mismatch: ${publicInputs.endBlockHash.toString()} !== ${endBlockLog.blockHash}`);
115
+ // Check the batched blob inputs from the root rollup against the batched blob computed in ts
116
+ const finalBlobAccumulator = batchedBlobInputs.toFinalBlobAccumulator();
117
+ if (!publicInputs.blobPublicInputs.equals(finalBlobAccumulator)) {
118
+ throw new Error(`Batched blob mismatch: ${inspect(publicInputs.blobPublicInputs)} !== ${inspect(finalBlobAccumulator)}`);
118
119
  }
119
120
  // Compare the public inputs computed by the contract with the ones injected
120
- const rollupPublicInputs = await this.rollupContract.getEpochProofPublicInputs(this.getSubmitEpochProofArgs(args));
121
- const aggregationObject = proof.isEmpty() ? times(AGGREGATION_OBJECT_LENGTH, Fr.zero) : proof.extractAggregationObject();
121
+ const rollupPublicInputs = await this.rollupContract.getEpochProofPublicInputs(this.getEpochProofPublicInputsArgs(args));
122
122
  const argsPublicInputs = [
123
- ...publicInputs.toFields(),
124
- ...aggregationObject
123
+ ...publicInputs.toFields()
125
124
  ];
126
125
  if (!areArraysEqual(rollupPublicInputs.map(Fr.fromHexString), argsPublicInputs, (a, b)=>a.equals(b))) {
127
126
  const fmt = (inputs)=>inputs.map((x)=>x.toString()).join(', ');
@@ -129,20 +128,14 @@ export class ProverNodePublisher {
129
128
  }
130
129
  }
131
130
  async sendSubmitEpochProofTx(args) {
132
- const proofHex = `0x${args.proof.withoutPublicInputs().toString('hex')}`;
133
- const argsArray = this.getSubmitEpochProofArgs(args);
134
131
  const txArgs = [
135
- {
136
- start: argsArray[0],
137
- end: argsArray[1],
138
- args: argsArray[2],
139
- fees: argsArray[3],
140
- blobPublicInputs: argsArray[4],
141
- aggregationObject: argsArray[5],
142
- proof: proofHex
143
- }
132
+ this.getSubmitEpochProofArgs(args)
144
133
  ];
145
- this.log.info(`SubmitEpochProof proofSize=${args.proof.withoutPublicInputs().length} bytes`);
134
+ this.log.info(`Submitting epoch proof to L1 rollup contract`, {
135
+ proofSize: args.proof.withoutPublicInputs().length,
136
+ fromBlock: args.fromBlock,
137
+ toBlock: args.toBlock
138
+ });
146
139
  const data = encodeFunctionData({
147
140
  abi: RollupAbi,
148
141
  functionName: 'submitEpochRootProof',
@@ -168,25 +161,32 @@ export class ProverNodePublisher {
168
161
  return undefined;
169
162
  }
170
163
  }
171
- getSubmitEpochProofArgs(args) {
164
+ getEpochProofPublicInputsArgs(args) {
165
+ // Returns arguments for EpochProofLib.sol -> getEpochProofPublicInputs()
172
166
  return [
173
167
  BigInt(args.fromBlock),
174
168
  BigInt(args.toBlock),
175
169
  {
176
- previousArchive: args.publicInputs.previousArchive.root.toString(),
177
- endArchive: args.publicInputs.endArchive.root.toString(),
178
- previousBlockHash: args.publicInputs.previousBlockHash.toString(),
179
- endBlockHash: args.publicInputs.endBlockHash.toString(),
180
- endTimestamp: args.publicInputs.endTimestamp.toBigInt(),
181
- outHash: args.publicInputs.outHash.toString(),
182
- proverId: EthAddress.fromField(args.publicInputs.proverId).toString()
183
- },
170
+ previousArchive: args.publicInputs.previousArchiveRoot.toString(),
171
+ endArchive: args.publicInputs.endArchiveRoot.toString(),
172
+ proverId: EthAddress.fromField(args.publicInputs.constants.proverId).toString()
173
+ } /*_args*/ ,
184
174
  makeTuple(AZTEC_MAX_EPOCH_DURATION * 2, (i)=>i % 2 === 0 ? args.publicInputs.fees[i / 2].recipient.toField().toString() : args.publicInputs.fees[(i - 1) / 2].value.toString()),
185
- `0x${args.publicInputs.blobPublicInputs.filter((_, i)=>i < args.toBlock - args.fromBlock + 1).map((b)=>b.toString()).join(``)}`,
186
- `0x${serializeToBuffer(args.proof.extractAggregationObject()).toString('hex')}`
175
+ getEthBlobEvaluationInputs(args.batchedBlobInputs)
187
176
  ];
188
177
  }
189
- async sleepOrInterrupted() {
190
- await this.interruptibleSleep.sleep(this.sleepTimeMs);
178
+ getSubmitEpochProofArgs(args) {
179
+ // Returns arguments for EpochProofLib.sol -> submitEpochRootProof()
180
+ const proofHex = `0x${args.proof.withoutPublicInputs().toString('hex')}`;
181
+ const argsArray = this.getEpochProofPublicInputsArgs(args);
182
+ return {
183
+ start: argsArray[0],
184
+ end: argsArray[1],
185
+ args: argsArray[2],
186
+ fees: argsArray[3],
187
+ attestations: new CommitteeAttestationsAndSigners(args.attestations.map((a)=>CommitteeAttestation.fromViem(a))).getPackedAttestations(),
188
+ blobInputs: argsArray[4],
189
+ proof: proofHex
190
+ };
191
191
  }
192
192
  }