@aztec/bb-prover 0.67.1 → 0.68.0
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/bb/execute.d.ts +1 -1
- package/dest/bb/execute.d.ts.map +1 -1
- package/dest/bb/execute.js +4 -3
- package/dest/prover/bb_private_kernel_prover.d.ts +2 -11
- package/dest/prover/bb_private_kernel_prover.d.ts.map +1 -1
- package/dest/prover/bb_private_kernel_prover.js +10 -72
- package/dest/prover/bb_prover.d.ts +3 -2
- package/dest/prover/bb_prover.d.ts.map +1 -1
- package/dest/prover/bb_prover.js +3 -2
- package/dest/prover/client_ivc_proof_utils.d.ts +23 -0
- package/dest/prover/client_ivc_proof_utils.d.ts.map +1 -0
- package/dest/prover/client_ivc_proof_utils.js +35 -0
- package/dest/prover/index.d.ts +1 -0
- package/dest/prover/index.d.ts.map +1 -1
- package/dest/prover/index.js +2 -1
- package/dest/test/test_circuit_prover.d.ts +2 -1
- package/dest/test/test_circuit_prover.d.ts.map +1 -1
- package/dest/test/test_circuit_prover.js +11 -6
- package/dest/verifier/bb_verifier.d.ts.map +1 -1
- package/dest/verifier/bb_verifier.js +3 -2
- package/dest/wasm/index.d.ts +19 -0
- package/dest/wasm/index.d.ts.map +1 -0
- package/dest/wasm/index.js +74 -0
- package/package.json +16 -12
- package/src/bb/execute.ts +3 -1
- package/src/prover/bb_private_kernel_prover.ts +14 -133
- package/src/prover/bb_prover.ts +15 -12
- package/src/prover/client_ivc_proof_utils.ts +39 -0
- package/src/prover/index.ts +1 -0
- package/src/test/test_circuit_prover.ts +25 -18
- package/src/verifier/bb_verifier.ts +2 -1
- package/src/wasm/index.ts +155 -0
package/src/bb/execute.ts
CHANGED
|
@@ -889,6 +889,7 @@ export async function computeGateCountForCircuit(
|
|
|
889
889
|
circuitName: string,
|
|
890
890
|
bytecode: Buffer,
|
|
891
891
|
flavor: UltraHonkFlavor | 'mega_honk',
|
|
892
|
+
log: LogFn,
|
|
892
893
|
): Promise<BBFailure | BBSuccess> {
|
|
893
894
|
// Check that the working directory exists
|
|
894
895
|
try {
|
|
@@ -912,6 +913,7 @@ export async function computeGateCountForCircuit(
|
|
|
912
913
|
let stdout = '';
|
|
913
914
|
const logHandler = (message: string) => {
|
|
914
915
|
stdout += message;
|
|
916
|
+
log(message);
|
|
915
917
|
};
|
|
916
918
|
|
|
917
919
|
try {
|
|
@@ -921,7 +923,7 @@ export async function computeGateCountForCircuit(
|
|
|
921
923
|
|
|
922
924
|
const result = await executeBB(
|
|
923
925
|
pathToBB,
|
|
924
|
-
flavor === 'mega_honk' ? `
|
|
926
|
+
flavor === 'mega_honk' ? `gates_for_ivc` : `gates`,
|
|
925
927
|
['-b', bytecodePath, '-v'],
|
|
926
928
|
logHandler,
|
|
927
929
|
);
|
|
@@ -1,22 +1,14 @@
|
|
|
1
|
+
import { type PrivateKernelProver, type PrivateKernelSimulateOutput } from '@aztec/circuit-types';
|
|
2
|
+
import { type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats';
|
|
1
3
|
import {
|
|
2
|
-
type
|
|
3
|
-
type PrivateKernelProver,
|
|
4
|
-
type PrivateKernelSimulateOutput,
|
|
5
|
-
} from '@aztec/circuit-types';
|
|
6
|
-
import { type CircuitSimulationStats, type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats';
|
|
7
|
-
import {
|
|
8
|
-
AGGREGATION_OBJECT_LENGTH,
|
|
9
|
-
ClientIvcProof,
|
|
10
|
-
Fr,
|
|
4
|
+
type ClientIvcProof,
|
|
11
5
|
type PrivateKernelCircuitPublicInputs,
|
|
12
6
|
type PrivateKernelInitCircuitPrivateInputs,
|
|
13
7
|
type PrivateKernelInnerCircuitPrivateInputs,
|
|
14
8
|
type PrivateKernelResetCircuitPrivateInputs,
|
|
15
9
|
type PrivateKernelTailCircuitPrivateInputs,
|
|
16
10
|
type PrivateKernelTailCircuitPublicInputs,
|
|
17
|
-
Proof,
|
|
18
|
-
RecursiveProof,
|
|
19
|
-
type VerificationKeyAsFields,
|
|
11
|
+
type Proof,
|
|
20
12
|
type VerificationKeyData,
|
|
21
13
|
} from '@aztec/circuits.js';
|
|
22
14
|
import { runInDirectory } from '@aztec/foundation/fs';
|
|
@@ -39,7 +31,7 @@ import {
|
|
|
39
31
|
convertPrivateKernelTailToPublicInputsToWitnessMap,
|
|
40
32
|
getPrivateKernelResetArtifactName,
|
|
41
33
|
} from '@aztec/noir-protocol-circuits-types';
|
|
42
|
-
import {
|
|
34
|
+
import { WASMSimulatorWithBlobs } from '@aztec/simulator';
|
|
43
35
|
import { type NoirCompiledCircuit } from '@aztec/types/noir';
|
|
44
36
|
|
|
45
37
|
import { encode } from '@msgpack/msgpack';
|
|
@@ -48,19 +40,12 @@ import { type WitnessMap } from '@noir-lang/types';
|
|
|
48
40
|
import { promises as fs } from 'fs';
|
|
49
41
|
import path from 'path';
|
|
50
42
|
|
|
51
|
-
import {
|
|
52
|
-
BB_RESULT,
|
|
53
|
-
PROOF_FIELDS_FILENAME,
|
|
54
|
-
PROOF_FILENAME,
|
|
55
|
-
computeGateCountForCircuit,
|
|
56
|
-
computeVerificationKey,
|
|
57
|
-
executeBbClientIvcProof,
|
|
58
|
-
verifyProof,
|
|
59
|
-
} from '../bb/execute.js';
|
|
43
|
+
import { BB_RESULT, computeGateCountForCircuit, executeBbClientIvcProof, verifyProof } from '../bb/execute.js';
|
|
60
44
|
import { type BBConfig } from '../config.js';
|
|
61
45
|
import { type UltraHonkFlavor, getUltraHonkFlavorForCircuit } from '../honk.js';
|
|
62
46
|
import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
|
|
63
47
|
import { extractVkData } from '../verification_key/verification_key_data.js';
|
|
48
|
+
import { readFromOutputDirectory } from './client_ivc_proof_utils.js';
|
|
64
49
|
|
|
65
50
|
/**
|
|
66
51
|
* This proof creator implementation uses the native bb binary.
|
|
@@ -68,7 +53,7 @@ import { extractVkData } from '../verification_key/verification_key_data.js';
|
|
|
68
53
|
* TODO(#7368): this class grew 'organically' aka it could use a look at its resposibilities
|
|
69
54
|
*/
|
|
70
55
|
export class BBNativePrivateKernelProver implements PrivateKernelProver {
|
|
71
|
-
private simulator = new
|
|
56
|
+
private simulator = new WASMSimulatorWithBlobs();
|
|
72
57
|
|
|
73
58
|
private verificationKeys: Map<ClientProtocolArtifact, Promise<VerificationKeyData>> = new Map<
|
|
74
59
|
ClientProtocolArtifact,
|
|
@@ -112,7 +97,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
|
|
|
112
97
|
throw new Error(provingResult.reason);
|
|
113
98
|
}
|
|
114
99
|
|
|
115
|
-
const proof = await
|
|
100
|
+
const proof = await readFromOutputDirectory(directory);
|
|
116
101
|
|
|
117
102
|
this.log.info(`Generated IVC proof`, {
|
|
118
103
|
duration: provingResult.durationMs,
|
|
@@ -184,22 +169,6 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
|
|
|
184
169
|
);
|
|
185
170
|
}
|
|
186
171
|
|
|
187
|
-
public async computeAppCircuitVerificationKey(
|
|
188
|
-
bytecode: Buffer,
|
|
189
|
-
appCircuitName?: string,
|
|
190
|
-
): Promise<AppCircuitSimulateOutput> {
|
|
191
|
-
const operation = async (directory: string) => {
|
|
192
|
-
this.log.debug(`Proving app circuit`);
|
|
193
|
-
// App circuits are always recursive; the #[recursive] attribute used to be applied automatically
|
|
194
|
-
// by the `private` comptime macro in noir-projects/aztec-nr/aztec/src/macros/functions/mod.nr
|
|
195
|
-
// Yet, inside `computeVerificationKey` the `mega_honk` flavor is used, which doesn't use the recursive flag.
|
|
196
|
-
const recursive = true;
|
|
197
|
-
return await this.computeVerificationKey(directory, bytecode, recursive, 'App', appCircuitName);
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
return await this.runInDirectory(operation);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
172
|
/**
|
|
204
173
|
* Verifies a proof, will generate the verification key if one is not cached internally
|
|
205
174
|
* @param circuitType - The type of circuit whose proof is to be verified
|
|
@@ -230,12 +199,17 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
|
|
|
230
199
|
}
|
|
231
200
|
|
|
232
201
|
public async computeGateCountForCircuit(bytecode: Buffer, circuitName: string): Promise<number> {
|
|
202
|
+
const logFunction = (message: string) => {
|
|
203
|
+
this.log.debug(`$bb gates ${circuitName} - ${message}`);
|
|
204
|
+
};
|
|
205
|
+
|
|
233
206
|
const result = await computeGateCountForCircuit(
|
|
234
207
|
this.bbBinaryPath,
|
|
235
208
|
this.bbWorkingDirectory,
|
|
236
209
|
circuitName,
|
|
237
210
|
bytecode,
|
|
238
211
|
'mega_honk',
|
|
212
|
+
logFunction,
|
|
239
213
|
);
|
|
240
214
|
if (result.status === BB_RESULT.FAILURE) {
|
|
241
215
|
throw new Error(result.reason);
|
|
@@ -313,99 +287,6 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
|
|
|
313
287
|
return kernelOutput;
|
|
314
288
|
}
|
|
315
289
|
|
|
316
|
-
private async computeVerificationKey(
|
|
317
|
-
directory: string,
|
|
318
|
-
bytecode: Buffer,
|
|
319
|
-
recursive: boolean,
|
|
320
|
-
circuitType: ClientProtocolArtifact | 'App',
|
|
321
|
-
appCircuitName?: string,
|
|
322
|
-
): Promise<{
|
|
323
|
-
verificationKey: VerificationKeyAsFields;
|
|
324
|
-
}> {
|
|
325
|
-
const dbgCircuitName = appCircuitName ? `(${appCircuitName})` : '';
|
|
326
|
-
this.log.info(`Computing VK of ${circuitType}${dbgCircuitName} circuit...`);
|
|
327
|
-
|
|
328
|
-
const timer = new Timer();
|
|
329
|
-
|
|
330
|
-
const vkResult = await computeVerificationKey(
|
|
331
|
-
this.bbBinaryPath,
|
|
332
|
-
directory,
|
|
333
|
-
circuitType,
|
|
334
|
-
bytecode,
|
|
335
|
-
recursive,
|
|
336
|
-
circuitType === 'App' ? 'mega_honk' : getUltraHonkFlavorForCircuit(circuitType),
|
|
337
|
-
this.log.debug,
|
|
338
|
-
);
|
|
339
|
-
|
|
340
|
-
if (vkResult.status === BB_RESULT.FAILURE) {
|
|
341
|
-
this.log.error(`Failed to generate verification key for ${circuitType}${dbgCircuitName}: ${vkResult.reason}`);
|
|
342
|
-
throw new Error(vkResult.reason);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
this.log.info(`Generated ${circuitType}${dbgCircuitName} VK in ${Math.ceil(timer.ms())} ms`);
|
|
346
|
-
|
|
347
|
-
if (circuitType === 'App') {
|
|
348
|
-
const vkData = await extractVkData(directory);
|
|
349
|
-
|
|
350
|
-
this.log.debug(`Computed verification key`, {
|
|
351
|
-
circuitName: 'app-circuit',
|
|
352
|
-
duration: vkResult.durationMs,
|
|
353
|
-
eventName: 'circuit-simulation',
|
|
354
|
-
inputSize: bytecode.length,
|
|
355
|
-
outputSize: vkData.keyAsBytes.length,
|
|
356
|
-
circuitSize: vkData.circuitSize,
|
|
357
|
-
numPublicInputs: vkData.numPublicInputs,
|
|
358
|
-
} as CircuitSimulationStats);
|
|
359
|
-
|
|
360
|
-
return { verificationKey: vkData.keyAsFields };
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
const vkData = await this.updateVerificationKeyAfterSimulation(directory, circuitType);
|
|
364
|
-
|
|
365
|
-
this.log.debug(`Computed verification key`, {
|
|
366
|
-
circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
|
|
367
|
-
duration: vkResult.durationMs,
|
|
368
|
-
eventName: 'circuit-simulation',
|
|
369
|
-
inputSize: bytecode.length,
|
|
370
|
-
outputSize: vkData.keyAsBytes.length,
|
|
371
|
-
circuitSize: vkData.circuitSize,
|
|
372
|
-
numPublicInputs: vkData.numPublicInputs,
|
|
373
|
-
} as CircuitSimulationStats);
|
|
374
|
-
|
|
375
|
-
return { verificationKey: vkData.keyAsFields };
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* Parses and returns the proof data stored at the specified directory
|
|
380
|
-
* @param filePath - The directory containing the proof data
|
|
381
|
-
* @param circuitType - The type of circuit proven
|
|
382
|
-
* @returns The proof
|
|
383
|
-
*/
|
|
384
|
-
private async readProofAsFields<PROOF_LENGTH extends number>(
|
|
385
|
-
filePath: string,
|
|
386
|
-
circuitType: ClientProtocolArtifact | 'App',
|
|
387
|
-
vkData: VerificationKeyData,
|
|
388
|
-
): Promise<RecursiveProof<PROOF_LENGTH>> {
|
|
389
|
-
const [binaryProof, proofString] = await Promise.all([
|
|
390
|
-
fs.readFile(`${filePath}/${PROOF_FILENAME}`),
|
|
391
|
-
fs.readFile(`${filePath}/${PROOF_FIELDS_FILENAME}`, { encoding: 'utf-8' }),
|
|
392
|
-
]);
|
|
393
|
-
const json = JSON.parse(proofString);
|
|
394
|
-
const fields = json.map(Fr.fromHexString);
|
|
395
|
-
const numPublicInputs = vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
|
|
396
|
-
const fieldsWithoutPublicInputs = fields.slice(numPublicInputs);
|
|
397
|
-
this.log.info(
|
|
398
|
-
`Circuit type: ${circuitType}, complete proof length: ${fields.length}, without public inputs: ${fieldsWithoutPublicInputs.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}, is recursive: ${vkData.isRecursive}, raw length: ${binaryProof.length}`,
|
|
399
|
-
);
|
|
400
|
-
const proof = new RecursiveProof<PROOF_LENGTH>(
|
|
401
|
-
fieldsWithoutPublicInputs,
|
|
402
|
-
new Proof(binaryProof, vkData.numPublicInputs),
|
|
403
|
-
true,
|
|
404
|
-
fieldsWithoutPublicInputs.length,
|
|
405
|
-
);
|
|
406
|
-
return proof;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
290
|
private runInDirectory<T>(fn: (dir: string) => Promise<T>) {
|
|
410
291
|
const log = this.log;
|
|
411
292
|
return runInDirectory(
|
package/src/prover/bb_prover.ts
CHANGED
|
@@ -12,35 +12,37 @@ import {
|
|
|
12
12
|
AGGREGATION_OBJECT_LENGTH,
|
|
13
13
|
AVM_PROOF_LENGTH_IN_FIELDS,
|
|
14
14
|
type AvmCircuitInputs,
|
|
15
|
-
type BaseOrMergeRollupPublicInputs,
|
|
16
15
|
type BaseParityInputs,
|
|
17
|
-
type BlockMergeRollupInputs,
|
|
18
|
-
type BlockRootOrBlockMergePublicInputs,
|
|
19
|
-
type BlockRootRollupInputs,
|
|
20
|
-
type EmptyBlockRootRollupInputs,
|
|
21
16
|
EmptyNestedCircuitInputs,
|
|
22
17
|
EmptyNestedData,
|
|
23
18
|
Fr,
|
|
24
19
|
type KernelCircuitPublicInputs,
|
|
25
|
-
type MergeRollupInputs,
|
|
26
20
|
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
27
21
|
type ParityPublicInputs,
|
|
28
|
-
type PrivateBaseRollupInputs,
|
|
29
22
|
type PrivateKernelEmptyInputData,
|
|
30
23
|
PrivateKernelEmptyInputs,
|
|
31
24
|
Proof,
|
|
32
|
-
type PublicBaseRollupInputs,
|
|
33
25
|
RECURSIVE_PROOF_LENGTH,
|
|
34
26
|
RecursiveProof,
|
|
35
27
|
type RootParityInputs,
|
|
36
|
-
type RootRollupInputs,
|
|
37
|
-
type RootRollupPublicInputs,
|
|
38
28
|
TUBE_PROOF_LENGTH,
|
|
39
|
-
type TubeInputs,
|
|
40
29
|
type VerificationKeyAsFields,
|
|
41
30
|
type VerificationKeyData,
|
|
42
31
|
makeRecursiveProofFromBinary,
|
|
43
32
|
} from '@aztec/circuits.js';
|
|
33
|
+
import {
|
|
34
|
+
type BaseOrMergeRollupPublicInputs,
|
|
35
|
+
type BlockMergeRollupInputs,
|
|
36
|
+
type BlockRootOrBlockMergePublicInputs,
|
|
37
|
+
type BlockRootRollupInputs,
|
|
38
|
+
type EmptyBlockRootRollupInputs,
|
|
39
|
+
type MergeRollupInputs,
|
|
40
|
+
type PrivateBaseRollupInputs,
|
|
41
|
+
type PublicBaseRollupInputs,
|
|
42
|
+
type RootRollupInputs,
|
|
43
|
+
type RootRollupPublicInputs,
|
|
44
|
+
type TubeInputs,
|
|
45
|
+
} from '@aztec/circuits.js/rollup';
|
|
44
46
|
import { runInDirectory } from '@aztec/foundation/fs';
|
|
45
47
|
import { createLogger } from '@aztec/foundation/log';
|
|
46
48
|
import { BufferReader } from '@aztec/foundation/serialize';
|
|
@@ -99,6 +101,7 @@ import { type UltraHonkFlavor, getUltraHonkFlavorForCircuit } from '../honk.js';
|
|
|
99
101
|
import { ProverInstrumentation } from '../instrumentation.js';
|
|
100
102
|
import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
|
|
101
103
|
import { extractAvmVkData, extractVkData } from '../verification_key/verification_key_data.js';
|
|
104
|
+
import { writeToOutputDirectory } from './client_ivc_proof_utils.js';
|
|
102
105
|
|
|
103
106
|
const logger = createLogger('bb-prover');
|
|
104
107
|
|
|
@@ -551,7 +554,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
551
554
|
const hasher = crypto.createHash('sha256');
|
|
552
555
|
hasher.update(input.toBuffer());
|
|
553
556
|
|
|
554
|
-
await input.clientIVCData
|
|
557
|
+
await writeToOutputDirectory(input.clientIVCData, bbWorkingDirectory);
|
|
555
558
|
const provingResult = await generateTubeProof(this.config.bbBinaryPath, bbWorkingDirectory, logger.verbose);
|
|
556
559
|
|
|
557
560
|
if (provingResult.status === BB_RESULT.FAILURE) {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ClientIvcProof } from '@aztec/circuits.js';
|
|
2
|
+
|
|
3
|
+
import { promises as fs } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* TODO(#7371): eventually remove client_ivc_prove_output_all_msgpack and properly handle these accumulators and VKs
|
|
8
|
+
* Create a ClientIvcProof from the result of client_ivc_prove_output_all or client_ivc_prove_output_all_msgpack
|
|
9
|
+
* @param directory the directory of results
|
|
10
|
+
* @returns the encapsulated client ivc proof
|
|
11
|
+
*/
|
|
12
|
+
export async function readFromOutputDirectory(directory: string) {
|
|
13
|
+
const [clientIvcVkBuffer, clientIvcProofBuffer] = await Promise.all(
|
|
14
|
+
['client_ivc_vk', 'client_ivc_proof'].map(fileName => fs.readFile(join(directory, fileName))),
|
|
15
|
+
);
|
|
16
|
+
return new ClientIvcProof(clientIvcProofBuffer, clientIvcVkBuffer);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* TODO(#7371): eventually remove client_ivc_prove_output_all_msgpack and properly handle these accumulators and VKs
|
|
21
|
+
* Serialize a ClientIvcProof to the files expected by prove_tube
|
|
22
|
+
*
|
|
23
|
+
* Example usage:
|
|
24
|
+
* await runInDirectory(bbWorkingDirectory, async (dir: string) => {
|
|
25
|
+
* await privateTx.clientIvcProof!.writeToOutputDirectory(bbWorkingDirectory);
|
|
26
|
+
* const result = await generateTubeProof(bbPath, dir, logger.info)
|
|
27
|
+
* expect(result.status).toBe(BB_RESULT.SUCCESS)
|
|
28
|
+
* });
|
|
29
|
+
* @param proof the ClientIvcProof from readFromOutputDirectory
|
|
30
|
+
* @param directory the directory of results
|
|
31
|
+
*/
|
|
32
|
+
export async function writeToOutputDirectory(clientIvcProof: ClientIvcProof, directory: string) {
|
|
33
|
+
const { clientIvcProofBuffer, clientIvcVkBuffer } = clientIvcProof;
|
|
34
|
+
const fileData = [
|
|
35
|
+
['client_ivc_proof', clientIvcProofBuffer],
|
|
36
|
+
['client_ivc_vk', clientIvcVkBuffer],
|
|
37
|
+
] as const;
|
|
38
|
+
await Promise.all(fileData.map(([fileName, buffer]) => fs.writeFile(join(directory, fileName), buffer)));
|
|
39
|
+
}
|
package/src/prover/index.ts
CHANGED
|
@@ -9,32 +9,34 @@ import {
|
|
|
9
9
|
AVM_PROOF_LENGTH_IN_FIELDS,
|
|
10
10
|
AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS,
|
|
11
11
|
type AvmCircuitInputs,
|
|
12
|
-
type BaseOrMergeRollupPublicInputs,
|
|
13
12
|
type BaseParityInputs,
|
|
14
|
-
type BlockMergeRollupInputs,
|
|
15
|
-
type BlockRootOrBlockMergePublicInputs,
|
|
16
|
-
type BlockRootRollupInputs,
|
|
17
|
-
type EmptyBlockRootRollupInputs,
|
|
18
13
|
EmptyNestedData,
|
|
19
14
|
type KernelCircuitPublicInputs,
|
|
20
|
-
type MergeRollupInputs,
|
|
21
15
|
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
22
16
|
type ParityPublicInputs,
|
|
23
|
-
type PrivateBaseRollupInputs,
|
|
24
17
|
type PrivateKernelEmptyInputData,
|
|
25
18
|
PrivateKernelEmptyInputs,
|
|
26
19
|
type Proof,
|
|
27
|
-
type PublicBaseRollupInputs,
|
|
28
20
|
RECURSIVE_PROOF_LENGTH,
|
|
29
21
|
type RootParityInputs,
|
|
30
|
-
type RootRollupInputs,
|
|
31
|
-
type RootRollupPublicInputs,
|
|
32
22
|
TUBE_PROOF_LENGTH,
|
|
33
|
-
type TubeInputs,
|
|
34
23
|
VerificationKeyData,
|
|
35
24
|
makeEmptyRecursiveProof,
|
|
36
25
|
makeRecursiveProof,
|
|
37
26
|
} from '@aztec/circuits.js';
|
|
27
|
+
import {
|
|
28
|
+
type BaseOrMergeRollupPublicInputs,
|
|
29
|
+
type BlockMergeRollupInputs,
|
|
30
|
+
type BlockRootOrBlockMergePublicInputs,
|
|
31
|
+
type BlockRootRollupInputs,
|
|
32
|
+
type EmptyBlockRootRollupInputs,
|
|
33
|
+
type MergeRollupInputs,
|
|
34
|
+
type PrivateBaseRollupInputs,
|
|
35
|
+
type PublicBaseRollupInputs,
|
|
36
|
+
type RootRollupInputs,
|
|
37
|
+
type RootRollupPublicInputs,
|
|
38
|
+
type TubeInputs,
|
|
39
|
+
} from '@aztec/circuits.js/rollup';
|
|
38
40
|
import { createLogger } from '@aztec/foundation/log';
|
|
39
41
|
import { sleep } from '@aztec/foundation/sleep';
|
|
40
42
|
import { Timer } from '@aztec/foundation/timer';
|
|
@@ -46,8 +48,6 @@ import {
|
|
|
46
48
|
convertBaseParityOutputsFromWitnessMap,
|
|
47
49
|
convertBlockMergeRollupInputsToWitnessMap,
|
|
48
50
|
convertBlockMergeRollupOutputsFromWitnessMap,
|
|
49
|
-
convertBlockRootRollupInputsToWitnessMap,
|
|
50
|
-
convertBlockRootRollupOutputsFromWitnessMap,
|
|
51
51
|
convertEmptyBlockRootRollupInputsToWitnessMap,
|
|
52
52
|
convertEmptyBlockRootRollupOutputsFromWitnessMap,
|
|
53
53
|
convertMergeRollupInputsToWitnessMap,
|
|
@@ -57,13 +57,15 @@ import {
|
|
|
57
57
|
convertRootParityOutputsFromWitnessMap,
|
|
58
58
|
convertRootRollupInputsToWitnessMap,
|
|
59
59
|
convertRootRollupOutputsFromWitnessMap,
|
|
60
|
+
convertSimulatedBlockRootRollupInputsToWitnessMap,
|
|
61
|
+
convertSimulatedBlockRootRollupOutputsFromWitnessMap,
|
|
60
62
|
convertSimulatedPrivateBaseRollupInputsToWitnessMap,
|
|
61
63
|
convertSimulatedPrivateBaseRollupOutputsFromWitnessMap,
|
|
62
64
|
convertSimulatedPrivateKernelEmptyOutputsFromWitnessMap,
|
|
63
65
|
convertSimulatedPublicBaseRollupInputsToWitnessMap,
|
|
64
66
|
convertSimulatedPublicBaseRollupOutputsFromWitnessMap,
|
|
65
67
|
} from '@aztec/noir-protocol-circuits-types';
|
|
66
|
-
import { type SimulationProvider,
|
|
68
|
+
import { type SimulationProvider, WASMSimulatorWithBlobs, emitCircuitSimulationStats } from '@aztec/simulator';
|
|
67
69
|
import { type TelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
68
70
|
|
|
69
71
|
import { type WitnessMap } from '@noir-lang/types';
|
|
@@ -76,7 +78,7 @@ import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
|
|
|
76
78
|
* Simulates circuits using the most efficient method and performs no proving.
|
|
77
79
|
*/
|
|
78
80
|
export class TestCircuitProver implements ServerCircuitProver {
|
|
79
|
-
private wasmSimulator = new
|
|
81
|
+
private wasmSimulator = new WASMSimulatorWithBlobs();
|
|
80
82
|
private instrumentation: ProverInstrumentation;
|
|
81
83
|
private logger = createLogger('bb-prover:test-prover');
|
|
82
84
|
|
|
@@ -215,8 +217,8 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
215
217
|
input,
|
|
216
218
|
'BlockRootRollupArtifact',
|
|
217
219
|
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
218
|
-
|
|
219
|
-
|
|
220
|
+
convertSimulatedBlockRootRollupInputsToWitnessMap,
|
|
221
|
+
convertSimulatedBlockRootRollupOutputsFromWitnessMap,
|
|
220
222
|
);
|
|
221
223
|
}
|
|
222
224
|
|
|
@@ -313,7 +315,12 @@ export class TestCircuitProver implements ServerCircuitProver {
|
|
|
313
315
|
const witnessMap = convertInput(input);
|
|
314
316
|
const circuitName = mapProtocolArtifactNameToCircuitName(artifactName);
|
|
315
317
|
|
|
316
|
-
|
|
318
|
+
let simulationProvider = this.simulationProvider ?? this.wasmSimulator;
|
|
319
|
+
if (artifactName == 'BlockRootRollupArtifact') {
|
|
320
|
+
// TODO(#10323): temporarily force block root to use wasm while we simulate
|
|
321
|
+
// the blob operations with an oracle. Appears to be no way to provide nativeACVM with a foreign call hander.
|
|
322
|
+
simulationProvider = this.wasmSimulator;
|
|
323
|
+
}
|
|
317
324
|
const witness = await simulationProvider.simulateCircuit(witnessMap, SimulatedServerCircuitArtifacts[artifactName]);
|
|
318
325
|
|
|
319
326
|
const result = convertOutput(witness);
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
} from '../bb/execute.js';
|
|
24
24
|
import { type BBConfig } from '../config.js';
|
|
25
25
|
import { type UltraKeccakHonkProtocolArtifact, getUltraHonkFlavorForCircuit } from '../honk.js';
|
|
26
|
+
import { writeToOutputDirectory } from '../prover/client_ivc_proof_utils.js';
|
|
26
27
|
import { isProtocolArtifactRecursive, mapProtocolArtifactNameToCircuitName } from '../stats.js';
|
|
27
28
|
import { extractVkData } from '../verification_key/verification_key_data.js';
|
|
28
29
|
|
|
@@ -162,7 +163,7 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
|
|
|
162
163
|
this.logger.debug(`${circuit} BB out - ${message}`);
|
|
163
164
|
};
|
|
164
165
|
|
|
165
|
-
await tx.clientIvcProof
|
|
166
|
+
await writeToOutputDirectory(tx.clientIvcProof, bbWorkingDirectory);
|
|
166
167
|
const result = await verifyClientIvcProof(this.config.bbBinaryPath, bbWorkingDirectory, logFunction);
|
|
167
168
|
|
|
168
169
|
if (result.status === BB_RESULT.FAILURE) {
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { AztecClientBackend } from '@aztec/bb.js';
|
|
2
|
+
import { type PrivateKernelProver, type PrivateKernelSimulateOutput } from '@aztec/circuit-types';
|
|
3
|
+
import {
|
|
4
|
+
ClientIvcProof,
|
|
5
|
+
type PrivateKernelCircuitPublicInputs,
|
|
6
|
+
type PrivateKernelInitCircuitPrivateInputs,
|
|
7
|
+
type PrivateKernelInnerCircuitPrivateInputs,
|
|
8
|
+
type PrivateKernelResetCircuitPrivateInputs,
|
|
9
|
+
type PrivateKernelTailCircuitPrivateInputs,
|
|
10
|
+
type PrivateKernelTailCircuitPublicInputs,
|
|
11
|
+
} from '@aztec/circuits.js';
|
|
12
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
13
|
+
import { Timer } from '@aztec/foundation/timer';
|
|
14
|
+
import {
|
|
15
|
+
ClientCircuitArtifacts,
|
|
16
|
+
ClientCircuitVks,
|
|
17
|
+
type ClientProtocolArtifact,
|
|
18
|
+
convertPrivateKernelInitInputsToWitnessMap,
|
|
19
|
+
convertPrivateKernelInitOutputsFromWitnessMap,
|
|
20
|
+
convertPrivateKernelInnerInputsToWitnessMap,
|
|
21
|
+
convertPrivateKernelInnerOutputsFromWitnessMap,
|
|
22
|
+
convertPrivateKernelResetInputsToWitnessMap,
|
|
23
|
+
convertPrivateKernelResetOutputsFromWitnessMap,
|
|
24
|
+
convertPrivateKernelTailForPublicOutputsFromWitnessMap,
|
|
25
|
+
convertPrivateKernelTailInputsToWitnessMap,
|
|
26
|
+
convertPrivateKernelTailOutputsFromWitnessMap,
|
|
27
|
+
convertPrivateKernelTailToPublicInputsToWitnessMap,
|
|
28
|
+
getPrivateKernelResetArtifactName,
|
|
29
|
+
} from '@aztec/noir-protocol-circuits-types/client';
|
|
30
|
+
import { WASMSimulator } from '@aztec/simulator/client';
|
|
31
|
+
import { type NoirCompiledCircuit } from '@aztec/types/noir';
|
|
32
|
+
|
|
33
|
+
import { type WitnessMap } from '@noir-lang/noir_js';
|
|
34
|
+
import { serializeWitness } from '@noir-lang/noirc_abi';
|
|
35
|
+
import { ungzip } from 'pako';
|
|
36
|
+
|
|
37
|
+
export class BBWasmPrivateKernelProver implements PrivateKernelProver {
|
|
38
|
+
private simulator = new WASMSimulator();
|
|
39
|
+
|
|
40
|
+
constructor(private threads: number = 1, private log = createLogger('bb-prover:wasm')) {}
|
|
41
|
+
|
|
42
|
+
public async simulateProofInit(
|
|
43
|
+
inputs: PrivateKernelInitCircuitPrivateInputs,
|
|
44
|
+
): Promise<PrivateKernelSimulateOutput<PrivateKernelCircuitPublicInputs>> {
|
|
45
|
+
return await this.simulate(
|
|
46
|
+
inputs,
|
|
47
|
+
'PrivateKernelInitArtifact',
|
|
48
|
+
convertPrivateKernelInitInputsToWitnessMap,
|
|
49
|
+
convertPrivateKernelInitOutputsFromWitnessMap,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public async simulateProofInner(
|
|
54
|
+
inputs: PrivateKernelInnerCircuitPrivateInputs,
|
|
55
|
+
): Promise<PrivateKernelSimulateOutput<PrivateKernelCircuitPublicInputs>> {
|
|
56
|
+
return await this.simulate(
|
|
57
|
+
inputs,
|
|
58
|
+
'PrivateKernelInnerArtifact',
|
|
59
|
+
convertPrivateKernelInnerInputsToWitnessMap,
|
|
60
|
+
convertPrivateKernelInnerOutputsFromWitnessMap,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public async simulateProofReset(
|
|
65
|
+
inputs: PrivateKernelResetCircuitPrivateInputs,
|
|
66
|
+
): Promise<PrivateKernelSimulateOutput<PrivateKernelCircuitPublicInputs>> {
|
|
67
|
+
const variantInputs = inputs.trimToSizes();
|
|
68
|
+
const artifactName = getPrivateKernelResetArtifactName(inputs.dimensions);
|
|
69
|
+
return await this.simulate(
|
|
70
|
+
variantInputs,
|
|
71
|
+
artifactName,
|
|
72
|
+
variantInputs => convertPrivateKernelResetInputsToWitnessMap(variantInputs, artifactName),
|
|
73
|
+
output => convertPrivateKernelResetOutputsFromWitnessMap(output, artifactName),
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public async simulateProofTail(
|
|
78
|
+
inputs: PrivateKernelTailCircuitPrivateInputs,
|
|
79
|
+
): Promise<PrivateKernelSimulateOutput<PrivateKernelTailCircuitPublicInputs>> {
|
|
80
|
+
if (!inputs.isForPublic()) {
|
|
81
|
+
return await this.simulate(
|
|
82
|
+
inputs,
|
|
83
|
+
'PrivateKernelTailArtifact',
|
|
84
|
+
convertPrivateKernelTailInputsToWitnessMap,
|
|
85
|
+
convertPrivateKernelTailOutputsFromWitnessMap,
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
return await this.simulate(
|
|
89
|
+
inputs,
|
|
90
|
+
'PrivateKernelTailToPublicArtifact',
|
|
91
|
+
convertPrivateKernelTailToPublicInputsToWitnessMap,
|
|
92
|
+
convertPrivateKernelTailForPublicOutputsFromWitnessMap,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private async simulate<
|
|
97
|
+
I extends { toBuffer: () => Buffer },
|
|
98
|
+
O extends PrivateKernelCircuitPublicInputs | PrivateKernelTailCircuitPublicInputs,
|
|
99
|
+
>(
|
|
100
|
+
inputs: I,
|
|
101
|
+
circuitType: ClientProtocolArtifact,
|
|
102
|
+
convertInputs: (inputs: I) => WitnessMap,
|
|
103
|
+
convertOutputs: (outputs: WitnessMap) => O,
|
|
104
|
+
): Promise<PrivateKernelSimulateOutput<O>> {
|
|
105
|
+
this.log.debug(`Generating witness for ${circuitType}`);
|
|
106
|
+
const compiledCircuit: NoirCompiledCircuit = ClientCircuitArtifacts[circuitType];
|
|
107
|
+
|
|
108
|
+
const witnessMap = convertInputs(inputs);
|
|
109
|
+
const timer = new Timer();
|
|
110
|
+
const outputWitness = await this.simulator.simulateCircuit(witnessMap, compiledCircuit);
|
|
111
|
+
const output = convertOutputs(outputWitness);
|
|
112
|
+
|
|
113
|
+
this.log.debug(`Generated witness for ${circuitType}`, {
|
|
114
|
+
eventName: 'circuit-witness-generation',
|
|
115
|
+
circuitName: circuitType,
|
|
116
|
+
duration: timer.ms(),
|
|
117
|
+
inputSize: inputs.toBuffer().length,
|
|
118
|
+
outputSize: output.toBuffer().length,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const verificationKey = ClientCircuitVks[circuitType].keyAsFields;
|
|
122
|
+
const bytecode = Buffer.from(compiledCircuit.bytecode, 'base64');
|
|
123
|
+
|
|
124
|
+
const kernelOutput: PrivateKernelSimulateOutput<O> = {
|
|
125
|
+
publicInputs: output,
|
|
126
|
+
verificationKey,
|
|
127
|
+
outputWitness,
|
|
128
|
+
bytecode,
|
|
129
|
+
};
|
|
130
|
+
return kernelOutput;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async createClientIvcProof(acirs: Buffer[], witnessStack: WitnessMap[]): Promise<ClientIvcProof> {
|
|
134
|
+
const timer = new Timer();
|
|
135
|
+
this.log.info(`Generating ClientIVC proof...`);
|
|
136
|
+
const backend = new AztecClientBackend(
|
|
137
|
+
acirs.map(acir => ungzip(acir)),
|
|
138
|
+
{ threads: this.threads },
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
const [proof, vk] = await backend.prove(witnessStack.map(witnessMap => ungzip(serializeWitness(witnessMap))));
|
|
142
|
+
await backend.destroy();
|
|
143
|
+
this.log.info(`Generated ClientIVC proof`, {
|
|
144
|
+
eventName: 'client-ivc-proof-generation',
|
|
145
|
+
duration: timer.ms(),
|
|
146
|
+
proofSize: proof.length,
|
|
147
|
+
vkSize: vk.length,
|
|
148
|
+
});
|
|
149
|
+
return new ClientIvcProof(Buffer.from(proof), Buffer.from(vk));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
computeGateCountForCircuit(_bytecode: Buffer, _circuitName: string): Promise<number> {
|
|
153
|
+
return Promise.resolve(0);
|
|
154
|
+
}
|
|
155
|
+
}
|