@aztec/bb-prover 0.42.0 → 0.44.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/bb/execute.d.ts +1 -1
- package/dest/bb/execute.d.ts.map +1 -1
- package/dest/bb/execute.js +10 -10
- package/dest/instrumentation.d.ts +47 -0
- package/dest/instrumentation.d.ts.map +1 -0
- package/dest/instrumentation.js +102 -0
- package/dest/prover/bb_native_proof_creator.d.ts.map +1 -1
- package/dest/prover/bb_native_proof_creator.js +10 -8
- package/dest/prover/bb_prover.d.ts +5 -2
- package/dest/prover/bb_prover.d.ts.map +1 -1
- package/dest/prover/bb_prover.js +444 -388
- package/dest/stats.d.ts +1 -2
- package/dest/stats.d.ts.map +1 -1
- package/dest/stats.js +2 -16
- package/dest/test/test_circuit_prover.d.ts +4 -1
- package/dest/test/test_circuit_prover.d.ts.map +1 -1
- package/dest/test/test_circuit_prover.js +166 -120
- package/package.json +16 -7
- package/src/bb/execute.ts +10 -10
- package/src/instrumentation.ts +149 -0
- package/src/prover/bb_native_proof_creator.ts +9 -9
- package/src/prover/bb_prover.ts +79 -38
- package/src/stats.ts +1 -15
- package/src/test/test_circuit_prover.ts +29 -4
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { type CircuitName } from '@aztec/circuit-types/stats';
|
|
2
|
+
import { type Timer } from '@aztec/foundation/timer';
|
|
3
|
+
import {
|
|
4
|
+
Attributes,
|
|
5
|
+
type Gauge,
|
|
6
|
+
type Histogram,
|
|
7
|
+
Metrics,
|
|
8
|
+
type TelemetryClient,
|
|
9
|
+
type Tracer,
|
|
10
|
+
ValueType,
|
|
11
|
+
} from '@aztec/telemetry-client';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Instrumentation class for Prover implementations.
|
|
15
|
+
*/
|
|
16
|
+
export class ProverInstrumentation {
|
|
17
|
+
private simulationDuration: Histogram;
|
|
18
|
+
private witGenDuration: Gauge;
|
|
19
|
+
private provingDuration: Gauge;
|
|
20
|
+
|
|
21
|
+
private witGenInputSize: Gauge;
|
|
22
|
+
private witGenOutputSize: Gauge;
|
|
23
|
+
|
|
24
|
+
private proofSize: Gauge;
|
|
25
|
+
private circuitSize: Gauge;
|
|
26
|
+
private circuitPublicInputCount: Gauge;
|
|
27
|
+
|
|
28
|
+
public readonly tracer: Tracer;
|
|
29
|
+
|
|
30
|
+
constructor(telemetry: TelemetryClient, name: string) {
|
|
31
|
+
this.tracer = telemetry.getTracer(name);
|
|
32
|
+
const meter = telemetry.getMeter(name);
|
|
33
|
+
|
|
34
|
+
this.simulationDuration = meter.createHistogram(Metrics.CIRCUIT_SIMULATION_DURATION, {
|
|
35
|
+
description: 'Records how long it takes to simulate a circuit',
|
|
36
|
+
unit: 's',
|
|
37
|
+
valueType: ValueType.DOUBLE,
|
|
38
|
+
advice: {
|
|
39
|
+
explicitBucketBoundaries: [0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60],
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
this.witGenDuration = meter.createGauge(Metrics.CIRCUIT_WITNESS_GEN_DURATION, {
|
|
44
|
+
description: 'Records how long it takes to generate the partial witness for a circuit',
|
|
45
|
+
unit: 's',
|
|
46
|
+
valueType: ValueType.DOUBLE,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// ideally this would be a histogram, but proving takes a long time on the server
|
|
50
|
+
// and they don't happen that often so Prometheus & Grafana have a hard time handling it
|
|
51
|
+
this.provingDuration = meter.createGauge(Metrics.CIRCUIT_PROVING_DURATION, {
|
|
52
|
+
unit: 's',
|
|
53
|
+
description: 'Records how long it takes to prove a circuit',
|
|
54
|
+
valueType: ValueType.DOUBLE,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
this.witGenInputSize = meter.createGauge(Metrics.CIRCUIT_WITNESS_GEN_INPUT_SIZE, {
|
|
58
|
+
unit: 'By',
|
|
59
|
+
description: 'Records the size of the input to the witness generation',
|
|
60
|
+
valueType: ValueType.INT,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
this.witGenOutputSize = meter.createGauge(Metrics.CIRCUIT_WITNESS_GEN_OUTPUT_SIZE, {
|
|
64
|
+
unit: 'By',
|
|
65
|
+
description: 'Records the size of the output of the witness generation',
|
|
66
|
+
valueType: ValueType.INT,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
this.proofSize = meter.createGauge(Metrics.CIRCUIT_PROVING_PROOF_SIZE, {
|
|
70
|
+
unit: 'By',
|
|
71
|
+
description: 'Records the size of the proof generated for a circuit',
|
|
72
|
+
valueType: ValueType.INT,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
this.circuitPublicInputCount = meter.createGauge(Metrics.CIRCUIT_PUBLIC_INPUTS_COUNT, {
|
|
76
|
+
description: 'Records the number of public inputs in a circuit',
|
|
77
|
+
valueType: ValueType.INT,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
this.circuitSize = meter.createGauge(Metrics.CIRCUIT_SIZE, {
|
|
81
|
+
description: 'Records the size of the circuit in gates',
|
|
82
|
+
valueType: ValueType.INT,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Records the duration of a circuit operation.
|
|
88
|
+
* @param metric - The metric to record
|
|
89
|
+
* @param circuitName - The name of the circuit
|
|
90
|
+
* @param timerOrS - The duration
|
|
91
|
+
*/
|
|
92
|
+
recordDuration(
|
|
93
|
+
metric: 'simulationDuration' | 'witGenDuration' | 'provingDuration',
|
|
94
|
+
circuitName: CircuitName,
|
|
95
|
+
timerOrS: Timer | number,
|
|
96
|
+
) {
|
|
97
|
+
const s = typeof timerOrS === 'number' ? timerOrS : timerOrS.s();
|
|
98
|
+
this[metric].record(s, {
|
|
99
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: circuitName,
|
|
100
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Records the duration of an AVM circuit operation.
|
|
106
|
+
* @param metric - The metric to record
|
|
107
|
+
* @param appCircuitName - The name of the function circuit (should be a `contract:function` string)
|
|
108
|
+
* @param timerOrS - The duration
|
|
109
|
+
*/
|
|
110
|
+
recordAvmDuration(metric: 'witGenDuration' | 'provingDuration', appCircuitName: string, timerOrS: Timer | number) {
|
|
111
|
+
const s = typeof timerOrS === 'number' ? timerOrS : timerOrS.s();
|
|
112
|
+
this[metric].record(s, {
|
|
113
|
+
[Attributes.APP_CIRCUIT_NAME]: appCircuitName,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Records the size of a circuit operation.
|
|
119
|
+
* @param metric - Records the size of a circuit operation.
|
|
120
|
+
* @param circuitName - The name of the circuit
|
|
121
|
+
* @param size - The size
|
|
122
|
+
*/
|
|
123
|
+
recordSize(
|
|
124
|
+
metric: 'witGenInputSize' | 'witGenOutputSize' | 'proofSize' | 'circuitSize' | 'circuitPublicInputCount',
|
|
125
|
+
circuitName: CircuitName,
|
|
126
|
+
size: number,
|
|
127
|
+
) {
|
|
128
|
+
this[metric].record(Math.ceil(size), {
|
|
129
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: circuitName,
|
|
130
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Records the size of an AVM circuit operation.
|
|
136
|
+
* @param metric - The metric to record
|
|
137
|
+
* @param appCircuitName - The name of the function circuit (should be a `contract:function` string)
|
|
138
|
+
* @param size - The size
|
|
139
|
+
*/
|
|
140
|
+
recordAvmSize(
|
|
141
|
+
metric: 'witGenInputSize' | 'witGenOutputSize' | 'proofSize' | 'circuitSize' | 'circuitPublicInputCount',
|
|
142
|
+
appCircuitName: string,
|
|
143
|
+
size: number,
|
|
144
|
+
) {
|
|
145
|
+
this[metric].record(Math.ceil(size), {
|
|
146
|
+
[Attributes.APP_CIRCUIT_NAME]: appCircuitName,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -42,6 +42,7 @@ import { type NoirCompiledCircuit } from '@aztec/types/noir';
|
|
|
42
42
|
import { serializeWitness } from '@noir-lang/noirc_abi';
|
|
43
43
|
import { type WitnessMap } from '@noir-lang/types';
|
|
44
44
|
import * as fs from 'fs/promises';
|
|
45
|
+
import { join } from 'path';
|
|
45
46
|
|
|
46
47
|
import {
|
|
47
48
|
BB_RESULT,
|
|
@@ -175,7 +176,7 @@ export class BBNativeProofCreator implements ProofCreator {
|
|
|
175
176
|
throw new Error(errorMessage);
|
|
176
177
|
}
|
|
177
178
|
|
|
178
|
-
this.log.info(`Successfully verified ${circuitType} proof in ${result.
|
|
179
|
+
this.log.info(`Successfully verified ${circuitType} proof in ${Math.ceil(result.durationMs)} ms`);
|
|
179
180
|
}
|
|
180
181
|
|
|
181
182
|
private async verifyProofFromKey(
|
|
@@ -304,13 +305,14 @@ export class BBNativeProofCreator implements ProofCreator {
|
|
|
304
305
|
}> {
|
|
305
306
|
const compressedBincodedWitness = serializeWitness(partialWitness);
|
|
306
307
|
|
|
307
|
-
const inputsWitnessFile =
|
|
308
|
+
const inputsWitnessFile = join(directory, 'witness.gz');
|
|
308
309
|
|
|
309
310
|
await fs.writeFile(inputsWitnessFile, compressedBincodedWitness);
|
|
310
311
|
|
|
311
312
|
this.log.debug(`Written ${inputsWitnessFile}`);
|
|
312
313
|
|
|
313
|
-
|
|
314
|
+
const dbgCircuitName = appCircuitName ? `(${appCircuitName})` : '';
|
|
315
|
+
this.log.info(`Proving ${circuitType}${dbgCircuitName} circuit...`);
|
|
314
316
|
|
|
315
317
|
const timer = new Timer();
|
|
316
318
|
|
|
@@ -324,13 +326,11 @@ export class BBNativeProofCreator implements ProofCreator {
|
|
|
324
326
|
);
|
|
325
327
|
|
|
326
328
|
if (provingResult.status === BB_RESULT.FAILURE) {
|
|
327
|
-
this.log.error(`Failed to generate proof for ${circuitType}: ${provingResult.reason}`);
|
|
329
|
+
this.log.error(`Failed to generate proof for ${circuitType}${dbgCircuitName}: ${provingResult.reason}`);
|
|
328
330
|
throw new Error(provingResult.reason);
|
|
329
331
|
}
|
|
330
332
|
|
|
331
|
-
this.log.info(
|
|
332
|
-
`Generated ${circuitType === 'App' ? appCircuitName : circuitType} circuit proof in ${timer.ms()} ms`,
|
|
333
|
-
);
|
|
333
|
+
this.log.info(`Generated ${circuitType}${dbgCircuitName} circuit proof in ${Math.ceil(timer.ms())} ms`);
|
|
334
334
|
|
|
335
335
|
if (circuitType === 'App') {
|
|
336
336
|
const vkData = await extractVkData(directory);
|
|
@@ -339,7 +339,7 @@ export class BBNativeProofCreator implements ProofCreator {
|
|
|
339
339
|
this.log.debug(`Generated proof`, {
|
|
340
340
|
eventName: 'circuit-proving',
|
|
341
341
|
circuitName: 'app-circuit',
|
|
342
|
-
duration: provingResult.
|
|
342
|
+
duration: provingResult.durationMs,
|
|
343
343
|
inputSize: compressedBincodedWitness.length,
|
|
344
344
|
proofSize: proof.binaryProof.buffer.length,
|
|
345
345
|
appCircuitName,
|
|
@@ -358,7 +358,7 @@ export class BBNativeProofCreator implements ProofCreator {
|
|
|
358
358
|
|
|
359
359
|
this.log.debug(`Generated proof`, {
|
|
360
360
|
circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
|
|
361
|
-
duration: provingResult.
|
|
361
|
+
duration: provingResult.durationMs,
|
|
362
362
|
eventName: 'circuit-proving',
|
|
363
363
|
inputSize: compressedBincodedWitness.length,
|
|
364
364
|
proofSize: proof.binaryProof.buffer.length,
|
package/src/prover/bb_prover.ts
CHANGED
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
type PublicInputsAndRecursiveProof,
|
|
5
5
|
type PublicKernelNonTailRequest,
|
|
6
6
|
type PublicKernelTailRequest,
|
|
7
|
-
PublicKernelType,
|
|
8
7
|
type ServerCircuitProver,
|
|
9
8
|
makePublicInputsAndRecursiveProof,
|
|
10
9
|
} from '@aztec/circuit-types';
|
|
@@ -58,6 +57,7 @@ import {
|
|
|
58
57
|
convertRootRollupOutputsFromWitnessMap,
|
|
59
58
|
} from '@aztec/noir-protocol-circuits-types';
|
|
60
59
|
import { NativeACVMSimulator } from '@aztec/simulator';
|
|
60
|
+
import { Attributes, type TelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
61
61
|
|
|
62
62
|
import { abiEncode } from '@noir-lang/noirc_abi';
|
|
63
63
|
import { type Abi, type WitnessMap } from '@noir-lang/types';
|
|
@@ -79,6 +79,7 @@ import {
|
|
|
79
79
|
writeProofAsFields,
|
|
80
80
|
} from '../bb/execute.js';
|
|
81
81
|
import type { ACVMConfig, BBConfig } from '../config.js';
|
|
82
|
+
import { ProverInstrumentation } from '../instrumentation.js';
|
|
82
83
|
import { PublicKernelArtifactMapping } from '../mappings/mappings.js';
|
|
83
84
|
import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
|
|
84
85
|
import { extractVkData } from '../verification_key/verification_key_data.js';
|
|
@@ -103,9 +104,18 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
103
104
|
ServerProtocolArtifact,
|
|
104
105
|
Promise<VerificationKeyData>
|
|
105
106
|
>();
|
|
106
|
-
constructor(private config: BBProverConfig) {}
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
private instrumentation: ProverInstrumentation;
|
|
109
|
+
|
|
110
|
+
constructor(private config: BBProverConfig, telemetry: TelemetryClient) {
|
|
111
|
+
this.instrumentation = new ProverInstrumentation(telemetry, 'BBNativeRollupProver');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
get tracer() {
|
|
115
|
+
return this.instrumentation.tracer;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static async new(config: BBProverConfig, telemetry: TelemetryClient) {
|
|
109
119
|
await fs.access(config.acvmBinaryPath, fs.constants.R_OK);
|
|
110
120
|
await fs.mkdir(config.acvmWorkingDirectory, { recursive: true });
|
|
111
121
|
await fs.access(config.bbBinaryPath, fs.constants.R_OK);
|
|
@@ -113,7 +123,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
113
123
|
logger.info(`Using native BB at ${config.bbBinaryPath} and working directory ${config.bbWorkingDirectory}`);
|
|
114
124
|
logger.info(`Using native ACVM at ${config.acvmBinaryPath} and working directory ${config.acvmWorkingDirectory}`);
|
|
115
125
|
|
|
116
|
-
return new BBNativeRollupProver(config);
|
|
126
|
+
return new BBNativeRollupProver(config, telemetry);
|
|
117
127
|
}
|
|
118
128
|
|
|
119
129
|
/**
|
|
@@ -121,6 +131,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
121
131
|
* @param inputs - Inputs to the circuit.
|
|
122
132
|
* @returns The public inputs of the parity circuit.
|
|
123
133
|
*/
|
|
134
|
+
@trackSpan('BBNativeRollupProver.getBaseParityProof', { [Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-parity' })
|
|
124
135
|
public async getBaseParityProof(inputs: BaseParityInputs): Promise<RootParityInput<typeof RECURSIVE_PROOF_LENGTH>> {
|
|
125
136
|
const { circuitOutput, proof } = await this.createRecursiveProof(
|
|
126
137
|
inputs,
|
|
@@ -142,6 +153,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
142
153
|
* @param inputs - Inputs to the circuit.
|
|
143
154
|
* @returns The public inputs of the parity circuit.
|
|
144
155
|
*/
|
|
156
|
+
@trackSpan('BBNativeRollupProver.getRootParityProof', { [Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-parity' })
|
|
145
157
|
public async getRootParityProof(
|
|
146
158
|
inputs: RootParityInputs,
|
|
147
159
|
): Promise<RootParityInput<typeof NESTED_RECURSIVE_PROOF_LENGTH>> {
|
|
@@ -165,6 +177,9 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
165
177
|
* @param inputs - The inputs to the AVM circuit.
|
|
166
178
|
* @returns The proof.
|
|
167
179
|
*/
|
|
180
|
+
@trackSpan('BBNativeRollupProver.getAvmProof', inputs => ({
|
|
181
|
+
[Attributes.APP_CIRCUIT_NAME]: inputs.functionName,
|
|
182
|
+
}))
|
|
168
183
|
public async getAvmProof(inputs: AvmCircuitInputs): Promise<ProofAndVerificationKey> {
|
|
169
184
|
const proofAndVk = await this.createAvmProof(inputs);
|
|
170
185
|
await this.verifyAvmProof(proofAndVk.proof, proofAndVk.verificationKey);
|
|
@@ -176,12 +191,17 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
176
191
|
* @param kernelRequest - The object encapsulating the request for a proof
|
|
177
192
|
* @returns The requested circuit's public inputs and proof
|
|
178
193
|
*/
|
|
194
|
+
@trackSpan('BBNativeRollupProver.getPublicKernelProof', kernelReq => ({
|
|
195
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: mapProtocolArtifactNameToCircuitName(
|
|
196
|
+
PublicKernelArtifactMapping[kernelReq.type]!.artifact,
|
|
197
|
+
),
|
|
198
|
+
}))
|
|
179
199
|
public async getPublicKernelProof(
|
|
180
200
|
kernelRequest: PublicKernelNonTailRequest,
|
|
181
201
|
): Promise<PublicInputsAndRecursiveProof<PublicKernelCircuitPublicInputs>> {
|
|
182
202
|
const kernelOps = PublicKernelArtifactMapping[kernelRequest.type];
|
|
183
203
|
if (kernelOps === undefined) {
|
|
184
|
-
throw new Error(`Unable to prove kernel type ${
|
|
204
|
+
throw new Error(`Unable to prove kernel type ${kernelRequest.type}`);
|
|
185
205
|
}
|
|
186
206
|
|
|
187
207
|
// We may need to convert the recursive proof into fields format
|
|
@@ -386,11 +406,16 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
386
406
|
const inputWitness = convertInput(input);
|
|
387
407
|
const timer = new Timer();
|
|
388
408
|
const outputWitness = await simulator.simulateCircuit(inputWitness, artifact);
|
|
389
|
-
const witnessGenerationDuration = timer.ms();
|
|
390
409
|
const output = convertOutput(outputWitness);
|
|
410
|
+
|
|
411
|
+
const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
|
|
412
|
+
this.instrumentation.recordDuration('witGenDuration', circuitName, timer);
|
|
413
|
+
this.instrumentation.recordSize('witGenInputSize', circuitName, input.toBuffer().length);
|
|
414
|
+
this.instrumentation.recordSize('witGenOutputSize', circuitName, output.toBuffer().length);
|
|
415
|
+
|
|
391
416
|
logger.debug(`Generated witness`, {
|
|
392
|
-
circuitName
|
|
393
|
-
duration:
|
|
417
|
+
circuitName,
|
|
418
|
+
duration: timer.ms(),
|
|
394
419
|
inputSize: input.toBuffer().length,
|
|
395
420
|
outputSize: output.toBuffer().length,
|
|
396
421
|
eventName: 'circuit-witness-generation',
|
|
@@ -440,22 +465,24 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
440
465
|
const rawProof = await fs.readFile(`${provingResult.proofPath!}/${PROOF_FILENAME}`);
|
|
441
466
|
|
|
442
467
|
const proof = new Proof(rawProof, vkData.numPublicInputs);
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
468
|
+
const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
|
|
469
|
+
|
|
470
|
+
this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs / 1000);
|
|
471
|
+
this.instrumentation.recordSize('proofSize', circuitName, proof.buffer.length);
|
|
472
|
+
this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs);
|
|
473
|
+
this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize);
|
|
474
|
+
|
|
475
|
+
logger.info(`Generated proof for ${circuitType} in ${Math.ceil(provingResult.durationMs)} ms`, {
|
|
476
|
+
circuitName,
|
|
477
|
+
// does not include reading the proof from disk
|
|
478
|
+
duration: provingResult.durationMs,
|
|
479
|
+
proofSize: proof.buffer.length,
|
|
480
|
+
eventName: 'circuit-proving',
|
|
481
|
+
// circuitOutput is the partial witness that became the input to the proof
|
|
482
|
+
inputSize: output.toBuffer().length,
|
|
483
|
+
circuitSize: vkData.circuitSize,
|
|
484
|
+
numPublicInputs: vkData.numPublicInputs,
|
|
485
|
+
} satisfies CircuitProvingStats);
|
|
459
486
|
|
|
460
487
|
return { circuitOutput: output, proof };
|
|
461
488
|
};
|
|
@@ -463,12 +490,12 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
463
490
|
}
|
|
464
491
|
|
|
465
492
|
private async generateAvmProofWithBB(input: AvmCircuitInputs, workingDirectory: string): Promise<BBSuccess> {
|
|
466
|
-
logger.
|
|
493
|
+
logger.info(`Proving avm-circuit for ${input.functionName}...`);
|
|
467
494
|
|
|
468
|
-
const provingResult = await generateAvmProof(this.config.bbBinaryPath, workingDirectory, input, logger.
|
|
495
|
+
const provingResult = await generateAvmProof(this.config.bbBinaryPath, workingDirectory, input, logger.verbose);
|
|
469
496
|
|
|
470
497
|
if (provingResult.status === BB_RESULT.FAILURE) {
|
|
471
|
-
logger.error(`Failed to generate proof for
|
|
498
|
+
logger.error(`Failed to generate AVM proof for ${input.functionName}: ${provingResult.reason}`);
|
|
472
499
|
throw new Error(provingResult.reason);
|
|
473
500
|
}
|
|
474
501
|
|
|
@@ -476,7 +503,11 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
476
503
|
}
|
|
477
504
|
|
|
478
505
|
private async createAvmProof(input: AvmCircuitInputs): Promise<ProofAndVerificationKey> {
|
|
506
|
+
const cleanupDir: boolean = !process.env.AVM_PROVING_PRESERVE_WORKING_DIR;
|
|
479
507
|
const operation = async (bbWorkingDirectory: string): Promise<ProofAndVerificationKey> => {
|
|
508
|
+
if (!cleanupDir) {
|
|
509
|
+
logger.info(`Preserving working directory ${bbWorkingDirectory}`);
|
|
510
|
+
}
|
|
480
511
|
const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory);
|
|
481
512
|
|
|
482
513
|
const rawProof = await fs.readFile(provingResult.proofPath!);
|
|
@@ -486,25 +517,30 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
486
517
|
const proof = new Proof(rawProof, verificationKey.numPublicInputs);
|
|
487
518
|
|
|
488
519
|
const circuitType = 'avm-circuit' as const;
|
|
520
|
+
const appCircuitName = 'unknown' as const;
|
|
521
|
+
this.instrumentation.recordAvmDuration('provingDuration', appCircuitName, provingResult.durationMs);
|
|
522
|
+
this.instrumentation.recordAvmSize('proofSize', appCircuitName, proof.buffer.length);
|
|
523
|
+
this.instrumentation.recordAvmSize('circuitPublicInputCount', appCircuitName, verificationKey.numPublicInputs);
|
|
524
|
+
this.instrumentation.recordAvmSize('circuitSize', appCircuitName, verificationKey.circuitSize);
|
|
525
|
+
|
|
489
526
|
logger.info(
|
|
490
|
-
`Generated proof for ${circuitType} in ${Math.ceil(provingResult.
|
|
491
|
-
proof.buffer.length
|
|
492
|
-
} bytes`,
|
|
527
|
+
`Generated proof for ${circuitType}(${input.functionName}) in ${Math.ceil(provingResult.durationMs)} ms`,
|
|
493
528
|
{
|
|
494
529
|
circuitName: circuitType,
|
|
530
|
+
appCircuitName: input.functionName,
|
|
495
531
|
// does not include reading the proof from disk
|
|
496
|
-
duration: provingResult.
|
|
532
|
+
duration: provingResult.durationMs,
|
|
497
533
|
proofSize: proof.buffer.length,
|
|
498
534
|
eventName: 'circuit-proving',
|
|
499
535
|
inputSize: input.toBuffer().length,
|
|
500
|
-
circuitSize: verificationKey.circuitSize,
|
|
501
|
-
numPublicInputs: verificationKey.numPublicInputs,
|
|
536
|
+
circuitSize: verificationKey.circuitSize, // FIX: wrong in VK
|
|
537
|
+
numPublicInputs: verificationKey.numPublicInputs, // FIX: wrong in VK
|
|
502
538
|
} satisfies CircuitProvingStats,
|
|
503
539
|
);
|
|
504
540
|
|
|
505
541
|
return { proof, verificationKey };
|
|
506
542
|
};
|
|
507
|
-
return await runInDirectory(this.config.bbWorkingDirectory, operation);
|
|
543
|
+
return await runInDirectory(this.config.bbWorkingDirectory, operation, cleanupDir);
|
|
508
544
|
}
|
|
509
545
|
|
|
510
546
|
/**
|
|
@@ -537,14 +573,19 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
537
573
|
// Read the proof as fields
|
|
538
574
|
const proof = await this.readProofAsFields(provingResult.proofPath!, circuitType, proofLength);
|
|
539
575
|
|
|
576
|
+
const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
|
|
577
|
+
this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs / 1000);
|
|
578
|
+
this.instrumentation.recordSize('proofSize', circuitName, proof.binaryProof.buffer.length);
|
|
579
|
+
this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs);
|
|
580
|
+
this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize);
|
|
540
581
|
logger.info(
|
|
541
|
-
`Generated proof for ${circuitType} in ${Math.ceil(provingResult.
|
|
582
|
+
`Generated proof for ${circuitType} in ${Math.ceil(provingResult.durationMs)} ms, size: ${
|
|
542
583
|
proof.proof.length
|
|
543
584
|
} fields`,
|
|
544
585
|
{
|
|
545
|
-
circuitName
|
|
586
|
+
circuitName,
|
|
546
587
|
circuitSize: vkData.circuitSize,
|
|
547
|
-
duration: provingResult.
|
|
588
|
+
duration: provingResult.durationMs,
|
|
548
589
|
inputSize: output.toBuffer().length,
|
|
549
590
|
proofSize: proof.binaryProof.buffer.length,
|
|
550
591
|
eventName: 'circuit-proving',
|
|
@@ -606,7 +647,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
606
647
|
throw new Error(errorMessage);
|
|
607
648
|
}
|
|
608
649
|
|
|
609
|
-
logger.debug(`Successfully verified proof from key in ${result.
|
|
650
|
+
logger.debug(`Successfully verified proof from key in ${result.durationMs} ms`);
|
|
610
651
|
};
|
|
611
652
|
|
|
612
653
|
await runInDirectory(this.config.bbWorkingDirectory, operation);
|
package/src/stats.ts
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
|
-
import { type PublicKernelRequest, PublicKernelType } from '@aztec/circuit-types';
|
|
2
1
|
import type { CircuitName } from '@aztec/circuit-types/stats';
|
|
3
2
|
import { type ClientProtocolArtifact, type ServerProtocolArtifact } from '@aztec/noir-protocol-circuits-types';
|
|
4
3
|
|
|
5
|
-
export
|
|
6
|
-
switch (kernelType) {
|
|
7
|
-
case PublicKernelType.SETUP:
|
|
8
|
-
return 'public-kernel-setup';
|
|
9
|
-
case PublicKernelType.APP_LOGIC:
|
|
10
|
-
return 'public-kernel-app-logic';
|
|
11
|
-
case PublicKernelType.TEARDOWN:
|
|
12
|
-
return 'public-kernel-teardown';
|
|
13
|
-
case PublicKernelType.TAIL:
|
|
14
|
-
return 'public-kernel-tail';
|
|
15
|
-
default:
|
|
16
|
-
throw new Error(`Unknown kernel type: ${kernelType}`);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
4
|
+
export { mapPublicKernelToCircuitName } from '@aztec/circuit-types';
|
|
19
5
|
|
|
20
6
|
export function mapProtocolArtifactNameToCircuitName(
|
|
21
7
|
artifact: ServerProtocolArtifact | ClientProtocolArtifact,
|
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
type PublicInputsAndRecursiveProof,
|
|
4
4
|
type PublicKernelNonTailRequest,
|
|
5
5
|
type PublicKernelTailRequest,
|
|
6
|
-
PublicKernelType,
|
|
7
6
|
type ServerCircuitProver,
|
|
8
7
|
makePublicInputsAndRecursiveProof,
|
|
9
8
|
} from '@aztec/circuit-types';
|
|
@@ -58,7 +57,9 @@ import {
|
|
|
58
57
|
convertSimulatedPublicTailOutputFromWitnessMap,
|
|
59
58
|
} from '@aztec/noir-protocol-circuits-types';
|
|
60
59
|
import { type SimulationProvider, WASMSimulator, emitCircuitSimulationStats } from '@aztec/simulator';
|
|
60
|
+
import { type TelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
61
61
|
|
|
62
|
+
import { ProverInstrumentation } from '../instrumentation.js';
|
|
62
63
|
import { SimulatedPublicKernelArtifactMapping } from '../mappings/mappings.js';
|
|
63
64
|
import { mapPublicKernelToCircuitName } from '../stats.js';
|
|
64
65
|
|
|
@@ -82,11 +83,19 @@ const VERIFICATION_KEYS: Record<ServerProtocolArtifact, VerificationKeyAsFields>
|
|
|
82
83
|
*/
|
|
83
84
|
export class TestCircuitProver implements ServerCircuitProver {
|
|
84
85
|
private wasmSimulator = new WASMSimulator();
|
|
86
|
+
private instrumentation: ProverInstrumentation;
|
|
85
87
|
|
|
86
88
|
constructor(
|
|
89
|
+
telemetry: TelemetryClient,
|
|
87
90
|
private simulationProvider?: SimulationProvider,
|
|
88
91
|
private logger = createDebugLogger('aztec:test-prover'),
|
|
89
|
-
) {
|
|
92
|
+
) {
|
|
93
|
+
this.instrumentation = new ProverInstrumentation(telemetry, 'TestCircuitProver');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
get tracer() {
|
|
97
|
+
return this.instrumentation.tracer;
|
|
98
|
+
}
|
|
90
99
|
|
|
91
100
|
public async getEmptyPrivateKernelProof(
|
|
92
101
|
inputs: PrivateKernelEmptyInputData,
|
|
@@ -112,6 +121,7 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
112
121
|
* @param inputs - Inputs to the circuit.
|
|
113
122
|
* @returns The public inputs of the parity circuit.
|
|
114
123
|
*/
|
|
124
|
+
@trackSpan('TestCircuitProver.getBaseParityProof')
|
|
115
125
|
public async getBaseParityProof(inputs: BaseParityInputs): Promise<RootParityInput<typeof RECURSIVE_PROOF_LENGTH>> {
|
|
116
126
|
const timer = new Timer();
|
|
117
127
|
const witnessMap = convertBaseParityInputsToWitnessMap(inputs);
|
|
@@ -126,6 +136,8 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
126
136
|
result,
|
|
127
137
|
);
|
|
128
138
|
|
|
139
|
+
this.instrumentation.recordDuration('simulationDuration', 'base-parity', timer);
|
|
140
|
+
|
|
129
141
|
emitCircuitSimulationStats(
|
|
130
142
|
'base-parity',
|
|
131
143
|
timer.ms(),
|
|
@@ -142,6 +154,7 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
142
154
|
* @param inputs - Inputs to the circuit.
|
|
143
155
|
* @returns The public inputs of the parity circuit.
|
|
144
156
|
*/
|
|
157
|
+
@trackSpan('TestCircuitProver.getRootParityProof')
|
|
145
158
|
public async getRootParityProof(
|
|
146
159
|
inputs: RootParityInputs,
|
|
147
160
|
): Promise<RootParityInput<typeof NESTED_RECURSIVE_PROOF_LENGTH>> {
|
|
@@ -159,6 +172,7 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
159
172
|
result,
|
|
160
173
|
);
|
|
161
174
|
|
|
175
|
+
this.instrumentation.recordDuration('simulationDuration', 'root-parity', timer);
|
|
162
176
|
emitCircuitSimulationStats(
|
|
163
177
|
'root-parity',
|
|
164
178
|
timer.ms(),
|
|
@@ -175,6 +189,7 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
175
189
|
* @param input - Inputs to the circuit.
|
|
176
190
|
* @returns The public inputs as outputs of the simulation.
|
|
177
191
|
*/
|
|
192
|
+
@trackSpan('TestCircuitProver.getBaseRollupProof')
|
|
178
193
|
public async getBaseRollupProof(
|
|
179
194
|
input: BaseRollupInputs,
|
|
180
195
|
): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>> {
|
|
@@ -186,6 +201,7 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
186
201
|
|
|
187
202
|
const result = convertSimulatedBaseRollupOutputsFromWitnessMap(witness);
|
|
188
203
|
|
|
204
|
+
this.instrumentation.recordDuration('simulationDuration', 'base-rollup', timer);
|
|
189
205
|
emitCircuitSimulationStats(
|
|
190
206
|
'base-rollup',
|
|
191
207
|
timer.ms(),
|
|
@@ -204,6 +220,7 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
204
220
|
* @param input - Inputs to the circuit.
|
|
205
221
|
* @returns The public inputs as outputs of the simulation.
|
|
206
222
|
*/
|
|
223
|
+
@trackSpan('TestCircuitProver.getMergeRollupProof')
|
|
207
224
|
public async getMergeRollupProof(
|
|
208
225
|
input: MergeRollupInputs,
|
|
209
226
|
): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>> {
|
|
@@ -215,6 +232,7 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
215
232
|
|
|
216
233
|
const result = convertMergeRollupOutputsFromWitnessMap(witness);
|
|
217
234
|
|
|
235
|
+
this.instrumentation.recordDuration('simulationDuration', 'merge-rollup', timer);
|
|
218
236
|
emitCircuitSimulationStats(
|
|
219
237
|
'merge-rollup',
|
|
220
238
|
timer.ms(),
|
|
@@ -234,6 +252,7 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
234
252
|
* @param input - Inputs to the circuit.
|
|
235
253
|
* @returns The public inputs as outputs of the simulation.
|
|
236
254
|
*/
|
|
255
|
+
@trackSpan('TestCircuitProver.getRootRollupProof')
|
|
237
256
|
public async getRootRollupProof(
|
|
238
257
|
input: RootRollupInputs,
|
|
239
258
|
): Promise<PublicInputsAndRecursiveProof<RootRollupPublicInputs>> {
|
|
@@ -245,6 +264,7 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
245
264
|
|
|
246
265
|
const result = convertRootRollupOutputsFromWitnessMap(witness);
|
|
247
266
|
|
|
267
|
+
this.instrumentation.recordDuration('simulationDuration', 'root-rollup', timer);
|
|
248
268
|
emitCircuitSimulationStats(
|
|
249
269
|
'root-rollup',
|
|
250
270
|
timer.ms(),
|
|
@@ -259,13 +279,14 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
259
279
|
);
|
|
260
280
|
}
|
|
261
281
|
|
|
282
|
+
@trackSpan('TestCircuitProver.getPublicKernelProof')
|
|
262
283
|
public async getPublicKernelProof(
|
|
263
284
|
kernelRequest: PublicKernelNonTailRequest,
|
|
264
285
|
): Promise<PublicInputsAndRecursiveProof<PublicKernelCircuitPublicInputs>> {
|
|
265
286
|
const timer = new Timer();
|
|
266
287
|
const kernelOps = SimulatedPublicKernelArtifactMapping[kernelRequest.type];
|
|
267
288
|
if (kernelOps === undefined) {
|
|
268
|
-
throw new Error(`Unable to prove for kernel type ${
|
|
289
|
+
throw new Error(`Unable to prove for kernel type ${kernelRequest.type}`);
|
|
269
290
|
}
|
|
270
291
|
const witnessMap = kernelOps.convertInputs(kernelRequest.inputs);
|
|
271
292
|
|
|
@@ -275,8 +296,10 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
275
296
|
);
|
|
276
297
|
|
|
277
298
|
const result = kernelOps.convertOutputs(witness);
|
|
299
|
+
const circuitName = mapPublicKernelToCircuitName(kernelRequest.type);
|
|
300
|
+
this.instrumentation.recordDuration('simulationDuration', circuitName, timer);
|
|
278
301
|
emitCircuitSimulationStats(
|
|
279
|
-
|
|
302
|
+
circuitName,
|
|
280
303
|
timer.ms(),
|
|
281
304
|
kernelRequest.inputs.toBuffer().length,
|
|
282
305
|
result.toBuffer().length,
|
|
@@ -290,6 +313,7 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
290
313
|
);
|
|
291
314
|
}
|
|
292
315
|
|
|
316
|
+
@trackSpan('TestCircuitProver.getPublicTailProof')
|
|
293
317
|
public async getPublicTailProof(
|
|
294
318
|
kernelRequest: PublicKernelTailRequest,
|
|
295
319
|
): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>> {
|
|
@@ -302,6 +326,7 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
302
326
|
);
|
|
303
327
|
|
|
304
328
|
const result = convertSimulatedPublicTailOutputFromWitnessMap(witness);
|
|
329
|
+
this.instrumentation.recordDuration('simulationDuration', 'public-kernel-tail', timer);
|
|
305
330
|
emitCircuitSimulationStats(
|
|
306
331
|
'public-kernel-tail',
|
|
307
332
|
timer.ms(),
|