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