@aztec/bb-prover 0.0.1-commit.d3ec352c → 0.0.1-commit.d58ff9d0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +182 -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 +21 -43
- package/dest/prover/client/bb_private_kernel_prover.d.ts +29 -7
- package/dest/prover/client/bb_private_kernel_prover.d.ts.map +1 -1
- package/dest/prover/client/bb_private_kernel_prover.js +90 -16
- package/dest/prover/client/bundle.d.ts +3 -3
- package/dest/prover/client/bundle.d.ts.map +1 -1
- package/dest/prover/client/bundle.js +2 -3
- package/dest/prover/client/lazy.d.ts +3 -3
- package/dest/prover/client/lazy.d.ts.map +1 -1
- package/dest/prover/client/lazy.js +2 -3
- 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 +25 -2
- package/dest/prover/server/bb_prover.d.ts +9 -13
- package/dest/prover/server/bb_prover.d.ts.map +1 -1
- package/dest/prover/server/bb_prover.js +613 -113
- package/dest/test/delay_values.d.ts +1 -1
- package/dest/test/delay_values.d.ts.map +1 -1
- package/dest/test/delay_values.js +28 -26
- package/dest/test/index.d.ts +2 -1
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +1 -0
- package/dest/test/test_circuit_prover.d.ts +5 -5
- package/dest/test/test_circuit_prover.d.ts.map +1 -1
- package/dest/test/test_circuit_prover.js +462 -59
- package/dest/verification_key/verification_key_data.d.ts +1 -8
- package/dest/verification_key/verification_key_data.d.ts.map +1 -1
- package/dest/verification_key/verification_key_data.js +2 -21
- 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 -48
- 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 +15 -45
- package/package.json +20 -18
- package/src/avm_proving_tests/avm_proving_tester.ts +91 -142
- 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 +20 -43
- package/src/prover/client/bb_private_kernel_prover.ts +259 -25
- package/src/prover/client/bundle.ts +3 -4
- package/src/prover/client/lazy.ts +3 -4
- package/src/prover/proof_utils.ts +42 -2
- package/src/prover/server/bb_prover.ts +132 -162
- package/src/test/delay_values.ts +30 -26
- package/src/test/index.ts +1 -0
- package/src/test/test_circuit_prover.ts +11 -16
- package/src/verification_key/verification_key_data.ts +2 -27
- package/src/verifier/batch_chonk_verifier.ts +415 -0
- package/src/verifier/bb_verifier.ts +66 -80
- package/src/verifier/index.ts +1 -0
- package/src/verifier/queued_chonk_verifier.ts +15 -47
- package/dest/bb/execute.d.ts +0 -107
- package/dest/bb/execute.d.ts.map +0 -1
- package/dest/bb/execute.js +0 -676
- package/src/bb/execute.ts +0 -706
|
@@ -1,15 +1,14 @@
|
|
|
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,
|
|
6
6
|
RECURSIVE_PROOF_LENGTH,
|
|
7
7
|
ULTRA_KECCAK_PROOF_LENGTH,
|
|
8
8
|
} from '@aztec/constants';
|
|
9
|
-
import { Fr } from '@aztec/foundation/
|
|
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
|
|
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 {
|
|
95
|
+
import { getUltraHonkFlavorForCircuit } from '../../honk.js';
|
|
110
96
|
import { ProverInstrumentation } from '../../instrumentation.js';
|
|
111
|
-
import {
|
|
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
|
|
130
|
+
logger.info(`Using bb.js API with binary at ${config.bbBinaryPath}`);
|
|
144
131
|
logger.info(`Using native ACVM at ${config.acvmBinaryPath} and working directory ${config.acvmWorkingDirectory}`);
|
|
145
132
|
|
|
146
133
|
return new BBNativeRollupProver(config, telemetry);
|
|
@@ -190,16 +177,10 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
190
177
|
@trackSpan('BBNativeRollupProver.getAvmProof', inputs => ({
|
|
191
178
|
[Attributes.APP_CIRCUIT_NAME]: inputs.hints.tx.hash,
|
|
192
179
|
}))
|
|
193
|
-
public async getAvmProof(
|
|
194
|
-
inputs
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const proofAndVk = await this.createAvmProof(inputs);
|
|
198
|
-
await this.verifyAvmProof(proofAndVk.proof.binaryProof, proofAndVk.verificationKey, inputs.publicInputs);
|
|
199
|
-
|
|
200
|
-
// TODO(#14234)[Unconditional PIs validation]: remove next lines and directly return proofAndVk
|
|
201
|
-
proofAndVk.proof.proof = enhanceProofWithPiValidationFlag(proofAndVk.proof.proof, skipPublicInputsValidation);
|
|
202
|
-
return proofAndVk;
|
|
180
|
+
public async getAvmProof(inputs: AvmCircuitInputs): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS>> {
|
|
181
|
+
const proof = await this.createAvmProof(inputs);
|
|
182
|
+
await this.verifyAvmProof(proof.binaryProof, inputs.publicInputs);
|
|
183
|
+
return proof;
|
|
203
184
|
}
|
|
204
185
|
|
|
205
186
|
public async getPublicChonkVerifierProof(
|
|
@@ -461,16 +442,16 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
461
442
|
convertInput: (input: Input) => WitnessMap,
|
|
462
443
|
convertOutput: (outputWitness: WitnessMap) => Output,
|
|
463
444
|
workingDirectory: string,
|
|
464
|
-
): Promise<{ circuitOutput: Output;
|
|
465
|
-
// Have the ACVM write the partial witness here
|
|
445
|
+
): Promise<{ circuitOutput: Output; proofResult: BBJsProofResult }> {
|
|
446
|
+
// Have the ACVM write the partial witness here (still needs a temp directory)
|
|
466
447
|
const outputWitnessFile = path.join(workingDirectory, 'partial-witness.gz');
|
|
467
448
|
|
|
468
449
|
// Generate the partial witness using the ACVM
|
|
469
|
-
// A further temp directory will be created beneath ours and then cleaned up after the partial witness has been copied to our specified location
|
|
470
450
|
const simulator = new NativeACVMSimulator(
|
|
471
451
|
this.config.acvmWorkingDirectory,
|
|
472
452
|
this.config.acvmBinaryPath,
|
|
473
453
|
outputWitnessFile,
|
|
454
|
+
logger,
|
|
474
455
|
);
|
|
475
456
|
|
|
476
457
|
const artifact = getServerCircuitArtifact(circuitType);
|
|
@@ -478,7 +459,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
478
459
|
logger.debug(`Generating witness data for ${circuitType}`);
|
|
479
460
|
|
|
480
461
|
const inputWitness = convertInput(input);
|
|
481
|
-
const foreignCallHandler = undefined;
|
|
462
|
+
const foreignCallHandler = undefined;
|
|
482
463
|
const witnessResult = await simulator.executeProtocolCircuit(inputWitness, artifact, foreignCallHandler);
|
|
483
464
|
const output = convertOutput(witnessResult.witness);
|
|
484
465
|
|
|
@@ -495,76 +476,72 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
495
476
|
eventName: 'circuit-witness-generation',
|
|
496
477
|
} satisfies CircuitWitnessGenerationStats);
|
|
497
478
|
|
|
498
|
-
//
|
|
499
|
-
|
|
479
|
+
// Read and decompress the witness for bb.js
|
|
480
|
+
const witnessGz = await fs.readFile(outputWitnessFile);
|
|
481
|
+
const witness = ungzip(witnessGz);
|
|
500
482
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
this.getVerificationKeyDataForCircuit(circuitType).keyAsBytes,
|
|
507
|
-
outputWitnessFile,
|
|
508
|
-
getUltraHonkFlavorForCircuit(circuitType),
|
|
509
|
-
logger,
|
|
510
|
-
);
|
|
483
|
+
// Decompress bytecode for bb.js
|
|
484
|
+
const bytecode = ungzip(Buffer.from(artifact.bytecode, 'base64'));
|
|
485
|
+
|
|
486
|
+
// Prove the circuit via bb.js API
|
|
487
|
+
logger.debug(`Proving ${circuitType} via bb.js...`);
|
|
511
488
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
489
|
+
let proofResult: BBJsProofResult;
|
|
490
|
+
try {
|
|
491
|
+
await using instance = await this.bbJsFactory.getInstance();
|
|
492
|
+
proofResult = await instance.generateProof(
|
|
493
|
+
circuitType,
|
|
494
|
+
bytecode,
|
|
495
|
+
this.getVerificationKeyDataForCircuit(circuitType).keyAsBytes,
|
|
496
|
+
witness,
|
|
497
|
+
getUltraHonkFlavorForCircuit(circuitType),
|
|
498
|
+
);
|
|
499
|
+
} catch (error) {
|
|
500
|
+
throw new ProvingError(`Failed to generate proof for ${circuitType}: ${error}`);
|
|
515
501
|
}
|
|
516
502
|
|
|
517
503
|
return {
|
|
518
504
|
circuitOutput: output,
|
|
519
|
-
|
|
505
|
+
proofResult,
|
|
520
506
|
};
|
|
521
507
|
}
|
|
522
508
|
|
|
523
|
-
private async
|
|
509
|
+
private async createAvmProof(input: AvmCircuitInputs): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS>> {
|
|
524
510
|
logger.info(`Proving avm-circuit for TX ${input.hints.tx.hash}...`);
|
|
525
511
|
|
|
526
|
-
const
|
|
512
|
+
const inputsBuffer = input.serializeWithMessagePack();
|
|
513
|
+
await using instance = await this.bbJsFactory.getInstance();
|
|
514
|
+
const { proof: proofFieldArrays, durationMs } = await instance.generateAvmProof(inputsBuffer);
|
|
527
515
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
throw new ProvingError(provingResult.reason, provingResult, provingResult.retry);
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
return provingResult;
|
|
534
|
-
}
|
|
516
|
+
// Convert Uint8Array[] (32-byte field elements) to Fr[]
|
|
517
|
+
const proofFields = proofFieldArrays.map(f => Fr.fromBuffer(Buffer.from(f)));
|
|
535
518
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
const operation = async (bbWorkingDirectory: string) => {
|
|
540
|
-
const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory);
|
|
519
|
+
if (proofFields.length !== AVM_V2_PROOF_LENGTH_IN_FIELDS) {
|
|
520
|
+
throw new Error(`Proof has ${proofFields.length} fields, expected exactly ${AVM_V2_PROOF_LENGTH_IN_FIELDS}.`);
|
|
521
|
+
}
|
|
541
522
|
|
|
542
|
-
|
|
543
|
-
|
|
523
|
+
// Build the binary proof from the raw field data
|
|
524
|
+
const rawProofBuffer = Buffer.concat(proofFieldArrays.map(f => Buffer.from(f)));
|
|
525
|
+
const binaryProof = new Proof(rawProofBuffer, /*numPublicInputs=*/ 0);
|
|
526
|
+
const avmProof = new RecursiveProof(proofFields, binaryProof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS);
|
|
544
527
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
528
|
+
const circuitType = 'avm-circuit' as const;
|
|
529
|
+
const appCircuitName = 'unknown' as const;
|
|
530
|
+
this.instrumentation.recordAvmDuration('provingDuration', appCircuitName, durationMs);
|
|
531
|
+
this.instrumentation.recordAvmSize('proofSize', appCircuitName, avmProof.binaryProof.buffer.length);
|
|
549
532
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
circuitSize: 1 << 21,
|
|
561
|
-
numPublicInputs: 0,
|
|
562
|
-
} satisfies CircuitProvingStats,
|
|
563
|
-
);
|
|
533
|
+
logger.info(`Generated proof for ${circuitType}(${input.hints.tx.hash}) in ${Math.ceil(durationMs)} ms`, {
|
|
534
|
+
circuitName: circuitType,
|
|
535
|
+
appCircuitName: input.hints.tx.hash,
|
|
536
|
+
duration: durationMs,
|
|
537
|
+
proofSize: avmProof.binaryProof.buffer.length,
|
|
538
|
+
eventName: 'circuit-proving',
|
|
539
|
+
inputSize: inputsBuffer.length,
|
|
540
|
+
circuitSize: 1 << 21,
|
|
541
|
+
numPublicInputs: 0,
|
|
542
|
+
} satisfies CircuitProvingStats);
|
|
564
543
|
|
|
565
|
-
|
|
566
|
-
};
|
|
567
|
-
return await this.runInDirectory(operation);
|
|
544
|
+
return avmProof;
|
|
568
545
|
}
|
|
569
546
|
|
|
570
547
|
/**
|
|
@@ -587,33 +564,38 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
587
564
|
convertInput: (input: CircuitInputType) => WitnessMap,
|
|
588
565
|
convertOutput: (outputWitness: WitnessMap) => CircuitOutputType,
|
|
589
566
|
): Promise<{ circuitOutput: CircuitOutputType; proof: RecursiveProof<PROOF_LENGTH> }> {
|
|
590
|
-
//
|
|
591
|
-
const operation = async (
|
|
592
|
-
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(
|
|
593
570
|
input,
|
|
594
571
|
circuitType,
|
|
595
572
|
convertInput,
|
|
596
573
|
convertOutput,
|
|
597
|
-
|
|
574
|
+
workingDirectory,
|
|
598
575
|
);
|
|
599
576
|
|
|
600
577
|
const vkData = this.getVerificationKeyDataForCircuit(circuitType);
|
|
601
|
-
//
|
|
602
|
-
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
|
+
);
|
|
603
585
|
|
|
604
586
|
const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
|
|
605
|
-
this.instrumentation.recordDuration('provingDuration', circuitName,
|
|
587
|
+
this.instrumentation.recordDuration('provingDuration', circuitName, proofResult.durationMs);
|
|
606
588
|
this.instrumentation.recordSize('proofSize', circuitName, proof.binaryProof.buffer.length);
|
|
607
589
|
this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs);
|
|
608
590
|
this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize);
|
|
609
591
|
logger.info(
|
|
610
|
-
`Generated proof for ${circuitType} in ${Math.ceil(
|
|
592
|
+
`Generated proof for ${circuitType} in ${Math.ceil(proofResult.durationMs)} ms, size: ${
|
|
611
593
|
proof.proof.length
|
|
612
594
|
} fields`,
|
|
613
595
|
{
|
|
614
596
|
circuitName,
|
|
615
597
|
circuitSize: vkData.circuitSize,
|
|
616
|
-
duration:
|
|
598
|
+
duration: proofResult.durationMs,
|
|
617
599
|
inputSize: output.toBuffer().length,
|
|
618
600
|
proofSize: proof.binaryProof.buffer.length,
|
|
619
601
|
eventName: 'circuit-proving',
|
|
@@ -630,56 +612,58 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
630
612
|
}
|
|
631
613
|
|
|
632
614
|
/**
|
|
633
|
-
* Verifies a proof
|
|
615
|
+
* Verifies a proof via bb.js API (no temp files needed).
|
|
634
616
|
* @param circuitType - The type of circuit whose proof is to be verified
|
|
635
617
|
* @param proof - The proof to be verified
|
|
636
618
|
*/
|
|
637
619
|
public async verifyProof(circuitType: ServerProtocolArtifact, proof: Proof) {
|
|
638
620
|
const verificationKey = this.getVerificationKeyDataForCircuit(circuitType);
|
|
639
|
-
|
|
640
|
-
|
|
621
|
+
const flavor = getUltraHonkFlavorForCircuit(circuitType);
|
|
622
|
+
|
|
623
|
+
// Split proof buffer into public input fields and proof fields (32-byte each)
|
|
624
|
+
const publicInputFields = splitBufferToFieldArrays(proof.buffer.subarray(0, proof.numPublicInputs * 32));
|
|
625
|
+
const proofFields = splitBufferToFieldArrays(proof.buffer.subarray(proof.numPublicInputs * 32));
|
|
626
|
+
|
|
627
|
+
let verified: boolean;
|
|
628
|
+
let durationMs: number;
|
|
629
|
+
try {
|
|
630
|
+
await using instance = await this.bbJsFactory.getInstance();
|
|
631
|
+
({ verified, durationMs } = await instance.verifyProof(
|
|
632
|
+
proofFields,
|
|
633
|
+
verificationKey.keyAsBytes,
|
|
634
|
+
publicInputFields,
|
|
635
|
+
flavor,
|
|
636
|
+
));
|
|
637
|
+
} catch (error) {
|
|
638
|
+
throw new ProvingError(`Failed to verify proof for ${circuitType}: ${error}`);
|
|
639
|
+
}
|
|
641
640
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
publicInputs: AvmCircuitPublicInputs,
|
|
646
|
-
) {
|
|
647
|
-
return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath) =>
|
|
648
|
-
verifyAvmProof(this.config.bbBinaryPath, this.config.bbWorkingDirectory, proofPath, publicInputs, vkPath, logger),
|
|
649
|
-
);
|
|
650
|
-
}
|
|
641
|
+
if (!verified) {
|
|
642
|
+
throw new ProvingError('Failed to verify proof from key!');
|
|
643
|
+
}
|
|
651
644
|
|
|
652
|
-
|
|
653
|
-
return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath) =>
|
|
654
|
-
verifyProof(this.config.bbBinaryPath, proofPath, vkPath, flavor, logger),
|
|
655
|
-
);
|
|
645
|
+
logger.info(`Successfully verified proof from key in ${durationMs} ms`);
|
|
656
646
|
}
|
|
657
647
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
const
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
await fs.writeFile(publicInputsFileName, proof.buffer.slice(0, proof.numPublicInputs * 32));
|
|
669
|
-
await fs.writeFile(proofFileName, proof.buffer.slice(proof.numPublicInputs * 32));
|
|
670
|
-
await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes);
|
|
671
|
-
|
|
672
|
-
const result = await verificationFunction(proofFileName, verificationKeyPath!);
|
|
673
|
-
|
|
674
|
-
if (result.status === BB_RESULT.FAILURE) {
|
|
675
|
-
const errorMessage = `Failed to verify proof from key!`;
|
|
676
|
-
throw new ProvingError(errorMessage, result, result.retry);
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
logger.info(`Successfully verified proof from key in ${result.durationMs} ms`);
|
|
680
|
-
};
|
|
648
|
+
/** Verify an AVM proof via bb.js API. */
|
|
649
|
+
public async verifyAvmProof(proof: Proof, publicInputs: AvmCircuitPublicInputs) {
|
|
650
|
+
// For AVM proofs, numPublicInputs is 0, so the full buffer is the proof.
|
|
651
|
+
const proofBuffer = proof.buffer.subarray(proof.numPublicInputs * 32);
|
|
652
|
+
// Split the raw proof buffer into 32-byte field element arrays
|
|
653
|
+
const proofFields: Uint8Array[] = [];
|
|
654
|
+
for (let i = 0; i < proofBuffer.length; i += Fr.SIZE_IN_BYTES) {
|
|
655
|
+
proofFields.push(new Uint8Array(proofBuffer.subarray(i, i + Fr.SIZE_IN_BYTES)));
|
|
656
|
+
}
|
|
657
|
+
const piBuffer = publicInputs.serializeWithMessagePack();
|
|
681
658
|
|
|
682
|
-
await this.
|
|
659
|
+
await using instance = await this.bbJsFactory.getInstance();
|
|
660
|
+
const { verified, durationMs } = await instance.verifyAvmProof(proofFields, piBuffer);
|
|
661
|
+
|
|
662
|
+
if (!verified) {
|
|
663
|
+
throw new ProvingError('Failed to verify AVM proof!');
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
logger.info(`Successfully verified AVM proof in ${durationMs} ms`);
|
|
683
667
|
}
|
|
684
668
|
|
|
685
669
|
/**
|
|
@@ -695,29 +679,6 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
695
679
|
return vk;
|
|
696
680
|
}
|
|
697
681
|
|
|
698
|
-
private async readAvmProofAsFields(
|
|
699
|
-
proofFilename: string,
|
|
700
|
-
): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
|
|
701
|
-
const rawProofBuffer = await fs.readFile(proofFilename);
|
|
702
|
-
const reader = BufferReader.asReader(rawProofBuffer);
|
|
703
|
-
const proofFields = reader.readArray(rawProofBuffer.length / Fr.SIZE_IN_BYTES, Fr);
|
|
704
|
-
|
|
705
|
-
// We extend to a fixed-size padded proof as during development any new AVM circuit column changes the
|
|
706
|
-
// proof length and we do not have a mechanism to feedback a cpp constant to noir/TS.
|
|
707
|
-
// TODO(#13390): Revive a non-padded AVM proof
|
|
708
|
-
if (proofFields.length > AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED) {
|
|
709
|
-
throw new Error(
|
|
710
|
-
`Proof has ${proofFields.length} fields, expected no more than ${AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED}.`,
|
|
711
|
-
);
|
|
712
|
-
}
|
|
713
|
-
const proofFieldsPadded = proofFields.concat(
|
|
714
|
-
Array(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED - proofFields.length).fill(new Fr(0)),
|
|
715
|
-
);
|
|
716
|
-
|
|
717
|
-
const proof = new Proof(rawProofBuffer, /*numPublicInputs=*/ 0);
|
|
718
|
-
return new RecursiveProof(proofFieldsPadded, proof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED);
|
|
719
|
-
}
|
|
720
|
-
|
|
721
682
|
private runInDirectory<T>(fn: (dir: string) => Promise<T>) {
|
|
722
683
|
return runInDirectory(
|
|
723
684
|
this.config.bbWorkingDirectory,
|
|
@@ -731,3 +692,12 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
731
692
|
);
|
|
732
693
|
}
|
|
733
694
|
}
|
|
695
|
+
|
|
696
|
+
/** Split a buffer into 32-byte Uint8Array field elements. */
|
|
697
|
+
function splitBufferToFieldArrays(buffer: Buffer): Uint8Array[] {
|
|
698
|
+
const fields: Uint8Array[] = [];
|
|
699
|
+
for (let i = 0; i < buffer.length; i += 32) {
|
|
700
|
+
fields.push(new Uint8Array(buffer.subarray(i, i + 32)));
|
|
701
|
+
}
|
|
702
|
+
return fields;
|
|
703
|
+
}
|
package/src/test/delay_values.ts
CHANGED
|
@@ -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.
|
|
5
|
-
[ProvingRequestType.
|
|
6
|
-
[ProvingRequestType.
|
|
7
|
-
[ProvingRequestType.
|
|
4
|
+
[ProvingRequestType.PUBLIC_CHONK_VERIFIER]: 60,
|
|
5
|
+
[ProvingRequestType.PARITY_BASE]: 1_600,
|
|
6
|
+
[ProvingRequestType.PARITY_ROOT]: 40,
|
|
7
|
+
[ProvingRequestType.BLOCK_ROOT_FIRST_ROLLUP]: 45,
|
|
8
8
|
[ProvingRequestType.BLOCK_ROOT_EMPTY_TX_FIRST_ROLLUP]: 18,
|
|
9
|
+
[ProvingRequestType.BLOCK_ROOT_SINGLE_TX_FIRST_ROLLUP]: 27,
|
|
10
|
+
[ProvingRequestType.CHECKPOINT_MERGE_ROLLUP]: 30,
|
|
11
|
+
[ProvingRequestType.CHECKPOINT_ROOT_SINGLE_BLOCK_ROLLUP]: 36_000,
|
|
12
|
+
[ProvingRequestType.ROOT_ROLLUP]: 35,
|
|
13
|
+
[ProvingRequestType.PUBLIC_TX_BASE_ROLLUP]: 2_500,
|
|
14
|
+
[ProvingRequestType.TX_MERGE_ROLLUP]: 25,
|
|
15
|
+
[ProvingRequestType.PUBLIC_VM]: 0,
|
|
16
|
+
|
|
17
|
+
// TBD
|
|
18
|
+
[ProvingRequestType.BLOCK_MERGE_ROLLUP]: 30,
|
|
9
19
|
[ProvingRequestType.BLOCK_ROOT_ROLLUP]: 40_000,
|
|
10
20
|
[ProvingRequestType.BLOCK_ROOT_SINGLE_TX_ROLLUP]: 20_000,
|
|
11
21
|
[ProvingRequestType.CHECKPOINT_ROOT_ROLLUP]: 40_000,
|
|
12
|
-
[ProvingRequestType.CHECKPOINT_ROOT_SINGLE_BLOCK_ROLLUP]: 36_000,
|
|
13
22
|
[ProvingRequestType.CHECKPOINT_PADDING_ROLLUP]: 0,
|
|
14
|
-
[ProvingRequestType.
|
|
15
|
-
[ProvingRequestType.TX_MERGE_ROLLUP]: 0,
|
|
16
|
-
[ProvingRequestType.PRIVATE_TX_BASE_ROLLUP]: 400_000,
|
|
17
|
-
[ProvingRequestType.PUBLIC_TX_BASE_ROLLUP]: 470_000,
|
|
18
|
-
[ProvingRequestType.PARITY_ROOT]: 39,
|
|
19
|
-
[ProvingRequestType.ROOT_ROLLUP]: 35,
|
|
20
|
-
[ProvingRequestType.PUBLIC_CHONK_VERIFIER]: 0,
|
|
21
|
-
[ProvingRequestType.PUBLIC_VM]: 0,
|
|
23
|
+
[ProvingRequestType.PRIVATE_TX_BASE_ROLLUP]: 2_500, // Guess based on public
|
|
22
24
|
};
|
|
23
25
|
|
|
24
26
|
export const PROOF_DELAY_MS: Record<ProvingRequestType, number> = {
|
|
25
|
-
[ProvingRequestType.
|
|
27
|
+
[ProvingRequestType.PUBLIC_CHONK_VERIFIER]: 16_300,
|
|
28
|
+
[ProvingRequestType.PARITY_BASE]: 15_300,
|
|
29
|
+
[ProvingRequestType.PARITY_ROOT]: 18_600,
|
|
30
|
+
[ProvingRequestType.BLOCK_ROOT_FIRST_ROLLUP]: 17_400,
|
|
31
|
+
[ProvingRequestType.BLOCK_ROOT_EMPTY_TX_FIRST_ROLLUP]: 4_500,
|
|
32
|
+
[ProvingRequestType.BLOCK_ROOT_SINGLE_TX_FIRST_ROLLUP]: 9_200,
|
|
33
|
+
[ProvingRequestType.CHECKPOINT_MERGE_ROLLUP]: 10_200,
|
|
34
|
+
[ProvingRequestType.CHECKPOINT_ROOT_SINGLE_BLOCK_ROLLUP]: 37_100,
|
|
35
|
+
[ProvingRequestType.ROOT_ROLLUP]: 93_000,
|
|
36
|
+
[ProvingRequestType.TX_MERGE_ROLLUP]: 10_000,
|
|
37
|
+
[ProvingRequestType.PUBLIC_TX_BASE_ROLLUP]: 44_500,
|
|
38
|
+
[ProvingRequestType.PUBLIC_VM]: 180_000,
|
|
39
|
+
|
|
40
|
+
// TBD
|
|
26
41
|
[ProvingRequestType.BLOCK_MERGE_ROLLUP]: 15_000,
|
|
27
|
-
[ProvingRequestType.BLOCK_ROOT_FIRST_ROLLUP]: 55_000,
|
|
28
|
-
[ProvingRequestType.BLOCK_ROOT_SINGLE_TX_FIRST_ROLLUP]: 35_000,
|
|
29
|
-
[ProvingRequestType.BLOCK_ROOT_EMPTY_TX_FIRST_ROLLUP]: 4_000,
|
|
30
42
|
[ProvingRequestType.BLOCK_ROOT_ROLLUP]: 35_000,
|
|
31
43
|
[ProvingRequestType.BLOCK_ROOT_SINGLE_TX_ROLLUP]: 15_000,
|
|
32
44
|
[ProvingRequestType.CHECKPOINT_ROOT_ROLLUP]: 35_000,
|
|
33
|
-
[ProvingRequestType.CHECKPOINT_ROOT_SINGLE_BLOCK_ROLLUP]: 35_000,
|
|
34
45
|
[ProvingRequestType.CHECKPOINT_PADDING_ROLLUP]: 0,
|
|
35
|
-
[ProvingRequestType.
|
|
36
|
-
[ProvingRequestType.TX_MERGE_ROLLUP]: 0,
|
|
37
|
-
[ProvingRequestType.PRIVATE_TX_BASE_ROLLUP]: 145_000,
|
|
38
|
-
[ProvingRequestType.PUBLIC_TX_BASE_ROLLUP]: 160_000,
|
|
39
|
-
[ProvingRequestType.PARITY_ROOT]: 16_000,
|
|
40
|
-
[ProvingRequestType.ROOT_ROLLUP]: 140_000,
|
|
41
|
-
[ProvingRequestType.PUBLIC_CHONK_VERIFIER]: 30_000,
|
|
42
|
-
[ProvingRequestType.PUBLIC_VM]: 0,
|
|
46
|
+
[ProvingRequestType.PRIVATE_TX_BASE_ROLLUP]: 22_000,
|
|
43
47
|
};
|
package/src/test/index.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED,
|
|
2
|
+
AVM_V2_PROOF_LENGTH_IN_FIELDS,
|
|
4
3
|
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
5
4
|
NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
|
|
6
5
|
RECURSIVE_PROOF_LENGTH,
|
|
@@ -51,14 +50,18 @@ import type { WitnessMap } from '@aztec/noir-types';
|
|
|
51
50
|
import { type CircuitSimulator, WASMSimulatorWithBlobs, emitCircuitSimulationStats } from '@aztec/simulator/server';
|
|
52
51
|
import type { AvmCircuitInputs } from '@aztec/stdlib/avm';
|
|
53
52
|
import {
|
|
54
|
-
type ProofAndVerificationKey,
|
|
55
53
|
type PublicInputsAndRecursiveProof,
|
|
56
54
|
type ServerCircuitProver,
|
|
57
|
-
makeProofAndVerificationKey,
|
|
58
55
|
makePublicInputsAndRecursiveProof,
|
|
59
56
|
} from '@aztec/stdlib/interfaces/server';
|
|
60
57
|
import type { ParityBasePrivateInputs, ParityPublicInputs, ParityRootPrivateInputs } from '@aztec/stdlib/parity';
|
|
61
|
-
import {
|
|
58
|
+
import {
|
|
59
|
+
type Proof,
|
|
60
|
+
ProvingRequestType,
|
|
61
|
+
RecursiveProof,
|
|
62
|
+
makeEmptyRecursiveProof,
|
|
63
|
+
makeRecursiveProof,
|
|
64
|
+
} from '@aztec/stdlib/proofs';
|
|
62
65
|
import {
|
|
63
66
|
type BlockMergeRollupPrivateInputs,
|
|
64
67
|
type BlockRollupPublicInputs,
|
|
@@ -81,7 +84,6 @@ import {
|
|
|
81
84
|
type TxMergeRollupPrivateInputs,
|
|
82
85
|
type TxRollupPublicInputs,
|
|
83
86
|
} from '@aztec/stdlib/rollup';
|
|
84
|
-
import { VerificationKeyData } from '@aztec/stdlib/vks';
|
|
85
87
|
import { type TelemetryClient, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
86
88
|
|
|
87
89
|
import { ProverInstrumentation } from '../instrumentation.js';
|
|
@@ -400,18 +402,11 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
400
402
|
);
|
|
401
403
|
}
|
|
402
404
|
|
|
403
|
-
public getAvmProof(
|
|
404
|
-
_inputs: AvmCircuitInputs,
|
|
405
|
-
): Promise<ProofAndVerificationKey<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
|
|
405
|
+
public getAvmProof(_inputs: AvmCircuitInputs): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS>> {
|
|
406
406
|
// We can't simulate the AVM because we don't have enough context to do so (e.g., DBs).
|
|
407
|
-
// We just return an empty proof
|
|
407
|
+
// We just return an empty proof.
|
|
408
408
|
this.logger.debug('Skipping AVM simulation in TestCircuitProver.');
|
|
409
|
-
return this.applyDelay(ProvingRequestType.PUBLIC_VM, () =>
|
|
410
|
-
makeProofAndVerificationKey(
|
|
411
|
-
makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED),
|
|
412
|
-
VerificationKeyData.makeFake(AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED),
|
|
413
|
-
),
|
|
414
|
-
);
|
|
409
|
+
return this.applyDelay(ProvingRequestType.PUBLIC_VM, () => makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS));
|
|
415
410
|
}
|
|
416
411
|
|
|
417
412
|
private async applyDelay<F extends () => any>(type: ProvingRequestType, fn: F): Promise<Awaited<ReturnType<F>>> {
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import {
|
|
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/
|
|
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
|
-
}
|