@aztec/bb-prover 0.41.0 → 0.43.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.
Files changed (59) hide show
  1. package/dest/bb/cli.d.ts.map +1 -1
  2. package/dest/bb/cli.js +24 -2
  3. package/dest/bb/execute.d.ts +30 -1
  4. package/dest/bb/execute.d.ts.map +1 -1
  5. package/dest/bb/execute.js +252 -60
  6. package/dest/config.d.ts +9 -0
  7. package/dest/config.d.ts.map +1 -0
  8. package/dest/config.js +2 -0
  9. package/dest/index.d.ts +2 -0
  10. package/dest/index.d.ts.map +1 -1
  11. package/dest/index.js +3 -1
  12. package/dest/mappings/mappings.d.ts +1 -0
  13. package/dest/mappings/mappings.d.ts.map +1 -1
  14. package/dest/mappings/mappings.js +27 -8
  15. package/dest/prover/bb_native_proof_creator.d.ts +2 -8
  16. package/dest/prover/bb_native_proof_creator.d.ts.map +1 -1
  17. package/dest/prover/bb_native_proof_creator.js +37 -79
  18. package/dest/prover/bb_prover.d.ts +33 -32
  19. package/dest/prover/bb_prover.d.ts.map +1 -1
  20. package/dest/prover/bb_prover.js +231 -162
  21. package/dest/stats.d.ts.map +1 -1
  22. package/dest/stats.js +8 -2
  23. package/dest/test/index.d.ts +1 -0
  24. package/dest/test/index.d.ts.map +1 -1
  25. package/dest/test/index.js +2 -1
  26. package/dest/test/test_circuit_prover.d.ts +9 -7
  27. package/dest/test/test_circuit_prover.d.ts.map +1 -1
  28. package/dest/test/test_circuit_prover.js +32 -16
  29. package/dest/test/test_verifier.d.ts +7 -0
  30. package/dest/test/test_verifier.d.ts.map +1 -0
  31. package/dest/test/test_verifier.js +10 -0
  32. package/dest/verification_key/verification_key_data.d.ts +8 -0
  33. package/dest/verification_key/verification_key_data.d.ts.map +1 -0
  34. package/dest/verification_key/verification_key_data.js +24 -0
  35. package/dest/verifier/bb_verifier.d.ts +18 -0
  36. package/dest/verifier/bb_verifier.d.ts.map +1 -0
  37. package/dest/verifier/bb_verifier.js +90 -0
  38. package/dest/verifier/index.d.ts +2 -0
  39. package/dest/verifier/index.d.ts.map +1 -0
  40. package/dest/verifier/index.js +2 -0
  41. package/package.json +6 -6
  42. package/src/bb/cli.ts +36 -1
  43. package/src/bb/execute.ts +340 -67
  44. package/src/config.ts +9 -0
  45. package/src/index.ts +2 -0
  46. package/src/mappings/mappings.ts +38 -12
  47. package/src/prover/bb_native_proof_creator.ts +49 -91
  48. package/src/prover/bb_prover.ts +396 -221
  49. package/src/stats.ts +7 -1
  50. package/src/test/index.ts +1 -0
  51. package/src/test/test_circuit_prover.ts +85 -23
  52. package/src/test/test_verifier.ts +12 -0
  53. package/src/verification_key/verification_key_data.ts +35 -0
  54. package/src/verifier/bb_verifier.ts +156 -0
  55. package/src/verifier/index.ts +1 -0
  56. package/dest/prover/verification_key_data.d.ts +0 -16
  57. package/dest/prover/verification_key_data.d.ts.map +0 -1
  58. package/dest/prover/verification_key_data.js +0 -5
  59. package/src/prover/verification_key_data.ts +0 -16
@@ -1,6 +1,7 @@
1
1
  import { type AppCircuitProofOutput, type KernelProofOutput, type ProofCreator } from '@aztec/circuit-types';
2
2
  import { type CircuitProvingStats, type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats';
3
3
  import {
4
+ AGGREGATION_OBJECT_LENGTH,
4
5
  Fr,
5
6
  NESTED_RECURSIVE_PROOF_LENGTH,
6
7
  type PrivateCircuitPublicInputs,
@@ -13,13 +14,12 @@ import {
13
14
  Proof,
14
15
  RECURSIVE_PROOF_LENGTH,
15
16
  RecursiveProof,
16
- type VERIFICATION_KEY_LENGTH_IN_FIELDS,
17
- VerificationKeyAsFields,
17
+ type VerificationKeyAsFields,
18
+ type VerificationKeyData,
18
19
  } from '@aztec/circuits.js';
19
20
  import { siloNoteHash } from '@aztec/circuits.js/hash';
20
- import { randomBytes } from '@aztec/foundation/crypto';
21
+ import { runInDirectory } from '@aztec/foundation/fs';
21
22
  import { createDebugLogger } from '@aztec/foundation/log';
22
- import { type Tuple } from '@aztec/foundation/serialize';
23
23
  import { Timer } from '@aztec/foundation/timer';
24
24
  import {
25
25
  ClientCircuitArtifacts,
@@ -36,7 +36,7 @@ import {
36
36
  convertPrivateKernelTailOutputsFromWitnessMap,
37
37
  convertPrivateKernelTailToPublicInputsToWitnessMap,
38
38
  } from '@aztec/noir-protocol-circuits-types';
39
- import { type ACVMField, WASMSimulator } from '@aztec/simulator';
39
+ import { WASMSimulator } from '@aztec/simulator';
40
40
  import { type NoirCompiledCircuit } from '@aztec/types/noir';
41
41
 
42
42
  import { serializeWitness } from '@noir-lang/noirc_abi';
@@ -47,20 +47,12 @@ import {
47
47
  BB_RESULT,
48
48
  PROOF_FIELDS_FILENAME,
49
49
  PROOF_FILENAME,
50
- VK_FIELDS_FILENAME,
51
- VK_FILENAME,
52
50
  generateKeyForNoirCircuit,
53
51
  generateProof,
54
52
  verifyProof,
55
53
  } from '../bb/execute.js';
56
54
  import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
57
- import {
58
- AGGREGATION_OBJECT_SIZE,
59
- CIRCUIT_PUBLIC_INPUTS_INDEX,
60
- CIRCUIT_RECURSIVE_INDEX,
61
- CIRCUIT_SIZE_INDEX,
62
- type VerificationKeyData,
63
- } from './verification_key_data.js';
55
+ import { extractVkData } from '../verification_key/verification_key_data.js';
64
56
 
65
57
  /**
66
58
  * This proof creator implementation uses the native bb binary.
@@ -141,16 +133,13 @@ export class BBNativeProofCreator implements ProofCreator {
141
133
  }
142
134
 
143
135
  public async createAppCircuitProof(
144
- partialWitness: Map<number, ACVMField>,
136
+ partialWitness: WitnessMap,
145
137
  bytecode: Buffer,
146
138
  appCircuitName?: string,
147
139
  ): Promise<AppCircuitProofOutput> {
148
- const directory = `${this.bbWorkingDirectory}/${randomBytes(8).toString('hex')}`;
149
- await fs.mkdir(directory, { recursive: true });
150
- this.log.debug(`Created directory: ${directory}`);
151
- try {
140
+ const operation = async (directory: string) => {
152
141
  this.log.debug(`Proving app circuit`);
153
- const proofOutput = await this.createProof(directory, partialWitness, bytecode, 'App', 0, 0, appCircuitName);
142
+ const proofOutput = await this.createProof(directory, partialWitness, bytecode, 'App', appCircuitName);
154
143
  if (proofOutput.proof.proof.length != RECURSIVE_PROOF_LENGTH) {
155
144
  throw new Error(`Incorrect proof length`);
156
145
  }
@@ -160,10 +149,9 @@ export class BBNativeProofCreator implements ProofCreator {
160
149
  verificationKey: proofOutput.verificationKey,
161
150
  };
162
151
  return output;
163
- } finally {
164
- await fs.rm(directory, { recursive: true, force: true });
165
- this.log.debug(`Deleted directory: ${directory}`);
166
- }
152
+ };
153
+
154
+ return await runInDirectory(this.bbWorkingDirectory, operation);
167
155
  }
168
156
 
169
157
  /**
@@ -174,7 +162,7 @@ export class BBNativeProofCreator implements ProofCreator {
174
162
  public async verifyProofForProtocolCircuit(circuitType: ClientProtocolArtifact, proof: Proof) {
175
163
  const verificationKey = await this.getVerificationKeyDataForCircuit(circuitType);
176
164
 
177
- this.log.debug(`Verifying with key: ${verificationKey.hash.toString()}`);
165
+ this.log.debug(`Verifying with key: ${verificationKey.keyAsFields.hash.toString()}`);
178
166
 
179
167
  const logFunction = (message: string) => {
180
168
  this.log.debug(`${circuitType} BB out - ${message}`);
@@ -195,21 +183,15 @@ export class BBNativeProofCreator implements ProofCreator {
195
183
  proof: Proof,
196
184
  logFunction: (message: string) => void = () => {},
197
185
  ) {
198
- // Create random directory to be used for temp files
199
- const bbWorkingDirectory = `${this.bbWorkingDirectory}/${randomBytes(8).toString('hex')}`;
200
- await fs.mkdir(bbWorkingDirectory, { recursive: true });
201
-
202
- const proofFileName = `${bbWorkingDirectory}/proof`;
203
- const verificationKeyPath = `${bbWorkingDirectory}/vk`;
186
+ const operation = async (bbWorkingDirectory: string) => {
187
+ const proofFileName = `${bbWorkingDirectory}/proof`;
188
+ const verificationKeyPath = `${bbWorkingDirectory}/vk`;
204
189
 
205
- await fs.writeFile(proofFileName, proof.buffer);
206
- await fs.writeFile(verificationKeyPath, verificationKey);
207
-
208
- try {
190
+ await fs.writeFile(proofFileName, proof.buffer);
191
+ await fs.writeFile(verificationKeyPath, verificationKey);
209
192
  return await verifyProof(this.bbBinaryPath, proofFileName, verificationKeyPath!, logFunction);
210
- } finally {
211
- await fs.rm(bbWorkingDirectory, { recursive: true, force: true });
212
- }
193
+ };
194
+ return await runInDirectory(this.bbWorkingDirectory, operation);
213
195
  }
214
196
 
215
197
  /**
@@ -231,39 +213,13 @@ export class BBNativeProofCreator implements ProofCreator {
231
213
  if (result.status === BB_RESULT.FAILURE) {
232
214
  throw new Error(`Failed to generate verification key for ${circuitType}, ${result.reason}`);
233
215
  }
234
- return this.convertVk(result.vkPath!);
216
+ return extractVkData(result.vkPath!);
235
217
  });
236
218
  this.verificationKeys.set(circuitType, promise);
237
219
  }
238
220
  return await promise;
239
221
  }
240
222
 
241
- /**
242
- * Reads the verification key data stored at the specified location and parses into a VerificationKeyData
243
- * @param filePath - The directory containing the verification key data files
244
- * @returns The verification key data
245
- */
246
- private async convertVk(filePath: string): Promise<VerificationKeyData> {
247
- const [rawFields, rawBinary] = await Promise.all([
248
- fs.readFile(`${filePath}/${VK_FIELDS_FILENAME}`, { encoding: 'utf-8' }),
249
- fs.readFile(`${filePath}/${VK_FILENAME}`),
250
- ]);
251
- const fieldsJson = JSON.parse(rawFields);
252
- const fields = fieldsJson.map(Fr.fromString);
253
- // The first item is the hash, this is not part of the actual VK
254
- const vkHash = fields[0];
255
- const actualVk = fields.slice(1);
256
- const vk: VerificationKeyData = {
257
- hash: vkHash,
258
- keyAsFields: actualVk as Tuple<Fr, typeof VERIFICATION_KEY_LENGTH_IN_FIELDS>,
259
- keyAsBytes: rawBinary,
260
- numPublicInputs: Number(actualVk[CIRCUIT_PUBLIC_INPUTS_INDEX]),
261
- circuitSize: Number(actualVk[CIRCUIT_SIZE_INDEX]),
262
- isRecursive: actualVk[CIRCUIT_RECURSIVE_INDEX] == Fr.ONE,
263
- };
264
- return vk;
265
- }
266
-
267
223
  /**
268
224
  * Ensures our verification key cache includes the key data located at the specified directory
269
225
  * @param filePath - The directory containing the verification key data files
@@ -272,7 +228,7 @@ export class BBNativeProofCreator implements ProofCreator {
272
228
  private async updateVerificationKeyAfterProof(filePath: string, circuitType: ClientProtocolArtifact) {
273
229
  let promise = this.verificationKeys.get(circuitType);
274
230
  if (!promise) {
275
- promise = this.convertVk(filePath);
231
+ promise = extractVkData(filePath);
276
232
  this.log.debug(`Updated verification key for circuit: ${circuitType}`);
277
233
  this.verificationKeys.set(circuitType, promise);
278
234
  }
@@ -285,15 +241,10 @@ export class BBNativeProofCreator implements ProofCreator {
285
241
  convertInputs: (inputs: I) => WitnessMap,
286
242
  convertOutputs: (outputs: WitnessMap) => O,
287
243
  ): Promise<KernelProofOutput<O>> {
288
- const directory = `${this.bbWorkingDirectory}/${randomBytes(8).toString('hex')}`;
289
- await fs.mkdir(directory, { recursive: true });
290
- this.log.debug(`Created directory: ${directory}`);
291
- try {
244
+ const operation = async (directory: string) => {
292
245
  return await this.generateWitnessAndCreateProof(inputs, circuitType, directory, convertInputs, convertOutputs);
293
- } finally {
294
- await fs.rm(directory, { recursive: true, force: true });
295
- this.log.debug(`Deleted directory: ${directory}`);
296
- }
246
+ };
247
+ return await runInDirectory(this.bbWorkingDirectory, operation);
297
248
  }
298
249
 
299
250
  private async generateWitnessAndCreateProof<
@@ -314,14 +265,12 @@ export class BBNativeProofCreator implements ProofCreator {
314
265
  const outputWitness = await this.simulator.simulateCircuit(witnessMap, compiledCircuit);
315
266
  const output = convertOutputs(outputWitness);
316
267
 
317
- const inputSize = inputs.toBuffer().length;
318
- const outputSize = output.toBuffer().length;
319
268
  this.log.debug(`Generated witness for ${circuitType}`, {
320
269
  eventName: 'circuit-witness-generation',
321
270
  circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
322
271
  duration: timer.ms(),
323
- inputSize,
324
- outputSize,
272
+ inputSize: inputs.toBuffer().length,
273
+ outputSize: output.toBuffer().length,
325
274
  } satisfies CircuitWitnessGenerationStats);
326
275
 
327
276
  const proofOutput = await this.createProof(
@@ -329,8 +278,6 @@ export class BBNativeProofCreator implements ProofCreator {
329
278
  outputWitness,
330
279
  Buffer.from(compiledCircuit.bytecode, 'base64'),
331
280
  circuitType,
332
- inputSize,
333
- outputSize,
334
281
  );
335
282
  if (proofOutput.proof.proof.length != NESTED_RECURSIVE_PROOF_LENGTH) {
336
283
  throw new Error(`Incorrect proof length`);
@@ -350,8 +297,6 @@ export class BBNativeProofCreator implements ProofCreator {
350
297
  partialWitness: WitnessMap,
351
298
  bytecode: Buffer,
352
299
  circuitType: ClientProtocolArtifact | 'App',
353
- inputSize: number,
354
- outputSize: number,
355
300
  appCircuitName?: string,
356
301
  ): Promise<{
357
302
  proof: RecursiveProof<typeof RECURSIVE_PROOF_LENGTH> | RecursiveProof<typeof NESTED_RECURSIVE_PROOF_LENGTH>;
@@ -365,6 +310,10 @@ export class BBNativeProofCreator implements ProofCreator {
365
310
 
366
311
  this.log.debug(`Written ${inputsWitnessFile}`);
367
312
 
313
+ this.log.info(`Proving ${circuitType} circuit...`);
314
+
315
+ const timer = new Timer();
316
+
368
317
  const provingResult = await generateProof(
369
318
  this.bbBinaryPath,
370
319
  directory,
@@ -379,40 +328,45 @@ export class BBNativeProofCreator implements ProofCreator {
379
328
  throw new Error(provingResult.reason);
380
329
  }
381
330
 
331
+ this.log.info(
332
+ `Generated ${circuitType === 'App' ? appCircuitName : circuitType} circuit proof in ${timer.ms()} ms`,
333
+ );
334
+
382
335
  if (circuitType === 'App') {
383
- const vkData = await this.convertVk(directory);
336
+ const vkData = await extractVkData(directory);
384
337
  const proof = await this.readProofAsFields<typeof RECURSIVE_PROOF_LENGTH>(directory, circuitType, vkData);
385
338
 
386
339
  this.log.debug(`Generated proof`, {
387
340
  eventName: 'circuit-proving',
388
341
  circuitName: 'app-circuit',
389
342
  duration: provingResult.duration,
390
- inputSize,
391
- outputSize,
343
+ inputSize: compressedBincodedWitness.length,
392
344
  proofSize: proof.binaryProof.buffer.length,
393
345
  appCircuitName,
394
346
  circuitSize: vkData.circuitSize,
395
347
  numPublicInputs: vkData.numPublicInputs,
396
348
  } as CircuitProvingStats);
397
349
 
398
- return { proof, verificationKey: new VerificationKeyAsFields(vkData.keyAsFields, vkData.hash) };
350
+ return { proof, verificationKey: vkData.keyAsFields };
399
351
  }
400
352
 
401
353
  const vkData = await this.updateVerificationKeyAfterProof(directory, circuitType);
354
+
402
355
  const proof = await this.readProofAsFields<typeof NESTED_RECURSIVE_PROOF_LENGTH>(directory, circuitType, vkData);
403
356
 
357
+ await this.verifyProofForProtocolCircuit(circuitType, proof.binaryProof);
358
+
404
359
  this.log.debug(`Generated proof`, {
405
360
  circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
406
361
  duration: provingResult.duration,
407
362
  eventName: 'circuit-proving',
408
- inputSize,
409
- outputSize,
363
+ inputSize: compressedBincodedWitness.length,
410
364
  proofSize: proof.binaryProof.buffer.length,
411
365
  circuitSize: vkData.circuitSize,
412
366
  numPublicInputs: vkData.numPublicInputs,
413
367
  } as CircuitProvingStats);
414
368
 
415
- return { proof, verificationKey: new VerificationKeyAsFields(vkData.keyAsFields, vkData.hash) };
369
+ return { proof, verificationKey: vkData.keyAsFields };
416
370
  }
417
371
 
418
372
  /**
@@ -433,12 +387,16 @@ export class BBNativeProofCreator implements ProofCreator {
433
387
  const json = JSON.parse(proofString);
434
388
  const fields = json.map(Fr.fromString);
435
389
  const numPublicInputs =
436
- circuitType === 'App' ? vkData.numPublicInputs : vkData.numPublicInputs - AGGREGATION_OBJECT_SIZE;
390
+ circuitType === 'App' ? vkData.numPublicInputs : vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
437
391
  const fieldsWithoutPublicInputs = fields.slice(numPublicInputs);
438
392
  this.log.debug(
439
393
  `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}`,
440
394
  );
441
- const proof = new RecursiveProof<PROOF_LENGTH>(fieldsWithoutPublicInputs, new Proof(binaryProof));
395
+ const proof = new RecursiveProof<PROOF_LENGTH>(
396
+ fieldsWithoutPublicInputs,
397
+ new Proof(binaryProof, vkData.numPublicInputs),
398
+ true,
399
+ );
442
400
  return proof;
443
401
  }
444
402
  }