@aztec/bb-prover 0.40.1 → 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 +37 -2
- package/dest/bb/execute.d.ts.map +1 -1
- package/dest/bb/execute.js +276 -75
- 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 +4 -9
- package/dest/prover/bb_native_proof_creator.d.ts.map +1 -1
- package/dest/prover/bb_native_proof_creator.js +77 -101
- package/dest/prover/bb_prover.d.ts +35 -23
- package/dest/prover/bb_prover.d.ts.map +1 -1
- package/dest/prover/bb_prover.js +247 -155
- package/dest/stats.d.ts +2 -5
- package/dest/stats.d.ts.map +1 -1
- package/dest/stats.js +27 -26
- 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 +371 -83
- 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 +139 -119
- package/src/prover/bb_prover.ts +454 -242
- package/src/stats.ts +30 -45
- 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';
|
|
11
|
+
import { type CircuitProvingStats, type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats';
|
|
10
12
|
import {
|
|
13
|
+
AGGREGATION_OBJECT_LENGTH,
|
|
14
|
+
type AvmCircuitInputs,
|
|
11
15
|
type BaseOrMergeRollupPublicInputs,
|
|
12
16
|
type BaseParityInputs,
|
|
13
17
|
type BaseRollupInputs,
|
|
18
|
+
EmptyNestedCircuitInputs,
|
|
19
|
+
EmptyNestedData,
|
|
14
20
|
Fr,
|
|
15
21
|
type KernelCircuitPublicInputs,
|
|
16
22
|
type MergeRollupInputs,
|
|
17
|
-
|
|
18
|
-
type
|
|
19
|
-
|
|
23
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
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
|
-
import {
|
|
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';
|
|
83
|
+
import { mapProtocolArtifactNameToCircuitName } from '../stats.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,19 +122,19 @@ 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
|
|
118
|
-
|
|
119
|
-
const [circuitOutput, proof] = await this.createRecursiveProof<typeof RECURSIVE_PROOF_LENGTH, ParityPublicInputs>(
|
|
120
|
-
witnessMap,
|
|
125
|
+
const { circuitOutput, proof } = await this.createRecursiveProof(
|
|
126
|
+
inputs,
|
|
121
127
|
'BaseParityArtifact',
|
|
128
|
+
RECURSIVE_PROOF_LENGTH,
|
|
129
|
+
convertBaseParityInputsToWitnessMap,
|
|
122
130
|
convertBaseParityOutputsFromWitnessMap,
|
|
123
131
|
);
|
|
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,18 +145,30 @@ 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
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
148
|
+
const { circuitOutput, proof } = await this.createRecursiveProof(
|
|
149
|
+
inputs,
|
|
150
|
+
'RootParityArtifact',
|
|
151
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
152
|
+
convertRootParityInputsToWitnessMap,
|
|
153
|
+
convertRootParityOutputsFromWitnessMap,
|
|
154
|
+
);
|
|
146
155
|
|
|
147
156
|
const verificationKey = await this.getVerificationKeyDataForCircuit('RootParityArtifact');
|
|
148
157
|
|
|
149
|
-
|
|
158
|
+
await this.verifyProof('RootParityArtifact', proof.binaryProof);
|
|
159
|
+
|
|
160
|
+
return new RootParityInput(proof, verificationKey.keyAsFields, circuitOutput);
|
|
161
|
+
}
|
|
150
162
|
|
|
151
|
-
|
|
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;
|
|
152
172
|
}
|
|
153
173
|
|
|
154
174
|
/**
|
|
@@ -158,17 +178,37 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
158
178
|
*/
|
|
159
179
|
public async getPublicKernelProof(
|
|
160
180
|
kernelRequest: PublicKernelNonTailRequest,
|
|
161
|
-
): Promise<
|
|
181
|
+
): Promise<PublicInputsAndRecursiveProof<PublicKernelCircuitPublicInputs>> {
|
|
162
182
|
const kernelOps = PublicKernelArtifactMapping[kernelRequest.type];
|
|
163
183
|
if (kernelOps === undefined) {
|
|
164
184
|
throw new Error(`Unable to prove kernel type ${PublicKernelType[kernelRequest.type]}`);
|
|
165
185
|
}
|
|
166
|
-
const witnessMap = kernelOps.convertInputs(kernelRequest.inputs);
|
|
167
186
|
|
|
168
|
-
|
|
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(
|
|
200
|
+
kernelRequest.inputs,
|
|
201
|
+
kernelOps.artifact,
|
|
202
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
203
|
+
kernelOps.convertInputs,
|
|
204
|
+
kernelOps.convertOutputs,
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
const verificationKey = await this.getVerificationKeyDataForCircuit(kernelOps.artifact);
|
|
208
|
+
|
|
209
|
+
await this.verifyProof(kernelOps.artifact, proof.binaryProof);
|
|
169
210
|
|
|
170
|
-
|
|
171
|
-
return makePublicInputsAndProof(result, proof);
|
|
211
|
+
return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
|
|
172
212
|
}
|
|
173
213
|
|
|
174
214
|
/**
|
|
@@ -178,13 +218,20 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
178
218
|
*/
|
|
179
219
|
public async getPublicTailProof(
|
|
180
220
|
kernelRequest: PublicKernelTailRequest,
|
|
181
|
-
): Promise<
|
|
182
|
-
const
|
|
221
|
+
): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>> {
|
|
222
|
+
const { circuitOutput, proof } = await this.createRecursiveProof(
|
|
223
|
+
kernelRequest.inputs,
|
|
224
|
+
'PublicKernelTailArtifact',
|
|
225
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
226
|
+
convertPublicTailInputsToWitnessMap,
|
|
227
|
+
convertPublicTailOutputFromWitnessMap,
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
const verificationKey = await this.getVerificationKeyDataForCircuit('PublicKernelTailArtifact');
|
|
183
231
|
|
|
184
|
-
|
|
232
|
+
await this.verifyProof('PublicKernelTailArtifact', proof.binaryProof);
|
|
185
233
|
|
|
186
|
-
|
|
187
|
-
return makePublicInputsAndProof(result, proof);
|
|
234
|
+
return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
|
|
188
235
|
}
|
|
189
236
|
|
|
190
237
|
/**
|
|
@@ -194,15 +241,29 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
194
241
|
*/
|
|
195
242
|
public async getBaseRollupProof(
|
|
196
243
|
input: BaseRollupInputs,
|
|
197
|
-
): Promise<
|
|
198
|
-
|
|
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(
|
|
253
|
+
input,
|
|
254
|
+
'BaseRollupArtifact',
|
|
255
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
256
|
+
convertBaseRollupInputsToWitnessMap,
|
|
257
|
+
convertBaseRollupOutputsFromWitnessMap,
|
|
258
|
+
);
|
|
199
259
|
|
|
200
|
-
const
|
|
260
|
+
const verificationKey = await this.getVerificationKeyDataForCircuit('BaseRollupArtifact');
|
|
201
261
|
|
|
202
|
-
|
|
262
|
+
await this.verifyProof('BaseRollupArtifact', proof.binaryProof);
|
|
203
263
|
|
|
204
|
-
return
|
|
264
|
+
return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
|
|
205
265
|
}
|
|
266
|
+
|
|
206
267
|
/**
|
|
207
268
|
* Simulates the merge rollup circuit from its inputs.
|
|
208
269
|
* @param input - Inputs to the circuit.
|
|
@@ -210,17 +271,20 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
210
271
|
*/
|
|
211
272
|
public async getMergeRollupProof(
|
|
212
273
|
input: MergeRollupInputs,
|
|
213
|
-
): Promise<
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
274
|
+
): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>> {
|
|
275
|
+
const { circuitOutput, proof } = await this.createRecursiveProof(
|
|
276
|
+
input,
|
|
277
|
+
'MergeRollupArtifact',
|
|
278
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
279
|
+
convertMergeRollupInputsToWitnessMap,
|
|
280
|
+
convertMergeRollupOutputsFromWitnessMap,
|
|
281
|
+
);
|
|
218
282
|
|
|
219
|
-
const
|
|
283
|
+
const verificationKey = await this.getVerificationKeyDataForCircuit('MergeRollupArtifact');
|
|
220
284
|
|
|
221
|
-
|
|
285
|
+
await this.verifyProof('MergeRollupArtifact', proof.binaryProof);
|
|
222
286
|
|
|
223
|
-
return
|
|
287
|
+
return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
|
|
224
288
|
}
|
|
225
289
|
|
|
226
290
|
/**
|
|
@@ -228,30 +292,84 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
228
292
|
* @param input - Inputs to the circuit.
|
|
229
293
|
* @returns The public inputs as outputs of the simulation.
|
|
230
294
|
*/
|
|
231
|
-
public async getRootRollupProof(
|
|
232
|
-
|
|
233
|
-
|
|
295
|
+
public async getRootRollupProof(
|
|
296
|
+
input: RootRollupInputs,
|
|
297
|
+
): Promise<PublicInputsAndRecursiveProof<RootRollupPublicInputs>> {
|
|
298
|
+
const { circuitOutput, proof } = await this.createProof(
|
|
299
|
+
input,
|
|
300
|
+
'RootRollupArtifact',
|
|
301
|
+
convertRootRollupInputsToWitnessMap,
|
|
302
|
+
convertRootRollupOutputsFromWitnessMap,
|
|
303
|
+
);
|
|
234
304
|
|
|
235
|
-
const
|
|
305
|
+
const recursiveProof = makeRecursiveProofFromBinary(proof, NESTED_RECURSIVE_PROOF_LENGTH);
|
|
236
306
|
|
|
237
|
-
const
|
|
307
|
+
const verificationKey = await this.getVerificationKeyDataForCircuit('RootRollupArtifact');
|
|
238
308
|
|
|
239
309
|
await this.verifyProof('RootRollupArtifact', proof);
|
|
240
310
|
|
|
241
|
-
|
|
242
|
-
|
|
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;
|
|
326
|
+
}
|
|
327
|
+
|
|
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);
|
|
243
342
|
}
|
|
244
343
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
const
|
|
249
|
-
|
|
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);
|
|
250
357
|
|
|
251
|
-
|
|
358
|
+
return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
|
|
359
|
+
}
|
|
252
360
|
|
|
361
|
+
private async generateProofWithBB<
|
|
362
|
+
Input extends { toBuffer: () => Buffer },
|
|
363
|
+
Output extends { toBuffer: () => Buffer },
|
|
364
|
+
>(
|
|
365
|
+
input: Input,
|
|
366
|
+
circuitType: ServerProtocolArtifact,
|
|
367
|
+
convertInput: (input: Input) => WitnessMap,
|
|
368
|
+
convertOutput: (outputWitness: WitnessMap) => Output,
|
|
369
|
+
workingDirectory: string,
|
|
370
|
+
): Promise<{ circuitOutput: Output; vkData: VerificationKeyData; provingResult: BBSuccess }> {
|
|
253
371
|
// Have the ACVM write the partial witness here
|
|
254
|
-
const outputWitnessFile =
|
|
372
|
+
const outputWitnessFile = path.join(workingDirectory, 'partial-witness.gz');
|
|
255
373
|
|
|
256
374
|
// Generate the partial witness using the ACVM
|
|
257
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
|
|
@@ -265,22 +383,25 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
265
383
|
|
|
266
384
|
logger.debug(`Generating witness data for ${circuitType}`);
|
|
267
385
|
|
|
386
|
+
const inputWitness = convertInput(input);
|
|
268
387
|
const timer = new Timer();
|
|
269
|
-
const outputWitness = await simulator.simulateCircuit(
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
388
|
+
const outputWitness = await simulator.simulateCircuit(inputWitness, artifact);
|
|
389
|
+
const witnessGenerationDuration = timer.ms();
|
|
390
|
+
const output = convertOutput(outputWitness);
|
|
391
|
+
logger.debug(`Generated witness`, {
|
|
392
|
+
circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
|
|
393
|
+
duration: witnessGenerationDuration,
|
|
394
|
+
inputSize: input.toBuffer().length,
|
|
395
|
+
outputSize: output.toBuffer().length,
|
|
396
|
+
eventName: 'circuit-witness-generation',
|
|
397
|
+
} satisfies CircuitWitnessGenerationStats);
|
|
277
398
|
|
|
278
399
|
// Now prove the circuit from the generated witness
|
|
279
400
|
logger.debug(`Proving ${circuitType}...`);
|
|
280
401
|
|
|
281
402
|
const provingResult = await generateProof(
|
|
282
403
|
this.config.bbBinaryPath,
|
|
283
|
-
|
|
404
|
+
workingDirectory,
|
|
284
405
|
circuitType,
|
|
285
406
|
Buffer.from(artifact.bytecode, 'base64'),
|
|
286
407
|
outputWitnessFile,
|
|
@@ -293,115 +414,150 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
293
414
|
}
|
|
294
415
|
|
|
295
416
|
// Ensure our vk cache is up to date
|
|
296
|
-
await this.updateVerificationKeyAfterProof(provingResult.vkPath!, circuitType);
|
|
297
|
-
|
|
298
|
-
// Read the proof and then cleanup up our temporary directory
|
|
299
|
-
const proof = await fs.readFile(`${provingResult.proofPath!}/${PROOF_FILENAME}`);
|
|
300
|
-
|
|
301
|
-
// does not include reading the proof from disk above because duration comes from the bb wrapper
|
|
302
|
-
emitCircuitProvingStats(
|
|
303
|
-
circuitTypeToCircuitName(circuitType),
|
|
304
|
-
provingResult.duration,
|
|
305
|
-
witnessMap.size * Fr.SIZE_IN_BYTES,
|
|
306
|
-
outputWitness.size * Fr.SIZE_IN_BYTES,
|
|
307
|
-
proof.length,
|
|
308
|
-
logger,
|
|
309
|
-
);
|
|
310
|
-
|
|
311
|
-
await fs.rm(bbWorkingDirectory, { recursive: true, force: true });
|
|
312
|
-
|
|
313
|
-
logger.info(`Generated proof for ${circuitType} in ${provingResult.duration} ms, size: ${proof.length} fields`);
|
|
417
|
+
const vkData = await this.updateVerificationKeyAfterProof(provingResult.vkPath!, circuitType);
|
|
314
418
|
|
|
315
|
-
return
|
|
419
|
+
return {
|
|
420
|
+
circuitOutput: output,
|
|
421
|
+
vkData,
|
|
422
|
+
provingResult,
|
|
423
|
+
};
|
|
316
424
|
}
|
|
317
425
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
* @param witnessMap - The input witness
|
|
321
|
-
* @param circuitType - The type of circuit to be executed
|
|
322
|
-
* @param convertOutput - Function for parsing the output witness to it's corresponding object
|
|
323
|
-
* @returns The circuits output object and it's proof
|
|
324
|
-
*/
|
|
325
|
-
public async createRecursiveProof<PROOF_LENGTH extends number, CircuitOutputType>(
|
|
326
|
-
witnessMap: WitnessMap,
|
|
426
|
+
private async createProof<Input extends { toBuffer: () => Buffer }, Output extends { toBuffer: () => Buffer }>(
|
|
427
|
+
input: Input,
|
|
327
428
|
circuitType: ServerProtocolArtifact,
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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,
|
|
346
458
|
);
|
|
347
459
|
|
|
348
|
-
|
|
460
|
+
return { circuitOutput: output, proof };
|
|
461
|
+
};
|
|
462
|
+
return await runInDirectory(this.config.bbWorkingDirectory, operation);
|
|
463
|
+
}
|
|
349
464
|
|
|
350
|
-
|
|
465
|
+
private async generateAvmProofWithBB(input: AvmCircuitInputs, workingDirectory: string): Promise<BBSuccess> {
|
|
466
|
+
logger.debug(`Proving avm-circuit...`);
|
|
351
467
|
|
|
352
|
-
|
|
353
|
-
const outputWitness = await simulator.simulateCircuit(witnessMap, artifact);
|
|
468
|
+
const provingResult = await generateAvmProof(this.config.bbBinaryPath, workingDirectory, input, logger.debug);
|
|
354
469
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
outputWitness.size * Fr.SIZE_IN_BYTES,
|
|
360
|
-
logger,
|
|
361
|
-
);
|
|
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
|
+
}
|
|
362
474
|
|
|
363
|
-
|
|
475
|
+
return provingResult;
|
|
476
|
+
}
|
|
364
477
|
|
|
365
|
-
|
|
366
|
-
|
|
478
|
+
private async createAvmProof(input: AvmCircuitInputs): Promise<ProofAndVerificationKey> {
|
|
479
|
+
const operation = async (bbWorkingDirectory: string): Promise<ProofAndVerificationKey> => {
|
|
480
|
+
const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory);
|
|
367
481
|
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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,
|
|
375
503
|
);
|
|
376
504
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
505
|
+
return { proof, verificationKey };
|
|
506
|
+
};
|
|
507
|
+
return await runInDirectory(this.config.bbWorkingDirectory, operation);
|
|
508
|
+
}
|
|
381
509
|
|
|
382
|
-
|
|
383
|
-
|
|
510
|
+
/**
|
|
511
|
+
* Executes a circuit and returns it's outputs and corresponding proof with embedded aggregation object
|
|
512
|
+
* @param witnessMap - The input witness
|
|
513
|
+
* @param circuitType - The type of circuit to be executed
|
|
514
|
+
* @param proofLength - The length of the proof to be generated. This is a dummy parameter to aid in type checking
|
|
515
|
+
* @param convertInput - Function for mapping the input object to a witness map.
|
|
516
|
+
* @param convertOutput - Function for parsing the output witness to it's corresponding object
|
|
517
|
+
* @returns The circuits output object and it's proof
|
|
518
|
+
*/
|
|
519
|
+
private async createRecursiveProof<
|
|
520
|
+
PROOF_LENGTH extends number,
|
|
521
|
+
CircuitInputType extends { toBuffer: () => Buffer },
|
|
522
|
+
CircuitOutputType extends { toBuffer: () => Buffer },
|
|
523
|
+
>(
|
|
524
|
+
input: CircuitInputType,
|
|
525
|
+
circuitType: ServerProtocolArtifact,
|
|
526
|
+
proofLength: PROOF_LENGTH,
|
|
527
|
+
convertInput: (input: CircuitInputType) => WitnessMap,
|
|
528
|
+
convertOutput: (outputWitness: WitnessMap) => CircuitOutputType,
|
|
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);
|
|
384
536
|
|
|
385
|
-
// Read the proof
|
|
386
|
-
const proof = await this.readProofAsFields
|
|
537
|
+
// Read the proof as fields
|
|
538
|
+
const proof = await this.readProofAsFields(provingResult.proofPath!, circuitType, proofLength);
|
|
387
539
|
|
|
388
540
|
logger.info(
|
|
389
|
-
`Generated proof for ${circuitType} in ${provingResult.duration} ms, size: ${
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
541
|
+
`Generated proof for ${circuitType} in ${Math.ceil(provingResult.duration)} ms, size: ${
|
|
542
|
+
proof.proof.length
|
|
543
|
+
} fields`,
|
|
544
|
+
{
|
|
545
|
+
circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
|
|
546
|
+
circuitSize: vkData.circuitSize,
|
|
547
|
+
duration: provingResult.duration,
|
|
548
|
+
inputSize: output.toBuffer().length,
|
|
549
|
+
proofSize: proof.binaryProof.buffer.length,
|
|
550
|
+
eventName: 'circuit-proving',
|
|
551
|
+
numPublicInputs: vkData.numPublicInputs,
|
|
552
|
+
} satisfies CircuitProvingStats,
|
|
399
553
|
);
|
|
400
554
|
|
|
401
|
-
return
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
555
|
+
return {
|
|
556
|
+
circuitOutput: output,
|
|
557
|
+
proof,
|
|
558
|
+
};
|
|
559
|
+
};
|
|
560
|
+
return await runInDirectory(this.config.bbWorkingDirectory, operation);
|
|
405
561
|
}
|
|
406
562
|
|
|
407
563
|
/**
|
|
@@ -410,33 +566,50 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
410
566
|
* @param proof - The proof to be verified
|
|
411
567
|
*/
|
|
412
568
|
public async verifyProof(circuitType: ServerProtocolArtifact, proof: Proof) {
|
|
413
|
-
// Create random directory to be used for temp files
|
|
414
|
-
const bbWorkingDirectory = `${this.config.bbWorkingDirectory}/${randomBytes(8).toString('hex')}`;
|
|
415
|
-
await fs.mkdir(bbWorkingDirectory, { recursive: true });
|
|
416
|
-
|
|
417
|
-
const proofFileName = `${bbWorkingDirectory}/proof`;
|
|
418
|
-
const verificationKeyPath = `${bbWorkingDirectory}/vk`;
|
|
419
569
|
const verificationKey = await this.getVerificationKeyDataForCircuit(circuitType);
|
|
570
|
+
return await this.verifyWithKey(verificationKey, proof);
|
|
571
|
+
}
|
|
420
572
|
|
|
421
|
-
|
|
573
|
+
public async verifyAvmProof(proof: Proof, verificationKey: VerificationKeyData) {
|
|
574
|
+
return await this.verifyWithKeyInternal(proof, verificationKey, verifyAvmProof);
|
|
575
|
+
}
|
|
422
576
|
|
|
423
|
-
|
|
424
|
-
await
|
|
577
|
+
public async verifyWithKey(verificationKey: VerificationKeyData, proof: Proof) {
|
|
578
|
+
return await this.verifyWithKeyInternal(proof, verificationKey, verifyProof);
|
|
579
|
+
}
|
|
425
580
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
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);
|
|
429
589
|
|
|
430
|
-
|
|
590
|
+
await fs.writeFile(proofFileName, proof.buffer);
|
|
591
|
+
await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes);
|
|
431
592
|
|
|
432
|
-
|
|
593
|
+
const logFunction = (message: string) => {
|
|
594
|
+
logger.debug(`BB out - ${message}`);
|
|
595
|
+
};
|
|
433
596
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
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
|
+
};
|
|
438
611
|
|
|
439
|
-
|
|
612
|
+
await runInDirectory(this.config.bbWorkingDirectory, operation);
|
|
440
613
|
}
|
|
441
614
|
|
|
442
615
|
/**
|
|
@@ -446,16 +619,66 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
446
619
|
*/
|
|
447
620
|
public async getVerificationKeyForCircuit(circuitType: ServerProtocolArtifact): Promise<VerificationKeyAsFields> {
|
|
448
621
|
const vkData = await this.getVerificationKeyDataForCircuit(circuitType);
|
|
449
|
-
return
|
|
622
|
+
return vkData.clone().keyAsFields;
|
|
450
623
|
}
|
|
451
624
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
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);
|
|
459
682
|
}
|
|
460
683
|
|
|
461
684
|
/**
|
|
@@ -477,37 +700,12 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
477
700
|
if (result.status === BB_RESULT.FAILURE) {
|
|
478
701
|
throw new Error(`Failed to generate verification key for ${circuitType}, ${result.reason}`);
|
|
479
702
|
}
|
|
480
|
-
return
|
|
703
|
+
return extractVkData(result.vkPath!);
|
|
481
704
|
});
|
|
482
705
|
this.verificationKeys.set(circuitType, promise);
|
|
483
706
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
/**
|
|
488
|
-
* Reads the verification key data stored at the specified location and parses into a VerificationKeyData
|
|
489
|
-
* @param filePath - The directory containing the verification key data files
|
|
490
|
-
* @returns The verification key data
|
|
491
|
-
*/
|
|
492
|
-
private async convertVk(filePath: string): Promise<VerificationKeyData> {
|
|
493
|
-
const [rawFields, rawBinary] = await Promise.all([
|
|
494
|
-
fs.readFile(`${filePath}/${VK_FIELDS_FILENAME}`, { encoding: 'utf-8' }),
|
|
495
|
-
fs.readFile(`${filePath}/${VK_FILENAME}`),
|
|
496
|
-
]);
|
|
497
|
-
const fieldsJson = JSON.parse(rawFields);
|
|
498
|
-
const fields = fieldsJson.map(Fr.fromString);
|
|
499
|
-
// The first item is the hash, this is not part of the actual VK
|
|
500
|
-
const vkHash = fields[0];
|
|
501
|
-
const actualVk = fields.slice(1);
|
|
502
|
-
const vk: VerificationKeyData = {
|
|
503
|
-
hash: vkHash,
|
|
504
|
-
keyAsFields: actualVk as Tuple<Fr, typeof VERIFICATION_KEY_LENGTH_IN_FIELDS>,
|
|
505
|
-
keyAsBytes: rawBinary,
|
|
506
|
-
numPublicInputs: Number(actualVk[CIRCUIT_PUBLIC_INPUTS_INDEX]),
|
|
507
|
-
circuitSize: Number(actualVk[CIRCUIT_SIZE_INDEX]),
|
|
508
|
-
isRecursive: actualVk[CIRCUIT_RECURSIVE_INDEX] == Fr.ONE,
|
|
509
|
-
};
|
|
510
|
-
return vk;
|
|
707
|
+
const vk = await promise;
|
|
708
|
+
return vk.clone();
|
|
511
709
|
}
|
|
512
710
|
|
|
513
711
|
/**
|
|
@@ -515,13 +713,16 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
515
713
|
* @param filePath - The directory containing the verification key data files
|
|
516
714
|
* @param circuitType - The type of circuit to which the verification key corresponds
|
|
517
715
|
*/
|
|
518
|
-
private async updateVerificationKeyAfterProof(
|
|
716
|
+
private async updateVerificationKeyAfterProof(
|
|
717
|
+
filePath: string,
|
|
718
|
+
circuitType: ServerProtocolArtifact,
|
|
719
|
+
): Promise<VerificationKeyData> {
|
|
519
720
|
let promise = this.verificationKeys.get(circuitType);
|
|
520
721
|
if (!promise) {
|
|
521
|
-
promise =
|
|
722
|
+
promise = extractVkData(filePath);
|
|
522
723
|
this.verificationKeys.set(circuitType, promise);
|
|
523
724
|
}
|
|
524
|
-
|
|
725
|
+
return promise;
|
|
525
726
|
}
|
|
526
727
|
|
|
527
728
|
/**
|
|
@@ -533,25 +734,36 @@ export class BBNativeRollupProver implements ServerCircuitProver {
|
|
|
533
734
|
private async readProofAsFields<PROOF_LENGTH extends number>(
|
|
534
735
|
filePath: string,
|
|
535
736
|
circuitType: ServerProtocolArtifact,
|
|
737
|
+
proofLength: PROOF_LENGTH,
|
|
536
738
|
): Promise<RecursiveProof<PROOF_LENGTH>> {
|
|
739
|
+
const proofFilename = path.join(filePath, PROOF_FILENAME);
|
|
740
|
+
const proofFieldsFilename = path.join(filePath, PROOF_FIELDS_FILENAME);
|
|
741
|
+
|
|
537
742
|
const [binaryProof, proofString] = await Promise.all([
|
|
538
|
-
fs.readFile(
|
|
539
|
-
fs.readFile(
|
|
743
|
+
fs.readFile(proofFilename),
|
|
744
|
+
fs.readFile(proofFieldsFilename, { encoding: 'utf-8' }),
|
|
540
745
|
]);
|
|
541
746
|
const json = JSON.parse(proofString);
|
|
542
|
-
const fields = json.map(Fr.fromString);
|
|
543
747
|
const vkData = await this.verificationKeys.get(circuitType);
|
|
544
748
|
if (!vkData) {
|
|
545
749
|
throw new Error(`Invalid verification key for ${circuitType}`);
|
|
546
750
|
}
|
|
547
751
|
const numPublicInputs = CIRCUITS_WITHOUT_AGGREGATION.has(circuitType)
|
|
548
752
|
? vkData.numPublicInputs
|
|
549
|
-
: vkData.numPublicInputs -
|
|
550
|
-
const fieldsWithoutPublicInputs =
|
|
753
|
+
: vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
|
|
754
|
+
const fieldsWithoutPublicInputs = json.slice(numPublicInputs).map(Fr.fromString);
|
|
551
755
|
logger.debug(
|
|
552
|
-
`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}`,
|
|
553
757
|
);
|
|
554
|
-
const proof = new RecursiveProof<PROOF_LENGTH>(
|
|
758
|
+
const proof = new RecursiveProof<PROOF_LENGTH>(
|
|
759
|
+
fieldsWithoutPublicInputs,
|
|
760
|
+
new Proof(binaryProof, numPublicInputs),
|
|
761
|
+
true,
|
|
762
|
+
);
|
|
763
|
+
if (proof.proof.length !== proofLength) {
|
|
764
|
+
throw new Error(`Proof length doesn't match expected length (${proof.proof.length} != ${proofLength})`);
|
|
765
|
+
}
|
|
766
|
+
|
|
555
767
|
return proof;
|
|
556
768
|
}
|
|
557
769
|
}
|