@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/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' ? `gates_mega_honk` : `gates`,
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 AppCircuitSimulateOutput,
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 { WASMSimulator } from '@aztec/simulator';
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 WASMSimulator();
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 ClientIvcProof.readFromOutputDirectory(directory);
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(
@@ -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.writeToOutputDirectory(bbWorkingDirectory);
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
+ }
@@ -1,2 +1,3 @@
1
1
  export * from './bb_prover.js';
2
2
  export * from './bb_private_kernel_prover.js';
3
+ export * from './client_ivc_proof_utils.js';
@@ -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, WASMSimulator, emitCircuitSimulationStats } from '@aztec/simulator';
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 WASMSimulator();
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
- convertBlockRootRollupInputsToWitnessMap,
219
- convertBlockRootRollupOutputsFromWitnessMap,
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
- const simulationProvider = this.simulationProvider ?? this.wasmSimulator;
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.writeToOutputDirectory(bbWorkingDirectory);
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
+ }