@aztec/bb-prover 0.43.0 → 0.45.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 +5 -1
- package/dest/bb/execute.d.ts.map +1 -1
- package/dest/bb/execute.js +20 -14
- 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 +442 -390
- 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 +165 -119
- package/dest/verifier/bb_verifier.d.ts.map +1 -1
- package/dest/verifier/bb_verifier.js +5 -3
- package/package.json +16 -7
- package/src/bb/execute.ts +20 -15
- package/src/instrumentation.ts +149 -0
- package/src/prover/bb_native_proof_creator.ts +9 -9
- package/src/prover/bb_prover.ts +73 -35
- package/src/stats.ts +1 -15
- package/src/test/test_circuit_prover.ts +28 -2
- package/src/verifier/bb_verifier.ts +4 -3
package/src/bb/execute.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type AvmCircuitInputs } from '@aztec/circuits.js';
|
|
2
2
|
import { sha256 } from '@aztec/foundation/crypto';
|
|
3
|
-
import { type LogFn } from '@aztec/foundation/log';
|
|
3
|
+
import { type LogFn, currentLevel as currentLogLevel } from '@aztec/foundation/log';
|
|
4
4
|
import { Timer } from '@aztec/foundation/timer';
|
|
5
5
|
import { type NoirCompiledCircuit } from '@aztec/types/noir';
|
|
6
6
|
|
|
@@ -12,6 +12,10 @@ export const VK_FILENAME = 'vk';
|
|
|
12
12
|
export const VK_FIELDS_FILENAME = 'vk_fields.json';
|
|
13
13
|
export const PROOF_FILENAME = 'proof';
|
|
14
14
|
export const PROOF_FIELDS_FILENAME = 'proof_fields.json';
|
|
15
|
+
export const AVM_BYTECODE_FILENAME = 'avm_bytecode.bin';
|
|
16
|
+
export const AVM_CALLDATA_FILENAME = 'avm_calldata.bin';
|
|
17
|
+
export const AVM_PUBLIC_INPUTS_FILENAME = 'avm_public_inputs.bin';
|
|
18
|
+
export const AVM_HINTS_FILENAME = 'avm_hints.bin';
|
|
15
19
|
|
|
16
20
|
export enum BB_RESULT {
|
|
17
21
|
SUCCESS,
|
|
@@ -21,7 +25,7 @@ export enum BB_RESULT {
|
|
|
21
25
|
|
|
22
26
|
export type BBSuccess = {
|
|
23
27
|
status: BB_RESULT.SUCCESS | BB_RESULT.ALREADY_PRESENT;
|
|
24
|
-
|
|
28
|
+
durationMs: number;
|
|
25
29
|
/** Full path of the public key. */
|
|
26
30
|
pkPath?: string;
|
|
27
31
|
/** Base directory for the VKs (raw, fields). */
|
|
@@ -155,7 +159,7 @@ export async function generateKeyForNoirCircuit(
|
|
|
155
159
|
if (result.status == BB_RESULT.SUCCESS) {
|
|
156
160
|
return {
|
|
157
161
|
status: BB_RESULT.SUCCESS,
|
|
158
|
-
duration,
|
|
162
|
+
durationMs: duration,
|
|
159
163
|
pkPath: key === 'pk' ? outputPath : undefined,
|
|
160
164
|
vkPath: key === 'vk' ? outputPath : undefined,
|
|
161
165
|
proofPath: undefined,
|
|
@@ -174,7 +178,7 @@ export async function generateKeyForNoirCircuit(
|
|
|
174
178
|
if (!res) {
|
|
175
179
|
return {
|
|
176
180
|
status: BB_RESULT.ALREADY_PRESENT,
|
|
177
|
-
|
|
181
|
+
durationMs: 0,
|
|
178
182
|
pkPath: key === 'pk' ? outputPath : undefined,
|
|
179
183
|
vkPath: key === 'vk' ? outputPath : undefined,
|
|
180
184
|
};
|
|
@@ -237,7 +241,7 @@ export async function generateProof(
|
|
|
237
241
|
if (result.status == BB_RESULT.SUCCESS) {
|
|
238
242
|
return {
|
|
239
243
|
status: BB_RESULT.SUCCESS,
|
|
240
|
-
duration,
|
|
244
|
+
durationMs: duration,
|
|
241
245
|
proofPath: `${outputPath}`,
|
|
242
246
|
pkPath: undefined,
|
|
243
247
|
vkPath: `${outputPath}`,
|
|
@@ -276,10 +280,10 @@ export async function generateAvmProof(
|
|
|
276
280
|
}
|
|
277
281
|
|
|
278
282
|
// Paths for the inputs
|
|
279
|
-
const bytecodePath = join(workingDirectory,
|
|
280
|
-
const calldataPath = join(workingDirectory,
|
|
281
|
-
const publicInputsPath = join(workingDirectory,
|
|
282
|
-
const avmHintsPath = join(workingDirectory,
|
|
283
|
+
const bytecodePath = join(workingDirectory, AVM_BYTECODE_FILENAME);
|
|
284
|
+
const calldataPath = join(workingDirectory, AVM_CALLDATA_FILENAME);
|
|
285
|
+
const publicInputsPath = join(workingDirectory, AVM_PUBLIC_INPUTS_FILENAME);
|
|
286
|
+
const avmHintsPath = join(workingDirectory, AVM_HINTS_FILENAME);
|
|
283
287
|
|
|
284
288
|
// The proof is written to e.g. /workingDirectory/proof
|
|
285
289
|
const outputPath = workingDirectory;
|
|
@@ -335,6 +339,7 @@ export async function generateAvmProof(
|
|
|
335
339
|
avmHintsPath,
|
|
336
340
|
'-o',
|
|
337
341
|
outputPath,
|
|
342
|
+
currentLogLevel == 'debug' ? '-d' : 'verbose' ? '-v' : '',
|
|
338
343
|
];
|
|
339
344
|
const timer = new Timer();
|
|
340
345
|
const logFunction = (message: string) => {
|
|
@@ -346,7 +351,7 @@ export async function generateAvmProof(
|
|
|
346
351
|
if (result.status == BB_RESULT.SUCCESS) {
|
|
347
352
|
return {
|
|
348
353
|
status: BB_RESULT.SUCCESS,
|
|
349
|
-
duration,
|
|
354
|
+
durationMs: duration,
|
|
350
355
|
proofPath: join(outputPath, PROOF_FILENAME),
|
|
351
356
|
pkPath: undefined,
|
|
352
357
|
vkPath: outputPath,
|
|
@@ -426,7 +431,7 @@ async function verifyProofInternal(
|
|
|
426
431
|
const result = await executeBB(pathToBB, command, args, log);
|
|
427
432
|
const duration = timer.ms();
|
|
428
433
|
if (result.status == BB_RESULT.SUCCESS) {
|
|
429
|
-
return { status: BB_RESULT.SUCCESS, duration };
|
|
434
|
+
return { status: BB_RESULT.SUCCESS, durationMs: duration };
|
|
430
435
|
}
|
|
431
436
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
432
437
|
return {
|
|
@@ -466,7 +471,7 @@ export async function writeVkAsFields(
|
|
|
466
471
|
const result = await executeBB(pathToBB, 'vk_as_fields', args, log);
|
|
467
472
|
const duration = timer.ms();
|
|
468
473
|
if (result.status == BB_RESULT.SUCCESS) {
|
|
469
|
-
return { status: BB_RESULT.SUCCESS, duration, vkPath: verificationKeyPath };
|
|
474
|
+
return { status: BB_RESULT.SUCCESS, durationMs: duration, vkPath: verificationKeyPath };
|
|
470
475
|
}
|
|
471
476
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
472
477
|
return {
|
|
@@ -508,7 +513,7 @@ export async function writeProofAsFields(
|
|
|
508
513
|
const result = await executeBB(pathToBB, 'proof_as_fields', args, log);
|
|
509
514
|
const duration = timer.ms();
|
|
510
515
|
if (result.status == BB_RESULT.SUCCESS) {
|
|
511
|
-
return { status: BB_RESULT.SUCCESS, duration, proofPath: proofPath };
|
|
516
|
+
return { status: BB_RESULT.SUCCESS, durationMs: duration, proofPath: proofPath };
|
|
512
517
|
}
|
|
513
518
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
514
519
|
return {
|
|
@@ -549,7 +554,7 @@ export async function generateContractForVerificationKey(
|
|
|
549
554
|
const result = await executeBB(pathToBB, 'contract', args, log);
|
|
550
555
|
const duration = timer.ms();
|
|
551
556
|
if (result.status == BB_RESULT.SUCCESS) {
|
|
552
|
-
return { status: BB_RESULT.SUCCESS, duration, contractPath };
|
|
557
|
+
return { status: BB_RESULT.SUCCESS, durationMs: duration, contractPath };
|
|
553
558
|
}
|
|
554
559
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
555
560
|
return {
|
|
@@ -564,7 +569,7 @@ export async function generateContractForVerificationKey(
|
|
|
564
569
|
if (!res) {
|
|
565
570
|
return {
|
|
566
571
|
status: BB_RESULT.ALREADY_PRESENT,
|
|
567
|
-
|
|
572
|
+
durationMs: 0,
|
|
568
573
|
contractPath,
|
|
569
574
|
};
|
|
570
575
|
}
|
|
@@ -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
|
@@ -57,6 +57,7 @@ import {
|
|
|
57
57
|
convertRootRollupOutputsFromWitnessMap,
|
|
58
58
|
} from '@aztec/noir-protocol-circuits-types';
|
|
59
59
|
import { NativeACVMSimulator } from '@aztec/simulator';
|
|
60
|
+
import { Attributes, type TelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
60
61
|
|
|
61
62
|
import { abiEncode } from '@noir-lang/noirc_abi';
|
|
62
63
|
import { type Abi, type WitnessMap } from '@noir-lang/types';
|
|
@@ -78,6 +79,7 @@ import {
|
|
|
78
79
|
writeProofAsFields,
|
|
79
80
|
} from '../bb/execute.js';
|
|
80
81
|
import type { ACVMConfig, BBConfig } from '../config.js';
|
|
82
|
+
import { ProverInstrumentation } from '../instrumentation.js';
|
|
81
83
|
import { PublicKernelArtifactMapping } from '../mappings/mappings.js';
|
|
82
84
|
import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
|
|
83
85
|
import { extractVkData } from '../verification_key/verification_key_data.js';
|
|
@@ -102,9 +104,18 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
102
104
|
ServerProtocolArtifact,
|
|
103
105
|
Promise<VerificationKeyData>
|
|
104
106
|
>();
|
|
105
|
-
constructor(private config: BBProverConfig) {}
|
|
106
107
|
|
|
107
|
-
|
|
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) {
|
|
108
119
|
await fs.access(config.acvmBinaryPath, fs.constants.R_OK);
|
|
109
120
|
await fs.mkdir(config.acvmWorkingDirectory, { recursive: true });
|
|
110
121
|
await fs.access(config.bbBinaryPath, fs.constants.R_OK);
|
|
@@ -112,7 +123,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
112
123
|
logger.info(`Using native BB at ${config.bbBinaryPath} and working directory ${config.bbWorkingDirectory}`);
|
|
113
124
|
logger.info(`Using native ACVM at ${config.acvmBinaryPath} and working directory ${config.acvmWorkingDirectory}`);
|
|
114
125
|
|
|
115
|
-
return new BBNativeRollupProver(config);
|
|
126
|
+
return new BBNativeRollupProver(config, telemetry);
|
|
116
127
|
}
|
|
117
128
|
|
|
118
129
|
/**
|
|
@@ -120,6 +131,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
120
131
|
* @param inputs - Inputs to the circuit.
|
|
121
132
|
* @returns The public inputs of the parity circuit.
|
|
122
133
|
*/
|
|
134
|
+
@trackSpan('BBNativeRollupProver.getBaseParityProof', { [Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-parity' })
|
|
123
135
|
public async getBaseParityProof(inputs: BaseParityInputs): Promise<RootParityInput<typeof RECURSIVE_PROOF_LENGTH>> {
|
|
124
136
|
const { circuitOutput, proof } = await this.createRecursiveProof(
|
|
125
137
|
inputs,
|
|
@@ -141,6 +153,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
141
153
|
* @param inputs - Inputs to the circuit.
|
|
142
154
|
* @returns The public inputs of the parity circuit.
|
|
143
155
|
*/
|
|
156
|
+
@trackSpan('BBNativeRollupProver.getRootParityProof', { [Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-parity' })
|
|
144
157
|
public async getRootParityProof(
|
|
145
158
|
inputs: RootParityInputs,
|
|
146
159
|
): Promise<RootParityInput<typeof NESTED_RECURSIVE_PROOF_LENGTH>> {
|
|
@@ -164,6 +177,9 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
164
177
|
* @param inputs - The inputs to the AVM circuit.
|
|
165
178
|
* @returns The proof.
|
|
166
179
|
*/
|
|
180
|
+
@trackSpan('BBNativeRollupProver.getAvmProof', inputs => ({
|
|
181
|
+
[Attributes.APP_CIRCUIT_NAME]: inputs.functionName,
|
|
182
|
+
}))
|
|
167
183
|
public async getAvmProof(inputs: AvmCircuitInputs): Promise<ProofAndVerificationKey> {
|
|
168
184
|
const proofAndVk = await this.createAvmProof(inputs);
|
|
169
185
|
await this.verifyAvmProof(proofAndVk.proof, proofAndVk.verificationKey);
|
|
@@ -175,6 +191,11 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
175
191
|
* @param kernelRequest - The object encapsulating the request for a proof
|
|
176
192
|
* @returns The requested circuit's public inputs and proof
|
|
177
193
|
*/
|
|
194
|
+
@trackSpan('BBNativeRollupProver.getPublicKernelProof', kernelReq => ({
|
|
195
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: mapProtocolArtifactNameToCircuitName(
|
|
196
|
+
PublicKernelArtifactMapping[kernelReq.type]!.artifact,
|
|
197
|
+
),
|
|
198
|
+
}))
|
|
178
199
|
public async getPublicKernelProof(
|
|
179
200
|
kernelRequest: PublicKernelNonTailRequest,
|
|
180
201
|
): Promise<PublicInputsAndRecursiveProof<PublicKernelCircuitPublicInputs>> {
|
|
@@ -385,11 +406,16 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
385
406
|
const inputWitness = convertInput(input);
|
|
386
407
|
const timer = new Timer();
|
|
387
408
|
const outputWitness = await simulator.simulateCircuit(inputWitness, artifact);
|
|
388
|
-
const witnessGenerationDuration = timer.ms();
|
|
389
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
|
+
|
|
390
416
|
logger.debug(`Generated witness`, {
|
|
391
|
-
circuitName
|
|
392
|
-
duration:
|
|
417
|
+
circuitName,
|
|
418
|
+
duration: timer.ms(),
|
|
393
419
|
inputSize: input.toBuffer().length,
|
|
394
420
|
outputSize: output.toBuffer().length,
|
|
395
421
|
eventName: 'circuit-witness-generation',
|
|
@@ -439,22 +465,24 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
439
465
|
const rawProof = await fs.readFile(`${provingResult.proofPath!}/${PROOF_FILENAME}`);
|
|
440
466
|
|
|
441
467
|
const proof = new Proof(rawProof, vkData.numPublicInputs);
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
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);
|
|
458
486
|
|
|
459
487
|
return { circuitOutput: output, proof };
|
|
460
488
|
};
|
|
@@ -462,12 +490,12 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
462
490
|
}
|
|
463
491
|
|
|
464
492
|
private async generateAvmProofWithBB(input: AvmCircuitInputs, workingDirectory: string): Promise<BBSuccess> {
|
|
465
|
-
logger.
|
|
493
|
+
logger.info(`Proving avm-circuit for ${input.functionName}...`);
|
|
466
494
|
|
|
467
495
|
const provingResult = await generateAvmProof(this.config.bbBinaryPath, workingDirectory, input, logger.verbose);
|
|
468
496
|
|
|
469
497
|
if (provingResult.status === BB_RESULT.FAILURE) {
|
|
470
|
-
logger.error(`Failed to generate proof for
|
|
498
|
+
logger.error(`Failed to generate AVM proof for ${input.functionName}: ${provingResult.reason}`);
|
|
471
499
|
throw new Error(provingResult.reason);
|
|
472
500
|
}
|
|
473
501
|
|
|
@@ -489,19 +517,24 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
489
517
|
const proof = new Proof(rawProof, verificationKey.numPublicInputs);
|
|
490
518
|
|
|
491
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
|
+
|
|
492
526
|
logger.info(
|
|
493
|
-
`Generated proof for ${circuitType} in ${Math.ceil(provingResult.
|
|
494
|
-
proof.buffer.length
|
|
495
|
-
} bytes`,
|
|
527
|
+
`Generated proof for ${circuitType}(${input.functionName}) in ${Math.ceil(provingResult.durationMs)} ms`,
|
|
496
528
|
{
|
|
497
529
|
circuitName: circuitType,
|
|
530
|
+
appCircuitName: input.functionName,
|
|
498
531
|
// does not include reading the proof from disk
|
|
499
|
-
duration: provingResult.
|
|
532
|
+
duration: provingResult.durationMs,
|
|
500
533
|
proofSize: proof.buffer.length,
|
|
501
534
|
eventName: 'circuit-proving',
|
|
502
535
|
inputSize: input.toBuffer().length,
|
|
503
|
-
circuitSize: verificationKey.circuitSize,
|
|
504
|
-
numPublicInputs: verificationKey.numPublicInputs,
|
|
536
|
+
circuitSize: verificationKey.circuitSize, // FIX: wrong in VK
|
|
537
|
+
numPublicInputs: verificationKey.numPublicInputs, // FIX: wrong in VK
|
|
505
538
|
} satisfies CircuitProvingStats,
|
|
506
539
|
);
|
|
507
540
|
|
|
@@ -540,14 +573,19 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
540
573
|
// Read the proof as fields
|
|
541
574
|
const proof = await this.readProofAsFields(provingResult.proofPath!, circuitType, proofLength);
|
|
542
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);
|
|
543
581
|
logger.info(
|
|
544
|
-
`Generated proof for ${circuitType} in ${Math.ceil(provingResult.
|
|
582
|
+
`Generated proof for ${circuitType} in ${Math.ceil(provingResult.durationMs)} ms, size: ${
|
|
545
583
|
proof.proof.length
|
|
546
584
|
} fields`,
|
|
547
585
|
{
|
|
548
|
-
circuitName
|
|
586
|
+
circuitName,
|
|
549
587
|
circuitSize: vkData.circuitSize,
|
|
550
|
-
duration: provingResult.
|
|
588
|
+
duration: provingResult.durationMs,
|
|
551
589
|
inputSize: output.toBuffer().length,
|
|
552
590
|
proofSize: proof.binaryProof.buffer.length,
|
|
553
591
|
eventName: 'circuit-proving',
|
|
@@ -594,7 +632,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
594
632
|
await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes);
|
|
595
633
|
|
|
596
634
|
const logFunction = (message: string) => {
|
|
597
|
-
logger.
|
|
635
|
+
logger.verbose(`BB out - ${message}`);
|
|
598
636
|
};
|
|
599
637
|
|
|
600
638
|
const result = await verificationFunction(
|
|
@@ -609,7 +647,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
609
647
|
throw new Error(errorMessage);
|
|
610
648
|
}
|
|
611
649
|
|
|
612
|
-
logger.
|
|
650
|
+
logger.info(`Successfully verified proof from key in ${result.durationMs} ms`);
|
|
613
651
|
};
|
|
614
652
|
|
|
615
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,
|