@aztec/bb-prover 3.0.0-nightly.20250906 → 3.0.0-nightly.20250910
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 -9
- package/dest/bb/execute.d.ts.map +1 -1
- package/dest/bb/execute.js +9 -75
- package/dest/instrumentation.d.ts +2 -2
- package/dest/instrumentation.d.ts.map +1 -1
- package/dest/prover/client/wasm/bb_wasm_private_kernel_prover.d.ts.map +1 -1
- package/dest/prover/client/wasm/bb_wasm_private_kernel_prover.js +2 -4
- package/dest/prover/proof_utils.d.ts +2 -2
- package/dest/prover/proof_utils.d.ts.map +1 -1
- package/dest/prover/proof_utils.js +35 -18
- package/dest/prover/server/bb_prover.d.ts +4 -4
- package/dest/prover/server/bb_prover.d.ts.map +1 -1
- package/dest/prover/server/bb_prover.js +15 -41
- package/dest/stats.d.ts.map +1 -1
- package/dest/stats.js +2 -0
- package/dest/test/delay_values.js +2 -2
- package/dest/test/test_circuit_prover.d.ts +4 -3
- package/dest/test/test_circuit_prover.d.ts.map +1 -1
- package/dest/test/test_circuit_prover.js +3 -3
- package/dest/verifier/bb_verifier.d.ts +2 -4
- package/dest/verifier/bb_verifier.d.ts.map +1 -1
- package/dest/verifier/bb_verifier.js +18 -23
- package/package.json +16 -17
- package/src/bb/execute.ts +6 -73
- package/src/instrumentation.ts +2 -2
- package/src/prover/client/wasm/bb_wasm_private_kernel_prover.ts +2 -4
- package/src/prover/proof_utils.ts +46 -24
- package/src/prover/server/bb_prover.ts +34 -60
- package/src/stats.ts +2 -0
- package/src/test/delay_values.ts +2 -2
- package/src/test/test_circuit_prover.ts +16 -5
- package/src/verifier/bb_verifier.ts +27 -29
|
@@ -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(
|
|
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,
|
|
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 {
|
|
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 {
|
|
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(
|
|
33
|
-
const vk =
|
|
27
|
+
getVerificationKeyData(circuit) {
|
|
28
|
+
const vk = ProtocolCircuitVks[circuit];
|
|
34
29
|
if (vk === undefined) {
|
|
35
|
-
throw new Error(
|
|
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
|
-
|
|
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(`${
|
|
68
|
+
this.logger.debug(`${proofType} BB out - ${message}`);
|
|
78
69
|
};
|
|
79
|
-
|
|
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,
|
|
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 ${
|
|
79
|
+
const errorMessage = `Failed to verify ${proofType} proof for ${circuit}!`;
|
|
85
80
|
throw new Error(errorMessage);
|
|
86
81
|
}
|
|
87
|
-
this.logger.debug(`${
|
|
88
|
-
circuitName: mapProtocolArtifactNameToCircuitName(
|
|
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
|
|
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.
|
|
3
|
+
"version": "3.0.0-nightly.20250910",
|
|
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.
|
|
74
|
-
"@aztec/constants": "3.0.0-nightly.
|
|
75
|
-
"@aztec/foundation": "3.0.0-nightly.
|
|
76
|
-
"@aztec/noir-noirc_abi": "3.0.0-nightly.
|
|
77
|
-
"@aztec/noir-protocol-circuits-types": "3.0.0-nightly.
|
|
78
|
-
"@aztec/noir-types": "3.0.0-nightly.
|
|
79
|
-
"@aztec/simulator": "3.0.0-nightly.
|
|
80
|
-
"@aztec/stdlib": "3.0.0-nightly.
|
|
81
|
-
"@aztec/telemetry-client": "3.0.0-nightly.
|
|
82
|
-
"@aztec/world-state": "3.0.0-nightly.
|
|
72
|
+
"@aztec/bb.js": "3.0.0-nightly.20250910",
|
|
73
|
+
"@aztec/constants": "3.0.0-nightly.20250910",
|
|
74
|
+
"@aztec/foundation": "3.0.0-nightly.20250910",
|
|
75
|
+
"@aztec/noir-noirc_abi": "3.0.0-nightly.20250910",
|
|
76
|
+
"@aztec/noir-protocol-circuits-types": "3.0.0-nightly.20250910",
|
|
77
|
+
"@aztec/noir-types": "3.0.0-nightly.20250910",
|
|
78
|
+
"@aztec/simulator": "3.0.0-nightly.20250910",
|
|
79
|
+
"@aztec/stdlib": "3.0.0-nightly.20250910",
|
|
80
|
+
"@aztec/telemetry-client": "3.0.0-nightly.20250910",
|
|
81
|
+
"@aztec/world-state": "3.0.0-nightly.20250910",
|
|
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.
|
|
90
|
-
"@aztec/kv-store": "3.0.0-nightly.
|
|
91
|
-
"@aztec/noir-contracts.js": "3.0.0-nightly.
|
|
92
|
-
"@aztec/noir-test-contracts.js": "3.0.0-nightly.
|
|
93
|
-
"@aztec/protocol-contracts": "3.0.0-nightly.
|
|
88
|
+
"@aztec/ethereum": "3.0.0-nightly.20250910",
|
|
89
|
+
"@aztec/kv-store": "3.0.0-nightly.20250910",
|
|
90
|
+
"@aztec/noir-contracts.js": "3.0.0-nightly.20250910",
|
|
91
|
+
"@aztec/noir-test-contracts.js": "3.0.0-nightly.20250910",
|
|
92
|
+
"@aztec/protocol-contracts": "3.0.0-nightly.20250910",
|
|
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.
|
package/src/instrumentation.ts
CHANGED
|
@@ -86,7 +86,7 @@ export class ProverInstrumentation {
|
|
|
86
86
|
*/
|
|
87
87
|
recordDuration(
|
|
88
88
|
metric: 'simulationDuration' | 'witGenDuration' | 'provingDuration',
|
|
89
|
-
circuitName: CircuitName
|
|
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
|
|
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
|
-
|
|
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
|
|
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 {
|
|
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
|
|
27
|
-
|
|
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
|
|
37
|
-
|
|
38
|
-
|
|
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
|
|
50
|
-
|
|
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 ==
|
|
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
|
-
|
|
73
|
-
|
|
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: ${
|
|
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
|
|
96
|
-
import {
|
|
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
|
|
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
|
|
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':
|