@aztec/prover-node 0.85.0-nightly.20250424 → 0.86.0

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.
package/dest/config.d.ts CHANGED
@@ -15,9 +15,9 @@ type SpecificProverNodeConfig = {
15
15
  proverNodeMaxPendingJobs: number;
16
16
  proverNodePollingIntervalMs: number;
17
17
  proverNodeMaxParallelBlocksPerEpoch: number;
18
- txGatheringTimeoutMs: number;
19
18
  txGatheringIntervalMs: number;
20
- txGatheringMaxParallelRequests: number;
19
+ txGatheringBatchSize: number;
20
+ txGatheringMaxParallelRequestsPerNode: number;
21
21
  };
22
22
  export declare const proverNodeConfigMappings: ConfigMappingsType<ProverNodeConfig>;
23
23
  export declare function getProverNodeConfigFromEnv(): ProverNodeConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAA0B,MAAM,wBAAwB,CAAC;AACrF,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,KAAK,kBAAkB,EAAwD,MAAM,iBAAiB,CAAC;AAChH,OAAO,EAAE,KAAK,kBAAkB,EAA6C,MAAM,0BAA0B,CAAC;AAE9G,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,KAAK,gBAAgB,EAA4B,MAAM,wBAAwB,CAAC;AACzF,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,mBAAmB,CAAC;AACtE,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EAGxB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAG5B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EAGpB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,KAAK,gBAAgB,EAA4B,MAAM,2BAA2B,CAAC;AAE5F,OAAO,EAAE,KAAK,wBAAwB,EAAoC,MAAM,iCAAiC,CAAC;AAElH,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAC3C,sBAAsB,GACtB,SAAS,GACT,gBAAgB,GAChB,eAAe,GACf,cAAc,GACd,eAAe,GACf,wBAAwB,GACxB,gBAAgB,GAChB,wBAAwB,GACxB,kBAAkB,CAAC;AAErB,KAAK,wBAAwB,GAAG;IAC9B,wBAAwB,EAAE,MAAM,CAAC;IACjC,2BAA2B,EAAE,MAAM,CAAC;IACpC,mCAAmC,EAAE,MAAM,CAAC;IAC5C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,8BAA8B,EAAE,MAAM,CAAC;CACxC,CAAC;AAmCF,eAAO,MAAM,wBAAwB,EAAE,kBAAkB,CAAC,gBAAgB,CAYzE,CAAC;AAEF,wBAAgB,0BAA0B,IAAI,gBAAgB,CAE7D;AAED,wBAAgB,gCAAgC,IAAI,kBAAkB,CAIrE;AAED,wBAAgB,+BAA+B,IAAI,iBAAiB,GAAG,QAAQ,GAAG,UAAU,CAK3F;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,kBAAkB,CAMjG"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAA0B,MAAM,wBAAwB,CAAC;AACrF,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,KAAK,kBAAkB,EAAwD,MAAM,iBAAiB,CAAC;AAChH,OAAO,EAAE,KAAK,kBAAkB,EAA6C,MAAM,0BAA0B,CAAC;AAE9G,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,KAAK,gBAAgB,EAA4B,MAAM,wBAAwB,CAAC;AACzF,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,mBAAmB,CAAC;AACtE,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EAGxB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAG5B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EAGpB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,KAAK,gBAAgB,EAA4B,MAAM,2BAA2B,CAAC;AAE5F,OAAO,EAAE,KAAK,wBAAwB,EAAoC,MAAM,iCAAiC,CAAC;AAElH,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAC3C,sBAAsB,GACtB,SAAS,GACT,gBAAgB,GAChB,eAAe,GACf,cAAc,GACd,eAAe,GACf,wBAAwB,GACxB,gBAAgB,GAChB,wBAAwB,GACxB,kBAAkB,CAAC;AAErB,KAAK,wBAAwB,GAAG;IAC9B,wBAAwB,EAAE,MAAM,CAAC;IACjC,2BAA2B,EAAE,MAAM,CAAC;IACpC,mCAAmC,EAAE,MAAM,CAAC;IAC5C,qBAAqB,EAAE,MAAM,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qCAAqC,EAAE,MAAM,CAAC;CAC/C,CAAC;AAmCF,eAAO,MAAM,wBAAwB,EAAE,kBAAkB,CAAC,gBAAgB,CAYzE,CAAC;AAEF,wBAAgB,0BAA0B,IAAI,gBAAgB,CAE7D;AAED,wBAAgB,gCAAgC,IAAI,kBAAkB,CAIrE;AAED,wBAAgB,+BAA+B,IAAI,iBAAiB,GAAG,QAAQ,GAAG,UAAU,CAK3F;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,kBAAkB,CAMjG"}
package/dest/config.js CHANGED
@@ -26,19 +26,19 @@ const specificProverNodeConfigMappings = {
26
26
  description: 'The Maximum number of blocks to process in parallel while proving an epoch',
27
27
  ...numberConfigHelper(32)
28
28
  },
29
- txGatheringTimeoutMs: {
30
- env: 'PROVER_NODE_TX_GATHERING_TIMEOUT_MS',
31
- description: 'The maximum amount of time to wait for tx data to be available',
32
- ...numberConfigHelper(60_000)
33
- },
34
29
  txGatheringIntervalMs: {
35
30
  env: 'PROVER_NODE_TX_GATHERING_INTERVAL_MS',
36
31
  description: 'How often to check that tx data is available',
37
32
  ...numberConfigHelper(1_000)
38
33
  },
39
- txGatheringMaxParallelRequests: {
40
- env: 'PROVER_NODE_TX_GATHERING_MAX_PARALLEL_REQUESTS',
41
- description: 'How many txs to load up a time',
34
+ txGatheringBatchSize: {
35
+ env: 'PROVER_NODE_TX_GATHERING_BATCH_SIZE',
36
+ description: 'How many transactions to gather from a node in a single request',
37
+ ...numberConfigHelper(10)
38
+ },
39
+ txGatheringMaxParallelRequestsPerNode: {
40
+ env: 'PROVER_NODE_TX_GATHERING_MAX_PARALLEL_REQUESTS_PER_NODE',
41
+ description: 'How many tx requests to make in parallel to each node',
42
42
  ...numberConfigHelper(100)
43
43
  }
44
44
  };
package/dest/factory.d.ts CHANGED
@@ -3,17 +3,18 @@ import { type BlobSinkClientInterface } from '@aztec/blob-sink/client';
3
3
  import { L1TxUtils } from '@aztec/ethereum';
4
4
  import { type Logger } from '@aztec/foundation/log';
5
5
  import type { DataStoreConfig } from '@aztec/kv-store/config';
6
- import type { ProverCoordination, ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
6
+ import type { ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
7
7
  import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
8
8
  import { type TelemetryClient } from '@aztec/telemetry-client';
9
9
  import { type ProverNodeConfig } from './config.js';
10
+ import type { TxSource } from './prover-coordination/combined-prover-coordination.js';
10
11
  import { ProverNodePublisher } from './prover-node-publisher.js';
11
12
  import { ProverNode } from './prover-node.js';
12
13
  /** Creates a new prover node given a config. */
13
14
  export declare function createProverNode(userConfig: ProverNodeConfig & DataStoreConfig, deps?: {
14
15
  telemetry?: TelemetryClient;
15
16
  log?: Logger;
16
- aztecNodeTxProvider?: ProverCoordination;
17
+ aztecNodeTxProvider?: TxSource;
17
18
  archiver?: Archiver;
18
19
  publisher?: ProverNodePublisher;
19
20
  blobSinkClient?: BlobSinkClientInterface;
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAkB,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,KAAK,uBAAuB,EAAwB,MAAM,yBAAyB,CAAC;AAE7F,OAAO,EAAE,SAAS,EAA+D,MAAM,iBAAiB,CAAC;AACzG,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAC5F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAGnF,OAAO,EAAE,KAAK,gBAAgB,EAAiB,MAAM,aAAa,CAAC;AAGnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,UAAU,EAA0B,MAAM,kBAAkB,CAAC;AAEtE,gDAAgD;AAChD,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,gBAAgB,GAAG,eAAe,EAC9C,IAAI,GAAE;IACJ,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mBAAmB,CAAC,EAAE,kBAAkB,CAAC;IACzC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,cAAc,CAAC,EAAE,uBAAuB,CAAC;IACzC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,SAAS,CAAC;CAClB,EACN,OAAO,GAAE;IACP,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,CAAC;CACvC,uBAqEP"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAkB,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,KAAK,uBAAuB,EAAwB,MAAM,yBAAyB,CAAC;AAE7F,OAAO,EAAE,SAAS,EAA+D,MAAM,iBAAiB,CAAC;AACzG,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAGnF,OAAO,EAAE,KAAK,gBAAgB,EAAiB,MAAM,aAAa,CAAC;AAEnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uDAAuD,CAAC;AAEtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,UAAU,EAA0B,MAAM,kBAAkB,CAAC;AAEtE,gDAAgD;AAChD,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,gBAAgB,GAAG,eAAe,EAC9C,IAAI,GAAE;IACJ,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mBAAmB,CAAC,EAAE,QAAQ,CAAC;IAC/B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,cAAc,CAAC,EAAE,uBAAuB,CAAC;IACzC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,SAAS,CAAC;CAClB,EACN,OAAO,GAAE;IACP,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,CAAC;CACvC,uBAmEP"}
package/dest/factory.js CHANGED
@@ -45,7 +45,7 @@ import { ProverNode } from './prover-node.js';
45
45
  });
46
46
  const epochCache = await EpochCache.create(config.l1Contracts.rollupAddress, config);
47
47
  // If config.p2pEnabled is true, createProverCoordination will create a p2p client where txs are requested
48
- // If config.p2pEnabled is false, createProverCoordination request information from the AztecNode
48
+ // If config.proverCoordinationNodeUrls is not empty, createProverCoordination will create set of aztec node clients from which txs are requested
49
49
  const proverCoordination = await createProverCoordination(config, {
50
50
  aztecNodeTxProvider: deps.aztecNodeTxProvider,
51
51
  worldStateSynchronizer,
@@ -57,9 +57,7 @@ import { ProverNode } from './prover-node.js';
57
57
  maxPendingJobs: config.proverNodeMaxPendingJobs,
58
58
  pollingIntervalMs: config.proverNodePollingIntervalMs,
59
59
  maxParallelBlocksPerEpoch: config.proverNodeMaxParallelBlocksPerEpoch,
60
- txGatheringMaxParallelRequests: config.txGatheringMaxParallelRequests,
61
- txGatheringIntervalMs: config.txGatheringIntervalMs,
62
- txGatheringTimeoutMs: config.txGatheringTimeoutMs
60
+ txGatheringIntervalMs: config.txGatheringIntervalMs
63
61
  };
64
62
  const epochMonitor = await EpochMonitor.create(archiver, proverNodeConfig, telemetry);
65
63
  return new ProverNode(prover, publisher, archiver, archiver, archiver, worldStateSynchronizer, proverCoordination, epochMonitor, proverNodeConfig, telemetry);
@@ -0,0 +1,22 @@
1
+ import type { P2P } from '@aztec/p2p';
2
+ import type { P2PClient, ProverCoordination } from '@aztec/stdlib/interfaces/server';
3
+ import { type Tx, TxHash } from '@aztec/stdlib/tx';
4
+ export type CombinedCoordinationOptions = {
5
+ txGatheringBatchSize: number;
6
+ txGatheringMaxParallelRequestsPerNode: number;
7
+ };
8
+ export interface TxSource {
9
+ getTxsByHash(txHashes: TxHash[]): Promise<(Tx | undefined)[]>;
10
+ }
11
+ export declare class CombinedProverCoordination implements ProverCoordination {
12
+ #private;
13
+ readonly p2p: P2P | undefined;
14
+ readonly aztecNodes: TxSource[];
15
+ private readonly options;
16
+ private readonly log;
17
+ constructor(p2p: P2P | undefined, aztecNodes: TxSource[], options?: CombinedCoordinationOptions, log?: import("@aztec/foundation/log").Logger);
18
+ getP2PClient(): P2PClient | undefined;
19
+ getTxsByHash(txHashes: TxHash[]): Promise<Tx[]>;
20
+ gatherTxs(txHashes: TxHash[]): Promise<void>;
21
+ }
22
+ //# sourceMappingURL=combined-prover-coordination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combined-prover-coordination.d.ts","sourceRoot":"","sources":["../../src/prover-coordination/combined-prover-coordination.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrF,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,MAAM,2BAA2B,GAAG;IAExC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qCAAqC,EAAE,MAAM,CAAC;CAC/C,CAAC;AASF,MAAM,WAAW,QAAQ;IACvB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;CAC/D;AAsCD,qBAAa,0BAA2B,YAAW,kBAAkB;;aAEjD,GAAG,EAAE,GAAG,GAAG,SAAS;aACpB,UAAU,EAAE,QAAQ,EAAE;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAIxB,OAAO,CAAC,QAAQ,CAAC,GAAG;gBANJ,GAAG,EAAE,GAAG,GAAG,SAAS,EACpB,UAAU,EAAE,QAAQ,EAAE,EACrB,OAAO,GAAE,2BAGzB,EACgB,GAAG,yCAA2D;IAG1E,YAAY,IAAI,SAAS,GAAG,SAAS;IAI/B,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,EAAE,CAAC;IAY/C,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAyE1D"}
@@ -0,0 +1,136 @@
1
+ import { asyncPool } from '@aztec/foundation/async-pool';
2
+ import { createLogger } from '@aztec/foundation/log';
3
+ import { TxHash } from '@aztec/stdlib/tx';
4
+ // Wraps the p2p client into a coordination pool
5
+ class P2PCoordinationPool {
6
+ p2p;
7
+ constructor(p2p){
8
+ this.p2p = p2p;
9
+ }
10
+ getTxsByHash(txHashes) {
11
+ return this.p2p.getTxsByHash(txHashes);
12
+ }
13
+ hasTxsInPool(txHashes) {
14
+ return this.p2p.hasTxsInPool(txHashes);
15
+ }
16
+ getTxsByHashFromPool(txHashes) {
17
+ return this.p2p.getTxsByHashFromPool(txHashes);
18
+ }
19
+ addTxs(txs) {
20
+ return this.p2p.addTxs(txs);
21
+ }
22
+ }
23
+ // Wraps an in memory tx pool into a coordination pool. Used for testing when no p2p/tx pool is available.
24
+ class InMemoryCoordinationPool {
25
+ txs = new Map();
26
+ getTxsByHash(txHashes) {
27
+ return Promise.resolve(txHashes.map((hash)=>this.txs.get(hash.toString())));
28
+ }
29
+ hasTxsInPool(txHashes) {
30
+ return Promise.resolve(txHashes.map((hash)=>this.txs.has(hash.toString())));
31
+ }
32
+ getTxsByHashFromPool(txHashes) {
33
+ return this.getTxsByHash(txHashes);
34
+ }
35
+ async addTxs(txs) {
36
+ const hashes = await Promise.all(txs.map((tx)=>tx.getTxHash()));
37
+ txs.forEach((tx, index)=>this.txs.set(hashes[index].toString(), tx));
38
+ }
39
+ }
40
+ // Class to implement combined transaction retrieval from p2p and any available nodes
41
+ export class CombinedProverCoordination {
42
+ p2p;
43
+ aztecNodes;
44
+ options;
45
+ log;
46
+ constructor(p2p, aztecNodes, options = {
47
+ txGatheringBatchSize: 10,
48
+ txGatheringMaxParallelRequestsPerNode: 10
49
+ }, log = createLogger('prover-node:combined-prover-coordination')){
50
+ this.p2p = p2p;
51
+ this.aztecNodes = aztecNodes;
52
+ this.options = options;
53
+ this.log = log;
54
+ }
55
+ getP2PClient() {
56
+ return this.p2p;
57
+ }
58
+ async getTxsByHash(txHashes) {
59
+ const pool = this.p2p ? new P2PCoordinationPool(this.p2p) : new InMemoryCoordinationPool();
60
+ await this.#gatherTxs(txHashes, pool);
61
+ const availability = await pool.hasTxsInPool(txHashes);
62
+ const notFound = txHashes.filter((_, index)=>!availability[index]);
63
+ if (notFound.length > 0) {
64
+ throw new Error(`Could not find txs: ${notFound.map((tx)=>tx.toString())}`);
65
+ }
66
+ const txs = await pool.getTxsByHashFromPool(txHashes);
67
+ return txs.filter((tx)=>tx !== undefined);
68
+ }
69
+ async gatherTxs(txHashes) {
70
+ const pool = this.p2p ? new P2PCoordinationPool(this.p2p) : new InMemoryCoordinationPool();
71
+ await this.#gatherTxs(txHashes, pool);
72
+ }
73
+ async #gatherTxs(txHashes, pool) {
74
+ const availability = await pool.hasTxsInPool(txHashes);
75
+ const notFound = txHashes.filter((_, index)=>!availability[index]);
76
+ const txsToFind = new Set(notFound.map((tx)=>tx.toString()));
77
+ if (txsToFind.size === 0) {
78
+ this.log.info(`Check for ${txHashes.length} txs found all in the pool}`);
79
+ return;
80
+ }
81
+ this.log.info(`Check for ${txHashes.length} txs found ${txsToFind.size} missing. Will gather from nodes and p2p`);
82
+ const originalToFind = txsToFind.size;
83
+ await this.#gatherTxsFromAllNodes(txsToFind, pool);
84
+ if (txsToFind.size === 0) {
85
+ this.log.info(`Found all ${originalToFind} txs directly from nodes`);
86
+ return;
87
+ }
88
+ const toFindFromP2P = txsToFind.size;
89
+ this.log.verbose(`Gathering ${toFindFromP2P} txs from p2p network`);
90
+ const foundFromP2P = await pool.getTxsByHash([
91
+ ...txsToFind
92
+ ].map((tx)=>TxHash.fromString(tx)));
93
+ const numFoundFromNodes = originalToFind - toFindFromP2P;
94
+ const numNotFound = toFindFromP2P - foundFromP2P.length;
95
+ if (numNotFound === 0) {
96
+ this.log.info(`Found all ${originalToFind} txs. ${numFoundFromNodes} from nodes, ${foundFromP2P.length} from p2p`);
97
+ return;
98
+ }
99
+ this.log.warn(`Failed to find ${numNotFound} txs from any source. Found ${foundFromP2P.length} from p2p and ${numFoundFromNodes} from nodes`);
100
+ }
101
+ async #gatherTxsFromAllNodes(txsToFind, pool) {
102
+ if (txsToFind.size === 0 || this.aztecNodes.length === 0) {
103
+ return;
104
+ }
105
+ await Promise.all(this.aztecNodes.map((aztecNode)=>this.#gatherTxsFromNode(txsToFind, aztecNode, pool)));
106
+ }
107
+ async #gatherTxsFromNode(txsToFind, aztecNode, pool) {
108
+ const totalTxsRequired = txsToFind.size;
109
+ // It's possible that the set is empty as we already found the txs
110
+ if (totalTxsRequired === 0) {
111
+ return;
112
+ }
113
+ let totalTxsGathered = 0;
114
+ const batches = [];
115
+ const allTxs = [
116
+ ...txsToFind
117
+ ];
118
+ while(allTxs.length){
119
+ const batch = allTxs.splice(0, this.options.txGatheringBatchSize);
120
+ batches.push(batch);
121
+ }
122
+ await asyncPool(this.options.txGatheringMaxParallelRequestsPerNode, batches, async (batch)=>{
123
+ try {
124
+ const txs = (await aztecNode.getTxsByHash(batch.map((b)=>TxHash.fromString(b)))).filter((tx)=>!!tx);
125
+ const hashes = await Promise.all(txs.map((tx)=>tx.getTxHash()));
126
+ await pool.addTxs(txs);
127
+ hashes.forEach((hash)=>txsToFind.delete(hash.toString()));
128
+ totalTxsGathered += txs.length;
129
+ } catch (err) {
130
+ this.log.error(`Error gathering txs from aztec node: ${err}`);
131
+ return;
132
+ }
133
+ });
134
+ this.log.verbose(`Gathered ${totalTxsGathered} of ${totalTxsRequired} txs from a node`);
135
+ }
136
+ }
@@ -1,6 +1,6 @@
1
1
  import { type ConfigMappingsType } from '@aztec/foundation/config';
2
2
  export type ProverCoordinationConfig = {
3
- proverCoordinationNodeUrl: string | undefined;
3
+ proverCoordinationNodeUrls: string[];
4
4
  };
5
5
  export declare const proverCoordinationConfigMappings: ConfigMappingsType<ProverCoordinationConfig>;
6
6
  export declare function getTxProviderConfigFromEnv(): ProverCoordinationConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/prover-coordination/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAyB,MAAM,0BAA0B,CAAC;AAE1F,MAAM,MAAM,wBAAwB,GAAG;IACrC,yBAAyB,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/C,CAAC;AAEF,eAAO,MAAM,gCAAgC,EAAE,kBAAkB,CAAC,wBAAwB,CAMzF,CAAC;AAEF,wBAAgB,0BAA0B,IAAI,wBAAwB,CAErE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/prover-coordination/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAyB,MAAM,0BAA0B,CAAC;AAE1F,MAAM,MAAM,wBAAwB,GAAG;IACrC,0BAA0B,EAAE,MAAM,EAAE,CAAC;CACtC,CAAC;AAEF,eAAO,MAAM,gCAAgC,EAAE,kBAAkB,CAAC,wBAAwB,CAMzF,CAAC;AAEF,wBAAgB,0BAA0B,IAAI,wBAAwB,CAErE"}
@@ -1,9 +1,9 @@
1
1
  import { getConfigFromMappings } from '@aztec/foundation/config';
2
2
  export const proverCoordinationConfigMappings = {
3
- proverCoordinationNodeUrl: {
4
- env: 'PROVER_COORDINATION_NODE_URL',
5
- description: 'The URL of the tx provider node',
6
- parseEnv: (val)=>val
3
+ proverCoordinationNodeUrls: {
4
+ env: 'PROVER_COORDINATION_NODE_URLS',
5
+ description: 'The URLs of the tx provider nodes',
6
+ parseEnv: (val)=>val.split(',').map((url)=>url.trim().replace(/\/$/, ''))
7
7
  }
8
8
  };
9
9
  export function getTxProviderConfigFromEnv() {
@@ -4,12 +4,13 @@ import type { DataStoreConfig } from '@aztec/kv-store/config';
4
4
  import type { ProverCoordination, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
5
5
  import { type TelemetryClient } from '@aztec/telemetry-client';
6
6
  import type { ProverNodeConfig } from '../config.js';
7
+ import { type TxSource } from './combined-prover-coordination.js';
7
8
  type ProverCoordinationDeps = {
8
- aztecNodeTxProvider?: ProverCoordination;
9
- worldStateSynchronizer?: WorldStateSynchronizer;
10
- archiver?: Archiver | ArchiveSource;
9
+ aztecNodeTxProvider?: TxSource;
10
+ worldStateSynchronizer: WorldStateSynchronizer;
11
+ archiver: Archiver | ArchiveSource;
11
12
  telemetry?: TelemetryClient;
12
- epochCache?: EpochCache;
13
+ epochCache: EpochCache;
13
14
  };
14
15
  /**
15
16
  * Creates a prover coordination service.
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/prover-coordination/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAK9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGlG,OAAO,EAAE,KAAK,eAAe,EAAmB,MAAM,yBAAyB,CAAC;AAEhF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGrD,KAAK,sBAAsB,GAAG;IAC5B,mBAAmB,CAAC,EAAE,kBAAkB,CAAC;IACzC,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;IAChD,QAAQ,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;IACpC,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,gBAAgB,GAAG,eAAe,EAC1C,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CAqC7B"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/prover-coordination/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAK9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGlG,OAAO,EAAE,KAAK,eAAe,EAAmB,MAAM,yBAAyB,CAAC;AAEhF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAGL,KAAK,QAAQ,EACd,MAAM,mCAAmC,CAAC;AAG3C,KAAK,sBAAsB,GAAG;IAC5B,mBAAmB,CAAC,EAAE,QAAQ,CAAC;IAC/B,sBAAsB,EAAE,sBAAsB,CAAC;IAC/C,QAAQ,EAAE,QAAQ,GAAG,aAAa,CAAC;IACnC,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,gBAAgB,GAAG,eAAe,EAC1C,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CA2C7B"}
@@ -7,6 +7,7 @@ import { createAztecNodeClient } from '@aztec/stdlib/interfaces/client';
7
7
  import { P2PClientType } from '@aztec/stdlib/p2p';
8
8
  import { getComponentsVersionsFromConfig } from '@aztec/stdlib/versioning';
9
9
  import { makeTracedFetch } from '@aztec/telemetry-client';
10
+ import { CombinedProverCoordination } from './combined-prover-coordination.js';
10
11
  /**
11
12
  * Creates a prover coordination service.
12
13
  * If p2p is enabled, prover coordination is done via p2p.
@@ -14,29 +15,34 @@ import { makeTracedFetch } from '@aztec/telemetry-client';
14
15
  * If an aztec node is provided, it is returned directly.
15
16
  */ export async function createProverCoordination(config, deps) {
16
17
  const log = createLogger('prover-node:prover-coordination');
18
+ const coordinationConfig = {
19
+ txGatheringBatchSize: config.txGatheringBatchSize ?? 10,
20
+ txGatheringMaxParallelRequestsPerNode: config.txGatheringMaxParallelRequestsPerNode ?? 10
21
+ };
17
22
  if (deps.aztecNodeTxProvider) {
18
23
  log.info('Using prover coordination via aztec node');
19
- return deps.aztecNodeTxProvider;
24
+ return new CombinedProverCoordination(undefined, [
25
+ deps.aztecNodeTxProvider
26
+ ], coordinationConfig);
20
27
  }
21
28
  if (config.p2pEnabled) {
22
29
  log.info('Using prover coordination via p2p');
23
30
  if (!deps.archiver || !deps.worldStateSynchronizer || !deps.telemetry || !deps.epochCache) {
24
31
  throw new Error('Missing dependencies for p2p prover coordination');
25
32
  }
26
- const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier();
27
- const p2pClient = await createP2PClient(P2PClientType.Prover, config, deps.archiver, proofVerifier, deps.worldStateSynchronizer, deps.epochCache, deps.telemetry);
28
- await p2pClient.start();
29
- return p2pClient;
30
33
  }
31
- if (config.proverCoordinationNodeUrl) {
32
- log.info('Using prover coordination via node url');
34
+ let nodes = [];
35
+ if (config.proverCoordinationNodeUrls.length > 0) {
36
+ log.info('Using prover coordination via node urls');
33
37
  const versions = getComponentsVersionsFromConfig(config, protocolContractTreeRoot, getVKTreeRoot());
34
- return createAztecNodeClient(config.proverCoordinationNodeUrl, versions, makeTracedFetch([
35
- 1,
36
- 2,
37
- 3
38
- ], false));
39
- } else {
40
- throw new Error(`Aztec Node URL for Tx Provider is not set.`);
38
+ nodes = config.proverCoordinationNodeUrls.map((url)=>createAztecNodeClient(url, versions, makeTracedFetch([
39
+ 1,
40
+ 2,
41
+ 3
42
+ ], false)));
41
43
  }
44
+ const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier();
45
+ const p2pClient = await createP2PClient(P2PClientType.Prover, config, deps.archiver, proofVerifier, deps.worldStateSynchronizer, deps.epochCache, deps.telemetry);
46
+ await p2pClient.start();
47
+ return new CombinedProverCoordination(p2pClient, nodes, coordinationConfig);
42
48
  }
@@ -1,11 +1,9 @@
1
1
  import type { Maybe } from '@aztec/foundation/types';
2
- import type { P2P } from '@aztec/p2p';
3
2
  import { PublicProcessorFactory } from '@aztec/simulator/server';
4
3
  import type { L2Block, L2BlockSource } from '@aztec/stdlib/block';
5
4
  import type { ContractDataSource } from '@aztec/stdlib/contract';
6
5
  import { type EpochProverManager, type ProverCoordination, type ProverNodeApi, type Service, type WorldStateSyncStatus, type WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
7
6
  import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
8
- import type { P2PClientType } from '@aztec/stdlib/p2p';
9
7
  import type { Tx } from '@aztec/stdlib/tx';
10
8
  import { type TelemetryClient, type Traceable, type Tracer } from '@aztec/telemetry-client';
11
9
  import { EpochProvingJob, type EpochProvingJobState } from './job/epoch-proving-job.js';
@@ -15,9 +13,7 @@ export type ProverNodeOptions = {
15
13
  pollingIntervalMs: number;
16
14
  maxPendingJobs: number;
17
15
  maxParallelBlocksPerEpoch: number;
18
- txGatheringTimeoutMs: number;
19
16
  txGatheringIntervalMs: number;
20
- txGatheringMaxParallelRequests: number;
21
17
  };
22
18
  /**
23
19
  * An Aztec Prover Node is a standalone process that monitors the unfinalised chain on L1 for unproven blocks,
@@ -32,7 +28,7 @@ export declare class ProverNode implements EpochMonitorHandler, ProverNodeApi, T
32
28
  protected readonly l1ToL2MessageSource: L1ToL2MessageSource;
33
29
  protected readonly contractDataSource: ContractDataSource;
34
30
  protected readonly worldState: WorldStateSynchronizer;
35
- protected readonly coordination: ProverCoordination & Maybe<Service>;
31
+ protected readonly coordination: ProverCoordination;
36
32
  protected readonly epochsMonitor: EpochMonitor;
37
33
  protected readonly telemetryClient: TelemetryClient;
38
34
  private log;
@@ -45,9 +41,9 @@ export declare class ProverNode implements EpochMonitorHandler, ProverNodeApi, T
45
41
  private txFetcher;
46
42
  private lastBlockNumber;
47
43
  readonly tracer: Tracer;
48
- constructor(prover: EpochProverManager, publisher: ProverNodePublisher, l2BlockSource: L2BlockSource & Maybe<Service>, l1ToL2MessageSource: L1ToL2MessageSource, contractDataSource: ContractDataSource, worldState: WorldStateSynchronizer, coordination: ProverCoordination & Maybe<Service>, epochsMonitor: EpochMonitor, options?: Partial<ProverNodeOptions>, telemetryClient?: TelemetryClient);
44
+ constructor(prover: EpochProverManager, publisher: ProverNodePublisher, l2BlockSource: L2BlockSource & Maybe<Service>, l1ToL2MessageSource: L1ToL2MessageSource, contractDataSource: ContractDataSource, worldState: WorldStateSynchronizer, coordination: ProverCoordination, epochsMonitor: EpochMonitor, options?: Partial<ProverNodeOptions>, telemetryClient?: TelemetryClient);
49
45
  getProverId(): import("@aztec/foundation/schemas").Fr;
50
- getP2P(): P2P<P2PClientType.Prover> | undefined;
46
+ getP2P(): import("@aztec/stdlib/interfaces/server").P2PClient | undefined;
51
47
  /**
52
48
  * Handles an epoch being completed by starting a proof for it if there are no active jobs for it.
53
49
  * @param epochNumber - The epoch number that was just completed.
@@ -1 +1 @@
1
- {"version":3,"file":"prover-node.d.ts","sourceRoot":"","sources":["../src/prover-node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prover-node.d.ts","sourceRoot":"","sources":["../src/prover-node.ts"],"names":[],"mappings":"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"}
@@ -61,9 +61,7 @@ import { ProverNodeJobMetrics, ProverNodeRewardsMetrics } from './metrics.js';
61
61
  pollingIntervalMs: 1_000,
62
62
  maxPendingJobs: 100,
63
63
  maxParallelBlocksPerEpoch: 32,
64
- txGatheringTimeoutMs: 60_000,
65
64
  txGatheringIntervalMs: 1_000,
66
- txGatheringMaxParallelRequests: 100,
67
65
  ...compact(options)
68
66
  };
69
67
  const meter = telemetryClient.getMeter('ProverNode');
@@ -76,11 +74,7 @@ import { ProverNodeJobMetrics, ProverNodeRewardsMetrics } from './metrics.js';
76
74
  return this.prover.getProverId();
77
75
  }
78
76
  getP2P() {
79
- const asP2PClient = this.coordination;
80
- if (typeof asP2PClient.isP2PClient === 'function' && asP2PClient.isP2PClient()) {
81
- return asP2PClient;
82
- }
83
- return undefined;
77
+ return this.coordination.getP2PClient();
84
78
  }
85
79
  /**
86
80
  * Handles an epoch being completed by starting a proof for it if there are no active jobs for it.
@@ -223,7 +217,7 @@ import { ProverNodeJobMetrics, ProverNodeRewardsMetrics } from './metrics.js';
223
217
  }
224
218
  const txHashes = block.body.txEffects.map((tx)=>tx.txHash);
225
219
  this.log.verbose(`Fetching ${txHashes.length} tx hashes for block number ${blockNumber} from coordination`);
226
- await this.coordination.getTxsByHash(txHashes); // This stores the txs in the tx pool, no need to persist them here
220
+ await this.coordination.gatherTxs(txHashes); // This stores the txs in the tx pool, no need to persist them here
227
221
  this.lastBlockNumber = blockNumber;
228
222
  }
229
223
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/prover-node",
3
- "version": "0.85.0-nightly.20250424",
3
+ "version": "0.86.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -51,25 +51,25 @@
51
51
  ]
52
52
  },
53
53
  "dependencies": {
54
- "@aztec/archiver": "0.85.0-nightly.20250424",
55
- "@aztec/bb-prover": "0.85.0-nightly.20250424",
56
- "@aztec/blob-sink": "0.85.0-nightly.20250424",
57
- "@aztec/constants": "0.85.0-nightly.20250424",
58
- "@aztec/epoch-cache": "0.85.0-nightly.20250424",
59
- "@aztec/ethereum": "0.85.0-nightly.20250424",
60
- "@aztec/foundation": "0.85.0-nightly.20250424",
61
- "@aztec/kv-store": "0.85.0-nightly.20250424",
62
- "@aztec/l1-artifacts": "0.85.0-nightly.20250424",
63
- "@aztec/node-lib": "0.85.0-nightly.20250424",
64
- "@aztec/noir-protocol-circuits-types": "0.85.0-nightly.20250424",
65
- "@aztec/p2p": "0.85.0-nightly.20250424",
66
- "@aztec/protocol-contracts": "0.85.0-nightly.20250424",
67
- "@aztec/prover-client": "0.85.0-nightly.20250424",
68
- "@aztec/sequencer-client": "0.85.0-nightly.20250424",
69
- "@aztec/simulator": "0.85.0-nightly.20250424",
70
- "@aztec/stdlib": "0.85.0-nightly.20250424",
71
- "@aztec/telemetry-client": "0.85.0-nightly.20250424",
72
- "@aztec/world-state": "0.85.0-nightly.20250424",
54
+ "@aztec/archiver": "0.86.0",
55
+ "@aztec/bb-prover": "0.86.0",
56
+ "@aztec/blob-sink": "0.86.0",
57
+ "@aztec/constants": "0.86.0",
58
+ "@aztec/epoch-cache": "0.86.0",
59
+ "@aztec/ethereum": "0.86.0",
60
+ "@aztec/foundation": "0.86.0",
61
+ "@aztec/kv-store": "0.86.0",
62
+ "@aztec/l1-artifacts": "0.86.0",
63
+ "@aztec/node-lib": "0.86.0",
64
+ "@aztec/noir-protocol-circuits-types": "0.86.0",
65
+ "@aztec/p2p": "0.86.0",
66
+ "@aztec/protocol-contracts": "0.86.0",
67
+ "@aztec/prover-client": "0.86.0",
68
+ "@aztec/sequencer-client": "0.86.0",
69
+ "@aztec/simulator": "0.86.0",
70
+ "@aztec/stdlib": "0.86.0",
71
+ "@aztec/telemetry-client": "0.86.0",
72
+ "@aztec/world-state": "0.86.0",
73
73
  "source-map-support": "^0.5.21",
74
74
  "tslib": "^2.4.0",
75
75
  "viem": "2.23.7"
package/src/config.ts CHANGED
@@ -44,9 +44,9 @@ type SpecificProverNodeConfig = {
44
44
  proverNodeMaxPendingJobs: number;
45
45
  proverNodePollingIntervalMs: number;
46
46
  proverNodeMaxParallelBlocksPerEpoch: number;
47
- txGatheringTimeoutMs: number;
48
47
  txGatheringIntervalMs: number;
49
- txGatheringMaxParallelRequests: number;
48
+ txGatheringBatchSize: number;
49
+ txGatheringMaxParallelRequestsPerNode: number;
50
50
  };
51
51
 
52
52
  const specificProverNodeConfigMappings: ConfigMappingsType<SpecificProverNodeConfig> = {
@@ -65,19 +65,19 @@ const specificProverNodeConfigMappings: ConfigMappingsType<SpecificProverNodeCon
65
65
  description: 'The Maximum number of blocks to process in parallel while proving an epoch',
66
66
  ...numberConfigHelper(32),
67
67
  },
68
- txGatheringTimeoutMs: {
69
- env: 'PROVER_NODE_TX_GATHERING_TIMEOUT_MS',
70
- description: 'The maximum amount of time to wait for tx data to be available',
71
- ...numberConfigHelper(60_000),
72
- },
73
68
  txGatheringIntervalMs: {
74
69
  env: 'PROVER_NODE_TX_GATHERING_INTERVAL_MS',
75
70
  description: 'How often to check that tx data is available',
76
71
  ...numberConfigHelper(1_000),
77
72
  },
78
- txGatheringMaxParallelRequests: {
79
- env: 'PROVER_NODE_TX_GATHERING_MAX_PARALLEL_REQUESTS',
80
- description: 'How many txs to load up a time',
73
+ txGatheringBatchSize: {
74
+ env: 'PROVER_NODE_TX_GATHERING_BATCH_SIZE',
75
+ description: 'How many transactions to gather from a node in a single request',
76
+ ...numberConfigHelper(10),
77
+ },
78
+ txGatheringMaxParallelRequestsPerNode: {
79
+ env: 'PROVER_NODE_TX_GATHERING_MAX_PARALLEL_REQUESTS_PER_NODE',
80
+ description: 'How many tx requests to make in parallel to each node',
81
81
  ...numberConfigHelper(100),
82
82
  },
83
83
  };
package/src/factory.ts CHANGED
@@ -7,13 +7,14 @@ import type { DataStoreConfig } from '@aztec/kv-store/config';
7
7
  import { trySnapshotSync } from '@aztec/node-lib/actions';
8
8
  import { createProverClient } from '@aztec/prover-client';
9
9
  import { createAndStartProvingBroker } from '@aztec/prover-client/broker';
10
- import type { ProverCoordination, ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
10
+ import type { ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
11
11
  import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
12
12
  import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
13
13
  import { createWorldStateSynchronizer } from '@aztec/world-state';
14
14
 
15
15
  import { type ProverNodeConfig, resolveConfig } from './config.js';
16
16
  import { EpochMonitor } from './monitors/epoch-monitor.js';
17
+ import type { TxSource } from './prover-coordination/combined-prover-coordination.js';
17
18
  import { createProverCoordination } from './prover-coordination/factory.js';
18
19
  import { ProverNodePublisher } from './prover-node-publisher.js';
19
20
  import { ProverNode, type ProverNodeOptions } from './prover-node.js';
@@ -24,7 +25,7 @@ export async function createProverNode(
24
25
  deps: {
25
26
  telemetry?: TelemetryClient;
26
27
  log?: Logger;
27
- aztecNodeTxProvider?: ProverCoordination;
28
+ aztecNodeTxProvider?: TxSource;
28
29
  archiver?: Archiver;
29
30
  publisher?: ProverNodePublisher;
30
31
  blobSinkClient?: BlobSinkClientInterface;
@@ -70,7 +71,7 @@ export async function createProverNode(
70
71
  const epochCache = await EpochCache.create(config.l1Contracts.rollupAddress, config);
71
72
 
72
73
  // If config.p2pEnabled is true, createProverCoordination will create a p2p client where txs are requested
73
- // If config.p2pEnabled is false, createProverCoordination request information from the AztecNode
74
+ // If config.proverCoordinationNodeUrls is not empty, createProverCoordination will create set of aztec node clients from which txs are requested
74
75
  const proverCoordination = await createProverCoordination(config, {
75
76
  aztecNodeTxProvider: deps.aztecNodeTxProvider,
76
77
  worldStateSynchronizer,
@@ -83,9 +84,7 @@ export async function createProverNode(
83
84
  maxPendingJobs: config.proverNodeMaxPendingJobs,
84
85
  pollingIntervalMs: config.proverNodePollingIntervalMs,
85
86
  maxParallelBlocksPerEpoch: config.proverNodeMaxParallelBlocksPerEpoch,
86
- txGatheringMaxParallelRequests: config.txGatheringMaxParallelRequests,
87
87
  txGatheringIntervalMs: config.txGatheringIntervalMs,
88
- txGatheringTimeoutMs: config.txGatheringTimeoutMs,
89
88
  };
90
89
 
91
90
  const epochMonitor = await EpochMonitor.create(archiver, proverNodeConfig, telemetry);
@@ -0,0 +1,160 @@
1
+ import { asyncPool } from '@aztec/foundation/async-pool';
2
+ import { createLogger } from '@aztec/foundation/log';
3
+ import type { P2P } from '@aztec/p2p';
4
+ import type { P2PClient, ProverCoordination } from '@aztec/stdlib/interfaces/server';
5
+ import { type Tx, TxHash } from '@aztec/stdlib/tx';
6
+
7
+ export type CombinedCoordinationOptions = {
8
+ // These options apply to http tx gathering only
9
+ txGatheringBatchSize: number;
10
+ txGatheringMaxParallelRequestsPerNode: number;
11
+ };
12
+
13
+ interface CoordinationPool {
14
+ getTxsByHash(txHashes: TxHash[]): Promise<(Tx | undefined)[]>;
15
+ hasTxsInPool(txHashes: TxHash[]): Promise<boolean[]>;
16
+ getTxsByHashFromPool(txHashes: TxHash[]): Promise<(Tx | undefined)[]>;
17
+ addTxs(txs: Tx[]): Promise<void>;
18
+ }
19
+
20
+ export interface TxSource {
21
+ getTxsByHash(txHashes: TxHash[]): Promise<(Tx | undefined)[]>;
22
+ }
23
+
24
+ // Wraps the p2p client into a coordination pool
25
+ class P2PCoordinationPool implements CoordinationPool {
26
+ constructor(private readonly p2p: P2P) {}
27
+ getTxsByHash(txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
28
+ return this.p2p.getTxsByHash(txHashes);
29
+ }
30
+ hasTxsInPool(txHashes: TxHash[]): Promise<boolean[]> {
31
+ return this.p2p.hasTxsInPool(txHashes);
32
+ }
33
+ getTxsByHashFromPool(txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
34
+ return this.p2p.getTxsByHashFromPool(txHashes);
35
+ }
36
+ addTxs(txs: Tx[]): Promise<void> {
37
+ return this.p2p.addTxs(txs);
38
+ }
39
+ }
40
+
41
+ // Wraps an in memory tx pool into a coordination pool. Used for testing when no p2p/tx pool is available.
42
+ class InMemoryCoordinationPool implements CoordinationPool {
43
+ private txs: Map<string, Tx> = new Map();
44
+ getTxsByHash(txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
45
+ return Promise.resolve(txHashes.map(hash => this.txs.get(hash.toString())));
46
+ }
47
+ hasTxsInPool(txHashes: TxHash[]): Promise<boolean[]> {
48
+ return Promise.resolve(txHashes.map(hash => this.txs.has(hash.toString())));
49
+ }
50
+ getTxsByHashFromPool(txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
51
+ return this.getTxsByHash(txHashes);
52
+ }
53
+ async addTxs(txs: Tx[]): Promise<void> {
54
+ const hashes = await Promise.all(txs.map(tx => tx.getTxHash()));
55
+ txs.forEach((tx, index) => this.txs.set(hashes[index].toString(), tx));
56
+ }
57
+ }
58
+
59
+ // Class to implement combined transaction retrieval from p2p and any available nodes
60
+ export class CombinedProverCoordination implements ProverCoordination {
61
+ constructor(
62
+ public readonly p2p: P2P | undefined,
63
+ public readonly aztecNodes: TxSource[],
64
+ private readonly options: CombinedCoordinationOptions = {
65
+ txGatheringBatchSize: 10,
66
+ txGatheringMaxParallelRequestsPerNode: 10,
67
+ },
68
+ private readonly log = createLogger('prover-node:combined-prover-coordination'),
69
+ ) {}
70
+
71
+ public getP2PClient(): P2PClient | undefined {
72
+ return this.p2p;
73
+ }
74
+
75
+ public async getTxsByHash(txHashes: TxHash[]): Promise<Tx[]> {
76
+ const pool = this.p2p ? new P2PCoordinationPool(this.p2p) : new InMemoryCoordinationPool();
77
+ await this.#gatherTxs(txHashes, pool);
78
+ const availability = await pool.hasTxsInPool(txHashes);
79
+ const notFound = txHashes.filter((_, index) => !availability[index]);
80
+ if (notFound.length > 0) {
81
+ throw new Error(`Could not find txs: ${notFound.map(tx => tx.toString())}`);
82
+ }
83
+ const txs = await pool.getTxsByHashFromPool(txHashes);
84
+ return txs.filter(tx => tx !== undefined) as Tx[];
85
+ }
86
+
87
+ public async gatherTxs(txHashes: TxHash[]): Promise<void> {
88
+ const pool = this.p2p ? new P2PCoordinationPool(this.p2p) : new InMemoryCoordinationPool();
89
+ await this.#gatherTxs(txHashes, pool);
90
+ }
91
+
92
+ async #gatherTxs(txHashes: TxHash[], pool: CoordinationPool): Promise<void> {
93
+ const availability = await pool.hasTxsInPool(txHashes);
94
+ const notFound = txHashes.filter((_, index) => !availability[index]);
95
+ const txsToFind = new Set(notFound.map(tx => tx.toString()));
96
+ if (txsToFind.size === 0) {
97
+ this.log.info(`Check for ${txHashes.length} txs found all in the pool}`);
98
+ return;
99
+ }
100
+ this.log.info(`Check for ${txHashes.length} txs found ${txsToFind.size} missing. Will gather from nodes and p2p`);
101
+ const originalToFind = txsToFind.size;
102
+ await this.#gatherTxsFromAllNodes(txsToFind, pool);
103
+ if (txsToFind.size === 0) {
104
+ this.log.info(`Found all ${originalToFind} txs directly from nodes`);
105
+ return;
106
+ }
107
+ const toFindFromP2P = txsToFind.size;
108
+ this.log.verbose(`Gathering ${toFindFromP2P} txs from p2p network`);
109
+ const foundFromP2P = await pool.getTxsByHash([...txsToFind].map(tx => TxHash.fromString(tx)));
110
+ const numFoundFromNodes = originalToFind - toFindFromP2P;
111
+ const numNotFound = toFindFromP2P - foundFromP2P.length;
112
+ if (numNotFound === 0) {
113
+ this.log.info(
114
+ `Found all ${originalToFind} txs. ${numFoundFromNodes} from nodes, ${foundFromP2P.length} from p2p`,
115
+ );
116
+ return;
117
+ }
118
+ this.log.warn(
119
+ `Failed to find ${numNotFound} txs from any source. Found ${foundFromP2P.length} from p2p and ${numFoundFromNodes} from nodes`,
120
+ );
121
+ }
122
+
123
+ async #gatherTxsFromAllNodes(txsToFind: Set<string>, pool: CoordinationPool) {
124
+ if (txsToFind.size === 0 || this.aztecNodes.length === 0) {
125
+ return;
126
+ }
127
+ await Promise.all(this.aztecNodes.map(aztecNode => this.#gatherTxsFromNode(txsToFind, aztecNode, pool)));
128
+ }
129
+
130
+ async #gatherTxsFromNode(txsToFind: Set<string>, aztecNode: TxSource, pool: CoordinationPool) {
131
+ const totalTxsRequired = txsToFind.size;
132
+
133
+ // It's possible that the set is empty as we already found the txs
134
+ if (totalTxsRequired === 0) {
135
+ return;
136
+ }
137
+ let totalTxsGathered = 0;
138
+
139
+ const batches: string[][] = [];
140
+ const allTxs: string[] = [...txsToFind];
141
+ while (allTxs.length) {
142
+ const batch = allTxs.splice(0, this.options.txGatheringBatchSize);
143
+ batches.push(batch);
144
+ }
145
+
146
+ await asyncPool(this.options.txGatheringMaxParallelRequestsPerNode, batches, async batch => {
147
+ try {
148
+ const txs = (await aztecNode.getTxsByHash(batch.map(b => TxHash.fromString(b)))).filter((tx): tx is Tx => !!tx);
149
+ const hashes = await Promise.all(txs.map(tx => tx.getTxHash()));
150
+ await pool.addTxs(txs);
151
+ hashes.forEach(hash => txsToFind.delete(hash.toString()));
152
+ totalTxsGathered += txs.length;
153
+ } catch (err) {
154
+ this.log.error(`Error gathering txs from aztec node: ${err}`);
155
+ return;
156
+ }
157
+ });
158
+ this.log.verbose(`Gathered ${totalTxsGathered} of ${totalTxsRequired} txs from a node`);
159
+ }
160
+ }
@@ -1,14 +1,14 @@
1
1
  import { type ConfigMappingsType, getConfigFromMappings } from '@aztec/foundation/config';
2
2
 
3
3
  export type ProverCoordinationConfig = {
4
- proverCoordinationNodeUrl: string | undefined;
4
+ proverCoordinationNodeUrls: string[];
5
5
  };
6
6
 
7
7
  export const proverCoordinationConfigMappings: ConfigMappingsType<ProverCoordinationConfig> = {
8
- proverCoordinationNodeUrl: {
9
- env: 'PROVER_COORDINATION_NODE_URL',
10
- description: 'The URL of the tx provider node',
11
- parseEnv: (val: string) => val,
8
+ proverCoordinationNodeUrls: {
9
+ env: 'PROVER_COORDINATION_NODE_URLS',
10
+ description: 'The URLs of the tx provider nodes',
11
+ parseEnv: (val: string) => val.split(',').map(url => url.trim().replace(/\/$/, '')),
12
12
  },
13
13
  };
14
14
 
@@ -6,21 +6,26 @@ import type { DataStoreConfig } from '@aztec/kv-store/config';
6
6
  import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
7
7
  import { createP2PClient } from '@aztec/p2p';
8
8
  import { protocolContractTreeRoot } from '@aztec/protocol-contracts';
9
- import { createAztecNodeClient } from '@aztec/stdlib/interfaces/client';
9
+ import { type AztecNode, createAztecNodeClient } from '@aztec/stdlib/interfaces/client';
10
10
  import type { ProverCoordination, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
11
11
  import { P2PClientType } from '@aztec/stdlib/p2p';
12
12
  import { getComponentsVersionsFromConfig } from '@aztec/stdlib/versioning';
13
13
  import { type TelemetryClient, makeTracedFetch } from '@aztec/telemetry-client';
14
14
 
15
15
  import type { ProverNodeConfig } from '../config.js';
16
+ import {
17
+ type CombinedCoordinationOptions,
18
+ CombinedProverCoordination,
19
+ type TxSource,
20
+ } from './combined-prover-coordination.js';
16
21
 
17
22
  // We return a reference to the P2P client so that the prover node can stop the service when it shuts down.
18
23
  type ProverCoordinationDeps = {
19
- aztecNodeTxProvider?: ProverCoordination;
20
- worldStateSynchronizer?: WorldStateSynchronizer;
21
- archiver?: Archiver | ArchiveSource;
24
+ aztecNodeTxProvider?: TxSource;
25
+ worldStateSynchronizer: WorldStateSynchronizer;
26
+ archiver: Archiver | ArchiveSource;
22
27
  telemetry?: TelemetryClient;
23
- epochCache?: EpochCache;
28
+ epochCache: EpochCache;
24
29
  };
25
30
 
26
31
  /**
@@ -35,9 +40,14 @@ export async function createProverCoordination(
35
40
  ): Promise<ProverCoordination> {
36
41
  const log = createLogger('prover-node:prover-coordination');
37
42
 
43
+ const coordinationConfig: CombinedCoordinationOptions = {
44
+ txGatheringBatchSize: config.txGatheringBatchSize ?? 10,
45
+ txGatheringMaxParallelRequestsPerNode: config.txGatheringMaxParallelRequestsPerNode ?? 10,
46
+ };
47
+
38
48
  if (deps.aztecNodeTxProvider) {
39
49
  log.info('Using prover coordination via aztec node');
40
- return deps.aztecNodeTxProvider;
50
+ return new CombinedProverCoordination(undefined, [deps.aztecNodeTxProvider!], coordinationConfig);
41
51
  }
42
52
 
43
53
  if (config.p2pEnabled) {
@@ -46,27 +56,28 @@ export async function createProverCoordination(
46
56
  if (!deps.archiver || !deps.worldStateSynchronizer || !deps.telemetry || !deps.epochCache) {
47
57
  throw new Error('Missing dependencies for p2p prover coordination');
48
58
  }
49
-
50
- const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier();
51
- const p2pClient = await createP2PClient(
52
- P2PClientType.Prover,
53
- config,
54
- deps.archiver,
55
- proofVerifier,
56
- deps.worldStateSynchronizer,
57
- deps.epochCache,
58
- deps.telemetry,
59
- );
60
- await p2pClient.start();
61
-
62
- return p2pClient;
63
59
  }
64
60
 
65
- if (config.proverCoordinationNodeUrl) {
66
- log.info('Using prover coordination via node url');
61
+ let nodes: AztecNode[] = [];
62
+ if (config.proverCoordinationNodeUrls.length > 0) {
63
+ log.info('Using prover coordination via node urls');
67
64
  const versions = getComponentsVersionsFromConfig(config, protocolContractTreeRoot, getVKTreeRoot());
68
- return createAztecNodeClient(config.proverCoordinationNodeUrl, versions, makeTracedFetch([1, 2, 3], false));
69
- } else {
70
- throw new Error(`Aztec Node URL for Tx Provider is not set.`);
65
+ nodes = config.proverCoordinationNodeUrls.map(url =>
66
+ createAztecNodeClient(url, versions, makeTracedFetch([1, 2, 3], false)),
67
+ );
71
68
  }
69
+
70
+ const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier();
71
+ const p2pClient = await createP2PClient(
72
+ P2PClientType.Prover,
73
+ config,
74
+ deps.archiver,
75
+ proofVerifier,
76
+ deps.worldStateSynchronizer,
77
+ deps.epochCache,
78
+ deps.telemetry,
79
+ );
80
+ await p2pClient.start();
81
+
82
+ return new CombinedProverCoordination(p2pClient, nodes, coordinationConfig);
72
83
  }
@@ -6,7 +6,6 @@ import { createLogger } from '@aztec/foundation/log';
6
6
  import { RunningPromise } from '@aztec/foundation/running-promise';
7
7
  import { DateProvider } from '@aztec/foundation/timer';
8
8
  import type { Maybe } from '@aztec/foundation/types';
9
- import type { P2P } from '@aztec/p2p';
10
9
  import { PublicProcessorFactory } from '@aztec/simulator/server';
11
10
  import type { L2Block, L2BlockSource } from '@aztec/stdlib/block';
12
11
  import type { ContractDataSource } from '@aztec/stdlib/contract';
@@ -22,7 +21,6 @@ import {
22
21
  tryStop,
23
22
  } from '@aztec/stdlib/interfaces/server';
24
23
  import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
25
- import type { P2PClientType } from '@aztec/stdlib/p2p';
26
24
  import type { Tx, TxHash } from '@aztec/stdlib/tx';
27
25
  import {
28
26
  Attributes,
@@ -43,9 +41,7 @@ export type ProverNodeOptions = {
43
41
  pollingIntervalMs: number;
44
42
  maxPendingJobs: number;
45
43
  maxParallelBlocksPerEpoch: number;
46
- txGatheringTimeoutMs: number;
47
44
  txGatheringIntervalMs: number;
48
- txGatheringMaxParallelRequests: number;
49
45
  };
50
46
 
51
47
  /**
@@ -76,7 +72,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
76
72
  protected readonly l1ToL2MessageSource: L1ToL2MessageSource,
77
73
  protected readonly contractDataSource: ContractDataSource,
78
74
  protected readonly worldState: WorldStateSynchronizer,
79
- protected readonly coordination: ProverCoordination & Maybe<Service>,
75
+ protected readonly coordination: ProverCoordination,
80
76
  protected readonly epochsMonitor: EpochMonitor,
81
77
  options: Partial<ProverNodeOptions> = {},
82
78
  protected readonly telemetryClient: TelemetryClient = getTelemetryClient(),
@@ -91,9 +87,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
91
87
  pollingIntervalMs: 1_000,
92
88
  maxPendingJobs: 100,
93
89
  maxParallelBlocksPerEpoch: 32,
94
- txGatheringTimeoutMs: 60_000,
95
90
  txGatheringIntervalMs: 1_000,
96
- txGatheringMaxParallelRequests: 100,
97
91
  ...compact(options),
98
92
  };
99
93
 
@@ -116,11 +110,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
116
110
  }
117
111
 
118
112
  public getP2P() {
119
- const asP2PClient = this.coordination as P2P<P2PClientType.Prover>;
120
- if (typeof asP2PClient.isP2PClient === 'function' && asP2PClient.isP2PClient()) {
121
- return asP2PClient;
122
- }
123
- return undefined;
113
+ return this.coordination.getP2PClient();
124
114
  }
125
115
 
126
116
  /**
@@ -299,7 +289,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
299
289
  }
300
290
  const txHashes = block.body.txEffects.map(tx => tx.txHash);
301
291
  this.log.verbose(`Fetching ${txHashes.length} tx hashes for block number ${blockNumber} from coordination`);
302
- await this.coordination.getTxsByHash(txHashes); // This stores the txs in the tx pool, no need to persist them here
292
+ await this.coordination.gatherTxs(txHashes); // This stores the txs in the tx pool, no need to persist them here
303
293
  this.lastBlockNumber = blockNumber;
304
294
  }
305
295
  }