@aztec/prover-node 0.69.0-devnet → 0.69.1-devnet

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.
@@ -1,7 +1,11 @@
1
1
  import { __esDecorate, __runInitializers } from "tslib";
2
- import { EpochProofQuotePayload, tryStop, } from '@aztec/circuit-types';
2
+ import { EpochProofQuotePayload, getTimestampRangeForEpoch, tryStop, } from '@aztec/circuit-types';
3
+ import { asyncPool } from '@aztec/foundation/async-pool';
3
4
  import { compact } from '@aztec/foundation/collection';
5
+ import { memoize } from '@aztec/foundation/decorators';
6
+ import { TimeoutError } from '@aztec/foundation/error';
4
7
  import { createLogger } from '@aztec/foundation/log';
8
+ import { retryUntil } from '@aztec/foundation/retry';
5
9
  import { DateProvider } from '@aztec/foundation/timer';
6
10
  import { PublicProcessorFactory } from '@aztec/simulator';
7
11
  import { Attributes, trackSpan } from '@aztec/telemetry-client';
@@ -17,6 +21,7 @@ let ProverNode = (() => {
17
21
  var _a;
18
22
  let _instanceExtraInitializers = [];
19
23
  let _createProvingJob_decorators;
24
+ let _getL1Constants_decorators;
20
25
  let _gatherEpochData_decorators;
21
26
  return _a = class ProverNode {
22
27
  constructor(prover, publisher, l2BlockSource, l1ToL2MessageSource, contractDataSource, worldState, coordination, quoteProvider, quoteSigner, claimsMonitor, epochsMonitor, bondManager, telemetryClient, options = {}) {
@@ -41,6 +46,9 @@ let ProverNode = (() => {
41
46
  pollingIntervalMs: 1000,
42
47
  maxPendingJobs: 100,
43
48
  maxParallelBlocksPerEpoch: 32,
49
+ txGatheringTimeoutMs: 60000,
50
+ txGatheringIntervalMs: 1000,
51
+ txGatheringMaxParallelRequests: 100,
44
52
  ...compact(options),
45
53
  };
46
54
  this.metrics = new ProverNodeMetrics(telemetryClient, 'ProverNode');
@@ -212,10 +220,15 @@ let ProverNode = (() => {
212
220
  this.jobs.delete(job.getId());
213
221
  return Promise.resolve();
214
222
  };
215
- const job = this.doCreateEpochProvingJob(epochNumber, blocks, txs, publicProcessorFactory, cleanUp);
223
+ const [_, endTimestamp] = getTimestampRangeForEpoch(epochNumber + 1n, await this.getL1Constants());
224
+ const deadline = new Date(Number(endTimestamp) * 1000);
225
+ const job = this.doCreateEpochProvingJob(epochNumber, deadline, blocks, txs, publicProcessorFactory, cleanUp);
216
226
  this.jobs.set(job.getId(), job);
217
227
  return job;
218
228
  }
229
+ getL1Constants() {
230
+ return this.l2BlockSource.getL1Constants();
231
+ }
219
232
  async gatherEpochData(epochNumber) {
220
233
  // Gather blocks for this epoch and their txs
221
234
  const blocks = await this.gatherBlocks(epochNumber);
@@ -230,19 +243,58 @@ let ProverNode = (() => {
230
243
  return blocks;
231
244
  }
232
245
  async gatherTxs(epochNumber, blocks) {
233
- const txs = await Promise.all(blocks.flatMap(block => block.body.txEffects
234
- .map(tx => tx.txHash)
235
- .map(txHash => this.coordination.getTxByHash(txHash).then(tx => [block.number, txHash, tx]))));
236
- const notFound = txs.filter(([_blockNum, _txHash, tx]) => !tx);
237
- if (notFound.length) {
238
- const notFoundList = notFound.map(([blockNum, txHash]) => `${txHash.toString()} (block ${blockNum})`).join(', ');
239
- throw new Error(`Txs not found for epoch ${epochNumber}: ${notFoundList}`);
246
+ let txsToFind = [];
247
+ const txHashToBlock = new Map();
248
+ const results = new Map();
249
+ for (const block of blocks) {
250
+ for (const tx of block.body.txEffects) {
251
+ txsToFind.push(tx.txHash);
252
+ txHashToBlock.set(tx.txHash.toString(), block.number);
253
+ }
254
+ }
255
+ const totalTxsRequired = txsToFind.length;
256
+ this.log.info(`Gathering a total of ${totalTxsRequired} txs for epoch=${epochNumber} made up of ${blocks.length} blocks`, { epochNumber });
257
+ let iteration = 0;
258
+ try {
259
+ await retryUntil(async () => {
260
+ const batch = [...txsToFind];
261
+ txsToFind = [];
262
+ const batchResults = await asyncPool(this.options.txGatheringMaxParallelRequests, batch, async (txHash) => {
263
+ const tx = await this.coordination.getTxByHash(txHash);
264
+ return [txHash, tx];
265
+ });
266
+ let found = 0;
267
+ for (const [txHash, maybeTx] of batchResults) {
268
+ if (maybeTx) {
269
+ found++;
270
+ results.set(txHash.toString(), maybeTx);
271
+ }
272
+ else {
273
+ txsToFind.push(txHash);
274
+ }
275
+ }
276
+ this.log.verbose(`Gathered ${found}/${batch.length} txs in iteration ${iteration} for epoch ${epochNumber}. In total ${results.size}/${totalTxsRequired} have been retrieved.`, { epochNumber });
277
+ iteration++;
278
+ // stop when we found all transactions
279
+ return txsToFind.length === 0;
280
+ }, 'Gather txs', this.options.txGatheringTimeoutMs / 1000, this.options.txGatheringIntervalMs / 1000);
281
+ }
282
+ catch (err) {
283
+ if (err && err instanceof TimeoutError) {
284
+ const notFoundList = txsToFind
285
+ .map(txHash => `${txHash.toString()} (block ${txHashToBlock.get(txHash.toString())})`)
286
+ .join(', ');
287
+ throw new Error(`Txs not found for epoch ${epochNumber}: ${notFoundList}`);
288
+ }
289
+ else {
290
+ throw err;
291
+ }
240
292
  }
241
- return txs.map(([_blockNumber, _txHash, tx]) => tx);
293
+ return Array.from(results.values());
242
294
  }
243
295
  /** Extracted for testing purposes. */
244
- doCreateEpochProvingJob(epochNumber, blocks, txs, publicProcessorFactory, cleanUp) {
245
- return new EpochProvingJob(this.worldState, epochNumber, blocks, txs, this.prover.createEpochProver(), publicProcessorFactory, this.publisher, this.l2BlockSource, this.l1ToL2MessageSource, this.metrics, { parallelBlockLimit: this.options.maxParallelBlocksPerEpoch }, cleanUp);
296
+ doCreateEpochProvingJob(epochNumber, deadline, blocks, txs, publicProcessorFactory, cleanUp) {
297
+ return new EpochProvingJob(this.worldState, epochNumber, blocks, txs, this.prover.createEpochProver(), publicProcessorFactory, this.publisher, this.l2BlockSource, this.l1ToL2MessageSource, this.metrics, deadline, { parallelBlockLimit: this.options.maxParallelBlocksPerEpoch }, cleanUp);
246
298
  }
247
299
  /** Extracted for testing purposes. */
248
300
  async triggerMonitors() {
@@ -253,12 +305,14 @@ let ProverNode = (() => {
253
305
  (() => {
254
306
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
255
307
  _createProvingJob_decorators = [trackSpan('ProverNode.createProvingJob', epochNumber => ({ [Attributes.EPOCH_NUMBER]: Number(epochNumber) }))];
308
+ _getL1Constants_decorators = [memoize];
256
309
  _gatherEpochData_decorators = [trackSpan('ProverNode.gatherEpochData', epochNumber => ({ [Attributes.EPOCH_NUMBER]: Number(epochNumber) }))];
257
310
  __esDecorate(_a, null, _createProvingJob_decorators, { kind: "method", name: "createProvingJob", static: false, private: false, access: { has: obj => "createProvingJob" in obj, get: obj => obj.createProvingJob }, metadata: _metadata }, null, _instanceExtraInitializers);
311
+ __esDecorate(_a, null, _getL1Constants_decorators, { kind: "method", name: "getL1Constants", static: false, private: false, access: { has: obj => "getL1Constants" in obj, get: obj => obj.getL1Constants }, metadata: _metadata }, null, _instanceExtraInitializers);
258
312
  __esDecorate(_a, null, _gatherEpochData_decorators, { kind: "method", name: "gatherEpochData", static: false, private: false, access: { has: obj => "gatherEpochData" in obj, get: obj => obj.gatherEpochData }, metadata: _metadata }, null, _instanceExtraInitializers);
259
313
  if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
260
314
  })(),
261
315
  _a;
262
316
  })();
263
317
  export { ProverNode };
264
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmVyLW5vZGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcHJvdmVyLW5vZGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFHTCxzQkFBc0IsRUFXdEIsT0FBTyxHQUNSLE1BQU0sc0JBQXNCLENBQUM7QUFFOUIsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFJdkQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDMUQsT0FBTyxFQUFFLFVBQVUsRUFBcUQsU0FBUyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHbkgsT0FBTyxFQUFFLGVBQWUsRUFBNkIsTUFBTSw0QkFBNEIsQ0FBQztBQUN4RixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFZakQ7Ozs7O0dBS0c7SUFDVSxVQUFVOzs7OztzQkFBVixVQUFVO1lBWXJCLFlBQ21CLE1BQTBCLEVBQzFCLFNBQXNCLEVBQ3RCLGFBQTZDLEVBQzdDLG1CQUF3QyxFQUN4QyxrQkFBc0MsRUFDdEMsVUFBa0MsRUFDbEMsWUFBaUQsRUFDakQsYUFBNEIsRUFDNUIsV0FBd0IsRUFDeEIsYUFBNEIsRUFDNUIsYUFBMkIsRUFDM0IsV0FBd0IsRUFDeEIsZUFBZ0MsRUFDakQsVUFBc0MsRUFBRTtnQkFidkIsV0FBTSxJQWJkLG1EQUFVLEVBYUYsTUFBTSxFQUFvQjtnQkFDMUIsY0FBUyxHQUFULFNBQVMsQ0FBYTtnQkFDdEIsa0JBQWEsR0FBYixhQUFhLENBQWdDO2dCQUM3Qyx3QkFBbUIsR0FBbkIsbUJBQW1CLENBQXFCO2dCQUN4Qyx1QkFBa0IsR0FBbEIsa0JBQWtCLENBQW9CO2dCQUN0QyxlQUFVLEdBQVYsVUFBVSxDQUF3QjtnQkFDbEMs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
318
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmVyLW5vZGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcHJvdmVyLW5vZGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFHTCxzQkFBc0IsRUFZdEIseUJBQXlCLEVBQ3pCLE9BQU8sR0FDUixNQUFNLHNCQUFzQixDQUFDO0FBRTlCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDdkQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDckQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUl2RCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUMxRCxPQUFPLEVBQUUsVUFBVSxFQUFxRCxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUduSCxPQUFPLEVBQUUsZUFBZSxFQUE2QixNQUFNLDRCQUE0QixDQUFDO0FBQ3hGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQWVqRDs7Ozs7R0FLRztJQUNVLFVBQVU7Ozs7OztzQkFBVixVQUFVO1lBWXJCLFlBQ3FCLE1BQTBCLEVBQzFCLFNBQXNCLEVBQ3RCLGFBQTZDLEVBQzdDLG1CQUF3QyxFQUN4QyxrQkFBc0MsRUFDdEMsVUFBa0MsRUFDbEMsWUFBaUQsRUFDakQsYUFBNEIsRUFDNUIsV0FBd0IsRUFDeEIsYUFBNEIsRUFDNUIsYUFBMkIsRUFDM0IsV0FBd0IsRUFDeEIsZUFBZ0MsRUFDbkQsVUFBc0MsRUFBRTtnQkFickIsV0FB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
@@ -0,0 +1,10 @@
1
+ import { type EpochProverManager } from '@aztec/circuit-types';
2
+ import { type L1Publisher } from '@aztec/sequencer-client';
3
+ import { ProverNode } from '../prover-node.js';
4
+ declare class TestProverNode_ extends ProverNode {
5
+ prover: EpochProverManager;
6
+ publisher: L1Publisher;
7
+ }
8
+ export type TestProverNode = TestProverNode_;
9
+ export {};
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,cAAM,eAAgB,SAAQ,UAAU;IACtB,MAAM,EAAG,kBAAkB,CAAC;IAC5B,SAAS,EAAG,WAAW,CAAC;CACzC;AAED,MAAM,MAAM,cAAc,GAAG,eAAe,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { ProverNode } from '../prover-node.js';
2
+ class TestProverNode_ extends ProverNode {
3
+ }
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVzdC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFL0MsTUFBTSxlQUFnQixTQUFRLFVBQVU7Q0FHdkMifQ==
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@aztec/prover-node",
3
- "version": "0.69.0-devnet",
3
+ "version": "0.69.1-devnet",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
7
- "./config": "./dest/config.js"
7
+ "./config": "./dest/config.js",
8
+ "./test": "./dest/test/index.js"
8
9
  },
9
10
  "inherits": [
10
11
  "../package.common.json"
@@ -52,22 +53,23 @@
52
53
  ]
53
54
  },
54
55
  "dependencies": {
55
- "@aztec/archiver": "0.69.0-devnet",
56
- "@aztec/bb-prover": "0.69.0-devnet",
57
- "@aztec/circuit-types": "0.69.0-devnet",
58
- "@aztec/circuits.js": "0.69.0-devnet",
59
- "@aztec/epoch-cache": "0.69.0-devnet",
60
- "@aztec/ethereum": "0.69.0-devnet",
61
- "@aztec/foundation": "0.69.0-devnet",
62
- "@aztec/kv-store": "0.69.0-devnet",
63
- "@aztec/l1-artifacts": "0.69.0-devnet",
64
- "@aztec/p2p": "0.69.0-devnet",
65
- "@aztec/prover-client": "0.69.0-devnet",
66
- "@aztec/sequencer-client": "0.69.0-devnet",
67
- "@aztec/simulator": "0.69.0-devnet",
68
- "@aztec/telemetry-client": "0.69.0-devnet",
69
- "@aztec/types": "0.69.0-devnet",
70
- "@aztec/world-state": "0.69.0-devnet",
56
+ "@aztec/archiver": "0.69.1-devnet",
57
+ "@aztec/bb-prover": "0.69.1-devnet",
58
+ "@aztec/blob-sink": "0.69.1-devnet",
59
+ "@aztec/circuit-types": "0.69.1-devnet",
60
+ "@aztec/circuits.js": "0.69.1-devnet",
61
+ "@aztec/epoch-cache": "0.69.1-devnet",
62
+ "@aztec/ethereum": "0.69.1-devnet",
63
+ "@aztec/foundation": "0.69.1-devnet",
64
+ "@aztec/kv-store": "0.69.1-devnet",
65
+ "@aztec/l1-artifacts": "0.69.1-devnet",
66
+ "@aztec/p2p": "0.69.1-devnet",
67
+ "@aztec/prover-client": "0.69.1-devnet",
68
+ "@aztec/sequencer-client": "0.69.1-devnet",
69
+ "@aztec/simulator": "0.69.1-devnet",
70
+ "@aztec/telemetry-client": "0.69.1-devnet",
71
+ "@aztec/types": "0.69.1-devnet",
72
+ "@aztec/world-state": "0.69.1-devnet",
71
73
  "source-map-support": "^0.5.21",
72
74
  "tslib": "^2.4.0",
73
75
  "viem": "^2.7.15"
package/src/config.ts CHANGED
@@ -1,11 +1,5 @@
1
1
  import { type ArchiverConfig, archiverConfigMappings, getArchiverConfigFromEnv } from '@aztec/archiver/config';
2
2
  import { type ACVMConfig, type BBConfig } from '@aztec/bb-prover/config';
3
- import {
4
- type ProverAgentConfig,
5
- type ProverBrokerConfig,
6
- proverAgentConfigMappings,
7
- proverBrokerConfigMappings,
8
- } from '@aztec/circuit-types/config';
9
3
  import {
10
4
  type ConfigMappingsType,
11
5
  bigintConfigHelper,
@@ -14,6 +8,12 @@ import {
14
8
  } from '@aztec/foundation/config';
15
9
  import { type DataStoreConfig, dataConfigMappings, getDataConfigFromEnv } from '@aztec/kv-store/config';
16
10
  import { type P2PConfig, getP2PConfigFromEnv, p2pConfigMappings } from '@aztec/p2p/config';
11
+ import {
12
+ type ProverAgentConfig,
13
+ type ProverBrokerConfig,
14
+ proverAgentConfigMappings,
15
+ proverBrokerConfigMappings,
16
+ } from '@aztec/prover-client/broker';
17
17
  import {
18
18
  type ProverClientConfig,
19
19
  bbConfigMappings,
@@ -53,6 +53,9 @@ type SpecificProverNodeConfig = {
53
53
  proverNodeMaxPendingJobs: number;
54
54
  proverNodePollingIntervalMs: number;
55
55
  proverNodeMaxParallelBlocksPerEpoch: number;
56
+ txGatheringTimeoutMs: number;
57
+ txGatheringIntervalMs: number;
58
+ txGatheringMaxParallelRequests: number;
56
59
  };
57
60
 
58
61
  export type QuoteProviderConfig = {
@@ -77,6 +80,21 @@ const specificProverNodeConfigMappings: ConfigMappingsType<SpecificProverNodeCon
77
80
  description: 'The Maximum number of blocks to process in parallel while proving an epoch',
78
81
  ...numberConfigHelper(32),
79
82
  },
83
+ txGatheringTimeoutMs: {
84
+ env: 'PROVER_NODE_TX_GATHERING_TIMEOUT_MS',
85
+ description: 'The maximum amount of time to wait for tx data to be available',
86
+ ...numberConfigHelper(60_000),
87
+ },
88
+ txGatheringIntervalMs: {
89
+ env: 'PROVER_NODE_TX_GATHERING_INTERVAL_MS',
90
+ description: 'How often to check that tx data is available',
91
+ ...numberConfigHelper(1_000),
92
+ },
93
+ txGatheringMaxParallelRequests: {
94
+ env: 'PROVER_NODE_TX_GATHERING_MAX_PARALLEL_REQUESTS',
95
+ description: 'How many txs to load up a time',
96
+ ...numberConfigHelper(100),
97
+ },
80
98
  };
81
99
 
82
100
  const quoteProviderConfigMappings: ConfigMappingsType<QuoteProviderConfig> = {
package/src/factory.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { type Archiver, createArchiver } from '@aztec/archiver';
2
+ import { type BlobSinkClientInterface, createBlobSinkClient } from '@aztec/blob-sink/client';
2
3
  import { type ProverCoordination, type ProvingJobBroker } from '@aztec/circuit-types';
3
4
  import { EpochCache } from '@aztec/epoch-cache';
4
5
  import { createEthereumChain } from '@aztec/ethereum';
@@ -34,12 +35,14 @@ export async function createProverNode(
34
35
  aztecNodeTxProvider?: ProverCoordination;
35
36
  archiver?: Archiver;
36
37
  publisher?: L1Publisher;
38
+ blobSinkClient?: BlobSinkClientInterface;
37
39
  broker?: ProvingJobBroker;
38
40
  } = {},
39
41
  ) {
40
42
  const telemetry = deps.telemetry ?? new NoopTelemetryClient();
43
+ const blobSinkClient = deps.blobSinkClient ?? createBlobSinkClient(config.blobSinkUrl);
41
44
  const log = deps.log ?? createLogger('prover-node');
42
- const archiver = deps.archiver ?? (await createArchiver(config, telemetry, { blockUntilSync: true }));
45
+ const archiver = deps.archiver ?? (await createArchiver(config, blobSinkClient, telemetry, { blockUntilSync: true }));
43
46
  log.verbose(`Created archiver and synced to block ${await archiver.getBlockNumber()}`);
44
47
 
45
48
  const worldStateConfig = { ...config, worldStateProvenBlocksOnly: false };
@@ -50,7 +53,7 @@ export async function createProverNode(
50
53
  const prover = await createProverClient(config, worldStateSynchronizer, broker, telemetry);
51
54
 
52
55
  // REFACTOR: Move publisher out of sequencer package and into an L1-related package
53
- const publisher = deps.publisher ?? new L1Publisher(config, telemetry);
56
+ const publisher = deps.publisher ?? new L1Publisher(config, { telemetry, blobSinkClient });
54
57
 
55
58
  const epochCache = await EpochCache.create(config.l1Contracts.rollupAddress, config);
56
59
 
@@ -71,6 +74,9 @@ export async function createProverNode(
71
74
  maxPendingJobs: config.proverNodeMaxPendingJobs,
72
75
  pollingIntervalMs: config.proverNodePollingIntervalMs,
73
76
  maxParallelBlocksPerEpoch: config.proverNodeMaxParallelBlocksPerEpoch,
77
+ txGatheringMaxParallelRequests: config.txGatheringMaxParallelRequests,
78
+ txGatheringIntervalMs: config.txGatheringIntervalMs,
79
+ txGatheringTimeoutMs: config.txGatheringTimeoutMs,
74
80
  };
75
81
 
76
82
  const claimsMonitor = new ClaimsMonitor(publisher, telemetry, proverNodeConfig);
@@ -1,7 +1,7 @@
1
1
  import {
2
- EmptyTxValidator,
3
2
  type EpochProver,
4
3
  type EpochProvingJobState,
4
+ EpochProvingJobTerminalState,
5
5
  type ForkMerkleTreeOperations,
6
6
  type L1ToL2MessageSource,
7
7
  type L2Block,
@@ -32,6 +32,7 @@ export class EpochProvingJob implements Traceable {
32
32
  private uuid: string;
33
33
 
34
34
  private runPromise: Promise<void> | undefined;
35
+ private deadlineTimeoutHandler: NodeJS.Timeout | undefined;
35
36
 
36
37
  public readonly tracer: Tracer;
37
38
 
@@ -46,6 +47,7 @@ export class EpochProvingJob implements Traceable {
46
47
  private l2BlockSource: L2BlockSource,
47
48
  private l1ToL2MessageSource: L1ToL2MessageSource,
48
49
  private metrics: ProverNodeMetrics,
50
+ private deadline: Date | undefined,
49
51
  private config: { parallelBlockLimit: number } = { parallelBlockLimit: 32 },
50
52
  private cleanUp: (job: EpochProvingJob) => Promise<void> = () => Promise.resolve(),
51
53
  ) {
@@ -68,9 +70,11 @@ export class EpochProvingJob implements Traceable {
68
70
  return { [Attributes.EPOCH_NUMBER]: Number(this.epochNumber) };
69
71
  })
70
72
  public async run() {
73
+ this.scheduleDeadlineStop();
74
+
71
75
  const epochNumber = Number(this.epochNumber);
72
76
  const epochSizeBlocks = this.blocks.length;
73
- const epochSizeTxs = this.blocks.reduce((total, current) => total + current.body.numberOfTxsIncludingPadded, 0);
77
+ const epochSizeTxs = this.blocks.reduce((total, current) => total + current.body.txEffects.length, 0);
74
78
  const [fromBlock, toBlock] = [this.blocks[0].number, this.blocks.at(-1)!.number];
75
79
  this.log.info(`Starting epoch ${epochNumber} proving job with blocks ${fromBlock} to ${toBlock}`, {
76
80
  fromBlock,
@@ -79,18 +83,20 @@ export class EpochProvingJob implements Traceable {
79
83
  epochNumber,
80
84
  uuid: this.uuid,
81
85
  });
82
- this.state = 'processing';
83
- const timer = new Timer();
84
86
 
87
+ this.progressState('processing');
88
+ const timer = new Timer();
85
89
  const { promise, resolve } = promiseWithResolvers<void>();
86
90
  this.runPromise = promise;
87
91
 
88
92
  try {
89
93
  this.prover.startNewEpoch(epochNumber, fromBlock, epochSizeBlocks);
94
+ this.prover.startTubeCircuits(this.txs);
90
95
 
91
96
  await asyncPool(this.config.parallelBlockLimit, this.blocks, async block => {
97
+ this.checkState();
98
+
92
99
  const globalVariables = block.header.globalVariables;
93
- const txCount = block.body.numberOfTxsIncludingPadded;
94
100
  const txs = this.getTxs(block);
95
101
  const l1ToL2Messages = await this.getL1ToL2Messages(block);
96
102
  const previousHeader = await this.getBlockHeader(block.number - 1);
@@ -106,13 +112,14 @@ export class EpochProvingJob implements Traceable {
106
112
  uuid: this.uuid,
107
113
  ...globalVariables,
108
114
  });
115
+
109
116
  // Start block proving
110
117
  await this.prover.startNewBlock(globalVariables, l1ToL2Messages);
111
118
 
112
119
  // Process public fns
113
120
  const db = await this.dbProvider.fork(block.number - 1);
114
121
  const publicProcessor = this.publicProcessorFactory.create(db, previousHeader, globalVariables, true);
115
- const processed = await this.processTxs(publicProcessor, txs, txCount);
122
+ const processed = await this.processTxs(publicProcessor, txs);
116
123
  await this.prover.addTxs(processed);
117
124
  await db.close();
118
125
  this.log.verbose(`Processed all ${txs.length} txs for block ${block.number}`, {
@@ -125,32 +132,76 @@ export class EpochProvingJob implements Traceable {
125
132
  await this.prover.setBlockCompleted(block.number, block.header);
126
133
  });
127
134
 
128
- this.state = 'awaiting-prover';
135
+ const executionTime = timer.ms();
136
+
137
+ this.progressState('awaiting-prover');
129
138
  const { publicInputs, proof } = await this.prover.finaliseEpoch();
130
139
  this.log.info(`Finalised proof for epoch ${epochNumber}`, { epochNumber, uuid: this.uuid, duration: timer.ms() });
131
140
 
132
- this.state = 'publishing-proof';
133
- await this.publisher.submitEpochProof({ fromBlock, toBlock, epochNumber, publicInputs, proof });
134
- this.log.info(`Submitted proof for epoch`, { epochNumber, uuid: this.uuid });
141
+ this.progressState('publishing-proof');
142
+ const success = await this.publisher.submitEpochProof({ fromBlock, toBlock, epochNumber, publicInputs, proof });
143
+ if (!success) {
144
+ throw new Error('Failed to submit epoch proof to L1');
145
+ }
135
146
 
147
+ this.log.info(`Submitted proof for epoch`, { epochNumber, uuid: this.uuid });
136
148
  this.state = 'completed';
137
- this.metrics.recordProvingJob(timer, epochSizeBlocks, epochSizeTxs);
138
- } catch (err) {
149
+ this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeBlocks, epochSizeTxs);
150
+ } catch (err: any) {
151
+ if (err && err.name === 'HaltExecutionError') {
152
+ this.log.warn(`Halted execution of epoch ${epochNumber} prover job`, { uuid: this.uuid, epochNumber });
153
+ return;
154
+ }
139
155
  this.log.error(`Error running epoch ${epochNumber} prover job`, err, { uuid: this.uuid, epochNumber });
140
156
  this.state = 'failed';
141
157
  } finally {
158
+ clearTimeout(this.deadlineTimeoutHandler);
142
159
  await this.cleanUp(this);
160
+ await this.prover.stop();
143
161
  resolve();
144
162
  }
145
163
  }
146
164
 
147
- public async stop() {
165
+ private progressState(state: EpochProvingJobState) {
166
+ this.checkState();
167
+ this.state = state;
168
+ }
169
+
170
+ private checkState() {
171
+ if (this.state === 'timed-out' || this.state === 'stopped' || this.state === 'failed') {
172
+ throw new HaltExecutionError(this.state);
173
+ }
174
+ }
175
+
176
+ public async stop(state: EpochProvingJobState = 'stopped') {
177
+ this.state = state;
148
178
  this.prover.cancel();
179
+ // TODO(palla/prover): Stop the publisher as well
149
180
  if (this.runPromise) {
150
181
  await this.runPromise;
151
182
  }
152
183
  }
153
184
 
185
+ private scheduleDeadlineStop() {
186
+ const deadline = this.deadline;
187
+ if (deadline) {
188
+ const timeout = deadline.getTime() - Date.now();
189
+ if (timeout <= 0) {
190
+ throw new Error('Cannot start job with deadline in the past');
191
+ }
192
+
193
+ this.deadlineTimeoutHandler = setTimeout(() => {
194
+ if (EpochProvingJobTerminalState.includes(this.state)) {
195
+ return;
196
+ }
197
+ this.log.warn('Stopping job due to deadline hit', { uuid: this.uuid, epochNumber: this.epochNumber });
198
+ this.stop('timed-out').catch(err => {
199
+ this.log.error('Error stopping job', err, { uuid: this.uuid, epochNumber: this.epochNumber });
200
+ });
201
+ }, timeout);
202
+ }
203
+ }
204
+
154
205
  /* Returns the header for the given block number, or undefined for block zero. */
155
206
  private getBlockHeader(blockNumber: number) {
156
207
  if (blockNumber === 0) {
@@ -168,21 +219,29 @@ export class EpochProvingJob implements Traceable {
168
219
  return this.l1ToL2MessageSource.getL1ToL2Messages(BigInt(block.number));
169
220
  }
170
221
 
171
- private async processTxs(
172
- publicProcessor: PublicProcessor,
173
- txs: Tx[],
174
- totalNumberOfTxs: number,
175
- ): Promise<ProcessedTx[]> {
176
- const [processedTxs, failedTxs] = await publicProcessor.process(txs, totalNumberOfTxs, new EmptyTxValidator());
222
+ private async processTxs(publicProcessor: PublicProcessor, txs: Tx[]): Promise<ProcessedTx[]> {
223
+ const { deadline } = this;
224
+ const [processedTxs, failedTxs] = await publicProcessor.process(txs, { deadline });
177
225
 
178
226
  if (failedTxs.length) {
179
227
  throw new Error(
180
- `Failed to process txs: ${failedTxs.map(({ tx, error }) => `${tx.getTxHash()} (${error})`).join(', ')}`,
228
+ `Txs failed processing: ${failedTxs.map(({ tx, error }) => `${tx.getTxHash()} (${error})`).join(', ')}`,
181
229
  );
182
230
  }
183
231
 
232
+ if (processedTxs.length !== txs.length) {
233
+ throw new Error(`Failed to process all txs: processed ${processedTxs.length} out of ${txs.length}`);
234
+ }
235
+
184
236
  return processedTxs;
185
237
  }
186
238
  }
187
239
 
240
+ class HaltExecutionError extends Error {
241
+ constructor(state: EpochProvingJobState) {
242
+ super(`Halted execution due to state ${state}`);
243
+ this.name = 'HaltExecutionError';
244
+ }
245
+ }
246
+
188
247
  export { type EpochProvingJobState };
package/src/metrics.ts CHANGED
@@ -1,13 +1,18 @@
1
- import { type Timer } from '@aztec/foundation/timer';
2
1
  import { type Histogram, Metrics, type TelemetryClient, ValueType } from '@aztec/telemetry-client';
3
2
 
4
3
  export class ProverNodeMetrics {
4
+ proverEpochExecutionDuration: Histogram;
5
5
  provingJobDuration: Histogram;
6
6
  provingJobBlocks: Histogram;
7
7
  provingJobTransactions: Histogram;
8
8
 
9
9
  constructor(public readonly client: TelemetryClient, name = 'ProverNode') {
10
10
  const meter = client.getMeter(name);
11
+ this.proverEpochExecutionDuration = meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION, {
12
+ description: 'Duration of execution of an epoch by the prover',
13
+ unit: 'ms',
14
+ valueType: ValueType.INT,
15
+ });
11
16
  this.provingJobDuration = meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION, {
12
17
  description: 'Duration of proving job',
13
18
  unit: 'ms',
@@ -23,9 +28,9 @@ export class ProverNodeMetrics {
23
28
  });
24
29
  }
25
30
 
26
- public recordProvingJob(timerOrMs: Timer | number, numBlocks: number, numTxs: number) {
27
- const ms = Math.ceil(typeof timerOrMs === 'number' ? timerOrMs : timerOrMs.ms());
28
- this.provingJobDuration.record(ms);
31
+ public recordProvingJob(executionTimeMs: number, totalTimeMs: number, numBlocks: number, numTxs: number) {
32
+ this.proverEpochExecutionDuration.record(Math.ceil(executionTimeMs));
33
+ this.provingJobDuration.record(Math.ceil(totalTimeMs));
29
34
  this.provingJobBlocks.record(Math.floor(numBlocks));
30
35
  this.provingJobTransactions.record(Math.floor(numTxs));
31
36
  }