@aztec/bb-prover 0.87.1 → 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
|
@@ -7,19 +7,12 @@ import { type BBResult, type BBSuccess } from '../bb/execute.js';
|
|
|
7
7
|
export declare class AvmProvingTester extends PublicTxSimulationTester {
|
|
8
8
|
private bbWorkingDirectory;
|
|
9
9
|
private checkCircuitOnly;
|
|
10
|
-
constructor(bbWorkingDirectory: string, checkCircuitOnly: boolean,
|
|
10
|
+
constructor(bbWorkingDirectory: string, checkCircuitOnly: boolean, contractDataSource: SimpleContractDataSource, merkleTrees: MerkleTreeWriteOperations, globals?: GlobalVariables);
|
|
11
11
|
static new(checkCircuitOnly?: boolean, globals?: GlobalVariables): Promise<AvmProvingTester>;
|
|
12
12
|
prove(avmCircuitInputs: AvmCircuitInputs): Promise<BBResult>;
|
|
13
|
-
verify(proofRes: BBSuccess): Promise<BBResult>;
|
|
13
|
+
verify(proofRes: BBSuccess, publicInputs: AvmCircuitPublicInputs): Promise<BBResult>;
|
|
14
|
+
proveVerify(avmCircuitInputs: AvmCircuitInputs): Promise<void>;
|
|
14
15
|
simProveVerify(sender: AztecAddress, setupCalls: TestEnqueuedCall[], appCalls: TestEnqueuedCall[], teardownCall: TestEnqueuedCall | undefined, expectRevert: boolean | undefined, feePayer?: AztecAddress): Promise<void>;
|
|
15
16
|
simProveVerifyAppLogic(appCall: TestEnqueuedCall, expectRevert?: boolean): Promise<void>;
|
|
16
17
|
}
|
|
17
|
-
export declare class AvmProvingTesterV2 extends PublicTxSimulationTester {
|
|
18
|
-
private bbWorkingDirectory;
|
|
19
|
-
constructor(bbWorkingDirectory: string, contractDataSource: SimpleContractDataSource, merkleTrees: MerkleTreeWriteOperations, globals?: GlobalVariables);
|
|
20
|
-
static new(globals?: GlobalVariables): Promise<AvmProvingTesterV2>;
|
|
21
|
-
proveV2(avmCircuitInputs: AvmCircuitInputs): Promise<BBResult>;
|
|
22
|
-
verifyV2(proofRes: BBSuccess, publicInputs: AvmCircuitPublicInputs): Promise<BBResult>;
|
|
23
|
-
simProveVerifyV2(sender: AztecAddress, setupCalls: TestEnqueuedCall[], appCalls: TestEnqueuedCall[], teardownCall: TestEnqueuedCall | undefined, expectRevert: boolean | undefined, feePayer?: AztecAddress): Promise<void>;
|
|
24
|
-
}
|
|
25
18
|
//# sourceMappingURL=avm_proving_tester.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"avm_proving_tester.d.ts","sourceRoot":"","sources":["../../src/avm_proving_tests/avm_proving_tester.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,gBAAgB,EACtB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,KAAK,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"avm_proving_tester.d.ts","sourceRoot":"","sources":["../../src/avm_proving_tests/avm_proving_tester.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,gBAAgB,EACtB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,KAAK,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAOxD,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,SAAS,EAKf,MAAM,kBAAkB,CAAC;AAI1B,qBAAa,gBAAiB,SAAQ,wBAAwB;IAE1D,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,gBAAgB;gBADhB,kBAAkB,EAAE,MAAM,EAC1B,gBAAgB,EAAE,OAAO,EACjC,kBAAkB,EAAE,wBAAwB,EAC5C,WAAW,EAAE,yBAAyB,EACtC,OAAO,CAAC,EAAE,eAAe;WAKd,GAAG,CAAC,gBAAgB,GAAE,OAAe,EAAE,OAAO,CAAC,EAAE,eAAe;IAQvE,KAAK,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAgB5D,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,sBAAsB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAiB7E,WAAW,CAAC,gBAAgB,EAAE,gBAAgB;IAQ9C,cAAc,CACzB,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,gBAAgB,EAAE,EAC9B,QAAQ,EAAE,gBAAgB,EAAE,EAC5B,YAAY,EAAE,gBAAgB,GAAG,SAAS,EAC1C,YAAY,EAAE,OAAO,GAAG,SAAS,EACjC,QAAQ,eAAS;IASN,sBAAsB,CAAC,OAAO,EAAE,gBAAgB,EAAE,YAAY,CAAC,EAAE,OAAO;CAStF"}
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
import { PublicTxSimulationTester, SimpleContractDataSource } from '@aztec/simulator/public/fixtures';
|
|
2
2
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
3
|
-
import { VerificationKeyData } from '@aztec/stdlib/vks';
|
|
4
3
|
import { NativeWorldStateService } from '@aztec/world-state';
|
|
5
4
|
import fs from 'node:fs/promises';
|
|
6
5
|
import { tmpdir } from 'node:os';
|
|
7
6
|
import path from 'path';
|
|
8
|
-
import { BB_RESULT,
|
|
9
|
-
import { extractAvmVkData } from '../verification_key/verification_key_data.js';
|
|
7
|
+
import { BB_RESULT, VK_FILENAME, generateAvmProof, verifyAvmProof } from '../bb/execute.js';
|
|
10
8
|
const BB_PATH = path.resolve('../../barretenberg/cpp/build/bin/bb');
|
|
11
9
|
export class AvmProvingTester extends PublicTxSimulationTester {
|
|
12
10
|
bbWorkingDirectory;
|
|
13
11
|
checkCircuitOnly;
|
|
14
|
-
constructor(bbWorkingDirectory, checkCircuitOnly,
|
|
15
|
-
super(
|
|
12
|
+
constructor(bbWorkingDirectory, checkCircuitOnly, contractDataSource, merkleTrees, globals){
|
|
13
|
+
super(merkleTrees, contractDataSource, globals), this.bbWorkingDirectory = bbWorkingDirectory, this.checkCircuitOnly = checkCircuitOnly;
|
|
16
14
|
}
|
|
17
|
-
// overriding parent class' create is a pain, so we use a different nam
|
|
18
15
|
static async new(checkCircuitOnly = false, globals) {
|
|
19
16
|
const bbWorkingDirectory = await fs.mkdtemp(path.join(tmpdir(), 'bb-'));
|
|
20
17
|
const contractDataSource = new SimpleContractDataSource();
|
|
21
18
|
const merkleTrees = await (await NativeWorldStateService.tmp()).fork();
|
|
22
|
-
return new AvmProvingTester(bbWorkingDirectory, checkCircuitOnly,
|
|
19
|
+
return new AvmProvingTester(bbWorkingDirectory, checkCircuitOnly, contractDataSource, merkleTrees, globals);
|
|
23
20
|
}
|
|
24
21
|
async prove(avmCircuitInputs) {
|
|
25
22
|
// Then we prove.
|
|
@@ -27,73 +24,32 @@ export class AvmProvingTester extends PublicTxSimulationTester {
|
|
|
27
24
|
if (proofRes.status === BB_RESULT.FAILURE) {
|
|
28
25
|
this.logger.error(`Proof generation failed: ${proofRes.reason}`);
|
|
29
26
|
}
|
|
27
|
+
expect(proofRes.status).toEqual(BB_RESULT.SUCCESS);
|
|
30
28
|
return proofRes;
|
|
31
29
|
}
|
|
32
|
-
async verify(proofRes) {
|
|
30
|
+
async verify(proofRes, publicInputs) {
|
|
33
31
|
if (this.checkCircuitOnly) {
|
|
34
|
-
// Skip verification if we
|
|
35
|
-
// Check-circuit
|
|
32
|
+
// Skip verification if we are only checking the circuit.
|
|
33
|
+
// Check-circuit does not generate a proof to verify.
|
|
36
34
|
return proofRes;
|
|
37
35
|
}
|
|
38
|
-
|
|
39
|
-
const succeededRes = proofRes;
|
|
40
|
-
const vkData = await extractAvmVkData(succeededRes.vkPath);
|
|
41
|
-
VerificationKeyData.fromBuffer(vkData.toBuffer());
|
|
42
|
-
// Then we verify.
|
|
43
|
-
const rawVkPath = path.join(succeededRes.vkPath, 'vk');
|
|
44
|
-
return await verifyAvmProof(BB_PATH, succeededRes.proofPath, rawVkPath, this.logger);
|
|
36
|
+
return await verifyAvmProof(BB_PATH, this.bbWorkingDirectory, proofRes.proofPath, publicInputs, path.join(proofRes.vkDirectoryPath, VK_FILENAME), this.logger);
|
|
45
37
|
}
|
|
46
|
-
async
|
|
47
|
-
const simRes = await this.simulateTx(sender, setupCalls, appCalls, teardownCall, feePayer);
|
|
48
|
-
expect(simRes.revertCode.isOK()).toBe(expectRevert ? false : true);
|
|
49
|
-
const avmCircuitInputs = simRes.avmProvingRequest.inputs;
|
|
38
|
+
async proveVerify(avmCircuitInputs) {
|
|
50
39
|
const provingRes = await this.prove(avmCircuitInputs);
|
|
51
40
|
expect(provingRes.status).toEqual(BB_RESULT.SUCCESS);
|
|
52
|
-
const verificationRes = await this.verify(provingRes);
|
|
41
|
+
const verificationRes = await this.verify(provingRes, avmCircuitInputs.publicInputs);
|
|
53
42
|
expect(verificationRes.status).toBe(BB_RESULT.SUCCESS);
|
|
54
43
|
}
|
|
55
|
-
async
|
|
56
|
-
const simRes = await this.simulateTx(/*sender=*/ AztecAddress.fromNumber(42), /*setupCalls=*/ [], [
|
|
57
|
-
appCall
|
|
58
|
-
]);
|
|
59
|
-
expect(simRes.revertCode.isOK()).toBe(expectRevert ? false : true);
|
|
60
|
-
const avmCircuitInputs = simRes.avmProvingRequest.inputs;
|
|
61
|
-
const provingRes = await this.prove(avmCircuitInputs);
|
|
62
|
-
expect(provingRes.status).toEqual(BB_RESULT.SUCCESS);
|
|
63
|
-
const verificationRes = await this.verify(provingRes);
|
|
64
|
-
expect(verificationRes.status).toBe(BB_RESULT.SUCCESS);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
export class AvmProvingTesterV2 extends PublicTxSimulationTester {
|
|
68
|
-
bbWorkingDirectory;
|
|
69
|
-
constructor(bbWorkingDirectory, contractDataSource, merkleTrees, globals){
|
|
70
|
-
super(merkleTrees, contractDataSource, globals), this.bbWorkingDirectory = bbWorkingDirectory;
|
|
71
|
-
}
|
|
72
|
-
static async new(globals) {
|
|
73
|
-
const bbWorkingDirectory = await fs.mkdtemp(path.join(tmpdir(), 'bb-'));
|
|
74
|
-
const contractDataSource = new SimpleContractDataSource();
|
|
75
|
-
const merkleTrees = await (await NativeWorldStateService.tmp()).fork();
|
|
76
|
-
return new AvmProvingTesterV2(bbWorkingDirectory, contractDataSource, merkleTrees, globals);
|
|
77
|
-
}
|
|
78
|
-
async proveV2(avmCircuitInputs) {
|
|
79
|
-
// Then we prove.
|
|
80
|
-
const proofRes = await generateAvmProofV2(BB_PATH, this.bbWorkingDirectory, avmCircuitInputs, this.logger);
|
|
81
|
-
if (proofRes.status === BB_RESULT.FAILURE) {
|
|
82
|
-
this.logger.error(`Proof generation failed: ${proofRes.reason}`);
|
|
83
|
-
}
|
|
84
|
-
expect(proofRes.status).toEqual(BB_RESULT.SUCCESS);
|
|
85
|
-
return proofRes;
|
|
86
|
-
}
|
|
87
|
-
async verifyV2(proofRes, publicInputs) {
|
|
88
|
-
return await verifyAvmProofV2(BB_PATH, this.bbWorkingDirectory, proofRes.proofPath, publicInputs, proofRes.vkPath, this.logger);
|
|
89
|
-
}
|
|
90
|
-
async simProveVerifyV2(sender, setupCalls, appCalls, teardownCall, expectRevert, feePayer = sender) {
|
|
44
|
+
async simProveVerify(sender, setupCalls, appCalls, teardownCall, expectRevert, feePayer = sender) {
|
|
91
45
|
const simRes = await this.simulateTx(sender, setupCalls, appCalls, teardownCall, feePayer);
|
|
92
46
|
expect(simRes.revertCode.isOK()).toBe(expectRevert ? false : true);
|
|
93
47
|
const avmCircuitInputs = simRes.avmProvingRequest.inputs;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
48
|
+
await this.proveVerify(avmCircuitInputs);
|
|
49
|
+
}
|
|
50
|
+
async simProveVerifyAppLogic(appCall, expectRevert) {
|
|
51
|
+
await this.simProveVerify(/*sender=*/ AztecAddress.fromNumber(42), /*setupCalls=*/ [], [
|
|
52
|
+
appCall
|
|
53
|
+
], undefined, expectRevert);
|
|
98
54
|
}
|
|
99
55
|
}
|
package/dest/bb/execute.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export type BBSuccess = {
|
|
|
22
22
|
/** Full path of the public key. */
|
|
23
23
|
pkPath?: string;
|
|
24
24
|
/** Base directory for the VKs (raw, fields). */
|
|
25
|
-
|
|
25
|
+
vkDirectoryPath?: string;
|
|
26
26
|
/** Full path of the proof. */
|
|
27
27
|
proofPath?: string;
|
|
28
28
|
/** Full path of the contract. */
|
|
@@ -36,7 +36,6 @@ export type BBFailure = {
|
|
|
36
36
|
retry?: boolean;
|
|
37
37
|
};
|
|
38
38
|
export type BBResult = BBSuccess | BBFailure;
|
|
39
|
-
export type VerificationFunction = typeof verifyProof | typeof verifyAvmProof;
|
|
40
39
|
type BBExecResult = {
|
|
41
40
|
status: BB_RESULT;
|
|
42
41
|
exitCode: number;
|
|
@@ -79,20 +78,11 @@ export declare function generateTubeProof(pathToBB: string, workingDirectory: st
|
|
|
79
78
|
* @param pathToBB - The full path to the bb binary
|
|
80
79
|
* @param workingDirectory - A working directory for use by bb
|
|
81
80
|
* @param input - The inputs for the public function to be proven
|
|
82
|
-
* @param
|
|
83
|
-
* @
|
|
84
|
-
*/
|
|
85
|
-
export declare function generateAvmProofV2(pathToBB: string, workingDirectory: string, input: AvmCircuitInputs, logger: Logger): Promise<BBFailure | BBSuccess>;
|
|
86
|
-
/**
|
|
87
|
-
* Used for generating AVM proofs (or doing check-circuit).
|
|
88
|
-
* It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof.
|
|
89
|
-
* @param pathToBB - The full path to the bb binary
|
|
90
|
-
* @param workingDirectory - A working directory for use by bb
|
|
91
|
-
* @param bytecode - The AVM bytecode for the public function to be proven (expected to be decompressed)
|
|
92
|
-
* @param log - A logging function
|
|
81
|
+
* @param logger - A logging function
|
|
82
|
+
* @param checkCircuitOnly - A boolean to toggle a "check-circuit only" operation instead of proving.
|
|
93
83
|
* @returns An object containing a result indication, the location of the proof and the duration taken
|
|
94
84
|
*/
|
|
95
|
-
export declare function generateAvmProof(pathToBB: string, workingDirectory: string,
|
|
85
|
+
export declare function generateAvmProof(pathToBB: string, workingDirectory: string, input: AvmCircuitInputs, logger: Logger, checkCircuitOnly?: boolean): Promise<BBFailure | BBSuccess>;
|
|
96
86
|
/**
|
|
97
87
|
* Used for verifying proofs of noir circuits
|
|
98
88
|
* @param pathToBB - The full path to the bb binary
|
|
@@ -102,16 +92,7 @@ export declare function generateAvmProof(pathToBB: string, workingDirectory: str
|
|
|
102
92
|
* @returns An object containing a result indication and duration taken
|
|
103
93
|
*/
|
|
104
94
|
export declare function verifyProof(pathToBB: string, proofFullPath: string, verificationKeyPath: string, ultraHonkFlavor: UltraHonkFlavor, log: Logger): Promise<BBFailure | BBSuccess>;
|
|
105
|
-
|
|
106
|
-
* Used for verifying proofs of the AVM
|
|
107
|
-
* @param pathToBB - The full path to the bb binary
|
|
108
|
-
* @param proofFullPath - The full path to the proof to be verified
|
|
109
|
-
* @param verificationKeyPath - The full path to the circuit verification key
|
|
110
|
-
* @param log - A logging function
|
|
111
|
-
* @returns An object containing a result indication and duration taken
|
|
112
|
-
*/
|
|
113
|
-
export declare function verifyAvmProof(pathToBB: string, proofFullPath: string, verificationKeyPath: string, logger: Logger): Promise<BBFailure | BBSuccess>;
|
|
114
|
-
export declare function verifyAvmProofV2(pathToBB: string, workingDirectory: string, proofFullPath: string, publicInputs: AvmCircuitPublicInputs, verificationKeyPath: string, logger: Logger): Promise<BBFailure | BBSuccess>;
|
|
95
|
+
export declare function verifyAvmProof(pathToBB: string, workingDirectory: string, proofFullPath: string, publicInputs: AvmCircuitPublicInputs, verificationKeyPath: string, logger: Logger): Promise<BBFailure | BBSuccess>;
|
|
115
96
|
/**
|
|
116
97
|
* Verifies a ClientIvcProof
|
|
117
98
|
* TODO(#7370) The verification keys should be supplied separately
|
package/dest/bb/execute.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/bb/execute.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAMlF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,eAAO,MAAM,WAAW,OAAO,CAAC;AAChC,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AACtD,eAAO,MAAM,6BAA6B,8BAA8B,CAAC;AACzE,eAAO,MAAM,cAAc,UAAU,CAAC;AACtC,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AACzD,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AACpD,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AACxD,eAAO,MAAM,0BAA0B,0BAA0B,CAAC;AAClE,eAAO,MAAM,0BAA0B,UAAU,CAAC;AAElD,oBAAY,SAAS;IACnB,OAAO,IAAA;IACP,OAAO,IAAA;IACP,eAAe,IAAA;CAChB;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE,SAAS,CAAC,OAAO,GAAG,SAAS,CAAC,eAAe,CAAC;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,
|
|
1
|
+
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/bb/execute.ts"],"names":[],"mappings":"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"}
|
package/dest/bb/execute.js
CHANGED
|
@@ -132,7 +132,7 @@ export async function executeBbClientIvcProof(pathToBB, workingDirectory, inputs
|
|
|
132
132
|
durationMs,
|
|
133
133
|
proofPath: `${outputPath}`,
|
|
134
134
|
pkPath: undefined,
|
|
135
|
-
|
|
135
|
+
vkDirectoryPath: `${outputPath}`
|
|
136
136
|
};
|
|
137
137
|
}
|
|
138
138
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
@@ -250,7 +250,7 @@ function getArgs(flavor) {
|
|
|
250
250
|
durationMs: duration,
|
|
251
251
|
proofPath: `${outputPath}`,
|
|
252
252
|
pkPath: undefined,
|
|
253
|
-
|
|
253
|
+
vkDirectoryPath: `${outputPath}`
|
|
254
254
|
};
|
|
255
255
|
}
|
|
256
256
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
@@ -319,7 +319,7 @@ function getArgs(flavor) {
|
|
|
319
319
|
durationMs,
|
|
320
320
|
proofPath: outputPath,
|
|
321
321
|
pkPath: undefined,
|
|
322
|
-
|
|
322
|
+
vkDirectoryPath: outputPath
|
|
323
323
|
};
|
|
324
324
|
}
|
|
325
325
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
@@ -341,9 +341,10 @@ function getArgs(flavor) {
|
|
|
341
341
|
* @param pathToBB - The full path to the bb binary
|
|
342
342
|
* @param workingDirectory - A working directory for use by bb
|
|
343
343
|
* @param input - The inputs for the public function to be proven
|
|
344
|
-
* @param
|
|
344
|
+
* @param logger - A logging function
|
|
345
|
+
* @param checkCircuitOnly - A boolean to toggle a "check-circuit only" operation instead of proving.
|
|
345
346
|
* @returns An object containing a result indication, the location of the proof and the duration taken
|
|
346
|
-
*/ export async function
|
|
347
|
+
*/ export async function generateAvmProof(pathToBB, workingDirectory, input, logger, checkCircuitOnly = false) {
|
|
347
348
|
// Check that the working directory exists
|
|
348
349
|
try {
|
|
349
350
|
await fs.access(workingDirectory);
|
|
@@ -385,90 +386,11 @@ function getArgs(flavor) {
|
|
|
385
386
|
args.push(loggingArg);
|
|
386
387
|
}
|
|
387
388
|
const timer = new Timer();
|
|
388
|
-
const
|
|
389
|
-
logger.verbose(`AvmCircuit (prove) BB out - ${message}`);
|
|
390
|
-
};
|
|
391
|
-
const result = await executeBB(pathToBB, 'avm2_prove', args, logFunction);
|
|
392
|
-
const duration = timer.ms();
|
|
393
|
-
if (result.status == 0) {
|
|
394
|
-
return {
|
|
395
|
-
status: 0,
|
|
396
|
-
durationMs: duration,
|
|
397
|
-
proofPath: join(outputPath, PROOF_FILENAME),
|
|
398
|
-
pkPath: undefined,
|
|
399
|
-
vkPath: join(outputPath, VK_FILENAME)
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
403
|
-
return {
|
|
404
|
-
status: 1,
|
|
405
|
-
reason: `Failed to generate proof. Exit code ${result.exitCode}. Signal ${result.signal}.`,
|
|
406
|
-
retry: !!result.signal
|
|
407
|
-
};
|
|
408
|
-
} catch (error) {
|
|
409
|
-
return {
|
|
410
|
-
status: 1,
|
|
411
|
-
reason: `${error}`
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
/**
|
|
416
|
-
* Used for generating AVM proofs (or doing check-circuit).
|
|
417
|
-
* It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof.
|
|
418
|
-
* @param pathToBB - The full path to the bb binary
|
|
419
|
-
* @param workingDirectory - A working directory for use by bb
|
|
420
|
-
* @param bytecode - The AVM bytecode for the public function to be proven (expected to be decompressed)
|
|
421
|
-
* @param log - A logging function
|
|
422
|
-
* @returns An object containing a result indication, the location of the proof and the duration taken
|
|
423
|
-
*/ export async function generateAvmProof(pathToBB, workingDirectory, _input, logger, checkCircuitOnly = false) {
|
|
424
|
-
// Check that the working directory exists
|
|
425
|
-
try {
|
|
426
|
-
await fs.access(workingDirectory);
|
|
427
|
-
} catch {
|
|
428
|
-
return {
|
|
429
|
-
status: 1,
|
|
430
|
-
reason: `Working directory ${workingDirectory} does not exist`
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
// Paths for the inputs
|
|
434
|
-
const publicInputsPath = join(workingDirectory, AVM_PUBLIC_INPUTS_FILENAME);
|
|
435
|
-
// The proof is written to e.g. /workingDirectory/proof
|
|
436
|
-
const outputPath = workingDirectory;
|
|
437
|
-
const filePresent = async (file)=>await fs.access(file, fs.constants.R_OK).then((_)=>true).catch((_)=>false);
|
|
438
|
-
const binaryPresent = await filePresent(pathToBB);
|
|
439
|
-
if (!binaryPresent) {
|
|
440
|
-
return {
|
|
441
|
-
status: 1,
|
|
442
|
-
reason: `Failed to find bb binary at ${pathToBB}`
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
try {
|
|
446
|
-
// Write the inputs to the working directory.
|
|
447
|
-
// WARNING: Not writing the inputs since VM1 is disabled!
|
|
448
|
-
// await fs.writeFile(publicInputsPath, input.publicInputs.toBuffer());
|
|
449
|
-
// if (!(await filePresent(publicInputsPath))) {
|
|
450
|
-
// return { status: BB_RESULT.FAILURE, reason: `Could not write publicInputs at ${publicInputsPath}` };
|
|
451
|
-
// }
|
|
452
|
-
// await fs.writeFile(avmHintsPath, input.avmHints.toBuffer());
|
|
453
|
-
// if (!(await filePresent(avmHintsPath))) {
|
|
454
|
-
// return { status: BB_RESULT.FAILURE, reason: `Could not write avmHints at ${avmHintsPath}` };
|
|
455
|
-
// }
|
|
456
|
-
const args = [
|
|
457
|
-
'--avm-public-inputs',
|
|
458
|
-
publicInputsPath,
|
|
459
|
-
'-o',
|
|
460
|
-
outputPath
|
|
461
|
-
];
|
|
462
|
-
const loggingArg = logger.level === 'debug' || logger.level === 'trace' ? '-d' : logger.level === 'verbose' ? '-v' : '';
|
|
463
|
-
if (loggingArg !== '') {
|
|
464
|
-
args.push(loggingArg);
|
|
465
|
-
}
|
|
466
|
-
const timer = new Timer();
|
|
467
|
-
const cmd = checkCircuitOnly ? 'check_circuit' : 'prove';
|
|
389
|
+
const cmd = checkCircuitOnly ? 'avm_check_circuit' : 'avm_prove';
|
|
468
390
|
const logFunction = (message)=>{
|
|
469
391
|
logger.verbose(`AvmCircuit (${cmd}) BB out - ${message}`);
|
|
470
392
|
};
|
|
471
|
-
const result = await executeBB(pathToBB,
|
|
393
|
+
const result = await executeBB(pathToBB, cmd, args, logFunction);
|
|
472
394
|
const duration = timer.ms();
|
|
473
395
|
if (result.status == 0) {
|
|
474
396
|
return {
|
|
@@ -476,7 +398,7 @@ function getArgs(flavor) {
|
|
|
476
398
|
durationMs: duration,
|
|
477
399
|
proofPath: join(outputPath, PROOF_FILENAME),
|
|
478
400
|
pkPath: undefined,
|
|
479
|
-
|
|
401
|
+
vkDirectoryPath: outputPath
|
|
480
402
|
};
|
|
481
403
|
}
|
|
482
404
|
// Not a great error message here but it is difficult to decipher what comes from bb
|
|
@@ -502,17 +424,7 @@ function getArgs(flavor) {
|
|
|
502
424
|
*/ export async function verifyProof(pathToBB, proofFullPath, verificationKeyPath, ultraHonkFlavor, log) {
|
|
503
425
|
return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, `verify`, log, getArgs(ultraHonkFlavor));
|
|
504
426
|
}
|
|
505
|
-
|
|
506
|
-
* Used for verifying proofs of the AVM
|
|
507
|
-
* @param pathToBB - The full path to the bb binary
|
|
508
|
-
* @param proofFullPath - The full path to the proof to be verified
|
|
509
|
-
* @param verificationKeyPath - The full path to the circuit verification key
|
|
510
|
-
* @param log - A logging function
|
|
511
|
-
* @returns An object containing a result indication and duration taken
|
|
512
|
-
*/ export async function verifyAvmProof(pathToBB, proofFullPath, verificationKeyPath, logger) {
|
|
513
|
-
return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'avm_verify', logger);
|
|
514
|
-
}
|
|
515
|
-
export async function verifyAvmProofV2(pathToBB, workingDirectory, proofFullPath, publicInputs, verificationKeyPath, logger) {
|
|
427
|
+
export async function verifyAvmProof(pathToBB, workingDirectory, proofFullPath, publicInputs, verificationKeyPath, logger) {
|
|
516
428
|
const inputsBuffer = publicInputs.serializeWithMessagePack();
|
|
517
429
|
// Write the inputs to the working directory.
|
|
518
430
|
const filePresent = async (file)=>await fs.access(file, fs.constants.R_OK).then((_)=>true).catch((_)=>false);
|
|
@@ -524,7 +436,7 @@ export async function verifyAvmProofV2(pathToBB, workingDirectory, proofFullPath
|
|
|
524
436
|
reason: `Could not write avm inputs to ${avmInputsPath}`
|
|
525
437
|
};
|
|
526
438
|
}
|
|
527
|
-
return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, '
|
|
439
|
+
return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'avm_verify', logger, [
|
|
528
440
|
'--avm-public-inputs',
|
|
529
441
|
avmInputsPath
|
|
530
442
|
]);
|
|
@@ -596,14 +508,14 @@ export async function verifyAvmProofV2(pathToBB, workingDirectory, proofFullPath
|
|
|
596
508
|
const logFunction = (message)=>{
|
|
597
509
|
logger.verbose(`bb-prover (verify) BB out - ${message}`);
|
|
598
510
|
};
|
|
599
|
-
// take proofFullPath and remove the suffix past the / to get the directory
|
|
600
|
-
const proofDir = proofFullPath.substring(0, proofFullPath.lastIndexOf('/'));
|
|
601
|
-
const publicInputsFullPath = join(proofDir, '/public_inputs');
|
|
602
|
-
logger.debug(`public inputs path: ${publicInputsFullPath}`);
|
|
603
511
|
try {
|
|
604
512
|
let args;
|
|
605
|
-
// Specify the public inputs path in the case of UH verification.
|
|
606
513
|
if (command == 'verify') {
|
|
514
|
+
// Specify the public inputs path in the case of UH verification.
|
|
515
|
+
// Take proofFullPath and remove the suffix past the / to get the directory.
|
|
516
|
+
const proofDir = proofFullPath.substring(0, proofFullPath.lastIndexOf('/'));
|
|
517
|
+
const publicInputsFullPath = join(proofDir, '/public_inputs');
|
|
518
|
+
logger.debug(`public inputs path: ${publicInputsFullPath}`);
|
|
607
519
|
args = [
|
|
608
520
|
'-p',
|
|
609
521
|
proofFullPath,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED, NESTED_RECURSIVE_PROOF_LENGTH, NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, RECURSIVE_PROOF_LENGTH, TUBE_PROOF_LENGTH } from '@aztec/constants';
|
|
2
2
|
import { type ServerProtocolArtifact } from '@aztec/noir-protocol-circuits-types/server';
|
|
3
|
-
import type { AvmCircuitInputs } from '@aztec/stdlib/avm';
|
|
3
|
+
import type { AvmCircuitInputs, AvmCircuitPublicInputs } from '@aztec/stdlib/avm';
|
|
4
4
|
import { type ProofAndVerificationKey, type PublicInputsAndRecursiveProof, type ServerCircuitProver } from '@aztec/stdlib/interfaces/server';
|
|
5
5
|
import type { BaseParityInputs, ParityPublicInputs, RootParityInputs } from '@aztec/stdlib/parity';
|
|
6
6
|
import { Proof } from '@aztec/stdlib/proofs';
|
|
7
|
-
import type
|
|
7
|
+
import { type BaseOrMergeRollupPublicInputs, type BlockMergeRollupInputs, type BlockRootOrBlockMergePublicInputs, type BlockRootRollupInputs, type EmptyBlockRootRollupInputs, type MergeRollupInputs, type PrivateBaseRollupInputs, PublicBaseRollupInputs, type RootRollupInputs, type RootRollupPublicInputs, type SingleTxBlockRootRollupInputs, type TubeInputs } from '@aztec/stdlib/rollup';
|
|
8
8
|
import type { VerificationKeyData } from '@aztec/stdlib/vks';
|
|
9
9
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
10
10
|
import type { ACVMConfig, BBConfig } from '../../config.js';
|
|
@@ -38,7 +38,7 @@ export declare class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
38
38
|
* @param inputs - The inputs to the AVM circuit.
|
|
39
39
|
* @returns The proof.
|
|
40
40
|
*/
|
|
41
|
-
getAvmProof(inputs: AvmCircuitInputs): Promise<ProofAndVerificationKey<typeof
|
|
41
|
+
getAvmProof(inputs: AvmCircuitInputs, skipPublicInputsValidation?: boolean): Promise<ProofAndVerificationKey<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>>;
|
|
42
42
|
/**
|
|
43
43
|
* Simulates the base rollup circuit from its inputs.
|
|
44
44
|
* @param inputs - Inputs to the circuit.
|
|
@@ -104,7 +104,7 @@ export declare class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
104
104
|
* @param proof - The proof to be verified
|
|
105
105
|
*/
|
|
106
106
|
verifyProof(circuitType: ServerProtocolArtifact, proof: Proof): Promise<void>;
|
|
107
|
-
verifyAvmProof(proof: Proof, verificationKey: VerificationKeyData): Promise<void>;
|
|
107
|
+
verifyAvmProof(proof: Proof, verificationKey: VerificationKeyData, publicInputs: AvmCircuitPublicInputs): Promise<void>;
|
|
108
108
|
verifyWithKey(flavor: UltraHonkFlavor, verificationKey: VerificationKeyData, proof: Proof): Promise<void>;
|
|
109
109
|
private verifyWithKeyInternal;
|
|
110
110
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bb_prover.d.ts","sourceRoot":"","sources":["../../../src/prover/server/bb_prover.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"bb_prover.d.ts","sourceRoot":"","sources":["../../../src/prover/server/bb_prover.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
4
4
|
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
}
|
|
7
|
-
import {
|
|
7
|
+
import { AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED, NESTED_RECURSIVE_PROOF_LENGTH, NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, PAIRING_POINTS_SIZE, RECURSIVE_PROOF_LENGTH, TUBE_PROOF_LENGTH } from '@aztec/constants';
|
|
8
8
|
import { Fr } from '@aztec/foundation/fields';
|
|
9
9
|
import { runInDirectory } from '@aztec/foundation/fs';
|
|
10
10
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -15,6 +15,7 @@ import { NativeACVMSimulator } from '@aztec/simulator/server';
|
|
|
15
15
|
import { ProvingError } from '@aztec/stdlib/errors';
|
|
16
16
|
import { makeProofAndVerificationKey, makePublicInputsAndRecursiveProof } from '@aztec/stdlib/interfaces/server';
|
|
17
17
|
import { Proof, RecursiveProof, makeRecursiveProofFromBinary } from '@aztec/stdlib/proofs';
|
|
18
|
+
import { enhanceProofWithPiValidationFlag } from '@aztec/stdlib/rollup';
|
|
18
19
|
import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
19
20
|
import crypto from 'crypto';
|
|
20
21
|
import { promises as fs } from 'fs';
|
|
@@ -78,9 +79,11 @@ const SERVER_CIRCUIT_RECURSIVE = true;
|
|
|
78
79
|
* Creates an AVM proof and verifies it.
|
|
79
80
|
* @param inputs - The inputs to the AVM circuit.
|
|
80
81
|
* @returns The proof.
|
|
81
|
-
*/ async getAvmProof(inputs) {
|
|
82
|
+
*/ async getAvmProof(inputs, skipPublicInputsValidation = false) {
|
|
82
83
|
const proofAndVk = await this.createAvmProof(inputs);
|
|
83
|
-
await this.verifyAvmProof(proofAndVk.proof.binaryProof, proofAndVk.verificationKey);
|
|
84
|
+
await this.verifyAvmProof(proofAndVk.proof.binaryProof, proofAndVk.verificationKey, inputs.publicInputs);
|
|
85
|
+
// TODO(#14234)[Unconditional PIs validation]: remove next lines and directly return proofAndVk
|
|
86
|
+
proofAndVk.proof.proof = enhanceProofWithPiValidationFlag(proofAndVk.proof.proof, skipPublicInputsValidation);
|
|
84
87
|
return proofAndVk;
|
|
85
88
|
}
|
|
86
89
|
/**
|
|
@@ -253,7 +256,7 @@ const SERVER_CIRCUIT_RECURSIVE = true;
|
|
|
253
256
|
const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory);
|
|
254
257
|
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6773): this VK data format is wrong.
|
|
255
258
|
// In particular, the number of public inputs, etc will be wrong.
|
|
256
|
-
const verificationKey = await extractAvmVkData(provingResult.
|
|
259
|
+
const verificationKey = await extractAvmVkData(provingResult.vkDirectoryPath);
|
|
257
260
|
const avmProof = await this.readAvmProofAsFields(provingResult.proofPath, verificationKey);
|
|
258
261
|
const circuitType = 'avm-circuit';
|
|
259
262
|
const appCircuitName = 'unknown';
|
|
@@ -282,7 +285,7 @@ const SERVER_CIRCUIT_RECURSIVE = true;
|
|
|
282
285
|
const provingResult = await this.generateTubeProofWithBB(bbWorkingDirectory, input);
|
|
283
286
|
// Read the proof as fields
|
|
284
287
|
// TODO(AD): this is the only remaining use of extractVkData.
|
|
285
|
-
const tubeVK = await extractVkData(provingResult.
|
|
288
|
+
const tubeVK = await extractVkData(provingResult.vkDirectoryPath);
|
|
286
289
|
const tubeProof = await readProofAsFields(provingResult.proofPath, tubeVK, TUBE_PROOF_LENGTH, logger);
|
|
287
290
|
this.instrumentation.recordDuration('provingDuration', 'tubeCircuit', provingResult.durationMs);
|
|
288
291
|
this.instrumentation.recordSize('proofSize', 'tubeCircuit', tubeProof.binaryProof.buffer.length);
|
|
@@ -339,8 +342,8 @@ const SERVER_CIRCUIT_RECURSIVE = true;
|
|
|
339
342
|
const verificationKey = this.getVerificationKeyDataForCircuit(circuitType);
|
|
340
343
|
return await this.verifyWithKey(getUltraHonkFlavorForCircuit(circuitType), verificationKey, proof);
|
|
341
344
|
}
|
|
342
|
-
async verifyAvmProof(proof, verificationKey) {
|
|
343
|
-
return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath)=>verifyAvmProof(this.config.bbBinaryPath, proofPath, vkPath, logger));
|
|
345
|
+
async verifyAvmProof(proof, verificationKey, publicInputs) {
|
|
346
|
+
return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath)=>verifyAvmProof(this.config.bbBinaryPath, this.config.bbWorkingDirectory, proofPath, publicInputs, vkPath, logger));
|
|
344
347
|
}
|
|
345
348
|
async verifyWithKey(flavor, verificationKey, proof) {
|
|
346
349
|
return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath)=>verifyProof(this.config.bbBinaryPath, proofPath, vkPath, flavor, logger));
|
|
@@ -375,12 +378,18 @@ const SERVER_CIRCUIT_RECURSIVE = true;
|
|
|
375
378
|
return vk;
|
|
376
379
|
}
|
|
377
380
|
async readAvmProofAsFields(proofFilename, vkData) {
|
|
378
|
-
const
|
|
379
|
-
const reader = BufferReader.asReader(
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
381
|
+
const rawProofBuffer = await fs.readFile(proofFilename);
|
|
382
|
+
const reader = BufferReader.asReader(rawProofBuffer);
|
|
383
|
+
const proofFields = reader.readArray(rawProofBuffer.length / Fr.SIZE_IN_BYTES, Fr);
|
|
384
|
+
// We extend to a fixed-size padded proof as during development any new AVM circuit column changes the
|
|
385
|
+
// proof length and we do not have a mechanism to feedback a cpp constant to noir/TS.
|
|
386
|
+
// TODO(#13390): Revive a non-padded AVM proof
|
|
387
|
+
if (proofFields.length > AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED) {
|
|
388
|
+
throw new Error(`Proof has ${proofFields.length} fields, expected no more than ${AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED}.`);
|
|
389
|
+
}
|
|
390
|
+
const proofFieldsPadded = proofFields.concat(Array(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED - proofFields.length).fill(new Fr(0)));
|
|
391
|
+
const proof = new Proof(rawProofBuffer, vkData.numPublicInputs);
|
|
392
|
+
return new RecursiveProof(proofFieldsPadded, proof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED);
|
|
384
393
|
}
|
|
385
394
|
runInDirectory(fn) {
|
|
386
395
|
return runInDirectory(this.config.bbWorkingDirectory, (dir)=>fn(dir).catch((err)=>{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED, NESTED_RECURSIVE_PROOF_LENGTH, NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, RECURSIVE_PROOF_LENGTH, TUBE_PROOF_LENGTH } from '@aztec/constants';
|
|
2
2
|
import { type ServerProtocolArtifact } from '@aztec/noir-protocol-circuits-types/server';
|
|
3
3
|
import { type SimulationProvider } from '@aztec/simulator/server';
|
|
4
4
|
import type { AvmCircuitInputs } from '@aztec/stdlib/avm';
|
|
@@ -72,7 +72,7 @@ export declare class TestCircuitProver implements ServerCircuitProver {
|
|
|
72
72
|
* @returns The public inputs as outputs of the simulation.
|
|
73
73
|
*/
|
|
74
74
|
getRootRollupProof(input: RootRollupInputs): Promise<PublicInputsAndRecursiveProof<RootRollupPublicInputs>>;
|
|
75
|
-
getAvmProof(_inputs: AvmCircuitInputs): Promise<ProofAndVerificationKey<typeof
|
|
75
|
+
getAvmProof(_inputs: AvmCircuitInputs): Promise<ProofAndVerificationKey<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>>;
|
|
76
76
|
private applyDelay;
|
|
77
77
|
verifyProof(_1: ServerProtocolArtifact, _2: Proof): Promise<void>;
|
|
78
78
|
private simulate;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test_circuit_prover.d.ts","sourceRoot":"","sources":["../../src/test/test_circuit_prover.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"test_circuit_prover.d.ts","sourceRoot":"","sources":["../../src/test/test_circuit_prover.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
4
4
|
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
}
|
|
7
|
-
import {
|
|
7
|
+
import { AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED, AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED, NESTED_RECURSIVE_PROOF_LENGTH, NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, RECURSIVE_PROOF_LENGTH, TUBE_PROOF_LENGTH } from '@aztec/constants';
|
|
8
8
|
import { createLogger } from '@aztec/foundation/log';
|
|
9
9
|
import { sleep } from '@aztec/foundation/sleep';
|
|
10
10
|
import { Timer } from '@aztec/foundation/timer';
|
|
@@ -105,7 +105,7 @@ import { PROOF_DELAY_MS, WITGEN_DELAY_MS } from './delay_values.js';
|
|
|
105
105
|
// We can't simulate the AVM because we don't have enough context to do so (e.g., DBs).
|
|
106
106
|
// We just return an empty proof and VK data.
|
|
107
107
|
this.logger.debug('Skipping AVM simulation in TestCircuitProver.');
|
|
108
|
-
return this.applyDelay(ProvingRequestType.PUBLIC_VM, ()=>makeProofAndVerificationKey(makeEmptyRecursiveProof(
|
|
108
|
+
return this.applyDelay(ProvingRequestType.PUBLIC_VM, ()=>makeProofAndVerificationKey(makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED), VerificationKeyData.makeFake(AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED)));
|
|
109
109
|
}
|
|
110
110
|
async applyDelay(type, fn) {
|
|
111
111
|
const timer = new Timer();
|
|
@@ -5,5 +5,11 @@ import { VerificationKeyData } from '@aztec/stdlib/vks';
|
|
|
5
5
|
* @returns The verification key data
|
|
6
6
|
*/
|
|
7
7
|
export declare function extractVkData(vkDirectoryPath: string): Promise<VerificationKeyData>;
|
|
8
|
+
/**
|
|
9
|
+
* Reads the verification key data stored in a binary file at the specified directory location and parses into a VerificationKeyData.
|
|
10
|
+
* We do not assume any JSON file available but only the binary version, contrary to the above extractVkData() method.
|
|
11
|
+
* @param vkDirectoryPath - The directory containing the verification key binary data file.
|
|
12
|
+
* @returns The verification key data
|
|
13
|
+
*/
|
|
8
14
|
export declare function extractAvmVkData(vkDirectoryPath: string): Promise<VerificationKeyData>;
|
|
9
15
|
//# sourceMappingURL=verification_key_data.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verification_key_data.d.ts","sourceRoot":"","sources":["../../src/verification_key/verification_key_data.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"verification_key_data.d.ts","sourceRoot":"","sources":["../../src/verification_key/verification_key_data.ts"],"names":[],"mappings":"AAIA,OAAO,EAA2B,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAQjF;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAWzF;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAe5F"}
|