@aztec/prover-client 0.62.0 → 0.63.1

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 (59) hide show
  1. package/dest/mocks/fixtures.d.ts +2 -4
  2. package/dest/mocks/fixtures.d.ts.map +1 -1
  3. package/dest/mocks/fixtures.js +8 -15
  4. package/dest/mocks/test_context.d.ts +3 -2
  5. package/dest/mocks/test_context.d.ts.map +1 -1
  6. package/dest/mocks/test_context.js +16 -15
  7. package/dest/orchestrator/block-building-helpers.d.ts +5 -13
  8. package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
  9. package/dest/orchestrator/block-building-helpers.js +28 -16
  10. package/dest/orchestrator/orchestrator.d.ts +3 -2
  11. package/dest/orchestrator/orchestrator.d.ts.map +1 -1
  12. package/dest/orchestrator/orchestrator.js +23 -22
  13. package/dest/orchestrator/tx-proving-state.d.ts +3 -3
  14. package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
  15. package/dest/orchestrator/tx-proving-state.js +31 -22
  16. package/dest/prover-agent/memory-proving-queue.d.ts +8 -9
  17. package/dest/prover-agent/memory-proving-queue.d.ts.map +1 -1
  18. package/dest/prover-agent/memory-proving-queue.js +6 -9
  19. package/dest/prover-agent/prover-agent.d.ts +7 -6
  20. package/dest/prover-agent/prover-agent.d.ts.map +1 -1
  21. package/dest/prover-agent/prover-agent.js +18 -10
  22. package/dest/prover-agent/rpc.d.ts +4 -5
  23. package/dest/prover-agent/rpc.d.ts.map +1 -1
  24. package/dest/prover-agent/rpc.js +9 -72
  25. package/dest/proving_broker/proving_broker.d.ts +45 -0
  26. package/dest/proving_broker/proving_broker.d.ts.map +1 -0
  27. package/dest/proving_broker/proving_broker.js +298 -0
  28. package/dest/proving_broker/proving_broker_interface.d.ts +61 -0
  29. package/dest/proving_broker/proving_broker_interface.d.ts.map +1 -0
  30. package/dest/proving_broker/proving_broker_interface.js +2 -0
  31. package/dest/proving_broker/proving_job_database/memory.d.ts +14 -0
  32. package/dest/proving_broker/proving_job_database/memory.d.ts.map +1 -0
  33. package/dest/proving_broker/proving_job_database/memory.js +35 -0
  34. package/dest/proving_broker/proving_job_database/persisted.d.ts +15 -0
  35. package/dest/proving_broker/proving_job_database/persisted.d.ts.map +1 -0
  36. package/dest/proving_broker/proving_job_database/persisted.js +34 -0
  37. package/dest/proving_broker/proving_job_database.d.ts +35 -0
  38. package/dest/proving_broker/proving_job_database.d.ts.map +1 -0
  39. package/dest/proving_broker/proving_job_database.js +2 -0
  40. package/dest/test/mock_prover.d.ts +5 -6
  41. package/dest/test/mock_prover.d.ts.map +1 -1
  42. package/dest/test/mock_prover.js +5 -8
  43. package/dest/tx-prover/tx-prover.js +2 -2
  44. package/package.json +13 -12
  45. package/src/mocks/fixtures.ts +12 -36
  46. package/src/mocks/test_context.ts +21 -32
  47. package/src/orchestrator/block-building-helpers.ts +35 -18
  48. package/src/orchestrator/orchestrator.ts +41 -27
  49. package/src/orchestrator/tx-proving-state.ts +45 -32
  50. package/src/prover-agent/memory-proving-queue.ts +15 -24
  51. package/src/prover-agent/prover-agent.ts +29 -16
  52. package/src/prover-agent/rpc.ts +9 -120
  53. package/src/proving_broker/proving_broker.ts +372 -0
  54. package/src/proving_broker/proving_broker_interface.ts +74 -0
  55. package/src/proving_broker/proving_job_database/memory.ts +43 -0
  56. package/src/proving_broker/proving_job_database/persisted.ts +44 -0
  57. package/src/proving_broker/proving_job_database.ts +44 -0
  58. package/src/test/mock_prover.ts +17 -15
  59. package/src/tx-prover/tx-prover.ts +1 -1
@@ -0,0 +1,372 @@
1
+ import {
2
+ ProvingRequestType,
3
+ type V2ProofOutput,
4
+ type V2ProvingJob,
5
+ type V2ProvingJobId,
6
+ type V2ProvingJobResult,
7
+ type V2ProvingJobStatus,
8
+ } from '@aztec/circuit-types';
9
+ import { createDebugLogger } from '@aztec/foundation/log';
10
+ import { RunningPromise } from '@aztec/foundation/promise';
11
+ import { PriorityMemoryQueue } from '@aztec/foundation/queue';
12
+
13
+ import assert from 'assert';
14
+
15
+ import type { ProvingJobConsumer, ProvingJobFilter, ProvingJobProducer } from './proving_broker_interface.js';
16
+ import { type ProvingJobDatabase } from './proving_job_database.js';
17
+
18
+ type InProgressMetadata = {
19
+ id: V2ProvingJobId;
20
+ startedAt: number;
21
+ lastUpdatedAt: number;
22
+ };
23
+
24
+ type ProofRequestBrokerConfig = {
25
+ timeoutIntervalSec?: number;
26
+ jobTimeoutSec?: number;
27
+ maxRetries?: number;
28
+ };
29
+
30
+ /**
31
+ * A broker that manages proof requests and distributes them to workers based on their priority.
32
+ * It takes a backend that is responsible for storing and retrieving proof requests and results.
33
+ */
34
+ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
35
+ 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),
39
+
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),
44
+
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),
48
+
49
+ [ProvingRequestType.BASE_PARITY]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
50
+ [ProvingRequestType.ROOT_PARITY]: new PriorityMemoryQueue<V2ProvingJob>(provingJobComparator),
51
+ };
52
+
53
+ // holds a copy of the database in memory in order to quickly fulfill requests
54
+ // this is fine because this broker is the only one that can modify the database
55
+ private jobsCache = new Map<V2ProvingJobId, V2ProvingJob>();
56
+ // as above, but for results
57
+ private resultsCache = new Map<V2ProvingJobId, V2ProvingJobResult>();
58
+
59
+ // keeps track of which jobs are currently being processed
60
+ // in the event of a crash this information is lost, but that's ok
61
+ // the next time the broker starts it will recreate jobsCache and still
62
+ // accept results from the workers
63
+ private inProgress = new Map<V2ProvingJobId, InProgressMetadata>();
64
+
65
+ // keep track of which proving job has been retried
66
+ private retries = new Map<V2ProvingJobId, number>();
67
+
68
+ private timeoutPromise: RunningPromise;
69
+ private timeSource = () => Math.floor(Date.now() / 1000);
70
+ private jobTimeoutSec: number;
71
+ private maxRetries: number;
72
+
73
+ public constructor(
74
+ private database: ProvingJobDatabase,
75
+ { jobTimeoutSec = 30, timeoutIntervalSec = 10, maxRetries = 3 }: ProofRequestBrokerConfig = {},
76
+ private logger = createDebugLogger('aztec:prover-client:proof-request-broker'),
77
+ ) {
78
+ this.timeoutPromise = new RunningPromise(this.timeoutCheck, timeoutIntervalSec * 1000);
79
+ this.jobTimeoutSec = jobTimeoutSec;
80
+ this.maxRetries = maxRetries;
81
+ }
82
+
83
+ // eslint-disable-next-line require-await
84
+ public async start(): Promise<void> {
85
+ for (const [item, result] of this.database.allProvingJobs()) {
86
+ this.logger.info(`Restoring proving job id=${item.id} settled=${!!result}`);
87
+
88
+ this.jobsCache.set(item.id, item);
89
+ if (result) {
90
+ this.resultsCache.set(item.id, result);
91
+ } else {
92
+ this.logger.debug(`Re-enqueuing proving job id=${item.id}`);
93
+ this.enqueueJobInternal(item);
94
+ }
95
+ }
96
+
97
+ this.timeoutPromise.start();
98
+ }
99
+
100
+ public stop(): Promise<void> {
101
+ return this.timeoutPromise.stop();
102
+ }
103
+
104
+ public async enqueueProvingJob(job: V2ProvingJob): Promise<void> {
105
+ if (this.jobsCache.has(job.id)) {
106
+ const existing = this.jobsCache.get(job.id);
107
+ assert.deepStrictEqual(job, existing, 'Duplicate proving job ID');
108
+ return;
109
+ }
110
+
111
+ await this.database.addProvingJob(job);
112
+ this.jobsCache.set(job.id, job);
113
+ this.enqueueJobInternal(job);
114
+ }
115
+
116
+ public async removeAndCancelProvingJob(id: V2ProvingJobId): Promise<void> {
117
+ this.logger.info(`Cancelling job id=${id}`);
118
+ await this.database.deleteProvingJobAndResult(id);
119
+
120
+ this.jobsCache.delete(id);
121
+ this.resultsCache.delete(id);
122
+ this.inProgress.delete(id);
123
+ this.retries.delete(id);
124
+ }
125
+
126
+ // eslint-disable-next-line require-await
127
+ public async getProvingJobStatus(id: V2ProvingJobId): Promise<V2ProvingJobStatus> {
128
+ const result = this.resultsCache.get(id);
129
+ if (!result) {
130
+ // no result yet, check if we know the item
131
+ const item = this.jobsCache.get(id);
132
+
133
+ if (!item) {
134
+ this.logger.warn(`Proving job id=${id} not found`);
135
+ return Promise.resolve({ status: 'not-found' });
136
+ }
137
+
138
+ 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
+ }
144
+ }
145
+
146
+ // 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');
153
+ allowedProofs.sort(proofTypeComparator);
154
+
155
+ for (const proofType of allowedProofs) {
156
+ const queue = this.queues[proofType];
157
+ let job: V2ProvingJob | undefined;
158
+ // exhaust the queue and make sure we're not sending a job that's already in progress
159
+ // or has already been completed
160
+ // 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
162
+ while ((job = queue.getImmediate())) {
163
+ if (!this.inProgress.has(job.id) && !this.resultsCache.has(job.id)) {
164
+ const time = this.timeSource();
165
+ this.inProgress.set(job.id, {
166
+ id: job.id,
167
+ startedAt: time,
168
+ lastUpdatedAt: time,
169
+ });
170
+
171
+ return { job, time };
172
+ }
173
+ }
174
+ }
175
+
176
+ return undefined;
177
+ }
178
+
179
+ async reportProvingJobError(id: V2ProvingJobId, err: Error, retry = false): Promise<void> {
180
+ const info = this.inProgress.get(id);
181
+ const item = this.jobsCache.get(id);
182
+ const retries = this.retries.get(id) ?? 0;
183
+
184
+ if (!item) {
185
+ this.logger.warn(`Proving job id=${id} not found`);
186
+ return;
187
+ }
188
+
189
+ if (!info) {
190
+ this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[item.type]} not in the in-progress set`);
191
+ } else {
192
+ this.inProgress.delete(id);
193
+ }
194
+
195
+ if (retry && retries + 1 < this.maxRetries) {
196
+ this.logger.info(`Retrying proving job id=${id} type=${ProvingRequestType[item.type]} retry=${retries + 1}`);
197
+ this.retries.set(id, retries + 1);
198
+ this.enqueueJobInternal(item);
199
+ return;
200
+ }
201
+
202
+ this.logger.debug(
203
+ `Marking proving job id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1} as failed`,
204
+ );
205
+ await this.database.setProvingJobError(id, err);
206
+ this.resultsCache.set(id, { error: String(err) });
207
+ }
208
+
209
+ reportProvingJobProgress<F extends ProvingRequestType[]>(
210
+ id: V2ProvingJobId,
211
+ startedAt: number,
212
+ filter?: ProvingJobFilter<F>,
213
+ ): Promise<{ job: V2ProvingJob; time: number } | undefined> {
214
+ const job = this.jobsCache.get(id);
215
+ if (!job) {
216
+ this.logger.warn(`Proving job id=${id} does not exist`);
217
+ return filter ? this.getProvingJob(filter) : Promise.resolve(undefined);
218
+ }
219
+
220
+ const metadata = this.inProgress.get(id);
221
+ const now = this.timeSource();
222
+ if (!metadata) {
223
+ this.logger.warn(
224
+ `Proving job id=${id} type=${ProvingRequestType[job.type]} not found in the in-progress cache, adding it`,
225
+ );
226
+ // the queue will still contain the item at this point!
227
+ // we need to be careful when popping off the queue to make sure we're not sending
228
+ // a job that's already in progress
229
+ this.inProgress.set(id, {
230
+ id,
231
+ startedAt,
232
+ lastUpdatedAt: this.timeSource(),
233
+ });
234
+ return Promise.resolve(undefined);
235
+ } else if (startedAt <= metadata.startedAt) {
236
+ if (startedAt < metadata.startedAt) {
237
+ this.logger.debug(
238
+ `Proving job id=${id} type=${ProvingRequestType[job.type]} startedAt=${startedAt} older agent has taken job`,
239
+ );
240
+ } else {
241
+ this.logger.debug(`Proving job id=${id} type=${ProvingRequestType[job.type]} heartbeat`);
242
+ }
243
+ metadata.startedAt = startedAt;
244
+ metadata.lastUpdatedAt = now;
245
+ return Promise.resolve(undefined);
246
+ } else if (filter) {
247
+ this.logger.warn(
248
+ `Proving job id=${id} type=${
249
+ ProvingRequestType[job.type]
250
+ } already being worked on by another agent. Sending new one`,
251
+ );
252
+ return this.getProvingJob(filter);
253
+ } else {
254
+ return Promise.resolve(undefined);
255
+ }
256
+ }
257
+
258
+ async reportProvingJobSuccess(id: V2ProvingJobId, value: V2ProofOutput): Promise<void> {
259
+ const info = this.inProgress.get(id);
260
+ const item = this.jobsCache.get(id);
261
+ const retries = this.retries.get(id) ?? 0;
262
+ if (!item) {
263
+ this.logger.warn(`Proving job id=${id} not found`);
264
+ return;
265
+ }
266
+
267
+ if (!info) {
268
+ this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[item.type]} not in the in-progress set`);
269
+ } else {
270
+ this.inProgress.delete(id);
271
+ }
272
+
273
+ this.logger.debug(
274
+ `Proving job complete id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1}`,
275
+ );
276
+ await this.database.setProvingJobResult(id, value);
277
+ this.resultsCache.set(id, { value });
278
+ }
279
+
280
+ private timeoutCheck = () => {
281
+ const inProgressEntries = Array.from(this.inProgress.entries());
282
+ for (const [id, metadata] of inProgressEntries) {
283
+ const item = this.jobsCache.get(id);
284
+ if (!item) {
285
+ this.logger.warn(`Proving job id=${id} not found. Removing it from the queue.`);
286
+ this.inProgress.delete(id);
287
+ continue;
288
+ }
289
+
290
+ const secondsSinceLastUpdate = this.timeSource() - metadata.lastUpdatedAt;
291
+ if (secondsSinceLastUpdate >= this.jobTimeoutSec) {
292
+ this.logger.warn(`Proving job id=${id} timed out. Adding it back to the queue.`);
293
+ this.inProgress.delete(id);
294
+ this.enqueueJobInternal(item);
295
+ }
296
+ }
297
+ };
298
+
299
+ private enqueueJobInternal(job: V2ProvingJob): void {
300
+ this.queues[job.type].put(job);
301
+ this.logger.debug(`Enqueued new proving job id=${job.id}`);
302
+ }
303
+ }
304
+
305
+ type ProvingQueues = {
306
+ [K in ProvingRequestType]: PriorityMemoryQueue<V2ProvingJob>;
307
+ };
308
+
309
+ /**
310
+ * Compares two proving jobs and selects which one's more important
311
+ * @param a - A proving job
312
+ * @param b - Another proving job
313
+ * @returns A number indicating the relative priority of the two proving jobs
314
+ */
315
+ function provingJobComparator(a: V2ProvingJob, b: V2ProvingJob): -1 | 0 | 1 {
316
+ if (a.blockNumber < b.blockNumber) {
317
+ return -1;
318
+ } else if (a.blockNumber > b.blockNumber) {
319
+ return 1;
320
+ } else {
321
+ return 0;
322
+ }
323
+ }
324
+
325
+ /**
326
+ * Compares two proofs and selects which one's more important.
327
+ * If some proofs does not exist in the priority array then it's considered the least important.
328
+ *
329
+ * @param a - A proof type
330
+ * @param b - Another proof type
331
+ * @returns A number indicating the relative priority of the two proof types
332
+ */
333
+ function proofTypeComparator(a: ProvingRequestType, b: ProvingRequestType): -1 | 0 | 1 {
334
+ const indexOfA = PROOF_TYPES_IN_PRIORITY_ORDER.indexOf(a);
335
+ const indexOfB = PROOF_TYPES_IN_PRIORITY_ORDER.indexOf(b);
336
+ if (indexOfA === indexOfB) {
337
+ return 0;
338
+ } else if (indexOfA === -1) {
339
+ // a is some new proof that didn't get added to the array
340
+ // b is more important because we know about it
341
+ return 1;
342
+ } else if (indexOfB === -1) {
343
+ // the opposite of the previous if branch
344
+ return -1;
345
+ } else if (indexOfA < indexOfB) {
346
+ return -1;
347
+ } else {
348
+ return 1;
349
+ }
350
+ }
351
+
352
+ /**
353
+ * Relative priority of each proof type. Proofs higher up on the list are more important and should be prioritized
354
+ * over proofs lower on the list.
355
+ *
356
+ * The aim is that this will speed up block proving as the closer we get to a block's root proof the more likely it
357
+ * is to get picked up by agents
358
+ */
359
+ const PROOF_TYPES_IN_PRIORITY_ORDER: ProvingRequestType[] = [
360
+ ProvingRequestType.BLOCK_ROOT_ROLLUP,
361
+ ProvingRequestType.BLOCK_MERGE_ROLLUP,
362
+ ProvingRequestType.ROOT_ROLLUP,
363
+ ProvingRequestType.MERGE_ROLLUP,
364
+ ProvingRequestType.PUBLIC_BASE_ROLLUP,
365
+ ProvingRequestType.PRIVATE_BASE_ROLLUP,
366
+ ProvingRequestType.PUBLIC_VM,
367
+ ProvingRequestType.TUBE_PROOF,
368
+ ProvingRequestType.ROOT_PARITY,
369
+ ProvingRequestType.BASE_PARITY,
370
+ ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP,
371
+ ProvingRequestType.PRIVATE_KERNEL_EMPTY,
372
+ ];
@@ -0,0 +1,74 @@
1
+ import {
2
+ type ProvingRequestType,
3
+ type V2ProofOutput,
4
+ type V2ProvingJob,
5
+ type V2ProvingJobId,
6
+ type V2ProvingJobStatus,
7
+ } from '@aztec/circuit-types';
8
+
9
+ /**
10
+ * An interface for the proving orchestrator. The producer uses this to enqueue jobs for agents
11
+ */
12
+ export interface ProvingJobProducer {
13
+ /**
14
+ * Enqueues a proving job
15
+ * @param job - The job to enqueue
16
+ */
17
+ enqueueProvingJob(job: V2ProvingJob): Promise<void>;
18
+
19
+ /**
20
+ * Cancels a proving job and clears all of its
21
+ * @param id - The ID of the job to cancel
22
+ */
23
+ removeAndCancelProvingJob(id: V2ProvingJobId): Promise<void>;
24
+
25
+ /**
26
+ * Returns the current status fof the proving job
27
+ * @param id - The ID of the job to get the status of
28
+ */
29
+ getProvingJobStatus(id: V2ProvingJobId): Promise<V2ProvingJobStatus>;
30
+ }
31
+
32
+ export interface ProvingJobFilter<T extends ProvingRequestType[]> {
33
+ allowList?: T;
34
+ }
35
+
36
+ /**
37
+ * An interface for proving agents to request jobs and report results
38
+ */
39
+ export interface ProvingJobConsumer {
40
+ /**
41
+ * Gets a proving job to work on
42
+ * @param filter - Optional filter for the type of job to get
43
+ */
44
+ getProvingJob<T extends ProvingRequestType[]>(
45
+ filter?: ProvingJobFilter<T>,
46
+ ): Promise<{ job: V2ProvingJob; time: number } | undefined>;
47
+
48
+ /**
49
+ * Marks a proving job as successful
50
+ * @param id - The ID of the job to report success for
51
+ * @param result - The result of the job
52
+ */
53
+ reportProvingJobSuccess(id: V2ProvingJobId, result: V2ProofOutput): Promise<void>;
54
+
55
+ /**
56
+ * Marks a proving job as errored
57
+ * @param id - The ID of the job to report an error for
58
+ * @param err - The error that occurred while processing the job
59
+ * @param retry - Whether to retry the job
60
+ */
61
+ reportProvingJobError(id: V2ProvingJobId, err: Error, retry?: boolean): Promise<void>;
62
+
63
+ /**
64
+ * Sends a heartbeat to the broker to indicate that the agent is still working on the given proving job
65
+ * @param id - The ID of the job to report progress for
66
+ * @param startedAt - The unix epoch when the job was started
67
+ * @param filter - Optional filter for the type of job to get
68
+ */
69
+ reportProvingJobProgress<F extends ProvingRequestType[]>(
70
+ id: V2ProvingJobId,
71
+ startedAt: number,
72
+ filter?: ProvingJobFilter<F>,
73
+ ): Promise<{ job: V2ProvingJob; time: number } | undefined>;
74
+ }
@@ -0,0 +1,43 @@
1
+ import type { V2ProofOutput, V2ProvingJob, V2ProvingJobId, V2ProvingJobResult } from '@aztec/circuit-types';
2
+
3
+ import { type ProvingJobDatabase } from '../proving_job_database.js';
4
+
5
+ export class InMemoryDatabase implements ProvingJobDatabase {
6
+ private jobs = new Map<V2ProvingJobId, V2ProvingJob>();
7
+ private results = new Map<V2ProvingJobId, V2ProvingJobResult>();
8
+
9
+ getProvingJob(id: V2ProvingJobId): V2ProvingJob | undefined {
10
+ return this.jobs.get(id);
11
+ }
12
+
13
+ getProvingJobResult(id: V2ProvingJobId): V2ProvingJobResult | undefined {
14
+ return this.results.get(id);
15
+ }
16
+
17
+ addProvingJob(request: V2ProvingJob): Promise<void> {
18
+ this.jobs.set(request.id, request);
19
+ return Promise.resolve();
20
+ }
21
+
22
+ setProvingJobResult(id: V2ProvingJobId, value: V2ProofOutput): Promise<void> {
23
+ this.results.set(id, { value });
24
+ return Promise.resolve();
25
+ }
26
+
27
+ setProvingJobError(id: V2ProvingJobId, error: Error): Promise<void> {
28
+ this.results.set(id, { error: String(error) });
29
+ return Promise.resolve();
30
+ }
31
+
32
+ deleteProvingJobAndResult(id: V2ProvingJobId): Promise<void> {
33
+ this.jobs.delete(id);
34
+ this.results.delete(id);
35
+ return Promise.resolve();
36
+ }
37
+
38
+ *allProvingJobs(): Iterable<[V2ProvingJob, V2ProvingJobResult | 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,44 @@
1
+ import { type V2ProofOutput, V2ProvingJob, type V2ProvingJobId, V2ProvingJobResult } from '@aztec/circuit-types';
2
+ import { type AztecKVStore, type AztecMap } from '@aztec/kv-store';
3
+
4
+ import { type ProvingJobDatabase } from '../proving_job_database.js';
5
+
6
+ export class PersistedProvingJobDatabase implements ProvingJobDatabase {
7
+ private jobs: AztecMap<V2ProvingJobId, string>;
8
+ private jobResults: AztecMap<V2ProvingJobId, string>;
9
+
10
+ constructor(private store: AztecKVStore) {
11
+ this.jobs = store.openMap('proving_jobs');
12
+ this.jobResults = store.openMap('proving_job_results');
13
+ }
14
+
15
+ async addProvingJob(job: V2ProvingJob): Promise<void> {
16
+ await this.jobs.set(job.id, JSON.stringify(job));
17
+ }
18
+
19
+ *allProvingJobs(): Iterable<[V2ProvingJob, V2ProvingJobResult | undefined]> {
20
+ for (const jobStr of this.jobs.values()) {
21
+ const job = V2ProvingJob.parse(JSON.parse(jobStr));
22
+ const resultStr = this.jobResults.get(job.id);
23
+ const result = resultStr ? V2ProvingJobResult.parse(JSON.parse(resultStr)) : undefined;
24
+ yield [job, result];
25
+ }
26
+ }
27
+
28
+ deleteProvingJobAndResult(id: V2ProvingJobId): Promise<void> {
29
+ return this.store.transaction(() => {
30
+ void this.jobs.delete(id);
31
+ void this.jobResults.delete(id);
32
+ });
33
+ }
34
+
35
+ async setProvingJobError(id: V2ProvingJobId, err: Error): Promise<void> {
36
+ const res: V2ProvingJobResult = { error: err.message };
37
+ await this.jobResults.set(id, JSON.stringify(res));
38
+ }
39
+
40
+ async setProvingJobResult(id: V2ProvingJobId, value: V2ProofOutput): Promise<void> {
41
+ const res: V2ProvingJobResult = { value };
42
+ await this.jobResults.set(id, JSON.stringify(res));
43
+ }
44
+ }
@@ -0,0 +1,44 @@
1
+ import {
2
+ type V2ProofOutput,
3
+ type V2ProvingJob,
4
+ type V2ProvingJobId,
5
+ type V2ProvingJobResult,
6
+ } from '@aztec/circuit-types';
7
+
8
+ /**
9
+ * A database for storing proof requests and their results
10
+ */
11
+ export interface ProvingJobDatabase {
12
+ /**
13
+ * Saves a proof request so it can be retrieved later
14
+ * @param request - The proof request to save
15
+ */
16
+ addProvingJob(request: V2ProvingJob): Promise<void>;
17
+
18
+ /**
19
+ * Removes a proof request from the backend
20
+ * @param id - The ID of the proof request to remove
21
+ */
22
+ deleteProvingJobAndResult(id: V2ProvingJobId): Promise<void>;
23
+
24
+ /**
25
+ * Returns an iterator over all saved proving jobs
26
+ */
27
+ allProvingJobs(): Iterable<[V2ProvingJob, V2ProvingJobResult | undefined]>;
28
+
29
+ /**
30
+ * Saves the result of a proof request
31
+ * @param id - The ID of the proof request to save the result for
32
+ * @param ProvingRequestType - The type of proof that was requested
33
+ * @param value - The result of the proof request
34
+ */
35
+ setProvingJobResult(id: V2ProvingJobId, value: V2ProofOutput): Promise<void>;
36
+
37
+ /**
38
+ * Saves an error that occurred while processing a proof request
39
+ * @param id - The ID of the proof request to save the error for
40
+ * @param ProvingRequestType - The type of proof that was requested
41
+ * @param err - The error that occurred while processing the proof request
42
+ */
43
+ setProvingJobError(id: V2ProvingJobId, err: Error): Promise<void>;
44
+ }
@@ -11,8 +11,8 @@ import {
11
11
  type BaseOrMergeRollupPublicInputs,
12
12
  type BlockRootOrBlockMergePublicInputs,
13
13
  type KernelCircuitPublicInputs,
14
+ NESTED_RECURSIVE_PROOF_LENGTH,
14
15
  RECURSIVE_PROOF_LENGTH,
15
- type RecursiveProof,
16
16
  type RootRollupPublicInputs,
17
17
  TUBE_PROOF_LENGTH,
18
18
  VerificationKeyData,
@@ -23,7 +23,7 @@ import {
23
23
  makeBaseOrMergeRollupPublicInputs,
24
24
  makeBlockRootOrBlockMergeRollupPublicInputs,
25
25
  makeKernelCircuitPublicInputs,
26
- makeRootParityInput,
26
+ makeParityPublicInputs,
27
27
  makeRootRollupPublicInputs,
28
28
  } from '@aztec/circuits.js/testing';
29
29
 
@@ -40,11 +40,23 @@ export class MockProver implements ServerCircuitProver {
40
40
  }
41
41
 
42
42
  getBaseParityProof() {
43
- return Promise.resolve(makeRootParityInput(RECURSIVE_PROOF_LENGTH));
43
+ return Promise.resolve(
44
+ makePublicInputsAndRecursiveProof(
45
+ makeParityPublicInputs(),
46
+ makeRecursiveProof(RECURSIVE_PROOF_LENGTH),
47
+ VerificationKeyData.makeFakeHonk(),
48
+ ),
49
+ );
44
50
  }
45
51
 
46
52
  getRootParityProof() {
47
- return Promise.resolve(makeRootParityInput(RECURSIVE_PROOF_LENGTH));
53
+ return Promise.resolve(
54
+ makePublicInputsAndRecursiveProof(
55
+ makeParityPublicInputs(),
56
+ makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH),
57
+ VerificationKeyData.makeFakeHonk(),
58
+ ),
59
+ );
48
60
  }
49
61
 
50
62
  getPrivateBaseRollupProof(): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>> {
@@ -117,16 +129,6 @@ export class MockProver implements ServerCircuitProver {
117
129
  );
118
130
  }
119
131
 
120
- getEmptyTubeProof(): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>> {
121
- return Promise.resolve(
122
- makePublicInputsAndRecursiveProof(
123
- makeKernelCircuitPublicInputs(),
124
- makeRecursiveProof(RECURSIVE_PROOF_LENGTH),
125
- VerificationKeyData.makeFakeHonk(),
126
- ),
127
- );
128
- }
129
-
130
132
  getRootRollupProof(): Promise<PublicInputsAndRecursiveProof<RootRollupPublicInputs>> {
131
133
  return Promise.resolve(
132
134
  makePublicInputsAndRecursiveProof(
@@ -137,7 +139,7 @@ export class MockProver implements ServerCircuitProver {
137
139
  );
138
140
  }
139
141
 
140
- getTubeProof(): Promise<ProofAndVerificationKey<RecursiveProof<typeof TUBE_PROOF_LENGTH>>> {
142
+ getTubeProof(): Promise<ProofAndVerificationKey<typeof TUBE_PROOF_LENGTH>> {
141
143
  return Promise.resolve(
142
144
  makeProofAndVerificationKey(makeRecursiveProof(TUBE_PROOF_LENGTH), VerificationKeyData.makeFake()),
143
145
  );
@@ -50,7 +50,7 @@ export class TxProver implements EpochProverManager {
50
50
  }
51
51
 
52
52
  if (this.config.proverAgentConcurrency !== newConfig.proverAgentConcurrency) {
53
- this.agent?.setMaxConcurrency(newConfig.proverAgentConcurrency);
53
+ await this.agent?.setMaxConcurrency(newConfig.proverAgentConcurrency);
54
54
  }
55
55
 
56
56
  if (!this.config.realProofs && newConfig.realProofs) {