@aztec/bb-prover 3.0.0-nightly.20250908 → 3.0.0-nightly.20250911

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.
@@ -1,19 +1,17 @@
1
1
  import { type Logger } from '@aztec/foundation/log';
2
- import type { ServerProtocolArtifact } from '@aztec/noir-protocol-circuits-types/types';
2
+ import type { ProtocolArtifact, ServerProtocolArtifact } from '@aztec/noir-protocol-circuits-types/types';
3
3
  import type { ClientProtocolCircuitVerifier, IVCProofVerificationResult } from '@aztec/stdlib/interfaces/server';
4
4
  import type { Proof } from '@aztec/stdlib/proofs';
5
5
  import { Tx } from '@aztec/stdlib/tx';
6
6
  import type { VerificationKeyData } from '@aztec/stdlib/vks';
7
7
  import type { BBConfig } from '../config.js';
8
- export declare const PRIVATE_TAIL_CIVC_VK: string;
9
- export declare const PUBLIC_TAIL_CIVC_VK: string;
10
8
  export declare class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
11
9
  private config;
12
10
  private logger;
13
11
  private constructor();
14
12
  stop(): Promise<void>;
15
13
  static new(config: BBConfig, logger?: Logger): Promise<BBCircuitVerifier>;
16
- getVerificationKeyData(circuitType: ServerProtocolArtifact): VerificationKeyData;
14
+ getVerificationKeyData(circuit: ProtocolArtifact): VerificationKeyData;
17
15
  verifyProofForCircuit(circuit: ServerProtocolArtifact, proof: Proof): Promise<void>;
18
16
  verifyProof(tx: Tx): Promise<IVCProofVerificationResult>;
19
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bb_verifier.d.ts","sourceRoot":"","sources":["../../src/verifier/bb_verifier.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAGlE,OAAO,KAAK,EAA0B,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AAChH,OAAO,KAAK,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AACjH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAc7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAQ7C,eAAO,MAAM,oBAAoB,QAA0D,CAAC;AAC5F,eAAO,MAAM,mBAAmB,QAAyD,CAAC;AAE1F,qBAAa,iBAAkB,YAAW,6BAA6B;IAEnE,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IAFhB,OAAO;IAKA,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;WAIR,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,SAAqC;IAK9E,sBAAsB,CAAC,WAAW,EAAE,sBAAsB,GAAG,mBAAmB;IAQ1E,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,EAAE,KAAK,EAAE,KAAK;IAqCnE,WAAW,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,0BAA0B,CAAC;CAiDtE"}
1
+ {"version":3,"file":"bb_verifier.d.ts","sourceRoot":"","sources":["../../src/verifier/bb_verifier.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAGlE,OAAO,KAAK,EAEV,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,2CAA2C,CAAC;AACnD,OAAO,KAAK,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AACjH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAa7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAK7C,qBAAa,iBAAkB,YAAW,6BAA6B;IAEnE,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IAFhB,OAAO;IAKA,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;WAIR,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,SAAqC;IAK9E,sBAAsB,CAAC,OAAO,EAAE,gBAAgB,GAAG,mBAAmB;IAQhE,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,EAAE,KAAK,EAAE,KAAK;IAqCnE,WAAW,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,0BAA0B,CAAC;CAkDtE"}
@@ -1,18 +1,13 @@
1
1
  import { runInDirectory } from '@aztec/foundation/fs';
2
2
  import { createLogger } from '@aztec/foundation/log';
3
3
  import { Timer } from '@aztec/foundation/timer';
4
- import { ServerCircuitVks } from '@aztec/noir-protocol-circuits-types/server/vks';
4
+ import { ProtocolCircuitVks } from '@aztec/noir-protocol-circuits-types/server/vks';
5
5
  import { promises as fs } from 'fs';
6
6
  import * as path from 'path';
7
- import { fileURLToPath } from 'url';
8
7
  import { BB_RESULT, PROOF_FILENAME, PUBLIC_INPUTS_FILENAME, VK_FILENAME, verifyClientIvcProof, verifyProof } from '../bb/execute.js';
9
8
  import { getUltraHonkFlavorForCircuit } from '../honk.js';
10
- import { writeClientIVCProofToOutputDirectory } from '../prover/proof_utils.js';
9
+ import { writeClientIVCProofToPath } from '../prover/proof_utils.js';
11
10
  import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
12
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
- // Built by yarn generate
14
- export const PRIVATE_TAIL_CIVC_VK = path.join(__dirname, '../../artifacts/private-civc-vk');
15
- export const PUBLIC_TAIL_CIVC_VK = path.join(__dirname, '../../artifacts/public-civc-vk');
16
11
  export class BBCircuitVerifier {
17
12
  config;
18
13
  logger;
@@ -29,10 +24,10 @@ export class BBCircuitVerifier {
29
24
  });
30
25
  return new BBCircuitVerifier(config, logger);
31
26
  }
32
- getVerificationKeyData(circuitType) {
33
- const vk = ServerCircuitVks[circuitType];
27
+ getVerificationKeyData(circuit) {
28
+ const vk = ProtocolCircuitVks[circuit];
34
29
  if (vk === undefined) {
35
- throw new Error('Could not find VK for server artifact ' + circuitType);
30
+ throw new Error(`Could not find VK for artifact ${circuit}`);
36
31
  }
37
32
  return vk;
38
33
  }
@@ -62,30 +57,30 @@ export class BBCircuitVerifier {
62
57
  await runInDirectory(this.config.bbWorkingDirectory, operation, this.config.bbSkipCleanup, this.logger);
63
58
  }
64
59
  async verifyProof(tx) {
60
+ const proofType = 'ClientIVC';
65
61
  try {
66
62
  const totalTimer = new Timer();
67
63
  let verificationDuration = 0;
68
- // TODO(#7370) The verification keys should be supplied separately and based on the expectedCircuit
69
- // rather than read from the tx object itself. We also need the vks for the translator and ecc, which
70
- // are not being saved along the other vks yet. Reuse the 'verifyProofForCircuit' method above once
71
- // we have all the verification keys available.
72
- const expectedCircuit = tx.data.forPublic ? 'PrivateKernelTailToPublicArtifact' : 'PrivateKernelTailArtifact';
73
- const circuit = 'ClientIVC';
64
+ const circuit = tx.data.forPublic ? 'HidingKernelToPublic' : 'HidingKernelToRollup';
74
65
  // Block below is almost copy-pasted from verifyProofForCircuit
75
66
  const operation = async (bbWorkingDirectory)=>{
76
67
  const logFunction = (message)=>{
77
- this.logger.debug(`${circuit} BB out - ${message}`);
68
+ this.logger.debug(`${proofType} BB out - ${message}`);
78
69
  };
79
- await writeClientIVCProofToOutputDirectory(tx.clientIvcProof, bbWorkingDirectory);
70
+ const proofPath = path.join(bbWorkingDirectory, PROOF_FILENAME);
71
+ await writeClientIVCProofToPath(tx.clientIvcProof, proofPath);
72
+ const verificationKeyPath = path.join(bbWorkingDirectory, VK_FILENAME);
73
+ const verificationKey = this.getVerificationKeyData(circuit);
74
+ await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes);
80
75
  const timer = new Timer();
81
- const result = await verifyClientIvcProof(this.config.bbBinaryPath, bbWorkingDirectory.concat('/proof'), tx.data.forPublic ? PUBLIC_TAIL_CIVC_VK : PRIVATE_TAIL_CIVC_VK, logFunction, this.config.bbIVCConcurrency);
76
+ const result = await verifyClientIvcProof(this.config.bbBinaryPath, proofPath, verificationKeyPath, logFunction, this.config.bbIVCConcurrency);
82
77
  verificationDuration = timer.ms();
83
78
  if (result.status === BB_RESULT.FAILURE) {
84
- const errorMessage = `Failed to verify ${circuit} proof for ${expectedCircuit}!`;
79
+ const errorMessage = `Failed to verify ${proofType} proof for ${circuit}!`;
85
80
  throw new Error(errorMessage);
86
81
  }
87
- this.logger.debug(`${circuit} verification successful`, {
88
- circuitName: mapProtocolArtifactNameToCircuitName(expectedCircuit),
82
+ this.logger.debug(`${proofType} verification successful`, {
83
+ circuitName: mapProtocolArtifactNameToCircuitName(circuit),
89
84
  duration: result.durationMs,
90
85
  eventName: 'circuit-verification',
91
86
  proofType: 'client-ivc'
@@ -98,7 +93,7 @@ export class BBCircuitVerifier {
98
93
  totalDurationMs: totalTimer.ms()
99
94
  };
100
95
  } catch (err) {
101
- this.logger.warn(`Failed to verify ClientIVC proof for tx ${tx.getTxHash().toString()}: ${String(err)}`);
96
+ this.logger.warn(`Failed to verify ${proofType} proof for tx ${tx.getTxHash().toString()}: ${String(err)}`);
102
97
  return {
103
98
  valid: false,
104
99
  durationMs: 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/bb-prover",
3
- "version": "3.0.0-nightly.20250908",
3
+ "version": "3.0.0-nightly.20250911",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -28,7 +28,6 @@
28
28
  "build": "yarn clean && tsc -b",
29
29
  "build:dev": "tsc -b --watch",
30
30
  "clean": "rm -rf ./dest .tsbuildinfo",
31
- "generate": "scripts/copy_ivc_hiding_circuit_vks.sh",
32
31
  "bb": "node --no-warnings ./dest/bb/index.js",
33
32
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
34
33
  },
@@ -70,27 +69,27 @@
70
69
  ]
71
70
  },
72
71
  "dependencies": {
73
- "@aztec/bb.js": "3.0.0-nightly.20250908",
74
- "@aztec/constants": "3.0.0-nightly.20250908",
75
- "@aztec/foundation": "3.0.0-nightly.20250908",
76
- "@aztec/noir-noirc_abi": "3.0.0-nightly.20250908",
77
- "@aztec/noir-protocol-circuits-types": "3.0.0-nightly.20250908",
78
- "@aztec/noir-types": "3.0.0-nightly.20250908",
79
- "@aztec/simulator": "3.0.0-nightly.20250908",
80
- "@aztec/stdlib": "3.0.0-nightly.20250908",
81
- "@aztec/telemetry-client": "3.0.0-nightly.20250908",
82
- "@aztec/world-state": "3.0.0-nightly.20250908",
72
+ "@aztec/bb.js": "3.0.0-nightly.20250911",
73
+ "@aztec/constants": "3.0.0-nightly.20250911",
74
+ "@aztec/foundation": "3.0.0-nightly.20250911",
75
+ "@aztec/noir-noirc_abi": "3.0.0-nightly.20250911",
76
+ "@aztec/noir-protocol-circuits-types": "3.0.0-nightly.20250911",
77
+ "@aztec/noir-types": "3.0.0-nightly.20250911",
78
+ "@aztec/simulator": "3.0.0-nightly.20250911",
79
+ "@aztec/stdlib": "3.0.0-nightly.20250911",
80
+ "@aztec/telemetry-client": "3.0.0-nightly.20250911",
81
+ "@aztec/world-state": "3.0.0-nightly.20250911",
83
82
  "commander": "^12.1.0",
84
83
  "pako": "^2.1.0",
85
84
  "source-map-support": "^0.5.21",
86
85
  "tslib": "^2.4.0"
87
86
  },
88
87
  "devDependencies": {
89
- "@aztec/ethereum": "3.0.0-nightly.20250908",
90
- "@aztec/kv-store": "3.0.0-nightly.20250908",
91
- "@aztec/noir-contracts.js": "3.0.0-nightly.20250908",
92
- "@aztec/noir-test-contracts.js": "3.0.0-nightly.20250908",
93
- "@aztec/protocol-contracts": "3.0.0-nightly.20250908",
88
+ "@aztec/ethereum": "3.0.0-nightly.20250911",
89
+ "@aztec/kv-store": "3.0.0-nightly.20250911",
90
+ "@aztec/noir-contracts.js": "3.0.0-nightly.20250911",
91
+ "@aztec/noir-test-contracts.js": "3.0.0-nightly.20250911",
92
+ "@aztec/protocol-contracts": "3.0.0-nightly.20250911",
94
93
  "@jest/globals": "^30.0.0",
95
94
  "@types/jest": "^30.0.0",
96
95
  "@types/node": "^22.15.17",
package/src/bb/execute.ts CHANGED
@@ -15,7 +15,6 @@ export const PROOF_FILENAME = 'proof';
15
15
  export const AVM_INPUTS_FILENAME = 'avm_inputs.bin';
16
16
  export const AVM_BYTECODE_FILENAME = 'avm_bytecode.bin';
17
17
  export const AVM_PUBLIC_INPUTS_FILENAME = 'avm_public_inputs.bin';
18
- export const CLIENT_IVC_PROOF_FILE_NAME = 'proof';
19
18
 
20
19
  export enum BB_RESULT {
21
20
  SUCCESS,
@@ -214,6 +213,7 @@ export async function generateProof(
214
213
  workingDirectory: string,
215
214
  circuitName: string,
216
215
  bytecode: Buffer,
216
+ verificationKey: Buffer,
217
217
  inputWitnessFile: string,
218
218
  flavor: UltraHonkFlavor,
219
219
  log: Logger,
@@ -227,6 +227,7 @@ export async function generateProof(
227
227
 
228
228
  // The bytecode is written to e.g. /workingDirectory/BaseParityArtifact-bytecode
229
229
  const bytecodePath = `${workingDirectory}/${circuitName}-bytecode`;
230
+ const vkPath = `${workingDirectory}/${circuitName}-vk`;
230
231
 
231
232
  // The proof is written to e.g. /workingDirectory/ultra_honk/proof
232
233
  const outputPath = `${workingDirectory}`;
@@ -240,16 +241,16 @@ export async function generateProof(
240
241
  }
241
242
 
242
243
  try {
243
- // Write the bytecode to the working directory
244
- await fs.writeFile(bytecodePath, bytecode);
245
- // TODO(#15043): Avoid write_vk flag here.
244
+ // Write the bytecode and vk to the working directory
245
+ await Promise.all([fs.writeFile(bytecodePath, bytecode), fs.writeFile(vkPath, verificationKey)]);
246
246
  const args = getArgs(flavor).concat([
247
247
  '--disable_zk',
248
- '--write_vk',
249
248
  '-o',
250
249
  outputPath,
251
250
  '-b',
252
251
  bytecodePath,
252
+ '-k',
253
+ vkPath,
253
254
  '-w',
254
255
  inputWitnessFile,
255
256
  '-v',
@@ -286,74 +287,6 @@ export async function generateProof(
286
287
  }
287
288
  }
288
289
 
289
- /**
290
- * Used for generating proofs of the tube circuit
291
- * It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof.
292
- *
293
- * @returns An object containing a result indication, the location of the proof and the duration taken
294
- */
295
- export async function generateTubeProof(
296
- pathToBB: string,
297
- workingDirectory: string,
298
- vkPath: string,
299
- log: LogFn,
300
- ): Promise<BBFailure | BBSuccess> {
301
- // Check that the working directory exists
302
- try {
303
- await fs.access(workingDirectory);
304
- } catch {
305
- return { status: BB_RESULT.FAILURE, reason: `Working directory ${workingDirectory} does not exist` };
306
- }
307
-
308
- // Paths for the inputs
309
- const proofPath = join(workingDirectory, CLIENT_IVC_PROOF_FILE_NAME);
310
-
311
- // The proof is written to e.g. /workingDirectory/proof
312
- const outputPath = workingDirectory;
313
- const filePresent = async (file: string) =>
314
- await fs
315
- .access(file, fs.constants.R_OK)
316
- .then(_ => true)
317
- .catch(_ => false);
318
-
319
- const binaryPresent = await filePresent(pathToBB);
320
- if (!binaryPresent) {
321
- return { status: BB_RESULT.FAILURE, reason: `Failed to find bb binary at ${pathToBB}` };
322
- }
323
-
324
- try {
325
- if (!(await filePresent(proofPath))) {
326
- return { status: BB_RESULT.FAILURE, reason: `Client IVC input files not present in ${workingDirectory}` };
327
- }
328
- const args = ['-o', outputPath, '-k', vkPath, '-v'];
329
-
330
- const timer = new Timer();
331
- const logFunction = (message: string) => {
332
- log(`TubeCircuit (prove) BB out - ${message}`);
333
- };
334
- const result = await executeBB(pathToBB, 'prove_tube', args, logFunction);
335
- const durationMs = timer.ms();
336
-
337
- if (result.status == BB_RESULT.SUCCESS) {
338
- return {
339
- status: BB_RESULT.SUCCESS,
340
- durationMs,
341
- proofPath: outputPath,
342
- pkPath: undefined,
343
- vkDirectoryPath: outputPath,
344
- };
345
- }
346
- // Not a great error message here but it is difficult to decipher what comes from bb
347
- return {
348
- status: BB_RESULT.FAILURE,
349
- reason: `Failed to generate proof. Exit code ${result.exitCode}. Signal ${result.signal}.`,
350
- retry: !!result.signal,
351
- };
352
- } catch (error) {
353
- return { status: BB_RESULT.FAILURE, reason: `${error}` };
354
- }
355
- }
356
-
357
290
  /**
358
291
  * Used for generating AVM proofs.
359
292
  * It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof.
@@ -86,7 +86,7 @@ export class ProverInstrumentation {
86
86
  */
87
87
  recordDuration(
88
88
  metric: 'simulationDuration' | 'witGenDuration' | 'provingDuration',
89
- circuitName: CircuitName | 'tubeCircuit',
89
+ circuitName: CircuitName,
90
90
  timerOrMS: Timer | number,
91
91
  ) {
92
92
  const s = typeof timerOrMS === 'number' ? timerOrMS / 1000 : timerOrMS.s();
@@ -116,7 +116,7 @@ export class ProverInstrumentation {
116
116
  */
117
117
  recordSize(
118
118
  metric: 'witGenInputSize' | 'witGenOutputSize' | 'proofSize' | 'circuitSize' | 'circuitPublicInputCount',
119
- circuitName: CircuitName | 'tubeCircuit',
119
+ circuitName: CircuitName,
120
120
  size: number,
121
121
  ) {
122
122
  this[metric].record(Math.ceil(size), {
@@ -29,9 +29,7 @@ export abstract class BBWASMPrivateKernelProver extends BBPrivateKernelProver {
29
29
  { threads: this.threads, logger: this.log.verbose, wasmPath: process.env.BB_WASM_PATH },
30
30
  );
31
31
 
32
- // TODO(https://github.com/AztecProtocol/barretenberg/issues/1297): the vk is not provided to the network anymore.
33
- // Move this sanity check inside the wasm code and remove the vk from the return value.
34
- const [proof, _vk] = await backend.prove(
32
+ const [proof] = await backend.prove(
35
33
  executionSteps.map(step => ungzip(serializeWitness(step.witness))),
36
34
  executionSteps.map(step => step.vk),
37
35
  );
@@ -41,7 +39,7 @@ export abstract class BBWASMPrivateKernelProver extends BBPrivateKernelProver {
41
39
  duration: timer.ms(),
42
40
  proofSize: proof.length,
43
41
  });
44
- return new ClientIvcProof(Buffer.from(proof));
42
+ return ClientIvcProof.fromBufferArray(proof);
45
43
  }
46
44
 
47
45
  public override async computeGateCountForCircuit(_bytecode: Buffer, _circuitName: string): Promise<number> {
@@ -1,4 +1,6 @@
1
1
  import {
2
+ CIVC_PROOF_LENGTH,
3
+ HIDING_KERNEL_IO_PUBLIC_INPUTS_SIZE,
2
4
  IPA_CLAIM_SIZE,
3
5
  NESTED_RECURSIVE_PROOF_LENGTH,
4
6
  NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
@@ -14,7 +16,7 @@ import assert from 'assert';
14
16
  import { promises as fs } from 'fs';
15
17
  import * as path from 'path';
16
18
 
17
- import { CLIENT_IVC_PROOF_FILE_NAME, PROOF_FILENAME, PUBLIC_INPUTS_FILENAME } from '../bb/execute.js';
19
+ import { PROOF_FILENAME, PUBLIC_INPUTS_FILENAME } from '../bb/execute.js';
18
20
 
19
21
  /**
20
22
  * Create a ClientIvcProof proof file.
@@ -23,8 +25,10 @@ import { CLIENT_IVC_PROOF_FILE_NAME, PROOF_FILENAME, PUBLIC_INPUTS_FILENAME } fr
23
25
  * @returns the encapsulated client ivc proof
24
26
  */
25
27
  export async function readClientIVCProofFromOutputDirectory(directory: string) {
26
- const clientIvcProofBuffer = await fs.readFile(path.join(directory, CLIENT_IVC_PROOF_FILE_NAME));
27
- return new ClientIvcProof(clientIvcProofBuffer);
28
+ const proofFilename = path.join(directory, PROOF_FILENAME);
29
+ const binaryProof = await fs.readFile(proofFilename);
30
+ const proofFields = splitBufferIntoFields(binaryProof);
31
+ return new ClientIvcProof(proofFields);
28
32
  }
29
33
 
30
34
  /**
@@ -33,9 +37,23 @@ export async function readClientIVCProofFromOutputDirectory(directory: string) {
33
37
  * @param proof the ClientIvcProof from object
34
38
  * @param directory the directory to write in
35
39
  */
36
- export async function writeClientIVCProofToOutputDirectory(clientIvcProof: ClientIvcProof, directory: string) {
37
- const { clientIvcProofBuffer } = clientIvcProof;
38
- await fs.writeFile(path.join(directory, CLIENT_IVC_PROOF_FILE_NAME), clientIvcProofBuffer);
40
+ export async function writeClientIVCProofToPath(clientIvcProof: ClientIvcProof, outputPath: string) {
41
+ // NB: Don't use clientIvcProof.toBuffer here because it will include the proof length.
42
+ const fieldsBuf = Buffer.concat(clientIvcProof.proof.map(field => field.toBuffer()));
43
+ await fs.writeFile(outputPath, fieldsBuf);
44
+ }
45
+
46
+ function getNumCustomPublicInputs(proofLength: number, vkData: VerificationKeyData) {
47
+ let numPublicInputs = vkData.numPublicInputs;
48
+ if (proofLength == CIVC_PROOF_LENGTH) {
49
+ numPublicInputs -= HIDING_KERNEL_IO_PUBLIC_INPUTS_SIZE;
50
+ } else {
51
+ numPublicInputs -= PAIRING_POINTS_SIZE;
52
+ if (proofLength == NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH) {
53
+ numPublicInputs -= IPA_CLAIM_SIZE;
54
+ }
55
+ }
56
+ return numPublicInputs;
39
57
  }
40
58
 
41
59
  function splitBufferIntoFields(buffer: Buffer): Fr[] {
@@ -46,43 +64,47 @@ function splitBufferIntoFields(buffer: Buffer): Fr[] {
46
64
  return fields;
47
65
  }
48
66
 
49
- export async function readProofAsFields<PROOF_LENGTH extends number>(
50
- filePath: string,
67
+ export async function readProofsFromOutputDirectory<PROOF_LENGTH extends number>(
68
+ directory: string,
51
69
  vkData: VerificationKeyData,
52
70
  proofLength: PROOF_LENGTH,
53
71
  logger: Logger,
54
72
  ): Promise<RecursiveProof<PROOF_LENGTH>> {
55
- const publicInputsFilename = path.join(filePath, PUBLIC_INPUTS_FILENAME);
56
- const proofFilename = path.join(filePath, PROOF_FILENAME);
57
-
58
- const [binaryPublicInputs, binaryProof] = await Promise.all([
59
- fs.readFile(publicInputsFilename),
60
- fs.readFile(proofFilename),
61
- ]);
62
-
63
- const fieldsWithoutPublicInputs = splitBufferIntoFields(binaryProof);
64
-
65
- let numPublicInputs = vkData.numPublicInputs - PAIRING_POINTS_SIZE;
66
73
  assert(
67
- proofLength == NESTED_RECURSIVE_PROOF_LENGTH ||
74
+ proofLength == CIVC_PROOF_LENGTH ||
75
+ proofLength == NESTED_RECURSIVE_PROOF_LENGTH ||
68
76
  proofLength == NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH ||
69
77
  proofLength == ULTRA_KECCAK_PROOF_LENGTH,
70
78
  `Proof length must be one of the expected proof lengths, received ${proofLength}`,
71
79
  );
72
- if (proofLength == NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH) {
73
- numPublicInputs -= IPA_CLAIM_SIZE;
80
+
81
+ const publicInputsFilename = path.join(directory, PUBLIC_INPUTS_FILENAME);
82
+ const proofFilename = path.join(directory, PROOF_FILENAME);
83
+
84
+ // Handle CIVC separately because bb outputs the proof fields with public inputs for CIVC.
85
+ const isCIVC = proofLength == CIVC_PROOF_LENGTH;
86
+
87
+ const [binaryPublicInputs, binaryProof] = await Promise.all([
88
+ isCIVC ? Buffer.alloc(0) : fs.readFile(publicInputsFilename),
89
+ fs.readFile(proofFilename),
90
+ ]);
91
+
92
+ const numPublicInputs = getNumCustomPublicInputs(proofLength, vkData);
93
+ let fieldsWithoutPublicInputs = splitBufferIntoFields(binaryProof);
94
+ if (isCIVC) {
95
+ fieldsWithoutPublicInputs = fieldsWithoutPublicInputs.slice(numPublicInputs);
74
96
  }
75
97
 
76
98
  assert(
77
99
  fieldsWithoutPublicInputs.length == proofLength,
78
- `Proof length mismatch: ${fieldsWithoutPublicInputs.length} != ${proofLength}`,
100
+ `Proof fields length mismatch: ${fieldsWithoutPublicInputs.length} != ${proofLength}`,
79
101
  );
80
102
 
81
103
  // Concat binary public inputs and binary proof
82
104
  // This buffer will have the form: [binary public inputs, binary proof]
83
105
  const binaryProofWithPublicInputs = Buffer.concat([binaryPublicInputs, binaryProof]);
84
106
  logger.debug(
85
- `Circuit path: ${filePath}, complete proof length: ${fieldsWithoutPublicInputs.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}`,
107
+ `Circuit path: ${directory}, proof fields length: ${fieldsWithoutPublicInputs.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}`,
86
108
  );
87
109
  return new RecursiveProof(
88
110
  fieldsWithoutPublicInputs,
@@ -4,7 +4,6 @@ import {
4
4
  NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
5
5
  PAIRING_POINTS_SIZE,
6
6
  RECURSIVE_PROOF_LENGTH,
7
- TUBE_PROOF_LENGTH,
8
7
  ULTRA_KECCAK_PROOF_LENGTH,
9
8
  } from '@aztec/constants';
10
9
  import { Fr } from '@aztec/foundation/fields';
@@ -29,6 +28,8 @@ import {
29
28
  convertPrivateBaseRollupOutputsFromWitnessMap,
30
29
  convertPublicBaseRollupInputsToWitnessMap,
31
30
  convertPublicBaseRollupOutputsFromWitnessMap,
31
+ convertPublicTubeOutputsFromWitnessMap,
32
+ convertPublicTubePrivateInputsToWitnessMap,
32
33
  convertRootParityInputsToWitnessMap,
33
34
  convertRootParityOutputsFromWitnessMap,
34
35
  convertRootRollupInputsToWitnessMap,
@@ -49,6 +50,7 @@ import {
49
50
  makeProofAndVerificationKey,
50
51
  makePublicInputsAndRecursiveProof,
51
52
  } from '@aztec/stdlib/interfaces/server';
53
+ import type { PrivateToPublicKernelCircuitPublicInputs } from '@aztec/stdlib/kernel';
52
54
  import type { BaseParityInputs, ParityPublicInputs, RootParityInputs } from '@aztec/stdlib/parity';
53
55
  import { Proof, RecursiveProof, makeRecursiveProofFromBinary } from '@aztec/stdlib/proofs';
54
56
  import {
@@ -61,17 +63,16 @@ import {
61
63
  PaddingBlockRootRollupInputs,
62
64
  type PrivateBaseRollupInputs,
63
65
  PublicBaseRollupInputs,
66
+ PublicTubePrivateInputs,
64
67
  type RootRollupInputs,
65
68
  type RootRollupPublicInputs,
66
69
  type SingleTxBlockRootRollupInputs,
67
- type TubeInputs,
68
70
  enhanceProofWithPiValidationFlag,
69
71
  } from '@aztec/stdlib/rollup';
70
72
  import type { CircuitProvingStats, CircuitWitnessGenerationStats } from '@aztec/stdlib/stats';
71
73
  import type { VerificationKeyData } from '@aztec/stdlib/vks';
72
74
  import { Attributes, type TelemetryClient, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
73
75
 
74
- import crypto from 'crypto';
75
76
  import { promises as fs } from 'fs';
76
77
  import * as path from 'path';
77
78
 
@@ -84,7 +85,6 @@ import {
84
85
  VK_FILENAME,
85
86
  generateAvmProof,
86
87
  generateProof,
87
- generateTubeProof,
88
88
  verifyAvmProof,
89
89
  verifyProof,
90
90
  } from '../../bb/execute.js';
@@ -92,9 +92,8 @@ import type { ACVMConfig, BBConfig } from '../../config.js';
92
92
  import { type UltraHonkFlavor, getUltraHonkFlavorForCircuit } from '../../honk.js';
93
93
  import { ProverInstrumentation } from '../../instrumentation.js';
94
94
  import { mapProtocolArtifactNameToCircuitName } from '../../stats.js';
95
- import { extractAvmVkData, extractVkData } from '../../verification_key/verification_key_data.js';
96
- import { PRIVATE_TAIL_CIVC_VK, PUBLIC_TAIL_CIVC_VK } from '../../verifier/bb_verifier.js';
97
- import { readProofAsFields, writeClientIVCProofToOutputDirectory } from '../proof_utils.js';
95
+ import { extractAvmVkData } from '../../verification_key/verification_key_data.js';
96
+ import { readProofsFromOutputDirectory } from '../proof_utils.js';
98
97
 
99
98
  const logger = createLogger('bb-prover');
100
99
 
@@ -197,6 +196,31 @@ export class BBNativeRollupProver implements ServerCircuitProver {
197
196
  return proofAndVk;
198
197
  }
199
198
 
199
+ public async getPublicTubeProof(
200
+ inputs: PublicTubePrivateInputs,
201
+ ): Promise<
202
+ PublicInputsAndRecursiveProof<
203
+ PrivateToPublicKernelCircuitPublicInputs,
204
+ typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
205
+ >
206
+ > {
207
+ const artifactName = 'PublicTube';
208
+
209
+ const { circuitOutput, proof } = await this.createRecursiveProof(
210
+ inputs,
211
+ artifactName,
212
+ NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
213
+ convertPublicTubePrivateInputsToWitnessMap,
214
+ convertPublicTubeOutputsFromWitnessMap,
215
+ );
216
+
217
+ const verificationKey = this.getVerificationKeyDataForCircuit(artifactName);
218
+
219
+ await this.verifyProof(artifactName, proof.binaryProof);
220
+
221
+ return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
222
+ }
223
+
200
224
  /**
201
225
  * Simulates the base rollup circuit from its inputs.
202
226
  * @param inputs - Inputs to the circuit.
@@ -467,6 +491,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
467
491
  workingDirectory,
468
492
  circuitType,
469
493
  Buffer.from(artifact.bytecode, 'base64'),
494
+ this.getVerificationKeyDataForCircuit(circuitType).keyAsBytes,
470
495
  outputWitnessFile,
471
496
  getUltraHonkFlavorForCircuit(circuitType),
472
497
  logger,
@@ -500,7 +525,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
500
525
  const vkData = this.getVerificationKeyDataForCircuit(circuitType);
501
526
 
502
527
  const PROOF_LENGTH = circuitType == 'RootRollupArtifact' ? ULTRA_KECCAK_PROOF_LENGTH : RECURSIVE_PROOF_LENGTH;
503
- const proof = await readProofAsFields(provingResult.proofPath!, vkData, PROOF_LENGTH, logger);
528
+ const proof = await readProofsFromOutputDirectory(provingResult.proofPath!, vkData, PROOF_LENGTH, logger);
504
529
 
505
530
  const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
506
531
 
@@ -539,28 +564,6 @@ export class BBNativeRollupProver implements ServerCircuitProver {
539
564
  return provingResult;
540
565
  }
541
566
 
542
- private async generateTubeProofWithBB(bbWorkingDirectory: string, input: TubeInputs): Promise<BBSuccess> {
543
- logger.debug(`Proving tube...`);
544
-
545
- const hasher = crypto.createHash('sha256');
546
- hasher.update(input.toBuffer());
547
-
548
- await writeClientIVCProofToOutputDirectory(input.clientIVCData, bbWorkingDirectory);
549
- const provingResult = await generateTubeProof(
550
- this.config.bbBinaryPath,
551
- bbWorkingDirectory,
552
- input.usePublicTailVk ? PUBLIC_TAIL_CIVC_VK : PRIVATE_TAIL_CIVC_VK,
553
- logger.verbose,
554
- );
555
-
556
- if (provingResult.status === BB_RESULT.FAILURE) {
557
- logger.error(`Failed to generate proof for tube circuit: ${provingResult.reason}`);
558
- throw new ProvingError(provingResult.reason, provingResult, provingResult.retry);
559
- }
560
-
561
- return provingResult;
562
- }
563
-
564
567
  private async createAvmProof(
565
568
  input: AvmCircuitInputs,
566
569
  ): Promise<ProofAndVerificationKey<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
@@ -595,35 +598,6 @@ export class BBNativeRollupProver implements ServerCircuitProver {
595
598
  return await this.runInDirectory(operation);
596
599
  }
597
600
 
598
- public async getTubeProof(input: TubeInputs): Promise<ProofAndVerificationKey<typeof TUBE_PROOF_LENGTH>> {
599
- const operation = async (bbWorkingDirectory: string) => {
600
- logger.debug(`createTubeProof: ${bbWorkingDirectory}`);
601
- const provingResult = await this.generateTubeProofWithBB(bbWorkingDirectory, input);
602
-
603
- // Read the proof as fields
604
- // TODO(AD): this is the only remaining use of extractVkData.
605
- const tubeVK = await extractVkData(provingResult.vkDirectoryPath!);
606
- const tubeProof = await readProofAsFields(provingResult.proofPath!, tubeVK, TUBE_PROOF_LENGTH, logger);
607
-
608
- this.instrumentation.recordDuration('provingDuration', 'tubeCircuit', provingResult.durationMs);
609
- this.instrumentation.recordSize('proofSize', 'tubeCircuit', tubeProof.binaryProof.buffer.length);
610
- this.instrumentation.recordSize('circuitPublicInputCount', 'tubeCircuit', tubeVK.numPublicInputs);
611
- this.instrumentation.recordSize('circuitSize', 'tubeCircuit', tubeVK.circuitSize);
612
-
613
- // Sanity check the tube proof (can be removed later)
614
- await this.verifyWithKey('ultra_rollup_honk', tubeVK, tubeProof.binaryProof);
615
-
616
- logger.info(
617
- `Generated proof for tubeCircuit in ${Math.ceil(provingResult.durationMs)} ms, size: ${
618
- tubeProof.proof.length
619
- } fields`,
620
- );
621
-
622
- return makeProofAndVerificationKey(tubeProof, tubeVK);
623
- };
624
- return await this.runInDirectory(operation);
625
- }
626
-
627
601
  /**
628
602
  * Executes a circuit and returns its outputs and corresponding proof with embedded aggregation object
629
603
  * @param witnessMap - The input witness
@@ -656,7 +630,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
656
630
 
657
631
  const vkData = this.getVerificationKeyDataForCircuit(circuitType);
658
632
  // Read the proof as fields
659
- const proof = await readProofAsFields(provingResult.proofPath!, vkData, proofLength, logger);
633
+ const proof = await readProofsFromOutputDirectory(provingResult.proofPath!, vkData, proofLength, logger);
660
634
 
661
635
  const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
662
636
  this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs);
package/src/stats.ts CHANGED
@@ -7,6 +7,8 @@ export function mapProtocolArtifactNameToCircuitName(artifact: ProtocolArtifact)
7
7
  return 'base-parity';
8
8
  case 'RootParityArtifact':
9
9
  return 'root-parity';
10
+ case 'PublicTube':
11
+ return 'public-tube';
10
12
  case 'PrivateBaseRollupArtifact':
11
13
  return 'private-base-rollup';
12
14
  case 'PublicBaseRollupArtifact':