@aztec/bb-prover 0.0.1-commit.d431d1c → 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.
- package/dest/avm_proving_tests/avm_proving_tester.d.ts +16 -10
- package/dest/avm_proving_tests/avm_proving_tester.d.ts.map +1 -1
- package/dest/avm_proving_tests/avm_proving_tester.js +178 -111
- 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 +21 -5
- package/dest/prover/client/bb_private_kernel_prover.d.ts.map +1 -1
- package/dest/prover/client/bb_private_kernel_prover.js +79 -15
- 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 +6 -7
- package/dest/prover/server/bb_prover.d.ts.map +1 -1
- package/dest/prover/server/bb_prover.js +207 -80
- package/dest/test/delay_values.js +1 -1
- package/dest/test/test_circuit_prover.d.ts +3 -3
- package/dest/test/test_circuit_prover.d.ts.map +1 -1
- package/dest/test/test_circuit_prover.js +2 -2
- 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 +8 -7
- package/package.json +19 -17
- package/src/avm_proving_tests/avm_proving_tester.ts +85 -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 +242 -21
- package/src/prover/proof_utils.ts +41 -1
- package/src/prover/server/bb_prover.ts +127 -141
- package/src/test/delay_values.ts +1 -1
- package/src/test/test_circuit_prover.ts +3 -5
- 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 +8 -8
- 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,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
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,
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
10
10
|
import { runInDirectory } from '@aztec/foundation/fs';
|
|
11
11
|
import { createLogger } from '@aztec/foundation/log';
|
|
12
|
-
import { BufferReader } from '@aztec/foundation/serialize';
|
|
13
12
|
import {
|
|
14
13
|
type ServerProtocolArtifact,
|
|
15
14
|
convertBlockMergeRollupOutputsFromWitnessMap,
|
|
@@ -88,24 +87,14 @@ import { VerificationKeyData } from '@aztec/stdlib/vks';
|
|
|
88
87
|
import { Attributes, type TelemetryClient, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
89
88
|
|
|
90
89
|
import { promises as fs } from 'fs';
|
|
90
|
+
import { ungzip } from 'pako';
|
|
91
91
|
import * as path from 'path';
|
|
92
92
|
|
|
93
|
-
import {
|
|
94
|
-
type BBFailure,
|
|
95
|
-
type BBSuccess,
|
|
96
|
-
BB_RESULT,
|
|
97
|
-
PROOF_FILENAME,
|
|
98
|
-
PUBLIC_INPUTS_FILENAME,
|
|
99
|
-
VK_FILENAME,
|
|
100
|
-
generateAvmProof,
|
|
101
|
-
generateProof,
|
|
102
|
-
verifyAvmProof,
|
|
103
|
-
verifyProof,
|
|
104
|
-
} from '../../bb/execute.js';
|
|
93
|
+
import { BBJsFactory, type BBJsProofResult } from '../../bb/bb_js_backend.js';
|
|
105
94
|
import type { ACVMConfig, BBConfig } from '../../config.js';
|
|
106
95
|
import { getUltraHonkFlavorForCircuit } from '../../honk.js';
|
|
107
96
|
import { ProverInstrumentation } from '../../instrumentation.js';
|
|
108
|
-
import {
|
|
97
|
+
import { constructRecursiveProofFromBuffers } from '../proof_utils.js';
|
|
109
98
|
|
|
110
99
|
const logger = createLogger('bb-prover');
|
|
111
100
|
|
|
@@ -119,12 +108,14 @@ export interface BBProverConfig extends BBConfig, ACVMConfig {
|
|
|
119
108
|
*/
|
|
120
109
|
export class BBNativeRollupProver implements ServerCircuitProver {
|
|
121
110
|
private instrumentation: ProverInstrumentation;
|
|
111
|
+
private bbJsFactory: BBJsFactory;
|
|
122
112
|
|
|
123
113
|
constructor(
|
|
124
114
|
private config: BBProverConfig,
|
|
125
115
|
telemetry: TelemetryClient,
|
|
126
116
|
) {
|
|
127
117
|
this.instrumentation = new ProverInstrumentation(telemetry, 'BBNativeRollupProver');
|
|
118
|
+
this.bbJsFactory = new BBJsFactory(config.bbBinaryPath, { logger, debugDir: config.bbDebugOutputDir });
|
|
128
119
|
}
|
|
129
120
|
|
|
130
121
|
get tracer() {
|
|
@@ -136,7 +127,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
136
127
|
await fs.mkdir(config.acvmWorkingDirectory, { recursive: true });
|
|
137
128
|
await fs.access(config.bbBinaryPath, fs.constants.R_OK);
|
|
138
129
|
await fs.mkdir(config.bbWorkingDirectory, { recursive: true });
|
|
139
|
-
logger.info(`Using
|
|
130
|
+
logger.info(`Using bb.js API with binary at ${config.bbBinaryPath}`);
|
|
140
131
|
logger.info(`Using native ACVM at ${config.acvmBinaryPath} and working directory ${config.acvmWorkingDirectory}`);
|
|
141
132
|
|
|
142
133
|
return new BBNativeRollupProver(config, telemetry);
|
|
@@ -186,9 +177,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
186
177
|
@trackSpan('BBNativeRollupProver.getAvmProof', inputs => ({
|
|
187
178
|
[Attributes.APP_CIRCUIT_NAME]: inputs.hints.tx.hash,
|
|
188
179
|
}))
|
|
189
|
-
public async getAvmProof(
|
|
190
|
-
inputs: AvmCircuitInputs,
|
|
191
|
-
): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
|
|
180
|
+
public async getAvmProof(inputs: AvmCircuitInputs): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS>> {
|
|
192
181
|
const proof = await this.createAvmProof(inputs);
|
|
193
182
|
await this.verifyAvmProof(proof.binaryProof, inputs.publicInputs);
|
|
194
183
|
return proof;
|
|
@@ -453,16 +442,16 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
453
442
|
convertInput: (input: Input) => WitnessMap,
|
|
454
443
|
convertOutput: (outputWitness: WitnessMap) => Output,
|
|
455
444
|
workingDirectory: string,
|
|
456
|
-
): Promise<{ circuitOutput: Output;
|
|
457
|
-
// 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)
|
|
458
447
|
const outputWitnessFile = path.join(workingDirectory, 'partial-witness.gz');
|
|
459
448
|
|
|
460
449
|
// Generate the partial witness using the ACVM
|
|
461
|
-
// A further temp directory will be created beneath ours and then cleaned up after the partial witness has been copied to our specified location
|
|
462
450
|
const simulator = new NativeACVMSimulator(
|
|
463
451
|
this.config.acvmWorkingDirectory,
|
|
464
452
|
this.config.acvmBinaryPath,
|
|
465
453
|
outputWitnessFile,
|
|
454
|
+
logger,
|
|
466
455
|
);
|
|
467
456
|
|
|
468
457
|
const artifact = getServerCircuitArtifact(circuitType);
|
|
@@ -470,7 +459,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
470
459
|
logger.debug(`Generating witness data for ${circuitType}`);
|
|
471
460
|
|
|
472
461
|
const inputWitness = convertInput(input);
|
|
473
|
-
const foreignCallHandler = undefined;
|
|
462
|
+
const foreignCallHandler = undefined;
|
|
474
463
|
const witnessResult = await simulator.executeProtocolCircuit(inputWitness, artifact, foreignCallHandler);
|
|
475
464
|
const output = convertOutput(witnessResult.witness);
|
|
476
465
|
|
|
@@ -487,75 +476,72 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
487
476
|
eventName: 'circuit-witness-generation',
|
|
488
477
|
} satisfies CircuitWitnessGenerationStats);
|
|
489
478
|
|
|
490
|
-
//
|
|
491
|
-
|
|
479
|
+
// Read and decompress the witness for bb.js
|
|
480
|
+
const witnessGz = await fs.readFile(outputWitnessFile);
|
|
481
|
+
const witness = ungzip(witnessGz);
|
|
492
482
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
this.getVerificationKeyDataForCircuit(circuitType).keyAsBytes,
|
|
499
|
-
outputWitnessFile,
|
|
500
|
-
getUltraHonkFlavorForCircuit(circuitType),
|
|
501
|
-
logger,
|
|
502
|
-
);
|
|
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...`);
|
|
503
488
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
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}`);
|
|
507
501
|
}
|
|
508
502
|
|
|
509
503
|
return {
|
|
510
504
|
circuitOutput: output,
|
|
511
|
-
|
|
505
|
+
proofResult,
|
|
512
506
|
};
|
|
513
507
|
}
|
|
514
508
|
|
|
515
|
-
private async
|
|
509
|
+
private async createAvmProof(input: AvmCircuitInputs): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS>> {
|
|
516
510
|
logger.info(`Proving avm-circuit for TX ${input.hints.tx.hash}...`);
|
|
517
511
|
|
|
518
|
-
const
|
|
512
|
+
const inputsBuffer = input.serializeWithMessagePack();
|
|
513
|
+
await using instance = await this.bbJsFactory.getInstance();
|
|
514
|
+
const { proof: proofFieldArrays, durationMs } = await instance.generateAvmProof(inputsBuffer);
|
|
519
515
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
throw new ProvingError(provingResult.reason, provingResult, provingResult.retry);
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
return provingResult;
|
|
526
|
-
}
|
|
516
|
+
// Convert Uint8Array[] (32-byte field elements) to Fr[]
|
|
517
|
+
const proofFields = proofFieldArrays.map(f => Fr.fromBuffer(Buffer.from(f)));
|
|
527
518
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
const operation = async (bbWorkingDirectory: string) => {
|
|
532
|
-
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
|
+
}
|
|
533
522
|
|
|
534
|
-
|
|
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);
|
|
535
527
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
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);
|
|
540
532
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
circuitSize: 1 << 21,
|
|
552
|
-
numPublicInputs: 0,
|
|
553
|
-
} satisfies CircuitProvingStats,
|
|
554
|
-
);
|
|
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);
|
|
555
543
|
|
|
556
|
-
|
|
557
|
-
};
|
|
558
|
-
return await this.runInDirectory(operation);
|
|
544
|
+
return avmProof;
|
|
559
545
|
}
|
|
560
546
|
|
|
561
547
|
/**
|
|
@@ -578,33 +564,38 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
578
564
|
convertInput: (input: CircuitInputType) => WitnessMap,
|
|
579
565
|
convertOutput: (outputWitness: WitnessMap) => CircuitOutputType,
|
|
580
566
|
): Promise<{ circuitOutput: CircuitOutputType; proof: RecursiveProof<PROOF_LENGTH> }> {
|
|
581
|
-
//
|
|
582
|
-
const operation = async (
|
|
583
|
-
const {
|
|
567
|
+
// Still need runInDirectory for ACVM witness generation temp files
|
|
568
|
+
const operation = async (workingDirectory: string) => {
|
|
569
|
+
const { proofResult, circuitOutput: output } = await this.generateProofWithBB(
|
|
584
570
|
input,
|
|
585
571
|
circuitType,
|
|
586
572
|
convertInput,
|
|
587
573
|
convertOutput,
|
|
588
|
-
|
|
574
|
+
workingDirectory,
|
|
589
575
|
);
|
|
590
576
|
|
|
591
577
|
const vkData = this.getVerificationKeyDataForCircuit(circuitType);
|
|
592
|
-
//
|
|
593
|
-
const proof =
|
|
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
|
+
);
|
|
594
585
|
|
|
595
586
|
const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
|
|
596
|
-
this.instrumentation.recordDuration('provingDuration', circuitName,
|
|
587
|
+
this.instrumentation.recordDuration('provingDuration', circuitName, proofResult.durationMs);
|
|
597
588
|
this.instrumentation.recordSize('proofSize', circuitName, proof.binaryProof.buffer.length);
|
|
598
589
|
this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs);
|
|
599
590
|
this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize);
|
|
600
591
|
logger.info(
|
|
601
|
-
`Generated proof for ${circuitType} in ${Math.ceil(
|
|
592
|
+
`Generated proof for ${circuitType} in ${Math.ceil(proofResult.durationMs)} ms, size: ${
|
|
602
593
|
proof.proof.length
|
|
603
594
|
} fields`,
|
|
604
595
|
{
|
|
605
596
|
circuitName,
|
|
606
597
|
circuitSize: vkData.circuitSize,
|
|
607
|
-
duration:
|
|
598
|
+
duration: proofResult.durationMs,
|
|
608
599
|
inputSize: output.toBuffer().length,
|
|
609
600
|
proofSize: proof.binaryProof.buffer.length,
|
|
610
601
|
eventName: 'circuit-proving',
|
|
@@ -621,49 +612,58 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
621
612
|
}
|
|
622
613
|
|
|
623
614
|
/**
|
|
624
|
-
* Verifies a proof
|
|
615
|
+
* Verifies a proof via bb.js API (no temp files needed).
|
|
625
616
|
* @param circuitType - The type of circuit whose proof is to be verified
|
|
626
617
|
* @param proof - The proof to be verified
|
|
627
618
|
*/
|
|
628
619
|
public async verifyProof(circuitType: ServerProtocolArtifact, proof: Proof) {
|
|
629
620
|
const verificationKey = this.getVerificationKeyDataForCircuit(circuitType);
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
)
|
|
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
|
+
}
|
|
640
|
+
|
|
641
|
+
if (!verified) {
|
|
642
|
+
throw new ProvingError('Failed to verify proof from key!');
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
logger.info(`Successfully verified proof from key in ${durationMs} ms`);
|
|
633
646
|
}
|
|
634
647
|
|
|
648
|
+
/** Verify an AVM proof via bb.js API. */
|
|
635
649
|
public async verifyAvmProof(proof: Proof, publicInputs: AvmCircuitPublicInputs) {
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
) {
|
|
645
|
-
const operation = async (bbWorkingDirectory: string) => {
|
|
646
|
-
const publicInputsFileName = path.join(bbWorkingDirectory, PUBLIC_INPUTS_FILENAME);
|
|
647
|
-
const proofFileName = path.join(bbWorkingDirectory, PROOF_FILENAME);
|
|
648
|
-
const verificationKeyPath = path.join(bbWorkingDirectory, VK_FILENAME);
|
|
649
|
-
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/13189): Put this proof parsing logic in the proof class.
|
|
650
|
-
await fs.writeFile(publicInputsFileName, proof.buffer.subarray(0, proof.numPublicInputs * 32));
|
|
651
|
-
await fs.writeFile(proofFileName, proof.buffer.subarray(proof.numPublicInputs * 32));
|
|
652
|
-
if (verificationKey !== undefined) {
|
|
653
|
-
await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes);
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
const result = await verificationFunction(proofFileName, verificationKeyPath);
|
|
657
|
-
|
|
658
|
-
if (result.status === BB_RESULT.FAILURE) {
|
|
659
|
-
const errorMessage = `Failed to verify proof from key!`;
|
|
660
|
-
throw new ProvingError(errorMessage, result, result.retry);
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
logger.info(`Successfully verified proof from key in ${result.durationMs} ms`);
|
|
664
|
-
};
|
|
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();
|
|
665
658
|
|
|
666
|
-
await this.
|
|
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`);
|
|
667
667
|
}
|
|
668
668
|
|
|
669
669
|
/**
|
|
@@ -679,29 +679,6 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
679
679
|
return vk;
|
|
680
680
|
}
|
|
681
681
|
|
|
682
|
-
private async readAvmProofAsFields(
|
|
683
|
-
proofFilename: string,
|
|
684
|
-
): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
|
|
685
|
-
const rawProofBuffer = await fs.readFile(proofFilename);
|
|
686
|
-
const reader = BufferReader.asReader(rawProofBuffer);
|
|
687
|
-
const proofFields = reader.readArray(rawProofBuffer.length / Fr.SIZE_IN_BYTES, Fr);
|
|
688
|
-
|
|
689
|
-
// We extend to a fixed-size padded proof as during development any new AVM circuit column changes the
|
|
690
|
-
// proof length and we do not have a mechanism to feedback a cpp constant to noir/TS.
|
|
691
|
-
// TODO(#13390): Revive a non-padded AVM proof
|
|
692
|
-
if (proofFields.length > AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED) {
|
|
693
|
-
throw new Error(
|
|
694
|
-
`Proof has ${proofFields.length} fields, expected no more than ${AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED}.`,
|
|
695
|
-
);
|
|
696
|
-
}
|
|
697
|
-
const proofFieldsPadded = proofFields.concat(
|
|
698
|
-
Array(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED - proofFields.length).fill(new Fr(0)),
|
|
699
|
-
);
|
|
700
|
-
|
|
701
|
-
const proof = new Proof(rawProofBuffer, /*numPublicInputs=*/ 0);
|
|
702
|
-
return new RecursiveProof(proofFieldsPadded, proof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED);
|
|
703
|
-
}
|
|
704
|
-
|
|
705
682
|
private runInDirectory<T>(fn: (dir: string) => Promise<T>) {
|
|
706
683
|
return runInDirectory(
|
|
707
684
|
this.config.bbWorkingDirectory,
|
|
@@ -715,3 +692,12 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
715
692
|
);
|
|
716
693
|
}
|
|
717
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
|
+
}
|
package/src/test/delay_values.ts
CHANGED
|
@@ -35,7 +35,7 @@ export const PROOF_DELAY_MS: Record<ProvingRequestType, number> = {
|
|
|
35
35
|
[ProvingRequestType.ROOT_ROLLUP]: 93_000,
|
|
36
36
|
[ProvingRequestType.TX_MERGE_ROLLUP]: 10_000,
|
|
37
37
|
[ProvingRequestType.PUBLIC_TX_BASE_ROLLUP]: 44_500,
|
|
38
|
-
[ProvingRequestType.PUBLIC_VM]:
|
|
38
|
+
[ProvingRequestType.PUBLIC_VM]: 180_000,
|
|
39
39
|
|
|
40
40
|
// TBD
|
|
41
41
|
[ProvingRequestType.BLOCK_MERGE_ROLLUP]: 15_000,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
AVM_V2_PROOF_LENGTH_IN_FIELDS,
|
|
3
3
|
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
4
4
|
NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
|
|
5
5
|
RECURSIVE_PROOF_LENGTH,
|
|
@@ -402,13 +402,11 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
402
402
|
);
|
|
403
403
|
}
|
|
404
404
|
|
|
405
|
-
public getAvmProof(_inputs: AvmCircuitInputs): Promise<RecursiveProof<typeof
|
|
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
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
|
-
makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED),
|
|
411
|
-
);
|
|
409
|
+
return this.applyDelay(ProvingRequestType.PUBLIC_VM, () => makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS));
|
|
412
410
|
}
|
|
413
411
|
|
|
414
412
|
private async applyDelay<F extends () => any>(type: ProvingRequestType, fn: F): Promise<Awaited<ReturnType<F>>> {
|
|
@@ -5,7 +5,7 @@ import { VerificationKeyAsFields, VerificationKeyData } from '@aztec/stdlib/vks'
|
|
|
5
5
|
import { promises as fs } from 'fs';
|
|
6
6
|
import * as path from 'path';
|
|
7
7
|
|
|
8
|
-
import { VK_FILENAME } from '../bb/
|
|
8
|
+
import { VK_FILENAME } from '../bb/file_names.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Reads the verification key data stored at the specified location and parses into a VerificationKeyData
|