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

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 (61) hide show
  1. package/README.md +572 -0
  2. package/dest/actions/rerun-epoch-proving-job.d.ts +12 -3
  3. package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -1
  4. package/dest/actions/rerun-epoch-proving-job.js +170 -28
  5. package/dest/checkpoint-store.d.ts +95 -0
  6. package/dest/checkpoint-store.d.ts.map +1 -0
  7. package/dest/checkpoint-store.js +178 -0
  8. package/dest/config.d.ts +1 -1
  9. package/dest/config.d.ts.map +1 -1
  10. package/dest/config.js +1 -1
  11. package/dest/factory.d.ts +4 -1
  12. package/dest/factory.d.ts.map +1 -1
  13. package/dest/factory.js +1 -6
  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 +154 -0
  18. package/dest/job/checkpoint-prover.d.ts.map +1 -0
  19. package/dest/job/checkpoint-prover.js +363 -0
  20. package/dest/job/epoch-session.d.ts +160 -0
  21. package/dest/job/epoch-session.d.ts.map +1 -0
  22. package/dest/job/epoch-session.js +744 -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 -19
  33. package/dest/prover-node-publisher.d.ts.map +1 -1
  34. package/dest/prover-node-publisher.js +38 -96
  35. package/dest/prover-node.d.ts +133 -66
  36. package/dest/prover-node.d.ts.map +1 -1
  37. package/dest/prover-node.js +529 -255
  38. package/dest/session-manager.d.ts +158 -0
  39. package/dest/session-manager.d.ts.map +1 -0
  40. package/dest/session-manager.js +486 -0
  41. package/dest/test/index.d.ts +7 -6
  42. package/dest/test/index.d.ts.map +1 -1
  43. package/package.json +24 -23
  44. package/src/actions/rerun-epoch-proving-job.ts +178 -30
  45. package/src/checkpoint-store.ts +212 -0
  46. package/src/config.ts +2 -1
  47. package/src/factory.ts +4 -8
  48. package/src/index.ts +1 -0
  49. package/src/job/checkpoint-prover.ts +496 -0
  50. package/src/job/epoch-session.ts +462 -0
  51. package/src/job/top-tree-job.ts +227 -0
  52. package/src/metrics.ts +65 -23
  53. package/src/proof-publishing-service.ts +427 -0
  54. package/src/prover-node-publisher.ts +52 -121
  55. package/src/prover-node.ts +617 -277
  56. package/src/session-manager.ts +589 -0
  57. package/src/test/index.ts +6 -6
  58. package/dest/job/epoch-proving-job.d.ts +0 -67
  59. package/dest/job/epoch-proving-job.d.ts.map +0 -1
  60. package/dest/job/epoch-proving-job.js +0 -912
  61. 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,12 +29,11 @@ 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;
@@ -73,23 +68,6 @@ export class ProverNodePublisher {
73
68
  return this.rollupContract;
74
69
  }
75
70
 
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
71
  public getSenderAddress() {
94
72
  return this.l1TxUtils.getSenderAddress();
95
73
  }
@@ -102,107 +80,54 @@ export class ProverNodePublisher {
102
80
  proof: Proof;
103
81
  batchedBlobInputs: BatchedBlob;
104
82
  attestations: ViemCommitteeAttestation[];
83
+ headers: CheckpointHeader[];
84
+ /** Wall-clock deadline (proof-submission window end) past which the L1 tx should stop retrying. */
85
+ deadline?: Date;
105
86
  }): Promise<boolean> {
106
87
  const { epochNumber, fromCheckpoint, toCheckpoint } = args;
107
88
  const ctx = { epochNumber, fromCheckpoint, toCheckpoint };
108
89
 
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
- }
90
+ const timer = new Timer();
91
+ // Validate epoch proof range and hashes are correct before submitting
92
+ await this.validateEpochProofSubmission(args);
152
93
 
153
- this.metrics.recordFailedTx();
154
- this.log.error(`Rollup submitEpochProof tx reverted ${txReceipt.transactionHash}`, undefined, ctx);
94
+ const txReceipt = await this.sendSubmitEpochProofTx(args);
95
+ if (!txReceipt) {
96
+ this.log.error(`Failed to mine submitEpochProof tx`, undefined, ctx);
97
+ return false;
155
98
  }
156
99
 
157
- this.log.verbose('Checkpoint data syncing interrupted', ctx);
158
- return false;
159
- }
100
+ try {
101
+ this.metrics.recordSenderBalance(
102
+ await this.l1TxUtils.getSenderBalance(),
103
+ this.l1TxUtils.getSenderAddress().toString(),
104
+ );
105
+ } catch (err) {
106
+ this.log.warn(`Failed to record the ETH balance of the prover node: ${err}`);
107
+ }
160
108
 
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)) {
109
+ // Tx was mined successfully
110
+ if (txReceipt.status === 'success') {
111
+ const tx = await this.l1TxUtils.getTransactionStats(txReceipt.transactionHash);
112
+ const stats: L1PublishProofStats = {
113
+ gasPrice: txReceipt.effectiveGasPrice,
114
+ gasUsed: txReceipt.gasUsed,
115
+ transactionHash: txReceipt.transactionHash,
116
+ calldataGas: tx!.calldataGas,
117
+ calldataSize: tx!.calldataSize,
118
+ sender: tx!.sender,
119
+ blobDataGas: 0n,
120
+ blobGasUsed: 0n,
121
+ eventName: 'proof-published-to-l1',
122
+ };
123
+ this.log.info(`Published epoch proof to L1 rollup contract`, { ...stats, ...ctx });
124
+ this.metrics.recordSubmitProof(timer.ms(), stats);
165
125
  return true;
166
126
  }
167
127
 
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);
128
+ this.metrics.recordFailedTx();
129
+ this.log.error(`Rollup submitEpochProof tx reverted ${txReceipt.transactionHash}`, undefined, ctx);
130
+ return false;
206
131
  }
207
132
 
208
133
  private async validateEpochProofSubmission(args: {
@@ -212,6 +137,7 @@ export class ProverNodePublisher {
212
137
  proof: Proof;
213
138
  batchedBlobInputs: BatchedBlob;
214
139
  attestations: ViemCommitteeAttestation[];
140
+ headers: CheckpointHeader[];
215
141
  }) {
216
142
  const { fromCheckpoint, toCheckpoint, publicInputs, batchedBlobInputs } = args;
217
143
 
@@ -285,6 +211,7 @@ export class ProverNodePublisher {
285
211
  proof: Proof;
286
212
  batchedBlobInputs: BatchedBlob;
287
213
  attestations: ViemCommitteeAttestation[];
214
+ headers: CheckpointHeader[];
288
215
  }): Promise<void> {
289
216
  const { epochNumber, fromCheckpoint, toCheckpoint } = args;
290
217
 
@@ -332,6 +259,7 @@ export class ProverNodePublisher {
332
259
  proof: Proof;
333
260
  batchedBlobInputs: BatchedBlob;
334
261
  attestations: ViemCommitteeAttestation[];
262
+ headers: CheckpointHeader[];
335
263
  }): Hex {
336
264
  return encodeFunctionData({
337
265
  abi: RollupAbi,
@@ -343,10 +271,12 @@ export class ProverNodePublisher {
343
271
  private async sendSubmitEpochProofTx(args: {
344
272
  fromCheckpoint: CheckpointNumber;
345
273
  toCheckpoint: CheckpointNumber;
274
+ deadline?: Date;
346
275
  publicInputs: RootRollupPublicInputs;
347
276
  proof: Proof;
348
277
  batchedBlobInputs: BatchedBlob;
349
278
  attestations: ViemCommitteeAttestation[];
279
+ headers: CheckpointHeader[];
350
280
  }): Promise<TransactionReceipt | undefined> {
351
281
  const txArgs = [this.getSubmitEpochProofArgs(args)] as const;
352
282
 
@@ -361,7 +291,10 @@ export class ProverNodePublisher {
361
291
  args: txArgs,
362
292
  });
363
293
  try {
364
- const { receipt } = await this.l1TxUtils.sendAndMonitorTransaction({ to: this.proofSubmissionTarget, data });
294
+ const { receipt } = await this.l1TxUtils.sendAndMonitorTransaction(
295
+ { to: this.proofSubmissionTarget, data },
296
+ { txTimeoutAt: args.deadline },
297
+ );
365
298
  if (receipt.status !== 'success') {
366
299
  const errorMsg = await this.l1TxUtils.tryGetErrorFromRevertedTx(
367
300
  data,
@@ -390,6 +323,7 @@ export class ProverNodePublisher {
390
323
  publicInputs: RootRollupPublicInputs;
391
324
  batchedBlobInputs: BatchedBlob;
392
325
  attestations: ViemCommitteeAttestation[];
326
+ headers: CheckpointHeader[];
393
327
  }) {
394
328
  // Returns arguments for EpochProofLib.sol -> getEpochProofPublicInputs()
395
329
  return [
@@ -401,11 +335,7 @@ export class ProverNodePublisher {
401
335
  outHash: args.publicInputs.outHash.toString(),
402
336
  proverId: EthAddress.fromField(args.publicInputs.constants.proverId).toString(),
403
337
  } /*_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*/,
338
+ args.headers.map(header => header.toViem()) /*_headers*/,
409
339
  getEthBlobEvaluationInputs(args.batchedBlobInputs) /*_blobPublicInputs*/,
410
340
  ] as const;
411
341
  }
@@ -417,6 +347,7 @@ export class ProverNodePublisher {
417
347
  proof: Proof;
418
348
  batchedBlobInputs: BatchedBlob;
419
349
  attestations: ViemCommitteeAttestation[];
350
+ headers: CheckpointHeader[];
420
351
  }) {
421
352
  // Returns arguments for EpochProofLib.sol -> submitEpochRootProof()
422
353
  const proofHex: Hex = `0x${args.proof.withoutPublicInputs().toString('hex')}`;
@@ -425,7 +356,7 @@ export class ProverNodePublisher {
425
356
  start: argsArray[0],
426
357
  end: argsArray[1],
427
358
  args: argsArray[2],
428
- fees: argsArray[3],
359
+ headers: argsArray[3],
429
360
  attestations: CommitteeAttestationsAndSigners.packAttestations(
430
361
  args.attestations.map(a => CommitteeAttestation.fromViem(a)),
431
362
  ),