@aztec/bb-prover 0.47.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/bb/execute.ts CHANGED
@@ -621,6 +621,46 @@ export async function verifyAvmProof(
621
621
  return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'avm_verify', log);
622
622
  }
623
623
 
624
+ /**
625
+ * Verifies a ClientIvcProof
626
+ * TODO(#7370) The verification keys should be supplied separately
627
+ * @param pathToBB - The full path to the bb binary
628
+ * @param targetPath - The path to the folder with the proof, accumulator, and verification keys
629
+ * @param log - A logging function
630
+ * @returns An object containing a result indication and duration taken
631
+ */
632
+ export async function verifyClientIvcProof(
633
+ pathToBB: string,
634
+ targetPath: string,
635
+ log: LogFn,
636
+ ): Promise<BBFailure | BBSuccess> {
637
+ const binaryPresent = await fs
638
+ .access(pathToBB, fs.constants.R_OK)
639
+ .then(_ => true)
640
+ .catch(_ => false);
641
+ if (!binaryPresent) {
642
+ return { status: BB_RESULT.FAILURE, reason: `Failed to find bb binary at ${pathToBB}` };
643
+ }
644
+
645
+ try {
646
+ const args = ['-o', targetPath];
647
+ const timer = new Timer();
648
+ const command = 'verify_client_ivc';
649
+ const result = await executeBB(pathToBB, command, args, log);
650
+ const duration = timer.ms();
651
+ if (result.status == BB_RESULT.SUCCESS) {
652
+ return { status: BB_RESULT.SUCCESS, durationMs: duration };
653
+ }
654
+ // Not a great error message here but it is difficult to decipher what comes from bb
655
+ return {
656
+ status: BB_RESULT.FAILURE,
657
+ reason: `Failed to verify proof. Exit code ${result.exitCode}. Signal ${result.signal}.`,
658
+ };
659
+ } catch (error) {
660
+ return { status: BB_RESULT.FAILURE, reason: `${error}` };
661
+ }
662
+ }
663
+
624
664
  /**
625
665
  * Used for verifying proofs with BB
626
666
  * @param pathToBB - The full path to the bb binary
@@ -8,6 +8,7 @@ import {
8
8
  type TelemetryClient,
9
9
  type Tracer,
10
10
  ValueType,
11
+ millisecondBuckets,
11
12
  } from '@aztec/telemetry-client';
12
13
 
13
14
  /**
@@ -15,8 +16,8 @@ import {
15
16
  */
16
17
  export class ProverInstrumentation {
17
18
  private simulationDuration: Histogram;
18
- private witGenDuration: Gauge;
19
- private provingDuration: Gauge;
19
+ private witGenDuration: Histogram;
20
+ private provingDuration: Histogram;
20
21
 
21
22
  private witGenInputSize: Gauge;
22
23
  private witGenOutputSize: Gauge;
@@ -33,25 +34,29 @@ export class ProverInstrumentation {
33
34
 
34
35
  this.simulationDuration = meter.createHistogram(Metrics.CIRCUIT_SIMULATION_DURATION, {
35
36
  description: 'Records how long it takes to simulate a circuit',
36
- unit: 's',
37
- valueType: ValueType.DOUBLE,
37
+ unit: 'ms',
38
+ valueType: ValueType.INT,
38
39
  advice: {
39
- explicitBucketBoundaries: [0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60],
40
+ explicitBucketBoundaries: millisecondBuckets(1), // 10ms -> ~327s
40
41
  },
41
42
  });
42
43
 
43
- this.witGenDuration = meter.createGauge(Metrics.CIRCUIT_WITNESS_GEN_DURATION, {
44
+ this.witGenDuration = meter.createHistogram(Metrics.CIRCUIT_WITNESS_GEN_DURATION, {
44
45
  description: 'Records how long it takes to generate the partial witness for a circuit',
45
- unit: 's',
46
- valueType: ValueType.DOUBLE,
46
+ unit: 'ms',
47
+ valueType: ValueType.INT,
48
+ advice: {
49
+ explicitBucketBoundaries: millisecondBuckets(1),
50
+ },
47
51
  });
48
52
 
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
+ this.provingDuration = meter.createHistogram(Metrics.CIRCUIT_PROVING_DURATION, {
54
+ unit: 'ms',
53
55
  description: 'Records how long it takes to prove a circuit',
54
- valueType: ValueType.DOUBLE,
56
+ valueType: ValueType.INT,
57
+ advice: {
58
+ explicitBucketBoundaries: millisecondBuckets(2), // 100ms -> 54 minutes
59
+ },
55
60
  });
56
61
 
57
62
  this.witGenInputSize = meter.createGauge(Metrics.CIRCUIT_WITNESS_GEN_INPUT_SIZE, {
@@ -87,15 +92,15 @@ export class ProverInstrumentation {
87
92
  * Records the duration of a circuit operation.
88
93
  * @param metric - The metric to record
89
94
  * @param circuitName - The name of the circuit
90
- * @param timerOrS - The duration
95
+ * @param timerOrMS - The duration
91
96
  */
92
97
  recordDuration(
93
98
  metric: 'simulationDuration' | 'witGenDuration' | 'provingDuration',
94
- circuitName: CircuitName,
95
- timerOrS: Timer | number,
99
+ circuitName: CircuitName | 'tubeCircuit',
100
+ timerOrMS: Timer | number,
96
101
  ) {
97
- const s = typeof timerOrS === 'number' ? timerOrS : timerOrS.s();
98
- this[metric].record(s, {
102
+ const ms = typeof timerOrMS === 'number' ? timerOrMS : timerOrMS.ms();
103
+ this[metric].record(Math.ceil(ms), {
99
104
  [Attributes.PROTOCOL_CIRCUIT_NAME]: circuitName,
100
105
  [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
101
106
  });
@@ -105,11 +110,11 @@ export class ProverInstrumentation {
105
110
  * Records the duration of an AVM circuit operation.
106
111
  * @param metric - The metric to record
107
112
  * @param appCircuitName - The name of the function circuit (should be a `contract:function` string)
108
- * @param timerOrS - The duration
113
+ * @param timerOrMS - The duration
109
114
  */
110
- recordAvmDuration(metric: 'witGenDuration' | 'provingDuration', appCircuitName: string, timerOrS: Timer | number) {
111
- const s = typeof timerOrS === 'number' ? timerOrS : timerOrS.s();
112
- this[metric].record(s, {
115
+ recordAvmDuration(metric: 'witGenDuration' | 'provingDuration', appCircuitName: string, timerOrMS: Timer | number) {
116
+ const ms = typeof timerOrMS === 'number' ? timerOrMS : timerOrMS.s();
117
+ this[metric].record(Math.ceil(ms), {
113
118
  [Attributes.APP_CIRCUIT_NAME]: appCircuitName,
114
119
  });
115
120
  }
@@ -122,7 +127,7 @@ export class ProverInstrumentation {
122
127
  */
123
128
  recordSize(
124
129
  metric: 'witGenInputSize' | 'witGenOutputSize' | 'proofSize' | 'circuitSize' | 'circuitPublicInputCount',
125
- circuitName: CircuitName,
130
+ circuitName: CircuitName | 'tubeCircuit',
126
131
  size: number,
127
132
  ) {
128
133
  this[metric].record(Math.ceil(size), {
@@ -5,6 +5,7 @@ import {
5
5
  } from '@aztec/circuit-types';
6
6
  import { type CircuitSimulationStats, type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats';
7
7
  import {
8
+ AGGREGATION_OBJECT_LENGTH,
8
9
  ClientIvcProof,
9
10
  Fr,
10
11
  type PrivateCircuitPublicInputs,
@@ -350,10 +351,8 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
350
351
  ]);
351
352
  const json = JSON.parse(proofString);
352
353
  const fields = json.map(Fr.fromString);
353
- const numPublicInputs = vkData.numPublicInputs;
354
- // const numPublicInputs =
355
- // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation
356
- // circuitType === 'App' ? vkData.numPublicInputs : vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
354
+ const numPublicInputs = vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
355
+
357
356
  const fieldsWithoutPublicInputs = fields.slice(numPublicInputs);
358
357
  this.log.info(
359
358
  `Circuit type: ${circuitType}, complete proof length: ${fields.length}, without public inputs: ${fieldsWithoutPublicInputs.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}, is recursive: ${vkData.isRecursive}, raw length: ${binaryProof.length}`,
@@ -9,6 +9,7 @@ import {
9
9
  } from '@aztec/circuit-types';
10
10
  import { type CircuitProvingStats, type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats';
11
11
  import {
12
+ AGGREGATION_OBJECT_LENGTH,
12
13
  type AvmCircuitInputs,
13
14
  type BaseOrMergeRollupPublicInputs,
14
15
  type BaseParityInputs,
@@ -30,7 +31,7 @@ import {
30
31
  type RootRollupInputs,
31
32
  type RootRollupPublicInputs,
32
33
  TUBE_PROOF_LENGTH,
33
- TubeInputs,
34
+ type TubeInputs,
34
35
  type VerificationKeyAsFields,
35
36
  type VerificationKeyData,
36
37
  makeRecursiveProofFromBinary,
@@ -225,16 +226,6 @@ export class BBNativeRollupProver implements ServerCircuitProver {
225
226
  kernelRequest.inputs.previousKernel.vk,
226
227
  );
227
228
 
228
- // PUBLIC KERNEL: kernel request should be nonempty at start of public kernel proving but it is not
229
- // TODO(#7369): We should properly enqueue the tube in the public kernel lifetime
230
- if (!kernelRequest.inputs.previousKernel.clientIvcProof.isEmpty()) {
231
- const { tubeVK, tubeProof } = await this.getTubeProof(
232
- new TubeInputs(kernelRequest.inputs.previousKernel.clientIvcProof),
233
- );
234
- kernelRequest.inputs.previousKernel.vk = tubeVK;
235
- kernelRequest.inputs.previousKernel.proof = tubeProof;
236
- }
237
-
238
229
  await this.verifyWithKey(
239
230
  kernelRequest.inputs.previousKernel.vk,
240
231
  kernelRequest.inputs.previousKernel.proof.binaryProof,
@@ -288,9 +279,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
288
279
  ): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>> {
289
280
  // We may need to convert the recursive proof into fields format
290
281
  logger.debug(`kernel Data proof: ${baseRollupInput.kernelData.proof}`);
291
- logger.info(`in getBaseRollupProof`);
292
- logger.info(`Number of public inputs in baseRollupInput: ${baseRollupInput.kernelData.vk.numPublicInputs}`);
293
- logger.info(`Number of public inputs ${baseRollupInput.kernelData.publicInputs}`);
282
+ logger.debug(`Number of public inputs in baseRollupInput: ${baseRollupInput.kernelData.vk.numPublicInputs}`);
294
283
  baseRollupInput.kernelData.proof = await this.ensureValidProof(
295
284
  baseRollupInput.kernelData.proof,
296
285
  'BaseRollupArtifact',
@@ -476,7 +465,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
476
465
  this.instrumentation.recordSize('witGenInputSize', circuitName, input.toBuffer().length);
477
466
  this.instrumentation.recordSize('witGenOutputSize', circuitName, output.toBuffer().length);
478
467
 
479
- logger.debug(`Generated witness`, {
468
+ logger.info(`Generated witness`, {
480
469
  circuitName,
481
470
  duration: timer.ms(),
482
471
  inputSize: input.toBuffer().length,
@@ -530,7 +519,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
530
519
  const proof = new Proof(rawProof, vkData.numPublicInputs);
531
520
  const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
532
521
 
533
- this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs / 1000);
522
+ this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs);
534
523
  this.instrumentation.recordSize('proofSize', circuitName, proof.buffer.length);
535
524
  this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs);
536
525
  this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize);
@@ -633,6 +622,12 @@ export class BBNativeRollupProver implements ServerCircuitProver {
633
622
  // Read the proof as fields
634
623
  const tubeVK = await extractVkData(provingResult.vkPath!);
635
624
  const tubeProof = await this.readTubeProofAsFields(provingResult.proofPath!, tubeVK, TUBE_PROOF_LENGTH);
625
+
626
+ this.instrumentation.recordDuration('provingDuration', 'tubeCircuit', provingResult.durationMs);
627
+ this.instrumentation.recordSize('proofSize', 'tubeCircuit', tubeProof.binaryProof.buffer.length);
628
+ this.instrumentation.recordSize('circuitPublicInputCount', 'tubeCircuit', tubeVK.numPublicInputs);
629
+ this.instrumentation.recordSize('circuitSize', 'tubeCircuit', tubeVK.circuitSize);
630
+
636
631
  // Sanity check the tube proof (can be removed later)
637
632
  await this.verifyWithKey(tubeVK, tubeProof.binaryProof);
638
633
 
@@ -680,7 +675,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
680
675
  const proof = await this.readProofAsFields(provingResult.proofPath!, circuitType, proofLength);
681
676
 
682
677
  const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
683
- this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs / 1000);
678
+ this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs);
684
679
  this.instrumentation.recordSize('proofSize', circuitName, proof.binaryProof.buffer.length);
685
680
  this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs);
686
681
  this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize);
@@ -787,8 +782,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
787
782
  }
788
783
 
789
784
  const operation = async (bbWorkingDirectory: string) => {
790
- // const numPublicInputs = vk.numPublicInputs;
791
- const numPublicInputs = vk.numPublicInputs; // - AGGREGATION_OBJECT_LENGTH;
785
+ const numPublicInputs = vk.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
792
786
  const proofFullFilename = path.join(bbWorkingDirectory, PROOF_FILENAME);
793
787
  const vkFullFilename = path.join(bbWorkingDirectory, VK_FILENAME);
794
788
 
@@ -900,11 +894,8 @@ export class BBNativeRollupProver implements ServerCircuitProver {
900
894
  if (!vkData) {
901
895
  throw new Error(`Invalid verification key for ${circuitType}`);
902
896
  }
903
- const numPublicInputs = vkData.numPublicInputs;
904
- // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation
905
- // const numPublicInputs = CIRCUITS_WITHOUT_AGGREGATION.has(circuitType)
906
- // ? vkData.numPublicInputs
907
- // : vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
897
+ const numPublicInputs = vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
898
+
908
899
  const fieldsWithoutPublicInputs = json
909
900
  .slice(0, 3)
910
901
  .map(Fr.fromString)
@@ -949,7 +940,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
949
940
 
950
941
  const json = JSON.parse(proofString);
951
942
 
952
- const numPublicInputs = vkData.numPublicInputs;
943
+ const numPublicInputs = vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
953
944
  if (numPublicInputs === 0) {
954
945
  throw new Error(`Tube proof should have public inputs (e.g. the number of public inputs from PrivateKernelTail)`);
955
946
  }
@@ -33,6 +33,7 @@ import {
33
33
  makeRecursiveProof,
34
34
  } from '@aztec/circuits.js';
35
35
  import { createDebugLogger } from '@aztec/foundation/log';
36
+ import { sleep } from '@aztec/foundation/sleep';
36
37
  import { Timer } from '@aztec/foundation/timer';
37
38
  import {
38
39
  ProtocolCircuitVkIndexes,
@@ -70,11 +71,12 @@ import { mapPublicKernelToCircuitName } from '../stats.js';
70
71
  export class TestCircuitProver implements ServerCircuitProver {
71
72
  private wasmSimulator = new WASMSimulator();
72
73
  private instrumentation: ProverInstrumentation;
74
+ private logger = createDebugLogger('aztec:test-prover');
73
75
 
74
76
  constructor(
75
77
  telemetry: TelemetryClient,
76
78
  private simulationProvider?: SimulationProvider,
77
- private logger = createDebugLogger('aztec:test-prover'),
79
+ private opts: { proverTestDelayMs: number } = { proverTestDelayMs: 0 },
78
80
  ) {
79
81
  this.instrumentation = new ProverInstrumentation(telemetry, 'TestCircuitProver');
80
82
  }
@@ -103,7 +105,7 @@ export class TestCircuitProver implements ServerCircuitProver {
103
105
  SimulatedServerCircuitArtifacts.PrivateKernelEmptyArtifact,
104
106
  );
105
107
  const result = convertSimulatedPrivateKernelEmptyOutputsFromWitnessMap(witness);
106
-
108
+ await this.delay();
107
109
  return makePublicInputsAndRecursiveProof(
108
110
  result,
109
111
  makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH),
@@ -131,7 +133,7 @@ export class TestCircuitProver implements ServerCircuitProver {
131
133
  SimulatedServerCircuitArtifacts.PrivateKernelEmptyArtifact,
132
134
  );
133
135
  const result = convertPrivateKernelEmptyOutputsFromWitnessMap(witness);
134
-
136
+ await this.delay();
135
137
  return makePublicInputsAndRecursiveProof(
136
138
  result,
137
139
  makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH),
@@ -172,7 +174,7 @@ export class TestCircuitProver implements ServerCircuitProver {
172
174
  result.toBuffer().length,
173
175
  this.logger,
174
176
  );
175
-
177
+ await this.delay();
176
178
  return Promise.resolve(rootParityInput);
177
179
  }
178
180
 
@@ -211,7 +213,7 @@ export class TestCircuitProver implements ServerCircuitProver {
211
213
  result.toBuffer().length,
212
214
  this.logger,
213
215
  );
214
-
216
+ await this.delay();
215
217
  return Promise.resolve(rootParityInput);
216
218
  }
217
219
 
@@ -243,6 +245,7 @@ export class TestCircuitProver implements ServerCircuitProver {
243
245
  result.toBuffer().length,
244
246
  this.logger,
245
247
  );
248
+ await this.delay();
246
249
  return makePublicInputsAndRecursiveProof(
247
250
  result,
248
251
  makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH),
@@ -250,13 +253,14 @@ export class TestCircuitProver implements ServerCircuitProver {
250
253
  );
251
254
  }
252
255
 
253
- public getTubeProof(
256
+ public async getTubeProof(
254
257
  _tubeInput: TubeInputs,
255
258
  ): Promise<{ tubeVK: VerificationKeyData; tubeProof: RecursiveProof<typeof TUBE_PROOF_LENGTH> }> {
256
- return Promise.resolve({
259
+ await this.delay();
260
+ return {
257
261
  tubeVK: VerificationKeyData.makeFake(),
258
262
  tubeProof: makeEmptyRecursiveProof(TUBE_PROOF_LENGTH),
259
- });
263
+ };
260
264
  }
261
265
 
262
266
  /**
@@ -287,6 +291,7 @@ export class TestCircuitProver implements ServerCircuitProver {
287
291
  result.toBuffer().length,
288
292
  this.logger,
289
293
  );
294
+ await this.delay();
290
295
  return makePublicInputsAndRecursiveProof(
291
296
  result,
292
297
  makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH),
@@ -322,6 +327,7 @@ export class TestCircuitProver implements ServerCircuitProver {
322
327
  result.toBuffer().length,
323
328
  this.logger,
324
329
  );
330
+ await this.delay();
325
331
  return makePublicInputsAndRecursiveProof(
326
332
  result,
327
333
  makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH),
@@ -355,7 +361,7 @@ export class TestCircuitProver implements ServerCircuitProver {
355
361
  result.toBuffer().length,
356
362
  this.logger,
357
363
  );
358
-
364
+ await this.delay();
359
365
  return makePublicInputsAndRecursiveProof(
360
366
  result,
361
367
  makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH),
@@ -384,7 +390,7 @@ export class TestCircuitProver implements ServerCircuitProver {
384
390
  result.toBuffer().length,
385
391
  this.logger,
386
392
  );
387
-
393
+ await this.delay();
388
394
  return makePublicInputsAndRecursiveProof(
389
395
  result,
390
396
  makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH),
@@ -392,11 +398,18 @@ export class TestCircuitProver implements ServerCircuitProver {
392
398
  );
393
399
  }
394
400
 
395
- getAvmProof(_inputs: AvmCircuitInputs): Promise<ProofAndVerificationKey> {
401
+ public async getAvmProof(_inputs: AvmCircuitInputs): Promise<ProofAndVerificationKey> {
396
402
  // We can't simulate the AVM because we don't have enough context to do so (e.g., DBs).
397
403
  // We just return an empty proof and VK data.
398
404
  this.logger.debug('Skipping AVM simulation in TestCircuitProver.');
399
- return Promise.resolve({ proof: makeEmptyProof(), verificationKey: VerificationKeyData.makeFake() });
405
+ await this.delay();
406
+ return { proof: makeEmptyProof(), verificationKey: VerificationKeyData.makeFake() };
407
+ }
408
+
409
+ private async delay(): Promise<void> {
410
+ if (this.opts.proverTestDelayMs > 0) {
411
+ await sleep(this.opts.proverTestDelayMs);
412
+ }
400
413
  }
401
414
 
402
415
  // Not implemented for test circuits
@@ -1,4 +1,5 @@
1
1
  import { type ClientProtocolCircuitVerifier, Tx } from '@aztec/circuit-types';
2
+ import { type CircuitVerificationStats } from '@aztec/circuit-types/stats';
2
3
  import { type Proof, type VerificationKeyData } from '@aztec/circuits.js';
3
4
  import { runInDirectory } from '@aztec/foundation/fs';
4
5
  import { type DebugLogger, type LogFn, createDebugLogger } from '@aztec/foundation/log';
@@ -17,9 +18,11 @@ import {
17
18
  VK_FILENAME,
18
19
  generateContractForCircuit,
19
20
  generateKeyForNoirCircuit,
21
+ verifyClientIvcProof,
20
22
  verifyProof,
21
23
  } from '../bb/execute.js';
22
24
  import { type BBConfig } from '../config.js';
25
+ import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
23
26
  import { extractVkData } from '../verification_key/verification_key_data.js';
24
27
 
25
28
  export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
@@ -106,7 +109,12 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
106
109
  throw new Error(errorMessage);
107
110
  }
108
111
 
109
- this.logger.debug(`${circuit} verification successful`);
112
+ this.logger.debug(`${circuit} verification successful`, {
113
+ circuitName: mapProtocolArtifactNameToCircuitName(circuit),
114
+ duration: result.durationMs,
115
+ eventName: 'circuit-verification',
116
+ proofType: 'ultra-honk',
117
+ } satisfies CircuitVerificationStats);
110
118
  };
111
119
  await runInDirectory(this.config.bbWorkingDirectory, operation);
112
120
  }
@@ -128,19 +136,43 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
128
136
  return fs.readFile(result.contractPath!, 'utf-8');
129
137
  }
130
138
 
131
- verifyProof(tx: Tx): Promise<boolean> {
132
- const expectedCircuit: ClientProtocolArtifact = tx.data.forPublic
133
- ? 'PrivateKernelTailToPublicArtifact'
134
- : 'PrivateKernelTailArtifact';
135
-
139
+ public async verifyProof(tx: Tx): Promise<boolean> {
136
140
  try {
137
- // TODO(https://github.com/AztecProtocol/barretenberg/issues/1050) we need a proper verify flow for clientIvcProof
138
- // For now we handle only the trivial blank data case
139
- // await this.verifyProofForCircuit(expectedCircuit, proof);
140
- return Promise.resolve(!tx.clientIvcProof.isEmpty());
141
+ // TODO(#7370) The verification keys should be supplied separately and based on the expectedCircuit
142
+ // rather than read from the tx object itself. We also need the vks for the translator and ecc, which
143
+ // are not being saved along the other vks yet. Reuse the 'verifyProofForCircuit' method above once
144
+ // we have all the verification keys available.
145
+ const expectedCircuit: ClientProtocolArtifact = tx.data.forPublic
146
+ ? 'PrivateKernelTailToPublicArtifact'
147
+ : 'PrivateKernelTailArtifact';
148
+ const circuit = 'ClientIVC';
149
+
150
+ // Block below is almost copy-pasted from verifyProofForCircuit
151
+ const operation = async (bbWorkingDirectory: string) => {
152
+ const logFunction = (message: string) => {
153
+ this.logger.debug(`${circuit} BB out - ${message}`);
154
+ };
155
+
156
+ await tx.clientIvcProof.writeToOutputDirectory(bbWorkingDirectory);
157
+ const result = await verifyClientIvcProof(this.config.bbBinaryPath, bbWorkingDirectory, logFunction);
158
+
159
+ if (result.status === BB_RESULT.FAILURE) {
160
+ const errorMessage = `Failed to verify ${circuit} proof!`;
161
+ throw new Error(errorMessage);
162
+ }
163
+
164
+ this.logger.debug(`${circuit} verification successful`, {
165
+ circuitName: mapProtocolArtifactNameToCircuitName(expectedCircuit),
166
+ duration: result.durationMs,
167
+ eventName: 'circuit-verification',
168
+ proofType: 'client-ivc',
169
+ } satisfies CircuitVerificationStats);
170
+ };
171
+ await runInDirectory(this.config.bbWorkingDirectory, operation);
172
+ return true;
141
173
  } catch (err) {
142
- this.logger.warn(`Failed to verify ${expectedCircuit} proof for tx ${Tx.getHash(tx)}: ${String(err)}`);
143
- return Promise.resolve(false);
174
+ this.logger.warn(`Failed to verify ClientIVC proof for tx ${Tx.getHash(tx)}: ${String(err)}`);
175
+ return false;
144
176
  }
145
177
  }
146
178
  }