@aztec/prover-node 0.0.1-commit.0b941701 → 0.0.1-commit.0dc957cde

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 (44) hide show
  1. package/dest/actions/download-epoch-proving-job.js +1 -1
  2. package/dest/actions/rerun-epoch-proving-job.d.ts +4 -3
  3. package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -1
  4. package/dest/actions/rerun-epoch-proving-job.js +7 -8
  5. package/dest/actions/upload-epoch-proof-failure.d.ts +2 -2
  6. package/dest/actions/upload-epoch-proof-failure.d.ts.map +1 -1
  7. package/dest/bin/run-failed-epoch.js +5 -2
  8. package/dest/config.d.ts +5 -8
  9. package/dest/config.d.ts.map +1 -1
  10. package/dest/config.js +16 -19
  11. package/dest/factory.d.ts +19 -13
  12. package/dest/factory.d.ts.map +1 -1
  13. package/dest/factory.js +39 -59
  14. package/dest/job/epoch-proving-job.d.ts +3 -2
  15. package/dest/job/epoch-proving-job.d.ts.map +1 -1
  16. package/dest/job/epoch-proving-job.js +52 -15
  17. package/dest/metrics.d.ts +21 -1
  18. package/dest/metrics.d.ts.map +1 -1
  19. package/dest/metrics.js +58 -3
  20. package/dest/monitors/epoch-monitor.d.ts +1 -1
  21. package/dest/monitors/epoch-monitor.d.ts.map +1 -1
  22. package/dest/monitors/epoch-monitor.js +5 -7
  23. package/dest/prover-node-publisher.d.ts +21 -5
  24. package/dest/prover-node-publisher.d.ts.map +1 -1
  25. package/dest/prover-node-publisher.js +56 -6
  26. package/dest/prover-node.d.ts +19 -9
  27. package/dest/prover-node.d.ts.map +1 -1
  28. package/dest/prover-node.js +16 -11
  29. package/dest/prover-publisher-factory.d.ts +7 -5
  30. package/dest/prover-publisher-factory.d.ts.map +1 -1
  31. package/dest/prover-publisher-factory.js +7 -5
  32. package/package.json +23 -22
  33. package/src/actions/download-epoch-proving-job.ts +1 -1
  34. package/src/actions/rerun-epoch-proving-job.ts +11 -5
  35. package/src/actions/upload-epoch-proof-failure.ts +1 -1
  36. package/src/bin/run-failed-epoch.ts +4 -1
  37. package/src/config.ts +23 -31
  38. package/src/factory.ts +67 -102
  39. package/src/job/epoch-proving-job.ts +70 -22
  40. package/src/metrics.ts +77 -2
  41. package/src/monitors/epoch-monitor.ts +3 -4
  42. package/src/prover-node-publisher.ts +78 -8
  43. package/src/prover-node.ts +19 -11
  44. package/src/prover-publisher-factory.ts +16 -10
@@ -1,5 +1,5 @@
1
1
  import { BatchedBlob, getEthBlobEvaluationInputs } from '@aztec/blob-lib';
2
- import { AZTEC_MAX_EPOCH_DURATION } from '@aztec/constants';
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
5
  import { makeTuple } from '@aztec/foundation/array';
@@ -7,7 +7,7 @@ import { CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
7
7
  import { areArraysEqual } from '@aztec/foundation/collection';
8
8
  import { Fr } from '@aztec/foundation/curves/bn254';
9
9
  import { EthAddress } from '@aztec/foundation/eth-address';
10
- import { createLogger } from '@aztec/foundation/log';
10
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
11
11
  import type { Tuple } from '@aztec/foundation/serialize';
12
12
  import { Timer } from '@aztec/foundation/timer';
13
13
  import { RollupAbi } from '@aztec/l1-artifacts';
@@ -19,9 +19,9 @@ import type { L1PublishProofStats } from '@aztec/stdlib/stats';
19
19
  import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
20
20
 
21
21
  import { inspect } from 'util';
22
- import { type Hex, type TransactionReceipt, encodeFunctionData } from 'viem';
22
+ import { type Hex, type TransactionReceipt, encodeFunctionData, formatEther, formatGwei } from 'viem';
23
23
 
24
- import { ProverNodePublisherMetrics } from './metrics.js';
24
+ import { type EstimatedSubmitProofStats, ProverNodePublisherMetrics } from './metrics.js';
25
25
 
26
26
  /** Arguments to the submitEpochProof method of the rollup contract */
27
27
  export type L1SubmitEpochProofArgs = {
@@ -31,7 +31,7 @@ export type L1SubmitEpochProofArgs = {
31
31
  endTimestamp: Fr;
32
32
  outHash: Fr;
33
33
  proverId: Fr;
34
- fees: Tuple<FeeRecipient, typeof AZTEC_MAX_EPOCH_DURATION>;
34
+ fees: Tuple<FeeRecipient, typeof MAX_CHECKPOINTS_PER_EPOCH>;
35
35
  proof: Proof;
36
36
  };
37
37
 
@@ -39,7 +39,7 @@ export class ProverNodePublisher {
39
39
  private interrupted = false;
40
40
  private metrics: ProverNodePublisherMetrics;
41
41
 
42
- protected log = createLogger('prover-node:l1-tx-publisher');
42
+ protected log: Logger;
43
43
 
44
44
  protected rollupContract: RollupContract;
45
45
 
@@ -52,10 +52,12 @@ export class ProverNodePublisher {
52
52
  l1TxUtils: L1TxUtils;
53
53
  telemetry?: TelemetryClient;
54
54
  },
55
+ bindings?: LoggerBindings,
55
56
  ) {
56
57
  const telemetry = deps.telemetry ?? getTelemetryClient();
57
58
 
58
59
  this.metrics = new ProverNodePublisherMetrics(telemetry, 'ProverNode');
60
+ this.log = createLogger('prover-node:l1-tx-publisher', bindings);
59
61
 
60
62
  this.rollupContract = deps.rollupContract;
61
63
  this.l1TxUtils = deps.l1TxUtils;
@@ -166,7 +168,7 @@ export class ProverNodePublisher {
166
168
  // toCheckpoint can't be greater than pending
167
169
  if (toCheckpoint > pending) {
168
170
  throw new Error(
169
- `Cannot submit epoch proof for ${fromCheckpoint}-${toCheckpoint} as pending checkpoint is ${pending}`,
171
+ `Cannot submit epoch proof for ${fromCheckpoint}-${toCheckpoint} as proposed checkpoint is ${pending}`,
170
172
  );
171
173
  }
172
174
 
@@ -208,6 +210,74 @@ export class ProverNodePublisher {
208
210
  }
209
211
  }
210
212
 
213
+ /**
214
+ * Estimates what submitting the epoch proof would have cost on L1 without actually sending it.
215
+ * Runs the same validation as `submitEpochProof`, encodes the calldata, estimates gas, and records metrics.
216
+ * Used when proof publishing is disabled (e.g. PROVER_NODE_DISABLE_PROOF_PUBLISH=true on mainnet).
217
+ */
218
+ public async analyzeEpochProofSubmission(args: {
219
+ epochNumber: EpochNumber;
220
+ fromCheckpoint: CheckpointNumber;
221
+ toCheckpoint: CheckpointNumber;
222
+ publicInputs: RootRollupPublicInputs;
223
+ proof: Proof;
224
+ batchedBlobInputs: BatchedBlob;
225
+ attestations: ViemCommitteeAttestation[];
226
+ }): Promise<void> {
227
+ const { epochNumber, fromCheckpoint, toCheckpoint } = args;
228
+
229
+ await this.validateEpochProofSubmission(args);
230
+
231
+ const data = this.encodeSubmitEpochProofCalldata(args);
232
+ const senderAddress = this.l1TxUtils.getSenderAddress();
233
+
234
+ const [gasLimit, gasPrice, latestBlock] = await Promise.all([
235
+ this.l1TxUtils.estimateGas(senderAddress.toString() as `0x${string}`, { to: this.rollupContract.address, data }),
236
+ this.l1TxUtils.getGasPrice(),
237
+ this.l1TxUtils.client.getBlock({ blockTag: 'latest' }),
238
+ ]);
239
+
240
+ const baseFeePerGas = latestBlock.baseFeePerGas ?? 0n;
241
+ const { maxPriorityFeePerGas } = gasPrice;
242
+
243
+ const effectiveFeePerGas = baseFeePerGas + maxPriorityFeePerGas;
244
+ const estimatedTotalFee = gasLimit * effectiveFeePerGas;
245
+
246
+ const stats: EstimatedSubmitProofStats = {
247
+ gasLimit,
248
+ baseFeePerGas,
249
+ maxPriorityFeePerGas,
250
+ estimatedTotalFee,
251
+ };
252
+
253
+ this.log.info(`Estimated epoch proof submission cost (not submitted)`, {
254
+ epochNumber,
255
+ fromCheckpoint,
256
+ toCheckpoint,
257
+ gasLimit: gasLimit.toString(),
258
+ baseFeePerGas: formatGwei(baseFeePerGas),
259
+ maxPriorityFeePerGas: formatGwei(maxPriorityFeePerGas),
260
+ estimatedTotalFeeEth: formatEther(estimatedTotalFee),
261
+ });
262
+
263
+ this.metrics.recordEstimatedSubmitProof(stats);
264
+ }
265
+
266
+ private encodeSubmitEpochProofCalldata(args: {
267
+ fromCheckpoint: CheckpointNumber;
268
+ toCheckpoint: CheckpointNumber;
269
+ publicInputs: RootRollupPublicInputs;
270
+ proof: Proof;
271
+ batchedBlobInputs: BatchedBlob;
272
+ attestations: ViemCommitteeAttestation[];
273
+ }): Hex {
274
+ return encodeFunctionData({
275
+ abi: RollupAbi,
276
+ functionName: 'submitEpochRootProof',
277
+ args: [this.getSubmitEpochProofArgs(args)],
278
+ });
279
+ }
280
+
211
281
  private async sendSubmitEpochProofTx(args: {
212
282
  fromCheckpoint: CheckpointNumber;
213
283
  toCheckpoint: CheckpointNumber;
@@ -269,7 +339,7 @@ export class ProverNodePublisher {
269
339
  outHash: args.publicInputs.outHash.toString(),
270
340
  proverId: EthAddress.fromField(args.publicInputs.constants.proverId).toString(),
271
341
  } /*_args*/,
272
- makeTuple(AZTEC_MAX_EPOCH_DURATION * 2, i =>
342
+ makeTuple(MAX_CHECKPOINTS_PER_EPOCH * 2, i =>
273
343
  i % 2 === 0
274
344
  ? args.publicInputs.fees[i / 2].recipient.toField().toString()
275
345
  : args.publicInputs.fees[(i - 1) / 2].value.toString(),
@@ -1,13 +1,12 @@
1
1
  import type { Archiver } from '@aztec/archiver';
2
2
  import type { RollupContract } from '@aztec/ethereum/contracts';
3
+ import type { Delayer } from '@aztec/ethereum/l1-tx-utils';
3
4
  import { BlockNumber, CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
4
5
  import { assertRequired, compact, pick, sum } from '@aztec/foundation/collection';
5
6
  import type { Fr } from '@aztec/foundation/curves/bn254';
6
7
  import { memoize } from '@aztec/foundation/decorators';
7
8
  import { createLogger } from '@aztec/foundation/log';
8
9
  import { DateProvider } from '@aztec/foundation/timer';
9
- import type { DataStoreConfig } from '@aztec/kv-store/config';
10
- import type { P2PClient } from '@aztec/p2p';
11
10
  import { PublicProcessorFactory } from '@aztec/simulator/server';
12
11
  import type { L2BlockSource } from '@aztec/stdlib/block';
13
12
  import type { Checkpoint } from '@aztec/stdlib/checkpoint';
@@ -17,14 +16,15 @@ import { getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers
17
16
  import {
18
17
  type EpochProverManager,
19
18
  EpochProvingJobTerminalState,
19
+ type ITxProvider,
20
20
  type ProverNodeApi,
21
21
  type Service,
22
22
  type WorldStateSyncStatus,
23
23
  type WorldStateSynchronizer,
24
24
  tryStop,
25
25
  } from '@aztec/stdlib/interfaces/server';
26
+ import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
26
27
  import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
27
- import type { P2PClientType } from '@aztec/stdlib/p2p';
28
28
  import type { Tx } from '@aztec/stdlib/tx';
29
29
  import {
30
30
  Attributes,
@@ -55,7 +55,6 @@ type DataStoreOptions = Pick<DataStoreConfig, 'dataDirectory'> & Pick<ChainConfi
55
55
  */
56
56
  export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable {
57
57
  private log = createLogger('prover-node');
58
- private dateProvider = new DateProvider();
59
58
 
60
59
  private jobs: Map<string, EpochProvingJob> = new Map();
61
60
  private config: ProverNodeOptions;
@@ -73,17 +72,19 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
73
72
  protected readonly l1ToL2MessageSource: L1ToL2MessageSource,
74
73
  protected readonly contractDataSource: ContractDataSource,
75
74
  protected readonly worldState: WorldStateSynchronizer,
76
- protected readonly p2pClient: Pick<P2PClient<P2PClientType.Prover>, 'getTxProvider'> & Partial<Service>,
75
+ protected readonly p2pClient: { getTxProvider(): ITxProvider } & Partial<Service>,
77
76
  protected readonly epochsMonitor: EpochMonitor,
78
77
  protected readonly rollupContract: RollupContract,
79
78
  protected readonly l1Metrics: L1Metrics,
80
79
  config: Partial<ProverNodeOptions> = {},
81
80
  protected readonly telemetryClient: TelemetryClient = getTelemetryClient(),
81
+ private delayer?: Delayer,
82
+ private readonly dateProvider: DateProvider = new DateProvider(),
82
83
  ) {
83
84
  this.config = {
84
85
  proverNodePollingIntervalMs: 1_000,
85
86
  proverNodeMaxPendingJobs: 100,
86
- proverNodeMaxParallelBlocksPerEpoch: 32,
87
+ proverNodeMaxParallelBlocksPerEpoch: 0,
87
88
  txGatheringIntervalMs: 1_000,
88
89
  txGatheringBatchSize: 10,
89
90
  txGatheringMaxParallelRequestsPerNode: 100,
@@ -111,6 +112,11 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
111
112
  return this.p2pClient;
112
113
  }
113
114
 
115
+ /** Returns the shared tx delayer for prover L1 txs, if enabled. Test-only. */
116
+ public getDelayer(): Delayer | undefined {
117
+ return this.delayer;
118
+ }
119
+
114
120
  /**
115
121
  * Handles an epoch being completed by starting a proof for it if there are no active jobs for it.
116
122
  * @param epochNumber - The epoch number that was just completed.
@@ -155,17 +161,15 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
155
161
 
156
162
  /**
157
163
  * Stops the prover node and all its dependencies.
164
+ * Resources not owned by this node (shared with the parent aztec-node) are skipped.
158
165
  */
159
166
  async stop() {
160
167
  this.log.info('Stopping ProverNode');
161
168
  await this.epochsMonitor.stop();
162
169
  await this.prover.stop();
163
- await tryStop(this.p2pClient);
164
- await tryStop(this.l2BlockSource);
165
170
  await tryStop(this.publisherFactory);
166
171
  this.publisher?.interrupt();
167
172
  await Promise.all(Array.from(this.jobs.values()).map(job => job.stop()));
168
- await this.worldState.stop();
169
173
  this.rewardsMetrics.stop();
170
174
  this.l1Metrics.stop();
171
175
  await this.telemetryClient.stop();
@@ -275,19 +279,22 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
275
279
  const fromCheckpoint = epochData.checkpoints[0].number;
276
280
  const toCheckpoint = epochData.checkpoints.at(-1)!.number;
277
281
  const fromBlock = epochData.checkpoints[0].blocks[0].number;
278
- const toBlock = epochData.checkpoints.at(-1)!.blocks.at(-1)!.number;
282
+ const lastBlock = epochData.checkpoints.at(-1)!.blocks.at(-1)!;
283
+ const toBlock = lastBlock.number;
279
284
  this.log.verbose(
280
285
  `Creating proving job for epoch ${epochNumber} for checkpoint range ${fromCheckpoint} to ${toCheckpoint} and block range ${fromBlock} to ${toBlock}`,
281
286
  );
282
287
 
283
288
  // Fast forward world state to right before the target block and get a fork
284
- await this.worldState.syncImmediate(toBlock);
289
+ const lastBlockHash = await lastBlock.header.hash();
290
+ await this.worldState.syncImmediate(toBlock, lastBlockHash);
285
291
 
286
292
  // Create a processor factory
287
293
  const publicProcessorFactory = new PublicProcessorFactory(
288
294
  this.contractDataSource,
289
295
  this.dateProvider,
290
296
  this.telemetryClient,
297
+ this.log.getBindings(),
291
298
  );
292
299
 
293
300
  // Set deadline for this job to run. It will abort if it takes too long.
@@ -384,6 +391,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
384
391
  this.jobMetrics,
385
392
  deadline,
386
393
  { parallelBlockLimit, skipSubmitProof: proverNodeDisableProofPublish, ...opts },
394
+ this.log.getBindings(),
387
395
  );
388
396
  }
389
397
 
@@ -1,27 +1,29 @@
1
1
  import type { RollupContract } from '@aztec/ethereum/contracts';
2
2
  import type { L1TxUtils } from '@aztec/ethereum/l1-tx-utils';
3
3
  import type { PublisherManager } from '@aztec/ethereum/publisher-manager';
4
- import type { PublisherConfig, TxSenderConfig } from '@aztec/sequencer-client';
4
+ import type { LoggerBindings } from '@aztec/foundation/log';
5
+ import type { ProverPublisherConfig, ProverTxSenderConfig } from '@aztec/sequencer-client';
5
6
  import type { TelemetryClient } from '@aztec/telemetry-client';
6
7
 
7
8
  import { ProverNodePublisher } from './prover-node-publisher.js';
8
9
 
9
10
  export class ProverPublisherFactory {
10
11
  constructor(
11
- private config: TxSenderConfig & PublisherConfig,
12
+ private config: ProverTxSenderConfig & ProverPublisherConfig,
12
13
  private deps: {
13
14
  rollupContract: RollupContract;
14
15
  publisherManager: PublisherManager<L1TxUtils>;
15
16
  telemetry?: TelemetryClient;
16
17
  },
18
+ private bindings?: LoggerBindings,
17
19
  ) {}
18
20
 
19
21
  public async start() {
20
- await this.deps.publisherManager.loadState();
22
+ await this.deps.publisherManager.start();
21
23
  }
22
24
 
23
- public stop() {
24
- this.deps.publisherManager.interrupt();
25
+ public async stop() {
26
+ await this.deps.publisherManager.stop();
25
27
  }
26
28
 
27
29
  /**
@@ -30,10 +32,14 @@ export class ProverPublisherFactory {
30
32
  */
31
33
  public async create(): Promise<ProverNodePublisher> {
32
34
  const l1Publisher = await this.deps.publisherManager.getAvailablePublisher();
33
- return new ProverNodePublisher(this.config, {
34
- rollupContract: this.deps.rollupContract,
35
- l1TxUtils: l1Publisher,
36
- telemetry: this.deps.telemetry,
37
- });
35
+ return new ProverNodePublisher(
36
+ this.config,
37
+ {
38
+ rollupContract: this.deps.rollupContract,
39
+ l1TxUtils: l1Publisher,
40
+ telemetry: this.deps.telemetry,
41
+ },
42
+ this.bindings,
43
+ );
38
44
  }
39
45
  }