@aztec/bb-prover 0.48.0 → 0.50.1

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
@@ -811,7 +811,7 @@ export async function generateContractForVerificationKey(
811
811
  try {
812
812
  const args = ['-k', vkFilePath, '-o', contractPath, '-v'];
813
813
  const timer = new Timer();
814
- const result = await executeBB(pathToBB, 'contract', args, log);
814
+ const result = await executeBB(pathToBB, 'contract_ultra_honk', args, log);
815
815
  const duration = timer.ms();
816
816
  if (result.status == BB_RESULT.SUCCESS) {
817
817
  return { status: BB_RESULT.SUCCESS, durationMs: duration, contractPath };
package/src/config.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export interface BBConfig {
2
2
  bbBinaryPath: string;
3
3
  bbWorkingDirectory: string;
4
+ /** Whether to skip tmp dir cleanup for debugging purposes */
5
+ bbSkipCleanup?: boolean;
4
6
  }
5
7
 
6
8
  export interface ACVMConfig {
package/src/index.ts CHANGED
@@ -2,3 +2,4 @@ export * from './prover/index.js';
2
2
  export * from './test/index.js';
3
3
  export * from './verifier/index.js';
4
4
  export * from './config.js';
5
+ export * from './bb/execute.js';
@@ -22,7 +22,7 @@ import {
22
22
  } from '@aztec/circuits.js';
23
23
  import { siloNoteHash } from '@aztec/circuits.js/hash';
24
24
  import { runInDirectory } from '@aztec/foundation/fs';
25
- import { createDebugLogger } from '@aztec/foundation/log';
25
+ import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
26
26
  import { Timer } from '@aztec/foundation/timer';
27
27
  import {
28
28
  ClientCircuitArtifacts,
@@ -57,6 +57,7 @@ import {
57
57
  executeBbClientIvcProof,
58
58
  verifyProof,
59
59
  } from '../bb/execute.js';
60
+ import { type BBConfig } from '../config.js';
60
61
  import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
61
62
  import { extractVkData } from '../verification_key/verification_key_data.js';
62
63
 
@@ -73,12 +74,18 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
73
74
  Promise<VerificationKeyData>
74
75
  >();
75
76
 
76
- constructor(
77
+ private constructor(
77
78
  private bbBinaryPath: string,
78
79
  private bbWorkingDirectory: string,
80
+ private skipCleanup: boolean,
79
81
  private log = createDebugLogger('aztec:bb-native-prover'),
80
82
  ) {}
81
83
 
84
+ public static async new(config: BBConfig, log?: DebugLogger) {
85
+ await fs.mkdir(config.bbWorkingDirectory, { recursive: true });
86
+ return new BBNativePrivateKernelProver(config.bbBinaryPath, config.bbWorkingDirectory, !!config.bbSkipCleanup, log);
87
+ }
88
+
82
89
  private async _createClientIvcProof(
83
90
  directory: string,
84
91
  acirs: Buffer[],
@@ -119,7 +126,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
119
126
  const operation = async (directory: string) => {
120
127
  return await this._createClientIvcProof(directory, acirs, witnessStack);
121
128
  };
122
- return await runInDirectory(this.bbWorkingDirectory, operation);
129
+ return await this.runInDirectory(operation);
123
130
  }
124
131
 
125
132
  public getSiloedCommitments(publicInputs: PrivateCircuitPublicInputs) {
@@ -189,7 +196,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
189
196
  return await this.computeVerificationKey(directory, bytecode, 'App', appCircuitName);
190
197
  };
191
198
 
192
- return await runInDirectory(this.bbWorkingDirectory, operation);
199
+ return await this.runInDirectory(operation);
193
200
  }
194
201
 
195
202
  /**
@@ -229,7 +236,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
229
236
  await fs.writeFile(verificationKeyPath, verificationKey);
230
237
  return await verifyProof(this.bbBinaryPath, proofFileName, verificationKeyPath!, logFunction);
231
238
  };
232
- return await runInDirectory(this.bbWorkingDirectory, operation);
239
+ return await this.runInDirectory(operation);
233
240
  }
234
241
 
235
242
  /**
@@ -270,7 +277,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
270
277
  } satisfies CircuitWitnessGenerationStats);
271
278
 
272
279
  // TODO(#7410) we dont need to generate vk's for these circuits, they are in the vk tree
273
- const { verificationKey } = await runInDirectory(this.bbWorkingDirectory, dir =>
280
+ const { verificationKey } = await this.runInDirectory(dir =>
274
281
  this.computeVerificationKey(dir, Buffer.from(compiledCircuit.bytecode, 'base64'), circuitType),
275
282
  );
276
283
  const kernelOutput: PrivateKernelSimulateOutput<O> = {
@@ -352,7 +359,6 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
352
359
  const json = JSON.parse(proofString);
353
360
  const fields = json.map(Fr.fromString);
354
361
  const numPublicInputs = vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
355
-
356
362
  const fieldsWithoutPublicInputs = fields.slice(numPublicInputs);
357
363
  this.log.info(
358
364
  `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}`,
@@ -364,4 +370,17 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
364
370
  );
365
371
  return proof;
366
372
  }
373
+
374
+ private runInDirectory<T>(fn: (dir: string) => Promise<T>) {
375
+ const log = this.log;
376
+ return runInDirectory(
377
+ this.bbWorkingDirectory,
378
+ (dir: string) =>
379
+ fn(dir).catch(err => {
380
+ log.error(`Error running operation at ${dir}: ${err}`);
381
+ throw err;
382
+ }),
383
+ this.skipCleanup,
384
+ );
385
+ }
367
386
  }
@@ -14,6 +14,9 @@ import {
14
14
  type BaseOrMergeRollupPublicInputs,
15
15
  type BaseParityInputs,
16
16
  type BaseRollupInputs,
17
+ type BlockMergeRollupInputs,
18
+ type BlockRootOrBlockMergePublicInputs,
19
+ type BlockRootRollupInputs,
17
20
  EmptyNestedCircuitInputs,
18
21
  EmptyNestedData,
19
22
  Fr,
@@ -47,6 +50,10 @@ import {
47
50
  convertBaseParityOutputsFromWitnessMap,
48
51
  convertBaseRollupInputsToWitnessMap,
49
52
  convertBaseRollupOutputsFromWitnessMap,
53
+ convertBlockMergeRollupInputsToWitnessMap,
54
+ convertBlockMergeRollupOutputsFromWitnessMap,
55
+ convertBlockRootRollupInputsToWitnessMap,
56
+ convertBlockRootRollupOutputsFromWitnessMap,
50
57
  convertMergeRollupInputsToWitnessMap,
51
58
  convertMergeRollupOutputsFromWitnessMap,
52
59
  convertPrivateKernelEmptyInputsToWitnessMap,
@@ -324,6 +331,55 @@ export class BBNativeRollupProver implements ServerCircuitProver {
324
331
  return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
325
332
  }
326
333
 
334
+ /**
335
+ * Simulates the block root rollup circuit from its inputs.
336
+ * @param input - Inputs to the circuit.
337
+ * @returns The public inputs as outputs of the simulation.
338
+ */
339
+ public async getBlockRootRollupProof(
340
+ input: BlockRootRollupInputs,
341
+ ): Promise<PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>> {
342
+ // TODO(#7346): When batch rollups are integrated, we probably want the below to be this.createRecursiveProof
343
+ // since we will no longer be verifying it directly on L1
344
+ const { circuitOutput, proof } = await this.createProof(
345
+ input,
346
+ 'BlockRootRollupArtifact',
347
+ convertBlockRootRollupInputsToWitnessMap,
348
+ convertBlockRootRollupOutputsFromWitnessMap,
349
+ );
350
+
351
+ const recursiveProof = makeRecursiveProofFromBinary(proof, NESTED_RECURSIVE_PROOF_LENGTH);
352
+
353
+ const verificationKey = await this.getVerificationKeyDataForCircuit('BlockRootRollupArtifact');
354
+
355
+ await this.verifyProof('BlockRootRollupArtifact', proof);
356
+
357
+ return makePublicInputsAndRecursiveProof(circuitOutput, recursiveProof, verificationKey);
358
+ }
359
+
360
+ /**
361
+ * Simulates the block merge rollup circuit from its inputs.
362
+ * @param input - Inputs to the circuit.
363
+ * @returns The public inputs as outputs of the simulation.
364
+ */
365
+ public async getBlockMergeRollupProof(
366
+ input: BlockMergeRollupInputs,
367
+ ): Promise<PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>> {
368
+ const { circuitOutput, proof } = await this.createRecursiveProof(
369
+ input,
370
+ 'BlockMergeRollupArtifact',
371
+ NESTED_RECURSIVE_PROOF_LENGTH,
372
+ convertBlockMergeRollupInputsToWitnessMap,
373
+ convertBlockMergeRollupOutputsFromWitnessMap,
374
+ );
375
+
376
+ const verificationKey = await this.getVerificationKeyDataForCircuit('BlockMergeRollupArtifact');
377
+
378
+ await this.verifyProof('BlockMergeRollupArtifact', proof.binaryProof);
379
+
380
+ return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
381
+ }
382
+
327
383
  /**
328
384
  * Simulates the root rollup circuit from its inputs.
329
385
  * @param input - Inputs to the circuit.
@@ -538,7 +594,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
538
594
 
539
595
  return { circuitOutput: output, proof };
540
596
  };
541
- return await runInDirectory(this.config.bbWorkingDirectory, operation);
597
+ return await this.runInDirectory(operation);
542
598
  }
543
599
 
544
600
  private async generateAvmProofWithBB(input: AvmCircuitInputs, workingDirectory: string): Promise<BBSuccess> {
@@ -571,11 +627,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
571
627
  }
572
628
 
573
629
  private async createAvmProof(input: AvmCircuitInputs): Promise<ProofAndVerificationKey> {
574
- const cleanupDir: boolean = !process.env.AVM_PROVING_PRESERVE_WORKING_DIR;
575
630
  const operation = async (bbWorkingDirectory: string): Promise<ProofAndVerificationKey> => {
576
- if (!cleanupDir) {
577
- logger.info(`Preserving working directory ${bbWorkingDirectory}`);
578
- }
579
631
  const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory);
580
632
 
581
633
  const rawProof = await fs.readFile(provingResult.proofPath!);
@@ -608,7 +660,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
608
660
 
609
661
  return { proof, verificationKey };
610
662
  };
611
- return await runInDirectory(this.config.bbWorkingDirectory, operation, cleanupDir);
663
+ return await this.runInDirectory(operation);
612
664
  }
613
665
 
614
666
  public async getTubeProof(
@@ -640,7 +692,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
640
692
 
641
693
  return { tubeVK, tubeProof };
642
694
  };
643
- return await runInDirectory(this.config.bbWorkingDirectory, operation);
695
+ return await this.runInDirectory(operation);
644
696
  }
645
697
 
646
698
  /**
@@ -699,7 +751,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
699
751
  proof,
700
752
  };
701
753
  };
702
- return await runInDirectory(this.config.bbWorkingDirectory, operation);
754
+ return await this.runInDirectory(operation);
703
755
  }
704
756
 
705
757
  /**
@@ -752,7 +804,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
752
804
  logger.info(`Successfully verified proof from key in ${result.durationMs} ms`);
753
805
  };
754
806
 
755
- await runInDirectory(this.config.bbWorkingDirectory, operation);
807
+ await this.runInDirectory(operation);
756
808
  }
757
809
 
758
810
  /**
@@ -824,7 +876,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
824
876
  true,
825
877
  );
826
878
  };
827
- return await runInDirectory(this.config.bbWorkingDirectory, operation);
879
+ return await this.runInDirectory(operation);
828
880
  }
829
881
 
830
882
  /**
@@ -895,7 +947,6 @@ export class BBNativeRollupProver implements ServerCircuitProver {
895
947
  throw new Error(`Invalid verification key for ${circuitType}`);
896
948
  }
897
949
  const numPublicInputs = vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
898
-
899
950
  const fieldsWithoutPublicInputs = json
900
951
  .slice(0, 3)
901
952
  .map(Fr.fromString)
@@ -959,4 +1010,16 @@ export class BBNativeRollupProver implements ServerCircuitProver {
959
1010
 
960
1011
  return proof;
961
1012
  }
1013
+
1014
+ private runInDirectory<T>(fn: (dir: string) => Promise<T>) {
1015
+ return runInDirectory(
1016
+ this.config.bbWorkingDirectory,
1017
+ (dir: string) =>
1018
+ fn(dir).catch(err => {
1019
+ logger.error(`Error running operation at ${dir}: ${err}`);
1020
+ throw err;
1021
+ }),
1022
+ this.config.bbSkipCleanup,
1023
+ );
1024
+ }
962
1025
  }
package/src/stats.ts CHANGED
@@ -15,6 +15,10 @@ export function mapProtocolArtifactNameToCircuitName(
15
15
  return 'base-rollup';
16
16
  case 'MergeRollupArtifact':
17
17
  return 'merge-rollup';
18
+ case 'BlockRootRollupArtifact':
19
+ return 'block-root-rollup';
20
+ case 'BlockMergeRollupArtifact':
21
+ return 'block-merge-rollup';
18
22
  case 'RootRollupArtifact':
19
23
  return 'root-rollup';
20
24
  case 'PublicKernelSetupArtifact':
@@ -35,6 +39,8 @@ export function mapProtocolArtifactNameToCircuitName(
35
39
  return 'private-kernel-tail-to-public';
36
40
  case 'PrivateKernelResetFullArtifact':
37
41
  return 'private-kernel-reset-full';
42
+ case 'PrivateKernelResetFullInnerArtifact':
43
+ return 'private-kernel-reset-full-inner';
38
44
  case 'PrivateKernelResetBigArtifact':
39
45
  return 'private-kernel-reset-big';
40
46
  case 'PrivateKernelResetMediumArtifact':
@@ -11,6 +11,9 @@ import {
11
11
  type BaseOrMergeRollupPublicInputs,
12
12
  type BaseParityInputs,
13
13
  type BaseRollupInputs,
14
+ type BlockMergeRollupInputs,
15
+ type BlockRootOrBlockMergePublicInputs,
16
+ type BlockRootRollupInputs,
14
17
  EmptyNestedData,
15
18
  type KernelCircuitPublicInputs,
16
19
  type MergeRollupInputs,
@@ -42,6 +45,10 @@ import {
42
45
  SimulatedServerCircuitArtifacts,
43
46
  convertBaseParityInputsToWitnessMap,
44
47
  convertBaseParityOutputsFromWitnessMap,
48
+ convertBlockMergeRollupInputsToWitnessMap,
49
+ convertBlockMergeRollupOutputsFromWitnessMap,
50
+ convertBlockRootRollupInputsToWitnessMap,
51
+ convertBlockRootRollupOutputsFromWitnessMap,
45
52
  convertMergeRollupInputsToWitnessMap,
46
53
  convertMergeRollupOutputsFromWitnessMap,
47
54
  convertPrivateKernelEmptyInputsToWitnessMap,
@@ -65,8 +72,8 @@ import { SimulatedPublicKernelArtifactMapping } from '../mappings/mappings.js';
65
72
  import { mapPublicKernelToCircuitName } from '../stats.js';
66
73
 
67
74
  /**
68
- * A class for use in testing situations (e2e, unit test etc)
69
- * Simulates circuits using the most efficient method and performs no proving
75
+ * A class for use in testing situations (e2e, unit test, etc) and temporarily for assembling a block in the sequencer.
76
+ * Simulates circuits using the most efficient method and performs no proving.
70
77
  */
71
78
  export class TestCircuitProver implements ServerCircuitProver {
72
79
  private wasmSimulator = new WASMSimulator();
@@ -299,6 +306,76 @@ export class TestCircuitProver implements ServerCircuitProver {
299
306
  );
300
307
  }
301
308
 
309
+ /**
310
+ * Simulates the block root rollup circuit from its inputs.
311
+ * @param input - Inputs to the circuit.
312
+ * @returns The public inputs as outputs of the simulation.
313
+ */
314
+ @trackSpan('TestCircuitProver.getBlockRootRollupProof')
315
+ public async getBlockRootRollupProof(
316
+ input: BlockRootRollupInputs,
317
+ ): Promise<PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>> {
318
+ const timer = new Timer();
319
+ const witnessMap = convertBlockRootRollupInputsToWitnessMap(input);
320
+
321
+ // use WASM here as it is faster for small circuits
322
+ const witness = await this.wasmSimulator.simulateCircuit(
323
+ witnessMap,
324
+ SimulatedServerCircuitArtifacts.BlockRootRollupArtifact,
325
+ );
326
+
327
+ const result = convertBlockRootRollupOutputsFromWitnessMap(witness);
328
+
329
+ this.instrumentation.recordDuration('simulationDuration', 'block-root-rollup', timer);
330
+ emitCircuitSimulationStats(
331
+ 'block-root-rollup',
332
+ timer.ms(),
333
+ input.toBuffer().length,
334
+ result.toBuffer().length,
335
+ this.logger,
336
+ );
337
+ return makePublicInputsAndRecursiveProof(
338
+ result,
339
+ makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH),
340
+ ProtocolCircuitVks['BlockRootRollupArtifact'],
341
+ );
342
+ }
343
+
344
+ /**
345
+ * Simulates the block merge rollup circuit from its inputs.
346
+ * @param input - Inputs to the circuit.
347
+ * @returns The public inputs as outputs of the simulation.
348
+ */
349
+ @trackSpan('TestCircuitProver.getBlockMergeRollupProof')
350
+ public async getBlockMergeRollupProof(
351
+ input: BlockMergeRollupInputs,
352
+ ): Promise<PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>> {
353
+ const timer = new Timer();
354
+ const witnessMap = convertBlockMergeRollupInputsToWitnessMap(input);
355
+
356
+ // use WASM here as it is faster for small circuits
357
+ const witness = await this.wasmSimulator.simulateCircuit(
358
+ witnessMap,
359
+ SimulatedServerCircuitArtifacts.BlockMergeRollupArtifact,
360
+ );
361
+
362
+ const result = convertBlockMergeRollupOutputsFromWitnessMap(witness);
363
+
364
+ this.instrumentation.recordDuration('simulationDuration', 'block-merge-rollup', timer);
365
+ emitCircuitSimulationStats(
366
+ 'block-merge-rollup',
367
+ timer.ms(),
368
+ input.toBuffer().length,
369
+ result.toBuffer().length,
370
+ this.logger,
371
+ );
372
+ return makePublicInputsAndRecursiveProof(
373
+ result,
374
+ makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH),
375
+ ProtocolCircuitVks['BlockMergeRollupArtifact'],
376
+ );
377
+ }
378
+
302
379
  /**
303
380
  * Simulates the root rollup circuit from its inputs.
304
381
  * @param input - Inputs to the circuit.
@@ -37,6 +37,7 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
37
37
  initialCircuits: ProtocolArtifact[] = [],
38
38
  logger = createDebugLogger('aztec:bb-verifier'),
39
39
  ) {
40
+ await fs.mkdir(config.bbWorkingDirectory, { recursive: true });
40
41
  const keys = new Map<ProtocolArtifact, Promise<VerificationKeyData>>();
41
42
  for (const circuit of initialCircuits) {
42
43
  const vkData = await this.generateVerificationKey(
@@ -116,7 +117,7 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
116
117
  proofType: 'ultra-honk',
117
118
  } satisfies CircuitVerificationStats);
118
119
  };
119
- await runInDirectory(this.config.bbWorkingDirectory, operation);
120
+ await runInDirectory(this.config.bbWorkingDirectory, operation, this.config.bbSkipCleanup);
120
121
  }
121
122
 
122
123
  public async generateSolidityContract(circuit: ProtocolArtifact, contractName: string) {
@@ -168,7 +169,7 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
168
169
  proofType: 'client-ivc',
169
170
  } satisfies CircuitVerificationStats);
170
171
  };
171
- await runInDirectory(this.config.bbWorkingDirectory, operation);
172
+ await runInDirectory(this.config.bbWorkingDirectory, operation, this.config.bbSkipCleanup);
172
173
  return true;
173
174
  } catch (err) {
174
175
  this.logger.warn(`Failed to verify ClientIVC proof for tx ${Tx.getHash(tx)}: ${String(err)}`);