@aztec/prover-client 0.47.0 → 0.48.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 +2 -0
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +28 -30
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +11 -7
- package/dest/mocks/test_context.d.ts +3 -3
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +6 -24
- package/dest/orchestrator/block-building-helpers.d.ts +3 -3
- package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
- package/dest/orchestrator/block-building-helpers.js +6 -5
- package/dest/orchestrator/orchestrator.d.ts +11 -6
- package/dest/orchestrator/orchestrator.d.ts.map +1 -1
- package/dest/orchestrator/orchestrator.js +115 -89
- package/dest/orchestrator/orchestrator_metrics.d.ts +8 -0
- package/dest/orchestrator/orchestrator_metrics.d.ts.map +1 -0
- package/dest/orchestrator/orchestrator_metrics.js +19 -0
- package/dest/orchestrator/proving-state.d.ts +3 -1
- package/dest/orchestrator/proving-state.d.ts.map +1 -1
- package/dest/orchestrator/proving-state.js +5 -1
- package/dest/orchestrator/tx-proving-state.d.ts +3 -2
- package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/tx-proving-state.js +26 -8
- package/dest/prover-agent/memory-proving-queue.d.ts +15 -13
- package/dest/prover-agent/memory-proving-queue.d.ts.map +1 -1
- package/dest/prover-agent/memory-proving-queue.js +37 -55
- package/dest/prover-agent/prover-agent.d.ts.map +1 -1
- package/dest/prover-agent/prover-agent.js +30 -8
- package/dest/prover-agent/queue_metrics.d.ts +10 -0
- package/dest/prover-agent/queue_metrics.d.ts.map +1 -0
- package/dest/prover-agent/queue_metrics.js +23 -0
- package/dest/prover-agent/rpc.d.ts.map +1 -1
- package/dest/prover-agent/rpc.js +4 -2
- package/dest/tx-prover/factory.d.ts +1 -3
- package/dest/tx-prover/factory.d.ts.map +1 -1
- package/dest/tx-prover/factory.js +3 -3
- package/dest/tx-prover/tx-prover.d.ts +8 -33
- package/dest/tx-prover/tx-prover.d.ts.map +1 -1
- package/dest/tx-prover/tx-prover.js +18 -46
- package/package.json +10 -10
- package/src/config.ts +28 -47
- package/src/mocks/fixtures.ts +14 -4
- package/src/mocks/test_context.ts +7 -27
- package/src/orchestrator/block-building-helpers.ts +6 -5
- package/src/orchestrator/orchestrator.ts +197 -103
- package/src/orchestrator/orchestrator_metrics.ts +32 -0
- package/src/orchestrator/proving-state.ts +5 -0
- package/src/orchestrator/tx-proving-state.ts +33 -7
- package/src/prover-agent/memory-proving-queue.ts +54 -70
- package/src/prover-agent/prover-agent.ts +42 -7
- package/src/prover-agent/queue_metrics.ts +29 -0
- package/src/prover-agent/rpc.ts +3 -0
- package/src/tx-prover/factory.ts +2 -9
- package/src/tx-prover/tx-prover.ts +21 -64
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Histogram,
|
|
3
|
+
Metrics,
|
|
4
|
+
type TelemetryClient,
|
|
5
|
+
type Tracer,
|
|
6
|
+
ValueType,
|
|
7
|
+
millisecondBuckets,
|
|
8
|
+
} from '@aztec/telemetry-client';
|
|
9
|
+
|
|
10
|
+
export class ProvingOrchestratorMetrics {
|
|
11
|
+
public readonly tracer: Tracer;
|
|
12
|
+
|
|
13
|
+
private baseRollupInputsDuration: Histogram;
|
|
14
|
+
|
|
15
|
+
constructor(client: TelemetryClient, name = 'ProvingOrchestrator') {
|
|
16
|
+
this.tracer = client.getTracer(name);
|
|
17
|
+
const meter = client.getMeter(name);
|
|
18
|
+
|
|
19
|
+
this.baseRollupInputsDuration = meter.createHistogram(Metrics.PROVING_ORCHESTRATOR_BASE_ROLLUP_INPUTS_DURATION, {
|
|
20
|
+
unit: 'ms',
|
|
21
|
+
description: 'Duration to build base rollup inputs',
|
|
22
|
+
valueType: ValueType.INT,
|
|
23
|
+
advice: {
|
|
24
|
+
explicitBucketBoundaries: millisecondBuckets(1), // 10ms -> ~327s
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
recordBaseRollupInputs(durationMs: number) {
|
|
30
|
+
this.baseRollupInputsDuration.record(Math.ceil(durationMs));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -143,6 +143,11 @@ export class ProvingState {
|
|
|
143
143
|
return this.txs;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
/** Returns the block number as an epoch number. Used for prioritizing proof requests. */
|
|
147
|
+
public get epochNumber(): number {
|
|
148
|
+
return this.globalVariables.blockNumber.toNumber();
|
|
149
|
+
}
|
|
150
|
+
|
|
146
151
|
/**
|
|
147
152
|
* Stores the inputs to a merge circuit and determines if the circuit is ready to be executed
|
|
148
153
|
* @param mergeInputs - The inputs to store
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
type BaseRollupInputs,
|
|
12
12
|
type NESTED_RECURSIVE_PROOF_LENGTH,
|
|
13
13
|
type Proof,
|
|
14
|
+
type RECURSIVE_PROOF_LENGTH,
|
|
14
15
|
type RecursiveProof,
|
|
15
16
|
type VerificationKeyData,
|
|
16
17
|
} from '@aztec/circuits.js';
|
|
@@ -48,23 +49,17 @@ export class TxProvingState {
|
|
|
48
49
|
public readonly processedTx: ProcessedTx,
|
|
49
50
|
public readonly baseRollupInputs: BaseRollupInputs,
|
|
50
51
|
public readonly treeSnapshots: Map<MerkleTreeId, AppendOnlyTreeSnapshot>,
|
|
51
|
-
privateKernelVk: VerificationKeyData,
|
|
52
52
|
) {
|
|
53
53
|
let previousProofType = PublicKernelType.NON_PUBLIC;
|
|
54
54
|
for (let i = 0; i < processedTx.publicProvingRequests.length; i++) {
|
|
55
55
|
const provingRequest = processedTx.publicProvingRequests[i];
|
|
56
56
|
const kernelRequest = provingRequest.type === AVM_REQUEST ? provingRequest.kernelRequest : provingRequest;
|
|
57
|
-
// the first circuit has a valid previous proof, it came from private
|
|
58
|
-
if (i === 0) {
|
|
59
|
-
kernelRequest.inputs.previousKernel.vk = privateKernelVk;
|
|
60
|
-
kernelRequest.inputs.previousKernel.clientIvcProof = processedTx.clientIvcProof;
|
|
61
|
-
}
|
|
62
57
|
const vmRequest = provingRequest.type === AVM_REQUEST ? provingRequest : undefined;
|
|
63
58
|
const publicFunction: PublicFunction = {
|
|
64
59
|
vmRequest,
|
|
65
60
|
vmProof: undefined,
|
|
66
61
|
previousProofType,
|
|
67
|
-
previousKernelProven:
|
|
62
|
+
previousKernelProven: false,
|
|
68
63
|
publicKernelRequest: kernelRequest,
|
|
69
64
|
};
|
|
70
65
|
this.publicFunctions.push(publicFunction);
|
|
@@ -105,6 +100,37 @@ export class TxProvingState {
|
|
|
105
100
|
return { code: TX_PROVING_CODE.READY, function: nextFunction };
|
|
106
101
|
}
|
|
107
102
|
|
|
103
|
+
// Updates the transaction's proving state after completion of a tube proof
|
|
104
|
+
// Returns an instruction as to the next stage of tx proving
|
|
105
|
+
public getNextPublicKernelFromTubeProof(
|
|
106
|
+
proof: RecursiveProof<typeof RECURSIVE_PROOF_LENGTH>,
|
|
107
|
+
verificationKey: VerificationKeyData,
|
|
108
|
+
): TxProvingInstruction {
|
|
109
|
+
const nextKernelIndex = 0;
|
|
110
|
+
if (nextKernelIndex >= this.publicFunctions.length) {
|
|
111
|
+
// The next kernel index is greater than our set of functions, we are done!
|
|
112
|
+
return { code: TX_PROVING_CODE.COMPLETED, function: undefined };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// There is more work to do, are we ready?
|
|
116
|
+
const nextFunction = this.publicFunctions[nextKernelIndex];
|
|
117
|
+
|
|
118
|
+
// pass both the proof and verification key forward to the next circuit
|
|
119
|
+
nextFunction.publicKernelRequest.inputs.previousKernel.proof = proof;
|
|
120
|
+
nextFunction.publicKernelRequest.inputs.previousKernel.vk = verificationKey;
|
|
121
|
+
|
|
122
|
+
// We need to update this so the state machine knows this proof is ready
|
|
123
|
+
nextFunction.previousKernelProven = true;
|
|
124
|
+
nextFunction.previousProofType = PublicKernelType.NON_PUBLIC;
|
|
125
|
+
if (nextFunction.vmProof === undefined) {
|
|
126
|
+
// The VM proof for the next function is not ready
|
|
127
|
+
return { code: TX_PROVING_CODE.NOT_READY, function: undefined };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// The VM proof is ready, we can continue
|
|
131
|
+
return { code: TX_PROVING_CODE.READY, function: nextFunction };
|
|
132
|
+
}
|
|
133
|
+
|
|
108
134
|
// Updates the transaction's proving state after completion of a VM proof
|
|
109
135
|
// Returns an instruction as to the next stage of tx proving
|
|
110
136
|
public getNextPublicKernelFromVMProof(provenIndex: number, proof: Proof): TxProvingInstruction {
|
|
@@ -31,35 +31,43 @@ import type {
|
|
|
31
31
|
} from '@aztec/circuits.js';
|
|
32
32
|
import { randomBytes } from '@aztec/foundation/crypto';
|
|
33
33
|
import { AbortError, TimeoutError } from '@aztec/foundation/error';
|
|
34
|
-
import { MemoryFifo } from '@aztec/foundation/fifo';
|
|
35
34
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
36
35
|
import { type PromiseWithResolvers, RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise';
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
import { PriorityMemoryQueue } from '@aztec/foundation/queue';
|
|
37
|
+
import { serializeToBuffer } from '@aztec/foundation/serialize';
|
|
38
|
+
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
39
|
+
|
|
40
|
+
import { ProvingQueueMetrics } from './queue_metrics.js';
|
|
41
|
+
|
|
42
|
+
type ProvingJobWithResolvers<T extends ProvingRequest = ProvingRequest> = ProvingJob<T> &
|
|
43
|
+
PromiseWithResolvers<ProvingRequestResult<T['type']>> & {
|
|
44
|
+
signal?: AbortSignal;
|
|
45
|
+
epochNumber?: number;
|
|
46
|
+
attempts: number;
|
|
47
|
+
heartbeat: number;
|
|
48
|
+
};
|
|
45
49
|
|
|
46
50
|
const MAX_RETRIES = 3;
|
|
47
51
|
|
|
48
52
|
const defaultIdGenerator = () => randomBytes(4).toString('hex');
|
|
49
53
|
const defaultTimeSource = () => Date.now();
|
|
50
|
-
|
|
51
54
|
/**
|
|
52
55
|
* A helper class that sits in between services that need proofs created and agents that can create them.
|
|
53
|
-
* The queue accumulates jobs and provides them to agents
|
|
56
|
+
* The queue accumulates jobs and provides them to agents prioritized by block number.
|
|
54
57
|
*/
|
|
55
58
|
export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource {
|
|
56
59
|
private log = createDebugLogger('aztec:prover-client:prover-pool:queue');
|
|
57
|
-
private queue = new
|
|
60
|
+
private queue = new PriorityMemoryQueue<ProvingJobWithResolvers>(
|
|
61
|
+
(a, b) => (a.epochNumber ?? 0) - (b.epochNumber ?? 0),
|
|
62
|
+
);
|
|
58
63
|
private jobsInProgress = new Map<string, ProvingJobWithResolvers>();
|
|
59
64
|
|
|
60
65
|
private runningPromise: RunningPromise;
|
|
61
66
|
|
|
67
|
+
private metrics: ProvingQueueMetrics;
|
|
68
|
+
|
|
62
69
|
constructor(
|
|
70
|
+
client: TelemetryClient,
|
|
63
71
|
/** Timeout the job if an agent doesn't report back in this time */
|
|
64
72
|
private jobTimeoutMs = 60 * 1000,
|
|
65
73
|
/** How often to check for timed out jobs */
|
|
@@ -67,6 +75,7 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource
|
|
|
67
75
|
private generateId = defaultIdGenerator,
|
|
68
76
|
private timeSource = defaultTimeSource,
|
|
69
77
|
) {
|
|
78
|
+
this.metrics = new ProvingQueueMetrics(client, 'MemoryProvingQueue');
|
|
70
79
|
this.runningPromise = new RunningPromise(this.poll, pollingIntervalMs);
|
|
71
80
|
}
|
|
72
81
|
|
|
@@ -156,7 +165,8 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource
|
|
|
156
165
|
return Promise.resolve();
|
|
157
166
|
}
|
|
158
167
|
|
|
159
|
-
|
|
168
|
+
// every job should be retried with the exception of the public VM since its in development and can fail
|
|
169
|
+
if (job.attempts < MAX_RETRIES && job.request.type !== ProvingRequestType.PUBLIC_VM) {
|
|
160
170
|
job.attempts++;
|
|
161
171
|
this.log.warn(
|
|
162
172
|
`Job id=${job.id} type=${ProvingRequestType[job.request.type]} failed with error: ${err}. Retry ${
|
|
@@ -190,6 +200,7 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource
|
|
|
190
200
|
|
|
191
201
|
private poll = () => {
|
|
192
202
|
const now = this.timeSource();
|
|
203
|
+
this.metrics.recordQueueSize(this.queue.length());
|
|
193
204
|
|
|
194
205
|
for (const job of this.jobsInProgress.values()) {
|
|
195
206
|
if (job.signal?.aborted) {
|
|
@@ -210,6 +221,7 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource
|
|
|
210
221
|
private enqueue<T extends ProvingRequest>(
|
|
211
222
|
request: T,
|
|
212
223
|
signal?: AbortSignal,
|
|
224
|
+
epochNumber?: number,
|
|
213
225
|
): Promise<ProvingRequestResult<T['type']>> {
|
|
214
226
|
if (!this.runningPromise.isRunning()) {
|
|
215
227
|
return Promise.reject(new Error('Proving queue is not running.'));
|
|
@@ -225,6 +237,7 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource
|
|
|
225
237
|
reject,
|
|
226
238
|
attempts: 1,
|
|
227
239
|
heartbeat: 0,
|
|
240
|
+
epochNumber,
|
|
228
241
|
};
|
|
229
242
|
|
|
230
243
|
if (signal) {
|
|
@@ -239,28 +252,34 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource
|
|
|
239
252
|
throw new Error();
|
|
240
253
|
}
|
|
241
254
|
|
|
255
|
+
const byteSize = serializeToBuffer(item.request.inputs).length;
|
|
256
|
+
this.metrics.recordNewJob(item.request.type, byteSize);
|
|
257
|
+
|
|
242
258
|
return promise;
|
|
243
259
|
}
|
|
244
260
|
|
|
245
261
|
getEmptyPrivateKernelProof(
|
|
246
262
|
inputs: PrivateKernelEmptyInputData,
|
|
247
263
|
signal?: AbortSignal,
|
|
264
|
+
epochNumber?: number,
|
|
248
265
|
): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>> {
|
|
249
|
-
return this.enqueue({ type: ProvingRequestType.PRIVATE_KERNEL_EMPTY, inputs }, signal);
|
|
266
|
+
return this.enqueue({ type: ProvingRequestType.PRIVATE_KERNEL_EMPTY, inputs }, signal, epochNumber);
|
|
250
267
|
}
|
|
251
268
|
|
|
252
269
|
getTubeProof(
|
|
253
270
|
inputs: TubeInputs,
|
|
254
|
-
signal?: AbortSignal
|
|
271
|
+
signal?: AbortSignal,
|
|
272
|
+
epochNumber?: number,
|
|
255
273
|
): Promise<{ tubeVK: VerificationKeyData; tubeProof: RecursiveProof<typeof RECURSIVE_PROOF_LENGTH> }> {
|
|
256
|
-
return this.enqueue({ type: ProvingRequestType.TUBE_PROOF, inputs }, signal);
|
|
274
|
+
return this.enqueue({ type: ProvingRequestType.TUBE_PROOF, inputs }, signal, epochNumber);
|
|
257
275
|
}
|
|
258
276
|
|
|
259
277
|
getEmptyTubeProof(
|
|
260
278
|
inputs: PrivateKernelEmptyInputData,
|
|
261
279
|
signal?: AbortSignal,
|
|
280
|
+
epochNumber?: number,
|
|
262
281
|
): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>> {
|
|
263
|
-
return this.enqueue({ type: ProvingRequestType.PRIVATE_KERNEL_EMPTY, inputs }, signal);
|
|
282
|
+
return this.enqueue({ type: ProvingRequestType.PRIVATE_KERNEL_EMPTY, inputs }, signal, epochNumber);
|
|
264
283
|
}
|
|
265
284
|
|
|
266
285
|
/**
|
|
@@ -270,14 +289,9 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource
|
|
|
270
289
|
getBaseParityProof(
|
|
271
290
|
inputs: BaseParityInputs,
|
|
272
291
|
signal?: AbortSignal,
|
|
292
|
+
epochNumber?: number,
|
|
273
293
|
): Promise<RootParityInput<typeof RECURSIVE_PROOF_LENGTH>> {
|
|
274
|
-
return this.enqueue(
|
|
275
|
-
{
|
|
276
|
-
type: ProvingRequestType.BASE_PARITY,
|
|
277
|
-
inputs,
|
|
278
|
-
},
|
|
279
|
-
signal,
|
|
280
|
-
);
|
|
294
|
+
return this.enqueue({ type: ProvingRequestType.BASE_PARITY, inputs }, signal, epochNumber);
|
|
281
295
|
}
|
|
282
296
|
|
|
283
297
|
/**
|
|
@@ -287,14 +301,9 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource
|
|
|
287
301
|
getRootParityProof(
|
|
288
302
|
inputs: RootParityInputs,
|
|
289
303
|
signal?: AbortSignal,
|
|
304
|
+
epochNumber?: number,
|
|
290
305
|
): Promise<RootParityInput<typeof NESTED_RECURSIVE_PROOF_LENGTH>> {
|
|
291
|
-
return this.enqueue(
|
|
292
|
-
{
|
|
293
|
-
type: ProvingRequestType.ROOT_PARITY,
|
|
294
|
-
inputs,
|
|
295
|
-
},
|
|
296
|
-
signal,
|
|
297
|
-
);
|
|
306
|
+
return this.enqueue({ type: ProvingRequestType.ROOT_PARITY, inputs }, signal, epochNumber);
|
|
298
307
|
}
|
|
299
308
|
|
|
300
309
|
/**
|
|
@@ -304,14 +313,9 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource
|
|
|
304
313
|
getBaseRollupProof(
|
|
305
314
|
baseRollupInput: BaseRollupInputs,
|
|
306
315
|
signal?: AbortSignal,
|
|
316
|
+
epochNumber?: number,
|
|
307
317
|
): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>> {
|
|
308
|
-
return this.enqueue(
|
|
309
|
-
{
|
|
310
|
-
type: ProvingRequestType.BASE_ROLLUP,
|
|
311
|
-
inputs: baseRollupInput,
|
|
312
|
-
},
|
|
313
|
-
signal,
|
|
314
|
-
);
|
|
318
|
+
return this.enqueue({ type: ProvingRequestType.BASE_ROLLUP, inputs: baseRollupInput }, signal, epochNumber);
|
|
315
319
|
}
|
|
316
320
|
|
|
317
321
|
/**
|
|
@@ -321,14 +325,9 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource
|
|
|
321
325
|
getMergeRollupProof(
|
|
322
326
|
input: MergeRollupInputs,
|
|
323
327
|
signal?: AbortSignal,
|
|
328
|
+
epochNumber?: number,
|
|
324
329
|
): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>> {
|
|
325
|
-
return this.enqueue(
|
|
326
|
-
{
|
|
327
|
-
type: ProvingRequestType.MERGE_ROLLUP,
|
|
328
|
-
inputs: input,
|
|
329
|
-
},
|
|
330
|
-
signal,
|
|
331
|
-
);
|
|
330
|
+
return this.enqueue({ type: ProvingRequestType.MERGE_ROLLUP, inputs: input }, signal, epochNumber);
|
|
332
331
|
}
|
|
333
332
|
|
|
334
333
|
/**
|
|
@@ -338,14 +337,9 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource
|
|
|
338
337
|
getRootRollupProof(
|
|
339
338
|
input: RootRollupInputs,
|
|
340
339
|
signal?: AbortSignal,
|
|
340
|
+
epochNumber?: number,
|
|
341
341
|
): Promise<PublicInputsAndRecursiveProof<RootRollupPublicInputs>> {
|
|
342
|
-
return this.enqueue(
|
|
343
|
-
{
|
|
344
|
-
type: ProvingRequestType.ROOT_ROLLUP,
|
|
345
|
-
inputs: input,
|
|
346
|
-
},
|
|
347
|
-
signal,
|
|
348
|
-
);
|
|
342
|
+
return this.enqueue({ type: ProvingRequestType.ROOT_ROLLUP, inputs: input }, signal, epochNumber);
|
|
349
343
|
}
|
|
350
344
|
|
|
351
345
|
/**
|
|
@@ -355,14 +349,12 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource
|
|
|
355
349
|
getPublicKernelProof(
|
|
356
350
|
kernelRequest: PublicKernelNonTailRequest,
|
|
357
351
|
signal?: AbortSignal,
|
|
352
|
+
epochNumber?: number,
|
|
358
353
|
): Promise<PublicInputsAndRecursiveProof<PublicKernelCircuitPublicInputs>> {
|
|
359
354
|
return this.enqueue(
|
|
360
|
-
{
|
|
361
|
-
type: ProvingRequestType.PUBLIC_KERNEL_NON_TAIL,
|
|
362
|
-
kernelType: kernelRequest.type,
|
|
363
|
-
inputs: kernelRequest.inputs,
|
|
364
|
-
},
|
|
355
|
+
{ type: ProvingRequestType.PUBLIC_KERNEL_NON_TAIL, kernelType: kernelRequest.type, inputs: kernelRequest.inputs },
|
|
365
356
|
signal,
|
|
357
|
+
epochNumber,
|
|
366
358
|
);
|
|
367
359
|
}
|
|
368
360
|
|
|
@@ -373,28 +365,20 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource
|
|
|
373
365
|
getPublicTailProof(
|
|
374
366
|
kernelRequest: PublicKernelTailRequest,
|
|
375
367
|
signal?: AbortSignal,
|
|
368
|
+
epochNumber?: number,
|
|
376
369
|
): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>> {
|
|
377
370
|
return this.enqueue(
|
|
378
|
-
{
|
|
379
|
-
type: ProvingRequestType.PUBLIC_KERNEL_TAIL,
|
|
380
|
-
kernelType: kernelRequest.type,
|
|
381
|
-
inputs: kernelRequest.inputs,
|
|
382
|
-
},
|
|
371
|
+
{ type: ProvingRequestType.PUBLIC_KERNEL_TAIL, kernelType: kernelRequest.type, inputs: kernelRequest.inputs },
|
|
383
372
|
signal,
|
|
373
|
+
epochNumber,
|
|
384
374
|
);
|
|
385
375
|
}
|
|
386
376
|
|
|
387
377
|
/**
|
|
388
378
|
* Creates an AVM proof.
|
|
389
379
|
*/
|
|
390
|
-
getAvmProof(inputs: AvmCircuitInputs, signal?: AbortSignal
|
|
391
|
-
return this.enqueue(
|
|
392
|
-
{
|
|
393
|
-
type: ProvingRequestType.PUBLIC_VM,
|
|
394
|
-
inputs,
|
|
395
|
-
},
|
|
396
|
-
signal,
|
|
397
|
-
);
|
|
380
|
+
getAvmProof(inputs: AvmCircuitInputs, signal?: AbortSignal, epochNumber?: number): Promise<ProofAndVerificationKey> {
|
|
381
|
+
return this.enqueue({ type: ProvingRequestType.PUBLIC_VM, inputs }, signal, epochNumber);
|
|
398
382
|
}
|
|
399
383
|
|
|
400
384
|
/**
|
|
@@ -12,11 +12,20 @@ import { elapsed } from '@aztec/foundation/timer';
|
|
|
12
12
|
|
|
13
13
|
import { ProvingError } from './proving-error.js';
|
|
14
14
|
|
|
15
|
+
const PRINT_THRESHOLD_NS = 6e10; // 60 seconds
|
|
16
|
+
|
|
15
17
|
/**
|
|
16
18
|
* A helper class that encapsulates a circuit prover and connects it to a job source.
|
|
17
19
|
*/
|
|
18
20
|
export class ProverAgent {
|
|
19
|
-
private inFlightPromises = new Map<
|
|
21
|
+
private inFlightPromises = new Map<
|
|
22
|
+
string,
|
|
23
|
+
{
|
|
24
|
+
id: string;
|
|
25
|
+
type: ProvingRequestType;
|
|
26
|
+
promise: Promise<any>;
|
|
27
|
+
}
|
|
28
|
+
>();
|
|
20
29
|
private runningPromise?: RunningPromise;
|
|
21
30
|
|
|
22
31
|
constructor(
|
|
@@ -49,11 +58,26 @@ export class ProverAgent {
|
|
|
49
58
|
throw new Error('Agent is already running');
|
|
50
59
|
}
|
|
51
60
|
|
|
61
|
+
let lastPrint = process.hrtime.bigint();
|
|
62
|
+
|
|
52
63
|
this.runningPromise = new RunningPromise(async () => {
|
|
53
64
|
for (const jobId of this.inFlightPromises.keys()) {
|
|
54
65
|
await jobSource.heartbeat(jobId);
|
|
55
66
|
}
|
|
56
67
|
|
|
68
|
+
const now = process.hrtime.bigint();
|
|
69
|
+
|
|
70
|
+
if (now - lastPrint >= PRINT_THRESHOLD_NS) {
|
|
71
|
+
// only log if we're actually doing work
|
|
72
|
+
if (this.inFlightPromises.size > 0) {
|
|
73
|
+
const jobs = Array.from(this.inFlightPromises.values())
|
|
74
|
+
.map(job => `id=${job.id},type=${ProvingRequestType[job.type]}`)
|
|
75
|
+
.join(' ');
|
|
76
|
+
this.log.info(`Agent is running with ${this.inFlightPromises.size} in-flight jobs: ${jobs}`);
|
|
77
|
+
}
|
|
78
|
+
lastPrint = now;
|
|
79
|
+
}
|
|
80
|
+
|
|
57
81
|
while (this.inFlightPromises.size < this.maxConcurrency) {
|
|
58
82
|
try {
|
|
59
83
|
const job = await jobSource.getProvingJob();
|
|
@@ -62,10 +86,20 @@ export class ProverAgent {
|
|
|
62
86
|
return;
|
|
63
87
|
}
|
|
64
88
|
|
|
65
|
-
|
|
66
|
-
|
|
89
|
+
try {
|
|
90
|
+
const promise = this.work(jobSource, job).finally(() => this.inFlightPromises.delete(job.id));
|
|
91
|
+
this.inFlightPromises.set(job.id, {
|
|
92
|
+
id: job.id,
|
|
93
|
+
type: job.request.type,
|
|
94
|
+
promise,
|
|
95
|
+
});
|
|
96
|
+
} catch (err) {
|
|
97
|
+
this.log.warn(
|
|
98
|
+
`Error processing job! type=${ProvingRequestType[job.request.type]}: ${err}. ${(err as Error).stack}`,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
67
101
|
} catch (err) {
|
|
68
|
-
this.log.
|
|
102
|
+
this.log.error(`Error fetching job`, err);
|
|
69
103
|
}
|
|
70
104
|
}
|
|
71
105
|
}, this.pollIntervalMs);
|
|
@@ -90,12 +124,12 @@ export class ProverAgent {
|
|
|
90
124
|
this.log.debug(`Picked up proving job id=${job.id} type=${ProvingRequestType[job.request.type]}`);
|
|
91
125
|
const [time, result] = await elapsed(this.getProof(job.request));
|
|
92
126
|
if (this.isRunning()) {
|
|
93
|
-
this.log.
|
|
127
|
+
this.log.verbose(
|
|
94
128
|
`Processed proving job id=${job.id} type=${ProvingRequestType[job.request.type]} duration=${time}ms`,
|
|
95
129
|
);
|
|
96
130
|
await jobSource.resolveProvingJob(job.id, result);
|
|
97
131
|
} else {
|
|
98
|
-
this.log.
|
|
132
|
+
this.log.verbose(
|
|
99
133
|
`Dropping proving job id=${job.id} type=${
|
|
100
134
|
ProvingRequestType[job.request.type]
|
|
101
135
|
} duration=${time}ms: agent stopped`,
|
|
@@ -107,10 +141,11 @@ export class ProverAgent {
|
|
|
107
141
|
`Error processing proving job id=${job.id} type=${ProvingRequestType[job.request.type]}: ${
|
|
108
142
|
(err as any).stack || err
|
|
109
143
|
}`,
|
|
144
|
+
err,
|
|
110
145
|
);
|
|
111
146
|
await jobSource.rejectProvingJob(job.id, new ProvingError((err as any)?.message ?? String(err)));
|
|
112
147
|
} else {
|
|
113
|
-
this.log.
|
|
148
|
+
this.log.verbose(
|
|
114
149
|
`Dropping proving job id=${job.id} type=${ProvingRequestType[job.request.type]}: agent stopped: ${
|
|
115
150
|
(err as any).stack || err
|
|
116
151
|
}`,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ProvingRequestType } from '@aztec/circuit-types';
|
|
2
|
+
import { Attributes, type Gauge, type Histogram, Metrics, type TelemetryClient } from '@aztec/telemetry-client';
|
|
3
|
+
|
|
4
|
+
export class ProvingQueueMetrics {
|
|
5
|
+
private jobSize: Histogram;
|
|
6
|
+
private queueSize: Gauge;
|
|
7
|
+
|
|
8
|
+
constructor(client: TelemetryClient, name = 'ProvingQueueMetrics') {
|
|
9
|
+
const meter = client.getMeter(name);
|
|
10
|
+
this.jobSize = meter.createHistogram(Metrics.PROVING_QUEUE_JOB_SIZE, {
|
|
11
|
+
description: 'Size of proving job',
|
|
12
|
+
unit: 'by',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
this.queueSize = meter.createGauge(Metrics.PROVING_QUEUE_SIZE, {
|
|
16
|
+
description: 'Size of proving queue',
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
recordNewJob(type: ProvingRequestType, size: number) {
|
|
21
|
+
this.jobSize.record(size, {
|
|
22
|
+
[Attributes.PROVING_JOB_TYPE]: ProvingRequestType[type],
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
recordQueueSize(size: number) {
|
|
27
|
+
this.queueSize.record(size);
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/prover-agent/rpc.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
KernelCircuitPublicInputs,
|
|
10
10
|
MergeRollupInputs,
|
|
11
11
|
ParityPublicInputs,
|
|
12
|
+
PrivateKernelEmptyInputData,
|
|
12
13
|
Proof,
|
|
13
14
|
PublicKernelCircuitPrivateInputs,
|
|
14
15
|
PublicKernelCircuitPublicInputs,
|
|
@@ -41,6 +42,7 @@ export function createProvingJobSourceServer(queue: ProvingJobSource): JsonRpcSe
|
|
|
41
42
|
ParityPublicInputs,
|
|
42
43
|
Proof,
|
|
43
44
|
ProvingError,
|
|
45
|
+
PrivateKernelEmptyInputData,
|
|
44
46
|
PublicKernelCircuitPrivateInputs,
|
|
45
47
|
PublicKernelCircuitPublicInputs,
|
|
46
48
|
PublicKernelTailCircuitPrivateInputs,
|
|
@@ -75,6 +77,7 @@ export function createProvingJobSourceClient(
|
|
|
75
77
|
ParityPublicInputs,
|
|
76
78
|
Proof,
|
|
77
79
|
ProvingError,
|
|
80
|
+
PrivateKernelEmptyInputData,
|
|
78
81
|
PublicKernelCircuitPrivateInputs,
|
|
79
82
|
PublicKernelCircuitPublicInputs,
|
|
80
83
|
PublicKernelTailCircuitPrivateInputs,
|
package/src/tx-prover/factory.ts
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
import { type L2BlockSource } from '@aztec/circuit-types';
|
|
2
1
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
3
2
|
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
|
|
4
|
-
import { type WorldStateSynchronizer } from '@aztec/world-state';
|
|
5
3
|
|
|
6
4
|
import { type ProverClientConfig } from '../config.js';
|
|
7
5
|
import { TxProver } from './tx-prover.js';
|
|
8
6
|
|
|
9
|
-
export function createProverClient(
|
|
10
|
-
config:
|
|
11
|
-
worldStateSynchronizer: WorldStateSynchronizer,
|
|
12
|
-
blockSource: L2BlockSource,
|
|
13
|
-
telemetry: TelemetryClient = new NoopTelemetryClient(),
|
|
14
|
-
) {
|
|
15
|
-
return config.disableProver ? undefined : TxProver.new(config, worldStateSynchronizer, blockSource, telemetry);
|
|
7
|
+
export function createProverClient(config: ProverClientConfig, telemetry: TelemetryClient = new NoopTelemetryClient()) {
|
|
8
|
+
return config.disableProver ? undefined : TxProver.new(config, telemetry);
|
|
16
9
|
}
|