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