@aztec/bb-prover 0.87.3-nightly.20250528 → 0.87.3
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 +10 -3
- package/dest/avm_proving_tests/avm_proving_tester.d.ts.map +1 -1
- package/dest/avm_proving_tests/avm_proving_tester.js +62 -18
- package/dest/bb/execute.d.ts +24 -5
- package/dest/bb/execute.d.ts.map +1 -1
- package/dest/bb/execute.js +104 -16
- 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 +13 -22
- 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 +0 -6
- 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 +87 -30
- package/src/bb/execute.ts +123 -22
- package/src/prover/server/bb_prover.ts +30 -48
- package/src/test/test_circuit_prover.ts +5 -7
- package/src/verification_key/verification_key_data.ts +13 -20
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS } from '@aztec/constants';
|
|
2
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
-
import { BufferReader } from '@aztec/foundation/serialize';
|
|
4
3
|
import { hashVK } from '@aztec/stdlib/hash';
|
|
5
4
|
import { VerificationKeyAsFields, VerificationKeyData } from '@aztec/stdlib/vks';
|
|
6
5
|
import { strict as assert } from 'assert';
|
|
@@ -25,20 +24,21 @@ import { VK_FIELDS_FILENAME, VK_FILENAME } from '../bb/execute.js';
|
|
|
25
24
|
const vkAsFields = new VerificationKeyAsFields(fields, vkHash);
|
|
26
25
|
return new VerificationKeyData(vkAsFields, rawBinary);
|
|
27
26
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
27
|
+
// TODO: This was adapted from the above function. A refactor might be needed.
|
|
28
|
+
export async function extractAvmVkData(vkDirectoryPath) {
|
|
29
|
+
const [rawFields, rawBinary] = await Promise.all([
|
|
30
|
+
fs.readFile(path.join(vkDirectoryPath, VK_FIELDS_FILENAME), {
|
|
31
|
+
encoding: 'utf-8'
|
|
32
|
+
}),
|
|
33
|
+
fs.readFile(path.join(vkDirectoryPath, VK_FILENAME))
|
|
34
|
+
]);
|
|
35
|
+
const fieldsJson = JSON.parse(rawFields);
|
|
36
|
+
const fields = fieldsJson.map(Fr.fromHexString);
|
|
37
|
+
// The first item is the hash, this is not part of the actual VK
|
|
38
|
+
// TODO: is the above actually the case?
|
|
39
|
+
const vkHash = fields[0];
|
|
40
|
+
assert(fields.length === AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, 'Invalid AVM verification key length');
|
|
41
|
+
const vkAsFields = new VerificationKeyAsFields(fields, vkHash);
|
|
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
|
|
3
|
+
"version": "0.87.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -66,16 +66,16 @@
|
|
|
66
66
|
]
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"@aztec/bb.js": "0.87.3
|
|
70
|
-
"@aztec/constants": "0.87.3
|
|
71
|
-
"@aztec/foundation": "0.87.3
|
|
72
|
-
"@aztec/noir-noirc_abi": "0.87.3
|
|
73
|
-
"@aztec/noir-protocol-circuits-types": "0.87.3
|
|
74
|
-
"@aztec/noir-types": "0.87.3
|
|
75
|
-
"@aztec/simulator": "0.87.3
|
|
76
|
-
"@aztec/stdlib": "0.87.3
|
|
77
|
-
"@aztec/telemetry-client": "0.87.3
|
|
78
|
-
"@aztec/world-state": "0.87.3
|
|
69
|
+
"@aztec/bb.js": "0.87.3",
|
|
70
|
+
"@aztec/constants": "0.87.3",
|
|
71
|
+
"@aztec/foundation": "0.87.3",
|
|
72
|
+
"@aztec/noir-noirc_abi": "0.87.3",
|
|
73
|
+
"@aztec/noir-protocol-circuits-types": "0.87.3",
|
|
74
|
+
"@aztec/noir-types": "0.87.3",
|
|
75
|
+
"@aztec/simulator": "0.87.3",
|
|
76
|
+
"@aztec/stdlib": "0.87.3",
|
|
77
|
+
"@aztec/telemetry-client": "0.87.3",
|
|
78
|
+
"@aztec/world-state": "0.87.3",
|
|
79
79
|
"commander": "^12.1.0",
|
|
80
80
|
"pako": "^2.1.0",
|
|
81
81
|
"pidusage": "^4.0.1",
|
|
@@ -83,11 +83,11 @@
|
|
|
83
83
|
"tslib": "^2.4.0"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
|
-
"@aztec/ethereum": "0.87.3
|
|
87
|
-
"@aztec/kv-store": "0.87.3
|
|
88
|
-
"@aztec/noir-contracts.js": "0.87.3
|
|
89
|
-
"@aztec/noir-test-contracts.js": "0.87.3
|
|
90
|
-
"@aztec/protocol-contracts": "0.87.3
|
|
86
|
+
"@aztec/ethereum": "0.87.3",
|
|
87
|
+
"@aztec/kv-store": "0.87.3",
|
|
88
|
+
"@aztec/noir-contracts.js": "0.87.3",
|
|
89
|
+
"@aztec/noir-test-contracts.js": "0.87.3",
|
|
90
|
+
"@aztec/protocol-contracts": "0.87.3",
|
|
91
91
|
"@jest/globals": "^29.5.0",
|
|
92
92
|
"@types/jest": "^29.5.0",
|
|
93
93
|
"@types/node": "^22.15.17",
|
|
@@ -7,6 +7,7 @@ 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';
|
|
10
11
|
import { NativeWorldStateService } from '@aztec/world-state';
|
|
11
12
|
|
|
12
13
|
import fs from 'node:fs/promises';
|
|
@@ -17,10 +18,12 @@ import {
|
|
|
17
18
|
type BBResult,
|
|
18
19
|
type BBSuccess,
|
|
19
20
|
BB_RESULT,
|
|
20
|
-
VK_FILENAME,
|
|
21
21
|
generateAvmProof,
|
|
22
|
+
generateAvmProofV2,
|
|
22
23
|
verifyAvmProof,
|
|
24
|
+
verifyAvmProofV2,
|
|
23
25
|
} from '../bb/execute.js';
|
|
26
|
+
import { extractAvmVkData } from '../verification_key/verification_key_data.js';
|
|
24
27
|
|
|
25
28
|
const BB_PATH = path.resolve('../../barretenberg/cpp/build/bin/bb');
|
|
26
29
|
|
|
@@ -28,19 +31,20 @@ export class AvmProvingTester extends PublicTxSimulationTester {
|
|
|
28
31
|
constructor(
|
|
29
32
|
private bbWorkingDirectory: string,
|
|
30
33
|
private checkCircuitOnly: boolean,
|
|
34
|
+
merkleTree: MerkleTreeWriteOperations,
|
|
31
35
|
contractDataSource: SimpleContractDataSource,
|
|
32
|
-
merkleTrees: MerkleTreeWriteOperations,
|
|
33
36
|
globals?: GlobalVariables,
|
|
34
37
|
) {
|
|
35
|
-
super(
|
|
38
|
+
super(merkleTree, contractDataSource, globals);
|
|
36
39
|
}
|
|
37
40
|
|
|
41
|
+
// overriding parent class' create is a pain, so we use a different nam
|
|
38
42
|
static async new(checkCircuitOnly: boolean = false, globals?: GlobalVariables) {
|
|
39
43
|
const bbWorkingDirectory = await fs.mkdtemp(path.join(tmpdir(), 'bb-'));
|
|
40
44
|
|
|
41
45
|
const contractDataSource = new SimpleContractDataSource();
|
|
42
46
|
const merkleTrees = await (await NativeWorldStateService.tmp()).fork();
|
|
43
|
-
return new AvmProvingTester(bbWorkingDirectory, checkCircuitOnly,
|
|
47
|
+
return new AvmProvingTester(bbWorkingDirectory, checkCircuitOnly, merkleTrees, contractDataSource, globals);
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
async prove(avmCircuitInputs: AvmCircuitInputs): Promise<BBResult> {
|
|
@@ -55,36 +59,95 @@ export class AvmProvingTester extends PublicTxSimulationTester {
|
|
|
55
59
|
if (proofRes.status === BB_RESULT.FAILURE) {
|
|
56
60
|
this.logger.error(`Proof generation failed: ${proofRes.reason}`);
|
|
57
61
|
}
|
|
58
|
-
|
|
59
|
-
return proofRes as BBSuccess;
|
|
62
|
+
return proofRes;
|
|
60
63
|
}
|
|
61
64
|
|
|
62
|
-
async verify(proofRes: BBSuccess
|
|
65
|
+
async verify(proofRes: BBSuccess): Promise<BBResult> {
|
|
63
66
|
if (this.checkCircuitOnly) {
|
|
64
|
-
// Skip verification if we
|
|
65
|
-
// Check-circuit
|
|
67
|
+
// Skip verification if we're only checking the circuit.
|
|
68
|
+
// Check-circuit doesn't generate a proof to verify.
|
|
66
69
|
return proofRes;
|
|
67
70
|
}
|
|
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());
|
|
68
75
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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);
|
|
77
96
|
}
|
|
78
97
|
|
|
79
|
-
public async
|
|
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;
|
|
80
103
|
const provingRes = await this.prove(avmCircuitInputs);
|
|
81
104
|
expect(provingRes.status).toEqual(BB_RESULT.SUCCESS);
|
|
82
105
|
|
|
83
|
-
const verificationRes = await this.verify(provingRes as BBSuccess
|
|
106
|
+
const verificationRes = await this.verify(provingRes as BBSuccess);
|
|
84
107
|
expect(verificationRes.status).toBe(BB_RESULT.SUCCESS);
|
|
85
108
|
}
|
|
109
|
+
}
|
|
86
110
|
|
|
87
|
-
|
|
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
|
+
|
|
139
|
+
async verifyV2(proofRes: BBSuccess, publicInputs: AvmCircuitPublicInputs): Promise<BBResult> {
|
|
140
|
+
return await verifyAvmProofV2(
|
|
141
|
+
BB_PATH,
|
|
142
|
+
this.bbWorkingDirectory,
|
|
143
|
+
proofRes.proofPath!,
|
|
144
|
+
publicInputs,
|
|
145
|
+
proofRes.vkPath!,
|
|
146
|
+
this.logger,
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
public async simProveVerifyV2(
|
|
88
151
|
sender: AztecAddress,
|
|
89
152
|
setupCalls: TestEnqueuedCall[],
|
|
90
153
|
appCalls: TestEnqueuedCall[],
|
|
@@ -96,16 +159,10 @@ export class AvmProvingTester extends PublicTxSimulationTester {
|
|
|
96
159
|
expect(simRes.revertCode.isOK()).toBe(expectRevert ? false : true);
|
|
97
160
|
|
|
98
161
|
const avmCircuitInputs = simRes.avmProvingRequest.inputs;
|
|
99
|
-
await this.
|
|
100
|
-
|
|
162
|
+
const provingRes = await this.proveV2(avmCircuitInputs);
|
|
163
|
+
expect(provingRes.status).toEqual(BB_RESULT.SUCCESS);
|
|
101
164
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
/*sender=*/ AztecAddress.fromNumber(42),
|
|
105
|
-
/*setupCalls=*/ [],
|
|
106
|
-
[appCall],
|
|
107
|
-
undefined,
|
|
108
|
-
expectRevert,
|
|
109
|
-
);
|
|
165
|
+
const verificationRes = await this.verifyV2(provingRes as BBSuccess, avmCircuitInputs.publicInputs);
|
|
166
|
+
expect(verificationRes.status).toBe(BB_RESULT.SUCCESS);
|
|
110
167
|
}
|
|
111
168
|
}
|
package/src/bb/execute.ts
CHANGED
|
@@ -33,7 +33,7 @@ export type BBSuccess = {
|
|
|
33
33
|
/** Full path of the public key. */
|
|
34
34
|
pkPath?: string;
|
|
35
35
|
/** Base directory for the VKs (raw, fields). */
|
|
36
|
-
|
|
36
|
+
vkPath?: string;
|
|
37
37
|
/** Full path of the proof. */
|
|
38
38
|
proofPath?: string;
|
|
39
39
|
/** Full path of the contract. */
|
|
@@ -50,6 +50,8 @@ export type BBFailure = {
|
|
|
50
50
|
|
|
51
51
|
export type BBResult = BBSuccess | BBFailure;
|
|
52
52
|
|
|
53
|
+
export type VerificationFunction = typeof verifyProof | typeof verifyAvmProof;
|
|
54
|
+
|
|
53
55
|
type BBExecResult = {
|
|
54
56
|
status: BB_RESULT;
|
|
55
57
|
exitCode: number;
|
|
@@ -173,7 +175,7 @@ export async function executeBbClientIvcProof(
|
|
|
173
175
|
durationMs,
|
|
174
176
|
proofPath: `${outputPath}`,
|
|
175
177
|
pkPath: undefined,
|
|
176
|
-
|
|
178
|
+
vkPath: `${outputPath}`,
|
|
177
179
|
};
|
|
178
180
|
}
|
|
179
181
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
@@ -277,7 +279,7 @@ export async function generateProof(
|
|
|
277
279
|
durationMs: duration,
|
|
278
280
|
proofPath: `${outputPath}`,
|
|
279
281
|
pkPath: undefined,
|
|
280
|
-
|
|
282
|
+
vkPath: `${outputPath}`,
|
|
281
283
|
};
|
|
282
284
|
}
|
|
283
285
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
@@ -345,7 +347,7 @@ export async function generateTubeProof(
|
|
|
345
347
|
durationMs,
|
|
346
348
|
proofPath: outputPath,
|
|
347
349
|
pkPath: undefined,
|
|
348
|
-
|
|
350
|
+
vkPath: outputPath,
|
|
349
351
|
};
|
|
350
352
|
}
|
|
351
353
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
@@ -365,16 +367,14 @@ export async function generateTubeProof(
|
|
|
365
367
|
* @param pathToBB - The full path to the bb binary
|
|
366
368
|
* @param workingDirectory - A working directory for use by bb
|
|
367
369
|
* @param input - The inputs for the public function to be proven
|
|
368
|
-
* @param
|
|
369
|
-
* @param checkCircuitOnly - A boolean to toggle a "check-circuit only" operation instead of proving.
|
|
370
|
+
* @param log - A logging function
|
|
370
371
|
* @returns An object containing a result indication, the location of the proof and the duration taken
|
|
371
372
|
*/
|
|
372
|
-
export async function
|
|
373
|
+
export async function generateAvmProofV2(
|
|
373
374
|
pathToBB: string,
|
|
374
375
|
workingDirectory: string,
|
|
375
376
|
input: AvmCircuitInputs,
|
|
376
377
|
logger: Logger,
|
|
377
|
-
checkCircuitOnly: boolean = false,
|
|
378
378
|
): Promise<BBFailure | BBSuccess> {
|
|
379
379
|
// Check that the working directory exists
|
|
380
380
|
try {
|
|
@@ -414,12 +414,99 @@ export async function generateAvmProof(
|
|
|
414
414
|
args.push(loggingArg);
|
|
415
415
|
}
|
|
416
416
|
const timer = new Timer();
|
|
417
|
+
const logFunction = (message: string) => {
|
|
418
|
+
logger.verbose(`AvmCircuit (prove) BB out - ${message}`);
|
|
419
|
+
};
|
|
420
|
+
const result = await executeBB(pathToBB, 'avm2_prove', args, logFunction);
|
|
421
|
+
const duration = timer.ms();
|
|
417
422
|
|
|
418
|
-
|
|
423
|
+
if (result.status == BB_RESULT.SUCCESS) {
|
|
424
|
+
return {
|
|
425
|
+
status: BB_RESULT.SUCCESS,
|
|
426
|
+
durationMs: duration,
|
|
427
|
+
proofPath: join(outputPath, PROOF_FILENAME),
|
|
428
|
+
pkPath: undefined,
|
|
429
|
+
vkPath: join(outputPath, VK_FILENAME),
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
433
|
+
return {
|
|
434
|
+
status: BB_RESULT.FAILURE,
|
|
435
|
+
reason: `Failed to generate proof. Exit code ${result.exitCode}. Signal ${result.signal}.`,
|
|
436
|
+
retry: !!result.signal,
|
|
437
|
+
};
|
|
438
|
+
} catch (error) {
|
|
439
|
+
return { status: BB_RESULT.FAILURE, reason: `${error}` };
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Used for generating AVM proofs (or doing check-circuit).
|
|
445
|
+
* It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof.
|
|
446
|
+
* @param pathToBB - The full path to the bb binary
|
|
447
|
+
* @param workingDirectory - A working directory for use by bb
|
|
448
|
+
* @param bytecode - The AVM bytecode for the public function to be proven (expected to be decompressed)
|
|
449
|
+
* @param log - A logging function
|
|
450
|
+
* @returns An object containing a result indication, the location of the proof and the duration taken
|
|
451
|
+
*/
|
|
452
|
+
export async function generateAvmProof(
|
|
453
|
+
pathToBB: string,
|
|
454
|
+
workingDirectory: string,
|
|
455
|
+
_input: AvmCircuitInputs,
|
|
456
|
+
logger: Logger,
|
|
457
|
+
checkCircuitOnly: boolean = false,
|
|
458
|
+
): Promise<BBFailure | BBSuccess> {
|
|
459
|
+
// Check that the working directory exists
|
|
460
|
+
try {
|
|
461
|
+
await fs.access(workingDirectory);
|
|
462
|
+
} catch {
|
|
463
|
+
return { status: BB_RESULT.FAILURE, reason: `Working directory ${workingDirectory} does not exist` };
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Paths for the inputs
|
|
467
|
+
const publicInputsPath = join(workingDirectory, AVM_PUBLIC_INPUTS_FILENAME);
|
|
468
|
+
|
|
469
|
+
// The proof is written to e.g. /workingDirectory/proof
|
|
470
|
+
const outputPath = workingDirectory;
|
|
471
|
+
|
|
472
|
+
const filePresent = async (file: string) =>
|
|
473
|
+
await fs
|
|
474
|
+
.access(file, fs.constants.R_OK)
|
|
475
|
+
.then(_ => true)
|
|
476
|
+
.catch(_ => false);
|
|
477
|
+
|
|
478
|
+
const binaryPresent = await filePresent(pathToBB);
|
|
479
|
+
if (!binaryPresent) {
|
|
480
|
+
return { status: BB_RESULT.FAILURE, reason: `Failed to find bb binary at ${pathToBB}` };
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
try {
|
|
484
|
+
// Write the inputs to the working directory.
|
|
485
|
+
|
|
486
|
+
// WARNING: Not writing the inputs since VM1 is disabled!
|
|
487
|
+
// await fs.writeFile(publicInputsPath, input.publicInputs.toBuffer());
|
|
488
|
+
// if (!(await filePresent(publicInputsPath))) {
|
|
489
|
+
// return { status: BB_RESULT.FAILURE, reason: `Could not write publicInputs at ${publicInputsPath}` };
|
|
490
|
+
// }
|
|
491
|
+
|
|
492
|
+
// await fs.writeFile(avmHintsPath, input.avmHints.toBuffer());
|
|
493
|
+
// if (!(await filePresent(avmHintsPath))) {
|
|
494
|
+
// return { status: BB_RESULT.FAILURE, reason: `Could not write avmHints at ${avmHintsPath}` };
|
|
495
|
+
// }
|
|
496
|
+
|
|
497
|
+
const args = ['--avm-public-inputs', publicInputsPath, '-o', outputPath];
|
|
498
|
+
const loggingArg =
|
|
499
|
+
logger.level === 'debug' || logger.level === 'trace' ? '-d' : logger.level === 'verbose' ? '-v' : '';
|
|
500
|
+
if (loggingArg !== '') {
|
|
501
|
+
args.push(loggingArg);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const timer = new Timer();
|
|
505
|
+
const cmd = checkCircuitOnly ? 'check_circuit' : 'prove';
|
|
419
506
|
const logFunction = (message: string) => {
|
|
420
507
|
logger.verbose(`AvmCircuit (${cmd}) BB out - ${message}`);
|
|
421
508
|
};
|
|
422
|
-
const result = await executeBB(pathToBB, cmd
|
|
509
|
+
const result = await executeBB(pathToBB, `avm_${cmd}`, args, logFunction);
|
|
423
510
|
const duration = timer.ms();
|
|
424
511
|
|
|
425
512
|
if (result.status == BB_RESULT.SUCCESS) {
|
|
@@ -428,7 +515,7 @@ export async function generateAvmProof(
|
|
|
428
515
|
durationMs: duration,
|
|
429
516
|
proofPath: join(outputPath, PROOF_FILENAME),
|
|
430
517
|
pkPath: undefined,
|
|
431
|
-
|
|
518
|
+
vkPath: outputPath,
|
|
432
519
|
};
|
|
433
520
|
}
|
|
434
521
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
@@ -467,7 +554,24 @@ export async function verifyProof(
|
|
|
467
554
|
);
|
|
468
555
|
}
|
|
469
556
|
|
|
557
|
+
/**
|
|
558
|
+
* Used for verifying proofs of the AVM
|
|
559
|
+
* @param pathToBB - The full path to the bb binary
|
|
560
|
+
* @param proofFullPath - The full path to the proof to be verified
|
|
561
|
+
* @param verificationKeyPath - The full path to the circuit verification key
|
|
562
|
+
* @param log - A logging function
|
|
563
|
+
* @returns An object containing a result indication and duration taken
|
|
564
|
+
*/
|
|
470
565
|
export async function verifyAvmProof(
|
|
566
|
+
pathToBB: string,
|
|
567
|
+
proofFullPath: string,
|
|
568
|
+
verificationKeyPath: string,
|
|
569
|
+
logger: Logger,
|
|
570
|
+
): Promise<BBFailure | BBSuccess> {
|
|
571
|
+
return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'avm_verify', logger);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export async function verifyAvmProofV2(
|
|
471
575
|
pathToBB: string,
|
|
472
576
|
workingDirectory: string,
|
|
473
577
|
proofFullPath: string,
|
|
@@ -489,7 +593,7 @@ export async function verifyAvmProof(
|
|
|
489
593
|
return { status: BB_RESULT.FAILURE, reason: `Could not write avm inputs to ${avmInputsPath}` };
|
|
490
594
|
}
|
|
491
595
|
|
|
492
|
-
return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, '
|
|
596
|
+
return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'avm2_verify', logger, [
|
|
493
597
|
'--avm-public-inputs',
|
|
494
598
|
avmInputsPath,
|
|
495
599
|
]);
|
|
@@ -550,7 +654,7 @@ async function verifyProofInternal(
|
|
|
550
654
|
pathToBB: string,
|
|
551
655
|
proofFullPath: string,
|
|
552
656
|
verificationKeyPath: string,
|
|
553
|
-
command: 'verify' | 'avm_verify',
|
|
657
|
+
command: 'verify' | 'avm_verify' | 'avm2_verify',
|
|
554
658
|
logger: Logger,
|
|
555
659
|
extraArgs: string[] = [],
|
|
556
660
|
): Promise<BBFailure | BBSuccess> {
|
|
@@ -566,27 +670,24 @@ async function verifyProofInternal(
|
|
|
566
670
|
logger.verbose(`bb-prover (verify) BB out - ${message}`);
|
|
567
671
|
};
|
|
568
672
|
|
|
673
|
+
// take proofFullPath and remove the suffix past the / to get the directory
|
|
674
|
+
const proofDir = proofFullPath.substring(0, proofFullPath.lastIndexOf('/'));
|
|
675
|
+
const publicInputsFullPath = join(proofDir, '/public_inputs');
|
|
676
|
+
|
|
677
|
+
logger.debug(`public inputs path: ${publicInputsFullPath}`);
|
|
569
678
|
try {
|
|
570
679
|
let args;
|
|
571
|
-
|
|
680
|
+
// Specify the public inputs path in the case of UH verification.
|
|
572
681
|
if (command == 'verify') {
|
|
573
|
-
// Specify the public inputs path in the case of UH verification.
|
|
574
|
-
// Take proofFullPath and remove the suffix past the / to get the directory.
|
|
575
|
-
const proofDir = proofFullPath.substring(0, proofFullPath.lastIndexOf('/'));
|
|
576
|
-
const publicInputsFullPath = join(proofDir, '/public_inputs');
|
|
577
|
-
logger.debug(`public inputs path: ${publicInputsFullPath}`);
|
|
578
|
-
|
|
579
682
|
args = ['-p', proofFullPath, '-k', verificationKeyPath, '-i', publicInputsFullPath, ...extraArgs];
|
|
580
683
|
} else {
|
|
581
684
|
args = ['-p', proofFullPath, '-k', verificationKeyPath, ...extraArgs];
|
|
582
685
|
}
|
|
583
|
-
|
|
584
686
|
const loggingArg =
|
|
585
687
|
logger.level === 'debug' || logger.level === 'trace' ? '-d' : logger.level === 'verbose' ? '-v' : '';
|
|
586
688
|
if (loggingArg !== '') {
|
|
587
689
|
args.push(loggingArg);
|
|
588
690
|
}
|
|
589
|
-
|
|
590
691
|
const timer = new Timer();
|
|
591
692
|
const result = await executeBB(pathToBB, command, args, logFunction);
|
|
592
693
|
const duration = timer.ms();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
AVM_PROOF_LENGTH_IN_FIELDS,
|
|
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
|
|
40
|
+
import type { AvmCircuitInputs } from '@aztec/stdlib/avm';
|
|
41
41
|
import { ProvingError } from '@aztec/stdlib/errors';
|
|
42
42
|
import {
|
|
43
43
|
type ProofAndVerificationKey,
|
|
@@ -48,20 +48,19 @@ 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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
import type {
|
|
52
|
+
BaseOrMergeRollupPublicInputs,
|
|
53
|
+
BlockMergeRollupInputs,
|
|
54
|
+
BlockRootOrBlockMergePublicInputs,
|
|
55
|
+
BlockRootRollupInputs,
|
|
56
|
+
EmptyBlockRootRollupInputs,
|
|
57
|
+
MergeRollupInputs,
|
|
58
|
+
PrivateBaseRollupInputs,
|
|
59
59
|
PublicBaseRollupInputs,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
enhanceProofWithPiValidationFlag,
|
|
60
|
+
RootRollupInputs,
|
|
61
|
+
RootRollupPublicInputs,
|
|
62
|
+
SingleTxBlockRootRollupInputs,
|
|
63
|
+
TubeInputs,
|
|
65
64
|
} from '@aztec/stdlib/rollup';
|
|
66
65
|
import type { CircuitProvingStats, CircuitWitnessGenerationStats } from '@aztec/stdlib/stats';
|
|
67
66
|
import type { VerificationKeyData } from '@aztec/stdlib/vks';
|
|
@@ -186,13 +185,9 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
186
185
|
}))
|
|
187
186
|
public async getAvmProof(
|
|
188
187
|
inputs: AvmCircuitInputs,
|
|
189
|
-
|
|
190
|
-
): Promise<ProofAndVerificationKey<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
|
|
188
|
+
): Promise<ProofAndVerificationKey<typeof AVM_PROOF_LENGTH_IN_FIELDS>> {
|
|
191
189
|
const proofAndVk = await this.createAvmProof(inputs);
|
|
192
|
-
await this.verifyAvmProof(proofAndVk.proof.binaryProof, proofAndVk.verificationKey
|
|
193
|
-
|
|
194
|
-
// TODO(#14234)[Unconditional PIs validation]: remove next lines and directly return proofAndVk
|
|
195
|
-
proofAndVk.proof.proof = enhanceProofWithPiValidationFlag(proofAndVk.proof.proof, skipPublicInputsValidation);
|
|
190
|
+
await this.verifyAvmProof(proofAndVk.proof.binaryProof, proofAndVk.verificationKey);
|
|
196
191
|
return proofAndVk;
|
|
197
192
|
}
|
|
198
193
|
|
|
@@ -541,13 +536,13 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
541
536
|
|
|
542
537
|
private async createAvmProof(
|
|
543
538
|
input: AvmCircuitInputs,
|
|
544
|
-
): Promise<ProofAndVerificationKey<typeof
|
|
539
|
+
): Promise<ProofAndVerificationKey<typeof AVM_PROOF_LENGTH_IN_FIELDS>> {
|
|
545
540
|
const operation = async (bbWorkingDirectory: string) => {
|
|
546
541
|
const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory);
|
|
547
542
|
|
|
548
543
|
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6773): this VK data format is wrong.
|
|
549
544
|
// In particular, the number of public inputs, etc will be wrong.
|
|
550
|
-
const verificationKey = await extractAvmVkData(provingResult.
|
|
545
|
+
const verificationKey = await extractAvmVkData(provingResult.vkPath!);
|
|
551
546
|
const avmProof = await this.readAvmProofAsFields(provingResult.proofPath!, verificationKey);
|
|
552
547
|
|
|
553
548
|
const circuitType = 'avm-circuit' as const;
|
|
@@ -584,7 +579,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
584
579
|
|
|
585
580
|
// Read the proof as fields
|
|
586
581
|
// TODO(AD): this is the only remaining use of extractVkData.
|
|
587
|
-
const tubeVK = await extractVkData(provingResult.
|
|
582
|
+
const tubeVK = await extractVkData(provingResult.vkPath!);
|
|
588
583
|
const tubeProof = await readProofAsFields(provingResult.proofPath!, tubeVK, TUBE_PROOF_LENGTH, logger);
|
|
589
584
|
|
|
590
585
|
this.instrumentation.recordDuration('provingDuration', 'tubeCircuit', provingResult.durationMs);
|
|
@@ -678,13 +673,9 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
678
673
|
return await this.verifyWithKey(getUltraHonkFlavorForCircuit(circuitType), verificationKey, proof);
|
|
679
674
|
}
|
|
680
675
|
|
|
681
|
-
public async verifyAvmProof(
|
|
682
|
-
proof: Proof,
|
|
683
|
-
verificationKey: VerificationKeyData,
|
|
684
|
-
publicInputs: AvmCircuitPublicInputs,
|
|
685
|
-
) {
|
|
676
|
+
public async verifyAvmProof(proof: Proof, verificationKey: VerificationKeyData) {
|
|
686
677
|
return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath) =>
|
|
687
|
-
verifyAvmProof(this.config.bbBinaryPath,
|
|
678
|
+
verifyAvmProof(this.config.bbBinaryPath, proofPath, vkPath, logger),
|
|
688
679
|
);
|
|
689
680
|
}
|
|
690
681
|
|
|
@@ -737,25 +728,16 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
737
728
|
private async readAvmProofAsFields(
|
|
738
729
|
proofFilename: string,
|
|
739
730
|
vkData: VerificationKeyData,
|
|
740
|
-
): Promise<RecursiveProof<typeof
|
|
741
|
-
const
|
|
742
|
-
|
|
743
|
-
const
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
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
|
-
);
|
|
731
|
+
): Promise<RecursiveProof<typeof AVM_PROOF_LENGTH_IN_FIELDS>> {
|
|
732
|
+
const rawProof = await fs.readFile(proofFilename);
|
|
733
|
+
|
|
734
|
+
const reader = BufferReader.asReader(rawProof);
|
|
735
|
+
const fields = reader.readArray(rawProof.length / Fr.SIZE_IN_BYTES, Fr);
|
|
736
|
+
const fieldsWithoutPublicCols = fields.slice(-1 * AVM_PROOF_LENGTH_IN_FIELDS);
|
|
737
|
+
|
|
738
|
+
const proof = new Proof(rawProof, vkData.numPublicInputs);
|
|
756
739
|
|
|
757
|
-
|
|
758
|
-
return new RecursiveProof(proofFieldsPadded, proof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED);
|
|
740
|
+
return new RecursiveProof(fieldsWithoutPublicCols, proof, true, AVM_PROOF_LENGTH_IN_FIELDS);
|
|
759
741
|
}
|
|
760
742
|
|
|
761
743
|
private runInDirectory<T>(fn: (dir: string) => Promise<T>) {
|