@aztec/prover-node 0.0.1-commit.04852196a → 0.0.1-commit.04d373f

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 (39) hide show
  1. package/dest/actions/download-epoch-proving-job.js +1 -1
  2. package/dest/actions/rerun-epoch-proving-job.d.ts +3 -2
  3. package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -1
  4. package/dest/actions/rerun-epoch-proving-job.js +8 -8
  5. package/dest/bin/run-failed-epoch.js +1 -3
  6. package/dest/config.js +1 -1
  7. package/dest/factory.d.ts +1 -1
  8. package/dest/factory.d.ts.map +1 -1
  9. package/dest/factory.js +26 -6
  10. package/dest/job/epoch-proving-job.d.ts +6 -2
  11. package/dest/job/epoch-proving-job.d.ts.map +1 -1
  12. package/dest/job/epoch-proving-job.js +198 -38
  13. package/dest/metrics.d.ts +21 -1
  14. package/dest/metrics.d.ts.map +1 -1
  15. package/dest/metrics.js +47 -0
  16. package/dest/monitors/epoch-monitor.d.ts +1 -1
  17. package/dest/monitors/epoch-monitor.d.ts.map +1 -1
  18. package/dest/monitors/epoch-monitor.js +11 -9
  19. package/dest/prover-node-publisher.d.ts +20 -1
  20. package/dest/prover-node-publisher.d.ts.map +1 -1
  21. package/dest/prover-node-publisher.js +200 -5
  22. package/dest/prover-node.d.ts +1 -2
  23. package/dest/prover-node.d.ts.map +1 -1
  24. package/dest/prover-node.js +21 -19
  25. package/dest/prover-publisher-factory.d.ts +2 -2
  26. package/dest/prover-publisher-factory.d.ts.map +1 -1
  27. package/dest/prover-publisher-factory.js +3 -3
  28. package/package.json +23 -22
  29. package/src/actions/download-epoch-proving-job.ts +1 -1
  30. package/src/actions/rerun-epoch-proving-job.ts +16 -5
  31. package/src/bin/run-failed-epoch.ts +1 -2
  32. package/src/config.ts +1 -1
  33. package/src/factory.ts +21 -4
  34. package/src/job/epoch-proving-job.ts +120 -38
  35. package/src/metrics.ts +71 -0
  36. package/src/monitors/epoch-monitor.ts +5 -6
  37. package/src/prover-node-publisher.ts +232 -9
  38. package/src/prover-node.ts +17 -23
  39. package/src/prover-publisher-factory.ts +3 -3
@@ -451,7 +451,7 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
451
451
  this.config = {
452
452
  proverNodePollingIntervalMs: 1_000,
453
453
  proverNodeMaxPendingJobs: 100,
454
- proverNodeMaxParallelBlocksPerEpoch: 32,
454
+ proverNodeMaxParallelBlocksPerEpoch: 0,
455
455
  txGatheringIntervalMs: 1_000,
456
456
  txGatheringBatchSize: 10,
457
457
  txGatheringMaxParallelRequestsPerNode: 100,
@@ -519,10 +519,10 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
519
519
  */ async stop() {
520
520
  this.log.info('Stopping ProverNode');
521
521
  await this.epochsMonitor.stop();
522
- await this.prover.stop();
523
- await tryStop(this.publisherFactory);
524
522
  this.publisher?.interrupt();
525
523
  await Promise.all(Array.from(this.jobs.values()).map((job)=>job.stop()));
524
+ await this.prover.stop();
525
+ await tryStop(this.publisherFactory);
526
526
  this.rewardsMetrics.stop();
527
527
  this.l1Metrics.stop();
528
528
  await this.telemetryClient.stop();
@@ -606,10 +606,12 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
606
606
  const fromCheckpoint = epochData.checkpoints[0].number;
607
607
  const toCheckpoint = epochData.checkpoints.at(-1).number;
608
608
  const fromBlock = epochData.checkpoints[0].blocks[0].number;
609
- const toBlock = epochData.checkpoints.at(-1).blocks.at(-1).number;
609
+ const lastBlock = epochData.checkpoints.at(-1).blocks.at(-1);
610
+ const toBlock = lastBlock.number;
610
611
  this.log.verbose(`Creating proving job for epoch ${epochNumber} for checkpoint range ${fromCheckpoint} to ${toCheckpoint} and block range ${fromBlock} to ${toBlock}`);
611
612
  // Fast forward world state to right before the target block and get a fork
612
- await this.worldState.syncImmediate(toBlock);
613
+ const lastBlockHash = await lastBlock.header.hash();
614
+ await this.worldState.syncImmediate(toBlock, lastBlockHash);
613
615
  // Create a processor factory
614
616
  const publicProcessorFactory = new PublicProcessorFactory(this.contractDataSource, this.dateProvider, this.telemetryClient, this.log.getBindings());
615
617
  // Set deadline for this job to run. It will abort if it takes too long.
@@ -623,7 +625,14 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
623
625
  return this.l2BlockSource.getL1Constants();
624
626
  }
625
627
  async gatherEpochData(epochNumber) {
626
- const checkpoints = await this.gatherCheckpoints(epochNumber);
628
+ const publishedCheckpoints = await this.l2BlockSource.getCheckpoints({
629
+ epoch: epochNumber
630
+ });
631
+ if (publishedCheckpoints.length === 0) {
632
+ throw new EmptyEpochError(epochNumber);
633
+ }
634
+ const checkpoints = publishedCheckpoints.map((p)=>p.checkpoint);
635
+ const attestations = publishedCheckpoints.at(-1)?.attestations ?? [];
627
636
  const txArray = await this.gatherTxs(epochNumber, checkpoints);
628
637
  const txs = new Map(txArray.map((tx)=>[
629
638
  tx.getTxHash().toString(),
@@ -632,8 +641,6 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
632
641
  const l1ToL2Messages = await this.gatherMessages(epochNumber, checkpoints);
633
642
  const [firstBlock] = checkpoints[0].blocks;
634
643
  const previousBlockHeader = await this.gatherPreviousBlockHeader(epochNumber, firstBlock.number - 1);
635
- const [lastPublishedCheckpoint] = await this.l2BlockSource.getCheckpoints(checkpoints.at(-1).number, 1);
636
- const attestations = lastPublishedCheckpoint?.attestations ?? [];
637
644
  return {
638
645
  checkpoints,
639
646
  txs,
@@ -643,13 +650,6 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
643
650
  attestations
644
651
  };
645
652
  }
646
- async gatherCheckpoints(epochNumber) {
647
- const checkpoints = await this.l2BlockSource.getCheckpointsForEpoch(epochNumber);
648
- if (checkpoints.length === 0) {
649
- throw new EmptyEpochError(epochNumber);
650
- }
651
- return checkpoints;
652
- }
653
653
  async gatherTxs(epochNumber, checkpoints) {
654
654
  const deadline = new Date(this.dateProvider.now() + this.config.txGatheringTimeoutMs);
655
655
  const txProvider = this.p2pClient.getTxProvider();
@@ -680,12 +680,14 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
680
680
  return messagesByCheckpoint;
681
681
  }
682
682
  async gatherPreviousBlockHeader(epochNumber, previousBlockNumber) {
683
- const header = await (previousBlockNumber === 0 ? this.worldState.getCommitted().getInitialHeader() : this.l2BlockSource.getBlockHeader(BlockNumber(previousBlockNumber)));
684
- if (!header) {
683
+ const data = await this.l2BlockSource.getBlockData({
684
+ number: BlockNumber(previousBlockNumber)
685
+ });
686
+ if (!data?.header) {
685
687
  throw new Error(`Previous block header ${previousBlockNumber} not found for proving epoch ${epochNumber}`);
686
688
  }
687
- this.log.verbose(`Gathered previous block header ${header.getBlockNumber()} for epoch ${epochNumber}`);
688
- return header;
689
+ this.log.verbose(`Gathered previous block header ${data.header.getBlockNumber()} for epoch ${epochNumber}`);
690
+ return data.header;
689
691
  }
690
692
  /** Extracted for testing purposes. */ doCreateEpochProvingJob(data, deadline, publicProcessorFactory, publisher, opts = {}) {
691
693
  const { proverNodeMaxParallelBlocksPerEpoch: parallelBlockLimit, proverNodeDisableProofPublish } = this.config;
@@ -15,11 +15,11 @@ export declare class ProverPublisherFactory {
15
15
  telemetry?: TelemetryClient;
16
16
  }, bindings?: LoggerBindings | undefined);
17
17
  start(): Promise<void>;
18
- stop(): void;
18
+ stop(): Promise<void>;
19
19
  /**
20
20
  * Creates a new Prover Publisher instance.
21
21
  * @returns A new ProverNodePublisher instance.
22
22
  */
23
23
  create(): Promise<ProverNodePublisher>;
24
24
  }
25
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmVyLXB1Ymxpc2hlci1mYWN0b3J5LmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcHJvdmVyLXB1Ymxpc2hlci1mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ2hFLE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzdELE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDMUUsT0FBTyxLQUFLLEVBQUUsY0FBYyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDNUQsT0FBTyxLQUFLLEVBQUUscUJBQXFCLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUMzRixPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUvRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVqRSxxQkFBYSxzQkFBc0I7SUFFL0IsT0FBTyxDQUFDLE1BQU07SUFDZCxPQUFPLENBQUMsSUFBSTtJQUtaLE9BQU8sQ0FBQyxRQUFRLENBQUM7SUFQbkIsWUFDVSxNQUFNLEVBQUUsb0JBQW9CLEdBQUcscUJBQXFCLEVBQ3BELElBQUksRUFBRTtRQUNaLGNBQWMsRUFBRSxjQUFjLENBQUM7UUFDL0IsZ0JBQWdCLEVBQUUsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDOUMsU0FBUyxDQUFDLEVBQUUsZUFBZSxDQUFDO0tBQzdCLEVBQ08sUUFBUSxDQUFDLDRCQUFnQixFQUMvQjtJQUVTLEtBQUssa0JBRWpCO0lBRU0sSUFBSSxTQUVWO0lBRUQ7OztPQUdHO0lBQ1UsTUFBTSxJQUFJLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQVdsRDtDQUNGIn0=
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmVyLXB1Ymxpc2hlci1mYWN0b3J5LmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcHJvdmVyLXB1Ymxpc2hlci1mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ2hFLE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzdELE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDMUUsT0FBTyxLQUFLLEVBQUUsY0FBYyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDNUQsT0FBTyxLQUFLLEVBQUUscUJBQXFCLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUMzRixPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUvRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVqRSxxQkFBYSxzQkFBc0I7SUFFL0IsT0FBTyxDQUFDLE1BQU07SUFDZCxPQUFPLENBQUMsSUFBSTtJQUtaLE9BQU8sQ0FBQyxRQUFRLENBQUM7SUFQbkIsWUFDVSxNQUFNLEVBQUUsb0JBQW9CLEdBQUcscUJBQXFCLEVBQ3BELElBQUksRUFBRTtRQUNaLGNBQWMsRUFBRSxjQUFjLENBQUM7UUFDL0IsZ0JBQWdCLEVBQUUsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDOUMsU0FBUyxDQUFDLEVBQUUsZUFBZSxDQUFDO0tBQzdCLEVBQ08sUUFBUSxDQUFDLDRCQUFnQixFQUMvQjtJQUVTLEtBQUssa0JBRWpCO0lBRVksSUFBSSxrQkFFaEI7SUFFRDs7O09BR0c7SUFDVSxNQUFNLElBQUksT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBV2xEO0NBQ0YifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"prover-publisher-factory.d.ts","sourceRoot":"","sources":["../src/prover-publisher-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,qBAAa,sBAAsB;IAE/B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,QAAQ,CAAC;IAPnB,YACU,MAAM,EAAE,oBAAoB,GAAG,qBAAqB,EACpD,IAAI,EAAE;QACZ,cAAc,EAAE,cAAc,CAAC;QAC/B,gBAAgB,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC9C,SAAS,CAAC,EAAE,eAAe,CAAC;KAC7B,EACO,QAAQ,CAAC,4BAAgB,EAC/B;IAES,KAAK,kBAEjB;IAEM,IAAI,SAEV;IAED;;;OAGG;IACU,MAAM,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAWlD;CACF"}
1
+ {"version":3,"file":"prover-publisher-factory.d.ts","sourceRoot":"","sources":["../src/prover-publisher-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,qBAAa,sBAAsB;IAE/B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,QAAQ,CAAC;IAPnB,YACU,MAAM,EAAE,oBAAoB,GAAG,qBAAqB,EACpD,IAAI,EAAE;QACZ,cAAc,EAAE,cAAc,CAAC;QAC/B,gBAAgB,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC9C,SAAS,CAAC,EAAE,eAAe,CAAC;KAC7B,EACO,QAAQ,CAAC,4BAAgB,EAC/B;IAES,KAAK,kBAEjB;IAEY,IAAI,kBAEhB;IAED;;;OAGG;IACU,MAAM,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAWlD;CACF"}
@@ -9,10 +9,10 @@ export class ProverPublisherFactory {
9
9
  this.bindings = bindings;
10
10
  }
11
11
  async start() {
12
- await this.deps.publisherManager.loadState();
12
+ await this.deps.publisherManager.start();
13
13
  }
14
- stop() {
15
- this.deps.publisherManager.interrupt();
14
+ async stop() {
15
+ await this.deps.publisherManager.stop();
16
16
  }
17
17
  /**
18
18
  * Creates a new Prover Publisher instance.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/prover-node",
3
- "version": "0.0.1-commit.04852196a",
3
+ "version": "0.0.1-commit.04d373f",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -56,27 +56,28 @@
56
56
  ]
57
57
  },
58
58
  "dependencies": {
59
- "@aztec/archiver": "0.0.1-commit.04852196a",
60
- "@aztec/bb-prover": "0.0.1-commit.04852196a",
61
- "@aztec/blob-client": "0.0.1-commit.04852196a",
62
- "@aztec/blob-lib": "0.0.1-commit.04852196a",
63
- "@aztec/constants": "0.0.1-commit.04852196a",
64
- "@aztec/epoch-cache": "0.0.1-commit.04852196a",
65
- "@aztec/ethereum": "0.0.1-commit.04852196a",
66
- "@aztec/foundation": "0.0.1-commit.04852196a",
67
- "@aztec/kv-store": "0.0.1-commit.04852196a",
68
- "@aztec/l1-artifacts": "0.0.1-commit.04852196a",
69
- "@aztec/node-keystore": "0.0.1-commit.04852196a",
70
- "@aztec/node-lib": "0.0.1-commit.04852196a",
71
- "@aztec/noir-protocol-circuits-types": "0.0.1-commit.04852196a",
72
- "@aztec/p2p": "0.0.1-commit.04852196a",
73
- "@aztec/protocol-contracts": "0.0.1-commit.04852196a",
74
- "@aztec/prover-client": "0.0.1-commit.04852196a",
75
- "@aztec/sequencer-client": "0.0.1-commit.04852196a",
76
- "@aztec/simulator": "0.0.1-commit.04852196a",
77
- "@aztec/stdlib": "0.0.1-commit.04852196a",
78
- "@aztec/telemetry-client": "0.0.1-commit.04852196a",
79
- "@aztec/world-state": "0.0.1-commit.04852196a",
59
+ "@aztec/archiver": "0.0.1-commit.04d373f",
60
+ "@aztec/bb-prover": "0.0.1-commit.04d373f",
61
+ "@aztec/blob-client": "0.0.1-commit.04d373f",
62
+ "@aztec/blob-lib": "0.0.1-commit.04d373f",
63
+ "@aztec/constants": "0.0.1-commit.04d373f",
64
+ "@aztec/epoch-cache": "0.0.1-commit.04d373f",
65
+ "@aztec/ethereum": "0.0.1-commit.04d373f",
66
+ "@aztec/foundation": "0.0.1-commit.04d373f",
67
+ "@aztec/kv-store": "0.0.1-commit.04d373f",
68
+ "@aztec/l1-artifacts": "0.0.1-commit.04d373f",
69
+ "@aztec/native": "0.0.1-commit.04d373f",
70
+ "@aztec/node-keystore": "0.0.1-commit.04d373f",
71
+ "@aztec/node-lib": "0.0.1-commit.04d373f",
72
+ "@aztec/noir-protocol-circuits-types": "0.0.1-commit.04d373f",
73
+ "@aztec/p2p": "0.0.1-commit.04d373f",
74
+ "@aztec/protocol-contracts": "0.0.1-commit.04d373f",
75
+ "@aztec/prover-client": "0.0.1-commit.04d373f",
76
+ "@aztec/sequencer-client": "0.0.1-commit.04d373f",
77
+ "@aztec/simulator": "0.0.1-commit.04d373f",
78
+ "@aztec/stdlib": "0.0.1-commit.04d373f",
79
+ "@aztec/telemetry-client": "0.0.1-commit.04d373f",
80
+ "@aztec/world-state": "0.0.1-commit.04d373f",
80
81
  "source-map-support": "^0.5.21",
81
82
  "tslib": "^2.4.0",
82
83
  "viem": "npm:@aztec/viem@2.38.2"
@@ -30,7 +30,7 @@ export async function downloadEpochProvingJob(
30
30
 
31
31
  const dataUrls = makeSnapshotPaths(location);
32
32
  log.info(`Downloading state snapshot from ${location} to local data directory`, { metadata, dataUrls });
33
- await snapshotSync({ dataUrls }, log, { ...config, ...metadata, snapshotsUrl: location });
33
+ await snapshotSync({ dataUrls }, log, { ...config, ...metadata, fileStore });
34
34
 
35
35
  const dataPath = urlJoin(location, 'data.bin');
36
36
  const localPath = config.jobDataDownloadPath;
@@ -1,10 +1,11 @@
1
- import { createArchiverStore } from '@aztec/archiver';
1
+ import { createArchiverStore, createContractDataSource } from '@aztec/archiver';
2
2
  import type { L1ContractsConfig } from '@aztec/ethereum/config';
3
3
  import type { Logger } from '@aztec/foundation/log';
4
4
  import { type ProverClientConfig, createProverClient } from '@aztec/prover-client';
5
5
  import { ProverBrokerConfig, createAndStartProvingBroker } from '@aztec/prover-client/broker';
6
6
  import { PublicProcessorFactory } from '@aztec/simulator/server';
7
7
  import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
8
+ import type { GenesisData } from '@aztec/stdlib/world-state';
8
9
  import { getTelemetryClient } from '@aztec/telemetry-client';
9
10
  import { createWorldState } from '@aztec/world-state';
10
11
 
@@ -23,17 +24,27 @@ export async function rerunEpochProvingJob(
23
24
  localPath: string,
24
25
  log: Logger,
25
26
  config: DataStoreConfig & ProverBrokerConfig & ProverClientConfig & Pick<L1ContractsConfig, 'aztecEpochDuration'>,
27
+ genesis?: GenesisData,
26
28
  ) {
27
29
  const jobData = deserializeEpochProvingJobData(readFileSync(localPath));
28
30
  log.info(`Loaded proving job data for epoch ${jobData.epochNumber}`);
29
31
 
30
32
  const telemetry = getTelemetryClient();
31
33
  const metrics = new ProverNodeJobMetrics(telemetry.getMeter('prover-job'), telemetry.getTracer('prover-job'));
32
- const worldState = await createWorldState(config);
33
- const archiver = await createArchiverStore(config, { epochDuration: config.aztecEpochDuration });
34
- const publicProcessorFactory = new PublicProcessorFactory(archiver, undefined, undefined, log.getBindings());
34
+ const worldState = await createWorldState(config, genesis);
35
+ const initialBlockHash = await worldState.getInitialHeader().hash();
36
+ const archiver = await createArchiverStore(config, initialBlockHash);
37
+ const publicProcessorFactory = new PublicProcessorFactory(
38
+ createContractDataSource(archiver),
39
+ undefined,
40
+ undefined,
41
+ log.getBindings(),
42
+ );
35
43
 
36
- const publisher = { submitEpochProof: () => Promise.resolve(true) };
44
+ const publisher = {
45
+ submitEpochProof: () => Promise.resolve(true),
46
+ analyzeEpochProofSubmission: () => Promise.resolve(),
47
+ };
37
48
  const l2BlockSourceForReorgDetection = undefined;
38
49
  const deadline = undefined;
39
50
 
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable no-console */
2
2
  import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
3
- import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
4
3
  import { EthAddress } from '@aztec/foundation/eth-address';
5
4
  import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc';
6
5
  import { createLogger } from '@aztec/foundation/log';
@@ -50,7 +49,7 @@ async function rerunFailedEpoch(provingJobUrl: string, baseLocalDir: string) {
50
49
  logger.info(`Rerunning proving job from ${jobPath} with state from ${dataDir}`, metadata);
51
50
  const result = await rerunEpochProvingJob(jobPath, logger, {
52
51
  ...config,
53
- l1Contracts: { rollupAddress: metadata.rollupAddress } as L1ContractAddresses,
52
+ rollupAddress: metadata.rollupAddress,
54
53
  rollupVersion: metadata.rollupVersion,
55
54
  });
56
55
 
package/src/config.ts CHANGED
@@ -60,7 +60,7 @@ export const specificProverNodeConfigMappings: ConfigMappingsType<SpecificProver
60
60
  proverNodeMaxParallelBlocksPerEpoch: {
61
61
  env: 'PROVER_NODE_MAX_PARALLEL_BLOCKS_PER_EPOCH',
62
62
  description: 'The Maximum number of blocks to process in parallel while proving an epoch',
63
- ...numberConfigHelper(32),
63
+ ...numberConfigHelper(0),
64
64
  },
65
65
  proverNodeFailedEpochStore: {
66
66
  env: 'PROVER_NODE_FAILED_EPOCH_STORE',
package/src/factory.ts CHANGED
@@ -3,6 +3,7 @@ import type { BlobClientInterface } from '@aztec/blob-client/client';
3
3
  import { Blob } from '@aztec/blob-lib';
4
4
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
5
5
  import { createEthereumChain } from '@aztec/ethereum/chain';
6
+ import { makeL1HttpTransport } from '@aztec/ethereum/client';
6
7
  import { RollupContract } from '@aztec/ethereum/contracts';
7
8
  import { L1TxUtils } from '@aztec/ethereum/l1-tx-utils';
8
9
  import { PublisherManager } from '@aztec/ethereum/publisher-manager';
@@ -27,7 +28,7 @@ import type {
27
28
  } from '@aztec/stdlib/interfaces/server';
28
29
  import { L1Metrics, type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
29
30
 
30
- import { createPublicClient, fallback, http } from 'viem';
31
+ import { createPublicClient } from 'viem';
31
32
 
32
33
  import type { SpecificProverNodeConfig } from './config.js';
33
34
  import { EpochMonitor } from './monitors/epoch-monitor.js';
@@ -95,11 +96,11 @@ export async function createProverNode(
95
96
 
96
97
  const publicClient = createPublicClient({
97
98
  chain: chain.chainInfo,
98
- transport: fallback(config.l1RpcUrls.map((url: string) => http(url, { batch: false }))),
99
+ transport: makeL1HttpTransport(config.l1RpcUrls, { timeout: config.l1HttpTimeoutMS }),
99
100
  pollingInterval: config.viemPollingIntervalMS,
100
101
  });
101
102
 
102
- const rollupContract = new RollupContract(publicClient, config.l1Contracts.rollupAddress.toString());
103
+ const rollupContract = new RollupContract(publicClient, config.rollupAddress.toString());
103
104
 
104
105
  const l1TxUtils = deps.l1TxUtils
105
106
  ? [deps.l1TxUtils]
@@ -118,11 +119,27 @@ export async function createProverNode(
118
119
  { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
119
120
  );
120
121
 
122
+ // Create a funder L1TxUtils from the keystore funding account (if configured)
123
+ const fundingSigner = keyStoreManager?.createFundingSigner();
124
+ let funderL1TxUtils: L1TxUtils | undefined;
125
+ if (fundingSigner) {
126
+ const [funder] = await createL1TxUtilsFromSigners(
127
+ publicClient,
128
+ [fundingSigner],
129
+ { ...config, scope: 'prover' },
130
+ { telemetry, logger: log.createChild('l1-tx-utils:funder'), dateProvider },
131
+ );
132
+ funderL1TxUtils = funder;
133
+ }
134
+
121
135
  const publisherFactory =
122
136
  deps.publisherFactory ??
123
137
  new ProverPublisherFactory(config, {
124
138
  rollupContract,
125
- publisherManager: new PublisherManager(l1TxUtils, getPublisherConfigFromProverConfig(config), log.getBindings()),
139
+ publisherManager: new PublisherManager(l1TxUtils, getPublisherConfigFromProverConfig(config), {
140
+ bindings: log.getBindings(),
141
+ funder: funderL1TxUtils,
142
+ }),
126
143
  telemetry,
127
144
  });
128
145
 
@@ -1,11 +1,10 @@
1
- import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
2
1
  import { asyncPool } from '@aztec/foundation/async-pool';
3
2
  import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
4
- import { padArrayEnd } from '@aztec/foundation/collection';
5
3
  import { Fr } from '@aztec/foundation/curves/bn254';
6
4
  import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
7
5
  import { RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise';
8
6
  import { Timer } from '@aztec/foundation/timer';
7
+ import { AVM_MAX_CONCURRENT_SIMULATIONS } from '@aztec/native';
9
8
  import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
10
9
  import { protocolContractsHash } from '@aztec/protocol-contracts';
11
10
  import { buildFinalBlobChallenges } from '@aztec/prover-client/helpers';
@@ -19,8 +18,8 @@ import {
19
18
  EpochProvingJobTerminalState,
20
19
  type ForkMerkleTreeOperations,
21
20
  } from '@aztec/stdlib/interfaces/server';
21
+ import { appendL1ToL2MessagesToTree } from '@aztec/stdlib/messaging';
22
22
  import { CheckpointConstantData } from '@aztec/stdlib/rollup';
23
- import { MerkleTreeId } from '@aztec/stdlib/trees';
24
23
  import type { ProcessedTx, Tx } from '@aztec/stdlib/tx';
25
24
  import { Attributes, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client';
26
25
 
@@ -47,6 +46,7 @@ export class EpochProvingJob implements Traceable {
47
46
  private uuid: string;
48
47
 
49
48
  private runPromise: Promise<void> | undefined;
49
+ private abortController = new AbortController();
50
50
  private epochCheckPromise: RunningPromise | undefined;
51
51
  private deadlineTimeoutHandler: NodeJS.Timeout | undefined;
52
52
 
@@ -57,7 +57,7 @@ export class EpochProvingJob implements Traceable {
57
57
  private dbProvider: Pick<ForkMerkleTreeOperations, 'fork'>,
58
58
  private prover: EpochProver,
59
59
  private publicProcessorFactory: PublicProcessorFactory,
60
- private publisher: Pick<ProverNodePublisher, 'submitEpochProof'>,
60
+ private publisher: Pick<ProverNodePublisher, 'submitEpochProof' | 'analyzeEpochProofSubmission'>,
61
61
  private l2BlockSource: L2BlockSource | undefined,
62
62
  private metrics: ProverNodeJobMetrics,
63
63
  private deadline: Date | undefined,
@@ -148,21 +148,32 @@ export class EpochProvingJob implements Traceable {
148
148
  this.runPromise = promise;
149
149
 
150
150
  try {
151
+ const blobTimer = new Timer();
151
152
  const blobFieldsPerCheckpoint = this.checkpoints.map(checkpoint => checkpoint.toBlobFields());
152
- this.log.info(`Blob fields per checkpoint: ${timer.ms()}ms`);
153
153
  const finalBlobBatchingChallenges = await buildFinalBlobChallenges(blobFieldsPerCheckpoint);
154
- this.log.info(`Final blob batching challeneger: ${timer.ms()}ms`);
154
+ this.metrics.recordBlobProcessing(blobTimer.ms());
155
155
 
156
156
  this.prover.startNewEpoch(epochNumber, epochSizeCheckpoints, finalBlobBatchingChallenges);
157
+ const chonkTimer = new Timer();
157
158
  await this.prover.startChonkVerifierCircuits(Array.from(this.txs.values()));
159
+ this.metrics.recordChonkVerifier(chonkTimer.ms());
158
160
 
159
161
  // Everything in the epoch should have the same chainId and version.
160
162
  const { chainId, version } = this.checkpoints[0].blocks[0].header.globalVariables;
161
163
 
162
164
  const previousBlockHeaders = this.gatherPreviousBlockHeaders();
163
165
 
164
- await asyncPool(this.config.parallelBlockLimit ?? 32, this.checkpoints, async checkpoint => {
166
+ const allCheckpointsTimer = new Timer();
167
+
168
+ const parallelism = this.config.parallelBlockLimit
169
+ ? this.config.parallelBlockLimit
170
+ : AVM_MAX_CONCURRENT_SIMULATIONS > 0
171
+ ? AVM_MAX_CONCURRENT_SIMULATIONS
172
+ : this.checkpoints.length;
173
+
174
+ await this.processCheckpoints(parallelism, async checkpoint => {
165
175
  this.checkState();
176
+ const checkpointTimer = new Timer();
166
177
 
167
178
  const checkpointIndex = checkpoint.number - fromCheckpoint;
168
179
  const checkpointConstants = CheckpointConstantData.from({
@@ -179,11 +190,12 @@ export class EpochProvingJob implements Traceable {
179
190
  const previousHeader = previousBlockHeaders[checkpointIndex];
180
191
  const l1ToL2Messages = this.getL1ToL2Messages(checkpoint);
181
192
 
182
- this.log.verbose(`Starting processing checkpoint ${checkpoint.number}`, {
193
+ this.log.debug(`Starting processing checkpoint ${checkpoint.number}`, {
183
194
  number: checkpoint.number,
184
195
  checkpointHash: checkpoint.hash().toString(),
185
- lastArchive: checkpoint.header.lastArchiveRoot,
186
- previousHeader: previousHeader.hash(),
196
+ headerHash: checkpoint.header.hash().toString(),
197
+ numL1ToL2Messages: l1ToL2Messages.length,
198
+ previousBlockNumber: previousHeader.globalVariables.blockNumber,
187
199
  uuid: this.uuid,
188
200
  });
189
201
 
@@ -196,6 +208,7 @@ export class EpochProvingJob implements Traceable {
196
208
  );
197
209
 
198
210
  for (let blockIndex = 0; blockIndex < checkpoint.blocks.length; blockIndex++) {
211
+ const blockTimer = new Timer();
199
212
  const block = checkpoint.blocks[blockIndex];
200
213
  const globalVariables = block.header.globalVariables;
201
214
  const txs = this.getTxs(block);
@@ -216,22 +229,26 @@ export class EpochProvingJob implements Traceable {
216
229
 
217
230
  // Process public fns. L1 to L2 messages are only inserted for the first block of a checkpoint,
218
231
  // as the fork for subsequent blocks already includes them from the previous block's synced state.
219
- const db = await this.createFork(
220
- BlockNumber(block.number - 1),
221
- blockIndex === 0 ? l1ToL2Messages : undefined,
222
- );
223
- const config = PublicSimulatorConfig.from({
224
- proverId: this.prover.getProverId().toField(),
225
- skipFeeEnforcement: false,
226
- collectDebugLogs: false,
227
- collectHints: true,
228
- collectPublicInputs: true,
229
- collectStatistics: false,
230
- });
231
- const publicProcessor = this.publicProcessorFactory.create(db, globalVariables, config);
232
- const processed = await this.processTxs(publicProcessor, txs);
233
- await this.prover.addTxs(processed);
234
- await db.close();
232
+ {
233
+ await using db = await this.createFork(
234
+ BlockNumber(block.number - 1),
235
+ blockIndex === 0 ? l1ToL2Messages : undefined,
236
+ );
237
+ this.checkState();
238
+ const config = PublicSimulatorConfig.from({
239
+ proverId: this.prover.getProverId().toField(),
240
+ skipFeeEnforcement: false,
241
+ collectDebugLogs: false,
242
+ collectHints: true,
243
+ collectPublicInputs: true,
244
+ collectStatistics: false,
245
+ });
246
+ const publicProcessor = this.publicProcessorFactory.create(db, globalVariables, config);
247
+ const processed = await this.processTxs(publicProcessor, txs);
248
+ this.checkState();
249
+ await this.prover.addTxs(processed);
250
+ }
251
+ this.checkState();
235
252
  this.log.verbose(`Processed all ${txs.length} txs for block ${block.number}`, {
236
253
  blockNumber: block.number,
237
254
  blockHash: (await block.hash()).toString(),
@@ -241,8 +258,11 @@ export class EpochProvingJob implements Traceable {
241
258
  // Mark block as completed to pad it
242
259
  const expectedBlockHeader = block.header;
243
260
  await this.prover.setBlockCompleted(block.number, expectedBlockHeader);
261
+ this.metrics.recordBlockProcessing(blockTimer.ms());
244
262
  }
263
+ this.metrics.recordCheckpointProcessing(checkpointTimer.ms());
245
264
  });
265
+ this.metrics.recordAllCheckpointsProcessing(allCheckpointsTimer.ms());
246
266
 
247
267
  const executionTime = timer.ms();
248
268
 
@@ -254,8 +274,21 @@ export class EpochProvingJob implements Traceable {
254
274
 
255
275
  if (this.config.skipSubmitProof) {
256
276
  this.log.info(
257
- `Proof publishing is disabled. Dropping valid proof for epoch ${epochNumber} (checkpoints ${fromCheckpoint} to ${toCheckpoint})`,
277
+ `Proof publishing is disabled. Analyzing estimated L1 fees for epoch ${epochNumber} (checkpoints ${fromCheckpoint} to ${toCheckpoint})`,
258
278
  );
279
+ try {
280
+ await this.publisher.analyzeEpochProofSubmission({
281
+ fromCheckpoint,
282
+ toCheckpoint,
283
+ epochNumber,
284
+ publicInputs,
285
+ proof,
286
+ batchedBlobInputs,
287
+ attestations,
288
+ });
289
+ } catch (err) {
290
+ this.log.warn(`Failed to analyze estimated L1 fees for epoch ${epochNumber}`, err);
291
+ }
259
292
  this.state = 'completed';
260
293
  this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeCheckpoints, epochSizeBlocks, epochSizeTxs);
261
294
  return;
@@ -309,25 +342,56 @@ export class EpochProvingJob implements Traceable {
309
342
  */
310
343
  private async createFork(blockNumber: BlockNumber, l1ToL2Messages: Fr[] | undefined) {
311
344
  this.log.verbose(`Creating fork at ${blockNumber}`, { blockNumber });
312
- const db = await this.dbProvider.fork(blockNumber);
345
+ // temporary stack to control fork lifetime
346
+ await using cleanup = new AsyncDisposableStack();
347
+ const db = cleanup.use(await this.dbProvider.fork(blockNumber));
313
348
 
314
349
  if (l1ToL2Messages !== undefined) {
315
350
  this.log.verbose(`Inserting ${l1ToL2Messages.length} L1 to L2 messages in fork`, {
316
351
  blockNumber,
317
352
  l1ToL2Messages: l1ToL2Messages.map(m => m.toString()),
318
353
  });
319
- const l1ToL2MessagesPadded = padArrayEnd<Fr, number>(
320
- l1ToL2Messages,
321
- Fr.ZERO,
322
- NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
323
- 'Too many L1 to L2 messages',
324
- );
325
- await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
354
+ await appendL1ToL2MessagesToTree(db, l1ToL2Messages);
326
355
  }
327
356
 
357
+ // everything run succesfully so we can release this stack and give control of the fork's lifetime to the caller
358
+ cleanup.move();
328
359
  return db;
329
360
  }
330
361
 
362
+ private async processCheckpoints(
363
+ parallelism: number,
364
+ processCheckpoint: (checkpoint: Checkpoint) => Promise<void>,
365
+ ): Promise<void> {
366
+ let hasError = false;
367
+ let firstError: unknown;
368
+
369
+ await asyncPool(Math.max(parallelism, 1), this.checkpoints, async checkpoint => {
370
+ if (hasError || this.abortController.signal.aborted) {
371
+ return;
372
+ }
373
+
374
+ try {
375
+ this.checkState();
376
+ await processCheckpoint(checkpoint);
377
+ } catch (err) {
378
+ if (!hasError) {
379
+ hasError = true;
380
+ firstError = err;
381
+ this.failProcessing();
382
+ }
383
+ }
384
+ });
385
+
386
+ if (hasError) {
387
+ throw firstError;
388
+ }
389
+
390
+ if (this.abortController.signal.aborted) {
391
+ this.checkState();
392
+ }
393
+ }
394
+
331
395
  private progressState(state: EpochProvingJobState) {
332
396
  this.checkState();
333
397
  this.state = state;
@@ -341,12 +405,24 @@ export class EpochProvingJob implements Traceable {
341
405
 
342
406
  public async stop(state: EpochProvingJobTerminalState = 'stopped') {
343
407
  this.state = state;
344
- this.prover.cancel();
408
+ this.interruptProcessing();
345
409
  if (this.runPromise) {
346
410
  await this.runPromise;
347
411
  }
348
412
  }
349
413
 
414
+ private failProcessing() {
415
+ if (!EpochProvingJobTerminalState.includes(this.state)) {
416
+ this.state = 'failed';
417
+ }
418
+ this.interruptProcessing();
419
+ }
420
+
421
+ private interruptProcessing() {
422
+ this.abortController.abort();
423
+ this.prover.cancel();
424
+ }
425
+
350
426
  private scheduleDeadlineStop() {
351
427
  const deadline = this.deadline;
352
428
  if (deadline) {
@@ -381,7 +457,9 @@ export class EpochProvingJob implements Traceable {
381
457
  const intervalMs = Math.ceil((await l2BlockSource.getL1Constants()).ethereumSlotDuration / 2) * 1000;
382
458
  this.epochCheckPromise = new RunningPromise(
383
459
  async () => {
384
- const blockHeaders = await l2BlockSource.getCheckpointedBlockHeadersForEpoch(this.epochNumber);
460
+ const blockHeaders = (
461
+ await l2BlockSource.getBlocksData({ epoch: this.epochNumber, onlyCheckpointed: true })
462
+ ).map(d => d.header);
385
463
  const blockHashes = await Promise.all(blockHeaders.map(header => header.hash()));
386
464
  const thisBlocks = this.checkpoints.flatMap(checkpoint => checkpoint.blocks);
387
465
  const thisBlockHashes = await Promise.all(thisBlocks.map(block => block.hash()));
@@ -420,7 +498,11 @@ export class EpochProvingJob implements Traceable {
420
498
 
421
499
  private async processTxs(publicProcessor: PublicProcessor, txs: Tx[]): Promise<ProcessedTx[]> {
422
500
  const { deadline } = this;
423
- const [processedTxs, failedTxs] = await publicProcessor.process(txs, { deadline });
501
+ const [processedTxs, failedTxs] = await publicProcessor.process(txs, {
502
+ deadline,
503
+ signal: this.abortController.signal,
504
+ });
505
+ this.checkState();
424
506
 
425
507
  if (failedTxs.length) {
426
508
  const failedTxHashes = await Promise.all(failedTxs.map(({ tx }) => tx.getTxHash()));