gnark-plonky2-verifier/verifier/utils/deserialize.go
verifier/utils/deserialize.goRaw
1package utils
2
3import (
4 "encoding/json"
5 "io"
6 "math/big"
7 "os"
8
9 "github.com/consensys/gnark/frontend"
10 "github.com/succinctlabs/gnark-plonky2-verifier/field"
11 "github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
12 "github.com/succinctlabs/gnark-plonky2-verifier/utils"
13 "github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
14 "github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/gates"
15)
16
17type ProofWithPublicInputsRaw struct {
18 Proof struct {
19 WiresCap []string `json:"wires_cap"`
20 PlonkZsPartialProductsCap []string `json:"plonk_zs_partial_products_cap"`
21 QuotientPolysCap []string `json:"quotient_polys_cap"`
22 Openings struct {
23 Constants [][]uint64 `json:"constants"`
24 PlonkSigmas [][]uint64 `json:"plonk_sigmas"`
25 Wires [][]uint64 `json:"wires"`
26 PlonkZs [][]uint64 `json:"plonk_zs"`
27 PlonkZsNext [][]uint64 `json:"plonk_zs_next"`
28 PartialProducts [][]uint64 `json:"partial_products"`
29 QuotientPolys [][]uint64 `json:"quotient_polys"`
30 } `json:"openings"`
31 OpeningProof struct {
32 CommitPhaseMerkleCaps [][]string `json:"commit_phase_merkle_caps"`
33 QueryRoundProofs []struct {
34 InitialTreesProof struct {
35 EvalsProofs []EvalProofRaw `json:"evals_proofs"`
36 } `json:"initial_trees_proof"`
37 Steps []struct {
38 Evals [][]uint64 `json:"evals"`
39 MerkleProof struct {
40 Siblings []string `json:"siblings"`
41 } `json:"merkle_proof"`
42 } `json:"steps"`
43 } `json:"query_round_proofs"`
44 FinalPoly struct {
45 Coeffs [][]uint64 `json:"coeffs"`
46 } `json:"final_poly"`
47 PowWitness uint64 `json:"pow_witness"`
48 } `json:"opening_proof"`
49 } `json:"proof"`
50 PublicInputs []uint64 `json:"public_inputs"`
51}
52
53type EvalProofRaw struct {
54 LeafElements []uint64
55 MerkleProof MerkleProofRaw
56}
57
58func (e *EvalProofRaw) UnmarshalJSON(data []byte) error {
59 return json.Unmarshal(data, &[]interface{}{&e.LeafElements, &e.MerkleProof})
60}
61
62type MerkleProofRaw struct {
63 Hash []string
64}
65
66func (m *MerkleProofRaw) UnmarshalJSON(data []byte) error {
67 type SiblingObject struct {
68 Siblings []string // "siblings"
69 }
70
71 var siblings SiblingObject
72 if err := json.Unmarshal(data, &siblings); err != nil {
73 panic(err)
74 }
75
76 m.Hash = make([]string, len(siblings.Siblings))
77 copy(m.Hash[:], siblings.Siblings)
78
79 return nil
80}
81
82type CommonCircuitDataRaw struct {
83 Config struct {
84 NumWires uint64 `json:"num_wires"`
85 NumRoutedWires uint64 `json:"num_routed_wires"`
86 NumConstants uint64 `json:"num_constants"`
87 UseBaseArithmeticGate bool `json:"use_base_arithmetic_gate"`
88 SecurityBits uint64 `json:"security_bits"`
89 NumChallenges uint64 `json:"num_challenges"`
90 ZeroKnowledge bool `json:"zero_knowledge"`
91 MaxQuotientDegreeFactor uint64 `json:"max_quotient_degree_factor"`
92 FriConfig struct {
93 RateBits uint64 `json:"rate_bits"`
94 CapHeight uint64 `json:"cap_height"`
95 ProofOfWorkBits uint64 `json:"proof_of_work_bits"`
96 ReductionStrategy struct {
97 ConstantArityBits []uint64 `json:"ConstantArityBits"`
98 } `json:"reduction_strategy"`
99 NumQueryRounds uint64 `json:"num_query_rounds"`
100 } `json:"fri_config"`
101 } `json:"config"`
102 FriParams struct {
103 Config struct {
104 RateBits uint64 `json:"rate_bits"`
105 CapHeight uint64 `json:"cap_height"`
106 ProofOfWorkBits uint64 `json:"proof_of_work_bits"`
107 ReductionStrategy struct {
108 ConstantArityBits []uint64 `json:"ConstantArityBits"`
109 } `json:"reduction_strategy"`
110 NumQueryRounds uint64 `json:"num_query_rounds"`
111 } `json:"config"`
112 Hiding bool `json:"hiding"`
113 DegreeBits uint64 `json:"degree_bits"`
114 ReductionArityBits []uint64 `json:"reduction_arity_bits"`
115 } `json:"fri_params"`
116 Gates []string `json:"gates"`
117 SelectorsInfo struct {
118 SelectorIndices []uint64 `json:"selector_indices"`
119 Groups []struct {
120 Start uint64 `json:"start"`
121 End uint64 `json:"end"`
122 } `json:"groups"`
123 } `json:"selectors_info"`
124 QuotientDegreeFactor uint64 `json:"quotient_degree_factor"`
125 NumGateConstraints uint64 `json:"num_gate_constraints"`
126 NumConstants uint64 `json:"num_constants"`
127 NumPublicInputs uint64 `json:"num_public_inputs"`
128 KIs []uint64 `json:"k_is"`
129 NumPartialProducts uint64 `json:"num_partial_products"`
130}
131
132type ProofChallengesRaw struct {
133 PlonkBetas []uint64 `json:"plonk_betas"`
134 PlonkGammas []uint64 `json:"plonk_gammas"`
135 PlonkAlphas []uint64 `json:"plonk_alphas"`
136 PlonkZeta []uint64 `json:"plonk_zeta"`
137 FriChallenges struct {
138 FriAlpha []uint64 `json:"fri_alpha"`
139 FriBetas [][]uint64 `json:"fri_betas"`
140 FriPowResponse uint64 `json:"fri_pow_response"`
141 FriQueryIndices []uint64 `json:"fri_query_indices"`
142 } `json:"fri_challenges"`
143}
144
145type VerifierOnlyCircuitDataRaw struct {
146 ConstantsSigmasCap []string `json:"constants_sigmas_cap"`
147 CircuitDigest string `json:"circuit_digest"`
148}
149
150func DeserializeMerkleCap(merkleCapRaw []string) common.MerkleCap {
151 n := len(merkleCapRaw)
152 merkleCap := make([]poseidon.PoseidonBN128HashOut, n)
153 for i := 0; i < n; i++ {
154 capBigInt, _ := new(big.Int).SetString(merkleCapRaw[i], 10)
155 merkleCap[i] = frontend.Variable(capBigInt)
156 }
157 return merkleCap
158}
159
160func DeserializeMerkleProof(merkleProofRaw struct{ Siblings []interface{} }) common.MerkleProof {
161 n := len(merkleProofRaw.Siblings)
162 var mp common.MerkleProof
163 mp.Siblings = make([]poseidon.PoseidonBN128HashOut, n)
164 for i := 0; i < n; i++ {
165 element := merkleProofRaw.Siblings[i].(struct{ Elements []uint64 })
166 mp.Siblings[i] = utils.Uint64ArrayToFArray(element.Elements)
167 }
168 return mp
169}
170
171func DeserializeOpeningSet(openingSetRaw struct {
172 Constants [][]uint64
173 PlonkSigmas [][]uint64
174 Wires [][]uint64
175 PlonkZs [][]uint64
176 PlonkZsNext [][]uint64
177 PartialProducts [][]uint64
178 QuotientPolys [][]uint64
179}) common.OpeningSet {
180 return common.OpeningSet{
181 Constants: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.Constants),
182 PlonkSigmas: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkSigmas),
183 Wires: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.Wires),
184 PlonkZs: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkZs),
185 PlonkZsNext: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkZsNext),
186 PartialProducts: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PartialProducts),
187 QuotientPolys: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.QuotientPolys),
188 }
189}
190
191func StringArrayToHashBN128Array(rawHashes []string) []poseidon.PoseidonBN128HashOut {
192 hashes := []poseidon.PoseidonBN128HashOut{}
193
194 for i := 0; i < len(rawHashes); i++ {
195 hashBigInt, _ := new(big.Int).SetString(rawHashes[i], 10)
196 hashVar := frontend.Variable(hashBigInt)
197 hashes = append(hashes, poseidon.PoseidonBN128HashOut(hashVar))
198 }
199
200 return hashes
201}
202
203func DeserializeFriProof(openingProofRaw struct {
204 CommitPhaseMerkleCaps [][]string
205 QueryRoundProofs []struct {
206 InitialTreesProof struct {
207 EvalsProofs []EvalProofRaw
208 }
209 Steps []struct {
210 Evals [][]uint64
211 MerkleProof struct {
212 Siblings []string
213 }
214 }
215 }
216 FinalPoly struct {
217 Coeffs [][]uint64
218 }
219 PowWitness uint64
220}) common.FriProof {
221 var openingProof common.FriProof
222 openingProof.PowWitness = field.NewFieldConst(openingProofRaw.PowWitness)
223 openingProof.FinalPoly.Coeffs = utils.Uint64ArrayToQuadraticExtensionArray(openingProofRaw.FinalPoly.Coeffs)
224
225 openingProof.CommitPhaseMerkleCaps = make([]common.MerkleCap, len(openingProofRaw.CommitPhaseMerkleCaps))
226 for i := 0; i < len(openingProofRaw.CommitPhaseMerkleCaps); i++ {
227 openingProof.CommitPhaseMerkleCaps[i] = StringArrayToHashBN128Array(openingProofRaw.CommitPhaseMerkleCaps[i])
228 }
229
230 numQueryRoundProofs := len(openingProofRaw.QueryRoundProofs)
231 openingProof.QueryRoundProofs = make([]common.FriQueryRound, numQueryRoundProofs)
232
233 for i := 0; i < numQueryRoundProofs; i++ {
234 numEvalProofs := len(openingProofRaw.QueryRoundProofs[i].InitialTreesProof.EvalsProofs)
235 openingProof.QueryRoundProofs[i].InitialTreesProof.EvalsProofs = make([]common.EvalProof, numEvalProofs)
236 for j := 0; j < numEvalProofs; j++ {
237 openingProof.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].Elements = utils.Uint64ArrayToFArray(openingProofRaw.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].LeafElements)
238 openingProof.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].MerkleProof.Siblings = StringArrayToHashBN128Array(openingProofRaw.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].MerkleProof.Hash)
239 }
240
241 numSteps := len(openingProofRaw.QueryRoundProofs[i].Steps)
242 openingProof.QueryRoundProofs[i].Steps = make([]common.FriQueryStep, numSteps)
243 for j := 0; j < numSteps; j++ {
244 openingProof.QueryRoundProofs[i].Steps[j].Evals = utils.Uint64ArrayToQuadraticExtensionArray(openingProofRaw.QueryRoundProofs[i].Steps[j].Evals)
245 openingProof.QueryRoundProofs[i].Steps[j].MerkleProof.Siblings = StringArrayToHashBN128Array(openingProofRaw.QueryRoundProofs[i].Steps[j].MerkleProof.Siblings)
246 }
247 }
248
249 return openingProof
250}
251
252func DeserializeProofWithPublicInputs(path string) common.ProofWithPublicInputs {
253 jsonFile, err := os.Open(path)
254 if err != nil {
255 panic(err)
256 }
257
258 defer jsonFile.Close()
259 rawBytes, _ := io.ReadAll(jsonFile)
260
261 var raw ProofWithPublicInputsRaw
262 err = json.Unmarshal(rawBytes, &raw)
263 if err != nil {
264 panic(err)
265 }
266
267 var proofWithPis common.ProofWithPublicInputs
268 proofWithPis.Proof.WiresCap = DeserializeMerkleCap(raw.Proof.WiresCap)
269 proofWithPis.Proof.PlonkZsPartialProductsCap = DeserializeMerkleCap(raw.Proof.PlonkZsPartialProductsCap)
270 proofWithPis.Proof.QuotientPolysCap = DeserializeMerkleCap(raw.Proof.QuotientPolysCap)
271 proofWithPis.Proof.Openings = DeserializeOpeningSet(struct {
272 Constants [][]uint64
273 PlonkSigmas [][]uint64
274 Wires [][]uint64
275 PlonkZs [][]uint64
276 PlonkZsNext [][]uint64
277 PartialProducts [][]uint64
278 QuotientPolys [][]uint64
279 }(raw.Proof.Openings))
280 proofWithPis.Proof.OpeningProof = DeserializeFriProof(struct {
281 CommitPhaseMerkleCaps [][]string
282 QueryRoundProofs []struct {
283 InitialTreesProof struct {
284 EvalsProofs []EvalProofRaw
285 }
286 Steps []struct {
287 Evals [][]uint64
288 MerkleProof struct {
289 Siblings []string
290 }
291 }
292 }
293 FinalPoly struct{ Coeffs [][]uint64 }
294 PowWitness uint64
295 }(raw.Proof.OpeningProof))
296 proofWithPis.PublicInputs = utils.Uint64ArrayToFArray(raw.PublicInputs)
297
298 return proofWithPis
299}
300
301func DeserializeProofChallenges(path string) common.ProofChallenges {
302 jsonFile, err := os.Open(path)
303 if err != nil {
304 panic(err)
305 }
306
307 defer jsonFile.Close()
308 rawBytes, _ := io.ReadAll(jsonFile)
309
310 var raw ProofChallengesRaw
311 err = json.Unmarshal(rawBytes, &raw)
312 if err != nil {
313 panic(err)
314 }
315
316 var proofChallenges common.ProofChallenges
317 proofChallenges.PlonkBetas = utils.Uint64ArrayToFArray(raw.PlonkBetas)
318 proofChallenges.PlonkGammas = utils.Uint64ArrayToFArray(raw.PlonkGammas)
319 proofChallenges.PlonkAlphas = utils.Uint64ArrayToFArray(raw.PlonkAlphas)
320 proofChallenges.PlonkZeta = utils.Uint64ArrayToQuadraticExtension(raw.PlonkZeta)
321 proofChallenges.FriChallenges.FriAlpha = utils.Uint64ArrayToQuadraticExtension(raw.FriChallenges.FriAlpha)
322 proofChallenges.FriChallenges.FriBetas = utils.Uint64ArrayToQuadraticExtensionArray(raw.FriChallenges.FriBetas)
323 proofChallenges.FriChallenges.FriPowResponse = field.NewFieldConst(raw.FriChallenges.FriPowResponse)
324 proofChallenges.FriChallenges.FriQueryIndices = utils.Uint64ArrayToFArray(raw.FriChallenges.FriQueryIndices)
325
326 return proofChallenges
327}
328
329func ReductionArityBits(
330 arityBits uint64,
331 finalPolyBits uint64,
332 degreeBits uint64,
333 rateBits uint64,
334 capHeight uint64,
335) []uint64 {
336 returnArr := make([]uint64, 0)
337
338 for degreeBits > finalPolyBits && degreeBits+rateBits-arityBits >= capHeight {
339 returnArr = append(returnArr, arityBits)
340 if degreeBits < arityBits {
341 panic("degreeBits < arityBits")
342 }
343 degreeBits -= arityBits
344 }
345
346 return returnArr
347}
348
349func DeserializeCommonCircuitData(path string) common.CommonCircuitData {
350 jsonFile, err := os.Open(path)
351 if err != nil {
352 panic(err)
353 }
354
355 defer jsonFile.Close()
356 rawBytes, _ := io.ReadAll(jsonFile)
357
358 var raw CommonCircuitDataRaw
359 err = json.Unmarshal(rawBytes, &raw)
360 if err != nil {
361 panic(err)
362 }
363
364 var commonCircuitData common.CommonCircuitData
365 commonCircuitData.Config.NumWires = raw.Config.NumWires
366 commonCircuitData.Config.NumRoutedWires = raw.Config.NumRoutedWires
367 commonCircuitData.Config.NumConstants = raw.Config.NumConstants
368 commonCircuitData.Config.UseBaseArithmeticGate = raw.Config.UseBaseArithmeticGate
369 commonCircuitData.Config.SecurityBits = raw.Config.SecurityBits
370 commonCircuitData.Config.NumChallenges = raw.Config.NumChallenges
371 commonCircuitData.Config.ZeroKnowledge = raw.Config.ZeroKnowledge
372 commonCircuitData.Config.MaxQuotientDegreeFactor = raw.Config.MaxQuotientDegreeFactor
373
374 commonCircuitData.Config.FriConfig.RateBits = raw.Config.FriConfig.RateBits
375 commonCircuitData.Config.FriConfig.CapHeight = raw.Config.FriConfig.CapHeight
376 commonCircuitData.Config.FriConfig.ProofOfWorkBits = raw.Config.FriConfig.ProofOfWorkBits
377 commonCircuitData.Config.FriConfig.NumQueryRounds = raw.Config.FriConfig.NumQueryRounds
378
379 commonCircuitData.FriParams.DegreeBits = raw.FriParams.DegreeBits
380 commonCircuitData.DegreeBits = raw.FriParams.DegreeBits
381 commonCircuitData.FriParams.Config.RateBits = raw.FriParams.Config.RateBits
382 commonCircuitData.FriParams.Config.CapHeight = raw.FriParams.Config.CapHeight
383 commonCircuitData.FriParams.Config.ProofOfWorkBits = raw.FriParams.Config.ProofOfWorkBits
384 commonCircuitData.FriParams.Config.NumQueryRounds = raw.FriParams.Config.NumQueryRounds
385 commonCircuitData.FriParams.ReductionArityBits = raw.FriParams.ReductionArityBits
386
387 commonCircuitData.Gates = []gates.Gate{}
388 for _, gate := range raw.Gates {
389 commonCircuitData.Gates = append(commonCircuitData.Gates, gates.GateInstanceFromId(gate))
390 }
391
392 selectorGroupStart := []uint64{}
393 selectorGroupEnd := []uint64{}
394 for _, group := range raw.SelectorsInfo.Groups {
395 selectorGroupStart = append(selectorGroupStart, group.Start)
396 selectorGroupEnd = append(selectorGroupEnd, group.End)
397 }
398
399 commonCircuitData.SelectorsInfo = *gates.NewSelectorsInfo(
400 raw.SelectorsInfo.SelectorIndices,
401 selectorGroupStart,
402 selectorGroupEnd,
403 )
404
405 commonCircuitData.QuotientDegreeFactor = raw.QuotientDegreeFactor
406 commonCircuitData.NumGateConstraints = raw.NumGateConstraints
407 commonCircuitData.NumConstants = raw.NumConstants
408 commonCircuitData.NumPublicInputs = raw.NumPublicInputs
409 commonCircuitData.KIs = utils.Uint64ArrayToFArray(raw.KIs)
410 commonCircuitData.NumPartialProducts = raw.NumPartialProducts
411
412 return commonCircuitData
413}
414
415func DeserializeVerifierOnlyCircuitData(path string) common.VerifierOnlyCircuitData {
416 jsonFile, err := os.Open(path)
417 if err != nil {
418 panic(err)
419 }
420
421 defer jsonFile.Close()
422 rawBytes, _ := io.ReadAll(jsonFile)
423
424 var raw VerifierOnlyCircuitDataRaw
425 err = json.Unmarshal(rawBytes, &raw)
426 if err != nil {
427 panic(err)
428 }
429
430 var verifierOnlyCircuitData common.VerifierOnlyCircuitData
431 verifierOnlyCircuitData.ConstantSigmasCap = DeserializeMerkleCap(raw.ConstantsSigmasCap)
432 circuitDigestBigInt, _ := new(big.Int).SetString(raw.CircuitDigest, 10)
433 circuitDigestVar := frontend.Variable(circuitDigestBigInt)
434 verifierOnlyCircuitData.CircuitDigest = poseidon.PoseidonBN128HashOut(circuitDigestVar)
435 return verifierOnlyCircuitData
436}