arnaucube
arnaucube/gnark-plonky2-verifierPublic Self-hosted repository
gnark-plonky2-verifier/verifier/deserialize.go
verifier/deserialize.goRaw
  1package verifier
  2
  3import (
  4	"encoding/json"
  5	"io"
  6	"math/big"
  7	"os"
  8
  9	"github.com/consensys/gnark/frontend"
 10	gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
 11	"github.com/succinctlabs/gnark-plonky2-verifier/plonk/gates"
 12	"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
 13	"github.com/succinctlabs/gnark-plonky2-verifier/variables"
 14)
 15
 16type ProofWithPublicInputsRaw struct {
 17	Proof struct {
 18		WiresCap                  []string `json:"wires_cap"`
 19		PlonkZsPartialProductsCap []string `json:"plonk_zs_partial_products_cap"`
 20		QuotientPolysCap          []string `json:"quotient_polys_cap"`
 21		Openings                  struct {
 22			Constants       [][]uint64 `json:"constants"`
 23			PlonkSigmas     [][]uint64 `json:"plonk_sigmas"`
 24			Wires           [][]uint64 `json:"wires"`
 25			PlonkZs         [][]uint64 `json:"plonk_zs"`
 26			PlonkZsNext     [][]uint64 `json:"plonk_zs_next"`
 27			PartialProducts [][]uint64 `json:"partial_products"`
 28			QuotientPolys   [][]uint64 `json:"quotient_polys"`
 29		} `json:"openings"`
 30		OpeningProof struct {
 31			CommitPhaseMerkleCaps [][]string `json:"commit_phase_merkle_caps"`
 32			QueryRoundProofs      []struct {
 33				InitialTreesProof struct {
 34					EvalsProofs []EvalProofRaw `json:"evals_proofs"`
 35				} `json:"initial_trees_proof"`
 36				Steps []struct {
 37					Evals       [][]uint64 `json:"evals"`
 38					MerkleProof struct {
 39						Siblings []string `json:"siblings"`
 40					} `json:"merkle_proof"`
 41				} `json:"steps"`
 42			} `json:"query_round_proofs"`
 43			FinalPoly struct {
 44				Coeffs [][]uint64 `json:"coeffs"`
 45			} `json:"final_poly"`
 46			PowWitness uint64 `json:"pow_witness"`
 47		} `json:"opening_proof"`
 48	} `json:"proof"`
 49	PublicInputs []uint64 `json:"public_inputs"`
 50}
 51
 52type EvalProofRaw struct {
 53	LeafElements []uint64
 54	MerkleProof  MerkleProofRaw
 55}
 56
 57func (e *EvalProofRaw) UnmarshalJSON(data []byte) error {
 58	return json.Unmarshal(data, &[]interface{}{&e.LeafElements, &e.MerkleProof})
 59}
 60
 61type MerkleProofRaw struct {
 62	Hash []string
 63}
 64
 65func (m *MerkleProofRaw) UnmarshalJSON(data []byte) error {
 66	type SiblingObject struct {
 67		Siblings []string // "siblings"
 68	}
 69
 70	var siblings SiblingObject
 71	if err := json.Unmarshal(data, &siblings); err != nil {
 72		panic(err)
 73	}
 74
 75	m.Hash = make([]string, len(siblings.Siblings))
 76	copy(m.Hash[:], siblings.Siblings)
 77
 78	return nil
 79}
 80
 81type CommonCircuitDataRaw struct {
 82	Config struct {
 83		NumWires                uint64 `json:"num_wires"`
 84		NumRoutedWires          uint64 `json:"num_routed_wires"`
 85		NumConstants            uint64 `json:"num_constants"`
 86		UseBaseArithmeticGate   bool   `json:"use_base_arithmetic_gate"`
 87		SecurityBits            uint64 `json:"security_bits"`
 88		NumChallenges           uint64 `json:"num_challenges"`
 89		ZeroKnowledge           bool   `json:"zero_knowledge"`
 90		MaxQuotientDegreeFactor uint64 `json:"max_quotient_degree_factor"`
 91		FriConfig               struct {
 92			RateBits          uint64 `json:"rate_bits"`
 93			CapHeight         uint64 `json:"cap_height"`
 94			ProofOfWorkBits   uint64 `json:"proof_of_work_bits"`
 95			ReductionStrategy struct {
 96				ConstantArityBits []uint64 `json:"ConstantArityBits"`
 97			} `json:"reduction_strategy"`
 98			NumQueryRounds uint64 `json:"num_query_rounds"`
 99		} `json:"fri_config"`
100	} `json:"config"`
101	FriParams struct {
102		Config struct {
103			RateBits          uint64 `json:"rate_bits"`
104			CapHeight         uint64 `json:"cap_height"`
105			ProofOfWorkBits   uint64 `json:"proof_of_work_bits"`
106			ReductionStrategy struct {
107				ConstantArityBits []uint64 `json:"ConstantArityBits"`
108			} `json:"reduction_strategy"`
109			NumQueryRounds uint64 `json:"num_query_rounds"`
110		} `json:"config"`
111		Hiding             bool     `json:"hiding"`
112		DegreeBits         uint64   `json:"degree_bits"`
113		ReductionArityBits []uint64 `json:"reduction_arity_bits"`
114	} `json:"fri_params"`
115	Gates         []string `json:"gates"`
116	SelectorsInfo struct {
117		SelectorIndices []uint64 `json:"selector_indices"`
118		Groups          []struct {
119			Start uint64 `json:"start"`
120			End   uint64 `json:"end"`
121		} `json:"groups"`
122	} `json:"selectors_info"`
123	QuotientDegreeFactor uint64   `json:"quotient_degree_factor"`
124	NumGateConstraints   uint64   `json:"num_gate_constraints"`
125	NumConstants         uint64   `json:"num_constants"`
126	NumPublicInputs      uint64   `json:"num_public_inputs"`
127	KIs                  []uint64 `json:"k_is"`
128	NumPartialProducts   uint64   `json:"num_partial_products"`
129}
130
131type ProofChallengesRaw struct {
132	PlonkBetas    []uint64 `json:"plonk_betas"`
133	PlonkGammas   []uint64 `json:"plonk_gammas"`
134	PlonkAlphas   []uint64 `json:"plonk_alphas"`
135	PlonkZeta     []uint64 `json:"plonk_zeta"`
136	FriChallenges struct {
137		FriAlpha        []uint64   `json:"fri_alpha"`
138		FriBetas        [][]uint64 `json:"fri_betas"`
139		FriPowResponse  uint64     `json:"fri_pow_response"`
140		FriQueryIndices []uint64   `json:"fri_query_indices"`
141	} `json:"fri_challenges"`
142}
143
144type VerifierOnlyCircuitDataRaw struct {
145	ConstantsSigmasCap []string `json:"constants_sigmas_cap"`
146	CircuitDigest      string   `json:"circuit_digest"`
147}
148
149func DeserializeMerkleCap(merkleCapRaw []string) variables.FriMerkleCap {
150	n := len(merkleCapRaw)
151	merkleCap := make([]poseidon.BN254HashOut, n)
152	for i := 0; i < n; i++ {
153		capBigInt, _ := new(big.Int).SetString(merkleCapRaw[i], 10)
154		merkleCap[i] = frontend.Variable(capBigInt)
155	}
156	return merkleCap
157}
158
159func DeserializeMerkleProof(merkleProofRaw struct{ Siblings []interface{} }) variables.FriMerkleProof {
160	n := len(merkleProofRaw.Siblings)
161	var mp variables.FriMerkleProof
162	mp.Siblings = make([]poseidon.BN254HashOut, n)
163	for i := 0; i < n; i++ {
164		element := merkleProofRaw.Siblings[i].(struct{ Elements []uint64 })
165		mp.Siblings[i] = gl.Uint64ArrayToVariableArray(element.Elements)
166	}
167	return mp
168}
169
170func DeserializeOpeningSet(openingSetRaw struct {
171	Constants       [][]uint64
172	PlonkSigmas     [][]uint64
173	Wires           [][]uint64
174	PlonkZs         [][]uint64
175	PlonkZsNext     [][]uint64
176	PartialProducts [][]uint64
177	QuotientPolys   [][]uint64
178}) variables.OpeningSet {
179	return variables.OpeningSet{
180		Constants:       gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.Constants),
181		PlonkSigmas:     gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkSigmas),
182		Wires:           gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.Wires),
183		PlonkZs:         gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkZs),
184		PlonkZsNext:     gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkZsNext),
185		PartialProducts: gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PartialProducts),
186		QuotientPolys:   gl.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.QuotientPolys),
187	}
188}
189
190func StringArrayToHashBN254Array(rawHashes []string) []poseidon.BN254HashOut {
191	hashes := []poseidon.BN254HashOut{}
192
193	for i := 0; i < len(rawHashes); i++ {
194		hashBigInt, _ := new(big.Int).SetString(rawHashes[i], 10)
195		hashVar := frontend.Variable(hashBigInt)
196		hashes = append(hashes, poseidon.BN254HashOut(hashVar))
197	}
198
199	return hashes
200}
201
202func DeserializeFriProof(openingProofRaw struct {
203	CommitPhaseMerkleCaps [][]string
204	QueryRoundProofs      []struct {
205		InitialTreesProof struct {
206			EvalsProofs []EvalProofRaw
207		}
208		Steps []struct {
209			Evals       [][]uint64
210			MerkleProof struct {
211				Siblings []string
212			}
213		}
214	}
215	FinalPoly struct {
216		Coeffs [][]uint64
217	}
218	PowWitness uint64
219}) variables.FriProof {
220	var openingProof variables.FriProof
221	openingProof.PowWitness = gl.NewVariable(openingProofRaw.PowWitness)
222	openingProof.FinalPoly.Coeffs = gl.Uint64ArrayToQuadraticExtensionArray(openingProofRaw.FinalPoly.Coeffs)
223
224	openingProof.CommitPhaseMerkleCaps = make([]variables.FriMerkleCap, len(openingProofRaw.CommitPhaseMerkleCaps))
225	for i := 0; i < len(openingProofRaw.CommitPhaseMerkleCaps); i++ {
226		openingProof.CommitPhaseMerkleCaps[i] = StringArrayToHashBN254Array(openingProofRaw.CommitPhaseMerkleCaps[i])
227	}
228
229	numQueryRoundProofs := len(openingProofRaw.QueryRoundProofs)
230	openingProof.QueryRoundProofs = make([]variables.FriQueryRound, numQueryRoundProofs)
231
232	for i := 0; i < numQueryRoundProofs; i++ {
233		numEvalProofs := len(openingProofRaw.QueryRoundProofs[i].InitialTreesProof.EvalsProofs)
234		openingProof.QueryRoundProofs[i].InitialTreesProof.EvalsProofs = make([]variables.FriEvalProof, numEvalProofs)
235		for j := 0; j < numEvalProofs; j++ {
236			openingProof.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].Elements = gl.Uint64ArrayToVariableArray(openingProofRaw.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].LeafElements)
237			openingProof.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].MerkleProof.Siblings = StringArrayToHashBN254Array(openingProofRaw.QueryRoundProofs[i].InitialTreesProof.EvalsProofs[j].MerkleProof.Hash)
238		}
239
240		numSteps := len(openingProofRaw.QueryRoundProofs[i].Steps)
241		openingProof.QueryRoundProofs[i].Steps = make([]variables.FriQueryStep, numSteps)
242		for j := 0; j < numSteps; j++ {
243			openingProof.QueryRoundProofs[i].Steps[j].Evals = gl.Uint64ArrayToQuadraticExtensionArray(openingProofRaw.QueryRoundProofs[i].Steps[j].Evals)
244			openingProof.QueryRoundProofs[i].Steps[j].MerkleProof.Siblings = StringArrayToHashBN254Array(openingProofRaw.QueryRoundProofs[i].Steps[j].MerkleProof.Siblings)
245		}
246	}
247
248	return openingProof
249}
250
251func DeserializeProofWithPublicInputs(path string) variables.ProofWithPublicInputs {
252	jsonFile, err := os.Open(path)
253	if err != nil {
254		panic(err)
255	}
256
257	defer jsonFile.Close()
258	rawBytes, _ := io.ReadAll(jsonFile)
259
260	var raw ProofWithPublicInputsRaw
261	err = json.Unmarshal(rawBytes, &raw)
262	if err != nil {
263		panic(err)
264	}
265
266	var proofWithPis variables.ProofWithPublicInputs
267	proofWithPis.Proof.WiresCap = DeserializeMerkleCap(raw.Proof.WiresCap)
268	proofWithPis.Proof.PlonkZsPartialProductsCap = DeserializeMerkleCap(raw.Proof.PlonkZsPartialProductsCap)
269	proofWithPis.Proof.QuotientPolysCap = DeserializeMerkleCap(raw.Proof.QuotientPolysCap)
270	proofWithPis.Proof.Openings = DeserializeOpeningSet(struct {
271		Constants       [][]uint64
272		PlonkSigmas     [][]uint64
273		Wires           [][]uint64
274		PlonkZs         [][]uint64
275		PlonkZsNext     [][]uint64
276		PartialProducts [][]uint64
277		QuotientPolys   [][]uint64
278	}(raw.Proof.Openings))
279	proofWithPis.Proof.OpeningProof = DeserializeFriProof(struct {
280		CommitPhaseMerkleCaps [][]string
281		QueryRoundProofs      []struct {
282			InitialTreesProof struct {
283				EvalsProofs []EvalProofRaw
284			}
285			Steps []struct {
286				Evals       [][]uint64
287				MerkleProof struct {
288					Siblings []string
289				}
290			}
291		}
292		FinalPoly  struct{ Coeffs [][]uint64 }
293		PowWitness uint64
294	}(raw.Proof.OpeningProof))
295	proofWithPis.PublicInputs = gl.Uint64ArrayToVariableArray(raw.PublicInputs)
296
297	return proofWithPis
298}
299
300// TODO: this seemed unused?
301// func DeserializeProofChallenges(path string) variables.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 variables.ProofChallenges
317// 	proofChallenges.PlonkBetas = gl.Uint64ArrayToVariableArray(raw.PlonkBetas)
318// 	proofChallenges.PlonkGammas = gl.Uint64ArrayToVariableArray(raw.PlonkGammas)
319// 	proofChallenges.PlonkAlphas = gl.Uint64ArrayToVariableArray(raw.PlonkAlphas)
320// 	proofChallenges.PlonkZeta = gl.Uint64ArrayToQuadraticExtension(raw.PlonkZeta)
321// 	proofChallenges.FriChallenges.FriAlpha = gl.Uint64ArrayToQuadraticExtension(raw.FriChallenges.FriAlpha)
322// 	proofChallenges.FriChallenges.FriBetas = gl.Uint64ArrayToQuadraticExtensionArray(raw.FriChallenges.FriBetas)
323// 	proofChallenges.FriChallenges.FriPowResponse = gl.NewVariable(raw.FriChallenges.FriPowResponse)
324// 	proofChallenges.FriChallenges.FriQueryIndices = gl.Uint64ArrayToVariableArray(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) variables.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 variables.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 = gl.Uint64ArrayToVariableArray(raw.KIs)
410	commonCircuitData.NumPartialProducts = raw.NumPartialProducts
411
412	return commonCircuitData
413}
414
415func DeserializeVerifierOnlyCircuitData(path string) variables.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 variables.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.BN254HashOut(circuitDigestVar)
435	return verifierOnlyCircuitData
436}