@aztec/prover-node 0.0.1-commit.2f68f620 → 0.0.1-commit.3100065

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 (65) hide show
  1. package/README.md +511 -0
  2. package/dest/actions/rerun-epoch-proving-job.d.ts +3 -3
  3. package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -1
  4. package/dest/actions/rerun-epoch-proving-job.js +106 -104
  5. package/dest/checkpoint-store.d.ts +88 -0
  6. package/dest/checkpoint-store.d.ts.map +1 -0
  7. package/dest/checkpoint-store.js +169 -0
  8. package/dest/config.d.ts +1 -3
  9. package/dest/config.d.ts.map +1 -1
  10. package/dest/config.js +1 -8
  11. package/dest/factory.d.ts +1 -1
  12. package/dest/factory.d.ts.map +1 -1
  13. package/dest/factory.js +1 -7
  14. package/dest/index.d.ts +2 -1
  15. package/dest/index.d.ts.map +1 -1
  16. package/dest/index.js +1 -0
  17. package/dest/job/checkpoint-prover.d.ts +124 -0
  18. package/dest/job/checkpoint-prover.d.ts.map +1 -0
  19. package/dest/job/checkpoint-prover.js +330 -0
  20. package/dest/job/epoch-session.d.ts +146 -0
  21. package/dest/job/epoch-session.d.ts.map +1 -0
  22. package/dest/job/epoch-session.js +720 -0
  23. package/dest/job/top-tree-job.d.ts +82 -0
  24. package/dest/job/top-tree-job.d.ts.map +1 -0
  25. package/dest/job/top-tree-job.js +152 -0
  26. package/dest/metrics.d.ts +25 -8
  27. package/dest/metrics.d.ts.map +1 -1
  28. package/dest/metrics.js +64 -14
  29. package/dest/proof-publishing-service.d.ts +161 -0
  30. package/dest/proof-publishing-service.d.ts.map +1 -0
  31. package/dest/proof-publishing-service.js +335 -0
  32. package/dest/prover-node-publisher.d.ts +7 -22
  33. package/dest/prover-node-publisher.d.ts.map +1 -1
  34. package/dest/prover-node-publisher.js +41 -101
  35. package/dest/prover-node.d.ts +105 -67
  36. package/dest/prover-node.d.ts.map +1 -1
  37. package/dest/prover-node.js +472 -261
  38. package/dest/prover-publisher-factory.d.ts +1 -3
  39. package/dest/prover-publisher-factory.d.ts.map +1 -1
  40. package/dest/prover-publisher-factory.js +0 -1
  41. package/dest/session-manager.d.ts +158 -0
  42. package/dest/session-manager.d.ts.map +1 -0
  43. package/dest/session-manager.js +482 -0
  44. package/dest/test/index.d.ts +7 -6
  45. package/dest/test/index.d.ts.map +1 -1
  46. package/package.json +23 -23
  47. package/src/actions/rerun-epoch-proving-job.ts +102 -27
  48. package/src/checkpoint-store.ts +194 -0
  49. package/src/config.ts +2 -11
  50. package/src/factory.ts +0 -9
  51. package/src/index.ts +1 -0
  52. package/src/job/checkpoint-prover.ts +442 -0
  53. package/src/job/epoch-session.ts +436 -0
  54. package/src/job/top-tree-job.ts +227 -0
  55. package/src/metrics.ts +65 -23
  56. package/src/proof-publishing-service.ts +427 -0
  57. package/src/prover-node-publisher.ts +54 -127
  58. package/src/prover-node.ts +545 -282
  59. package/src/prover-publisher-factory.ts +0 -3
  60. package/src/session-manager.ts +583 -0
  61. package/src/test/index.ts +6 -6
  62. package/dest/job/epoch-proving-job.d.ts +0 -67
  63. package/dest/job/epoch-proving-job.d.ts.map +0 -1
  64. package/dest/job/epoch-proving-job.js +0 -912
  65. package/src/job/epoch-proving-job.ts +0 -531
@@ -2,21 +2,17 @@ import { BatchedBlob, getEthBlobEvaluationInputs } from '@aztec/blob-lib';
2
2
  import { MAX_CHECKPOINTS_PER_EPOCH } from '@aztec/constants';
3
3
  import type { RollupContract, ViemCommitteeAttestation } from '@aztec/ethereum/contracts';
4
4
  import type { L1TxUtils } from '@aztec/ethereum/l1-tx-utils';
5
- import { makeTuple } from '@aztec/foundation/array';
6
5
  import { CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
7
6
  import { areArraysEqual } from '@aztec/foundation/collection';
8
7
  import { Fr } from '@aztec/foundation/curves/bn254';
9
8
  import { EthAddress } from '@aztec/foundation/eth-address';
10
9
  import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
11
- import { retryUntil } from '@aztec/foundation/retry';
12
- import type { Tuple } from '@aztec/foundation/serialize';
13
10
  import { Timer } from '@aztec/foundation/timer';
14
11
  import { RollupAbi } from '@aztec/l1-artifacts';
15
12
  import type { PublisherConfig, TxSenderConfig } from '@aztec/sequencer-client';
16
13
  import { CommitteeAttestation, CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
17
- import { getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers';
18
14
  import type { Proof } from '@aztec/stdlib/proofs';
19
- import type { FeeRecipient, RootRollupPublicInputs } from '@aztec/stdlib/rollup';
15
+ import type { CheckpointHeader, RootRollupPublicInputs } from '@aztec/stdlib/rollup';
20
16
  import type { L1PublishProofStats } from '@aztec/stdlib/stats';
21
17
  import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
22
18
 
@@ -33,20 +29,17 @@ export type L1SubmitEpochProofArgs = {
33
29
  endTimestamp: Fr;
34
30
  outHash: Fr;
35
31
  proverId: Fr;
36
- fees: Tuple<FeeRecipient, typeof MAX_CHECKPOINTS_PER_EPOCH>;
32
+ headers: CheckpointHeader[];
37
33
  proof: Proof;
38
34
  };
39
35
 
40
36
  export class ProverNodePublisher {
41
- private interrupted = false;
42
37
  private metrics: ProverNodePublisherMetrics;
43
38
 
44
39
  protected log: Logger;
45
40
 
46
41
  protected rollupContract: RollupContract;
47
42
 
48
- protected proofSubmissionTarget: Hex;
49
-
50
43
  public readonly l1TxUtils: L1TxUtils;
51
44
 
52
45
  constructor(
@@ -54,7 +47,6 @@ export class ProverNodePublisher {
54
47
  deps: {
55
48
  rollupContract: RollupContract;
56
49
  l1TxUtils: L1TxUtils;
57
- proofSubmissionTarget?: EthAddress;
58
50
  telemetry?: TelemetryClient;
59
51
  },
60
52
  bindings?: LoggerBindings,
@@ -65,7 +57,6 @@ export class ProverNodePublisher {
65
57
  this.log = createLogger('prover-node:l1-tx-publisher', bindings);
66
58
 
67
59
  this.rollupContract = deps.rollupContract;
68
- this.proofSubmissionTarget = deps.proofSubmissionTarget?.toString() ?? deps.rollupContract.address;
69
60
  this.l1TxUtils = deps.l1TxUtils;
70
61
  }
71
62
 
@@ -73,23 +64,6 @@ export class ProverNodePublisher {
73
64
  return this.rollupContract;
74
65
  }
75
66
 
76
- /**
77
- * Calling `interrupt` will cause any in progress call to `publishRollup` to return `false` asap.
78
- * Be warned, the call may return false even if the tx subsequently gets successfully mined.
79
- * In practice this shouldn't matter, as we'll only ever be calling `interrupt` when we know it's going to fail.
80
- * A call to `restart` is required before you can continue publishing.
81
- */
82
- public interrupt() {
83
- this.interrupted = true;
84
- this.l1TxUtils.interrupt();
85
- }
86
-
87
- /** Restarts the publisher after calling `interrupt`. */
88
- public restart() {
89
- this.interrupted = false;
90
- this.l1TxUtils.restart();
91
- }
92
-
93
67
  public getSenderAddress() {
94
68
  return this.l1TxUtils.getSenderAddress();
95
69
  }
@@ -102,107 +76,54 @@ export class ProverNodePublisher {
102
76
  proof: Proof;
103
77
  batchedBlobInputs: BatchedBlob;
104
78
  attestations: ViemCommitteeAttestation[];
79
+ headers: CheckpointHeader[];
80
+ /** Wall-clock deadline (proof-submission window end) past which the L1 tx should stop retrying. */
81
+ deadline?: Date;
105
82
  }): Promise<boolean> {
106
83
  const { epochNumber, fromCheckpoint, toCheckpoint } = args;
107
84
  const ctx = { epochNumber, fromCheckpoint, toCheckpoint };
108
85
 
109
- if (!this.interrupted) {
110
- if (!(await this.waitUntilStartBuildsOnProven(args))) {
111
- this.log.verbose('Checkpoint data syncing interrupted', ctx);
112
- return false;
113
- }
114
-
115
- const timer = new Timer();
116
- // Validate epoch proof range and hashes are correct before submitting
117
- await this.validateEpochProofSubmission(args);
118
-
119
- const txReceipt = await this.sendSubmitEpochProofTx(args);
120
- if (!txReceipt) {
121
- this.log.error(`Failed to mine submitEpochProof tx`, undefined, ctx);
122
- return false;
123
- }
124
-
125
- try {
126
- this.metrics.recordSenderBalance(
127
- await this.l1TxUtils.getSenderBalance(),
128
- this.l1TxUtils.getSenderAddress().toString(),
129
- );
130
- } catch (err) {
131
- this.log.warn(`Failed to record the ETH balance of the prover node: ${err}`);
132
- }
133
-
134
- // Tx was mined successfully
135
- if (txReceipt.status === 'success') {
136
- const tx = await this.l1TxUtils.getTransactionStats(txReceipt.transactionHash);
137
- const stats: L1PublishProofStats = {
138
- gasPrice: txReceipt.effectiveGasPrice,
139
- gasUsed: txReceipt.gasUsed,
140
- transactionHash: txReceipt.transactionHash,
141
- calldataGas: tx!.calldataGas,
142
- calldataSize: tx!.calldataSize,
143
- sender: tx!.sender,
144
- blobDataGas: 0n,
145
- blobGasUsed: 0n,
146
- eventName: 'proof-published-to-l1',
147
- };
148
- this.log.info(`Published epoch proof to L1 rollup contract`, { ...stats, ...ctx });
149
- this.metrics.recordSubmitProof(timer.ms(), stats);
150
- return true;
151
- }
86
+ const timer = new Timer();
87
+ // Validate epoch proof range and hashes are correct before submitting
88
+ await this.validateEpochProofSubmission(args);
152
89
 
153
- this.metrics.recordFailedTx();
154
- this.log.error(`Rollup submitEpochProof tx reverted ${txReceipt.transactionHash}`, undefined, ctx);
90
+ const txReceipt = await this.sendSubmitEpochProofTx(args);
91
+ if (!txReceipt) {
92
+ this.log.error(`Failed to mine submitEpochProof tx`, undefined, ctx);
93
+ return false;
155
94
  }
156
95
 
157
- this.log.verbose('Checkpoint data syncing interrupted', ctx);
158
- return false;
159
- }
96
+ try {
97
+ this.metrics.recordSenderBalance(
98
+ await this.l1TxUtils.getSenderBalance(),
99
+ this.l1TxUtils.getSenderAddress().toString(),
100
+ );
101
+ } catch (err) {
102
+ this.log.warn(`Failed to record the ETH balance of the prover node: ${err}`);
103
+ }
160
104
 
161
- private async waitUntilStartBuildsOnProven(args: { epochNumber: EpochNumber; fromCheckpoint: CheckpointNumber }) {
162
- const { epochNumber, fromCheckpoint } = args;
163
- const provenCheckpoint = await this.getProvenCheckpoint();
164
- if (this.isStartBuildingOnProven(fromCheckpoint, provenCheckpoint)) {
105
+ // Tx was mined successfully
106
+ if (txReceipt.status === 'success') {
107
+ const tx = await this.l1TxUtils.getTransactionStats(txReceipt.transactionHash);
108
+ const stats: L1PublishProofStats = {
109
+ gasPrice: txReceipt.effectiveGasPrice,
110
+ gasUsed: txReceipt.gasUsed,
111
+ transactionHash: txReceipt.transactionHash,
112
+ calldataGas: tx!.calldataGas,
113
+ calldataSize: tx!.calldataSize,
114
+ sender: tx!.sender,
115
+ blobDataGas: 0n,
116
+ blobGasUsed: 0n,
117
+ eventName: 'proof-published-to-l1',
118
+ };
119
+ this.log.info(`Published epoch proof to L1 rollup contract`, { ...stats, ...ctx });
120
+ this.metrics.recordSubmitProof(timer.ms(), stats);
165
121
  return true;
166
122
  }
167
123
 
168
- const timeout = await this.getSecondsUntilProofSubmissionWindowEnd(epochNumber);
169
- this.log.info(`Waiting for proven checkpoint to reach proof start`, {
170
- epochNumber,
171
- fromCheckpoint,
172
- provenCheckpoint,
173
- timeout,
174
- });
175
-
176
- await retryUntil(
177
- async () => {
178
- if (this.interrupted) {
179
- return true;
180
- }
181
-
182
- const proven = await this.getProvenCheckpoint();
183
- this.log.verbose(`Proven checkpoint is at ${proven} (waiting for ${fromCheckpoint - 1})`, { epochNumber });
184
- return this.isStartBuildingOnProven(fromCheckpoint, proven) ? true : undefined;
185
- },
186
- `proven checkpoint to reach ${fromCheckpoint - 1}`,
187
- timeout,
188
- 4,
189
- );
190
-
191
- return !this.interrupted;
192
- }
193
-
194
- private async getProvenCheckpoint() {
195
- return (await this.rollupContract.getTips()).proven;
196
- }
197
-
198
- private isStartBuildingOnProven(fromCheckpoint: CheckpointNumber, provenCheckpoint: CheckpointNumber) {
199
- return fromCheckpoint - 1 <= provenCheckpoint;
200
- }
201
-
202
- private async getSecondsUntilProofSubmissionWindowEnd(epochNumber: EpochNumber) {
203
- const deadline = getProofSubmissionDeadlineTimestamp(epochNumber, await this.rollupContract.getRollupConstants());
204
- const now = BigInt(Math.floor(Date.now() / 1000));
205
- return Math.max(Number(deadline - now), 0.001);
124
+ this.metrics.recordFailedTx();
125
+ this.log.error(`Rollup submitEpochProof tx reverted ${txReceipt.transactionHash}`, undefined, ctx);
126
+ return false;
206
127
  }
207
128
 
208
129
  private async validateEpochProofSubmission(args: {
@@ -212,6 +133,7 @@ export class ProverNodePublisher {
212
133
  proof: Proof;
213
134
  batchedBlobInputs: BatchedBlob;
214
135
  attestations: ViemCommitteeAttestation[];
136
+ headers: CheckpointHeader[];
215
137
  }) {
216
138
  const { fromCheckpoint, toCheckpoint, publicInputs, batchedBlobInputs } = args;
217
139
 
@@ -285,6 +207,7 @@ export class ProverNodePublisher {
285
207
  proof: Proof;
286
208
  batchedBlobInputs: BatchedBlob;
287
209
  attestations: ViemCommitteeAttestation[];
210
+ headers: CheckpointHeader[];
288
211
  }): Promise<void> {
289
212
  const { epochNumber, fromCheckpoint, toCheckpoint } = args;
290
213
 
@@ -294,7 +217,7 @@ export class ProverNodePublisher {
294
217
  const senderAddress = this.l1TxUtils.getSenderAddress();
295
218
 
296
219
  const [gasLimit, gasPrice, latestBlock] = await Promise.all([
297
- this.l1TxUtils.estimateGas(senderAddress.toString() as `0x${string}`, { to: this.proofSubmissionTarget, data }),
220
+ this.l1TxUtils.estimateGas(senderAddress.toString() as `0x${string}`, { to: this.rollupContract.address, data }),
298
221
  this.l1TxUtils.getGasPrice(),
299
222
  this.l1TxUtils.client.getBlock({ blockTag: 'latest' }),
300
223
  ]);
@@ -332,6 +255,7 @@ export class ProverNodePublisher {
332
255
  proof: Proof;
333
256
  batchedBlobInputs: BatchedBlob;
334
257
  attestations: ViemCommitteeAttestation[];
258
+ headers: CheckpointHeader[];
335
259
  }): Hex {
336
260
  return encodeFunctionData({
337
261
  abi: RollupAbi,
@@ -343,10 +267,12 @@ export class ProverNodePublisher {
343
267
  private async sendSubmitEpochProofTx(args: {
344
268
  fromCheckpoint: CheckpointNumber;
345
269
  toCheckpoint: CheckpointNumber;
270
+ deadline?: Date;
346
271
  publicInputs: RootRollupPublicInputs;
347
272
  proof: Proof;
348
273
  batchedBlobInputs: BatchedBlob;
349
274
  attestations: ViemCommitteeAttestation[];
275
+ headers: CheckpointHeader[];
350
276
  }): Promise<TransactionReceipt | undefined> {
351
277
  const txArgs = [this.getSubmitEpochProofArgs(args)] as const;
352
278
 
@@ -361,7 +287,10 @@ export class ProverNodePublisher {
361
287
  args: txArgs,
362
288
  });
363
289
  try {
364
- const { receipt } = await this.l1TxUtils.sendAndMonitorTransaction({ to: this.proofSubmissionTarget, data });
290
+ const { receipt } = await this.l1TxUtils.sendAndMonitorTransaction(
291
+ { to: this.rollupContract.address, data },
292
+ { txTimeoutAt: args.deadline },
293
+ );
365
294
  if (receipt.status !== 'success') {
366
295
  const errorMsg = await this.l1TxUtils.tryGetErrorFromRevertedTx(
367
296
  data,
@@ -369,7 +298,7 @@ export class ProverNodePublisher {
369
298
  args: [...txArgs],
370
299
  functionName: 'submitEpochRootProof',
371
300
  abi: RollupAbi,
372
- address: this.proofSubmissionTarget,
301
+ address: this.rollupContract.address,
373
302
  },
374
303
  /*blobInputs*/ undefined,
375
304
  /*stateOverride*/ [],
@@ -390,6 +319,7 @@ export class ProverNodePublisher {
390
319
  publicInputs: RootRollupPublicInputs;
391
320
  batchedBlobInputs: BatchedBlob;
392
321
  attestations: ViemCommitteeAttestation[];
322
+ headers: CheckpointHeader[];
393
323
  }) {
394
324
  // Returns arguments for EpochProofLib.sol -> getEpochProofPublicInputs()
395
325
  return [
@@ -401,11 +331,7 @@ export class ProverNodePublisher {
401
331
  outHash: args.publicInputs.outHash.toString(),
402
332
  proverId: EthAddress.fromField(args.publicInputs.constants.proverId).toString(),
403
333
  } /*_args*/,
404
- makeTuple(MAX_CHECKPOINTS_PER_EPOCH * 2, i =>
405
- i % 2 === 0
406
- ? args.publicInputs.fees[i / 2].recipient.toField().toString()
407
- : args.publicInputs.fees[(i - 1) / 2].value.toString(),
408
- ) /*_fees*/,
334
+ args.headers.map(header => header.toViem()) /*_headers*/,
409
335
  getEthBlobEvaluationInputs(args.batchedBlobInputs) /*_blobPublicInputs*/,
410
336
  ] as const;
411
337
  }
@@ -417,6 +343,7 @@ export class ProverNodePublisher {
417
343
  proof: Proof;
418
344
  batchedBlobInputs: BatchedBlob;
419
345
  attestations: ViemCommitteeAttestation[];
346
+ headers: CheckpointHeader[];
420
347
  }) {
421
348
  // Returns arguments for EpochProofLib.sol -> submitEpochRootProof()
422
349
  const proofHex: Hex = `0x${args.proof.withoutPublicInputs().toString('hex')}`;
@@ -425,7 +352,7 @@ export class ProverNodePublisher {
425
352
  start: argsArray[0],
426
353
  end: argsArray[1],
427
354
  args: argsArray[2],
428
- fees: argsArray[3],
355
+ headers: argsArray[3],
429
356
  attestations: CommitteeAttestationsAndSigners.packAttestations(
430
357
  args.attestations.map(a => CommitteeAttestation.fromViem(a)),
431
358
  ),