@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.
@@ -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,
@@ -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
- 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) {
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 ${PublicKernelType[kernelRequest.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: mapProtocolArtifactNameToCircuitName(circuitType),
393
- duration: witnessGenerationDuration,
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
- logger.info(
444
- `Generated proof for ${circuitType} in ${Math.ceil(provingResult.duration)} ms, size: ${
445
- proof.buffer.length
446
- } bytes`,
447
- {
448
- circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
449
- // does not include reading the proof from disk
450
- duration: provingResult.duration,
451
- proofSize: proof.buffer.length,
452
- eventName: 'circuit-proving',
453
- // circuitOutput is the partial witness that became the input to the proof
454
- inputSize: output.toBuffer().length,
455
- circuitSize: vkData.circuitSize,
456
- numPublicInputs: vkData.numPublicInputs,
457
- } satisfies CircuitProvingStats,
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.debug(`Proving avm-circuit...`);
493
+ logger.info(`Proving avm-circuit for ${input.functionName}...`);
467
494
 
468
- const provingResult = await generateAvmProof(this.config.bbBinaryPath, workingDirectory, input, logger.debug);
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 avm-circuit: ${provingResult.reason}`);
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.duration)} ms, size: ${
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.duration,
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.duration)} ms, size: ${
582
+ `Generated proof for ${circuitType} in ${Math.ceil(provingResult.durationMs)} ms, size: ${
542
583
  proof.proof.length
543
584
  } fields`,
544
585
  {
545
- circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
586
+ circuitName,
546
587
  circuitSize: vkData.circuitSize,
547
- duration: provingResult.duration,
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.duration} ms`);
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 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,
@@ -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 ${PublicKernelType[kernelRequest.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
- mapPublicKernelToCircuitName(kernelRequest.type),
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(),