@aztec/bb-prover 0.0.1-commit.03f7ef2 → 0.0.1-commit.04d373f

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 (84) 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 -107
  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 +21 -43
  21. package/dest/prover/client/bb_private_kernel_prover.d.ts +18 -4
  22. package/dest/prover/client/bb_private_kernel_prover.d.ts.map +1 -1
  23. package/dest/prover/client/bb_private_kernel_prover.js +54 -8
  24. package/dest/prover/client/bundle.d.ts +3 -3
  25. package/dest/prover/client/bundle.d.ts.map +1 -1
  26. package/dest/prover/client/bundle.js +2 -3
  27. package/dest/prover/client/lazy.d.ts +3 -3
  28. package/dest/prover/client/lazy.d.ts.map +1 -1
  29. package/dest/prover/client/lazy.js +2 -3
  30. package/dest/prover/proof_utils.d.ts +11 -1
  31. package/dest/prover/proof_utils.d.ts.map +1 -1
  32. package/dest/prover/proof_utils.js +24 -1
  33. package/dest/prover/server/bb_prover.d.ts +8 -12
  34. package/dest/prover/server/bb_prover.d.ts.map +1 -1
  35. package/dest/prover/server/bb_prover.js +612 -107
  36. package/dest/test/delay_values.d.ts +1 -1
  37. package/dest/test/delay_values.d.ts.map +1 -1
  38. package/dest/test/delay_values.js +27 -25
  39. package/dest/test/index.d.ts +2 -1
  40. package/dest/test/index.d.ts.map +1 -1
  41. package/dest/test/index.js +1 -0
  42. package/dest/test/test_circuit_prover.d.ts +4 -4
  43. package/dest/test/test_circuit_prover.d.ts.map +1 -1
  44. package/dest/test/test_circuit_prover.js +462 -59
  45. package/dest/verification_key/verification_key_data.d.ts +1 -8
  46. package/dest/verification_key/verification_key_data.d.ts.map +1 -1
  47. package/dest/verification_key/verification_key_data.js +1 -20
  48. package/dest/verifier/batch_chonk_verifier.d.ts +45 -0
  49. package/dest/verifier/batch_chonk_verifier.d.ts.map +1 -0
  50. package/dest/verifier/batch_chonk_verifier.js +232 -0
  51. package/dest/verifier/bb_verifier.d.ts +4 -1
  52. package/dest/verifier/bb_verifier.d.ts.map +1 -1
  53. package/dest/verifier/bb_verifier.js +134 -48
  54. package/dest/verifier/index.d.ts +2 -1
  55. package/dest/verifier/index.d.ts.map +1 -1
  56. package/dest/verifier/index.js +1 -0
  57. package/dest/verifier/queued_chonk_verifier.d.ts +2 -3
  58. package/dest/verifier/queued_chonk_verifier.d.ts.map +1 -1
  59. package/dest/verifier/queued_chonk_verifier.js +15 -45
  60. package/package.json +20 -18
  61. package/src/avm_proving_tests/avm_proving_tester.ts +53 -136
  62. package/src/bb/bb_js_backend.ts +435 -0
  63. package/src/bb/bb_js_debug.ts +227 -0
  64. package/src/bb/file_names.ts +6 -0
  65. package/src/config.ts +16 -0
  66. package/src/index.ts +2 -1
  67. package/src/instrumentation.ts +20 -43
  68. package/src/prover/client/bb_private_kernel_prover.ts +135 -9
  69. package/src/prover/client/bundle.ts +3 -4
  70. package/src/prover/client/lazy.ts +3 -4
  71. package/src/prover/proof_utils.ts +41 -1
  72. package/src/prover/server/bb_prover.ts +138 -153
  73. package/src/test/delay_values.ts +28 -24
  74. package/src/test/index.ts +1 -0
  75. package/src/test/test_circuit_prover.ts +10 -13
  76. package/src/verification_key/verification_key_data.ts +1 -26
  77. package/src/verifier/batch_chonk_verifier.ts +276 -0
  78. package/src/verifier/bb_verifier.ts +66 -80
  79. package/src/verifier/index.ts +1 -0
  80. package/src/verifier/queued_chonk_verifier.ts +15 -47
  81. package/dest/bb/execute.d.ts +0 -107
  82. package/dest/bb/execute.d.ts.map +0 -1
  83. package/dest/bb/execute.js +0 -676
  84. package/src/bb/execute.ts +0 -706
@@ -9,7 +9,6 @@ import {
9
9
  import { Fr } from '@aztec/foundation/curves/bn254';
10
10
  import { runInDirectory } from '@aztec/foundation/fs';
11
11
  import { createLogger } from '@aztec/foundation/log';
12
- import { BufferReader } from '@aztec/foundation/serialize';
13
12
  import {
14
13
  type ServerProtocolArtifact,
15
14
  convertBlockMergeRollupOutputsFromWitnessMap,
@@ -55,10 +54,8 @@ import { NativeACVMSimulator } from '@aztec/simulator/server';
55
54
  import type { AvmCircuitInputs, AvmCircuitPublicInputs } from '@aztec/stdlib/avm';
56
55
  import { ProvingError } from '@aztec/stdlib/errors';
57
56
  import {
58
- type ProofAndVerificationKey,
59
57
  type PublicInputsAndRecursiveProof,
60
58
  type ServerCircuitProver,
61
- makeProofAndVerificationKey,
62
59
  makePublicInputsAndRecursiveProof,
63
60
  } from '@aztec/stdlib/interfaces/server';
64
61
  import type { ParityBasePrivateInputs, ParityPublicInputs, ParityRootPrivateInputs } from '@aztec/stdlib/parity';
@@ -86,29 +83,18 @@ import {
86
83
  type TxRollupPublicInputs,
87
84
  } from '@aztec/stdlib/rollup';
88
85
  import type { CircuitProvingStats, CircuitWitnessGenerationStats } from '@aztec/stdlib/stats';
89
- import type { VerificationKeyData } from '@aztec/stdlib/vks';
86
+ import { VerificationKeyData } from '@aztec/stdlib/vks';
90
87
  import { Attributes, type TelemetryClient, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
91
88
 
92
89
  import { promises as fs } from 'fs';
90
+ import { ungzip } from 'pako';
93
91
  import * as path from 'path';
94
92
 
95
- import {
96
- type BBFailure,
97
- type BBSuccess,
98
- BB_RESULT,
99
- PROOF_FILENAME,
100
- PUBLIC_INPUTS_FILENAME,
101
- VK_FILENAME,
102
- generateAvmProof,
103
- generateProof,
104
- verifyAvmProof,
105
- verifyProof,
106
- } from '../../bb/execute.js';
93
+ import { BBJsFactory, type BBJsProofResult } from '../../bb/bb_js_backend.js';
107
94
  import type { ACVMConfig, BBConfig } from '../../config.js';
108
- import { type UltraHonkFlavor, getUltraHonkFlavorForCircuit } from '../../honk.js';
95
+ import { getUltraHonkFlavorForCircuit } from '../../honk.js';
109
96
  import { ProverInstrumentation } from '../../instrumentation.js';
110
- import { extractAvmVkData } from '../../verification_key/verification_key_data.js';
111
- import { readProofsFromOutputDirectory } from '../proof_utils.js';
97
+ import { constructRecursiveProofFromBuffers } from '../proof_utils.js';
112
98
 
113
99
  const logger = createLogger('bb-prover');
114
100
 
@@ -122,12 +108,14 @@ export interface BBProverConfig extends BBConfig, ACVMConfig {
122
108
  */
123
109
  export class BBNativeRollupProver implements ServerCircuitProver {
124
110
  private instrumentation: ProverInstrumentation;
111
+ private bbJsFactory: BBJsFactory;
125
112
 
126
113
  constructor(
127
114
  private config: BBProverConfig,
128
115
  telemetry: TelemetryClient,
129
116
  ) {
130
117
  this.instrumentation = new ProverInstrumentation(telemetry, 'BBNativeRollupProver');
118
+ this.bbJsFactory = new BBJsFactory(config.bbBinaryPath, { logger, debugDir: config.bbDebugOutputDir });
131
119
  }
132
120
 
133
121
  get tracer() {
@@ -139,7 +127,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
139
127
  await fs.mkdir(config.acvmWorkingDirectory, { recursive: true });
140
128
  await fs.access(config.bbBinaryPath, fs.constants.R_OK);
141
129
  await fs.mkdir(config.bbWorkingDirectory, { recursive: true });
142
- logger.info(`Using native BB at ${config.bbBinaryPath} and working directory ${config.bbWorkingDirectory}`);
130
+ logger.info(`Using bb.js API with binary at ${config.bbBinaryPath}`);
143
131
  logger.info(`Using native ACVM at ${config.acvmBinaryPath} and working directory ${config.acvmWorkingDirectory}`);
144
132
 
145
133
  return new BBNativeRollupProver(config, telemetry);
@@ -191,10 +179,10 @@ export class BBNativeRollupProver implements ServerCircuitProver {
191
179
  }))
192
180
  public async getAvmProof(
193
181
  inputs: AvmCircuitInputs,
194
- ): Promise<ProofAndVerificationKey<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
195
- const proofAndVk = await this.createAvmProof(inputs);
196
- await this.verifyAvmProof(proofAndVk.proof.binaryProof, proofAndVk.verificationKey, inputs.publicInputs);
197
- return proofAndVk;
182
+ ): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
183
+ const proof = await this.createAvmProof(inputs);
184
+ await this.verifyAvmProof(proof.binaryProof, inputs.publicInputs);
185
+ return proof;
198
186
  }
199
187
 
200
188
  public async getPublicChonkVerifierProof(
@@ -456,16 +444,16 @@ export class BBNativeRollupProver implements ServerCircuitProver {
456
444
  convertInput: (input: Input) => WitnessMap,
457
445
  convertOutput: (outputWitness: WitnessMap) => Output,
458
446
  workingDirectory: string,
459
- ): Promise<{ circuitOutput: Output; provingResult: BBSuccess }> {
460
- // Have the ACVM write the partial witness here
447
+ ): Promise<{ circuitOutput: Output; proofResult: BBJsProofResult }> {
448
+ // Have the ACVM write the partial witness here (still needs a temp directory)
461
449
  const outputWitnessFile = path.join(workingDirectory, 'partial-witness.gz');
462
450
 
463
451
  // Generate the partial witness using the ACVM
464
- // A further temp directory will be created beneath ours and then cleaned up after the partial witness has been copied to our specified location
465
452
  const simulator = new NativeACVMSimulator(
466
453
  this.config.acvmWorkingDirectory,
467
454
  this.config.acvmBinaryPath,
468
455
  outputWitnessFile,
456
+ logger,
469
457
  );
470
458
 
471
459
  const artifact = getServerCircuitArtifact(circuitType);
@@ -473,7 +461,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
473
461
  logger.debug(`Generating witness data for ${circuitType}`);
474
462
 
475
463
  const inputWitness = convertInput(input);
476
- const foreignCallHandler = undefined; // We don't handle foreign calls in the native ACVM simulator
464
+ const foreignCallHandler = undefined;
477
465
  const witnessResult = await simulator.executeProtocolCircuit(inputWitness, artifact, foreignCallHandler);
478
466
  const output = convertOutput(witnessResult.witness);
479
467
 
@@ -490,76 +478,80 @@ export class BBNativeRollupProver implements ServerCircuitProver {
490
478
  eventName: 'circuit-witness-generation',
491
479
  } satisfies CircuitWitnessGenerationStats);
492
480
 
493
- // Now prove the circuit from the generated witness
494
- logger.debug(`Proving ${circuitType}...`);
481
+ // Read and decompress the witness for bb.js
482
+ const witnessGz = await fs.readFile(outputWitnessFile);
483
+ const witness = ungzip(witnessGz);
495
484
 
496
- const provingResult = await generateProof(
497
- this.config.bbBinaryPath,
498
- workingDirectory,
499
- circuitType,
500
- Buffer.from(artifact.bytecode, 'base64'),
501
- this.getVerificationKeyDataForCircuit(circuitType).keyAsBytes,
502
- outputWitnessFile,
503
- getUltraHonkFlavorForCircuit(circuitType),
504
- logger,
505
- );
485
+ // Decompress bytecode for bb.js
486
+ const bytecode = ungzip(Buffer.from(artifact.bytecode, 'base64'));
506
487
 
507
- if (provingResult.status === BB_RESULT.FAILURE) {
508
- logger.error(`Failed to generate proof for ${circuitType}: ${provingResult.reason}`);
509
- throw new ProvingError(provingResult.reason, provingResult, provingResult.retry);
488
+ // Prove the circuit via bb.js API
489
+ logger.debug(`Proving ${circuitType} via bb.js...`);
490
+
491
+ let proofResult: BBJsProofResult;
492
+ try {
493
+ await using instance = await this.bbJsFactory.getInstance();
494
+ proofResult = await instance.generateProof(
495
+ circuitType,
496
+ bytecode,
497
+ this.getVerificationKeyDataForCircuit(circuitType).keyAsBytes,
498
+ witness,
499
+ getUltraHonkFlavorForCircuit(circuitType),
500
+ );
501
+ } catch (error) {
502
+ throw new ProvingError(`Failed to generate proof for ${circuitType}: ${error}`);
510
503
  }
511
504
 
512
505
  return {
513
506
  circuitOutput: output,
514
- provingResult,
507
+ proofResult,
515
508
  };
516
509
  }
517
510
 
518
- private async generateAvmProofWithBB(input: AvmCircuitInputs, workingDirectory: string): Promise<BBSuccess> {
511
+ private async createAvmProof(
512
+ input: AvmCircuitInputs,
513
+ ): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
519
514
  logger.info(`Proving avm-circuit for TX ${input.hints.tx.hash}...`);
520
515
 
521
- const provingResult = await generateAvmProof(this.config.bbBinaryPath, workingDirectory, input, logger);
516
+ const inputsBuffer = input.serializeWithMessagePack();
517
+ await using instance = await this.bbJsFactory.getInstance();
518
+ const { proof: proofFieldArrays, durationMs } = await instance.generateAvmProof(inputsBuffer);
522
519
 
523
- if (provingResult.status === BB_RESULT.FAILURE) {
524
- logger.error(`Failed to generate AVM proof for TX ${input.hints.tx.hash}: ${provingResult.reason}`);
525
- throw new ProvingError(provingResult.reason, provingResult, provingResult.retry);
526
- }
527
-
528
- return provingResult;
529
- }
520
+ // Convert Uint8Array[] (32-byte field elements) to Fr[]
521
+ const proofFields = proofFieldArrays.map(f => Fr.fromBuffer(Buffer.from(f)));
530
522
 
531
- private async createAvmProof(
532
- input: AvmCircuitInputs,
533
- ): Promise<ProofAndVerificationKey<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
534
- const operation = async (bbWorkingDirectory: string) => {
535
- const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory);
523
+ // Pad to fixed size (during development the proof length may vary)
524
+ if (proofFields.length > AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED) {
525
+ throw new Error(
526
+ `Proof has ${proofFields.length} fields, expected no more than ${AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED}.`,
527
+ );
528
+ }
529
+ const proofFieldsPadded = proofFields.concat(
530
+ Array(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED - proofFields.length).fill(new Fr(0)),
531
+ );
536
532
 
537
- const avmVK = await extractAvmVkData(provingResult.vkDirectoryPath!);
538
- const avmProof = await this.readAvmProofAsFields(provingResult.proofPath!);
533
+ // Build the binary proof from the raw field data
534
+ const rawProofBuffer = Buffer.concat(proofFieldArrays.map(f => Buffer.from(f)));
535
+ const binaryProof = new Proof(rawProofBuffer, /*numPublicInputs=*/ 0);
536
+ const avmProof = new RecursiveProof(proofFieldsPadded, binaryProof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED);
539
537
 
540
- const circuitType = 'avm-circuit' as const;
541
- const appCircuitName = 'unknown' as const;
542
- this.instrumentation.recordAvmDuration('provingDuration', appCircuitName, provingResult.durationMs);
543
- this.instrumentation.recordAvmSize('proofSize', appCircuitName, avmProof.binaryProof.buffer.length);
538
+ const circuitType = 'avm-circuit' as const;
539
+ const appCircuitName = 'unknown' as const;
540
+ this.instrumentation.recordAvmDuration('provingDuration', appCircuitName, durationMs);
541
+ this.instrumentation.recordAvmSize('proofSize', appCircuitName, avmProof.binaryProof.buffer.length);
544
542
 
545
- logger.info(
546
- `Generated proof for ${circuitType}(${input.hints.tx.hash}) in ${Math.ceil(provingResult.durationMs)} ms`,
547
- {
548
- circuitName: circuitType,
549
- appCircuitName: input.hints.tx.hash,
550
- // does not include reading the proof from disk
551
- duration: provingResult.durationMs,
552
- proofSize: avmProof.binaryProof.buffer.length,
553
- eventName: 'circuit-proving',
554
- inputSize: input.serializeWithMessagePack().length,
555
- circuitSize: 1 << 21,
556
- numPublicInputs: 0,
557
- } satisfies CircuitProvingStats,
558
- );
543
+ logger.info(`Generated proof for ${circuitType}(${input.hints.tx.hash}) in ${Math.ceil(durationMs)} ms`, {
544
+ circuitName: circuitType,
545
+ appCircuitName: input.hints.tx.hash,
546
+ duration: durationMs,
547
+ proofSize: avmProof.binaryProof.buffer.length,
548
+ eventName: 'circuit-proving',
549
+ inputSize: inputsBuffer.length,
550
+ circuitSize: 1 << 21,
551
+ numPublicInputs: 0,
552
+ } satisfies CircuitProvingStats);
559
553
 
560
- return makeProofAndVerificationKey(avmProof, avmVK);
561
- };
562
- return await this.runInDirectory(operation);
554
+ return avmProof;
563
555
  }
564
556
 
565
557
  /**
@@ -582,33 +574,38 @@ export class BBNativeRollupProver implements ServerCircuitProver {
582
574
  convertInput: (input: CircuitInputType) => WitnessMap,
583
575
  convertOutput: (outputWitness: WitnessMap) => CircuitOutputType,
584
576
  ): Promise<{ circuitOutput: CircuitOutputType; proof: RecursiveProof<PROOF_LENGTH> }> {
585
- // this probably is gonna need to call chonk
586
- const operation = async (bbWorkingDirectory: string) => {
587
- const { provingResult, circuitOutput: output } = await this.generateProofWithBB(
577
+ // Still need runInDirectory for ACVM witness generation temp files
578
+ const operation = async (workingDirectory: string) => {
579
+ const { proofResult, circuitOutput: output } = await this.generateProofWithBB(
588
580
  input,
589
581
  circuitType,
590
582
  convertInput,
591
583
  convertOutput,
592
- bbWorkingDirectory,
584
+ workingDirectory,
593
585
  );
594
586
 
595
587
  const vkData = this.getVerificationKeyDataForCircuit(circuitType);
596
- // Read the proof as fields
597
- const proof = await readProofsFromOutputDirectory(provingResult.proofPath!, vkData, proofLength, logger);
588
+ // Construct proof from in-memory buffers (no file I/O needed)
589
+ const proof = constructRecursiveProofFromBuffers(
590
+ proofResult.proofFields,
591
+ proofResult.publicInputFields,
592
+ vkData,
593
+ proofLength,
594
+ );
598
595
 
599
596
  const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
600
- this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs);
597
+ this.instrumentation.recordDuration('provingDuration', circuitName, proofResult.durationMs);
601
598
  this.instrumentation.recordSize('proofSize', circuitName, proof.binaryProof.buffer.length);
602
599
  this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs);
603
600
  this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize);
604
601
  logger.info(
605
- `Generated proof for ${circuitType} in ${Math.ceil(provingResult.durationMs)} ms, size: ${
602
+ `Generated proof for ${circuitType} in ${Math.ceil(proofResult.durationMs)} ms, size: ${
606
603
  proof.proof.length
607
604
  } fields`,
608
605
  {
609
606
  circuitName,
610
607
  circuitSize: vkData.circuitSize,
611
- duration: provingResult.durationMs,
608
+ duration: proofResult.durationMs,
612
609
  inputSize: output.toBuffer().length,
613
610
  proofSize: proof.binaryProof.buffer.length,
614
611
  eventName: 'circuit-proving',
@@ -625,56 +622,58 @@ export class BBNativeRollupProver implements ServerCircuitProver {
625
622
  }
626
623
 
627
624
  /**
628
- * Verifies a proof, will generate the verification key if one is not cached internally
625
+ * Verifies a proof via bb.js API (no temp files needed).
629
626
  * @param circuitType - The type of circuit whose proof is to be verified
630
627
  * @param proof - The proof to be verified
631
628
  */
632
629
  public async verifyProof(circuitType: ServerProtocolArtifact, proof: Proof) {
633
630
  const verificationKey = this.getVerificationKeyDataForCircuit(circuitType);
634
- return await this.verifyWithKey(getUltraHonkFlavorForCircuit(circuitType), verificationKey, proof);
635
- }
631
+ const flavor = getUltraHonkFlavorForCircuit(circuitType);
632
+
633
+ // Split proof buffer into public input fields and proof fields (32-byte each)
634
+ const publicInputFields = splitBufferToFieldArrays(proof.buffer.subarray(0, proof.numPublicInputs * 32));
635
+ const proofFields = splitBufferToFieldArrays(proof.buffer.subarray(proof.numPublicInputs * 32));
636
+
637
+ let verified: boolean;
638
+ let durationMs: number;
639
+ try {
640
+ await using instance = await this.bbJsFactory.getInstance();
641
+ ({ verified, durationMs } = await instance.verifyProof(
642
+ proofFields,
643
+ verificationKey.keyAsBytes,
644
+ publicInputFields,
645
+ flavor,
646
+ ));
647
+ } catch (error) {
648
+ throw new ProvingError(`Failed to verify proof for ${circuitType}: ${error}`);
649
+ }
636
650
 
637
- public async verifyAvmProof(
638
- proof: Proof,
639
- verificationKey: VerificationKeyData,
640
- publicInputs: AvmCircuitPublicInputs,
641
- ) {
642
- return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath) =>
643
- verifyAvmProof(this.config.bbBinaryPath, this.config.bbWorkingDirectory, proofPath, publicInputs, vkPath, logger),
644
- );
645
- }
651
+ if (!verified) {
652
+ throw new ProvingError('Failed to verify proof from key!');
653
+ }
646
654
 
647
- public async verifyWithKey(flavor: UltraHonkFlavor, verificationKey: VerificationKeyData, proof: Proof) {
648
- return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath) =>
649
- verifyProof(this.config.bbBinaryPath, proofPath, vkPath, flavor, logger),
650
- );
655
+ logger.info(`Successfully verified proof from key in ${durationMs} ms`);
651
656
  }
652
657
 
653
- private async verifyWithKeyInternal(
654
- proof: Proof,
655
- verificationKey: { keyAsBytes: Buffer },
656
- verificationFunction: (proofPath: string, vkPath: string) => Promise<BBFailure | BBSuccess>,
657
- ) {
658
- const operation = async (bbWorkingDirectory: string) => {
659
- const publicInputsFileName = path.join(bbWorkingDirectory, PUBLIC_INPUTS_FILENAME);
660
- const proofFileName = path.join(bbWorkingDirectory, PROOF_FILENAME);
661
- const verificationKeyPath = path.join(bbWorkingDirectory, VK_FILENAME);
662
- // TODO(https://github.com/AztecProtocol/aztec-packages/issues/13189): Put this proof parsing logic in the proof class.
663
- await fs.writeFile(publicInputsFileName, proof.buffer.slice(0, proof.numPublicInputs * 32));
664
- await fs.writeFile(proofFileName, proof.buffer.slice(proof.numPublicInputs * 32));
665
- await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes);
666
-
667
- const result = await verificationFunction(proofFileName, verificationKeyPath!);
668
-
669
- if (result.status === BB_RESULT.FAILURE) {
670
- const errorMessage = `Failed to verify proof from key!`;
671
- throw new ProvingError(errorMessage, result, result.retry);
672
- }
673
-
674
- logger.info(`Successfully verified proof from key in ${result.durationMs} ms`);
675
- };
658
+ /** Verify an AVM proof via bb.js API. */
659
+ public async verifyAvmProof(proof: Proof, publicInputs: AvmCircuitPublicInputs) {
660
+ // For AVM proofs, numPublicInputs is 0, so the full buffer is the proof.
661
+ const proofBuffer = proof.buffer.subarray(proof.numPublicInputs * 32);
662
+ // Split the raw proof buffer into 32-byte field element arrays
663
+ const proofFields: Uint8Array[] = [];
664
+ for (let i = 0; i < proofBuffer.length; i += Fr.SIZE_IN_BYTES) {
665
+ proofFields.push(new Uint8Array(proofBuffer.subarray(i, i + Fr.SIZE_IN_BYTES)));
666
+ }
667
+ const piBuffer = publicInputs.serializeWithMessagePack();
676
668
 
677
- await this.runInDirectory(operation);
669
+ await using instance = await this.bbJsFactory.getInstance();
670
+ const { verified, durationMs } = await instance.verifyAvmProof(proofFields, piBuffer);
671
+
672
+ if (!verified) {
673
+ throw new ProvingError('Failed to verify AVM proof!');
674
+ }
675
+
676
+ logger.info(`Successfully verified AVM proof in ${durationMs} ms`);
678
677
  }
679
678
 
680
679
  /**
@@ -690,29 +689,6 @@ export class BBNativeRollupProver implements ServerCircuitProver {
690
689
  return vk;
691
690
  }
692
691
 
693
- private async readAvmProofAsFields(
694
- proofFilename: string,
695
- ): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
696
- const rawProofBuffer = await fs.readFile(proofFilename);
697
- const reader = BufferReader.asReader(rawProofBuffer);
698
- const proofFields = reader.readArray(rawProofBuffer.length / Fr.SIZE_IN_BYTES, Fr);
699
-
700
- // We extend to a fixed-size padded proof as during development any new AVM circuit column changes the
701
- // proof length and we do not have a mechanism to feedback a cpp constant to noir/TS.
702
- // TODO(#13390): Revive a non-padded AVM proof
703
- if (proofFields.length > AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED) {
704
- throw new Error(
705
- `Proof has ${proofFields.length} fields, expected no more than ${AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED}.`,
706
- );
707
- }
708
- const proofFieldsPadded = proofFields.concat(
709
- Array(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED - proofFields.length).fill(new Fr(0)),
710
- );
711
-
712
- const proof = new Proof(rawProofBuffer, /*numPublicInputs=*/ 0);
713
- return new RecursiveProof(proofFieldsPadded, proof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED);
714
- }
715
-
716
692
  private runInDirectory<T>(fn: (dir: string) => Promise<T>) {
717
693
  return runInDirectory(
718
694
  this.config.bbWorkingDirectory,
@@ -726,3 +702,12 @@ export class BBNativeRollupProver implements ServerCircuitProver {
726
702
  );
727
703
  }
728
704
  }
705
+
706
+ /** Split a buffer into 32-byte Uint8Array field elements. */
707
+ function splitBufferToFieldArrays(buffer: Buffer): Uint8Array[] {
708
+ const fields: Uint8Array[] = [];
709
+ for (let i = 0; i < buffer.length; i += 32) {
710
+ fields.push(new Uint8Array(buffer.subarray(i, i + 32)));
711
+ }
712
+ return fields;
713
+ }
@@ -1,43 +1,47 @@
1
1
  import { ProvingRequestType } from '@aztec/stdlib/proofs';
2
2
 
3
3
  export const WITGEN_DELAY_MS: Record<ProvingRequestType, number> = {
4
- [ProvingRequestType.PARITY_BASE]: 2_000,
5
- [ProvingRequestType.BLOCK_MERGE_ROLLUP]: 30,
4
+ [ProvingRequestType.PUBLIC_CHONK_VERIFIER]: 60,
5
+ [ProvingRequestType.PARITY_BASE]: 1_600,
6
+ [ProvingRequestType.PARITY_ROOT]: 40,
6
7
  [ProvingRequestType.BLOCK_ROOT_FIRST_ROLLUP]: 45,
7
- [ProvingRequestType.BLOCK_ROOT_SINGLE_TX_FIRST_ROLLUP]: 27,
8
8
  [ProvingRequestType.BLOCK_ROOT_EMPTY_TX_FIRST_ROLLUP]: 18,
9
+ [ProvingRequestType.BLOCK_ROOT_SINGLE_TX_FIRST_ROLLUP]: 27,
10
+ [ProvingRequestType.CHECKPOINT_MERGE_ROLLUP]: 30,
11
+ [ProvingRequestType.CHECKPOINT_ROOT_SINGLE_BLOCK_ROLLUP]: 36_000,
12
+ [ProvingRequestType.ROOT_ROLLUP]: 35,
13
+ [ProvingRequestType.PUBLIC_TX_BASE_ROLLUP]: 2_500,
14
+ [ProvingRequestType.TX_MERGE_ROLLUP]: 25,
15
+ [ProvingRequestType.PUBLIC_VM]: 0,
16
+
17
+ // TBD
18
+ [ProvingRequestType.BLOCK_MERGE_ROLLUP]: 30,
9
19
  [ProvingRequestType.BLOCK_ROOT_ROLLUP]: 40_000,
10
20
  [ProvingRequestType.BLOCK_ROOT_SINGLE_TX_ROLLUP]: 20_000,
11
21
  [ProvingRequestType.CHECKPOINT_ROOT_ROLLUP]: 40_000,
12
- [ProvingRequestType.CHECKPOINT_ROOT_SINGLE_BLOCK_ROLLUP]: 36_600,
13
22
  [ProvingRequestType.CHECKPOINT_PADDING_ROLLUP]: 0,
14
- [ProvingRequestType.CHECKPOINT_MERGE_ROLLUP]: 30,
15
- [ProvingRequestType.TX_MERGE_ROLLUP]: 0,
16
23
  [ProvingRequestType.PRIVATE_TX_BASE_ROLLUP]: 2_500, // Guess based on public
17
- [ProvingRequestType.PUBLIC_TX_BASE_ROLLUP]: 2_500,
18
- [ProvingRequestType.PARITY_ROOT]: 40,
19
- [ProvingRequestType.ROOT_ROLLUP]: 35,
20
- [ProvingRequestType.PUBLIC_CHONK_VERIFIER]: 60,
21
- [ProvingRequestType.PUBLIC_VM]: 0,
22
24
  };
23
25
 
24
26
  export const PROOF_DELAY_MS: Record<ProvingRequestType, number> = {
25
- [ProvingRequestType.PARITY_BASE]: 16_300,
27
+ [ProvingRequestType.PUBLIC_CHONK_VERIFIER]: 16_300,
28
+ [ProvingRequestType.PARITY_BASE]: 15_300,
29
+ [ProvingRequestType.PARITY_ROOT]: 18_600,
30
+ [ProvingRequestType.BLOCK_ROOT_FIRST_ROLLUP]: 17_400,
31
+ [ProvingRequestType.BLOCK_ROOT_EMPTY_TX_FIRST_ROLLUP]: 4_500,
32
+ [ProvingRequestType.BLOCK_ROOT_SINGLE_TX_FIRST_ROLLUP]: 9_200,
33
+ [ProvingRequestType.CHECKPOINT_MERGE_ROLLUP]: 10_200,
34
+ [ProvingRequestType.CHECKPOINT_ROOT_SINGLE_BLOCK_ROLLUP]: 37_100,
35
+ [ProvingRequestType.ROOT_ROLLUP]: 93_000,
36
+ [ProvingRequestType.TX_MERGE_ROLLUP]: 10_000,
37
+ [ProvingRequestType.PUBLIC_TX_BASE_ROLLUP]: 44_500,
38
+ [ProvingRequestType.PUBLIC_VM]: 180_000,
39
+
40
+ // TBD
26
41
  [ProvingRequestType.BLOCK_MERGE_ROLLUP]: 15_000,
27
- [ProvingRequestType.BLOCK_ROOT_FIRST_ROLLUP]: 16_500,
28
- [ProvingRequestType.BLOCK_ROOT_SINGLE_TX_FIRST_ROLLUP]: 9_210,
29
- [ProvingRequestType.BLOCK_ROOT_EMPTY_TX_FIRST_ROLLUP]: 4_560,
30
42
  [ProvingRequestType.BLOCK_ROOT_ROLLUP]: 35_000,
31
43
  [ProvingRequestType.BLOCK_ROOT_SINGLE_TX_ROLLUP]: 15_000,
32
44
  [ProvingRequestType.CHECKPOINT_ROOT_ROLLUP]: 35_000,
33
- [ProvingRequestType.CHECKPOINT_ROOT_SINGLE_BLOCK_ROLLUP]: 38_800,
34
45
  [ProvingRequestType.CHECKPOINT_PADDING_ROLLUP]: 0,
35
- [ProvingRequestType.CHECKPOINT_MERGE_ROLLUP]: 9_760,
36
- [ProvingRequestType.TX_MERGE_ROLLUP]: 0,
37
- [ProvingRequestType.PRIVATE_TX_BASE_ROLLUP]: 45_000, // Guess based on public
38
- [ProvingRequestType.PUBLIC_TX_BASE_ROLLUP]: 45_000,
39
- [ProvingRequestType.PARITY_ROOT]: 18_600,
40
- [ProvingRequestType.ROOT_ROLLUP]: 84_000,
41
- [ProvingRequestType.PUBLIC_CHONK_VERIFIER]: 16_300,
42
- [ProvingRequestType.PUBLIC_VM]: 0,
46
+ [ProvingRequestType.PRIVATE_TX_BASE_ROLLUP]: 22_000,
43
47
  };
package/src/test/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './test_circuit_prover.js';
2
2
  export * from './test_verifier.js';
3
+ export * from './delay_values.js';
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED,
3
- AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED,
4
3
  NESTED_RECURSIVE_PROOF_LENGTH,
5
4
  NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
6
5
  RECURSIVE_PROOF_LENGTH,
@@ -51,14 +50,18 @@ import type { WitnessMap } from '@aztec/noir-types';
51
50
  import { type CircuitSimulator, WASMSimulatorWithBlobs, emitCircuitSimulationStats } from '@aztec/simulator/server';
52
51
  import type { AvmCircuitInputs } from '@aztec/stdlib/avm';
53
52
  import {
54
- type ProofAndVerificationKey,
55
53
  type PublicInputsAndRecursiveProof,
56
54
  type ServerCircuitProver,
57
- makeProofAndVerificationKey,
58
55
  makePublicInputsAndRecursiveProof,
59
56
  } from '@aztec/stdlib/interfaces/server';
60
57
  import type { ParityBasePrivateInputs, ParityPublicInputs, ParityRootPrivateInputs } from '@aztec/stdlib/parity';
61
- import { type Proof, ProvingRequestType, makeEmptyRecursiveProof, makeRecursiveProof } from '@aztec/stdlib/proofs';
58
+ import {
59
+ type Proof,
60
+ ProvingRequestType,
61
+ RecursiveProof,
62
+ makeEmptyRecursiveProof,
63
+ makeRecursiveProof,
64
+ } from '@aztec/stdlib/proofs';
62
65
  import {
63
66
  type BlockMergeRollupPrivateInputs,
64
67
  type BlockRollupPublicInputs,
@@ -81,7 +84,6 @@ import {
81
84
  type TxMergeRollupPrivateInputs,
82
85
  type TxRollupPublicInputs,
83
86
  } from '@aztec/stdlib/rollup';
84
- import { VerificationKeyData } from '@aztec/stdlib/vks';
85
87
  import { type TelemetryClient, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
86
88
 
87
89
  import { ProverInstrumentation } from '../instrumentation.js';
@@ -400,17 +402,12 @@ export class TestCircuitProver implements ServerCircuitProver {
400
402
  );
401
403
  }
402
404
 
403
- public getAvmProof(
404
- _inputs: AvmCircuitInputs,
405
- ): Promise<ProofAndVerificationKey<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
405
+ public getAvmProof(_inputs: AvmCircuitInputs): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
406
406
  // We can't simulate the AVM because we don't have enough context to do so (e.g., DBs).
407
- // We just return an empty proof and VK data.
407
+ // We just return an empty proof.
408
408
  this.logger.debug('Skipping AVM simulation in TestCircuitProver.');
409
409
  return this.applyDelay(ProvingRequestType.PUBLIC_VM, () =>
410
- makeProofAndVerificationKey(
411
- makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED),
412
- VerificationKeyData.makeFake(AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED),
413
- ),
410
+ makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED),
414
411
  );
415
412
  }
416
413
 
@@ -1,13 +1,11 @@
1
- import { AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED } from '@aztec/constants';
2
1
  import { Fr } from '@aztec/foundation/curves/bn254';
3
2
  import { BufferReader } from '@aztec/foundation/serialize';
4
3
  import { VerificationKeyAsFields, VerificationKeyData } from '@aztec/stdlib/vks';
5
4
 
6
- import { strict as assert } from 'assert';
7
5
  import { promises as fs } from 'fs';
8
6
  import * as path from 'path';
9
7
 
10
- import { VK_FILENAME } from '../bb/execute.js';
8
+ import { VK_FILENAME } from '../bb/file_names.js';
11
9
 
12
10
  /**
13
11
  * Reads the verification key data stored at the specified location and parses into a VerificationKeyData
@@ -25,26 +23,3 @@ export async function extractVkData(vkDirectoryPath: string): Promise<Verificati
25
23
  const vkAsFields = await VerificationKeyAsFields.fromKey(fields);
26
24
  return new VerificationKeyData(vkAsFields, rawBinary);
27
25
  }
28
-
29
- /**
30
- * Reads the verification key data stored in a binary file at the specified directory location and parses into a VerificationKeyData.
31
- * We do not assume any JSON file available but only the binary version, contrary to the above extractVkData() method.
32
- * @param vkDirectoryPath - The directory containing the verification key binary data file.
33
- * @returns The verification key data
34
- */
35
- export async function extractAvmVkData(vkDirectoryPath: string): Promise<VerificationKeyData> {
36
- const rawBinary = await fs.readFile(path.join(vkDirectoryPath, VK_FILENAME));
37
-
38
- const numFields = rawBinary.length / Fr.SIZE_IN_BYTES;
39
- assert(numFields <= AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED, 'Invalid AVM verification key length');
40
- const reader = BufferReader.asReader(rawBinary);
41
- const fieldsArray = reader.readArray(numFields, Fr);
42
-
43
- const fieldsArrayPadded = fieldsArray.concat(
44
- Array(AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED - fieldsArray.length).fill(new Fr(0)),
45
- );
46
- const vkAsFields = await VerificationKeyAsFields.fromKey(fieldsArrayPadded);
47
- // TODO(#16644): We should have a different type for AVM verification keys since we don't have circuit size or num public inputs in AVM VKs.
48
- const vk = new VerificationKeyData(vkAsFields, rawBinary);
49
- return vk;
50
- }