@aztec/bb-prover 0.41.0 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/bb/cli.d.ts.map +1 -1
- package/dest/bb/cli.js +24 -2
- package/dest/bb/execute.d.ts +30 -1
- package/dest/bb/execute.d.ts.map +1 -1
- package/dest/bb/execute.js +252 -60
- package/dest/config.d.ts +9 -0
- package/dest/config.d.ts.map +1 -0
- package/dest/config.js +2 -0
- package/dest/index.d.ts +2 -0
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +3 -1
- package/dest/mappings/mappings.d.ts +1 -0
- package/dest/mappings/mappings.d.ts.map +1 -1
- package/dest/mappings/mappings.js +27 -8
- package/dest/prover/bb_native_proof_creator.d.ts +2 -8
- package/dest/prover/bb_native_proof_creator.d.ts.map +1 -1
- package/dest/prover/bb_native_proof_creator.js +37 -79
- package/dest/prover/bb_prover.d.ts +33 -32
- package/dest/prover/bb_prover.d.ts.map +1 -1
- package/dest/prover/bb_prover.js +226 -161
- package/dest/stats.d.ts.map +1 -1
- package/dest/stats.js +8 -2
- package/dest/test/index.d.ts +1 -0
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +2 -1
- package/dest/test/test_circuit_prover.d.ts +9 -7
- package/dest/test/test_circuit_prover.d.ts.map +1 -1
- package/dest/test/test_circuit_prover.js +31 -15
- package/dest/test/test_verifier.d.ts +7 -0
- package/dest/test/test_verifier.d.ts.map +1 -0
- package/dest/test/test_verifier.js +10 -0
- package/dest/verification_key/verification_key_data.d.ts +8 -0
- package/dest/verification_key/verification_key_data.d.ts.map +1 -0
- package/dest/verification_key/verification_key_data.js +24 -0
- package/dest/verifier/bb_verifier.d.ts +18 -0
- package/dest/verifier/bb_verifier.d.ts.map +1 -0
- package/dest/verifier/bb_verifier.js +90 -0
- package/dest/verifier/index.d.ts +2 -0
- package/dest/verifier/index.d.ts.map +1 -0
- package/dest/verifier/index.js +2 -0
- package/package.json +6 -6
- package/src/bb/cli.ts +36 -1
- package/src/bb/execute.ts +340 -67
- package/src/config.ts +9 -0
- package/src/index.ts +2 -0
- package/src/mappings/mappings.ts +38 -12
- package/src/prover/bb_native_proof_creator.ts +49 -91
- package/src/prover/bb_prover.ts +391 -219
- package/src/stats.ts +7 -1
- package/src/test/index.ts +1 -0
- package/src/test/test_circuit_prover.ts +84 -21
- package/src/test/test_verifier.ts +12 -0
- package/src/verification_key/verification_key_data.ts +35 -0
- package/src/verifier/bb_verifier.ts +156 -0
- package/src/verifier/index.ts +1 -0
- package/dest/prover/verification_key_data.d.ts +0 -16
- package/dest/prover/verification_key_data.d.ts.map +0 -1
- package/dest/prover/verification_key_data.js +0 -5
- package/src/prover/verification_key_data.ts +0 -16
package/src/prover/bb_prover.ts
CHANGED
|
@@ -1,39 +1,45 @@
|
|
|
1
1
|
/* eslint-disable require-await */
|
|
2
2
|
import {
|
|
3
|
-
type
|
|
3
|
+
type ProofAndVerificationKey,
|
|
4
|
+
type PublicInputsAndRecursiveProof,
|
|
4
5
|
type PublicKernelNonTailRequest,
|
|
5
6
|
type PublicKernelTailRequest,
|
|
6
7
|
PublicKernelType,
|
|
7
8
|
type ServerCircuitProver,
|
|
8
|
-
|
|
9
|
+
makePublicInputsAndRecursiveProof,
|
|
9
10
|
} from '@aztec/circuit-types';
|
|
10
11
|
import { type CircuitProvingStats, type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats';
|
|
11
12
|
import {
|
|
13
|
+
AGGREGATION_OBJECT_LENGTH,
|
|
14
|
+
type AvmCircuitInputs,
|
|
12
15
|
type BaseOrMergeRollupPublicInputs,
|
|
13
16
|
type BaseParityInputs,
|
|
14
17
|
type BaseRollupInputs,
|
|
18
|
+
EmptyNestedCircuitInputs,
|
|
19
|
+
EmptyNestedData,
|
|
15
20
|
Fr,
|
|
16
21
|
type KernelCircuitPublicInputs,
|
|
17
22
|
type MergeRollupInputs,
|
|
18
23
|
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
19
|
-
type
|
|
24
|
+
type PrivateKernelEmptyInputData,
|
|
25
|
+
PrivateKernelEmptyInputs,
|
|
20
26
|
Proof,
|
|
21
27
|
type PublicKernelCircuitPublicInputs,
|
|
22
28
|
RECURSIVE_PROOF_LENGTH,
|
|
23
29
|
RecursiveProof,
|
|
24
|
-
RollupTypes,
|
|
25
30
|
RootParityInput,
|
|
26
31
|
type RootParityInputs,
|
|
27
32
|
type RootRollupInputs,
|
|
28
33
|
type RootRollupPublicInputs,
|
|
29
|
-
type
|
|
30
|
-
|
|
34
|
+
type VerificationKeyAsFields,
|
|
35
|
+
type VerificationKeyData,
|
|
36
|
+
makeRecursiveProofFromBinary,
|
|
31
37
|
} from '@aztec/circuits.js';
|
|
32
|
-
import {
|
|
38
|
+
import { runInDirectory } from '@aztec/foundation/fs';
|
|
33
39
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
34
|
-
import { type Tuple } from '@aztec/foundation/serialize';
|
|
35
40
|
import { Timer } from '@aztec/foundation/timer';
|
|
36
41
|
import {
|
|
42
|
+
EmptyNestedArtifact,
|
|
37
43
|
ServerCircuitArtifacts,
|
|
38
44
|
type ServerProtocolArtifact,
|
|
39
45
|
convertBaseParityInputsToWitnessMap,
|
|
@@ -42,6 +48,8 @@ import {
|
|
|
42
48
|
convertBaseRollupOutputsFromWitnessMap,
|
|
43
49
|
convertMergeRollupInputsToWitnessMap,
|
|
44
50
|
convertMergeRollupOutputsFromWitnessMap,
|
|
51
|
+
convertPrivateKernelEmptyInputsToWitnessMap,
|
|
52
|
+
convertPrivateKernelEmptyOutputsFromWitnessMap,
|
|
45
53
|
convertPublicTailInputsToWitnessMap,
|
|
46
54
|
convertPublicTailOutputFromWitnessMap,
|
|
47
55
|
convertRootParityInputsToWitnessMap,
|
|
@@ -51,41 +59,41 @@ import {
|
|
|
51
59
|
} from '@aztec/noir-protocol-circuits-types';
|
|
52
60
|
import { NativeACVMSimulator } from '@aztec/simulator';
|
|
53
61
|
|
|
54
|
-
import {
|
|
62
|
+
import { abiEncode } from '@noir-lang/noirc_abi';
|
|
63
|
+
import { type Abi, type WitnessMap } from '@noir-lang/types';
|
|
55
64
|
import * as fs from 'fs/promises';
|
|
65
|
+
import * as path from 'path';
|
|
56
66
|
|
|
57
67
|
import {
|
|
68
|
+
type BBSuccess,
|
|
58
69
|
BB_RESULT,
|
|
59
70
|
PROOF_FIELDS_FILENAME,
|
|
60
71
|
PROOF_FILENAME,
|
|
61
|
-
VK_FIELDS_FILENAME,
|
|
62
72
|
VK_FILENAME,
|
|
73
|
+
type VerificationFunction,
|
|
74
|
+
generateAvmProof,
|
|
63
75
|
generateKeyForNoirCircuit,
|
|
64
76
|
generateProof,
|
|
77
|
+
verifyAvmProof,
|
|
65
78
|
verifyProof,
|
|
79
|
+
writeProofAsFields,
|
|
66
80
|
} from '../bb/execute.js';
|
|
81
|
+
import type { ACVMConfig, BBConfig } from '../config.js';
|
|
67
82
|
import { PublicKernelArtifactMapping } from '../mappings/mappings.js';
|
|
68
83
|
import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
|
|
69
|
-
import {
|
|
70
|
-
AGGREGATION_OBJECT_SIZE,
|
|
71
|
-
CIRCUIT_PUBLIC_INPUTS_INDEX,
|
|
72
|
-
CIRCUIT_RECURSIVE_INDEX,
|
|
73
|
-
CIRCUIT_SIZE_INDEX,
|
|
74
|
-
type VerificationKeyData,
|
|
75
|
-
} from './verification_key_data.js';
|
|
84
|
+
import { extractVkData } from '../verification_key/verification_key_data.js';
|
|
76
85
|
|
|
77
86
|
const logger = createDebugLogger('aztec:bb-prover');
|
|
78
87
|
|
|
79
|
-
const CIRCUITS_WITHOUT_AGGREGATION: Set<ServerProtocolArtifact> = new Set([
|
|
88
|
+
const CIRCUITS_WITHOUT_AGGREGATION: Set<ServerProtocolArtifact> = new Set([
|
|
89
|
+
'BaseParityArtifact',
|
|
90
|
+
'EmptyNestedArtifact',
|
|
91
|
+
]);
|
|
80
92
|
|
|
81
|
-
export
|
|
82
|
-
bbBinaryPath: string;
|
|
83
|
-
bbWorkingDirectory: string;
|
|
84
|
-
acvmBinaryPath: string;
|
|
85
|
-
acvmWorkingDirectory: string;
|
|
93
|
+
export interface BBProverConfig extends BBConfig, ACVMConfig {
|
|
86
94
|
// list of circuits supported by this prover. defaults to all circuits if empty
|
|
87
95
|
circuitFilter?: ServerProtocolArtifact[];
|
|
88
|
-
}
|
|
96
|
+
}
|
|
89
97
|
|
|
90
98
|
/**
|
|
91
99
|
* Prover implementation that uses barretenberg native proving
|
|
@@ -114,7 +122,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
114
122
|
* @returns The public inputs of the parity circuit.
|
|
115
123
|
*/
|
|
116
124
|
public async getBaseParityProof(inputs: BaseParityInputs): Promise<RootParityInput<typeof RECURSIVE_PROOF_LENGTH>> {
|
|
117
|
-
const
|
|
125
|
+
const { circuitOutput, proof } = await this.createRecursiveProof(
|
|
118
126
|
inputs,
|
|
119
127
|
'BaseParityArtifact',
|
|
120
128
|
RECURSIVE_PROOF_LENGTH,
|
|
@@ -124,9 +132,9 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
124
132
|
|
|
125
133
|
const verificationKey = await this.getVerificationKeyDataForCircuit('BaseParityArtifact');
|
|
126
134
|
|
|
127
|
-
|
|
135
|
+
await this.verifyProof('BaseParityArtifact', proof.binaryProof);
|
|
128
136
|
|
|
129
|
-
return new RootParityInput(proof,
|
|
137
|
+
return new RootParityInput(proof, verificationKey.keyAsFields, circuitOutput);
|
|
130
138
|
}
|
|
131
139
|
|
|
132
140
|
/**
|
|
@@ -137,7 +145,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
137
145
|
public async getRootParityProof(
|
|
138
146
|
inputs: RootParityInputs,
|
|
139
147
|
): Promise<RootParityInput<typeof NESTED_RECURSIVE_PROOF_LENGTH>> {
|
|
140
|
-
const
|
|
148
|
+
const { circuitOutput, proof } = await this.createRecursiveProof(
|
|
141
149
|
inputs,
|
|
142
150
|
'RootParityArtifact',
|
|
143
151
|
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
@@ -147,9 +155,20 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
147
155
|
|
|
148
156
|
const verificationKey = await this.getVerificationKeyDataForCircuit('RootParityArtifact');
|
|
149
157
|
|
|
150
|
-
|
|
158
|
+
await this.verifyProof('RootParityArtifact', proof.binaryProof);
|
|
159
|
+
|
|
160
|
+
return new RootParityInput(proof, verificationKey.keyAsFields, circuitOutput);
|
|
161
|
+
}
|
|
151
162
|
|
|
152
|
-
|
|
163
|
+
/**
|
|
164
|
+
* Creates an AVM proof and verifies it.
|
|
165
|
+
* @param inputs - The inputs to the AVM circuit.
|
|
166
|
+
* @returns The proof.
|
|
167
|
+
*/
|
|
168
|
+
public async getAvmProof(inputs: AvmCircuitInputs): Promise<ProofAndVerificationKey> {
|
|
169
|
+
const proofAndVk = await this.createAvmProof(inputs);
|
|
170
|
+
await this.verifyAvmProof(proofAndVk.proof, proofAndVk.verificationKey);
|
|
171
|
+
return proofAndVk;
|
|
153
172
|
}
|
|
154
173
|
|
|
155
174
|
/**
|
|
@@ -159,19 +178,37 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
159
178
|
*/
|
|
160
179
|
public async getPublicKernelProof(
|
|
161
180
|
kernelRequest: PublicKernelNonTailRequest,
|
|
162
|
-
): Promise<
|
|
181
|
+
): Promise<PublicInputsAndRecursiveProof<PublicKernelCircuitPublicInputs>> {
|
|
163
182
|
const kernelOps = PublicKernelArtifactMapping[kernelRequest.type];
|
|
164
183
|
if (kernelOps === undefined) {
|
|
165
184
|
throw new Error(`Unable to prove kernel type ${PublicKernelType[kernelRequest.type]}`);
|
|
166
185
|
}
|
|
167
|
-
|
|
186
|
+
|
|
187
|
+
// We may need to convert the recursive proof into fields format
|
|
188
|
+
kernelRequest.inputs.previousKernel.proof = await this.ensureValidProof(
|
|
189
|
+
kernelRequest.inputs.previousKernel.proof,
|
|
190
|
+
kernelOps.artifact,
|
|
191
|
+
kernelRequest.inputs.previousKernel.vk,
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
await this.verifyWithKey(
|
|
195
|
+
kernelRequest.inputs.previousKernel.vk,
|
|
196
|
+
kernelRequest.inputs.previousKernel.proof.binaryProof,
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
const { circuitOutput, proof } = await this.createRecursiveProof(
|
|
168
200
|
kernelRequest.inputs,
|
|
169
201
|
kernelOps.artifact,
|
|
202
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
170
203
|
kernelOps.convertInputs,
|
|
171
204
|
kernelOps.convertOutputs,
|
|
172
205
|
);
|
|
173
206
|
|
|
174
|
-
|
|
207
|
+
const verificationKey = await this.getVerificationKeyDataForCircuit(kernelOps.artifact);
|
|
208
|
+
|
|
209
|
+
await this.verifyProof(kernelOps.artifact, proof.binaryProof);
|
|
210
|
+
|
|
211
|
+
return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
|
|
175
212
|
}
|
|
176
213
|
|
|
177
214
|
/**
|
|
@@ -181,15 +218,20 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
181
218
|
*/
|
|
182
219
|
public async getPublicTailProof(
|
|
183
220
|
kernelRequest: PublicKernelTailRequest,
|
|
184
|
-
): Promise<
|
|
185
|
-
const
|
|
221
|
+
): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>> {
|
|
222
|
+
const { circuitOutput, proof } = await this.createRecursiveProof(
|
|
186
223
|
kernelRequest.inputs,
|
|
187
224
|
'PublicKernelTailArtifact',
|
|
225
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
188
226
|
convertPublicTailInputsToWitnessMap,
|
|
189
227
|
convertPublicTailOutputFromWitnessMap,
|
|
190
228
|
);
|
|
191
229
|
|
|
192
|
-
|
|
230
|
+
const verificationKey = await this.getVerificationKeyDataForCircuit('PublicKernelTailArtifact');
|
|
231
|
+
|
|
232
|
+
await this.verifyProof('PublicKernelTailArtifact', proof.binaryProof);
|
|
233
|
+
|
|
234
|
+
return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
|
|
193
235
|
}
|
|
194
236
|
|
|
195
237
|
/**
|
|
@@ -199,16 +241,29 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
199
241
|
*/
|
|
200
242
|
public async getBaseRollupProof(
|
|
201
243
|
input: BaseRollupInputs,
|
|
202
|
-
): Promise<
|
|
203
|
-
|
|
244
|
+
): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>> {
|
|
245
|
+
// We may need to convert the recursive proof into fields format
|
|
246
|
+
input.kernelData.proof = await this.ensureValidProof(
|
|
247
|
+
input.kernelData.proof,
|
|
248
|
+
'BaseRollupArtifact',
|
|
249
|
+
input.kernelData.vk,
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
const { circuitOutput, proof } = await this.createRecursiveProof(
|
|
204
253
|
input,
|
|
205
254
|
'BaseRollupArtifact',
|
|
255
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
206
256
|
convertBaseRollupInputsToWitnessMap,
|
|
207
257
|
convertBaseRollupOutputsFromWitnessMap,
|
|
208
258
|
);
|
|
209
259
|
|
|
210
|
-
|
|
260
|
+
const verificationKey = await this.getVerificationKeyDataForCircuit('BaseRollupArtifact');
|
|
261
|
+
|
|
262
|
+
await this.verifyProof('BaseRollupArtifact', proof.binaryProof);
|
|
263
|
+
|
|
264
|
+
return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
|
|
211
265
|
}
|
|
266
|
+
|
|
212
267
|
/**
|
|
213
268
|
* Simulates the merge rollup circuit from its inputs.
|
|
214
269
|
* @param input - Inputs to the circuit.
|
|
@@ -216,18 +271,20 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
216
271
|
*/
|
|
217
272
|
public async getMergeRollupProof(
|
|
218
273
|
input: MergeRollupInputs,
|
|
219
|
-
): Promise<
|
|
220
|
-
|
|
221
|
-
await Promise.all(input.previousRollupData.map(prev => this.verifyPreviousRollupProof(prev)));
|
|
222
|
-
|
|
223
|
-
const [result, proof] = await this.createProof(
|
|
274
|
+
): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>> {
|
|
275
|
+
const { circuitOutput, proof } = await this.createRecursiveProof(
|
|
224
276
|
input,
|
|
225
277
|
'MergeRollupArtifact',
|
|
278
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
226
279
|
convertMergeRollupInputsToWitnessMap,
|
|
227
280
|
convertMergeRollupOutputsFromWitnessMap,
|
|
228
281
|
);
|
|
229
282
|
|
|
230
|
-
|
|
283
|
+
const verificationKey = await this.getVerificationKeyDataForCircuit('MergeRollupArtifact');
|
|
284
|
+
|
|
285
|
+
await this.verifyProof('MergeRollupArtifact', proof.binaryProof);
|
|
286
|
+
|
|
287
|
+
return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
|
|
231
288
|
}
|
|
232
289
|
|
|
233
290
|
/**
|
|
@@ -235,37 +292,84 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
235
292
|
* @param input - Inputs to the circuit.
|
|
236
293
|
* @returns The public inputs as outputs of the simulation.
|
|
237
294
|
*/
|
|
238
|
-
public async getRootRollupProof(
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const [result, proof] = await this.createProof(
|
|
295
|
+
public async getRootRollupProof(
|
|
296
|
+
input: RootRollupInputs,
|
|
297
|
+
): Promise<PublicInputsAndRecursiveProof<RootRollupPublicInputs>> {
|
|
298
|
+
const { circuitOutput, proof } = await this.createProof(
|
|
243
299
|
input,
|
|
244
300
|
'RootRollupArtifact',
|
|
245
301
|
convertRootRollupInputsToWitnessMap,
|
|
246
302
|
convertRootRollupOutputsFromWitnessMap,
|
|
247
303
|
);
|
|
248
304
|
|
|
305
|
+
const recursiveProof = makeRecursiveProofFromBinary(proof, NESTED_RECURSIVE_PROOF_LENGTH);
|
|
306
|
+
|
|
307
|
+
const verificationKey = await this.getVerificationKeyDataForCircuit('RootRollupArtifact');
|
|
308
|
+
|
|
249
309
|
await this.verifyProof('RootRollupArtifact', proof);
|
|
250
310
|
|
|
251
|
-
return
|
|
311
|
+
return makePublicInputsAndRecursiveProof(circuitOutput, recursiveProof, verificationKey);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
public async getEmptyPrivateKernelProof(
|
|
315
|
+
inputs: PrivateKernelEmptyInputData,
|
|
316
|
+
): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>> {
|
|
317
|
+
const emptyNested = await this.getEmptyNestedProof();
|
|
318
|
+
const emptyPrivateKernelProof = await this.getEmptyPrivateKernelProofFromEmptyNested(
|
|
319
|
+
PrivateKernelEmptyInputs.from({
|
|
320
|
+
...inputs,
|
|
321
|
+
emptyNested,
|
|
322
|
+
}),
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
return emptyPrivateKernelProof;
|
|
252
326
|
}
|
|
253
327
|
|
|
254
|
-
|
|
255
|
-
|
|
328
|
+
private async getEmptyNestedProof(): Promise<EmptyNestedData> {
|
|
329
|
+
const inputs = new EmptyNestedCircuitInputs();
|
|
330
|
+
const { proof } = await this.createRecursiveProof(
|
|
331
|
+
inputs,
|
|
332
|
+
'EmptyNestedArtifact',
|
|
333
|
+
RECURSIVE_PROOF_LENGTH,
|
|
334
|
+
(nothing: any) => abiEncode(EmptyNestedArtifact.abi as Abi, { _inputs: nothing as any }),
|
|
335
|
+
() => new EmptyNestedCircuitInputs(),
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
const verificationKey = await this.getVerificationKeyDataForCircuit('EmptyNestedArtifact');
|
|
339
|
+
await this.verifyProof('EmptyNestedArtifact', proof.binaryProof);
|
|
340
|
+
|
|
341
|
+
return new EmptyNestedData(proof, verificationKey.keyAsFields);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
private async getEmptyPrivateKernelProofFromEmptyNested(
|
|
345
|
+
inputs: PrivateKernelEmptyInputs,
|
|
346
|
+
): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>> {
|
|
347
|
+
const { circuitOutput, proof } = await this.createRecursiveProof(
|
|
348
|
+
inputs,
|
|
349
|
+
'PrivateKernelEmptyArtifact',
|
|
350
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
351
|
+
convertPrivateKernelEmptyInputsToWitnessMap,
|
|
352
|
+
convertPrivateKernelEmptyOutputsFromWitnessMap,
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
const verificationKey = await this.getVerificationKeyDataForCircuit('PrivateKernelEmptyArtifact');
|
|
356
|
+
await this.verifyProof('PrivateKernelEmptyArtifact', proof.binaryProof);
|
|
357
|
+
|
|
358
|
+
return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
private async generateProofWithBB<
|
|
362
|
+
Input extends { toBuffer: () => Buffer },
|
|
363
|
+
Output extends { toBuffer: () => Buffer },
|
|
364
|
+
>(
|
|
256
365
|
input: Input,
|
|
257
366
|
circuitType: ServerProtocolArtifact,
|
|
258
367
|
convertInput: (input: Input) => WitnessMap,
|
|
259
368
|
convertOutput: (outputWitness: WitnessMap) => Output,
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
const bbWorkingDirectory = `${this.config.bbWorkingDirectory}/${randomBytes(8).toString('hex')}`;
|
|
263
|
-
await fs.mkdir(bbWorkingDirectory, { recursive: true });
|
|
264
|
-
|
|
265
|
-
await fs.access(bbWorkingDirectory);
|
|
266
|
-
|
|
369
|
+
workingDirectory: string,
|
|
370
|
+
): Promise<{ circuitOutput: Output; vkData: VerificationKeyData; provingResult: BBSuccess }> {
|
|
267
371
|
// Have the ACVM write the partial witness here
|
|
268
|
-
const outputWitnessFile =
|
|
372
|
+
const outputWitnessFile = path.join(workingDirectory, 'partial-witness.gz');
|
|
269
373
|
|
|
270
374
|
// Generate the partial witness using the ACVM
|
|
271
375
|
// A further temp directory will be created beneath ours and then cleaned up after the partial witness has been copied to our specified location
|
|
@@ -279,14 +383,16 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
279
383
|
|
|
280
384
|
logger.debug(`Generating witness data for ${circuitType}`);
|
|
281
385
|
|
|
282
|
-
const
|
|
386
|
+
const inputWitness = convertInput(input);
|
|
283
387
|
const timer = new Timer();
|
|
284
|
-
const outputWitness = await simulator.simulateCircuit(
|
|
388
|
+
const outputWitness = await simulator.simulateCircuit(inputWitness, artifact);
|
|
389
|
+
const witnessGenerationDuration = timer.ms();
|
|
390
|
+
const output = convertOutput(outputWitness);
|
|
285
391
|
logger.debug(`Generated witness`, {
|
|
286
392
|
circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
|
|
287
|
-
duration:
|
|
288
|
-
inputSize:
|
|
289
|
-
outputSize:
|
|
393
|
+
duration: witnessGenerationDuration,
|
|
394
|
+
inputSize: input.toBuffer().length,
|
|
395
|
+
outputSize: output.toBuffer().length,
|
|
290
396
|
eventName: 'circuit-witness-generation',
|
|
291
397
|
} satisfies CircuitWitnessGenerationStats);
|
|
292
398
|
|
|
@@ -295,7 +401,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
295
401
|
|
|
296
402
|
const provingResult = await generateProof(
|
|
297
403
|
this.config.bbBinaryPath,
|
|
298
|
-
|
|
404
|
+
workingDirectory,
|
|
299
405
|
circuitType,
|
|
300
406
|
Buffer.from(artifact.bytecode, 'base64'),
|
|
301
407
|
outputWitnessFile,
|
|
@@ -310,29 +416,95 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
310
416
|
// Ensure our vk cache is up to date
|
|
311
417
|
const vkData = await this.updateVerificationKeyAfterProof(provingResult.vkPath!, circuitType);
|
|
312
418
|
|
|
313
|
-
|
|
314
|
-
|
|
419
|
+
return {
|
|
420
|
+
circuitOutput: output,
|
|
421
|
+
vkData,
|
|
422
|
+
provingResult,
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
private async createProof<Input extends { toBuffer: () => Buffer }, Output extends { toBuffer: () => Buffer }>(
|
|
427
|
+
input: Input,
|
|
428
|
+
circuitType: ServerProtocolArtifact,
|
|
429
|
+
convertInput: (input: Input) => WitnessMap,
|
|
430
|
+
convertOutput: (outputWitness: WitnessMap) => Output,
|
|
431
|
+
): Promise<{ circuitOutput: Output; proof: Proof }> {
|
|
432
|
+
const operation = async (bbWorkingDirectory: string) => {
|
|
433
|
+
const {
|
|
434
|
+
provingResult,
|
|
435
|
+
vkData,
|
|
436
|
+
circuitOutput: output,
|
|
437
|
+
} = await this.generateProofWithBB(input, circuitType, convertInput, convertOutput, bbWorkingDirectory);
|
|
438
|
+
|
|
439
|
+
// Read the binary proof
|
|
440
|
+
const rawProof = await fs.readFile(`${provingResult.proofPath!}/${PROOF_FILENAME}`);
|
|
441
|
+
|
|
442
|
+
const proof = new Proof(rawProof, vkData.numPublicInputs);
|
|
443
|
+
logger.info(
|
|
444
|
+
`Generated proof for ${circuitType} in ${Math.ceil(provingResult.duration)} ms, size: ${
|
|
445
|
+
proof.buffer.length
|
|
446
|
+
} bytes`,
|
|
447
|
+
{
|
|
448
|
+
circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
|
|
449
|
+
// does not include reading the proof from disk
|
|
450
|
+
duration: provingResult.duration,
|
|
451
|
+
proofSize: proof.buffer.length,
|
|
452
|
+
eventName: 'circuit-proving',
|
|
453
|
+
// circuitOutput is the partial witness that became the input to the proof
|
|
454
|
+
inputSize: output.toBuffer().length,
|
|
455
|
+
circuitSize: vkData.circuitSize,
|
|
456
|
+
numPublicInputs: vkData.numPublicInputs,
|
|
457
|
+
} satisfies CircuitProvingStats,
|
|
458
|
+
);
|
|
315
459
|
|
|
316
|
-
|
|
460
|
+
return { circuitOutput: output, proof };
|
|
461
|
+
};
|
|
462
|
+
return await runInDirectory(this.config.bbWorkingDirectory, operation);
|
|
463
|
+
}
|
|
317
464
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
logger.info(
|
|
321
|
-
`Generated proof for ${circuitType} in ${provingResult.duration} ms, size: ${proof.buffer.length} fields`,
|
|
322
|
-
{
|
|
323
|
-
circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
|
|
324
|
-
// does not include reading the proof from disk
|
|
325
|
-
duration: provingResult.duration,
|
|
326
|
-
proofSize: proof.buffer.length,
|
|
327
|
-
eventName: 'circuit-proving',
|
|
328
|
-
inputSize: input.toBuffer().length,
|
|
329
|
-
outputSize: output.toBuffer().length,
|
|
330
|
-
circuitSize: vkData.circuitSize,
|
|
331
|
-
numPublicInputs: vkData.numPublicInputs,
|
|
332
|
-
} satisfies CircuitProvingStats,
|
|
333
|
-
);
|
|
465
|
+
private async generateAvmProofWithBB(input: AvmCircuitInputs, workingDirectory: string): Promise<BBSuccess> {
|
|
466
|
+
logger.debug(`Proving avm-circuit...`);
|
|
334
467
|
|
|
335
|
-
|
|
468
|
+
const provingResult = await generateAvmProof(this.config.bbBinaryPath, workingDirectory, input, logger.debug);
|
|
469
|
+
|
|
470
|
+
if (provingResult.status === BB_RESULT.FAILURE) {
|
|
471
|
+
logger.error(`Failed to generate proof for avm-circuit: ${provingResult.reason}`);
|
|
472
|
+
throw new Error(provingResult.reason);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
return provingResult;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
private async createAvmProof(input: AvmCircuitInputs): Promise<ProofAndVerificationKey> {
|
|
479
|
+
const operation = async (bbWorkingDirectory: string): Promise<ProofAndVerificationKey> => {
|
|
480
|
+
const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory);
|
|
481
|
+
|
|
482
|
+
const rawProof = await fs.readFile(provingResult.proofPath!);
|
|
483
|
+
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6773): this VK data format is wrong.
|
|
484
|
+
// In particular, the number of public inputs, etc will be wrong.
|
|
485
|
+
const verificationKey = await extractVkData(provingResult.vkPath!);
|
|
486
|
+
const proof = new Proof(rawProof, verificationKey.numPublicInputs);
|
|
487
|
+
|
|
488
|
+
const circuitType = 'avm-circuit' as const;
|
|
489
|
+
logger.info(
|
|
490
|
+
`Generated proof for ${circuitType} in ${Math.ceil(provingResult.duration)} ms, size: ${
|
|
491
|
+
proof.buffer.length
|
|
492
|
+
} bytes`,
|
|
493
|
+
{
|
|
494
|
+
circuitName: circuitType,
|
|
495
|
+
// does not include reading the proof from disk
|
|
496
|
+
duration: provingResult.duration,
|
|
497
|
+
proofSize: proof.buffer.length,
|
|
498
|
+
eventName: 'circuit-proving',
|
|
499
|
+
inputSize: input.toBuffer().length,
|
|
500
|
+
circuitSize: verificationKey.circuitSize,
|
|
501
|
+
numPublicInputs: verificationKey.numPublicInputs,
|
|
502
|
+
} satisfies CircuitProvingStats,
|
|
503
|
+
);
|
|
504
|
+
|
|
505
|
+
return { proof, verificationKey };
|
|
506
|
+
};
|
|
507
|
+
return await runInDirectory(this.config.bbWorkingDirectory, operation);
|
|
336
508
|
}
|
|
337
509
|
|
|
338
510
|
/**
|
|
@@ -344,7 +516,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
344
516
|
* @param convertOutput - Function for parsing the output witness to it's corresponding object
|
|
345
517
|
* @returns The circuits output object and it's proof
|
|
346
518
|
*/
|
|
347
|
-
|
|
519
|
+
private async createRecursiveProof<
|
|
348
520
|
PROOF_LENGTH extends number,
|
|
349
521
|
CircuitInputType extends { toBuffer: () => Buffer },
|
|
350
522
|
CircuitOutputType extends { toBuffer: () => Buffer },
|
|
@@ -354,86 +526,38 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
354
526
|
proofLength: PROOF_LENGTH,
|
|
355
527
|
convertInput: (input: CircuitInputType) => WitnessMap,
|
|
356
528
|
convertOutput: (outputWitness: WitnessMap) => CircuitOutputType,
|
|
357
|
-
): Promise<
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
//
|
|
366
|
-
const outputWitnessFile = `${bbWorkingDirectory}/partial-witness.gz`;
|
|
367
|
-
|
|
368
|
-
// Generate the partial witness using the ACVM
|
|
369
|
-
// A further temp directory will be created beneath ours and then cleaned up after the partial witness has been copied to our specified location
|
|
370
|
-
const simulator = new NativeACVMSimulator(
|
|
371
|
-
this.config.acvmWorkingDirectory,
|
|
372
|
-
this.config.acvmBinaryPath,
|
|
373
|
-
outputWitnessFile,
|
|
374
|
-
);
|
|
375
|
-
|
|
376
|
-
const artifact = ServerCircuitArtifacts[circuitType];
|
|
377
|
-
|
|
378
|
-
logger.debug(`Generating witness data for ${circuitType}`);
|
|
379
|
-
|
|
380
|
-
const timer = new Timer();
|
|
381
|
-
const witnessMap = convertInput(input);
|
|
382
|
-
const outputWitness = await simulator.simulateCircuit(witnessMap, artifact);
|
|
383
|
-
|
|
384
|
-
const output = convertOutput(outputWitness);
|
|
385
|
-
|
|
386
|
-
const inputSize = input.toBuffer().length;
|
|
387
|
-
const outputSize = output.toBuffer().length;
|
|
388
|
-
logger.debug(`Generated witness`, {
|
|
389
|
-
circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
|
|
390
|
-
duration: timer.ms(),
|
|
391
|
-
inputSize,
|
|
392
|
-
outputSize,
|
|
393
|
-
eventName: 'circuit-witness-generation',
|
|
394
|
-
} satisfies CircuitWitnessGenerationStats);
|
|
395
|
-
|
|
396
|
-
// Now prove the circuit from the generated witness
|
|
397
|
-
logger.debug(`Proving ${circuitType}...`);
|
|
398
|
-
|
|
399
|
-
const provingResult = await generateProof(
|
|
400
|
-
this.config.bbBinaryPath,
|
|
401
|
-
bbWorkingDirectory,
|
|
402
|
-
circuitType,
|
|
403
|
-
Buffer.from(artifact.bytecode, 'base64'),
|
|
404
|
-
outputWitnessFile,
|
|
405
|
-
logger.debug,
|
|
406
|
-
);
|
|
407
|
-
|
|
408
|
-
if (provingResult.status === BB_RESULT.FAILURE) {
|
|
409
|
-
logger.error(`Failed to generate proof for ${circuitType}: ${provingResult.reason}`);
|
|
410
|
-
throw new Error(provingResult.reason);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// Ensure our vk cache is up to date
|
|
414
|
-
const vkData = await this.updateVerificationKeyAfterProof(provingResult.vkPath!, circuitType);
|
|
415
|
-
|
|
416
|
-
// Read the proof and then cleanup up our temporary directory
|
|
529
|
+
): Promise<{ circuitOutput: CircuitOutputType; proof: RecursiveProof<PROOF_LENGTH> }> {
|
|
530
|
+
const operation = async (bbWorkingDirectory: string) => {
|
|
531
|
+
const {
|
|
532
|
+
provingResult,
|
|
533
|
+
vkData,
|
|
534
|
+
circuitOutput: output,
|
|
535
|
+
} = await this.generateProofWithBB(input, circuitType, convertInput, convertOutput, bbWorkingDirectory);
|
|
536
|
+
|
|
537
|
+
// Read the proof as fields
|
|
417
538
|
const proof = await this.readProofAsFields(provingResult.proofPath!, circuitType, proofLength);
|
|
418
539
|
|
|
419
540
|
logger.info(
|
|
420
|
-
`Generated proof for ${circuitType} in ${provingResult.duration} ms, size: ${
|
|
541
|
+
`Generated proof for ${circuitType} in ${Math.ceil(provingResult.duration)} ms, size: ${
|
|
542
|
+
proof.proof.length
|
|
543
|
+
} fields`,
|
|
421
544
|
{
|
|
422
545
|
circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
|
|
423
546
|
circuitSize: vkData.circuitSize,
|
|
424
547
|
duration: provingResult.duration,
|
|
425
|
-
inputSize,
|
|
426
|
-
outputSize,
|
|
548
|
+
inputSize: output.toBuffer().length,
|
|
427
549
|
proofSize: proof.binaryProof.buffer.length,
|
|
428
550
|
eventName: 'circuit-proving',
|
|
429
551
|
numPublicInputs: vkData.numPublicInputs,
|
|
430
552
|
} satisfies CircuitProvingStats,
|
|
431
553
|
);
|
|
432
554
|
|
|
433
|
-
return
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
555
|
+
return {
|
|
556
|
+
circuitOutput: output,
|
|
557
|
+
proof,
|
|
558
|
+
};
|
|
559
|
+
};
|
|
560
|
+
return await runInDirectory(this.config.bbWorkingDirectory, operation);
|
|
437
561
|
}
|
|
438
562
|
|
|
439
563
|
/**
|
|
@@ -442,33 +566,50 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
442
566
|
* @param proof - The proof to be verified
|
|
443
567
|
*/
|
|
444
568
|
public async verifyProof(circuitType: ServerProtocolArtifact, proof: Proof) {
|
|
445
|
-
// Create random directory to be used for temp files
|
|
446
|
-
const bbWorkingDirectory = `${this.config.bbWorkingDirectory}/${randomBytes(8).toString('hex')}`;
|
|
447
|
-
await fs.mkdir(bbWorkingDirectory, { recursive: true });
|
|
448
|
-
|
|
449
|
-
const proofFileName = `${bbWorkingDirectory}/proof`;
|
|
450
|
-
const verificationKeyPath = `${bbWorkingDirectory}/vk`;
|
|
451
569
|
const verificationKey = await this.getVerificationKeyDataForCircuit(circuitType);
|
|
570
|
+
return await this.verifyWithKey(verificationKey, proof);
|
|
571
|
+
}
|
|
452
572
|
|
|
453
|
-
|
|
573
|
+
public async verifyAvmProof(proof: Proof, verificationKey: VerificationKeyData) {
|
|
574
|
+
return await this.verifyWithKeyInternal(proof, verificationKey, verifyAvmProof);
|
|
575
|
+
}
|
|
454
576
|
|
|
455
|
-
|
|
456
|
-
await
|
|
577
|
+
public async verifyWithKey(verificationKey: VerificationKeyData, proof: Proof) {
|
|
578
|
+
return await this.verifyWithKeyInternal(proof, verificationKey, verifyProof);
|
|
579
|
+
}
|
|
457
580
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
581
|
+
private async verifyWithKeyInternal(
|
|
582
|
+
proof: Proof,
|
|
583
|
+
verificationKey: VerificationKeyData,
|
|
584
|
+
verificationFunction: VerificationFunction,
|
|
585
|
+
) {
|
|
586
|
+
const operation = async (bbWorkingDirectory: string) => {
|
|
587
|
+
const proofFileName = path.join(bbWorkingDirectory, PROOF_FILENAME);
|
|
588
|
+
const verificationKeyPath = path.join(bbWorkingDirectory, VK_FILENAME);
|
|
461
589
|
|
|
462
|
-
|
|
590
|
+
await fs.writeFile(proofFileName, proof.buffer);
|
|
591
|
+
await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes);
|
|
463
592
|
|
|
464
|
-
|
|
593
|
+
const logFunction = (message: string) => {
|
|
594
|
+
logger.debug(`BB out - ${message}`);
|
|
595
|
+
};
|
|
465
596
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
597
|
+
const result = await verificationFunction(
|
|
598
|
+
this.config.bbBinaryPath,
|
|
599
|
+
proofFileName,
|
|
600
|
+
verificationKeyPath!,
|
|
601
|
+
logFunction,
|
|
602
|
+
);
|
|
603
|
+
|
|
604
|
+
if (result.status === BB_RESULT.FAILURE) {
|
|
605
|
+
const errorMessage = `Failed to verify proof from key!`;
|
|
606
|
+
throw new Error(errorMessage);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
logger.debug(`Successfully verified proof from key in ${result.duration} ms`);
|
|
610
|
+
};
|
|
470
611
|
|
|
471
|
-
|
|
612
|
+
await runInDirectory(this.config.bbWorkingDirectory, operation);
|
|
472
613
|
}
|
|
473
614
|
|
|
474
615
|
/**
|
|
@@ -478,16 +619,66 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
478
619
|
*/
|
|
479
620
|
public async getVerificationKeyForCircuit(circuitType: ServerProtocolArtifact): Promise<VerificationKeyAsFields> {
|
|
480
621
|
const vkData = await this.getVerificationKeyDataForCircuit(circuitType);
|
|
481
|
-
return
|
|
622
|
+
return vkData.clone().keyAsFields;
|
|
482
623
|
}
|
|
483
624
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
625
|
+
/**
|
|
626
|
+
* Will check a recursive proof argument for validity of it's 'fields' format of proof and convert if required
|
|
627
|
+
* @param proof - The input proof that may need converting
|
|
628
|
+
* @returns - The valid proof
|
|
629
|
+
*/
|
|
630
|
+
public async ensureValidProof(
|
|
631
|
+
proof: RecursiveProof<typeof NESTED_RECURSIVE_PROOF_LENGTH>,
|
|
632
|
+
circuit: ServerProtocolArtifact,
|
|
633
|
+
vk: VerificationKeyData,
|
|
634
|
+
) {
|
|
635
|
+
// If the 'fields' proof is already valid then simply return
|
|
636
|
+
// This will be false for proofs coming from clients
|
|
637
|
+
if (proof.fieldsValid) {
|
|
638
|
+
return proof;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
const operation = async (bbWorkingDirectory: string) => {
|
|
642
|
+
const numPublicInputs = vk.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
|
|
643
|
+
const proofFullFilename = path.join(bbWorkingDirectory, PROOF_FILENAME);
|
|
644
|
+
const vkFullFilename = path.join(bbWorkingDirectory, VK_FILENAME);
|
|
645
|
+
|
|
646
|
+
logger.debug(
|
|
647
|
+
`Converting proof to fields format for circuit ${circuit}, directory ${bbWorkingDirectory}, num public inputs: ${vk.numPublicInputs}, proof length ${proof.binaryProof.buffer.length}, vk length ${vk.keyAsBytes.length}`,
|
|
648
|
+
);
|
|
649
|
+
|
|
650
|
+
await fs.writeFile(proofFullFilename, proof.binaryProof.buffer);
|
|
651
|
+
await fs.writeFile(vkFullFilename, vk.keyAsBytes);
|
|
652
|
+
|
|
653
|
+
const logFunction = (message: string) => {
|
|
654
|
+
logger.debug(`${circuit} BB out - ${message}`);
|
|
655
|
+
};
|
|
656
|
+
|
|
657
|
+
const result = await writeProofAsFields(
|
|
658
|
+
this.config.bbBinaryPath,
|
|
659
|
+
bbWorkingDirectory,
|
|
660
|
+
PROOF_FILENAME,
|
|
661
|
+
vkFullFilename,
|
|
662
|
+
logFunction,
|
|
663
|
+
);
|
|
664
|
+
|
|
665
|
+
if (result.status === BB_RESULT.FAILURE) {
|
|
666
|
+
const errorMessage = `Failed to convert ${circuit} proof to fields, ${result.reason}`;
|
|
667
|
+
throw new Error(errorMessage);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
const proofString = await fs.readFile(path.join(bbWorkingDirectory, PROOF_FIELDS_FILENAME), {
|
|
671
|
+
encoding: 'utf-8',
|
|
672
|
+
});
|
|
673
|
+
const json = JSON.parse(proofString);
|
|
674
|
+
const fields = json.slice(numPublicInputs).map(Fr.fromString);
|
|
675
|
+
return new RecursiveProof<typeof NESTED_RECURSIVE_PROOF_LENGTH>(
|
|
676
|
+
fields,
|
|
677
|
+
new Proof(proof.binaryProof.buffer, vk.numPublicInputs),
|
|
678
|
+
true,
|
|
679
|
+
);
|
|
680
|
+
};
|
|
681
|
+
return await runInDirectory(this.config.bbWorkingDirectory, operation);
|
|
491
682
|
}
|
|
492
683
|
|
|
493
684
|
/**
|
|
@@ -509,37 +700,12 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
509
700
|
if (result.status === BB_RESULT.FAILURE) {
|
|
510
701
|
throw new Error(`Failed to generate verification key for ${circuitType}, ${result.reason}`);
|
|
511
702
|
}
|
|
512
|
-
return
|
|
703
|
+
return extractVkData(result.vkPath!);
|
|
513
704
|
});
|
|
514
705
|
this.verificationKeys.set(circuitType, promise);
|
|
515
706
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
/**
|
|
520
|
-
* Reads the verification key data stored at the specified location and parses into a VerificationKeyData
|
|
521
|
-
* @param filePath - The directory containing the verification key data files
|
|
522
|
-
* @returns The verification key data
|
|
523
|
-
*/
|
|
524
|
-
private async convertVk(filePath: string): Promise<VerificationKeyData> {
|
|
525
|
-
const [rawFields, rawBinary] = await Promise.all([
|
|
526
|
-
fs.readFile(`${filePath}/${VK_FIELDS_FILENAME}`, { encoding: 'utf-8' }),
|
|
527
|
-
fs.readFile(`${filePath}/${VK_FILENAME}`),
|
|
528
|
-
]);
|
|
529
|
-
const fieldsJson = JSON.parse(rawFields);
|
|
530
|
-
const fields = fieldsJson.map(Fr.fromString);
|
|
531
|
-
// The first item is the hash, this is not part of the actual VK
|
|
532
|
-
const vkHash = fields[0];
|
|
533
|
-
const actualVk = fields.slice(1);
|
|
534
|
-
const vk: VerificationKeyData = {
|
|
535
|
-
hash: vkHash,
|
|
536
|
-
keyAsFields: actualVk as Tuple<Fr, typeof VERIFICATION_KEY_LENGTH_IN_FIELDS>,
|
|
537
|
-
keyAsBytes: rawBinary,
|
|
538
|
-
numPublicInputs: Number(actualVk[CIRCUIT_PUBLIC_INPUTS_INDEX]),
|
|
539
|
-
circuitSize: Number(actualVk[CIRCUIT_SIZE_INDEX]),
|
|
540
|
-
isRecursive: actualVk[CIRCUIT_RECURSIVE_INDEX] == Fr.ONE,
|
|
541
|
-
};
|
|
542
|
-
return vk;
|
|
707
|
+
const vk = await promise;
|
|
708
|
+
return vk.clone();
|
|
543
709
|
}
|
|
544
710
|
|
|
545
711
|
/**
|
|
@@ -553,7 +719,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
553
719
|
): Promise<VerificationKeyData> {
|
|
554
720
|
let promise = this.verificationKeys.get(circuitType);
|
|
555
721
|
if (!promise) {
|
|
556
|
-
promise =
|
|
722
|
+
promise = extractVkData(filePath);
|
|
557
723
|
this.verificationKeys.set(circuitType, promise);
|
|
558
724
|
}
|
|
559
725
|
return promise;
|
|
@@ -570,26 +736,32 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
570
736
|
circuitType: ServerProtocolArtifact,
|
|
571
737
|
proofLength: PROOF_LENGTH,
|
|
572
738
|
): Promise<RecursiveProof<PROOF_LENGTH>> {
|
|
739
|
+
const proofFilename = path.join(filePath, PROOF_FILENAME);
|
|
740
|
+
const proofFieldsFilename = path.join(filePath, PROOF_FIELDS_FILENAME);
|
|
741
|
+
|
|
573
742
|
const [binaryProof, proofString] = await Promise.all([
|
|
574
|
-
fs.readFile(
|
|
575
|
-
fs.readFile(
|
|
743
|
+
fs.readFile(proofFilename),
|
|
744
|
+
fs.readFile(proofFieldsFilename, { encoding: 'utf-8' }),
|
|
576
745
|
]);
|
|
577
746
|
const json = JSON.parse(proofString);
|
|
578
|
-
const fields = json.map(Fr.fromString);
|
|
579
747
|
const vkData = await this.verificationKeys.get(circuitType);
|
|
580
748
|
if (!vkData) {
|
|
581
749
|
throw new Error(`Invalid verification key for ${circuitType}`);
|
|
582
750
|
}
|
|
583
751
|
const numPublicInputs = CIRCUITS_WITHOUT_AGGREGATION.has(circuitType)
|
|
584
752
|
? vkData.numPublicInputs
|
|
585
|
-
: vkData.numPublicInputs -
|
|
586
|
-
const fieldsWithoutPublicInputs =
|
|
753
|
+
: vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
|
|
754
|
+
const fieldsWithoutPublicInputs = json.slice(numPublicInputs).map(Fr.fromString);
|
|
587
755
|
logger.debug(
|
|
588
|
-
`Circuit type: ${circuitType}, complete proof length: ${
|
|
756
|
+
`Circuit type: ${circuitType}, complete proof length: ${json.length}, without public inputs: ${fieldsWithoutPublicInputs.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}, is recursive: ${vkData.isRecursive}, raw length: ${binaryProof.length}`,
|
|
757
|
+
);
|
|
758
|
+
const proof = new RecursiveProof<PROOF_LENGTH>(
|
|
759
|
+
fieldsWithoutPublicInputs,
|
|
760
|
+
new Proof(binaryProof, numPublicInputs),
|
|
761
|
+
true,
|
|
589
762
|
);
|
|
590
|
-
const proof = new RecursiveProof<PROOF_LENGTH>(fieldsWithoutPublicInputs, new Proof(binaryProof));
|
|
591
763
|
if (proof.proof.length !== proofLength) {
|
|
592
|
-
throw new Error(
|
|
764
|
+
throw new Error(`Proof length doesn't match expected length (${proof.proof.length} != ${proofLength})`);
|
|
593
765
|
}
|
|
594
766
|
|
|
595
767
|
return proof;
|