@aztec/bb-prover 0.87.0 → 0.87.2-nightly.20250523
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/avm_proving_tests/avm_proving_tester.d.ts +3 -10
- package/dest/avm_proving_tests/avm_proving_tester.d.ts.map +1 -1
- package/dest/avm_proving_tests/avm_proving_tester.js +18 -62
- package/dest/bb/execute.d.ts +5 -24
- package/dest/bb/execute.d.ts.map +1 -1
- package/dest/bb/execute.js +16 -104
- package/dest/prover/server/bb_prover.d.ts +5 -5
- package/dest/prover/server/bb_prover.d.ts.map +1 -1
- package/dest/prover/server/bb_prover.js +22 -13
- package/dest/test/test_circuit_prover.d.ts +2 -2
- package/dest/test/test_circuit_prover.d.ts.map +1 -1
- package/dest/test/test_circuit_prover.js +2 -2
- package/dest/verification_key/verification_key_data.d.ts +6 -0
- package/dest/verification_key/verification_key_data.d.ts.map +1 -1
- package/dest/verification_key/verification_key_data.js +16 -16
- package/package.json +16 -16
- package/src/avm_proving_tests/avm_proving_tester.ts +30 -87
- package/src/bb/execute.ts +22 -123
- package/src/prover/server/bb_prover.ts +48 -30
- package/src/test/test_circuit_prover.ts +7 -5
- package/src/verification_key/verification_key_data.ts +20 -13
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED } from '@aztec/constants';
|
|
2
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
+
import { BufferReader } from '@aztec/foundation/serialize';
|
|
3
4
|
import { hashVK } from '@aztec/stdlib/hash';
|
|
4
5
|
import { VerificationKeyAsFields, VerificationKeyData } from '@aztec/stdlib/vks';
|
|
5
6
|
import { strict as assert } from 'assert';
|
|
@@ -24,21 +25,20 @@ import { VK_FIELDS_FILENAME, VK_FILENAME } from '../bb/execute.js';
|
|
|
24
25
|
const vkAsFields = new VerificationKeyAsFields(fields, vkHash);
|
|
25
26
|
return new VerificationKeyData(vkAsFields, rawBinary);
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const vkAsFields = new VerificationKeyAsFields(fields, vkHash);
|
|
28
|
+
/**
|
|
29
|
+
* Reads the verification key data stored in a binary file at the specified directory location and parses into a VerificationKeyData.
|
|
30
|
+
* We do not assume any JSON file available but only the binary version, contrary to the above extractVkData() method.
|
|
31
|
+
* @param vkDirectoryPath - The directory containing the verification key binary data file.
|
|
32
|
+
* @returns The verification key data
|
|
33
|
+
*/ export async function extractAvmVkData(vkDirectoryPath) {
|
|
34
|
+
const rawBinary = await fs.readFile(path.join(vkDirectoryPath, VK_FILENAME));
|
|
35
|
+
const numFields = rawBinary.length / Fr.SIZE_IN_BYTES;
|
|
36
|
+
assert(numFields <= AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED, 'Invalid AVM verification key length');
|
|
37
|
+
const reader = BufferReader.asReader(rawBinary);
|
|
38
|
+
const fieldsArray = reader.readArray(numFields, Fr);
|
|
39
|
+
const fieldsArrayPadded = fieldsArray.concat(Array(AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED - fieldsArray.length).fill(new Fr(0)));
|
|
40
|
+
// Currently, we do not need the vk hash for the AVM as we are not adding in the vk tree.
|
|
41
|
+
const vkAsFields = new VerificationKeyAsFields(fieldsArrayPadded, new Fr(0));
|
|
42
42
|
const vk = new VerificationKeyData(vkAsFields, rawBinary);
|
|
43
43
|
return vk;
|
|
44
44
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/bb-prover",
|
|
3
|
-
"version": "0.87.
|
|
3
|
+
"version": "0.87.2-nightly.20250523",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -66,27 +66,27 @@
|
|
|
66
66
|
]
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"@aztec/bb.js": "0.87.
|
|
70
|
-
"@aztec/constants": "0.87.
|
|
71
|
-
"@aztec/foundation": "0.87.
|
|
72
|
-
"@aztec/noir-noirc_abi": "0.87.
|
|
73
|
-
"@aztec/noir-protocol-circuits-types": "0.87.
|
|
74
|
-
"@aztec/noir-types": "0.87.
|
|
75
|
-
"@aztec/simulator": "0.87.
|
|
76
|
-
"@aztec/stdlib": "0.87.
|
|
77
|
-
"@aztec/telemetry-client": "0.87.
|
|
78
|
-
"@aztec/world-state": "0.87.
|
|
69
|
+
"@aztec/bb.js": "0.87.2-nightly.20250523",
|
|
70
|
+
"@aztec/constants": "0.87.2-nightly.20250523",
|
|
71
|
+
"@aztec/foundation": "0.87.2-nightly.20250523",
|
|
72
|
+
"@aztec/noir-noirc_abi": "0.87.2-nightly.20250523",
|
|
73
|
+
"@aztec/noir-protocol-circuits-types": "0.87.2-nightly.20250523",
|
|
74
|
+
"@aztec/noir-types": "0.87.2-nightly.20250523",
|
|
75
|
+
"@aztec/simulator": "0.87.2-nightly.20250523",
|
|
76
|
+
"@aztec/stdlib": "0.87.2-nightly.20250523",
|
|
77
|
+
"@aztec/telemetry-client": "0.87.2-nightly.20250523",
|
|
78
|
+
"@aztec/world-state": "0.87.2-nightly.20250523",
|
|
79
79
|
"commander": "^12.1.0",
|
|
80
80
|
"pako": "^2.1.0",
|
|
81
81
|
"source-map-support": "^0.5.21",
|
|
82
82
|
"tslib": "^2.4.0"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
|
-
"@aztec/ethereum": "0.87.
|
|
86
|
-
"@aztec/kv-store": "0.87.
|
|
87
|
-
"@aztec/noir-contracts.js": "0.87.
|
|
88
|
-
"@aztec/noir-test-contracts.js": "0.87.
|
|
89
|
-
"@aztec/protocol-contracts": "0.87.
|
|
85
|
+
"@aztec/ethereum": "0.87.2-nightly.20250523",
|
|
86
|
+
"@aztec/kv-store": "0.87.2-nightly.20250523",
|
|
87
|
+
"@aztec/noir-contracts.js": "0.87.2-nightly.20250523",
|
|
88
|
+
"@aztec/noir-test-contracts.js": "0.87.2-nightly.20250523",
|
|
89
|
+
"@aztec/protocol-contracts": "0.87.2-nightly.20250523",
|
|
90
90
|
"@jest/globals": "^29.5.0",
|
|
91
91
|
"@types/jest": "^29.5.0",
|
|
92
92
|
"@types/node": "^22.15.17",
|
|
@@ -7,7 +7,6 @@ import { type AvmCircuitInputs, AvmCircuitPublicInputs } from '@aztec/stdlib/avm
|
|
|
7
7
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
8
8
|
import type { MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
|
|
9
9
|
import type { GlobalVariables } from '@aztec/stdlib/tx';
|
|
10
|
-
import { VerificationKeyData } from '@aztec/stdlib/vks';
|
|
11
10
|
import { NativeWorldStateService } from '@aztec/world-state';
|
|
12
11
|
|
|
13
12
|
import fs from 'node:fs/promises';
|
|
@@ -18,12 +17,10 @@ import {
|
|
|
18
17
|
type BBResult,
|
|
19
18
|
type BBSuccess,
|
|
20
19
|
BB_RESULT,
|
|
20
|
+
VK_FILENAME,
|
|
21
21
|
generateAvmProof,
|
|
22
|
-
generateAvmProofV2,
|
|
23
22
|
verifyAvmProof,
|
|
24
|
-
verifyAvmProofV2,
|
|
25
23
|
} from '../bb/execute.js';
|
|
26
|
-
import { extractAvmVkData } from '../verification_key/verification_key_data.js';
|
|
27
24
|
|
|
28
25
|
const BB_PATH = path.resolve('../../barretenberg/cpp/build/bin/bb');
|
|
29
26
|
|
|
@@ -31,20 +28,19 @@ export class AvmProvingTester extends PublicTxSimulationTester {
|
|
|
31
28
|
constructor(
|
|
32
29
|
private bbWorkingDirectory: string,
|
|
33
30
|
private checkCircuitOnly: boolean,
|
|
34
|
-
merkleTree: MerkleTreeWriteOperations,
|
|
35
31
|
contractDataSource: SimpleContractDataSource,
|
|
32
|
+
merkleTrees: MerkleTreeWriteOperations,
|
|
36
33
|
globals?: GlobalVariables,
|
|
37
34
|
) {
|
|
38
|
-
super(
|
|
35
|
+
super(merkleTrees, contractDataSource, globals);
|
|
39
36
|
}
|
|
40
37
|
|
|
41
|
-
// overriding parent class' create is a pain, so we use a different nam
|
|
42
38
|
static async new(checkCircuitOnly: boolean = false, globals?: GlobalVariables) {
|
|
43
39
|
const bbWorkingDirectory = await fs.mkdtemp(path.join(tmpdir(), 'bb-'));
|
|
44
40
|
|
|
45
41
|
const contractDataSource = new SimpleContractDataSource();
|
|
46
42
|
const merkleTrees = await (await NativeWorldStateService.tmp()).fork();
|
|
47
|
-
return new AvmProvingTester(bbWorkingDirectory, checkCircuitOnly,
|
|
43
|
+
return new AvmProvingTester(bbWorkingDirectory, checkCircuitOnly, contractDataSource, merkleTrees, globals);
|
|
48
44
|
}
|
|
49
45
|
|
|
50
46
|
async prove(avmCircuitInputs: AvmCircuitInputs): Promise<BBResult> {
|
|
@@ -59,95 +55,36 @@ export class AvmProvingTester extends PublicTxSimulationTester {
|
|
|
59
55
|
if (proofRes.status === BB_RESULT.FAILURE) {
|
|
60
56
|
this.logger.error(`Proof generation failed: ${proofRes.reason}`);
|
|
61
57
|
}
|
|
62
|
-
|
|
58
|
+
expect(proofRes.status).toEqual(BB_RESULT.SUCCESS);
|
|
59
|
+
return proofRes as BBSuccess;
|
|
63
60
|
}
|
|
64
61
|
|
|
65
|
-
async verify(proofRes: BBSuccess): Promise<BBResult> {
|
|
62
|
+
async verify(proofRes: BBSuccess, publicInputs: AvmCircuitPublicInputs): Promise<BBResult> {
|
|
66
63
|
if (this.checkCircuitOnly) {
|
|
67
|
-
// Skip verification if we
|
|
68
|
-
// Check-circuit
|
|
64
|
+
// Skip verification if we are only checking the circuit.
|
|
65
|
+
// Check-circuit does not generate a proof to verify.
|
|
69
66
|
return proofRes;
|
|
70
67
|
}
|
|
71
|
-
// Then we test VK extraction and serialization.
|
|
72
|
-
const succeededRes = proofRes as BBSuccess;
|
|
73
|
-
const vkData = await extractAvmVkData(succeededRes.vkPath!);
|
|
74
|
-
VerificationKeyData.fromBuffer(vkData.toBuffer());
|
|
75
|
-
|
|
76
|
-
// Then we verify.
|
|
77
|
-
const rawVkPath = path.join(succeededRes.vkPath!, 'vk');
|
|
78
|
-
return await verifyAvmProof(BB_PATH, succeededRes.proofPath!, rawVkPath, this.logger);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
public async simProveVerify(
|
|
82
|
-
sender: AztecAddress,
|
|
83
|
-
setupCalls: TestEnqueuedCall[],
|
|
84
|
-
appCalls: TestEnqueuedCall[],
|
|
85
|
-
teardownCall: TestEnqueuedCall | undefined,
|
|
86
|
-
expectRevert: boolean | undefined,
|
|
87
|
-
feePayer = sender,
|
|
88
|
-
) {
|
|
89
|
-
const simRes = await this.simulateTx(sender, setupCalls, appCalls, teardownCall, feePayer);
|
|
90
|
-
expect(simRes.revertCode.isOK()).toBe(expectRevert ? false : true);
|
|
91
|
-
const avmCircuitInputs = simRes.avmProvingRequest.inputs;
|
|
92
|
-
const provingRes = await this.prove(avmCircuitInputs);
|
|
93
|
-
expect(provingRes.status).toEqual(BB_RESULT.SUCCESS);
|
|
94
|
-
const verificationRes = await this.verify(provingRes as BBSuccess);
|
|
95
|
-
expect(verificationRes.status).toBe(BB_RESULT.SUCCESS);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
public async simProveVerifyAppLogic(appCall: TestEnqueuedCall, expectRevert?: boolean) {
|
|
99
|
-
const simRes = await this.simulateTx(/*sender=*/ AztecAddress.fromNumber(42), /*setupCalls=*/ [], [appCall]);
|
|
100
|
-
expect(simRes.revertCode.isOK()).toBe(expectRevert ? false : true);
|
|
101
|
-
|
|
102
|
-
const avmCircuitInputs = simRes.avmProvingRequest.inputs;
|
|
103
|
-
const provingRes = await this.prove(avmCircuitInputs);
|
|
104
|
-
expect(provingRes.status).toEqual(BB_RESULT.SUCCESS);
|
|
105
|
-
|
|
106
|
-
const verificationRes = await this.verify(provingRes as BBSuccess);
|
|
107
|
-
expect(verificationRes.status).toBe(BB_RESULT.SUCCESS);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export class AvmProvingTesterV2 extends PublicTxSimulationTester {
|
|
112
|
-
constructor(
|
|
113
|
-
private bbWorkingDirectory: string,
|
|
114
|
-
contractDataSource: SimpleContractDataSource,
|
|
115
|
-
merkleTrees: MerkleTreeWriteOperations,
|
|
116
|
-
globals?: GlobalVariables,
|
|
117
|
-
) {
|
|
118
|
-
super(merkleTrees, contractDataSource, globals);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
static async new(globals?: GlobalVariables) {
|
|
122
|
-
const bbWorkingDirectory = await fs.mkdtemp(path.join(tmpdir(), 'bb-'));
|
|
123
|
-
|
|
124
|
-
const contractDataSource = new SimpleContractDataSource();
|
|
125
|
-
const merkleTrees = await (await NativeWorldStateService.tmp()).fork();
|
|
126
|
-
return new AvmProvingTesterV2(bbWorkingDirectory, contractDataSource, merkleTrees, globals);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
async proveV2(avmCircuitInputs: AvmCircuitInputs): Promise<BBResult> {
|
|
130
|
-
// Then we prove.
|
|
131
|
-
const proofRes = await generateAvmProofV2(BB_PATH, this.bbWorkingDirectory, avmCircuitInputs, this.logger);
|
|
132
|
-
if (proofRes.status === BB_RESULT.FAILURE) {
|
|
133
|
-
this.logger.error(`Proof generation failed: ${proofRes.reason}`);
|
|
134
|
-
}
|
|
135
|
-
expect(proofRes.status).toEqual(BB_RESULT.SUCCESS);
|
|
136
|
-
return proofRes as BBSuccess;
|
|
137
|
-
}
|
|
138
68
|
|
|
139
|
-
|
|
140
|
-
return await verifyAvmProofV2(
|
|
69
|
+
return await verifyAvmProof(
|
|
141
70
|
BB_PATH,
|
|
142
71
|
this.bbWorkingDirectory,
|
|
143
72
|
proofRes.proofPath!,
|
|
144
73
|
publicInputs,
|
|
145
|
-
proofRes.
|
|
74
|
+
path.join(proofRes.vkDirectoryPath!, VK_FILENAME),
|
|
146
75
|
this.logger,
|
|
147
76
|
);
|
|
148
77
|
}
|
|
149
78
|
|
|
150
|
-
public async
|
|
79
|
+
public async proveVerify(avmCircuitInputs: AvmCircuitInputs) {
|
|
80
|
+
const provingRes = await this.prove(avmCircuitInputs);
|
|
81
|
+
expect(provingRes.status).toEqual(BB_RESULT.SUCCESS);
|
|
82
|
+
|
|
83
|
+
const verificationRes = await this.verify(provingRes as BBSuccess, avmCircuitInputs.publicInputs);
|
|
84
|
+
expect(verificationRes.status).toBe(BB_RESULT.SUCCESS);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public async simProveVerify(
|
|
151
88
|
sender: AztecAddress,
|
|
152
89
|
setupCalls: TestEnqueuedCall[],
|
|
153
90
|
appCalls: TestEnqueuedCall[],
|
|
@@ -159,10 +96,16 @@ export class AvmProvingTesterV2 extends PublicTxSimulationTester {
|
|
|
159
96
|
expect(simRes.revertCode.isOK()).toBe(expectRevert ? false : true);
|
|
160
97
|
|
|
161
98
|
const avmCircuitInputs = simRes.avmProvingRequest.inputs;
|
|
162
|
-
|
|
163
|
-
|
|
99
|
+
await this.proveVerify(avmCircuitInputs);
|
|
100
|
+
}
|
|
164
101
|
|
|
165
|
-
|
|
166
|
-
|
|
102
|
+
public async simProveVerifyAppLogic(appCall: TestEnqueuedCall, expectRevert?: boolean) {
|
|
103
|
+
await this.simProveVerify(
|
|
104
|
+
/*sender=*/ AztecAddress.fromNumber(42),
|
|
105
|
+
/*setupCalls=*/ [],
|
|
106
|
+
[appCall],
|
|
107
|
+
undefined,
|
|
108
|
+
expectRevert,
|
|
109
|
+
);
|
|
167
110
|
}
|
|
168
111
|
}
|
package/src/bb/execute.ts
CHANGED
|
@@ -32,7 +32,7 @@ export type BBSuccess = {
|
|
|
32
32
|
/** Full path of the public key. */
|
|
33
33
|
pkPath?: string;
|
|
34
34
|
/** Base directory for the VKs (raw, fields). */
|
|
35
|
-
|
|
35
|
+
vkDirectoryPath?: string;
|
|
36
36
|
/** Full path of the proof. */
|
|
37
37
|
proofPath?: string;
|
|
38
38
|
/** Full path of the contract. */
|
|
@@ -49,8 +49,6 @@ export type BBFailure = {
|
|
|
49
49
|
|
|
50
50
|
export type BBResult = BBSuccess | BBFailure;
|
|
51
51
|
|
|
52
|
-
export type VerificationFunction = typeof verifyProof | typeof verifyAvmProof;
|
|
53
|
-
|
|
54
52
|
type BBExecResult = {
|
|
55
53
|
status: BB_RESULT;
|
|
56
54
|
exitCode: number;
|
|
@@ -162,7 +160,7 @@ export async function executeBbClientIvcProof(
|
|
|
162
160
|
durationMs,
|
|
163
161
|
proofPath: `${outputPath}`,
|
|
164
162
|
pkPath: undefined,
|
|
165
|
-
|
|
163
|
+
vkDirectoryPath: `${outputPath}`,
|
|
166
164
|
};
|
|
167
165
|
}
|
|
168
166
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
@@ -266,7 +264,7 @@ export async function generateProof(
|
|
|
266
264
|
durationMs: duration,
|
|
267
265
|
proofPath: `${outputPath}`,
|
|
268
266
|
pkPath: undefined,
|
|
269
|
-
|
|
267
|
+
vkDirectoryPath: `${outputPath}`,
|
|
270
268
|
};
|
|
271
269
|
}
|
|
272
270
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
@@ -334,7 +332,7 @@ export async function generateTubeProof(
|
|
|
334
332
|
durationMs,
|
|
335
333
|
proofPath: outputPath,
|
|
336
334
|
pkPath: undefined,
|
|
337
|
-
|
|
335
|
+
vkDirectoryPath: outputPath,
|
|
338
336
|
};
|
|
339
337
|
}
|
|
340
338
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
@@ -354,14 +352,16 @@ export async function generateTubeProof(
|
|
|
354
352
|
* @param pathToBB - The full path to the bb binary
|
|
355
353
|
* @param workingDirectory - A working directory for use by bb
|
|
356
354
|
* @param input - The inputs for the public function to be proven
|
|
357
|
-
* @param
|
|
355
|
+
* @param logger - A logging function
|
|
356
|
+
* @param checkCircuitOnly - A boolean to toggle a "check-circuit only" operation instead of proving.
|
|
358
357
|
* @returns An object containing a result indication, the location of the proof and the duration taken
|
|
359
358
|
*/
|
|
360
|
-
export async function
|
|
359
|
+
export async function generateAvmProof(
|
|
361
360
|
pathToBB: string,
|
|
362
361
|
workingDirectory: string,
|
|
363
362
|
input: AvmCircuitInputs,
|
|
364
363
|
logger: Logger,
|
|
364
|
+
checkCircuitOnly: boolean = false,
|
|
365
365
|
): Promise<BBFailure | BBSuccess> {
|
|
366
366
|
// Check that the working directory exists
|
|
367
367
|
try {
|
|
@@ -401,99 +401,12 @@ export async function generateAvmProofV2(
|
|
|
401
401
|
args.push(loggingArg);
|
|
402
402
|
}
|
|
403
403
|
const timer = new Timer();
|
|
404
|
-
const logFunction = (message: string) => {
|
|
405
|
-
logger.verbose(`AvmCircuit (prove) BB out - ${message}`);
|
|
406
|
-
};
|
|
407
|
-
const result = await executeBB(pathToBB, 'avm2_prove', args, logFunction);
|
|
408
|
-
const duration = timer.ms();
|
|
409
404
|
|
|
410
|
-
|
|
411
|
-
return {
|
|
412
|
-
status: BB_RESULT.SUCCESS,
|
|
413
|
-
durationMs: duration,
|
|
414
|
-
proofPath: join(outputPath, PROOF_FILENAME),
|
|
415
|
-
pkPath: undefined,
|
|
416
|
-
vkPath: join(outputPath, VK_FILENAME),
|
|
417
|
-
};
|
|
418
|
-
}
|
|
419
|
-
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
420
|
-
return {
|
|
421
|
-
status: BB_RESULT.FAILURE,
|
|
422
|
-
reason: `Failed to generate proof. Exit code ${result.exitCode}. Signal ${result.signal}.`,
|
|
423
|
-
retry: !!result.signal,
|
|
424
|
-
};
|
|
425
|
-
} catch (error) {
|
|
426
|
-
return { status: BB_RESULT.FAILURE, reason: `${error}` };
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
/**
|
|
431
|
-
* Used for generating AVM proofs (or doing check-circuit).
|
|
432
|
-
* It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof.
|
|
433
|
-
* @param pathToBB - The full path to the bb binary
|
|
434
|
-
* @param workingDirectory - A working directory for use by bb
|
|
435
|
-
* @param bytecode - The AVM bytecode for the public function to be proven (expected to be decompressed)
|
|
436
|
-
* @param log - A logging function
|
|
437
|
-
* @returns An object containing a result indication, the location of the proof and the duration taken
|
|
438
|
-
*/
|
|
439
|
-
export async function generateAvmProof(
|
|
440
|
-
pathToBB: string,
|
|
441
|
-
workingDirectory: string,
|
|
442
|
-
_input: AvmCircuitInputs,
|
|
443
|
-
logger: Logger,
|
|
444
|
-
checkCircuitOnly: boolean = false,
|
|
445
|
-
): Promise<BBFailure | BBSuccess> {
|
|
446
|
-
// Check that the working directory exists
|
|
447
|
-
try {
|
|
448
|
-
await fs.access(workingDirectory);
|
|
449
|
-
} catch {
|
|
450
|
-
return { status: BB_RESULT.FAILURE, reason: `Working directory ${workingDirectory} does not exist` };
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
// Paths for the inputs
|
|
454
|
-
const publicInputsPath = join(workingDirectory, AVM_PUBLIC_INPUTS_FILENAME);
|
|
455
|
-
|
|
456
|
-
// The proof is written to e.g. /workingDirectory/proof
|
|
457
|
-
const outputPath = workingDirectory;
|
|
458
|
-
|
|
459
|
-
const filePresent = async (file: string) =>
|
|
460
|
-
await fs
|
|
461
|
-
.access(file, fs.constants.R_OK)
|
|
462
|
-
.then(_ => true)
|
|
463
|
-
.catch(_ => false);
|
|
464
|
-
|
|
465
|
-
const binaryPresent = await filePresent(pathToBB);
|
|
466
|
-
if (!binaryPresent) {
|
|
467
|
-
return { status: BB_RESULT.FAILURE, reason: `Failed to find bb binary at ${pathToBB}` };
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
try {
|
|
471
|
-
// Write the inputs to the working directory.
|
|
472
|
-
|
|
473
|
-
// WARNING: Not writing the inputs since VM1 is disabled!
|
|
474
|
-
// await fs.writeFile(publicInputsPath, input.publicInputs.toBuffer());
|
|
475
|
-
// if (!(await filePresent(publicInputsPath))) {
|
|
476
|
-
// return { status: BB_RESULT.FAILURE, reason: `Could not write publicInputs at ${publicInputsPath}` };
|
|
477
|
-
// }
|
|
478
|
-
|
|
479
|
-
// await fs.writeFile(avmHintsPath, input.avmHints.toBuffer());
|
|
480
|
-
// if (!(await filePresent(avmHintsPath))) {
|
|
481
|
-
// return { status: BB_RESULT.FAILURE, reason: `Could not write avmHints at ${avmHintsPath}` };
|
|
482
|
-
// }
|
|
483
|
-
|
|
484
|
-
const args = ['--avm-public-inputs', publicInputsPath, '-o', outputPath];
|
|
485
|
-
const loggingArg =
|
|
486
|
-
logger.level === 'debug' || logger.level === 'trace' ? '-d' : logger.level === 'verbose' ? '-v' : '';
|
|
487
|
-
if (loggingArg !== '') {
|
|
488
|
-
args.push(loggingArg);
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
const timer = new Timer();
|
|
492
|
-
const cmd = checkCircuitOnly ? 'check_circuit' : 'prove';
|
|
405
|
+
const cmd = checkCircuitOnly ? 'avm_check_circuit' : 'avm_prove';
|
|
493
406
|
const logFunction = (message: string) => {
|
|
494
407
|
logger.verbose(`AvmCircuit (${cmd}) BB out - ${message}`);
|
|
495
408
|
};
|
|
496
|
-
const result = await executeBB(pathToBB,
|
|
409
|
+
const result = await executeBB(pathToBB, cmd, args, logFunction);
|
|
497
410
|
const duration = timer.ms();
|
|
498
411
|
|
|
499
412
|
if (result.status == BB_RESULT.SUCCESS) {
|
|
@@ -502,7 +415,7 @@ export async function generateAvmProof(
|
|
|
502
415
|
durationMs: duration,
|
|
503
416
|
proofPath: join(outputPath, PROOF_FILENAME),
|
|
504
417
|
pkPath: undefined,
|
|
505
|
-
|
|
418
|
+
vkDirectoryPath: outputPath,
|
|
506
419
|
};
|
|
507
420
|
}
|
|
508
421
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
@@ -541,24 +454,7 @@ export async function verifyProof(
|
|
|
541
454
|
);
|
|
542
455
|
}
|
|
543
456
|
|
|
544
|
-
/**
|
|
545
|
-
* Used for verifying proofs of the AVM
|
|
546
|
-
* @param pathToBB - The full path to the bb binary
|
|
547
|
-
* @param proofFullPath - The full path to the proof to be verified
|
|
548
|
-
* @param verificationKeyPath - The full path to the circuit verification key
|
|
549
|
-
* @param log - A logging function
|
|
550
|
-
* @returns An object containing a result indication and duration taken
|
|
551
|
-
*/
|
|
552
457
|
export async function verifyAvmProof(
|
|
553
|
-
pathToBB: string,
|
|
554
|
-
proofFullPath: string,
|
|
555
|
-
verificationKeyPath: string,
|
|
556
|
-
logger: Logger,
|
|
557
|
-
): Promise<BBFailure | BBSuccess> {
|
|
558
|
-
return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'avm_verify', logger);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
export async function verifyAvmProofV2(
|
|
562
458
|
pathToBB: string,
|
|
563
459
|
workingDirectory: string,
|
|
564
460
|
proofFullPath: string,
|
|
@@ -580,7 +476,7 @@ export async function verifyAvmProofV2(
|
|
|
580
476
|
return { status: BB_RESULT.FAILURE, reason: `Could not write avm inputs to ${avmInputsPath}` };
|
|
581
477
|
}
|
|
582
478
|
|
|
583
|
-
return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, '
|
|
479
|
+
return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'avm_verify', logger, [
|
|
584
480
|
'--avm-public-inputs',
|
|
585
481
|
avmInputsPath,
|
|
586
482
|
]);
|
|
@@ -641,7 +537,7 @@ async function verifyProofInternal(
|
|
|
641
537
|
pathToBB: string,
|
|
642
538
|
proofFullPath: string,
|
|
643
539
|
verificationKeyPath: string,
|
|
644
|
-
command: 'verify' | 'avm_verify'
|
|
540
|
+
command: 'verify' | 'avm_verify',
|
|
645
541
|
logger: Logger,
|
|
646
542
|
extraArgs: string[] = [],
|
|
647
543
|
): Promise<BBFailure | BBSuccess> {
|
|
@@ -657,24 +553,27 @@ async function verifyProofInternal(
|
|
|
657
553
|
logger.verbose(`bb-prover (verify) BB out - ${message}`);
|
|
658
554
|
};
|
|
659
555
|
|
|
660
|
-
// take proofFullPath and remove the suffix past the / to get the directory
|
|
661
|
-
const proofDir = proofFullPath.substring(0, proofFullPath.lastIndexOf('/'));
|
|
662
|
-
const publicInputsFullPath = join(proofDir, '/public_inputs');
|
|
663
|
-
|
|
664
|
-
logger.debug(`public inputs path: ${publicInputsFullPath}`);
|
|
665
556
|
try {
|
|
666
557
|
let args;
|
|
667
|
-
|
|
558
|
+
|
|
668
559
|
if (command == 'verify') {
|
|
560
|
+
// Specify the public inputs path in the case of UH verification.
|
|
561
|
+
// Take proofFullPath and remove the suffix past the / to get the directory.
|
|
562
|
+
const proofDir = proofFullPath.substring(0, proofFullPath.lastIndexOf('/'));
|
|
563
|
+
const publicInputsFullPath = join(proofDir, '/public_inputs');
|
|
564
|
+
logger.debug(`public inputs path: ${publicInputsFullPath}`);
|
|
565
|
+
|
|
669
566
|
args = ['-p', proofFullPath, '-k', verificationKeyPath, '-i', publicInputsFullPath, ...extraArgs];
|
|
670
567
|
} else {
|
|
671
568
|
args = ['-p', proofFullPath, '-k', verificationKeyPath, ...extraArgs];
|
|
672
569
|
}
|
|
570
|
+
|
|
673
571
|
const loggingArg =
|
|
674
572
|
logger.level === 'debug' || logger.level === 'trace' ? '-d' : logger.level === 'verbose' ? '-v' : '';
|
|
675
573
|
if (loggingArg !== '') {
|
|
676
574
|
args.push(loggingArg);
|
|
677
575
|
}
|
|
576
|
+
|
|
678
577
|
const timer = new Timer();
|
|
679
578
|
const result = await executeBB(pathToBB, command, args, logFunction);
|
|
680
579
|
const duration = timer.ms();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED,
|
|
3
3
|
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
4
4
|
NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
|
|
5
5
|
PAIRING_POINTS_SIZE,
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
import { ServerCircuitVks } from '@aztec/noir-protocol-circuits-types/server/vks';
|
|
38
38
|
import type { WitnessMap } from '@aztec/noir-types';
|
|
39
39
|
import { NativeACVMSimulator } from '@aztec/simulator/server';
|
|
40
|
-
import type { AvmCircuitInputs } from '@aztec/stdlib/avm';
|
|
40
|
+
import type { AvmCircuitInputs, AvmCircuitPublicInputs } from '@aztec/stdlib/avm';
|
|
41
41
|
import { ProvingError } from '@aztec/stdlib/errors';
|
|
42
42
|
import {
|
|
43
43
|
type ProofAndVerificationKey,
|
|
@@ -48,19 +48,20 @@ import {
|
|
|
48
48
|
} from '@aztec/stdlib/interfaces/server';
|
|
49
49
|
import type { BaseParityInputs, ParityPublicInputs, RootParityInputs } from '@aztec/stdlib/parity';
|
|
50
50
|
import { Proof, RecursiveProof, makeRecursiveProofFromBinary } from '@aztec/stdlib/proofs';
|
|
51
|
-
import
|
|
52
|
-
BaseOrMergeRollupPublicInputs,
|
|
53
|
-
BlockMergeRollupInputs,
|
|
54
|
-
BlockRootOrBlockMergePublicInputs,
|
|
55
|
-
BlockRootRollupInputs,
|
|
56
|
-
EmptyBlockRootRollupInputs,
|
|
57
|
-
MergeRollupInputs,
|
|
58
|
-
PrivateBaseRollupInputs,
|
|
51
|
+
import {
|
|
52
|
+
type BaseOrMergeRollupPublicInputs,
|
|
53
|
+
type BlockMergeRollupInputs,
|
|
54
|
+
type BlockRootOrBlockMergePublicInputs,
|
|
55
|
+
type BlockRootRollupInputs,
|
|
56
|
+
type EmptyBlockRootRollupInputs,
|
|
57
|
+
type MergeRollupInputs,
|
|
58
|
+
type PrivateBaseRollupInputs,
|
|
59
59
|
PublicBaseRollupInputs,
|
|
60
|
-
RootRollupInputs,
|
|
61
|
-
RootRollupPublicInputs,
|
|
62
|
-
SingleTxBlockRootRollupInputs,
|
|
63
|
-
TubeInputs,
|
|
60
|
+
type RootRollupInputs,
|
|
61
|
+
type RootRollupPublicInputs,
|
|
62
|
+
type SingleTxBlockRootRollupInputs,
|
|
63
|
+
type TubeInputs,
|
|
64
|
+
enhanceProofWithPiValidationFlag,
|
|
64
65
|
} from '@aztec/stdlib/rollup';
|
|
65
66
|
import type { CircuitProvingStats, CircuitWitnessGenerationStats } from '@aztec/stdlib/stats';
|
|
66
67
|
import type { VerificationKeyData } from '@aztec/stdlib/vks';
|
|
@@ -185,9 +186,13 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
185
186
|
}))
|
|
186
187
|
public async getAvmProof(
|
|
187
188
|
inputs: AvmCircuitInputs,
|
|
188
|
-
|
|
189
|
+
skipPublicInputsValidation: boolean = false,
|
|
190
|
+
): Promise<ProofAndVerificationKey<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
|
|
189
191
|
const proofAndVk = await this.createAvmProof(inputs);
|
|
190
|
-
await this.verifyAvmProof(proofAndVk.proof.binaryProof, proofAndVk.verificationKey);
|
|
192
|
+
await this.verifyAvmProof(proofAndVk.proof.binaryProof, proofAndVk.verificationKey, inputs.publicInputs);
|
|
193
|
+
|
|
194
|
+
// TODO(#14234)[Unconditional PIs validation]: remove next lines and directly return proofAndVk
|
|
195
|
+
proofAndVk.proof.proof = enhanceProofWithPiValidationFlag(proofAndVk.proof.proof, skipPublicInputsValidation);
|
|
191
196
|
return proofAndVk;
|
|
192
197
|
}
|
|
193
198
|
|
|
@@ -536,13 +541,13 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
536
541
|
|
|
537
542
|
private async createAvmProof(
|
|
538
543
|
input: AvmCircuitInputs,
|
|
539
|
-
): Promise<ProofAndVerificationKey<typeof
|
|
544
|
+
): Promise<ProofAndVerificationKey<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
|
|
540
545
|
const operation = async (bbWorkingDirectory: string) => {
|
|
541
546
|
const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory);
|
|
542
547
|
|
|
543
548
|
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6773): this VK data format is wrong.
|
|
544
549
|
// In particular, the number of public inputs, etc will be wrong.
|
|
545
|
-
const verificationKey = await extractAvmVkData(provingResult.
|
|
550
|
+
const verificationKey = await extractAvmVkData(provingResult.vkDirectoryPath!);
|
|
546
551
|
const avmProof = await this.readAvmProofAsFields(provingResult.proofPath!, verificationKey);
|
|
547
552
|
|
|
548
553
|
const circuitType = 'avm-circuit' as const;
|
|
@@ -579,7 +584,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
579
584
|
|
|
580
585
|
// Read the proof as fields
|
|
581
586
|
// TODO(AD): this is the only remaining use of extractVkData.
|
|
582
|
-
const tubeVK = await extractVkData(provingResult.
|
|
587
|
+
const tubeVK = await extractVkData(provingResult.vkDirectoryPath!);
|
|
583
588
|
const tubeProof = await readProofAsFields(provingResult.proofPath!, tubeVK, TUBE_PROOF_LENGTH, logger);
|
|
584
589
|
|
|
585
590
|
this.instrumentation.recordDuration('provingDuration', 'tubeCircuit', provingResult.durationMs);
|
|
@@ -673,9 +678,13 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
673
678
|
return await this.verifyWithKey(getUltraHonkFlavorForCircuit(circuitType), verificationKey, proof);
|
|
674
679
|
}
|
|
675
680
|
|
|
676
|
-
public async verifyAvmProof(
|
|
681
|
+
public async verifyAvmProof(
|
|
682
|
+
proof: Proof,
|
|
683
|
+
verificationKey: VerificationKeyData,
|
|
684
|
+
publicInputs: AvmCircuitPublicInputs,
|
|
685
|
+
) {
|
|
677
686
|
return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath) =>
|
|
678
|
-
verifyAvmProof(this.config.bbBinaryPath, proofPath, vkPath, logger),
|
|
687
|
+
verifyAvmProof(this.config.bbBinaryPath, this.config.bbWorkingDirectory, proofPath, publicInputs, vkPath, logger),
|
|
679
688
|
);
|
|
680
689
|
}
|
|
681
690
|
|
|
@@ -728,16 +737,25 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
728
737
|
private async readAvmProofAsFields(
|
|
729
738
|
proofFilename: string,
|
|
730
739
|
vkData: VerificationKeyData,
|
|
731
|
-
): Promise<RecursiveProof<typeof
|
|
732
|
-
const
|
|
733
|
-
|
|
734
|
-
const
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
740
|
+
): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
|
|
741
|
+
const rawProofBuffer = await fs.readFile(proofFilename);
|
|
742
|
+
const reader = BufferReader.asReader(rawProofBuffer);
|
|
743
|
+
const proofFields = reader.readArray(rawProofBuffer.length / Fr.SIZE_IN_BYTES, Fr);
|
|
744
|
+
|
|
745
|
+
// We extend to a fixed-size padded proof as during development any new AVM circuit column changes the
|
|
746
|
+
// proof length and we do not have a mechanism to feedback a cpp constant to noir/TS.
|
|
747
|
+
// TODO(#13390): Revive a non-padded AVM proof
|
|
748
|
+
if (proofFields.length > AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED) {
|
|
749
|
+
throw new Error(
|
|
750
|
+
`Proof has ${proofFields.length} fields, expected no more than ${AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED}.`,
|
|
751
|
+
);
|
|
752
|
+
}
|
|
753
|
+
const proofFieldsPadded = proofFields.concat(
|
|
754
|
+
Array(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED - proofFields.length).fill(new Fr(0)),
|
|
755
|
+
);
|
|
739
756
|
|
|
740
|
-
|
|
757
|
+
const proof = new Proof(rawProofBuffer, vkData.numPublicInputs);
|
|
758
|
+
return new RecursiveProof(proofFieldsPadded, proof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED);
|
|
741
759
|
}
|
|
742
760
|
|
|
743
761
|
private runInDirectory<T>(fn: (dir: string) => Promise<T>) {
|