@aztec/prover-client 0.65.1 → 0.65.2

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 (98) hide show
  1. package/dest/config.d.ts +4 -10
  2. package/dest/config.d.ts.map +1 -1
  3. package/dest/config.js +8 -7
  4. package/dest/index.d.ts +1 -0
  5. package/dest/index.d.ts.map +1 -1
  6. package/dest/index.js +2 -1
  7. package/dest/mocks/test_context.js +3 -2
  8. package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
  9. package/dest/orchestrator/block-building-helpers.js +10 -18
  10. package/dest/orchestrator/block-proving-state.js +2 -2
  11. package/dest/prover-agent/memory-proving-queue.d.ts +10 -8
  12. package/dest/prover-agent/memory-proving-queue.d.ts.map +1 -1
  13. package/dest/prover-agent/memory-proving-queue.js +35 -35
  14. package/dest/prover-agent/prover-agent.d.ts +1 -0
  15. package/dest/prover-agent/prover-agent.d.ts.map +1 -1
  16. package/dest/prover-agent/prover-agent.js +12 -9
  17. package/dest/proving_broker/caching_broker_facade.d.ts +30 -0
  18. package/dest/proving_broker/caching_broker_facade.d.ts.map +1 -0
  19. package/dest/proving_broker/caching_broker_facade.js +150 -0
  20. package/dest/proving_broker/factory.d.ts +4 -0
  21. package/dest/proving_broker/factory.d.ts.map +1 -0
  22. package/dest/proving_broker/factory.js +17 -0
  23. package/dest/proving_broker/index.d.ts +9 -0
  24. package/dest/proving_broker/index.d.ts.map +1 -0
  25. package/dest/proving_broker/index.js +9 -0
  26. package/dest/proving_broker/proof_store.d.ts +46 -0
  27. package/dest/proving_broker/proof_store.d.ts.map +1 -0
  28. package/dest/proving_broker/proof_store.js +37 -0
  29. package/dest/proving_broker/prover_cache/memory.d.ts +9 -0
  30. package/dest/proving_broker/prover_cache/memory.d.ts.map +1 -0
  31. package/dest/proving_broker/prover_cache/memory.js +16 -0
  32. package/dest/proving_broker/proving_agent.d.ts +11 -6
  33. package/dest/proving_broker/proving_agent.d.ts.map +1 -1
  34. package/dest/proving_broker/proving_agent.js +48 -20
  35. package/dest/proving_broker/proving_broker.d.ts +17 -16
  36. package/dest/proving_broker/proving_broker.d.ts.map +1 -1
  37. package/dest/proving_broker/proving_broker.js +44 -23
  38. package/dest/proving_broker/proving_broker_database/memory.d.ts +14 -0
  39. package/dest/proving_broker/proving_broker_database/memory.d.ts.map +1 -0
  40. package/dest/proving_broker/proving_broker_database/memory.js +35 -0
  41. package/dest/proving_broker/proving_broker_database/persisted.d.ts +15 -0
  42. package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -0
  43. package/dest/proving_broker/proving_broker_database/persisted.js +35 -0
  44. package/dest/proving_broker/{proving_job_database.d.ts → proving_broker_database.d.ts} +8 -8
  45. package/dest/proving_broker/proving_broker_database.d.ts.map +1 -0
  46. package/dest/proving_broker/proving_broker_database.js +2 -0
  47. package/dest/proving_broker/proving_job_controller.d.ts +13 -8
  48. package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
  49. package/dest/proving_broker/proving_job_controller.js +43 -43
  50. package/dest/proving_broker/rpc.d.ts +11 -0
  51. package/dest/proving_broker/rpc.d.ts.map +1 -0
  52. package/dest/proving_broker/rpc.js +44 -0
  53. package/dest/test/mock_prover.d.ts +15 -1
  54. package/dest/test/mock_prover.d.ts.map +1 -1
  55. package/dest/test/mock_prover.js +36 -1
  56. package/dest/tx-prover/factory.d.ts +2 -1
  57. package/dest/tx-prover/factory.d.ts.map +1 -1
  58. package/dest/tx-prover/factory.js +3 -3
  59. package/dest/tx-prover/tx-prover.d.ts +13 -7
  60. package/dest/tx-prover/tx-prover.d.ts.map +1 -1
  61. package/dest/tx-prover/tx-prover.js +52 -35
  62. package/package.json +14 -12
  63. package/src/config.ts +17 -16
  64. package/src/index.ts +1 -0
  65. package/src/mocks/test_context.ts +2 -2
  66. package/src/orchestrator/block-building-helpers.ts +22 -33
  67. package/src/orchestrator/block-proving-state.ts +1 -1
  68. package/src/prover-agent/memory-proving-queue.ts +43 -44
  69. package/src/prover-agent/prover-agent.ts +16 -20
  70. package/src/proving_broker/caching_broker_facade.ts +312 -0
  71. package/src/proving_broker/factory.ts +21 -0
  72. package/src/proving_broker/index.ts +8 -0
  73. package/src/proving_broker/proof_store.ts +106 -0
  74. package/src/proving_broker/prover_cache/memory.ts +20 -0
  75. package/src/proving_broker/proving_agent.ts +75 -20
  76. package/src/proving_broker/proving_broker.ts +98 -65
  77. package/src/proving_broker/proving_broker_database/memory.ts +43 -0
  78. package/src/proving_broker/proving_broker_database/persisted.ts +45 -0
  79. package/src/proving_broker/{proving_job_database.ts → proving_broker_database.ts} +7 -12
  80. package/src/proving_broker/proving_job_controller.ts +54 -46
  81. package/src/proving_broker/rpc.ts +64 -0
  82. package/src/test/mock_prover.ts +51 -0
  83. package/src/tx-prover/factory.ts +7 -2
  84. package/src/tx-prover/tx-prover.ts +78 -46
  85. package/dest/proving_broker/proving_broker_interface.d.ts +0 -61
  86. package/dest/proving_broker/proving_broker_interface.d.ts.map +0 -1
  87. package/dest/proving_broker/proving_broker_interface.js +0 -2
  88. package/dest/proving_broker/proving_job_database/memory.d.ts +0 -14
  89. package/dest/proving_broker/proving_job_database/memory.d.ts.map +0 -1
  90. package/dest/proving_broker/proving_job_database/memory.js +0 -35
  91. package/dest/proving_broker/proving_job_database/persisted.d.ts +0 -15
  92. package/dest/proving_broker/proving_job_database/persisted.d.ts.map +0 -1
  93. package/dest/proving_broker/proving_job_database/persisted.js +0 -35
  94. package/dest/proving_broker/proving_job_database.d.ts.map +0 -1
  95. package/dest/proving_broker/proving_job_database.js +0 -2
  96. package/src/proving_broker/proving_broker_interface.ts +0 -74
  97. package/src/proving_broker/proving_job_database/memory.ts +0 -43
  98. package/src/proving_broker/proving_job_database/persisted.ts +0 -45
@@ -1,14 +1,18 @@
1
1
  import {
2
2
  ProvingError,
3
- type ProvingRequestType,
3
+ type ProvingJob,
4
+ type ProvingJobConsumer,
5
+ type ProvingJobId,
6
+ type ProvingJobInputs,
7
+ type ProvingJobResultsMap,
8
+ ProvingRequestType,
4
9
  type ServerCircuitProver,
5
- type V2ProvingJob,
6
10
  } from '@aztec/circuit-types';
7
11
  import { createDebugLogger } from '@aztec/foundation/log';
8
12
  import { RunningPromise } from '@aztec/foundation/running-promise';
9
13
 
10
- import { type ProvingJobConsumer } from './proving_broker_interface.js';
11
- import { ProvingJobController, ProvingJobStatus } from './proving_job_controller.js';
14
+ import { type ProofStore } from './proof_store.js';
15
+ import { ProvingJobController, ProvingJobControllerStatus } from './proving_job_controller.js';
12
16
 
13
17
  /**
14
18
  * A helper class that encapsulates a circuit prover and connects it to a job source.
@@ -19,14 +23,16 @@ export class ProvingAgent {
19
23
 
20
24
  constructor(
21
25
  /** The source of proving jobs */
22
- private jobSource: ProvingJobConsumer,
26
+ private broker: ProvingJobConsumer,
27
+ /** Database holding proof inputs and outputs */
28
+ private proofStore: ProofStore,
23
29
  /** The prover implementation to defer jobs to */
24
30
  private circuitProver: ServerCircuitProver,
25
31
  /** Optional list of allowed proof types to build */
26
- private proofAllowList?: Array<ProvingRequestType>,
32
+ private proofAllowList: Array<ProvingRequestType> = [],
27
33
  /** How long to wait between jobs */
28
34
  private pollIntervalMs = 1000,
29
- private log = createDebugLogger('aztec:proving-broker:proving-agent'),
35
+ private log = createDebugLogger('aztec:prover-client:proving-agent'),
30
36
  ) {
31
37
  this.runningPromise = new RunningPromise(this.safeWork, this.pollIntervalMs);
32
38
  }
@@ -54,37 +60,86 @@ export class ProvingAgent {
54
60
  // (1) either do a heartbeat, telling the broker that we're working
55
61
  // (2) get a new job
56
62
  // If during (1) the broker returns a new job that means we can cancel the current job and start the new one
57
- let maybeJob: { job: V2ProvingJob; time: number } | undefined;
58
- if (this.currentJobController?.getStatus() === ProvingJobStatus.PROVING) {
59
- maybeJob = await this.jobSource.reportProvingJobProgress(
63
+ let maybeJob: { job: ProvingJob; time: number } | undefined;
64
+ if (this.currentJobController?.getStatus() === ProvingJobControllerStatus.PROVING) {
65
+ maybeJob = await this.broker.reportProvingJobProgress(
60
66
  this.currentJobController.getJobId(),
61
67
  this.currentJobController.getStartedAt(),
62
68
  { allowList: this.proofAllowList },
63
69
  );
64
70
  } else {
65
- maybeJob = await this.jobSource.getProvingJob({ allowList: this.proofAllowList });
71
+ maybeJob = await this.broker.getProvingJob({ allowList: this.proofAllowList });
66
72
  }
67
73
 
68
74
  if (!maybeJob) {
69
75
  return;
70
76
  }
71
77
 
72
- if (this.currentJobController?.getStatus() === ProvingJobStatus.PROVING) {
78
+ let abortedProofJobId: string | undefined;
79
+ let abortedProofName: string | undefined;
80
+ if (this.currentJobController?.getStatus() === ProvingJobControllerStatus.PROVING) {
81
+ abortedProofJobId = this.currentJobController.getJobId();
82
+ abortedProofName = this.currentJobController.getProofTypeName();
73
83
  this.currentJobController?.abort();
74
84
  }
75
85
 
76
86
  const { job, time } = maybeJob;
77
- this.currentJobController = new ProvingJobController(job, time, this.circuitProver, (err, result) => {
78
- if (err) {
79
- const retry = err.name === ProvingError.NAME ? (err as ProvingError).retry : false;
80
- return this.jobSource.reportProvingJobError(job.id, err, retry);
81
- } else if (result) {
82
- return this.jobSource.reportProvingJobSuccess(job.id, result);
83
- }
84
- });
87
+ let inputs: ProvingJobInputs;
88
+ try {
89
+ inputs = await this.proofStore.getProofInput(job.inputsUri);
90
+ } catch (err) {
91
+ await this.broker.reportProvingJobError(job.id, 'Failed to load proof inputs', true);
92
+ return;
93
+ }
94
+
95
+ this.currentJobController = new ProvingJobController(
96
+ job.id,
97
+ inputs,
98
+ time,
99
+ this.circuitProver,
100
+ this.handleJobResult,
101
+ );
102
+
103
+ if (abortedProofJobId) {
104
+ this.log.info(
105
+ `Aborting job id=${abortedProofJobId} type=${abortedProofName} to start new job id=${this.currentJobController.getJobId()} type=${this.currentJobController.getProofTypeName()} inputsUri=${truncateString(
106
+ job.inputsUri,
107
+ )}`,
108
+ );
109
+ } else {
110
+ this.log.info(
111
+ `Starting job id=${this.currentJobController.getJobId()} type=${this.currentJobController.getProofTypeName()} inputsUri=${truncateString(
112
+ job.inputsUri,
113
+ )}`,
114
+ );
115
+ }
116
+
85
117
  this.currentJobController.start();
86
118
  } catch (err) {
87
119
  this.log.error(`Error in ProvingAgent: ${String(err)}`);
88
120
  }
89
121
  };
122
+
123
+ handleJobResult = async <T extends ProvingRequestType>(
124
+ jobId: ProvingJobId,
125
+ type: T,
126
+ err: Error | undefined,
127
+ result: ProvingJobResultsMap[T] | undefined,
128
+ ) => {
129
+ if (err) {
130
+ const retry = err.name === ProvingError.NAME ? (err as ProvingError).retry : false;
131
+ this.log.info(`Job id=${jobId} type=${ProvingRequestType[type]} failed err=${err.message} retry=${retry}`);
132
+ return this.broker.reportProvingJobError(jobId, err.message, retry);
133
+ } else if (result) {
134
+ const outputUri = await this.proofStore.saveProofOutput(jobId, type, result);
135
+ this.log.info(
136
+ `Job id=${jobId} type=${ProvingRequestType[type]} completed outputUri=${truncateString(outputUri)}`,
137
+ );
138
+ return this.broker.reportProvingJobSuccess(jobId, outputUri);
139
+ }
140
+ };
141
+ }
142
+
143
+ function truncateString(str: string, length: number = 64): string {
144
+ return str.length > length ? str.slice(0, length) + '...' : str;
90
145
  }
@@ -1,29 +1,31 @@
1
1
  import {
2
+ type ProofUri,
3
+ type ProvingJob,
4
+ type ProvingJobConsumer,
5
+ type ProvingJobFilter,
6
+ type ProvingJobId,
7
+ type ProvingJobProducer,
8
+ type ProvingJobSettledResult,
9
+ type ProvingJobStatus,
2
10
  ProvingRequestType,
3
- type V2ProofOutput,
4
- type V2ProvingJob,
5
- type V2ProvingJobId,
6
- type V2ProvingJobResult,
7
- type V2ProvingJobStatus,
8
11
  } from '@aztec/circuit-types';
9
12
  import { createDebugLogger } from '@aztec/foundation/log';
10
- import { RunningPromise } from '@aztec/foundation/promise';
13
+ import { type PromiseWithResolvers, RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise';
11
14
  import { PriorityMemoryQueue } from '@aztec/foundation/queue';
12
15
 
13
16
  import assert from 'assert';
14
17
 
15
- import type { ProvingJobConsumer, ProvingJobFilter, ProvingJobProducer } from './proving_broker_interface.js';
16
- import { type ProvingJobDatabase } from './proving_job_database.js';
18
+ import { type ProvingBrokerDatabase } from './proving_broker_database.js';
17
19
 
18
20
  type InProgressMetadata = {
19
- id: V2ProvingJobId;
21
+ id: ProvingJobId;
20
22
  startedAt: number;
21
23
  lastUpdatedAt: number;
22
24
  };
23
25
 
24
26
  type ProofRequestBrokerConfig = {
25
- timeoutIntervalSec?: number;
26
- jobTimeoutSec?: number;
27
+ timeoutIntervalMs?: number;
28
+ jobTimeoutMs?: number;
27
29
  maxRetries?: number;
28
30
  };
29
31
 
@@ -33,50 +35,53 @@ type ProofRequestBrokerConfig = {
33
35
  */
34
36
  export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
35
37
  private queues: ProvingQueues = {
36
- [ProvingRequestType.PUBLIC_VM]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
37
- [ProvingRequestType.TUBE_PROOF]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
38
- [ProvingRequestType.PRIVATE_KERNEL_EMPTY]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
38
+ [ProvingRequestType.PUBLIC_VM]: new PriorityMemoryQueue<ProvingJob>(provingJobComparator),
39
+ [ProvingRequestType.TUBE_PROOF]: new PriorityMemoryQueue<ProvingJob>(provingJobComparator),
40
+ [ProvingRequestType.PRIVATE_KERNEL_EMPTY]: new PriorityMemoryQueue<ProvingJob>(provingJobComparator),
39
41
 
40
- [ProvingRequestType.PRIVATE_BASE_ROLLUP]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
41
- [ProvingRequestType.PUBLIC_BASE_ROLLUP]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
42
- [ProvingRequestType.MERGE_ROLLUP]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
43
- [ProvingRequestType.ROOT_ROLLUP]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
42
+ [ProvingRequestType.PRIVATE_BASE_ROLLUP]: new PriorityMemoryQueue<ProvingJob>(provingJobComparator),
43
+ [ProvingRequestType.PUBLIC_BASE_ROLLUP]: new PriorityMemoryQueue<ProvingJob>(provingJobComparator),
44
+ [ProvingRequestType.MERGE_ROLLUP]: new PriorityMemoryQueue<ProvingJob>(provingJobComparator),
45
+ [ProvingRequestType.ROOT_ROLLUP]: new PriorityMemoryQueue<ProvingJob>(provingJobComparator),
44
46
 
45
- [ProvingRequestType.BLOCK_MERGE_ROLLUP]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
46
- [ProvingRequestType.BLOCK_ROOT_ROLLUP]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
47
- [ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
47
+ [ProvingRequestType.BLOCK_MERGE_ROLLUP]: new PriorityMemoryQueue<ProvingJob>(provingJobComparator),
48
+ [ProvingRequestType.BLOCK_ROOT_ROLLUP]: new PriorityMemoryQueue<ProvingJob>(provingJobComparator),
49
+ [ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP]: new PriorityMemoryQueue<ProvingJob>(provingJobComparator),
48
50
 
49
- [ProvingRequestType.BASE_PARITY]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
50
- [ProvingRequestType.ROOT_PARITY]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
51
+ [ProvingRequestType.BASE_PARITY]: new PriorityMemoryQueue<ProvingJob>(provingJobComparator),
52
+ [ProvingRequestType.ROOT_PARITY]: new PriorityMemoryQueue<ProvingJob>(provingJobComparator),
51
53
  };
52
54
 
53
55
  // holds a copy of the database in memory in order to quickly fulfill requests
54
56
  // this is fine because this broker is the only one that can modify the database
55
- private jobsCache = new Map<V2ProvingJobId, V2ProvingJob>();
57
+ private jobsCache = new Map<ProvingJobId, ProvingJob>();
56
58
  // as above, but for results
57
- private resultsCache = new Map<V2ProvingJobId, V2ProvingJobResult>();
59
+ private resultsCache = new Map<ProvingJobId, ProvingJobSettledResult>();
58
60
 
59
61
  // keeps track of which jobs are currently being processed
60
62
  // in the event of a crash this information is lost, but that's ok
61
63
  // the next time the broker starts it will recreate jobsCache and still
62
64
  // accept results from the workers
63
- private inProgress = new Map<V2ProvingJobId, InProgressMetadata>();
65
+ private inProgress = new Map<ProvingJobId, InProgressMetadata>();
64
66
 
65
67
  // keep track of which proving job has been retried
66
- private retries = new Map<V2ProvingJobId, number>();
68
+ private retries = new Map<ProvingJobId, number>();
69
+
70
+ // a map of promises that will be resolved when a job is settled
71
+ private promises = new Map<ProvingJobId, PromiseWithResolvers<ProvingJobSettledResult>>();
67
72
 
68
73
  private timeoutPromise: RunningPromise;
69
74
  private timeSource = () => Math.floor(Date.now() / 1000);
70
- private jobTimeoutSec: number;
75
+ private jobTimeoutMs: number;
71
76
  private maxRetries: number;
72
77
 
73
78
  public constructor(
74
- private database: ProvingJobDatabase,
75
- { jobTimeoutSec = 30, timeoutIntervalSec = 10, maxRetries = 3 }: ProofRequestBrokerConfig = {},
76
- private logger = createDebugLogger('aztec:prover-client:proof-request-broker'),
79
+ private database: ProvingBrokerDatabase,
80
+ { jobTimeoutMs = 30, timeoutIntervalMs = 10, maxRetries = 3 }: ProofRequestBrokerConfig = {},
81
+ private logger = createDebugLogger('aztec:prover-client:proving-broker'),
77
82
  ) {
78
- this.timeoutPromise = new RunningPromise(this.timeoutCheck, timeoutIntervalSec * 1000);
79
- this.jobTimeoutSec = jobTimeoutSec;
83
+ this.timeoutPromise = new RunningPromise(this.timeoutCheck, timeoutIntervalMs);
84
+ this.jobTimeoutMs = jobTimeoutMs;
80
85
  this.maxRetries = maxRetries;
81
86
  }
82
87
 
@@ -86,7 +91,10 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
86
91
  this.logger.info(`Restoring proving job id=${item.id} settled=${!!result}`);
87
92
 
88
93
  this.jobsCache.set(item.id, item);
94
+ this.promises.set(item.id, promiseWithResolvers());
95
+
89
96
  if (result) {
97
+ this.promises.get(item.id)!.resolve(result);
90
98
  this.resultsCache.set(item.id, result);
91
99
  } else {
92
100
  this.logger.debug(`Re-enqueuing proving job id=${item.id}`);
@@ -101,7 +109,7 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
101
109
  return this.timeoutPromise.stop();
102
110
  }
103
111
 
104
- public async enqueueProvingJob(job: V2ProvingJob): Promise<void> {
112
+ public async enqueueProvingJob(job: ProvingJob): Promise<void> {
105
113
  if (this.jobsCache.has(job.id)) {
106
114
  const existing = this.jobsCache.get(job.id);
107
115
  assert.deepStrictEqual(job, existing, 'Duplicate proving job ID');
@@ -113,20 +121,35 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
113
121
  this.enqueueJobInternal(job);
114
122
  }
115
123
 
116
- public async removeAndCancelProvingJob(id: V2ProvingJobId): Promise<void> {
124
+ public waitForJobToSettle(id: ProvingJobId): Promise<ProvingJobSettledResult> {
125
+ const promiseWithResolvers = this.promises.get(id);
126
+ if (!promiseWithResolvers) {
127
+ return Promise.resolve({ status: 'rejected', reason: `Job ${id} not found` });
128
+ }
129
+ return promiseWithResolvers.promise;
130
+ }
131
+
132
+ public async removeAndCancelProvingJob(id: ProvingJobId): Promise<void> {
117
133
  this.logger.info(`Cancelling job id=${id}`);
118
134
  await this.database.deleteProvingJobAndResult(id);
119
135
 
136
+ // notify listeners of the cancellation
137
+ if (!this.resultsCache.has(id)) {
138
+ this.promises.get(id)?.resolve({ status: 'rejected', reason: 'Aborted' });
139
+ }
140
+
120
141
  this.jobsCache.delete(id);
142
+ this.promises.delete(id);
121
143
  this.resultsCache.delete(id);
122
144
  this.inProgress.delete(id);
123
145
  this.retries.delete(id);
124
146
  }
125
147
 
126
- // eslint-disable-next-line require-await
127
- public async getProvingJobStatus(id: V2ProvingJobId): Promise<V2ProvingJobStatus> {
148
+ public getProvingJobStatus(id: ProvingJobId): Promise<ProvingJobStatus> {
128
149
  const result = this.resultsCache.get(id);
129
- if (!result) {
150
+ if (result) {
151
+ return Promise.resolve(result);
152
+ } else {
130
153
  // no result yet, check if we know the item
131
154
  const item = this.jobsCache.get(id);
132
155
 
@@ -136,29 +159,26 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
136
159
  }
137
160
 
138
161
  return Promise.resolve({ status: this.inProgress.has(id) ? 'in-progress' : 'in-queue' });
139
- } else if ('value' in result) {
140
- return Promise.resolve({ status: 'resolved', value: result.value });
141
- } else {
142
- return Promise.resolve({ status: 'rejected', error: result.error });
143
162
  }
144
163
  }
145
164
 
146
165
  // eslint-disable-next-line require-await
147
- async getProvingJob<T extends ProvingRequestType[]>(
148
- filter: ProvingJobFilter<T> = {},
149
- ): Promise<{ job: V2ProvingJob; time: number } | undefined> {
150
- const allowedProofs: ProvingRequestType[] = filter.allowList
151
- ? [...filter.allowList]
152
- : Object.values(ProvingRequestType).filter((x): x is ProvingRequestType => typeof x === 'number');
166
+ async getProvingJob(
167
+ filter: ProvingJobFilter = { allowList: [] },
168
+ ): Promise<{ job: ProvingJob; time: number } | undefined> {
169
+ const allowedProofs: ProvingRequestType[] =
170
+ Array.isArray(filter.allowList) && filter.allowList.length > 0
171
+ ? [...filter.allowList]
172
+ : Object.values(ProvingRequestType).filter((x): x is ProvingRequestType => typeof x === 'number');
153
173
  allowedProofs.sort(proofTypeComparator);
154
174
 
155
175
  for (const proofType of allowedProofs) {
156
176
  const queue = this.queues[proofType];
157
- let job: V2ProvingJob | undefined;
177
+ let job: ProvingJob | undefined;
158
178
  // exhaust the queue and make sure we're not sending a job that's already in progress
159
179
  // or has already been completed
160
180
  // this can happen if the broker crashes and restarts
161
- // it's possible agents will report progress or results for jobs that are no longer in the queue
181
+ // it's possible agents will report progress or results for jobs that are in the queue (after the restart)
162
182
  while ((job = queue.getImmediate())) {
163
183
  if (!this.inProgress.has(job.id) && !this.resultsCache.has(job.id)) {
164
184
  const time = this.timeSource();
@@ -176,7 +196,7 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
176
196
  return undefined;
177
197
  }
178
198
 
179
- async reportProvingJobError(id: V2ProvingJobId, err: Error, retry = false): Promise<void> {
199
+ async reportProvingJobError(id: ProvingJobId, err: string, retry = false): Promise<void> {
180
200
  const info = this.inProgress.get(id);
181
201
  const item = this.jobsCache.get(id);
182
202
  const retries = this.retries.get(id) ?? 0;
@@ -202,15 +222,19 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
202
222
  this.logger.debug(
203
223
  `Marking proving job id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1} as failed`,
204
224
  );
225
+
205
226
  await this.database.setProvingJobError(id, err);
206
- this.resultsCache.set(id, { error: String(err) });
227
+
228
+ const result: ProvingJobSettledResult = { status: 'rejected', reason: String(err) };
229
+ this.resultsCache.set(id, result);
230
+ this.promises.get(id)!.resolve(result);
207
231
  }
208
232
 
209
- reportProvingJobProgress<F extends ProvingRequestType[]>(
210
- id: V2ProvingJobId,
233
+ reportProvingJobProgress(
234
+ id: ProvingJobId,
211
235
  startedAt: number,
212
- filter?: ProvingJobFilter<F>,
213
- ): Promise<{ job: V2ProvingJob; time: number } | undefined> {
236
+ filter?: ProvingJobFilter,
237
+ ): Promise<{ job: ProvingJob; time: number } | undefined> {
214
238
  const job = this.jobsCache.get(id);
215
239
  if (!job) {
216
240
  this.logger.warn(`Proving job id=${id} does not exist`);
@@ -255,7 +279,7 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
255
279
  }
256
280
  }
257
281
 
258
- async reportProvingJobSuccess(id: V2ProvingJobId, value: V2ProofOutput): Promise<void> {
282
+ async reportProvingJobSuccess(id: ProvingJobId, value: ProofUri): Promise<void> {
259
283
  const info = this.inProgress.get(id);
260
284
  const item = this.jobsCache.get(id);
261
285
  const retries = this.retries.get(id) ?? 0;
@@ -273,8 +297,12 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
273
297
  this.logger.debug(
274
298
  `Proving job complete id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1}`,
275
299
  );
300
+
276
301
  await this.database.setProvingJobResult(id, value);
277
- this.resultsCache.set(id, { value });
302
+
303
+ const result: ProvingJobSettledResult = { status: 'fulfilled', value };
304
+ this.resultsCache.set(id, result);
305
+ this.promises.get(id)!.resolve(result);
278
306
  }
279
307
 
280
308
  private timeoutCheck = () => {
@@ -287,8 +315,8 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
287
315
  continue;
288
316
  }
289
317
 
290
- const secondsSinceLastUpdate = this.timeSource() - metadata.lastUpdatedAt;
291
- if (secondsSinceLastUpdate >= this.jobTimeoutSec) {
318
+ const msSinceLastUpdate = (this.timeSource() - metadata.lastUpdatedAt) * 1000;
319
+ if (msSinceLastUpdate >= this.jobTimeoutMs) {
292
320
  this.logger.warn(`Proving job id=${id} timed out. Adding it back to the queue.`);
293
321
  this.inProgress.delete(id);
294
322
  this.enqueueJobInternal(item);
@@ -296,14 +324,17 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
296
324
  }
297
325
  };
298
326
 
299
- private enqueueJobInternal(job: V2ProvingJob): void {
327
+ private enqueueJobInternal(job: ProvingJob): void {
328
+ if (!this.promises.has(job.id)) {
329
+ this.promises.set(job.id, promiseWithResolvers());
330
+ }
300
331
  this.queues[job.type].put(job);
301
332
  this.logger.debug(`Enqueued new proving job id=${job.id}`);
302
333
  }
303
334
  }
304
335
 
305
336
  type ProvingQueues = {
306
- [K in ProvingRequestType]: PriorityMemoryQueue<V2ProvingJob>;
337
+ [K in ProvingRequestType]: PriorityMemoryQueue<ProvingJob>;
307
338
  };
308
339
 
309
340
  /**
@@ -312,10 +343,12 @@ type ProvingQueues = {
312
343
  * @param b - Another proving job
313
344
  * @returns A number indicating the relative priority of the two proving jobs
314
345
  */
315
- function provingJobComparator(a: V2ProvingJob, b: V2ProvingJob): -1 | 0 | 1 {
316
- if (a.blockNumber < b.blockNumber) {
346
+ function provingJobComparator(a: ProvingJob, b: ProvingJob): -1 | 0 | 1 {
347
+ const aBlockNumber = a.blockNumber ?? 0;
348
+ const bBlockNumber = b.blockNumber ?? 0;
349
+ if (aBlockNumber < bBlockNumber) {
317
350
  return -1;
318
- } else if (a.blockNumber > b.blockNumber) {
351
+ } else if (aBlockNumber > bBlockNumber) {
319
352
  return 1;
320
353
  } else {
321
354
  return 0;
@@ -0,0 +1,43 @@
1
+ import type { ProofUri, ProvingJob, ProvingJobId, ProvingJobSettledResult } from '@aztec/circuit-types';
2
+
3
+ import { type ProvingBrokerDatabase } from '../proving_broker_database.js';
4
+
5
+ export class InMemoryBrokerDatabase implements ProvingBrokerDatabase {
6
+ private jobs = new Map<ProvingJobId, ProvingJob>();
7
+ private results = new Map<ProvingJobId, ProvingJobSettledResult>();
8
+
9
+ getProvingJob(id: ProvingJobId): ProvingJob | undefined {
10
+ return this.jobs.get(id);
11
+ }
12
+
13
+ getProvingJobResult(id: ProvingJobId): ProvingJobSettledResult | undefined {
14
+ return this.results.get(id);
15
+ }
16
+
17
+ addProvingJob(request: ProvingJob): Promise<void> {
18
+ this.jobs.set(request.id, request);
19
+ return Promise.resolve();
20
+ }
21
+
22
+ setProvingJobResult(id: ProvingJobId, value: ProofUri): Promise<void> {
23
+ this.results.set(id, { status: 'fulfilled', value });
24
+ return Promise.resolve();
25
+ }
26
+
27
+ setProvingJobError(id: ProvingJobId, reason: string): Promise<void> {
28
+ this.results.set(id, { status: 'rejected', reason });
29
+ return Promise.resolve();
30
+ }
31
+
32
+ deleteProvingJobAndResult(id: ProvingJobId): Promise<void> {
33
+ this.jobs.delete(id);
34
+ this.results.delete(id);
35
+ return Promise.resolve();
36
+ }
37
+
38
+ *allProvingJobs(): Iterable<[ProvingJob, ProvingJobSettledResult | undefined]> {
39
+ for (const item of this.jobs.values()) {
40
+ yield [item, this.results.get(item.id)] as const;
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,45 @@
1
+ import { type ProofUri, ProvingJob, type ProvingJobId, ProvingJobSettledResult } from '@aztec/circuit-types';
2
+ import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc';
3
+ import { type AztecKVStore, type AztecMap } from '@aztec/kv-store';
4
+
5
+ import { type ProvingBrokerDatabase } from '../proving_broker_database.js';
6
+
7
+ export class KVBrokerDatabase implements ProvingBrokerDatabase {
8
+ private jobs: AztecMap<ProvingJobId, string>;
9
+ private jobResults: AztecMap<ProvingJobId, string>;
10
+
11
+ constructor(private store: AztecKVStore) {
12
+ this.jobs = store.openMap('proving_jobs');
13
+ this.jobResults = store.openMap('proving_job_results');
14
+ }
15
+
16
+ async addProvingJob(job: ProvingJob): Promise<void> {
17
+ await this.jobs.set(job.id, jsonStringify(job));
18
+ }
19
+
20
+ *allProvingJobs(): Iterable<[ProvingJob, ProvingJobSettledResult | undefined]> {
21
+ for (const jobStr of this.jobs.values()) {
22
+ const job = jsonParseWithSchema(jobStr, ProvingJob);
23
+ const resultStr = this.jobResults.get(job.id);
24
+ const result = resultStr ? jsonParseWithSchema(resultStr, ProvingJobSettledResult) : undefined;
25
+ yield [job, result];
26
+ }
27
+ }
28
+
29
+ deleteProvingJobAndResult(id: ProvingJobId): Promise<void> {
30
+ return this.store.transaction(() => {
31
+ void this.jobs.delete(id);
32
+ void this.jobResults.delete(id);
33
+ });
34
+ }
35
+
36
+ async setProvingJobError(id: ProvingJobId, reason: string): Promise<void> {
37
+ const result: ProvingJobSettledResult = { status: 'rejected', reason };
38
+ await this.jobResults.set(id, jsonStringify(result));
39
+ }
40
+
41
+ async setProvingJobResult(id: ProvingJobId, value: ProofUri): Promise<void> {
42
+ const result: ProvingJobSettledResult = { status: 'fulfilled', value };
43
+ await this.jobResults.set(id, jsonStringify(result));
44
+ }
45
+ }
@@ -1,30 +1,25 @@
1
- import {
2
- type V2ProofOutput,
3
- type V2ProvingJob,
4
- type V2ProvingJobId,
5
- type V2ProvingJobResult,
6
- } from '@aztec/circuit-types';
1
+ import { type ProofUri, type ProvingJob, type ProvingJobId, type ProvingJobSettledResult } from '@aztec/circuit-types';
7
2
 
8
3
  /**
9
4
  * A database for storing proof requests and their results
10
5
  */
11
- export interface ProvingJobDatabase {
6
+ export interface ProvingBrokerDatabase {
12
7
  /**
13
8
  * Saves a proof request so it can be retrieved later
14
9
  * @param request - The proof request to save
15
10
  */
16
- addProvingJob(request: V2ProvingJob): Promise<void>;
11
+ addProvingJob(request: ProvingJob): Promise<void>;
17
12
 
18
13
  /**
19
14
  * Removes a proof request from the backend
20
15
  * @param id - The ID of the proof request to remove
21
16
  */
22
- deleteProvingJobAndResult(id: V2ProvingJobId): Promise<void>;
17
+ deleteProvingJobAndResult(id: ProvingJobId): Promise<void>;
23
18
 
24
19
  /**
25
20
  * Returns an iterator over all saved proving jobs
26
21
  */
27
- allProvingJobs(): Iterable<[V2ProvingJob, V2ProvingJobResult | undefined]>;
22
+ allProvingJobs(): Iterable<[ProvingJob, ProvingJobSettledResult | undefined]>;
28
23
 
29
24
  /**
30
25
  * Saves the result of a proof request
@@ -32,7 +27,7 @@ export interface ProvingJobDatabase {
32
27
  * @param ProvingRequestType - The type of proof that was requested
33
28
  * @param value - The result of the proof request
34
29
  */
35
- setProvingJobResult(id: V2ProvingJobId, value: V2ProofOutput): Promise<void>;
30
+ setProvingJobResult(id: ProvingJobId, value: ProofUri): Promise<void>;
36
31
 
37
32
  /**
38
33
  * Saves an error that occurred while processing a proof request
@@ -40,5 +35,5 @@ export interface ProvingJobDatabase {
40
35
  * @param ProvingRequestType - The type of proof that was requested
41
36
  * @param err - The error that occurred while processing the proof request
42
37
  */
43
- setProvingJobError(id: V2ProvingJobId, err: Error): Promise<void>;
38
+ setProvingJobError(id: ProvingJobId, err: string): Promise<void>;
44
39
  }