@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/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
- duration: number;
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
- duration: 0,
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, 'avm_bytecode.bin');
280
- const calldataPath = join(workingDirectory, 'avm_calldata.bin');
281
- const publicInputsPath = join(workingDirectory, 'avm_public_inputs.bin');
282
- const avmHintsPath = join(workingDirectory, 'avm_hints.bin');
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
- duration: 0,
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.duration} ms`);
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 = `${directory}/witness.gz`;
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
- this.log.info(`Proving ${circuitType} circuit...`);
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.duration,
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.duration,
361
+ duration: provingResult.durationMs,
362
362
  eventName: 'circuit-proving',
363
363
  inputSize: compressedBincodedWitness.length,
364
364
  proofSize: proof.binaryProof.buffer.length,
@@ -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
- static async new(config: BBProverConfig) {
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: mapProtocolArtifactNameToCircuitName(circuitType),
392
- duration: witnessGenerationDuration,
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
- logger.info(
443
- `Generated proof for ${circuitType} in ${Math.ceil(provingResult.duration)} ms, size: ${
444
- proof.buffer.length
445
- } bytes`,
446
- {
447
- circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
448
- // does not include reading the proof from disk
449
- duration: provingResult.duration,
450
- proofSize: proof.buffer.length,
451
- eventName: 'circuit-proving',
452
- // circuitOutput is the partial witness that became the input to the proof
453
- inputSize: output.toBuffer().length,
454
- circuitSize: vkData.circuitSize,
455
- numPublicInputs: vkData.numPublicInputs,
456
- } satisfies CircuitProvingStats,
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.debug(`Proving avm-circuit...`);
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 avm-circuit: ${provingResult.reason}`);
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.duration)} ms, size: ${
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.duration,
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.duration)} ms, size: ${
582
+ `Generated proof for ${circuitType} in ${Math.ceil(provingResult.durationMs)} ms, size: ${
545
583
  proof.proof.length
546
584
  } fields`,
547
585
  {
548
- circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
586
+ circuitName,
549
587
  circuitSize: vkData.circuitSize,
550
- duration: provingResult.duration,
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.debug(`BB out - ${message}`);
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.debug(`Successfully verified proof from key in ${result.duration} ms`);
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 function mapPublicKernelToCircuitName(kernelType: PublicKernelRequest['type']): CircuitName {
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,