@aztec/bb-prover 3.0.0-canary.a9708bd → 3.0.0-devnet.2-patch.1

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.
Files changed (90) hide show
  1. package/dest/avm_proving_tests/avm_proving_tester.d.ts +7 -6
  2. package/dest/avm_proving_tests/avm_proving_tester.d.ts.map +1 -1
  3. package/dest/avm_proving_tests/avm_proving_tester.js +33 -13
  4. package/dest/bb/cli.d.ts +1 -1
  5. package/dest/bb/execute.d.ts +5 -13
  6. package/dest/bb/execute.d.ts.map +1 -1
  7. package/dest/bb/execute.js +30 -92
  8. package/dest/bb/index.d.ts +1 -1
  9. package/dest/config.d.ts +1 -1
  10. package/dest/honk.d.ts +2 -2
  11. package/dest/honk.js +2 -2
  12. package/dest/index.d.ts +1 -1
  13. package/dest/instrumentation.d.ts +3 -3
  14. package/dest/instrumentation.d.ts.map +1 -1
  15. package/dest/prover/client/bb_private_kernel_prover.d.ts +12 -6
  16. package/dest/prover/client/bb_private_kernel_prover.d.ts.map +1 -1
  17. package/dest/prover/client/bb_private_kernel_prover.js +36 -7
  18. package/dest/prover/client/bundle.d.ts +6 -0
  19. package/dest/prover/client/bundle.d.ts.map +1 -0
  20. package/dest/prover/client/bundle.js +7 -0
  21. package/dest/prover/client/lazy.d.ts +6 -0
  22. package/dest/prover/client/lazy.d.ts.map +1 -0
  23. package/dest/prover/client/lazy.js +7 -0
  24. package/dest/prover/index.d.ts +1 -1
  25. package/dest/prover/proof_utils.d.ts +9 -9
  26. package/dest/prover/proof_utils.d.ts.map +1 -1
  27. package/dest/prover/proof_utils.js +42 -25
  28. package/dest/prover/server/bb_prover.d.ts +22 -42
  29. package/dest/prover/server/bb_prover.d.ts.map +1 -1
  30. package/dest/prover/server/bb_prover.js +66 -143
  31. package/dest/test/delay_values.d.ts +1 -1
  32. package/dest/test/delay_values.d.ts.map +1 -1
  33. package/dest/test/delay_values.js +33 -23
  34. package/dest/test/index.d.ts +1 -1
  35. package/dest/test/test_circuit_prover.d.ts +21 -31
  36. package/dest/test/test_circuit_prover.d.ts.map +1 -1
  37. package/dest/test/test_circuit_prover.js +74 -56
  38. package/dest/test/test_verifier.d.ts +3 -1
  39. package/dest/test/test_verifier.d.ts.map +1 -1
  40. package/dest/test/test_verifier.js +15 -0
  41. package/dest/verification_key/verification_key_data.d.ts +1 -1
  42. package/dest/verification_key/verification_key_data.js +1 -1
  43. package/dest/verifier/bb_verifier.d.ts +3 -5
  44. package/dest/verifier/bb_verifier.d.ts.map +1 -1
  45. package/dest/verifier/bb_verifier.js +24 -26
  46. package/dest/verifier/index.d.ts +2 -2
  47. package/dest/verifier/index.d.ts.map +1 -1
  48. package/dest/verifier/index.js +1 -1
  49. package/dest/verifier/queued_chonk_verifier.d.ts +15 -0
  50. package/dest/verifier/queued_chonk_verifier.d.ts.map +1 -0
  51. package/dest/verifier/{queued_ivc_verifier.js → queued_chonk_verifier.js} +3 -3
  52. package/package.json +23 -23
  53. package/src/avm_proving_tests/avm_proving_tester.ts +43 -19
  54. package/src/bb/execute.ts +20 -90
  55. package/src/honk.ts +1 -1
  56. package/src/instrumentation.ts +2 -2
  57. package/src/prover/client/bb_private_kernel_prover.ts +49 -10
  58. package/src/prover/client/bundle.ts +10 -0
  59. package/src/prover/client/lazy.ts +10 -0
  60. package/src/prover/proof_utils.ts +53 -31
  61. package/src/prover/server/bb_prover.ts +231 -288
  62. package/src/test/delay_values.ts +33 -23
  63. package/src/test/test_circuit_prover.ts +219 -142
  64. package/src/test/test_verifier.ts +8 -0
  65. package/src/verification_key/verification_key_data.ts +1 -1
  66. package/src/verifier/bb_verifier.ts +34 -33
  67. package/src/verifier/index.ts +1 -1
  68. package/src/verifier/{queued_ivc_verifier.ts → queued_chonk_verifier.ts} +3 -3
  69. package/dest/prover/client/native/bb_native_private_kernel_prover.d.ts +0 -23
  70. package/dest/prover/client/native/bb_native_private_kernel_prover.d.ts.map +0 -1
  71. package/dest/prover/client/native/bb_native_private_kernel_prover.js +0 -66
  72. package/dest/prover/client/wasm/bb_wasm_private_kernel_prover.d.ts +0 -15
  73. package/dest/prover/client/wasm/bb_wasm_private_kernel_prover.d.ts.map +0 -1
  74. package/dest/prover/client/wasm/bb_wasm_private_kernel_prover.js +0 -48
  75. package/dest/prover/client/wasm/bundle.d.ts +0 -6
  76. package/dest/prover/client/wasm/bundle.d.ts.map +0 -1
  77. package/dest/prover/client/wasm/bundle.js +0 -8
  78. package/dest/prover/client/wasm/lazy.d.ts +0 -6
  79. package/dest/prover/client/wasm/lazy.d.ts.map +0 -1
  80. package/dest/prover/client/wasm/lazy.js +0 -8
  81. package/dest/stats.d.ts +0 -4
  82. package/dest/stats.d.ts.map +0 -1
  83. package/dest/stats.js +0 -45
  84. package/dest/verifier/queued_ivc_verifier.d.ts +0 -15
  85. package/dest/verifier/queued_ivc_verifier.d.ts.map +0 -1
  86. package/src/prover/client/native/bb_native_private_kernel_prover.ts +0 -105
  87. package/src/prover/client/wasm/bb_wasm_private_kernel_prover.ts +0 -60
  88. package/src/prover/client/wasm/bundle.ts +0 -11
  89. package/src/prover/client/wasm/lazy.ts +0 -11
  90. package/src/stats.ts +0 -47
@@ -8,7 +8,7 @@ import {
8
8
  type TestPrivateInsertions,
9
9
  } from '@aztec/simulator/public/fixtures';
10
10
  import type { PublicTxResult } from '@aztec/simulator/server';
11
- import { type AvmCircuitInputs, AvmCircuitPublicInputs } from '@aztec/stdlib/avm';
11
+ import { AvmCircuitInputs, AvmCircuitPublicInputs, PublicSimulatorConfig } from '@aztec/stdlib/avm';
12
12
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
13
13
  import type { MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
14
14
  import type { GlobalVariables } from '@aztec/stdlib/tx';
@@ -27,7 +27,7 @@ import {
27
27
  verifyAvmProof,
28
28
  } from '../bb/execute.js';
29
29
 
30
- const BB_PATH = path.resolve('../../barretenberg/cpp/build/bin/bb');
30
+ const BB_PATH = path.resolve('../../barretenberg/cpp/build/bin/bb-avm');
31
31
 
32
32
  // An InterceptingLogger that records all log messages and forwards them to a wrapped logger.
33
33
  class InterceptingLogger implements Logger {
@@ -88,34 +88,45 @@ class InterceptingLogger implements Logger {
88
88
  }
89
89
  }
90
90
 
91
+ // Config with collectHints enabled for proving tests
92
+ const provingConfig: PublicSimulatorConfig = PublicSimulatorConfig.from({
93
+ skipFeeEnforcement: false,
94
+ collectCallMetadata: true, // For results.
95
+ collectDebugLogs: false,
96
+ collectHints: true, // Required for proving!
97
+ collectPublicInputs: true, // Required for proving!
98
+ collectStatistics: false,
99
+ });
100
+
91
101
  export class AvmProvingTester extends PublicTxSimulationTester {
102
+ private bbWorkingDirectory: string = '';
103
+
92
104
  constructor(
93
- private bbWorkingDirectory: string,
94
105
  private checkCircuitOnly: boolean,
95
106
  contractDataSource: SimpleContractDataSource,
96
107
  merkleTrees: MerkleTreeWriteOperations,
97
108
  globals?: GlobalVariables,
98
109
  metrics?: TestExecutorMetrics,
99
110
  ) {
100
- super(merkleTrees, contractDataSource, globals, metrics);
111
+ // simulator factory is undefined because for proving, we use the default C++ simulator
112
+ super(merkleTrees, contractDataSource, globals, metrics, /*simulatorFactory=*/ undefined, provingConfig);
101
113
  }
102
114
 
103
- static async new(checkCircuitOnly: boolean = false, globals?: GlobalVariables, metrics?: TestExecutorMetrics) {
104
- const bbWorkingDirectory = await fs.mkdtemp(path.join(tmpdir(), 'bb-'));
105
-
115
+ static async new(
116
+ worldStateService: NativeWorldStateService, // make sure to close this later
117
+ checkCircuitOnly: boolean = false,
118
+ globals?: GlobalVariables,
119
+ metrics?: TestExecutorMetrics,
120
+ ) {
106
121
  const contractDataSource = new SimpleContractDataSource();
107
- const merkleTrees = await (await NativeWorldStateService.tmp()).fork();
108
- return new AvmProvingTester(
109
- bbWorkingDirectory,
110
- checkCircuitOnly,
111
- contractDataSource,
112
- merkleTrees,
113
- globals,
114
- metrics,
115
- );
122
+ const merkleTrees = await worldStateService.fork();
123
+ return new AvmProvingTester(checkCircuitOnly, contractDataSource, merkleTrees, globals, metrics);
116
124
  }
117
125
 
118
126
  async prove(avmCircuitInputs: AvmCircuitInputs, txLabel: string = 'unlabeledTx'): Promise<BBResult> {
127
+ // We use a new working directory for each proof.
128
+ this.bbWorkingDirectory = await fs.mkdtemp(path.join(tmpdir(), 'bb-'));
129
+
119
130
  const interceptingLogger = new InterceptingLogger(this.logger);
120
131
 
121
132
  // Then we prove.
@@ -151,6 +162,11 @@ export class AvmProvingTester extends PublicTxSimulationTester {
151
162
  }
152
163
  });
153
164
 
165
+ // Throw if logs did not contain any times.
166
+ if (Object.keys(times).length === 0) {
167
+ throw new Error('AVM stdout did not contain any proving times in the stats!');
168
+ }
169
+
154
170
  // Hack to make labels match.
155
171
  const txLabelWithCount = `${txLabel}/${this.txCount - 1}`;
156
172
  // I need to cast because TS doesnt realize metrics is protected not private.
@@ -204,7 +220,9 @@ export class AvmProvingTester extends PublicTxSimulationTester {
204
220
  feePayer = sender,
205
221
  privateInsertions?: TestPrivateInsertions,
206
222
  txLabel: string = 'unlabeledTx',
223
+ disableRevertCheck: boolean = false,
207
224
  ): Promise<PublicTxResult> {
225
+ const simTimer = new Timer();
208
226
  const simRes = await this.simulateTx(
209
227
  sender,
210
228
  setupCalls,
@@ -214,11 +232,16 @@ export class AvmProvingTester extends PublicTxSimulationTester {
214
232
  privateInsertions,
215
233
  txLabel,
216
234
  );
217
- expect(simRes.revertCode.isOK()).toBe(expectRevert ? false : true);
235
+ const simDuration = simTimer.ms();
236
+ this.logger.info(`Simulation took ${simDuration} ms for tx ${txLabel}`);
237
+
238
+ if (!disableRevertCheck) {
239
+ expect(simRes.revertCode.isOK()).toBe(expectRevert ? false : true);
240
+ }
218
241
 
219
242
  const opString = this.checkCircuitOnly ? 'Check circuit' : 'Proving and verification';
220
243
 
221
- const avmCircuitInputs = simRes.avmProvingRequest.inputs;
244
+ const avmCircuitInputs = new AvmCircuitInputs(simRes.hints!, simRes.publicInputs!);
222
245
  const timer = new Timer();
223
246
  await this.proveVerify(avmCircuitInputs, txLabel);
224
247
  this.logger.info(`${opString} took ${timer.ms()} ms for tx ${txLabel}`);
@@ -240,10 +263,11 @@ export class AvmProvingTester extends PublicTxSimulationTester {
240
263
  setupCalls ?? [],
241
264
  appCalls ?? [],
242
265
  teardownCall,
243
- /*expectRevert=*/ false,
266
+ undefined,
244
267
  feePayer,
245
268
  privateInsertions,
246
269
  txLabel,
270
+ true,
247
271
  );
248
272
  }
249
273
 
package/src/bb/execute.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { sha256 } from '@aztec/foundation/crypto';
1
+ import { sha256 } from '@aztec/foundation/crypto/sha256';
2
2
  import type { LogFn, Logger } from '@aztec/foundation/log';
3
3
  import { Timer } from '@aztec/foundation/timer';
4
4
  import type { AvmCircuitInputs, AvmCircuitPublicInputs } from '@aztec/stdlib/avm';
@@ -6,6 +6,7 @@ import type { AvmCircuitInputs, AvmCircuitPublicInputs } from '@aztec/stdlib/avm
6
6
  import * as proc from 'child_process';
7
7
  import { promises as fs } from 'fs';
8
8
  import { basename, dirname, join } from 'path';
9
+ import readline from 'readline';
9
10
 
10
11
  import type { UltraHonkFlavor } from '../honk.js';
11
12
 
@@ -15,7 +16,6 @@ export const PROOF_FILENAME = 'proof';
15
16
  export const AVM_INPUTS_FILENAME = 'avm_inputs.bin';
16
17
  export const AVM_BYTECODE_FILENAME = 'avm_bytecode.bin';
17
18
  export const AVM_PUBLIC_INPUTS_FILENAME = 'avm_public_inputs.bin';
18
- export const CLIENT_IVC_PROOF_FILE_NAME = 'proof';
19
19
 
20
20
  export enum BB_RESULT {
21
21
  SUCCESS,
@@ -86,6 +86,7 @@ export function executeBB(
86
86
  logger(`BB concurrency: ${env.HARDWARE_CONCURRENCY}`);
87
87
  logger(`Executing BB with: ${pathToBB} ${command} ${args.join(' ')}`);
88
88
  const bb = proc.spawn(pathToBB, [command, ...args], {
89
+ stdio: ['ignore', 'pipe', 'pipe'],
89
90
  env,
90
91
  });
91
92
 
@@ -100,14 +101,9 @@ export function executeBB(
100
101
  }, timeout);
101
102
  }
102
103
 
103
- bb.stdout.on('data', data => {
104
- const message = data.toString('utf-8').replace(/\n$/, '');
105
- logger(message);
106
- });
107
- bb.stderr.on('data', data => {
108
- const message = data.toString('utf-8').replace(/\n$/, '');
109
- logger(message);
110
- });
104
+ readline.createInterface({ input: bb.stdout }).on('line', logger);
105
+ readline.createInterface({ input: bb.stderr }).on('line', logger);
106
+
111
107
  bb.on('close', (exitCode: number, signal?: string) => {
112
108
  if (timeoutId) {
113
109
  clearTimeout(timeoutId);
@@ -121,7 +117,7 @@ export function executeBB(
121
117
  }).catch(_ => ({ status: BB_RESULT.FAILURE, exitCode: -1, signal: undefined }));
122
118
  }
123
119
 
124
- export async function executeBbClientIvcProof(
120
+ export async function executeBbChonkProof(
125
121
  pathToBB: string,
126
122
  workingDirectory: string,
127
123
  inputsPath: string,
@@ -154,7 +150,7 @@ export async function executeBbClientIvcProof(
154
150
  log(`bb - ${message}`);
155
151
  };
156
152
 
157
- const args = ['-o', outputPath, '--ivc_inputs_path', inputsPath, '-v', '--scheme', 'client_ivc'];
153
+ const args = ['-o', outputPath, '--ivc_inputs_path', inputsPath, '-v', '--scheme', 'chonk'];
158
154
  if (writeVk) {
159
155
  args.push('--write_vk');
160
156
  }
@@ -214,6 +210,7 @@ export async function generateProof(
214
210
  workingDirectory: string,
215
211
  circuitName: string,
216
212
  bytecode: Buffer,
213
+ verificationKey: Buffer,
217
214
  inputWitnessFile: string,
218
215
  flavor: UltraHonkFlavor,
219
216
  log: Logger,
@@ -225,8 +222,9 @@ export async function generateProof(
225
222
  return { status: BB_RESULT.FAILURE, reason: `Working directory ${workingDirectory} does not exist` };
226
223
  }
227
224
 
228
- // The bytecode is written to e.g. /workingDirectory/BaseParityArtifact-bytecode
225
+ // The bytecode is written to e.g. /workingDirectory/ParityBaseArtifact-bytecode
229
226
  const bytecodePath = `${workingDirectory}/${circuitName}-bytecode`;
227
+ const vkPath = `${workingDirectory}/${circuitName}-vk`;
230
228
 
231
229
  // The proof is written to e.g. /workingDirectory/ultra_honk/proof
232
230
  const outputPath = `${workingDirectory}`;
@@ -240,16 +238,16 @@ export async function generateProof(
240
238
  }
241
239
 
242
240
  try {
243
- // Write the bytecode to the working directory
244
- await fs.writeFile(bytecodePath, bytecode);
245
- // TODO(#15043): Avoid write_vk flag here.
241
+ // Write the bytecode and vk to the working directory
242
+ await Promise.all([fs.writeFile(bytecodePath, bytecode), fs.writeFile(vkPath, verificationKey)]);
246
243
  const args = getArgs(flavor).concat([
247
244
  '--disable_zk',
248
- '--write_vk',
249
245
  '-o',
250
246
  outputPath,
251
247
  '-b',
252
248
  bytecodePath,
249
+ '-k',
250
+ vkPath,
253
251
  '-w',
254
252
  inputWitnessFile,
255
253
  '-v',
@@ -286,74 +284,6 @@ export async function generateProof(
286
284
  }
287
285
  }
288
286
 
289
- /**
290
- * Used for generating proofs of the tube circuit
291
- * It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof.
292
- *
293
- * @returns An object containing a result indication, the location of the proof and the duration taken
294
- */
295
- export async function generateTubeProof(
296
- pathToBB: string,
297
- workingDirectory: string,
298
- vkPath: string,
299
- log: LogFn,
300
- ): Promise<BBFailure | BBSuccess> {
301
- // Check that the working directory exists
302
- try {
303
- await fs.access(workingDirectory);
304
- } catch {
305
- return { status: BB_RESULT.FAILURE, reason: `Working directory ${workingDirectory} does not exist` };
306
- }
307
-
308
- // Paths for the inputs
309
- const proofPath = join(workingDirectory, CLIENT_IVC_PROOF_FILE_NAME);
310
-
311
- // The proof is written to e.g. /workingDirectory/proof
312
- const outputPath = workingDirectory;
313
- const filePresent = async (file: string) =>
314
- await fs
315
- .access(file, fs.constants.R_OK)
316
- .then(_ => true)
317
- .catch(_ => false);
318
-
319
- const binaryPresent = await filePresent(pathToBB);
320
- if (!binaryPresent) {
321
- return { status: BB_RESULT.FAILURE, reason: `Failed to find bb binary at ${pathToBB}` };
322
- }
323
-
324
- try {
325
- if (!(await filePresent(proofPath))) {
326
- return { status: BB_RESULT.FAILURE, reason: `Client IVC input files not present in ${workingDirectory}` };
327
- }
328
- const args = ['-o', outputPath, '-k', vkPath, '-v'];
329
-
330
- const timer = new Timer();
331
- const logFunction = (message: string) => {
332
- log(`TubeCircuit (prove) BB out - ${message}`);
333
- };
334
- const result = await executeBB(pathToBB, 'prove_tube', args, logFunction);
335
- const durationMs = timer.ms();
336
-
337
- if (result.status == BB_RESULT.SUCCESS) {
338
- return {
339
- status: BB_RESULT.SUCCESS,
340
- durationMs,
341
- proofPath: outputPath,
342
- pkPath: undefined,
343
- vkDirectoryPath: outputPath,
344
- };
345
- }
346
- // Not a great error message here but it is difficult to decipher what comes from bb
347
- return {
348
- status: BB_RESULT.FAILURE,
349
- reason: `Failed to generate proof. Exit code ${result.exitCode}. Signal ${result.signal}.`,
350
- retry: !!result.signal,
351
- };
352
- } catch (error) {
353
- return { status: BB_RESULT.FAILURE, reason: `${error}` };
354
- }
355
- }
356
-
357
287
  /**
358
288
  * Used for generating AVM proofs.
359
289
  * It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof.
@@ -491,7 +421,7 @@ export async function verifyAvmProof(
491
421
  }
492
422
 
493
423
  /**
494
- * Verifies a ClientIvcProof
424
+ * Verifies a ChonkProof
495
425
  * TODO(#7370) The verification keys should be supplied separately
496
426
  * @param pathToBB - The full path to the bb binary
497
427
  * @param targetPath - The path to the folder with the proof, accumulator, and verification keys
@@ -499,7 +429,7 @@ export async function verifyAvmProof(
499
429
  * @param concurrency - The number of threads to use for the verification
500
430
  * @returns An object containing a result indication and duration taken
501
431
  */
502
- export async function verifyClientIvcProof(
432
+ export async function verifyChonkProof(
503
433
  pathToBB: string,
504
434
  proofPath: string,
505
435
  keyPath: string,
@@ -515,7 +445,7 @@ export async function verifyClientIvcProof(
515
445
  }
516
446
 
517
447
  try {
518
- const args = ['--scheme', 'client_ivc', '-p', proofPath, '-k', keyPath, '-v'];
448
+ const args = ['--scheme', 'chonk', '-p', proofPath, '-k', keyPath, '-v'];
519
449
  const timer = new Timer();
520
450
  const command = 'verify';
521
451
 
@@ -679,7 +609,7 @@ export async function computeGateCountForCircuit(
679
609
  return { status: BB_RESULT.FAILURE, reason: `Working directory ${workingDirectory} does not exist` };
680
610
  }
681
611
 
682
- // The bytecode is written to e.g. /workingDirectory/BaseParityArtifact-bytecode
612
+ // The bytecode is written to e.g. /workingDirectory/ParityBaseArtifact-bytecode
683
613
  const bytecodePath = `${workingDirectory}/${circuitName}-bytecode`;
684
614
 
685
615
  const binaryPresent = await fs
@@ -705,7 +635,7 @@ export async function computeGateCountForCircuit(
705
635
  const result = await executeBB(
706
636
  pathToBB,
707
637
  'gates',
708
- ['--scheme', flavor === 'mega_honk' ? 'client_ivc' : 'ultra_honk', '-b', bytecodePath, '-v'],
638
+ ['--scheme', flavor === 'mega_honk' ? 'chonk' : 'ultra_honk', '-b', bytecodePath, '-v'],
709
639
  logHandler,
710
640
  );
711
641
  const duration = timer.ms();
package/src/honk.ts CHANGED
@@ -3,7 +3,7 @@ import type { ServerProtocolArtifact } from '@aztec/noir-protocol-circuits-types
3
3
  export type UltraHonkFlavor = 'ultra_honk' | 'ultra_keccak_honk' | 'ultra_starknet_honk' | 'ultra_rollup_honk';
4
4
 
5
5
  const UltraKeccakHonkCircuits = ['RootRollupArtifact'] as const satisfies ServerProtocolArtifact[];
6
- const UltraHonkCircuits = ['BaseParityArtifact', 'RootParityArtifact'] as const satisfies ServerProtocolArtifact[];
6
+ const UltraHonkCircuits = ['ParityBaseArtifact', 'ParityRootArtifact'] as const satisfies ServerProtocolArtifact[];
7
7
 
8
8
  export type UltraKeccakHonkServerProtocolArtifact = (typeof UltraKeccakHonkCircuits)[number];
9
9
  export type UltraHonkServerProtocolArtifact = (typeof UltraHonkCircuits)[number];
@@ -86,7 +86,7 @@ export class ProverInstrumentation {
86
86
  */
87
87
  recordDuration(
88
88
  metric: 'simulationDuration' | 'witGenDuration' | 'provingDuration',
89
- circuitName: CircuitName | 'tubeCircuit',
89
+ circuitName: CircuitName,
90
90
  timerOrMS: Timer | number,
91
91
  ) {
92
92
  const s = typeof timerOrMS === 'number' ? timerOrMS / 1000 : timerOrMS.s();
@@ -116,7 +116,7 @@ export class ProverInstrumentation {
116
116
  */
117
117
  recordSize(
118
118
  metric: 'witGenInputSize' | 'witGenOutputSize' | 'proofSize' | 'circuitSize' | 'circuitPublicInputCount',
119
- circuitName: CircuitName | 'tubeCircuit',
119
+ circuitName: CircuitName,
120
120
  size: number,
121
121
  ) {
122
122
  this[metric].record(Math.ceil(size), {
@@ -1,4 +1,7 @@
1
- import { createLogger } from '@aztec/foundation/log';
1
+ import { AztecClientBackend, type BackendOptions, Barretenberg } from '@aztec/bb.js';
2
+ import { type LogLevel, type Logger, createLogger } from '@aztec/foundation/log';
3
+ import { Timer } from '@aztec/foundation/timer';
4
+ import { serializeWitness } from '@aztec/noir-noirc_abi';
2
5
  import {
3
6
  convertHidingKernelPublicInputsToWitnessMapWithAbi,
4
7
  convertHidingKernelToRollupInputsToWitnessMapWithAbi,
@@ -16,7 +19,11 @@ import {
16
19
  getPrivateKernelResetArtifactName,
17
20
  updateResetCircuitSampleInputs,
18
21
  } from '@aztec/noir-protocol-circuits-types/client';
19
- import type { ArtifactProvider, ClientProtocolArtifact } from '@aztec/noir-protocol-circuits-types/types';
22
+ import {
23
+ type ArtifactProvider,
24
+ type ClientProtocolArtifact,
25
+ mapProtocolArtifactNameToCircuitName,
26
+ } from '@aztec/noir-protocol-circuits-types/types';
20
27
  import type { Abi, WitnessMap } from '@aztec/noir-types';
21
28
  import type { CircuitSimulator } from '@aztec/simulator/client';
22
29
  import type { PrivateKernelProver } from '@aztec/stdlib/interfaces/client';
@@ -33,17 +40,22 @@ import type {
33
40
  PrivateKernelTailCircuitPublicInputs,
34
41
  } from '@aztec/stdlib/kernel';
35
42
  import type { NoirCompiledCircuitWithName } from '@aztec/stdlib/noir';
36
- import type { ClientIvcProof } from '@aztec/stdlib/proofs';
43
+ import { ChonkProofWithPublicInputs } from '@aztec/stdlib/proofs';
37
44
  import type { CircuitSimulationStats, CircuitWitnessGenerationStats } from '@aztec/stdlib/stats';
38
45
 
39
- import { mapProtocolArtifactNameToCircuitName } from '../../stats.js';
46
+ import { ungzip } from 'pako';
40
47
 
48
+ export type BBPrivateKernelProverOptions = Omit<BackendOptions, 'logger'> & { logger?: Logger };
41
49
  export abstract class BBPrivateKernelProver implements PrivateKernelProver {
50
+ private log: Logger;
51
+
42
52
  constructor(
43
53
  protected artifactProvider: ArtifactProvider,
44
54
  protected simulator: CircuitSimulator,
45
- protected log = createLogger('bb-prover'),
46
- ) {}
55
+ protected options: BBPrivateKernelProverOptions = {},
56
+ ) {
57
+ this.log = options.logger || createLogger('bb-prover:private-kernel');
58
+ }
47
59
 
48
60
  public async generateInitOutput(
49
61
  inputs: PrivateKernelInitCircuitPrivateInputs,
@@ -261,11 +273,38 @@ export abstract class BBPrivateKernelProver implements PrivateKernelProver {
261
273
  return kernelProofOutput;
262
274
  }
263
275
 
264
- public createClientIvcProof(_executionSteps: PrivateExecutionStep[]): Promise<ClientIvcProof> {
265
- throw new Error('Not implemented');
276
+ public async createChonkProof(executionSteps: PrivateExecutionStep[]): Promise<ChonkProofWithPublicInputs> {
277
+ const timer = new Timer();
278
+ this.log.info(`Generating ClientIVC proof...`);
279
+ const barretenberg = await Barretenberg.initSingleton({
280
+ ...this.options,
281
+ logger: this.options.logger?.[(process.env.LOG_LEVEL as LogLevel) || 'verbose'],
282
+ });
283
+ const backend = new AztecClientBackend(
284
+ executionSteps.map(step => ungzip(step.bytecode)),
285
+ barretenberg,
286
+ );
287
+
288
+ const [proof] = await backend.prove(
289
+ executionSteps.map(step => ungzip(serializeWitness(step.witness))),
290
+ executionSteps.map(step => step.vk),
291
+ );
292
+ this.log.info(`Generated ClientIVC proof`, {
293
+ eventName: 'client-ivc-proof-generation',
294
+ duration: timer.ms(),
295
+ proofSize: proof.length,
296
+ });
297
+ return ChonkProofWithPublicInputs.fromBufferArray(proof);
266
298
  }
267
299
 
268
- public computeGateCountForCircuit(_bytecode: Buffer, _circuitName: string): Promise<number> {
269
- throw new Error('Not implemented');
300
+ public async computeGateCountForCircuit(_bytecode: Buffer, _circuitName: string): Promise<number> {
301
+ // Note we do not pass the vk to the backend. This is unneeded for gate counts.
302
+ const barretenberg = await Barretenberg.initSingleton({
303
+ ...this.options,
304
+ logger: this.options.logger?.[(process.env.LOG_LEVEL as LogLevel) || 'verbose'],
305
+ });
306
+ const backend = new AztecClientBackend([ungzip(_bytecode)], barretenberg);
307
+ const gateCount = await backend.gates();
308
+ return gateCount[0];
270
309
  }
271
310
  }
@@ -0,0 +1,10 @@
1
+ import { BundleArtifactProvider } from '@aztec/noir-protocol-circuits-types/client/bundle';
2
+ import type { CircuitSimulator } from '@aztec/simulator/client';
3
+
4
+ import { BBPrivateKernelProver, type BBPrivateKernelProverOptions } from './bb_private_kernel_prover.js';
5
+
6
+ export class BBBundlePrivateKernelProver extends BBPrivateKernelProver {
7
+ constructor(simulator: CircuitSimulator, options: BBPrivateKernelProverOptions = {}) {
8
+ super(new BundleArtifactProvider(), simulator, options);
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ import { LazyArtifactProvider } from '@aztec/noir-protocol-circuits-types/client/lazy';
2
+ import type { CircuitSimulator } from '@aztec/simulator/client';
3
+
4
+ import { BBPrivateKernelProver, type BBPrivateKernelProverOptions } from './bb_private_kernel_prover.js';
5
+
6
+ export class BBLazyPrivateKernelProver extends BBPrivateKernelProver {
7
+ constructor(simulator: CircuitSimulator, options: BBPrivateKernelProverOptions = {}) {
8
+ super(new LazyArtifactProvider(), simulator, options);
9
+ }
10
+ }
@@ -1,41 +1,59 @@
1
1
  import {
2
+ CHONK_PROOF_LENGTH,
3
+ HIDING_KERNEL_IO_PUBLIC_INPUTS_SIZE,
2
4
  IPA_CLAIM_SIZE,
3
5
  NESTED_RECURSIVE_PROOF_LENGTH,
4
6
  NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
5
7
  PAIRING_POINTS_SIZE,
6
8
  ULTRA_KECCAK_PROOF_LENGTH,
7
9
  } from '@aztec/constants';
8
- import { Fr } from '@aztec/foundation/fields';
10
+ import { Fr } from '@aztec/foundation/curves/bn254';
9
11
  import type { Logger } from '@aztec/foundation/log';
10
- import { ClientIvcProof, Proof, RecursiveProof } from '@aztec/stdlib/proofs';
12
+ import { ChonkProofWithPublicInputs, Proof, RecursiveProof } from '@aztec/stdlib/proofs';
11
13
  import type { VerificationKeyData } from '@aztec/stdlib/vks';
12
14
 
13
15
  import assert from 'assert';
14
16
  import { promises as fs } from 'fs';
15
17
  import * as path from 'path';
16
18
 
17
- import { CLIENT_IVC_PROOF_FILE_NAME, PROOF_FILENAME, PUBLIC_INPUTS_FILENAME } from '../bb/execute.js';
19
+ import { PROOF_FILENAME, PUBLIC_INPUTS_FILENAME } from '../bb/execute.js';
18
20
 
19
21
  /**
20
- * Create a ClientIvcProof proof file.
22
+ * Create a ChonkProof proof file.
21
23
  *
22
24
  * @param directory the directory to read the proof from.
23
- * @returns the encapsulated client ivc proof
25
+ * @returns the encapsulated chonk proof
24
26
  */
25
- export async function readClientIVCProofFromOutputDirectory(directory: string) {
26
- const clientIvcProofBuffer = await fs.readFile(path.join(directory, CLIENT_IVC_PROOF_FILE_NAME));
27
- return new ClientIvcProof(clientIvcProofBuffer);
27
+ export async function readChonkProofFromOutputDirectory(directory: string) {
28
+ const proofFilename = path.join(directory, PROOF_FILENAME);
29
+ const binaryProof = await fs.readFile(proofFilename);
30
+ const proofFields = splitBufferIntoFields(binaryProof);
31
+ return new ChonkProofWithPublicInputs(proofFields);
28
32
  }
29
33
 
30
34
  /**
31
- * Serialize a ClientIvcProof to a proof file.
35
+ * Serialize a ChonkProof to a proof file.
32
36
  *
33
- * @param proof the ClientIvcProof from object
37
+ * @param proof the ChonkProof from object
34
38
  * @param directory the directory to write in
35
39
  */
36
- export async function writeClientIVCProofToOutputDirectory(clientIvcProof: ClientIvcProof, directory: string) {
37
- const { clientIvcProofBuffer } = clientIvcProof;
38
- await fs.writeFile(path.join(directory, CLIENT_IVC_PROOF_FILE_NAME), clientIvcProofBuffer);
40
+ export async function writeChonkProofToPath(chonkProof: ChonkProofWithPublicInputs, outputPath: string) {
41
+ // NB: Don't use chonkProof.toBuffer here because it will include the proof length.
42
+ const fieldsBuf = Buffer.concat(chonkProof.fieldsWithPublicInputs.map(field => field.toBuffer()));
43
+ await fs.writeFile(outputPath, fieldsBuf);
44
+ }
45
+
46
+ function getNumCustomPublicInputs(proofLength: number, vkData: VerificationKeyData) {
47
+ let numPublicInputs = vkData.numPublicInputs;
48
+ if (proofLength == CHONK_PROOF_LENGTH) {
49
+ numPublicInputs -= HIDING_KERNEL_IO_PUBLIC_INPUTS_SIZE;
50
+ } else {
51
+ numPublicInputs -= PAIRING_POINTS_SIZE;
52
+ if (proofLength == NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH) {
53
+ numPublicInputs -= IPA_CLAIM_SIZE;
54
+ }
55
+ }
56
+ return numPublicInputs;
39
57
  }
40
58
 
41
59
  function splitBufferIntoFields(buffer: Buffer): Fr[] {
@@ -46,43 +64,47 @@ function splitBufferIntoFields(buffer: Buffer): Fr[] {
46
64
  return fields;
47
65
  }
48
66
 
49
- export async function readProofAsFields<PROOF_LENGTH extends number>(
50
- filePath: string,
67
+ export async function readProofsFromOutputDirectory<PROOF_LENGTH extends number>(
68
+ directory: string,
51
69
  vkData: VerificationKeyData,
52
70
  proofLength: PROOF_LENGTH,
53
71
  logger: Logger,
54
72
  ): Promise<RecursiveProof<PROOF_LENGTH>> {
55
- const publicInputsFilename = path.join(filePath, PUBLIC_INPUTS_FILENAME);
56
- const proofFilename = path.join(filePath, PROOF_FILENAME);
57
-
58
- const [binaryPublicInputs, binaryProof] = await Promise.all([
59
- fs.readFile(publicInputsFilename),
60
- fs.readFile(proofFilename),
61
- ]);
62
-
63
- const fieldsWithoutPublicInputs = splitBufferIntoFields(binaryProof);
64
-
65
- let numPublicInputs = vkData.numPublicInputs - PAIRING_POINTS_SIZE;
66
73
  assert(
67
- proofLength == NESTED_RECURSIVE_PROOF_LENGTH ||
74
+ proofLength == CHONK_PROOF_LENGTH ||
75
+ proofLength == NESTED_RECURSIVE_PROOF_LENGTH ||
68
76
  proofLength == NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH ||
69
77
  proofLength == ULTRA_KECCAK_PROOF_LENGTH,
70
78
  `Proof length must be one of the expected proof lengths, received ${proofLength}`,
71
79
  );
72
- if (proofLength == NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH) {
73
- numPublicInputs -= IPA_CLAIM_SIZE;
80
+
81
+ const publicInputsFilename = path.join(directory, PUBLIC_INPUTS_FILENAME);
82
+ const proofFilename = path.join(directory, PROOF_FILENAME);
83
+
84
+ // Handle CHONK separately because bb outputs the proof fields with public inputs for CHONK.
85
+ const isChonk = proofLength == CHONK_PROOF_LENGTH;
86
+
87
+ const [binaryPublicInputs, binaryProof] = await Promise.all([
88
+ isChonk ? Buffer.alloc(0) : fs.readFile(publicInputsFilename),
89
+ fs.readFile(proofFilename),
90
+ ]);
91
+
92
+ const numPublicInputs = getNumCustomPublicInputs(proofLength, vkData);
93
+ let fieldsWithoutPublicInputs = splitBufferIntoFields(binaryProof);
94
+ if (isChonk) {
95
+ fieldsWithoutPublicInputs = fieldsWithoutPublicInputs.slice(numPublicInputs);
74
96
  }
75
97
 
76
98
  assert(
77
99
  fieldsWithoutPublicInputs.length == proofLength,
78
- `Proof length mismatch: ${fieldsWithoutPublicInputs.length} != ${proofLength}`,
100
+ `Proof fields length mismatch: ${fieldsWithoutPublicInputs.length} != ${proofLength}`,
79
101
  );
80
102
 
81
103
  // Concat binary public inputs and binary proof
82
104
  // This buffer will have the form: [binary public inputs, binary proof]
83
105
  const binaryProofWithPublicInputs = Buffer.concat([binaryPublicInputs, binaryProof]);
84
106
  logger.debug(
85
- `Circuit path: ${filePath}, complete proof length: ${fieldsWithoutPublicInputs.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}`,
107
+ `Circuit path: ${directory}, proof fields length: ${fieldsWithoutPublicInputs.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}`,
86
108
  );
87
109
  return new RecursiveProof(
88
110
  fieldsWithoutPublicInputs,