@aztec/bb-prover 0.0.1-commit.24de95ac → 0.0.1-commit.2606882

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 (108) hide show
  1. package/dest/avm_proving_tests/avm_proving_tester.d.ts +15 -11
  2. package/dest/avm_proving_tests/avm_proving_tester.d.ts.map +1 -1
  3. package/dest/avm_proving_tests/avm_proving_tester.js +167 -108
  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/cli.d.ts +1 -1
  11. package/dest/bb/file_names.d.ts +4 -0
  12. package/dest/bb/file_names.d.ts.map +1 -0
  13. package/dest/bb/file_names.js +5 -0
  14. package/dest/bb/index.d.ts +1 -1
  15. package/dest/config.d.ts +17 -1
  16. package/dest/config.d.ts.map +1 -1
  17. package/dest/honk.d.ts +1 -1
  18. package/dest/index.d.ts +3 -2
  19. package/dest/index.d.ts.map +1 -1
  20. package/dest/index.js +2 -1
  21. package/dest/instrumentation.d.ts +1 -1
  22. package/dest/instrumentation.d.ts.map +1 -1
  23. package/dest/instrumentation.js +21 -43
  24. package/dest/prover/client/bb_private_kernel_prover.d.ts +20 -6
  25. package/dest/prover/client/bb_private_kernel_prover.d.ts.map +1 -1
  26. package/dest/prover/client/bb_private_kernel_prover.js +73 -8
  27. package/dest/prover/client/bundle.d.ts +6 -0
  28. package/dest/prover/client/bundle.d.ts.map +1 -0
  29. package/dest/prover/client/bundle.js +7 -0
  30. package/dest/prover/client/lazy.d.ts +6 -0
  31. package/dest/prover/client/lazy.d.ts.map +1 -0
  32. package/dest/prover/client/lazy.js +7 -0
  33. package/dest/prover/index.d.ts +1 -1
  34. package/dest/prover/proof_utils.d.ts +11 -1
  35. package/dest/prover/proof_utils.d.ts.map +1 -1
  36. package/dest/prover/proof_utils.js +25 -2
  37. package/dest/prover/server/bb_prover.d.ts +8 -21
  38. package/dest/prover/server/bb_prover.d.ts.map +1 -1
  39. package/dest/prover/server/bb_prover.js +614 -112
  40. package/dest/test/delay_values.d.ts +1 -1
  41. package/dest/test/delay_values.d.ts.map +1 -1
  42. package/dest/test/delay_values.js +29 -27
  43. package/dest/test/index.d.ts +2 -1
  44. package/dest/test/index.d.ts.map +1 -1
  45. package/dest/test/index.js +1 -0
  46. package/dest/test/test_circuit_prover.d.ts +4 -4
  47. package/dest/test/test_circuit_prover.d.ts.map +1 -1
  48. package/dest/test/test_circuit_prover.js +462 -59
  49. package/dest/test/test_verifier.d.ts +3 -1
  50. package/dest/test/test_verifier.d.ts.map +1 -1
  51. package/dest/test/test_verifier.js +15 -0
  52. package/dest/verification_key/verification_key_data.d.ts +1 -8
  53. package/dest/verification_key/verification_key_data.d.ts.map +1 -1
  54. package/dest/verification_key/verification_key_data.js +2 -21
  55. package/dest/verifier/batch_chonk_verifier.d.ts +56 -0
  56. package/dest/verifier/batch_chonk_verifier.d.ts.map +1 -0
  57. package/dest/verifier/batch_chonk_verifier.js +384 -0
  58. package/dest/verifier/bb_verifier.d.ts +4 -1
  59. package/dest/verifier/bb_verifier.d.ts.map +1 -1
  60. package/dest/verifier/bb_verifier.js +137 -48
  61. package/dest/verifier/index.d.ts +2 -1
  62. package/dest/verifier/index.d.ts.map +1 -1
  63. package/dest/verifier/index.js +1 -0
  64. package/dest/verifier/queued_chonk_verifier.d.ts +2 -3
  65. package/dest/verifier/queued_chonk_verifier.d.ts.map +1 -1
  66. package/dest/verifier/queued_chonk_verifier.js +15 -45
  67. package/package.json +26 -23
  68. package/src/avm_proving_tests/avm_proving_tester.ts +69 -138
  69. package/src/bb/bb_js_backend.ts +435 -0
  70. package/src/bb/bb_js_debug.ts +227 -0
  71. package/src/bb/file_names.ts +6 -0
  72. package/src/config.ts +16 -0
  73. package/src/index.ts +2 -1
  74. package/src/instrumentation.ts +20 -43
  75. package/src/prover/client/bb_private_kernel_prover.ts +158 -8
  76. package/src/prover/client/bundle.ts +10 -0
  77. package/src/prover/client/lazy.ts +10 -0
  78. package/src/prover/proof_utils.ts +42 -2
  79. package/src/prover/server/bb_prover.ts +139 -159
  80. package/src/test/delay_values.ts +31 -27
  81. package/src/test/index.ts +1 -0
  82. package/src/test/test_circuit_prover.ts +10 -13
  83. package/src/test/test_verifier.ts +8 -0
  84. package/src/verification_key/verification_key_data.ts +2 -27
  85. package/src/verifier/batch_chonk_verifier.ts +415 -0
  86. package/src/verifier/bb_verifier.ts +69 -80
  87. package/src/verifier/index.ts +1 -0
  88. package/src/verifier/queued_chonk_verifier.ts +15 -47
  89. package/dest/bb/execute.d.ts +0 -107
  90. package/dest/bb/execute.d.ts.map +0 -1
  91. package/dest/bb/execute.js +0 -672
  92. package/dest/prover/client/native/bb_native_private_kernel_prover.d.ts +0 -23
  93. package/dest/prover/client/native/bb_native_private_kernel_prover.d.ts.map +0 -1
  94. package/dest/prover/client/native/bb_native_private_kernel_prover.js +0 -66
  95. package/dest/prover/client/wasm/bb_wasm_private_kernel_prover.d.ts +0 -15
  96. package/dest/prover/client/wasm/bb_wasm_private_kernel_prover.d.ts.map +0 -1
  97. package/dest/prover/client/wasm/bb_wasm_private_kernel_prover.js +0 -46
  98. package/dest/prover/client/wasm/bundle.d.ts +0 -6
  99. package/dest/prover/client/wasm/bundle.d.ts.map +0 -1
  100. package/dest/prover/client/wasm/bundle.js +0 -8
  101. package/dest/prover/client/wasm/lazy.d.ts +0 -6
  102. package/dest/prover/client/wasm/lazy.d.ts.map +0 -1
  103. package/dest/prover/client/wasm/lazy.js +0 -8
  104. package/src/bb/execute.ts +0 -709
  105. package/src/prover/client/native/bb_native_private_kernel_prover.ts +0 -105
  106. package/src/prover/client/wasm/bb_wasm_private_kernel_prover.ts +0 -58
  107. package/src/prover/client/wasm/bundle.ts +0 -11
  108. package/src/prover/client/wasm/lazy.ts +0 -11
@@ -6,10 +6,9 @@ import {
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);
@@ -192,14 +179,10 @@ export class BBNativeRollupProver implements ServerCircuitProver {
192
179
  }))
193
180
  public async getAvmProof(
194
181
  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;
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;
203
186
  }
204
187
 
205
188
  public async getPublicChonkVerifierProof(
@@ -461,16 +444,16 @@ export class BBNativeRollupProver implements ServerCircuitProver {
461
444
  convertInput: (input: Input) => WitnessMap,
462
445
  convertOutput: (outputWitness: WitnessMap) => Output,
463
446
  workingDirectory: string,
464
- ): Promise<{ circuitOutput: Output; provingResult: BBSuccess }> {
465
- // 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)
466
449
  const outputWitnessFile = path.join(workingDirectory, 'partial-witness.gz');
467
450
 
468
451
  // 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
452
  const simulator = new NativeACVMSimulator(
471
453
  this.config.acvmWorkingDirectory,
472
454
  this.config.acvmBinaryPath,
473
455
  outputWitnessFile,
456
+ logger,
474
457
  );
475
458
 
476
459
  const artifact = getServerCircuitArtifact(circuitType);
@@ -478,7 +461,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
478
461
  logger.debug(`Generating witness data for ${circuitType}`);
479
462
 
480
463
  const inputWitness = convertInput(input);
481
- const foreignCallHandler = undefined; // We don't handle foreign calls in the native ACVM simulator
464
+ const foreignCallHandler = undefined;
482
465
  const witnessResult = await simulator.executeProtocolCircuit(inputWitness, artifact, foreignCallHandler);
483
466
  const output = convertOutput(witnessResult.witness);
484
467
 
@@ -495,76 +478,80 @@ export class BBNativeRollupProver implements ServerCircuitProver {
495
478
  eventName: 'circuit-witness-generation',
496
479
  } satisfies CircuitWitnessGenerationStats);
497
480
 
498
- // Now prove the circuit from the generated witness
499
- 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);
500
484
 
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
- );
485
+ // Decompress bytecode for bb.js
486
+ const bytecode = ungzip(Buffer.from(artifact.bytecode, 'base64'));
511
487
 
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);
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}`);
515
503
  }
516
504
 
517
505
  return {
518
506
  circuitOutput: output,
519
- provingResult,
507
+ proofResult,
520
508
  };
521
509
  }
522
510
 
523
- 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>> {
524
514
  logger.info(`Proving avm-circuit for TX ${input.hints.tx.hash}...`);
525
515
 
526
- 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);
527
519
 
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
- }
520
+ // Convert Uint8Array[] (32-byte field elements) to Fr[]
521
+ const proofFields = proofFieldArrays.map(f => Fr.fromBuffer(Buffer.from(f)));
535
522
 
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);
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
+ );
541
532
 
542
- const avmVK = await extractAvmVkData(provingResult.vkDirectoryPath!);
543
- 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);
544
537
 
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);
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);
549
542
 
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
- );
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);
564
553
 
565
- return makeProofAndVerificationKey(avmProof, avmVK);
566
- };
567
- return await this.runInDirectory(operation);
554
+ return avmProof;
568
555
  }
569
556
 
570
557
  /**
@@ -587,33 +574,38 @@ export class BBNativeRollupProver implements ServerCircuitProver {
587
574
  convertInput: (input: CircuitInputType) => WitnessMap,
588
575
  convertOutput: (outputWitness: WitnessMap) => CircuitOutputType,
589
576
  ): 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(
577
+ // Still need runInDirectory for ACVM witness generation temp files
578
+ const operation = async (workingDirectory: string) => {
579
+ const { proofResult, circuitOutput: output } = await this.generateProofWithBB(
593
580
  input,
594
581
  circuitType,
595
582
  convertInput,
596
583
  convertOutput,
597
- bbWorkingDirectory,
584
+ workingDirectory,
598
585
  );
599
586
 
600
587
  const vkData = this.getVerificationKeyDataForCircuit(circuitType);
601
- // Read the proof as fields
602
- 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
+ );
603
595
 
604
596
  const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
605
- this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs);
597
+ this.instrumentation.recordDuration('provingDuration', circuitName, proofResult.durationMs);
606
598
  this.instrumentation.recordSize('proofSize', circuitName, proof.binaryProof.buffer.length);
607
599
  this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs);
608
600
  this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize);
609
601
  logger.info(
610
- `Generated proof for ${circuitType} in ${Math.ceil(provingResult.durationMs)} ms, size: ${
602
+ `Generated proof for ${circuitType} in ${Math.ceil(proofResult.durationMs)} ms, size: ${
611
603
  proof.proof.length
612
604
  } fields`,
613
605
  {
614
606
  circuitName,
615
607
  circuitSize: vkData.circuitSize,
616
- duration: provingResult.durationMs,
608
+ duration: proofResult.durationMs,
617
609
  inputSize: output.toBuffer().length,
618
610
  proofSize: proof.binaryProof.buffer.length,
619
611
  eventName: 'circuit-proving',
@@ -630,56 +622,58 @@ export class BBNativeRollupProver implements ServerCircuitProver {
630
622
  }
631
623
 
632
624
  /**
633
- * 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).
634
626
  * @param circuitType - The type of circuit whose proof is to be verified
635
627
  * @param proof - The proof to be verified
636
628
  */
637
629
  public async verifyProof(circuitType: ServerProtocolArtifact, proof: Proof) {
638
630
  const verificationKey = this.getVerificationKeyDataForCircuit(circuitType);
639
- return await this.verifyWithKey(getUltraHonkFlavorForCircuit(circuitType), verificationKey, proof);
640
- }
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
+ }
641
650
 
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
- }
651
+ if (!verified) {
652
+ throw new ProvingError('Failed to verify proof from key!');
653
+ }
651
654
 
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
- );
655
+ logger.info(`Successfully verified proof from key in ${durationMs} ms`);
656
656
  }
657
657
 
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
- };
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();
681
668
 
682
- 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`);
683
677
  }
684
678
 
685
679
  /**
@@ -695,29 +689,6 @@ export class BBNativeRollupProver implements ServerCircuitProver {
695
689
  return vk;
696
690
  }
697
691
 
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
692
  private runInDirectory<T>(fn: (dir: string) => Promise<T>) {
722
693
  return runInDirectory(
723
694
  this.config.bbWorkingDirectory,
@@ -731,3 +702,12 @@ export class BBNativeRollupProver implements ServerCircuitProver {
731
702
  );
732
703
  }
733
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]: 60,
5
- [ProvingRequestType.BLOCK_MERGE_ROLLUP]: 650,
6
- [ProvingRequestType.BLOCK_ROOT_FIRST_ROLLUP]: 60_000,
7
- [ProvingRequestType.BLOCK_ROOT_SINGLE_TX_FIRST_ROLLUP]: 40_000,
8
- [ProvingRequestType.BLOCK_ROOT_EMPTY_TX_FIRST_ROLLUP]: 20_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
+ [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]: 20_000,
13
22
  [ProvingRequestType.CHECKPOINT_PADDING_ROLLUP]: 0,
14
- [ProvingRequestType.CHECKPOINT_MERGE_ROLLUP]: 650,
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]: 100,
19
- [ProvingRequestType.ROOT_ROLLUP]: 650,
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]: 3_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]: 15_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]: 15_000,
34
45
  [ProvingRequestType.CHECKPOINT_PADDING_ROLLUP]: 0,
35
- [ProvingRequestType.CHECKPOINT_MERGE_ROLLUP]: 15_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]: 30_000,
40
- [ProvingRequestType.ROOT_ROLLUP]: 15_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
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
 
@@ -2,7 +2,15 @@ import type { ClientProtocolCircuitVerifier, IVCProofVerificationResult } from '
2
2
  import type { Tx } from '@aztec/stdlib/tx';
3
3
 
4
4
  export class TestCircuitVerifier implements ClientProtocolCircuitVerifier {
5
+ constructor(private verificationDelayMs?: number) {}
5
6
  verifyProof(_tx: Tx): Promise<IVCProofVerificationResult> {
7
+ if (this.verificationDelayMs !== undefined && this.verificationDelayMs > 0) {
8
+ return new Promise(resolve => {
9
+ setTimeout(() => {
10
+ resolve({ valid: true, durationMs: this.verificationDelayMs!, totalDurationMs: this.verificationDelayMs! });
11
+ }, this.verificationDelayMs);
12
+ });
13
+ }
6
14
  return Promise.resolve({ valid: true, durationMs: 0, totalDurationMs: 0 });
7
15
  }
8
16
 
@@ -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
- }