@aztec/bb-prover 0.47.1 → 0.49.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/bb-prover",
3
- "version": "0.47.1",
3
+ "version": "0.49.2",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js"
@@ -59,12 +59,12 @@
59
59
  ]
60
60
  },
61
61
  "dependencies": {
62
- "@aztec/circuit-types": "0.47.1",
63
- "@aztec/circuits.js": "0.47.1",
64
- "@aztec/foundation": "0.47.1",
65
- "@aztec/noir-protocol-circuits-types": "0.47.1",
66
- "@aztec/simulator": "0.47.1",
67
- "@aztec/telemetry-client": "0.47.1",
62
+ "@aztec/circuit-types": "0.49.2",
63
+ "@aztec/circuits.js": "0.49.2",
64
+ "@aztec/foundation": "0.49.2",
65
+ "@aztec/noir-protocol-circuits-types": "0.49.2",
66
+ "@aztec/simulator": "0.49.2",
67
+ "@aztec/telemetry-client": "0.49.2",
68
68
  "@msgpack/msgpack": "^3.0.0-beta2",
69
69
  "@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi",
70
70
  "@noir-lang/types": "portal:../../noir/packages/types",
package/src/bb/execute.ts CHANGED
@@ -811,7 +811,7 @@ export async function generateContractForVerificationKey(
811
811
  try {
812
812
  const args = ['-k', vkFilePath, '-o', contractPath, '-v'];
813
813
  const timer = new Timer();
814
- const result = await executeBB(pathToBB, 'contract', args, log);
814
+ const result = await executeBB(pathToBB, 'contract_ultra_honk', args, log);
815
815
  const duration = timer.ms();
816
816
  if (result.status == BB_RESULT.SUCCESS) {
817
817
  return { status: BB_RESULT.SUCCESS, durationMs: duration, contractPath };
package/src/config.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export interface BBConfig {
2
2
  bbBinaryPath: string;
3
3
  bbWorkingDirectory: string;
4
+ /** Whether to skip tmp dir cleanup for debugging purposes */
5
+ bbSkipCleanup?: boolean;
4
6
  }
5
7
 
6
8
  export interface ACVMConfig {
package/src/index.ts CHANGED
@@ -2,3 +2,4 @@ export * from './prover/index.js';
2
2
  export * from './test/index.js';
3
3
  export * from './verifier/index.js';
4
4
  export * from './config.js';
5
+ export * from './bb/execute.js';
@@ -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), {
@@ -76,6 +76,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
76
76
  constructor(
77
77
  private bbBinaryPath: string,
78
78
  private bbWorkingDirectory: string,
79
+ private skipCleanup: boolean,
79
80
  private log = createDebugLogger('aztec:bb-native-prover'),
80
81
  ) {}
81
82
 
@@ -119,7 +120,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
119
120
  const operation = async (directory: string) => {
120
121
  return await this._createClientIvcProof(directory, acirs, witnessStack);
121
122
  };
122
- return await runInDirectory(this.bbWorkingDirectory, operation);
123
+ return await this.runInDirectory(operation);
123
124
  }
124
125
 
125
126
  public getSiloedCommitments(publicInputs: PrivateCircuitPublicInputs) {
@@ -189,7 +190,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
189
190
  return await this.computeVerificationKey(directory, bytecode, 'App', appCircuitName);
190
191
  };
191
192
 
192
- return await runInDirectory(this.bbWorkingDirectory, operation);
193
+ return await this.runInDirectory(operation);
193
194
  }
194
195
 
195
196
  /**
@@ -229,7 +230,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
229
230
  await fs.writeFile(verificationKeyPath, verificationKey);
230
231
  return await verifyProof(this.bbBinaryPath, proofFileName, verificationKeyPath!, logFunction);
231
232
  };
232
- return await runInDirectory(this.bbWorkingDirectory, operation);
233
+ return await this.runInDirectory(operation);
233
234
  }
234
235
 
235
236
  /**
@@ -270,7 +271,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
270
271
  } satisfies CircuitWitnessGenerationStats);
271
272
 
272
273
  // TODO(#7410) we dont need to generate vk's for these circuits, they are in the vk tree
273
- const { verificationKey } = await runInDirectory(this.bbWorkingDirectory, dir =>
274
+ const { verificationKey } = await this.runInDirectory(dir =>
274
275
  this.computeVerificationKey(dir, Buffer.from(compiledCircuit.bytecode, 'base64'), circuitType),
275
276
  );
276
277
  const kernelOutput: PrivateKernelSimulateOutput<O> = {
@@ -352,7 +353,6 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
352
353
  const json = JSON.parse(proofString);
353
354
  const fields = json.map(Fr.fromString);
354
355
  const numPublicInputs = vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
355
-
356
356
  const fieldsWithoutPublicInputs = fields.slice(numPublicInputs);
357
357
  this.log.info(
358
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}`,
@@ -364,4 +364,17 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
364
364
  );
365
365
  return proof;
366
366
  }
367
+
368
+ private runInDirectory<T>(fn: (dir: string) => Promise<T>) {
369
+ const log = this.log;
370
+ return runInDirectory(
371
+ this.bbWorkingDirectory,
372
+ (dir: string) =>
373
+ fn(dir).catch(err => {
374
+ log.error(`Error running operation at ${dir}: ${err}`);
375
+ throw err;
376
+ }),
377
+ this.skipCleanup,
378
+ );
379
+ }
367
380
  }
@@ -31,7 +31,7 @@ import {
31
31
  type RootRollupInputs,
32
32
  type RootRollupPublicInputs,
33
33
  TUBE_PROOF_LENGTH,
34
- TubeInputs,
34
+ type TubeInputs,
35
35
  type VerificationKeyAsFields,
36
36
  type VerificationKeyData,
37
37
  makeRecursiveProofFromBinary,
@@ -226,16 +226,6 @@ export class BBNativeRollupProver implements ServerCircuitProver {
226
226
  kernelRequest.inputs.previousKernel.vk,
227
227
  );
228
228
 
229
- // PUBLIC KERNEL: kernel request should be nonempty at start of public kernel proving but it is not
230
- // TODO(#7369): We should properly enqueue the tube in the public kernel lifetime
231
- if (!kernelRequest.inputs.previousKernel.clientIvcProof.isEmpty()) {
232
- const { tubeVK, tubeProof } = await this.getTubeProof(
233
- new TubeInputs(kernelRequest.inputs.previousKernel.clientIvcProof),
234
- );
235
- kernelRequest.inputs.previousKernel.vk = tubeVK;
236
- kernelRequest.inputs.previousKernel.proof = tubeProof;
237
- }
238
-
239
229
  await this.verifyWithKey(
240
230
  kernelRequest.inputs.previousKernel.vk,
241
231
  kernelRequest.inputs.previousKernel.proof.binaryProof,
@@ -289,9 +279,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
289
279
  ): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>> {
290
280
  // We may need to convert the recursive proof into fields format
291
281
  logger.debug(`kernel Data proof: ${baseRollupInput.kernelData.proof}`);
292
- logger.info(`in getBaseRollupProof`);
293
- logger.info(`Number of public inputs in baseRollupInput: ${baseRollupInput.kernelData.vk.numPublicInputs}`);
294
- logger.info(`Number of public inputs ${baseRollupInput.kernelData.publicInputs}`);
282
+ logger.debug(`Number of public inputs in baseRollupInput: ${baseRollupInput.kernelData.vk.numPublicInputs}`);
295
283
  baseRollupInput.kernelData.proof = await this.ensureValidProof(
296
284
  baseRollupInput.kernelData.proof,
297
285
  'BaseRollupArtifact',
@@ -477,7 +465,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
477
465
  this.instrumentation.recordSize('witGenInputSize', circuitName, input.toBuffer().length);
478
466
  this.instrumentation.recordSize('witGenOutputSize', circuitName, output.toBuffer().length);
479
467
 
480
- logger.debug(`Generated witness`, {
468
+ logger.info(`Generated witness`, {
481
469
  circuitName,
482
470
  duration: timer.ms(),
483
471
  inputSize: input.toBuffer().length,
@@ -531,7 +519,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
531
519
  const proof = new Proof(rawProof, vkData.numPublicInputs);
532
520
  const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
533
521
 
534
- this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs / 1000);
522
+ this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs);
535
523
  this.instrumentation.recordSize('proofSize', circuitName, proof.buffer.length);
536
524
  this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs);
537
525
  this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize);
@@ -550,7 +538,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
550
538
 
551
539
  return { circuitOutput: output, proof };
552
540
  };
553
- return await runInDirectory(this.config.bbWorkingDirectory, operation);
541
+ return await this.runInDirectory(operation);
554
542
  }
555
543
 
556
544
  private async generateAvmProofWithBB(input: AvmCircuitInputs, workingDirectory: string): Promise<BBSuccess> {
@@ -583,11 +571,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
583
571
  }
584
572
 
585
573
  private async createAvmProof(input: AvmCircuitInputs): Promise<ProofAndVerificationKey> {
586
- const cleanupDir: boolean = !process.env.AVM_PROVING_PRESERVE_WORKING_DIR;
587
574
  const operation = async (bbWorkingDirectory: string): Promise<ProofAndVerificationKey> => {
588
- if (!cleanupDir) {
589
- logger.info(`Preserving working directory ${bbWorkingDirectory}`);
590
- }
591
575
  const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory);
592
576
 
593
577
  const rawProof = await fs.readFile(provingResult.proofPath!);
@@ -620,7 +604,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
620
604
 
621
605
  return { proof, verificationKey };
622
606
  };
623
- return await runInDirectory(this.config.bbWorkingDirectory, operation, cleanupDir);
607
+ return await this.runInDirectory(operation);
624
608
  }
625
609
 
626
610
  public async getTubeProof(
@@ -634,6 +618,12 @@ export class BBNativeRollupProver implements ServerCircuitProver {
634
618
  // Read the proof as fields
635
619
  const tubeVK = await extractVkData(provingResult.vkPath!);
636
620
  const tubeProof = await this.readTubeProofAsFields(provingResult.proofPath!, tubeVK, TUBE_PROOF_LENGTH);
621
+
622
+ this.instrumentation.recordDuration('provingDuration', 'tubeCircuit', provingResult.durationMs);
623
+ this.instrumentation.recordSize('proofSize', 'tubeCircuit', tubeProof.binaryProof.buffer.length);
624
+ this.instrumentation.recordSize('circuitPublicInputCount', 'tubeCircuit', tubeVK.numPublicInputs);
625
+ this.instrumentation.recordSize('circuitSize', 'tubeCircuit', tubeVK.circuitSize);
626
+
637
627
  // Sanity check the tube proof (can be removed later)
638
628
  await this.verifyWithKey(tubeVK, tubeProof.binaryProof);
639
629
 
@@ -646,7 +636,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
646
636
 
647
637
  return { tubeVK, tubeProof };
648
638
  };
649
- return await runInDirectory(this.config.bbWorkingDirectory, operation);
639
+ return await this.runInDirectory(operation);
650
640
  }
651
641
 
652
642
  /**
@@ -681,7 +671,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
681
671
  const proof = await this.readProofAsFields(provingResult.proofPath!, circuitType, proofLength);
682
672
 
683
673
  const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
684
- this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs / 1000);
674
+ this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs);
685
675
  this.instrumentation.recordSize('proofSize', circuitName, proof.binaryProof.buffer.length);
686
676
  this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs);
687
677
  this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize);
@@ -705,7 +695,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
705
695
  proof,
706
696
  };
707
697
  };
708
- return await runInDirectory(this.config.bbWorkingDirectory, operation);
698
+ return await this.runInDirectory(operation);
709
699
  }
710
700
 
711
701
  /**
@@ -758,7 +748,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
758
748
  logger.info(`Successfully verified proof from key in ${result.durationMs} ms`);
759
749
  };
760
750
 
761
- await runInDirectory(this.config.bbWorkingDirectory, operation);
751
+ await this.runInDirectory(operation);
762
752
  }
763
753
 
764
754
  /**
@@ -830,7 +820,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
830
820
  true,
831
821
  );
832
822
  };
833
- return await runInDirectory(this.config.bbWorkingDirectory, operation);
823
+ return await this.runInDirectory(operation);
834
824
  }
835
825
 
836
826
  /**
@@ -901,7 +891,6 @@ export class BBNativeRollupProver implements ServerCircuitProver {
901
891
  throw new Error(`Invalid verification key for ${circuitType}`);
902
892
  }
903
893
  const numPublicInputs = vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
904
-
905
894
  const fieldsWithoutPublicInputs = json
906
895
  .slice(0, 3)
907
896
  .map(Fr.fromString)
@@ -965,4 +954,16 @@ export class BBNativeRollupProver implements ServerCircuitProver {
965
954
 
966
955
  return proof;
967
956
  }
957
+
958
+ private runInDirectory<T>(fn: (dir: string) => Promise<T>) {
959
+ return runInDirectory(
960
+ this.config.bbWorkingDirectory,
961
+ (dir: string) =>
962
+ fn(dir).catch(err => {
963
+ logger.error(`Error running operation at ${dir}: ${err}`);
964
+ throw err;
965
+ }),
966
+ this.config.bbSkipCleanup,
967
+ );
968
+ }
968
969
  }
package/src/stats.ts CHANGED
@@ -35,6 +35,8 @@ export function mapProtocolArtifactNameToCircuitName(
35
35
  return 'private-kernel-tail-to-public';
36
36
  case 'PrivateKernelResetFullArtifact':
37
37
  return 'private-kernel-reset-full';
38
+ case 'PrivateKernelResetFullInnerArtifact':
39
+ return 'private-kernel-reset-full-inner';
38
40
  case 'PrivateKernelResetBigArtifact':
39
41
  return 'private-kernel-reset-big';
40
42
  case 'PrivateKernelResetMediumArtifact':
@@ -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,
@@ -64,17 +65,18 @@ import { SimulatedPublicKernelArtifactMapping } from '../mappings/mappings.js';
64
65
  import { mapPublicKernelToCircuitName } from '../stats.js';
65
66
 
66
67
  /**
67
- * A class for use in testing situations (e2e, unit test etc)
68
- * Simulates circuits using the most efficient method and performs no proving
68
+ * A class for use in testing situations (e2e, unit test, etc) and temporarily for assembling a block in the sequencer.
69
+ * Simulates circuits using the most efficient method and performs no proving.
69
70
  */
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
@@ -116,7 +116,7 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
116
116
  proofType: 'ultra-honk',
117
117
  } satisfies CircuitVerificationStats);
118
118
  };
119
- await runInDirectory(this.config.bbWorkingDirectory, operation);
119
+ await runInDirectory(this.config.bbWorkingDirectory, operation, this.config.bbSkipCleanup);
120
120
  }
121
121
 
122
122
  public async generateSolidityContract(circuit: ProtocolArtifact, contractName: string) {
@@ -168,7 +168,7 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
168
168
  proofType: 'client-ivc',
169
169
  } satisfies CircuitVerificationStats);
170
170
  };
171
- await runInDirectory(this.config.bbWorkingDirectory, operation);
171
+ await runInDirectory(this.config.bbWorkingDirectory, operation, this.config.bbSkipCleanup);
172
172
  return true;
173
173
  } catch (err) {
174
174
  this.logger.warn(`Failed to verify ClientIVC proof for tx ${Tx.getHash(tx)}: ${String(err)}`);