@aztec/bb-prover 0.0.1-commit.e558bd1c → 0.0.1-commit.e57c76e

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 (62) hide show
  1. package/dest/avm_proving_tests/avm_proving_tester.d.ts +13 -8
  2. package/dest/avm_proving_tests/avm_proving_tester.d.ts.map +1 -1
  3. package/dest/avm_proving_tests/avm_proving_tester.js +152 -110
  4. package/dest/bb/bb_js_backend.d.ts +196 -0
  5. package/dest/bb/bb_js_backend.d.ts.map +1 -0
  6. package/dest/bb/bb_js_backend.js +379 -0
  7. package/dest/bb/bb_js_debug.d.ts +52 -0
  8. package/dest/bb/bb_js_debug.d.ts.map +1 -0
  9. package/dest/bb/bb_js_debug.js +176 -0
  10. package/dest/bb/file_names.d.ts +4 -0
  11. package/dest/bb/file_names.d.ts.map +1 -0
  12. package/dest/bb/file_names.js +5 -0
  13. package/dest/config.d.ts +17 -1
  14. package/dest/config.d.ts.map +1 -1
  15. package/dest/index.d.ts +3 -2
  16. package/dest/index.d.ts.map +1 -1
  17. package/dest/index.js +2 -1
  18. package/dest/instrumentation.d.ts +1 -1
  19. package/dest/instrumentation.d.ts.map +1 -1
  20. package/dest/instrumentation.js +12 -4
  21. package/dest/prover/client/bb_private_kernel_prover.d.ts +10 -2
  22. package/dest/prover/client/bb_private_kernel_prover.d.ts.map +1 -1
  23. package/dest/prover/client/bb_private_kernel_prover.js +39 -5
  24. package/dest/prover/proof_utils.d.ts +11 -1
  25. package/dest/prover/proof_utils.d.ts.map +1 -1
  26. package/dest/prover/proof_utils.js +24 -1
  27. package/dest/prover/server/bb_prover.d.ts +4 -5
  28. package/dest/prover/server/bb_prover.d.ts.map +1 -1
  29. package/dest/prover/server/bb_prover.js +207 -78
  30. package/dest/verification_key/verification_key_data.js +1 -1
  31. package/dest/verifier/batch_chonk_verifier.d.ts +56 -0
  32. package/dest/verifier/batch_chonk_verifier.d.ts.map +1 -0
  33. package/dest/verifier/batch_chonk_verifier.js +384 -0
  34. package/dest/verifier/bb_verifier.d.ts +4 -1
  35. package/dest/verifier/bb_verifier.d.ts.map +1 -1
  36. package/dest/verifier/bb_verifier.js +134 -45
  37. package/dest/verifier/index.d.ts +2 -1
  38. package/dest/verifier/index.d.ts.map +1 -1
  39. package/dest/verifier/index.js +1 -0
  40. package/dest/verifier/queued_chonk_verifier.d.ts +2 -3
  41. package/dest/verifier/queued_chonk_verifier.d.ts.map +1 -1
  42. package/dest/verifier/queued_chonk_verifier.js +6 -5
  43. package/package.json +19 -17
  44. package/src/avm_proving_tests/avm_proving_tester.ts +53 -126
  45. package/src/bb/bb_js_backend.ts +435 -0
  46. package/src/bb/bb_js_debug.ts +227 -0
  47. package/src/bb/file_names.ts +6 -0
  48. package/src/config.ts +16 -0
  49. package/src/index.ts +2 -1
  50. package/src/instrumentation.ts +12 -4
  51. package/src/prover/client/bb_private_kernel_prover.ts +116 -4
  52. package/src/prover/proof_utils.ts +41 -1
  53. package/src/prover/server/bb_prover.ts +132 -137
  54. package/src/verification_key/verification_key_data.ts +1 -1
  55. package/src/verifier/batch_chonk_verifier.ts +415 -0
  56. package/src/verifier/bb_verifier.ts +66 -76
  57. package/src/verifier/index.ts +1 -0
  58. package/src/verifier/queued_chonk_verifier.ts +6 -7
  59. package/dest/bb/execute.d.ts +0 -107
  60. package/dest/bb/execute.d.ts.map +0 -1
  61. package/dest/bb/execute.js +0 -647
  62. package/src/bb/execute.ts +0 -678
@@ -1,3 +1,68 @@
1
+ function _ts_add_disposable_resource(env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose, inner;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ if (async) inner = dispose;
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ if (inner) dispose = function() {
16
+ try {
17
+ inner.call(this);
18
+ } catch (e) {
19
+ return Promise.reject(e);
20
+ }
21
+ };
22
+ env.stack.push({
23
+ value: value,
24
+ dispose: dispose,
25
+ async: async
26
+ });
27
+ } else if (async) {
28
+ env.stack.push({
29
+ async: true
30
+ });
31
+ }
32
+ return value;
33
+ }
34
+ function _ts_dispose_resources(env) {
35
+ var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
36
+ var e = new Error(message);
37
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
38
+ };
39
+ return (_ts_dispose_resources = function _ts_dispose_resources(env) {
40
+ function fail(e) {
41
+ env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
42
+ env.hasError = true;
43
+ }
44
+ var r, s = 0;
45
+ function next() {
46
+ while(r = env.stack.pop()){
47
+ try {
48
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
49
+ if (r.dispose) {
50
+ var result = r.dispose.call(r.value);
51
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
52
+ fail(e);
53
+ return next();
54
+ });
55
+ } else s |= 1;
56
+ } catch (e) {
57
+ fail(e);
58
+ }
59
+ }
60
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
61
+ if (env.hasError) throw env.error;
62
+ }
63
+ return next();
64
+ })(env);
65
+ }
1
66
  function applyDecs2203RFactory() {
2
67
  function createAddInitializerMethod(initializers, decoratorFinishedRef) {
3
68
  return function addInitializer(initializer) {
@@ -375,7 +440,6 @@ import { AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED, NESTED_RECURSIVE_PROOF_LENGTH, NE
375
440
  import { Fr } from '@aztec/foundation/curves/bn254';
376
441
  import { runInDirectory } from '@aztec/foundation/fs';
377
442
  import { createLogger } from '@aztec/foundation/log';
378
- import { BufferReader } from '@aztec/foundation/serialize';
379
443
  import { convertBlockMergeRollupOutputsFromWitnessMap, convertBlockMergeRollupPrivateInputsToWitnessMap, convertBlockRootEmptyTxFirstRollupOutputsFromWitnessMap, convertBlockRootEmptyTxFirstRollupPrivateInputsToWitnessMap, convertBlockRootFirstRollupOutputsFromWitnessMap, convertBlockRootFirstRollupPrivateInputsToWitnessMap, convertBlockRootRollupOutputsFromWitnessMap, convertBlockRootRollupPrivateInputsToWitnessMap, convertBlockRootSingleTxFirstRollupOutputsFromWitnessMap, convertBlockRootSingleTxFirstRollupPrivateInputsToWitnessMap, convertBlockRootSingleTxRollupOutputsFromWitnessMap, convertBlockRootSingleTxRollupPrivateInputsToWitnessMap, convertCheckpointMergeRollupOutputsFromWitnessMap, convertCheckpointMergeRollupPrivateInputsToWitnessMap, convertCheckpointPaddingRollupOutputsFromWitnessMap, convertCheckpointPaddingRollupPrivateInputsToWitnessMap, convertCheckpointRootRollupOutputsFromWitnessMap, convertCheckpointRootRollupPrivateInputsToWitnessMap, convertCheckpointRootSingleBlockRollupOutputsFromWitnessMap, convertCheckpointRootSingleBlockRollupPrivateInputsToWitnessMap, convertParityBaseOutputsFromWitnessMap, convertParityBasePrivateInputsToWitnessMap, convertParityRootOutputsFromWitnessMap, convertParityRootPrivateInputsToWitnessMap, convertPrivateTxBaseRollupOutputsFromWitnessMap, convertPrivateTxBaseRollupPrivateInputsToWitnessMap, convertPublicChonkVerifierOutputsFromWitnessMap, convertPublicChonkVerifierPrivateInputsToWitnessMap, convertPublicTxBaseRollupOutputsFromWitnessMap, convertPublicTxBaseRollupPrivateInputsToWitnessMap, convertRootRollupOutputsFromWitnessMap, convertRootRollupPrivateInputsToWitnessMap, convertTxMergeRollupOutputsFromWitnessMap, convertTxMergeRollupPrivateInputsToWitnessMap, getServerCircuitArtifact } from '@aztec/noir-protocol-circuits-types/server';
380
444
  import { ServerCircuitVks } from '@aztec/noir-protocol-circuits-types/server/vks';
381
445
  import { mapProtocolArtifactNameToCircuitName } from '@aztec/noir-protocol-circuits-types/types';
@@ -385,11 +449,12 @@ import { makePublicInputsAndRecursiveProof } from '@aztec/stdlib/interfaces/serv
385
449
  import { Proof, RecursiveProof, makeRecursiveProofFromBinary } from '@aztec/stdlib/proofs';
386
450
  import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
387
451
  import { promises as fs } from 'fs';
452
+ import { ungzip } from 'pako';
388
453
  import * as path from 'path';
389
- import { BB_RESULT, PROOF_FILENAME, PUBLIC_INPUTS_FILENAME, VK_FILENAME, generateAvmProof, generateProof, verifyAvmProof, verifyProof } from '../../bb/execute.js';
454
+ import { BBJsFactory } from '../../bb/bb_js_backend.js';
390
455
  import { getUltraHonkFlavorForCircuit } from '../../honk.js';
391
456
  import { ProverInstrumentation } from '../../instrumentation.js';
392
- import { readProofsFromOutputDirectory } from '../proof_utils.js';
457
+ import { constructRecursiveProofFromBuffers } from '../proof_utils.js';
393
458
  const logger = createLogger('bb-prover');
394
459
  _dec = trackSpan('BBNativeRollupProver.getBaseParityProof', {
395
460
  [Attributes.PROTOCOL_CIRCUIT_NAME]: 'parity-base'
@@ -422,10 +487,15 @@ _dec = trackSpan('BBNativeRollupProver.getBaseParityProof', {
422
487
  ], []));
423
488
  }
424
489
  instrumentation;
490
+ bbJsFactory;
425
491
  constructor(config, telemetry){
426
492
  this.config = config;
427
493
  _initProto(this);
428
494
  this.instrumentation = new ProverInstrumentation(telemetry, 'BBNativeRollupProver');
495
+ this.bbJsFactory = new BBJsFactory(config.bbBinaryPath, {
496
+ logger,
497
+ debugDir: config.bbDebugOutputDir
498
+ });
429
499
  }
430
500
  get tracer() {
431
501
  return this.instrumentation.tracer;
@@ -439,7 +509,7 @@ _dec = trackSpan('BBNativeRollupProver.getBaseParityProof', {
439
509
  await fs.mkdir(config.bbWorkingDirectory, {
440
510
  recursive: true
441
511
  });
442
- logger.info(`Using native BB at ${config.bbBinaryPath} and working directory ${config.bbWorkingDirectory}`);
512
+ logger.info(`Using bb.js API with binary at ${config.bbBinaryPath}`);
443
513
  logger.info(`Using native ACVM at ${config.acvmBinaryPath} and working directory ${config.acvmWorkingDirectory}`);
444
514
  return new BBNativeRollupProver(config, telemetry);
445
515
  }
@@ -545,15 +615,14 @@ _dec = trackSpan('BBNativeRollupProver.getBaseParityProof', {
545
615
  return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
546
616
  }
547
617
  async generateProofWithBB(input, circuitType, convertInput, convertOutput, workingDirectory) {
548
- // Have the ACVM write the partial witness here
618
+ // Have the ACVM write the partial witness here (still needs a temp directory)
549
619
  const outputWitnessFile = path.join(workingDirectory, 'partial-witness.gz');
550
620
  // Generate the partial witness using the ACVM
551
- // A further temp directory will be created beneath ours and then cleaned up after the partial witness has been copied to our specified location
552
621
  const simulator = new NativeACVMSimulator(this.config.acvmWorkingDirectory, this.config.acvmBinaryPath, outputWitnessFile, logger);
553
622
  const artifact = getServerCircuitArtifact(circuitType);
554
623
  logger.debug(`Generating witness data for ${circuitType}`);
555
624
  const inputWitness = convertInput(input);
556
- const foreignCallHandler = undefined; // We don't handle foreign calls in the native ACVM simulator
625
+ const foreignCallHandler = undefined;
557
626
  const witnessResult = await simulator.executeProtocolCircuit(inputWitness, artifact, foreignCallHandler);
558
627
  const output = convertOutput(witnessResult.witness);
559
628
  const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
@@ -567,49 +636,82 @@ _dec = trackSpan('BBNativeRollupProver.getBaseParityProof', {
567
636
  outputSize: output.toBuffer().length,
568
637
  eventName: 'circuit-witness-generation'
569
638
  });
570
- // Now prove the circuit from the generated witness
571
- logger.debug(`Proving ${circuitType}...`);
572
- const provingResult = await generateProof(this.config.bbBinaryPath, workingDirectory, circuitType, Buffer.from(artifact.bytecode, 'base64'), this.getVerificationKeyDataForCircuit(circuitType).keyAsBytes, outputWitnessFile, getUltraHonkFlavorForCircuit(circuitType), logger);
573
- if (provingResult.status === BB_RESULT.FAILURE) {
574
- logger.error(`Failed to generate proof for ${circuitType}: ${provingResult.reason}`);
575
- throw new ProvingError(provingResult.reason, provingResult, provingResult.retry);
639
+ // Read and decompress the witness for bb.js
640
+ const witnessGz = await fs.readFile(outputWitnessFile);
641
+ const witness = ungzip(witnessGz);
642
+ // Decompress bytecode for bb.js
643
+ const bytecode = ungzip(Buffer.from(artifact.bytecode, 'base64'));
644
+ // Prove the circuit via bb.js API
645
+ logger.debug(`Proving ${circuitType} via bb.js...`);
646
+ let proofResult;
647
+ try {
648
+ const env = {
649
+ stack: [],
650
+ error: void 0,
651
+ hasError: false
652
+ };
653
+ try {
654
+ const instance = _ts_add_disposable_resource(env, await this.bbJsFactory.getInstance(), true);
655
+ proofResult = await instance.generateProof(circuitType, bytecode, this.getVerificationKeyDataForCircuit(circuitType).keyAsBytes, witness, getUltraHonkFlavorForCircuit(circuitType));
656
+ } catch (e) {
657
+ env.error = e;
658
+ env.hasError = true;
659
+ } finally{
660
+ const result = _ts_dispose_resources(env);
661
+ if (result) await result;
662
+ }
663
+ } catch (error) {
664
+ throw new ProvingError(`Failed to generate proof for ${circuitType}: ${error}`);
576
665
  }
577
666
  return {
578
667
  circuitOutput: output,
579
- provingResult
668
+ proofResult
580
669
  };
581
670
  }
582
- async generateAvmProofWithBB(input, workingDirectory) {
583
- logger.info(`Proving avm-circuit for TX ${input.hints.tx.hash}...`);
584
- const provingResult = await generateAvmProof(this.config.bbBinaryPath, workingDirectory, input, logger);
585
- if (provingResult.status === BB_RESULT.FAILURE) {
586
- logger.error(`Failed to generate AVM proof for TX ${input.hints.tx.hash}: ${provingResult.reason}`);
587
- throw new ProvingError(provingResult.reason, provingResult, provingResult.retry);
588
- }
589
- return provingResult;
590
- }
591
671
  async createAvmProof(input) {
592
- const operation = async (bbWorkingDirectory)=>{
593
- const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory);
594
- const avmProof = await this.readAvmProofAsFields(provingResult.proofPath);
672
+ const env = {
673
+ stack: [],
674
+ error: void 0,
675
+ hasError: false
676
+ };
677
+ try {
678
+ logger.info(`Proving avm-circuit for TX ${input.hints.tx.hash}...`);
679
+ const inputsBuffer = input.serializeWithMessagePack();
680
+ const instance = _ts_add_disposable_resource(env, await this.bbJsFactory.getInstance(), true);
681
+ const { proof: proofFieldArrays, durationMs } = await instance.generateAvmProof(inputsBuffer);
682
+ // Convert Uint8Array[] (32-byte field elements) to Fr[]
683
+ const proofFields = proofFieldArrays.map((f)=>Fr.fromBuffer(Buffer.from(f)));
684
+ // Pad to fixed size (during development the proof length may vary)
685
+ if (proofFields.length > AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED) {
686
+ throw new Error(`Proof has ${proofFields.length} fields, expected no more than ${AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED}.`);
687
+ }
688
+ const proofFieldsPadded = proofFields.concat(Array(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED - proofFields.length).fill(new Fr(0)));
689
+ // Build the binary proof from the raw field data
690
+ const rawProofBuffer = Buffer.concat(proofFieldArrays.map((f)=>Buffer.from(f)));
691
+ const binaryProof = new Proof(rawProofBuffer, /*numPublicInputs=*/ 0);
692
+ const avmProof = new RecursiveProof(proofFieldsPadded, binaryProof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED);
595
693
  const circuitType = 'avm-circuit';
596
694
  const appCircuitName = 'unknown';
597
- this.instrumentation.recordAvmDuration('provingDuration', appCircuitName, provingResult.durationMs);
695
+ this.instrumentation.recordAvmDuration('provingDuration', appCircuitName, durationMs);
598
696
  this.instrumentation.recordAvmSize('proofSize', appCircuitName, avmProof.binaryProof.buffer.length);
599
- logger.info(`Generated proof for ${circuitType}(${input.hints.tx.hash}) in ${Math.ceil(provingResult.durationMs)} ms`, {
697
+ logger.info(`Generated proof for ${circuitType}(${input.hints.tx.hash}) in ${Math.ceil(durationMs)} ms`, {
600
698
  circuitName: circuitType,
601
699
  appCircuitName: input.hints.tx.hash,
602
- // does not include reading the proof from disk
603
- duration: provingResult.durationMs,
700
+ duration: durationMs,
604
701
  proofSize: avmProof.binaryProof.buffer.length,
605
702
  eventName: 'circuit-proving',
606
- inputSize: input.serializeWithMessagePack().length,
703
+ inputSize: inputsBuffer.length,
607
704
  circuitSize: 1 << 21,
608
705
  numPublicInputs: 0
609
706
  });
610
707
  return avmProof;
611
- };
612
- return await this.runInDirectory(operation);
708
+ } catch (e) {
709
+ env.error = e;
710
+ env.hasError = true;
711
+ } finally{
712
+ const result = _ts_dispose_resources(env);
713
+ if (result) await result;
714
+ }
613
715
  }
614
716
  /**
615
717
  * Executes a circuit and returns its outputs and corresponding proof with embedded aggregation object
@@ -620,21 +722,21 @@ _dec = trackSpan('BBNativeRollupProver.getBaseParityProof', {
620
722
  * @param convertOutput - Function for parsing the output witness to it's corresponding object
621
723
  * @returns The circuits output object and it's proof
622
724
  */ async createRecursiveProof(input, circuitType, proofLength, convertInput, convertOutput) {
623
- // this probably is gonna need to call chonk
624
- const operation = async (bbWorkingDirectory)=>{
625
- const { provingResult, circuitOutput: output } = await this.generateProofWithBB(input, circuitType, convertInput, convertOutput, bbWorkingDirectory);
725
+ // Still need runInDirectory for ACVM witness generation temp files
726
+ const operation = async (workingDirectory)=>{
727
+ const { proofResult, circuitOutput: output } = await this.generateProofWithBB(input, circuitType, convertInput, convertOutput, workingDirectory);
626
728
  const vkData = this.getVerificationKeyDataForCircuit(circuitType);
627
- // Read the proof as fields
628
- const proof = await readProofsFromOutputDirectory(provingResult.proofPath, vkData, proofLength, logger);
729
+ // Construct proof from in-memory buffers (no file I/O needed)
730
+ const proof = constructRecursiveProofFromBuffers(proofResult.proofFields, proofResult.publicInputFields, vkData, proofLength);
629
731
  const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
630
- this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs);
732
+ this.instrumentation.recordDuration('provingDuration', circuitName, proofResult.durationMs);
631
733
  this.instrumentation.recordSize('proofSize', circuitName, proof.binaryProof.buffer.length);
632
734
  this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs);
633
735
  this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize);
634
- logger.info(`Generated proof for ${circuitType} in ${Math.ceil(provingResult.durationMs)} ms, size: ${proof.proof.length} fields`, {
736
+ logger.info(`Generated proof for ${circuitType} in ${Math.ceil(proofResult.durationMs)} ms, size: ${proof.proof.length} fields`, {
635
737
  circuitName,
636
738
  circuitSize: vkData.circuitSize,
637
- duration: provingResult.durationMs,
739
+ duration: proofResult.durationMs,
638
740
  inputSize: output.toBuffer().length,
639
741
  proofSize: proof.binaryProof.buffer.length,
640
742
  eventName: 'circuit-proving',
@@ -648,35 +750,69 @@ _dec = trackSpan('BBNativeRollupProver.getBaseParityProof', {
648
750
  return await this.runInDirectory(operation);
649
751
  }
650
752
  /**
651
- * Verifies a proof, will generate the verification key if one is not cached internally
753
+ * Verifies a proof via bb.js API (no temp files needed).
652
754
  * @param circuitType - The type of circuit whose proof is to be verified
653
755
  * @param proof - The proof to be verified
654
756
  */ async verifyProof(circuitType, proof) {
655
757
  const verificationKey = this.getVerificationKeyDataForCircuit(circuitType);
656
- return await this.verifyInternal(proof, verificationKey, (proofPath, vkPath)=>verifyProof(this.config.bbBinaryPath, proofPath, vkPath, getUltraHonkFlavorForCircuit(circuitType), logger));
657
- }
658
- async verifyAvmProof(proof, publicInputs) {
659
- return await this.verifyInternal(proof, /*verificationKey=*/ undefined, (proofPath, /*unused*/ _vkPath)=>verifyAvmProof(this.config.bbBinaryPath, this.config.bbWorkingDirectory, proofPath, publicInputs, logger));
660
- }
661
- async verifyInternal(proof, verificationKey, verificationFunction) {
662
- const operation = async (bbWorkingDirectory)=>{
663
- const publicInputsFileName = path.join(bbWorkingDirectory, PUBLIC_INPUTS_FILENAME);
664
- const proofFileName = path.join(bbWorkingDirectory, PROOF_FILENAME);
665
- const verificationKeyPath = path.join(bbWorkingDirectory, VK_FILENAME);
666
- // TODO(https://github.com/AztecProtocol/aztec-packages/issues/13189): Put this proof parsing logic in the proof class.
667
- await fs.writeFile(publicInputsFileName, proof.buffer.subarray(0, proof.numPublicInputs * 32));
668
- await fs.writeFile(proofFileName, proof.buffer.subarray(proof.numPublicInputs * 32));
669
- if (verificationKey !== undefined) {
670
- await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes);
671
- }
672
- const result = await verificationFunction(proofFileName, verificationKeyPath);
673
- if (result.status === BB_RESULT.FAILURE) {
674
- const errorMessage = `Failed to verify proof from key!`;
675
- throw new ProvingError(errorMessage, result, result.retry);
758
+ const flavor = getUltraHonkFlavorForCircuit(circuitType);
759
+ // Split proof buffer into public input fields and proof fields (32-byte each)
760
+ const publicInputFields = splitBufferToFieldArrays(proof.buffer.subarray(0, proof.numPublicInputs * 32));
761
+ const proofFields = splitBufferToFieldArrays(proof.buffer.subarray(proof.numPublicInputs * 32));
762
+ let verified;
763
+ let durationMs;
764
+ try {
765
+ const env = {
766
+ stack: [],
767
+ error: void 0,
768
+ hasError: false
769
+ };
770
+ try {
771
+ const instance = _ts_add_disposable_resource(env, await this.bbJsFactory.getInstance(), true);
772
+ ({ verified, durationMs } = await instance.verifyProof(proofFields, verificationKey.keyAsBytes, publicInputFields, flavor));
773
+ } catch (e) {
774
+ env.error = e;
775
+ env.hasError = true;
776
+ } finally{
777
+ const result = _ts_dispose_resources(env);
778
+ if (result) await result;
676
779
  }
677
- logger.info(`Successfully verified proof from key in ${result.durationMs} ms`);
780
+ } catch (error) {
781
+ throw new ProvingError(`Failed to verify proof for ${circuitType}: ${error}`);
782
+ }
783
+ if (!verified) {
784
+ throw new ProvingError('Failed to verify proof from key!');
785
+ }
786
+ logger.info(`Successfully verified proof from key in ${durationMs} ms`);
787
+ }
788
+ /** Verify an AVM proof via bb.js API. */ async verifyAvmProof(proof, publicInputs) {
789
+ const env = {
790
+ stack: [],
791
+ error: void 0,
792
+ hasError: false
678
793
  };
679
- await this.runInDirectory(operation);
794
+ try {
795
+ // For AVM proofs, numPublicInputs is 0, so the full buffer is the proof.
796
+ const proofBuffer = proof.buffer.subarray(proof.numPublicInputs * 32);
797
+ // Split the raw proof buffer into 32-byte field element arrays
798
+ const proofFields = [];
799
+ for(let i = 0; i < proofBuffer.length; i += Fr.SIZE_IN_BYTES){
800
+ proofFields.push(new Uint8Array(proofBuffer.subarray(i, i + Fr.SIZE_IN_BYTES)));
801
+ }
802
+ const piBuffer = publicInputs.serializeWithMessagePack();
803
+ const instance = _ts_add_disposable_resource(env, await this.bbJsFactory.getInstance(), true);
804
+ const { verified, durationMs } = await instance.verifyAvmProof(proofFields, piBuffer);
805
+ if (!verified) {
806
+ throw new ProvingError('Failed to verify AVM proof!');
807
+ }
808
+ logger.info(`Successfully verified AVM proof in ${durationMs} ms`);
809
+ } catch (e) {
810
+ env.error = e;
811
+ env.hasError = true;
812
+ } finally{
813
+ const result = _ts_dispose_resources(env);
814
+ if (result) await result;
815
+ }
680
816
  }
681
817
  /**
682
818
  * Returns the verification key data for a circuit.
@@ -689,20 +825,6 @@ _dec = trackSpan('BBNativeRollupProver.getBaseParityProof', {
689
825
  }
690
826
  return vk;
691
827
  }
692
- async readAvmProofAsFields(proofFilename) {
693
- const rawProofBuffer = await fs.readFile(proofFilename);
694
- const reader = BufferReader.asReader(rawProofBuffer);
695
- const proofFields = reader.readArray(rawProofBuffer.length / Fr.SIZE_IN_BYTES, Fr);
696
- // We extend to a fixed-size padded proof as during development any new AVM circuit column changes the
697
- // proof length and we do not have a mechanism to feedback a cpp constant to noir/TS.
698
- // TODO(#13390): Revive a non-padded AVM proof
699
- if (proofFields.length > AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED) {
700
- throw new Error(`Proof has ${proofFields.length} fields, expected no more than ${AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED}.`);
701
- }
702
- const proofFieldsPadded = proofFields.concat(Array(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED - proofFields.length).fill(new Fr(0)));
703
- const proof = new Proof(rawProofBuffer, /*numPublicInputs=*/ 0);
704
- return new RecursiveProof(proofFieldsPadded, proof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED);
705
- }
706
828
  runInDirectory(fn) {
707
829
  return runInDirectory(this.config.bbWorkingDirectory, (dir)=>fn(dir).catch((err)=>{
708
830
  logger.error(`Error running operation at ${dir}: ${err}`);
@@ -710,3 +832,10 @@ _dec = trackSpan('BBNativeRollupProver.getBaseParityProof', {
710
832
  }), this.config.bbSkipCleanup, logger);
711
833
  }
712
834
  }
835
+ /** Split a buffer into 32-byte Uint8Array field elements. */ function splitBufferToFieldArrays(buffer) {
836
+ const fields = [];
837
+ for(let i = 0; i < buffer.length; i += 32){
838
+ fields.push(new Uint8Array(buffer.subarray(i, i + 32)));
839
+ }
840
+ return fields;
841
+ }
@@ -3,7 +3,7 @@ import { BufferReader } from '@aztec/foundation/serialize';
3
3
  import { VerificationKeyAsFields, VerificationKeyData } from '@aztec/stdlib/vks';
4
4
  import { promises as fs } from 'fs';
5
5
  import * as path from 'path';
6
- import { VK_FILENAME } from '../bb/execute.js';
6
+ import { VK_FILENAME } from '../bb/file_names.js';
7
7
  /**
8
8
  * Reads the verification key data stored at the specified location and parses into a VerificationKeyData
9
9
  * @param vkDirectoryPath - The directory containing the verification key data files
@@ -0,0 +1,56 @@
1
+ import type { ClientProtocolCircuitVerifier, IVCProofVerificationResult } from '@aztec/stdlib/interfaces/server';
2
+ import type { Tx } from '@aztec/stdlib/tx';
3
+ import type { BBConfig } from '../config.js';
4
+ /**
5
+ * Batch verifier for Chonk IVC proofs. Uses the bb batch verifier service
6
+ * which batches IPA verification into a constant number of SRS MSMs for better throughput.
7
+ *
8
+ * Architecture:
9
+ * - Spawns a persistent `bb msgpack run` process via Barretenberg (native backend)
10
+ * - Sends proofs via the msgpack RPC protocol (ChonkBatchVerifierQueue)
11
+ * - Receives results via a named FIFO pipe (async, out-of-order)
12
+ * - Bisects batch failures to isolate individual bad proofs
13
+ */
14
+ export declare class BatchChonkVerifier implements ClientProtocolCircuitVerifier {
15
+ private config;
16
+ private vkBuffers;
17
+ private batchSize;
18
+ private label;
19
+ private bb;
20
+ private fifoDir;
21
+ private fifoPath;
22
+ private nextRequestId;
23
+ private pendingRequests;
24
+ private sendQueue;
25
+ private fifoReader;
26
+ private logger;
27
+ /** Maps artifact name to VK index in the batch verifier. */
28
+ private vkIndexMap;
29
+ /** Bound cleanup handler for process exit signals. */
30
+ private exitCleanup;
31
+ private stopped;
32
+ private fatalError;
33
+ private pendingDrainedResolvers;
34
+ private constructor();
35
+ /** Create and start a BatchChonkVerifier using the protocol circuit VKs. */
36
+ static new(config: BBConfig, batchSize: number, label: string): Promise<BatchChonkVerifier>;
37
+ /** Create and start a BatchChonkVerifier with custom VKs (for testing). */
38
+ static newForTesting(config: Pick<BBConfig, 'bbChonkVerifyConcurrency'> & Partial<Pick<BBConfig, 'bbBinaryPath'>>, vks: Uint8Array[], batchSize: number): Promise<BatchChonkVerifier>;
39
+ private start;
40
+ verifyProof(tx: Tx): Promise<IVCProofVerificationResult>;
41
+ /** Enqueue raw proof fields for verification. Used directly by tests with custom VKs. */
42
+ enqueueProof(vkIndex: number, proofFields: Uint8Array[]): Promise<IVCProofVerificationResult>;
43
+ stop(): Promise<void>;
44
+ private withTimeout;
45
+ private startFifoReader;
46
+ private handleResult;
47
+ private registerExitCleanup;
48
+ private deregisterExitCleanup;
49
+ private rejectPendingRequests;
50
+ private failVerifier;
51
+ private waitForPendingRequestsToDrain;
52
+ private notifyPendingDrained;
53
+ private cleanupFifo;
54
+ private cleanupFifoSync;
55
+ }
56
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmF0Y2hfY2hvbmtfdmVyaWZpZXIuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92ZXJpZmllci9iYXRjaF9jaG9ua192ZXJpZmllci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNQSxPQUFPLEtBQUssRUFBRSw2QkFBNkIsRUFBRSwwQkFBMEIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2pILE9BQU8sS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBVTNDLE9BQU8sS0FBSyxFQUFFLFFBQVEsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQXdCN0M7Ozs7Ozs7OztHQVNHO0FBQ0gscUJBQWEsa0JBQW1CLFlBQVcsNkJBQTZCO0lBa0JwRSxPQUFPLENBQUMsTUFBTTtJQUNkLE9BQU8sQ0FBQyxTQUFTO0lBQ2pCLE9BQU8sQ0FBQyxTQUFTO0lBQ2pCLE9BQU8sQ0FBQyxLQUFLO0lBcEJmLE9BQU8sQ0FBQyxFQUFFLENBQWdCO0lBQzFCLE9BQU8sQ0FBQyxPQUFPLENBQXFCO0lBQ3BDLE9BQU8sQ0FBQyxRQUFRLENBQU07SUFDdEIsT0FBTyxDQUFDLGFBQWEsQ0FBSztJQUMxQixPQUFPLENBQUMsZUFBZSxDQUFxQztJQUM1RCxPQUFPLENBQUMsU0FBUyxDQUFjO0lBQy9CLE9BQU8sQ0FBQyxVQUFVLENBQWtCO0lBQ3BDLE9BQU8sQ0FBQyxNQUFNLENBQWtEO0lBQ2hFLDREQUE0RDtJQUM1RCxPQUFPLENBQUMsVUFBVSxDQUE2QjtJQUMvQyxzREFBc0Q7SUFDdEQsT0FBTyxDQUFDLFdBQVcsQ0FBNkI7SUFDaEQsT0FBTyxDQUFDLE9BQU8sQ0FBUztJQUN4QixPQUFPLENBQUMsVUFBVSxDQUFvQjtJQUN0QyxPQUFPLENBQUMsdUJBQXVCLENBQXlCO0lBRXhELE9BQU8sZUFTTjtJQUVELDRFQUE0RTtJQUM1RSxPQUFhLEdBQUcsQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FlaEc7SUFFRCwyRUFBMkU7SUFDM0UsT0FBYSxhQUFhLENBQ3hCLE1BQU0sRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLDBCQUEwQixDQUFDLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsY0FBYyxDQUFDLENBQUMsRUFDNUYsR0FBRyxFQUFFLFVBQVUsRUFBRSxFQUNqQixTQUFTLEVBQUUsTUFBTSxHQUNoQixPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FPN0I7WUFFYSxLQUFLO0lBaUNaLFdBQVcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxDQWU5RDtJQUVELHlGQUF5RjtJQUNsRixZQUFZLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLEdBQUcsT0FBTyxDQUFDLDBCQUEwQixDQUFDLENBa0RuRztJQUVZLElBQUksSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBK0JqQztZQU9hLFdBQVc7SUFrQnpCLE9BQU8sQ0FBQyxlQUFlO0lBNkJ2QixPQUFPLENBQUMsWUFBWTtJQTZCcEIsT0FBTyxDQUFDLG1CQUFtQjtJQU8zQixPQUFPLENBQUMscUJBQXFCO0lBTzdCLE9BQU8sQ0FBQyxxQkFBcUI7SUFTN0IsT0FBTyxDQUFDLFlBQVk7SUFPcEIsT0FBTyxDQUFDLDZCQUE2QjtJQTBCckMsT0FBTyxDQUFDLG9CQUFvQjtZQVNkLFdBQVc7SUFVekIsT0FBTyxDQUFDLGVBQWU7Q0FXeEIifQ==
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch_chonk_verifier.d.ts","sourceRoot":"","sources":["../../src/verifier/batch_chonk_verifier.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AACjH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAU3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAwB7C;;;;;;;;;GASG;AACH,qBAAa,kBAAmB,YAAW,6BAA6B;IAkBpE,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,KAAK;IApBf,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,eAAe,CAAqC;IAC5D,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,MAAM,CAAkD;IAChE,4DAA4D;IAC5D,OAAO,CAAC,UAAU,CAA6B;IAC/C,sDAAsD;IACtD,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,uBAAuB,CAAyB;IAExD,OAAO,eASN;IAED,4EAA4E;IAC5E,OAAa,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAehG;IAED,2EAA2E;IAC3E,OAAa,aAAa,CACxB,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,0BAA0B,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,EAC5F,GAAG,EAAE,UAAU,EAAE,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,CAAC,CAO7B;YAEa,KAAK;IAiCZ,WAAW,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAe9D;IAED,yFAAyF;IAClF,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAkDnG;IAEY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA+BjC;YAOa,WAAW;IAkBzB,OAAO,CAAC,eAAe;IA6BvB,OAAO,CAAC,YAAY;IA6BpB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,qBAAqB;IAO7B,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,6BAA6B;IA0BrC,OAAO,CAAC,oBAAoB;YASd,WAAW;IAUzB,OAAO,CAAC,eAAe;CAWxB"}