@aztec/bb-prover 0.0.1-commit.d3ec352c → 0.0.1-commit.d58ff9d0

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 +16 -10
  2. package/dest/avm_proving_tests/avm_proving_tester.d.ts.map +1 -1
  3. package/dest/avm_proving_tests/avm_proving_tester.js +182 -111
  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 +29 -7
  22. package/dest/prover/client/bb_private_kernel_prover.d.ts.map +1 -1
  23. package/dest/prover/client/bb_private_kernel_prover.js +90 -16
  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 +25 -2
  33. package/dest/prover/server/bb_prover.d.ts +9 -13
  34. package/dest/prover/server/bb_prover.d.ts.map +1 -1
  35. package/dest/prover/server/bb_prover.js +613 -113
  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 +28 -26
  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 +5 -5
  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 +2 -21
  48. package/dest/verifier/batch_chonk_verifier.d.ts +56 -0
  49. package/dest/verifier/batch_chonk_verifier.d.ts.map +1 -0
  50. package/dest/verifier/batch_chonk_verifier.js +384 -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 +91 -142
  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 +259 -25
  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 +42 -2
  72. package/src/prover/server/bb_prover.ts +132 -162
  73. package/src/test/delay_values.ts +30 -26
  74. package/src/test/index.ts +1 -0
  75. package/src/test/test_circuit_prover.ts +11 -16
  76. package/src/verification_key/verification_key_data.ts +2 -27
  77. package/src/verifier/batch_chonk_verifier.ts +415 -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
@@ -1,15 +1,14 @@
1
1
  import {
2
- AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED,
2
+ AVM_V2_PROOF_LENGTH_IN_FIELDS,
3
3
  NESTED_RECURSIVE_PROOF_LENGTH,
4
4
  NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
5
5
  PAIRING_POINTS_SIZE,
6
6
  RECURSIVE_PROOF_LENGTH,
7
7
  ULTRA_KECCAK_PROOF_LENGTH,
8
8
  } from '@aztec/constants';
9
- import { Fr } from '@aztec/foundation/fields';
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';
@@ -84,32 +81,20 @@ import {
84
81
  type RootRollupPublicInputs,
85
82
  type TxMergeRollupPrivateInputs,
86
83
  type TxRollupPublicInputs,
87
- enhanceProofWithPiValidationFlag,
88
84
  } from '@aztec/stdlib/rollup';
89
85
  import type { CircuitProvingStats, CircuitWitnessGenerationStats } from '@aztec/stdlib/stats';
90
- import type { VerificationKeyData } from '@aztec/stdlib/vks';
86
+ import { VerificationKeyData } from '@aztec/stdlib/vks';
91
87
  import { Attributes, type TelemetryClient, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
92
88
 
93
89
  import { promises as fs } from 'fs';
90
+ import { ungzip } from 'pako';
94
91
  import * as path from 'path';
95
92
 
96
- import {
97
- type BBFailure,
98
- type BBSuccess,
99
- BB_RESULT,
100
- PROOF_FILENAME,
101
- PUBLIC_INPUTS_FILENAME,
102
- VK_FILENAME,
103
- generateAvmProof,
104
- generateProof,
105
- verifyAvmProof,
106
- verifyProof,
107
- } from '../../bb/execute.js';
93
+ import { BBJsFactory, type BBJsProofResult } from '../../bb/bb_js_backend.js';
108
94
  import type { ACVMConfig, BBConfig } from '../../config.js';
109
- import { type UltraHonkFlavor, getUltraHonkFlavorForCircuit } from '../../honk.js';
95
+ import { getUltraHonkFlavorForCircuit } from '../../honk.js';
110
96
  import { ProverInstrumentation } from '../../instrumentation.js';
111
- import { extractAvmVkData } from '../../verification_key/verification_key_data.js';
112
- import { readProofsFromOutputDirectory } from '../proof_utils.js';
97
+ import { constructRecursiveProofFromBuffers } from '../proof_utils.js';
113
98
 
114
99
  const logger = createLogger('bb-prover');
115
100
 
@@ -123,12 +108,14 @@ export interface BBProverConfig extends BBConfig, ACVMConfig {
123
108
  */
124
109
  export class BBNativeRollupProver implements ServerCircuitProver {
125
110
  private instrumentation: ProverInstrumentation;
111
+ private bbJsFactory: BBJsFactory;
126
112
 
127
113
  constructor(
128
114
  private config: BBProverConfig,
129
115
  telemetry: TelemetryClient,
130
116
  ) {
131
117
  this.instrumentation = new ProverInstrumentation(telemetry, 'BBNativeRollupProver');
118
+ this.bbJsFactory = new BBJsFactory(config.bbBinaryPath, { logger, debugDir: config.bbDebugOutputDir });
132
119
  }
133
120
 
134
121
  get tracer() {
@@ -140,7 +127,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
140
127
  await fs.mkdir(config.acvmWorkingDirectory, { recursive: true });
141
128
  await fs.access(config.bbBinaryPath, fs.constants.R_OK);
142
129
  await fs.mkdir(config.bbWorkingDirectory, { recursive: true });
143
- 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}`);
144
131
  logger.info(`Using native ACVM at ${config.acvmBinaryPath} and working directory ${config.acvmWorkingDirectory}`);
145
132
 
146
133
  return new BBNativeRollupProver(config, telemetry);
@@ -190,16 +177,10 @@ export class BBNativeRollupProver implements ServerCircuitProver {
190
177
  @trackSpan('BBNativeRollupProver.getAvmProof', inputs => ({
191
178
  [Attributes.APP_CIRCUIT_NAME]: inputs.hints.tx.hash,
192
179
  }))
193
- public async getAvmProof(
194
- inputs: AvmCircuitInputs,
195
- skipPublicInputsValidation: boolean = false,
196
- ): Promise<ProofAndVerificationKey<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
197
- const proofAndVk = await this.createAvmProof(inputs);
198
- await this.verifyAvmProof(proofAndVk.proof.binaryProof, proofAndVk.verificationKey, inputs.publicInputs);
199
-
200
- // TODO(#14234)[Unconditional PIs validation]: remove next lines and directly return proofAndVk
201
- proofAndVk.proof.proof = enhanceProofWithPiValidationFlag(proofAndVk.proof.proof, skipPublicInputsValidation);
202
- return proofAndVk;
180
+ public async getAvmProof(inputs: AvmCircuitInputs): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS>> {
181
+ const proof = await this.createAvmProof(inputs);
182
+ await this.verifyAvmProof(proof.binaryProof, inputs.publicInputs);
183
+ return proof;
203
184
  }
204
185
 
205
186
  public async getPublicChonkVerifierProof(
@@ -461,16 +442,16 @@ export class BBNativeRollupProver implements ServerCircuitProver {
461
442
  convertInput: (input: Input) => WitnessMap,
462
443
  convertOutput: (outputWitness: WitnessMap) => Output,
463
444
  workingDirectory: string,
464
- ): Promise<{ circuitOutput: Output; provingResult: BBSuccess }> {
465
- // Have the ACVM write the partial witness here
445
+ ): Promise<{ circuitOutput: Output; proofResult: BBJsProofResult }> {
446
+ // Have the ACVM write the partial witness here (still needs a temp directory)
466
447
  const outputWitnessFile = path.join(workingDirectory, 'partial-witness.gz');
467
448
 
468
449
  // Generate the partial witness using the ACVM
469
- // A further temp directory will be created beneath ours and then cleaned up after the partial witness has been copied to our specified location
470
450
  const simulator = new NativeACVMSimulator(
471
451
  this.config.acvmWorkingDirectory,
472
452
  this.config.acvmBinaryPath,
473
453
  outputWitnessFile,
454
+ logger,
474
455
  );
475
456
 
476
457
  const artifact = getServerCircuitArtifact(circuitType);
@@ -478,7 +459,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
478
459
  logger.debug(`Generating witness data for ${circuitType}`);
479
460
 
480
461
  const inputWitness = convertInput(input);
481
- const foreignCallHandler = undefined; // We don't handle foreign calls in the native ACVM simulator
462
+ const foreignCallHandler = undefined;
482
463
  const witnessResult = await simulator.executeProtocolCircuit(inputWitness, artifact, foreignCallHandler);
483
464
  const output = convertOutput(witnessResult.witness);
484
465
 
@@ -495,76 +476,72 @@ export class BBNativeRollupProver implements ServerCircuitProver {
495
476
  eventName: 'circuit-witness-generation',
496
477
  } satisfies CircuitWitnessGenerationStats);
497
478
 
498
- // Now prove the circuit from the generated witness
499
- logger.debug(`Proving ${circuitType}...`);
479
+ // Read and decompress the witness for bb.js
480
+ const witnessGz = await fs.readFile(outputWitnessFile);
481
+ const witness = ungzip(witnessGz);
500
482
 
501
- const provingResult = await generateProof(
502
- this.config.bbBinaryPath,
503
- workingDirectory,
504
- circuitType,
505
- Buffer.from(artifact.bytecode, 'base64'),
506
- this.getVerificationKeyDataForCircuit(circuitType).keyAsBytes,
507
- outputWitnessFile,
508
- getUltraHonkFlavorForCircuit(circuitType),
509
- logger,
510
- );
483
+ // Decompress bytecode for bb.js
484
+ const bytecode = ungzip(Buffer.from(artifact.bytecode, 'base64'));
485
+
486
+ // Prove the circuit via bb.js API
487
+ logger.debug(`Proving ${circuitType} via bb.js...`);
511
488
 
512
- if (provingResult.status === BB_RESULT.FAILURE) {
513
- logger.error(`Failed to generate proof for ${circuitType}: ${provingResult.reason}`);
514
- throw new ProvingError(provingResult.reason, provingResult, provingResult.retry);
489
+ let proofResult: BBJsProofResult;
490
+ try {
491
+ await using instance = await this.bbJsFactory.getInstance();
492
+ proofResult = await instance.generateProof(
493
+ circuitType,
494
+ bytecode,
495
+ this.getVerificationKeyDataForCircuit(circuitType).keyAsBytes,
496
+ witness,
497
+ getUltraHonkFlavorForCircuit(circuitType),
498
+ );
499
+ } catch (error) {
500
+ throw new ProvingError(`Failed to generate proof for ${circuitType}: ${error}`);
515
501
  }
516
502
 
517
503
  return {
518
504
  circuitOutput: output,
519
- provingResult,
505
+ proofResult,
520
506
  };
521
507
  }
522
508
 
523
- private async generateAvmProofWithBB(input: AvmCircuitInputs, workingDirectory: string): Promise<BBSuccess> {
509
+ private async createAvmProof(input: AvmCircuitInputs): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS>> {
524
510
  logger.info(`Proving avm-circuit for TX ${input.hints.tx.hash}...`);
525
511
 
526
- const provingResult = await generateAvmProof(this.config.bbBinaryPath, workingDirectory, input, logger);
512
+ const inputsBuffer = input.serializeWithMessagePack();
513
+ await using instance = await this.bbJsFactory.getInstance();
514
+ const { proof: proofFieldArrays, durationMs } = await instance.generateAvmProof(inputsBuffer);
527
515
 
528
- if (provingResult.status === BB_RESULT.FAILURE) {
529
- logger.error(`Failed to generate AVM proof for TX ${input.hints.tx.hash}: ${provingResult.reason}`);
530
- throw new ProvingError(provingResult.reason, provingResult, provingResult.retry);
531
- }
532
-
533
- return provingResult;
534
- }
516
+ // Convert Uint8Array[] (32-byte field elements) to Fr[]
517
+ const proofFields = proofFieldArrays.map(f => Fr.fromBuffer(Buffer.from(f)));
535
518
 
536
- private async createAvmProof(
537
- input: AvmCircuitInputs,
538
- ): Promise<ProofAndVerificationKey<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
539
- const operation = async (bbWorkingDirectory: string) => {
540
- const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory);
519
+ if (proofFields.length !== AVM_V2_PROOF_LENGTH_IN_FIELDS) {
520
+ throw new Error(`Proof has ${proofFields.length} fields, expected exactly ${AVM_V2_PROOF_LENGTH_IN_FIELDS}.`);
521
+ }
541
522
 
542
- const avmVK = await extractAvmVkData(provingResult.vkDirectoryPath!);
543
- const avmProof = await this.readAvmProofAsFields(provingResult.proofPath!);
523
+ // Build the binary proof from the raw field data
524
+ const rawProofBuffer = Buffer.concat(proofFieldArrays.map(f => Buffer.from(f)));
525
+ const binaryProof = new Proof(rawProofBuffer, /*numPublicInputs=*/ 0);
526
+ const avmProof = new RecursiveProof(proofFields, binaryProof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS);
544
527
 
545
- const circuitType = 'avm-circuit' as const;
546
- const appCircuitName = 'unknown' as const;
547
- this.instrumentation.recordAvmDuration('provingDuration', appCircuitName, provingResult.durationMs);
548
- this.instrumentation.recordAvmSize('proofSize', appCircuitName, avmProof.binaryProof.buffer.length);
528
+ const circuitType = 'avm-circuit' as const;
529
+ const appCircuitName = 'unknown' as const;
530
+ this.instrumentation.recordAvmDuration('provingDuration', appCircuitName, durationMs);
531
+ this.instrumentation.recordAvmSize('proofSize', appCircuitName, avmProof.binaryProof.buffer.length);
549
532
 
550
- logger.info(
551
- `Generated proof for ${circuitType}(${input.hints.tx.hash}) in ${Math.ceil(provingResult.durationMs)} ms`,
552
- {
553
- circuitName: circuitType,
554
- appCircuitName: input.hints.tx.hash,
555
- // does not include reading the proof from disk
556
- duration: provingResult.durationMs,
557
- proofSize: avmProof.binaryProof.buffer.length,
558
- eventName: 'circuit-proving',
559
- inputSize: input.serializeWithMessagePack().length,
560
- circuitSize: 1 << 21,
561
- numPublicInputs: 0,
562
- } satisfies CircuitProvingStats,
563
- );
533
+ logger.info(`Generated proof for ${circuitType}(${input.hints.tx.hash}) in ${Math.ceil(durationMs)} ms`, {
534
+ circuitName: circuitType,
535
+ appCircuitName: input.hints.tx.hash,
536
+ duration: durationMs,
537
+ proofSize: avmProof.binaryProof.buffer.length,
538
+ eventName: 'circuit-proving',
539
+ inputSize: inputsBuffer.length,
540
+ circuitSize: 1 << 21,
541
+ numPublicInputs: 0,
542
+ } satisfies CircuitProvingStats);
564
543
 
565
- return makeProofAndVerificationKey(avmProof, avmVK);
566
- };
567
- return await this.runInDirectory(operation);
544
+ return avmProof;
568
545
  }
569
546
 
570
547
  /**
@@ -587,33 +564,38 @@ export class BBNativeRollupProver implements ServerCircuitProver {
587
564
  convertInput: (input: CircuitInputType) => WitnessMap,
588
565
  convertOutput: (outputWitness: WitnessMap) => CircuitOutputType,
589
566
  ): Promise<{ circuitOutput: CircuitOutputType; proof: RecursiveProof<PROOF_LENGTH> }> {
590
- // this probably is gonna need to call chonk
591
- const operation = async (bbWorkingDirectory: string) => {
592
- const { provingResult, circuitOutput: output } = await this.generateProofWithBB(
567
+ // Still need runInDirectory for ACVM witness generation temp files
568
+ const operation = async (workingDirectory: string) => {
569
+ const { proofResult, circuitOutput: output } = await this.generateProofWithBB(
593
570
  input,
594
571
  circuitType,
595
572
  convertInput,
596
573
  convertOutput,
597
- bbWorkingDirectory,
574
+ workingDirectory,
598
575
  );
599
576
 
600
577
  const vkData = this.getVerificationKeyDataForCircuit(circuitType);
601
- // Read the proof as fields
602
- const proof = await readProofsFromOutputDirectory(provingResult.proofPath!, vkData, proofLength, logger);
578
+ // Construct proof from in-memory buffers (no file I/O needed)
579
+ const proof = constructRecursiveProofFromBuffers(
580
+ proofResult.proofFields,
581
+ proofResult.publicInputFields,
582
+ vkData,
583
+ proofLength,
584
+ );
603
585
 
604
586
  const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
605
- this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs);
587
+ this.instrumentation.recordDuration('provingDuration', circuitName, proofResult.durationMs);
606
588
  this.instrumentation.recordSize('proofSize', circuitName, proof.binaryProof.buffer.length);
607
589
  this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs);
608
590
  this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize);
609
591
  logger.info(
610
- `Generated proof for ${circuitType} in ${Math.ceil(provingResult.durationMs)} ms, size: ${
592
+ `Generated proof for ${circuitType} in ${Math.ceil(proofResult.durationMs)} ms, size: ${
611
593
  proof.proof.length
612
594
  } fields`,
613
595
  {
614
596
  circuitName,
615
597
  circuitSize: vkData.circuitSize,
616
- duration: provingResult.durationMs,
598
+ duration: proofResult.durationMs,
617
599
  inputSize: output.toBuffer().length,
618
600
  proofSize: proof.binaryProof.buffer.length,
619
601
  eventName: 'circuit-proving',
@@ -630,56 +612,58 @@ export class BBNativeRollupProver implements ServerCircuitProver {
630
612
  }
631
613
 
632
614
  /**
633
- * Verifies a proof, will generate the verification key if one is not cached internally
615
+ * Verifies a proof via bb.js API (no temp files needed).
634
616
  * @param circuitType - The type of circuit whose proof is to be verified
635
617
  * @param proof - The proof to be verified
636
618
  */
637
619
  public async verifyProof(circuitType: ServerProtocolArtifact, proof: Proof) {
638
620
  const verificationKey = this.getVerificationKeyDataForCircuit(circuitType);
639
- return await this.verifyWithKey(getUltraHonkFlavorForCircuit(circuitType), verificationKey, proof);
640
- }
621
+ const flavor = getUltraHonkFlavorForCircuit(circuitType);
622
+
623
+ // Split proof buffer into public input fields and proof fields (32-byte each)
624
+ const publicInputFields = splitBufferToFieldArrays(proof.buffer.subarray(0, proof.numPublicInputs * 32));
625
+ const proofFields = splitBufferToFieldArrays(proof.buffer.subarray(proof.numPublicInputs * 32));
626
+
627
+ let verified: boolean;
628
+ let durationMs: number;
629
+ try {
630
+ await using instance = await this.bbJsFactory.getInstance();
631
+ ({ verified, durationMs } = await instance.verifyProof(
632
+ proofFields,
633
+ verificationKey.keyAsBytes,
634
+ publicInputFields,
635
+ flavor,
636
+ ));
637
+ } catch (error) {
638
+ throw new ProvingError(`Failed to verify proof for ${circuitType}: ${error}`);
639
+ }
641
640
 
642
- public async verifyAvmProof(
643
- proof: Proof,
644
- verificationKey: VerificationKeyData,
645
- publicInputs: AvmCircuitPublicInputs,
646
- ) {
647
- return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath) =>
648
- verifyAvmProof(this.config.bbBinaryPath, this.config.bbWorkingDirectory, proofPath, publicInputs, vkPath, logger),
649
- );
650
- }
641
+ if (!verified) {
642
+ throw new ProvingError('Failed to verify proof from key!');
643
+ }
651
644
 
652
- public async verifyWithKey(flavor: UltraHonkFlavor, verificationKey: VerificationKeyData, proof: Proof) {
653
- return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath) =>
654
- verifyProof(this.config.bbBinaryPath, proofPath, vkPath, flavor, logger),
655
- );
645
+ logger.info(`Successfully verified proof from key in ${durationMs} ms`);
656
646
  }
657
647
 
658
- private async verifyWithKeyInternal(
659
- proof: Proof,
660
- verificationKey: { keyAsBytes: Buffer },
661
- verificationFunction: (proofPath: string, vkPath: string) => Promise<BBFailure | BBSuccess>,
662
- ) {
663
- const operation = async (bbWorkingDirectory: string) => {
664
- const publicInputsFileName = path.join(bbWorkingDirectory, PUBLIC_INPUTS_FILENAME);
665
- const proofFileName = path.join(bbWorkingDirectory, PROOF_FILENAME);
666
- const verificationKeyPath = path.join(bbWorkingDirectory, VK_FILENAME);
667
- // TODO(https://github.com/AztecProtocol/aztec-packages/issues/13189): Put this proof parsing logic in the proof class.
668
- await fs.writeFile(publicInputsFileName, proof.buffer.slice(0, proof.numPublicInputs * 32));
669
- await fs.writeFile(proofFileName, proof.buffer.slice(proof.numPublicInputs * 32));
670
- await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes);
671
-
672
- const result = await verificationFunction(proofFileName, verificationKeyPath!);
673
-
674
- if (result.status === BB_RESULT.FAILURE) {
675
- const errorMessage = `Failed to verify proof from key!`;
676
- throw new ProvingError(errorMessage, result, result.retry);
677
- }
678
-
679
- logger.info(`Successfully verified proof from key in ${result.durationMs} ms`);
680
- };
648
+ /** Verify an AVM proof via bb.js API. */
649
+ public async verifyAvmProof(proof: Proof, publicInputs: AvmCircuitPublicInputs) {
650
+ // For AVM proofs, numPublicInputs is 0, so the full buffer is the proof.
651
+ const proofBuffer = proof.buffer.subarray(proof.numPublicInputs * 32);
652
+ // Split the raw proof buffer into 32-byte field element arrays
653
+ const proofFields: Uint8Array[] = [];
654
+ for (let i = 0; i < proofBuffer.length; i += Fr.SIZE_IN_BYTES) {
655
+ proofFields.push(new Uint8Array(proofBuffer.subarray(i, i + Fr.SIZE_IN_BYTES)));
656
+ }
657
+ const piBuffer = publicInputs.serializeWithMessagePack();
681
658
 
682
- await this.runInDirectory(operation);
659
+ await using instance = await this.bbJsFactory.getInstance();
660
+ const { verified, durationMs } = await instance.verifyAvmProof(proofFields, piBuffer);
661
+
662
+ if (!verified) {
663
+ throw new ProvingError('Failed to verify AVM proof!');
664
+ }
665
+
666
+ logger.info(`Successfully verified AVM proof in ${durationMs} ms`);
683
667
  }
684
668
 
685
669
  /**
@@ -695,29 +679,6 @@ export class BBNativeRollupProver implements ServerCircuitProver {
695
679
  return vk;
696
680
  }
697
681
 
698
- private async readAvmProofAsFields(
699
- proofFilename: string,
700
- ): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
701
- const rawProofBuffer = await fs.readFile(proofFilename);
702
- const reader = BufferReader.asReader(rawProofBuffer);
703
- const proofFields = reader.readArray(rawProofBuffer.length / Fr.SIZE_IN_BYTES, Fr);
704
-
705
- // We extend to a fixed-size padded proof as during development any new AVM circuit column changes the
706
- // proof length and we do not have a mechanism to feedback a cpp constant to noir/TS.
707
- // TODO(#13390): Revive a non-padded AVM proof
708
- if (proofFields.length > AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED) {
709
- throw new Error(
710
- `Proof has ${proofFields.length} fields, expected no more than ${AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED}.`,
711
- );
712
- }
713
- const proofFieldsPadded = proofFields.concat(
714
- Array(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED - proofFields.length).fill(new Fr(0)),
715
- );
716
-
717
- const proof = new Proof(rawProofBuffer, /*numPublicInputs=*/ 0);
718
- return new RecursiveProof(proofFieldsPadded, proof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED);
719
- }
720
-
721
682
  private runInDirectory<T>(fn: (dir: string) => Promise<T>) {
722
683
  return runInDirectory(
723
684
  this.config.bbWorkingDirectory,
@@ -731,3 +692,12 @@ export class BBNativeRollupProver implements ServerCircuitProver {
731
692
  );
732
693
  }
733
694
  }
695
+
696
+ /** Split a buffer into 32-byte Uint8Array field elements. */
697
+ function splitBufferToFieldArrays(buffer: Buffer): Uint8Array[] {
698
+ const fields: Uint8Array[] = [];
699
+ for (let i = 0; i < buffer.length; i += 32) {
700
+ fields.push(new Uint8Array(buffer.subarray(i, i + 32)));
701
+ }
702
+ return fields;
703
+ }
@@ -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]: 2000,
5
- [ProvingRequestType.BLOCK_MERGE_ROLLUP]: 30,
6
- [ProvingRequestType.BLOCK_ROOT_FIRST_ROLLUP]: 60_000,
7
- [ProvingRequestType.BLOCK_ROOT_SINGLE_TX_FIRST_ROLLUP]: 40_000,
4
+ [ProvingRequestType.PUBLIC_CHONK_VERIFIER]: 60,
5
+ [ProvingRequestType.PARITY_BASE]: 1_600,
6
+ [ProvingRequestType.PARITY_ROOT]: 40,
7
+ [ProvingRequestType.BLOCK_ROOT_FIRST_ROLLUP]: 45,
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_000,
13
22
  [ProvingRequestType.CHECKPOINT_PADDING_ROLLUP]: 0,
14
- [ProvingRequestType.CHECKPOINT_MERGE_ROLLUP]: 30,
15
- [ProvingRequestType.TX_MERGE_ROLLUP]: 0,
16
- [ProvingRequestType.PRIVATE_TX_BASE_ROLLUP]: 400_000,
17
- [ProvingRequestType.PUBLIC_TX_BASE_ROLLUP]: 470_000,
18
- [ProvingRequestType.PARITY_ROOT]: 39,
19
- [ProvingRequestType.ROOT_ROLLUP]: 35,
20
- [ProvingRequestType.PUBLIC_CHONK_VERIFIER]: 0,
21
- [ProvingRequestType.PUBLIC_VM]: 0,
23
+ [ProvingRequestType.PRIVATE_TX_BASE_ROLLUP]: 2_500, // Guess based on public
22
24
  };
23
25
 
24
26
  export const PROOF_DELAY_MS: Record<ProvingRequestType, number> = {
25
- [ProvingRequestType.PARITY_BASE]: 14_000,
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]: 55_000,
28
- [ProvingRequestType.BLOCK_ROOT_SINGLE_TX_FIRST_ROLLUP]: 35_000,
29
- [ProvingRequestType.BLOCK_ROOT_EMPTY_TX_FIRST_ROLLUP]: 4_000,
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]: 35_000,
34
45
  [ProvingRequestType.CHECKPOINT_PADDING_ROLLUP]: 0,
35
- [ProvingRequestType.CHECKPOINT_MERGE_ROLLUP]: 9_000,
36
- [ProvingRequestType.TX_MERGE_ROLLUP]: 0,
37
- [ProvingRequestType.PRIVATE_TX_BASE_ROLLUP]: 145_000,
38
- [ProvingRequestType.PUBLIC_TX_BASE_ROLLUP]: 160_000,
39
- [ProvingRequestType.PARITY_ROOT]: 16_000,
40
- [ProvingRequestType.ROOT_ROLLUP]: 140_000,
41
- [ProvingRequestType.PUBLIC_CHONK_VERIFIER]: 30_000,
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
- AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED,
3
- AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED,
2
+ AVM_V2_PROOF_LENGTH_IN_FIELDS,
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,18 +402,11 @@ 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>> {
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
- 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
- ),
414
- );
409
+ return this.applyDelay(ProvingRequestType.PUBLIC_VM, () => makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS));
415
410
  }
416
411
 
417
412
  private async applyDelay<F extends () => any>(type: ProvingRequestType, fn: F): Promise<Awaited<ReturnType<F>>> {
@@ -1,13 +1,11 @@
1
- import { AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED } from '@aztec/constants';
2
- import { Fr } from '@aztec/foundation/fields';
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
- }