arnaucube
arnaucube/gnark-plonky2-verifierPublic Self-hosted repository
fixed some bugs
Kevin Jue kjue235@gmail.com
Tue, 15 Nov 2022 17:50:45 -0800
commit

a16fe09634057772466de29d71095b818fa0b149

parent

1095665ed1af09dbbc8a3238d89cab832b386d58

2 files changed, 51 insertions(+), 14 deletions(-)

jump to
M plonky2_verifier/deserialize.go → plonky2_verifier/deserialize.go

@@ -29,7 +29,7 @@ PartialProducts [][]uint64 `json:"partial_products"`

QuotientPolys [][]uint64 `json:"quotient_polys"` } `json:"openings"` OpeningProof struct { - CommitPhaseMerkleCaps []interface{} `json:"commit_phase_merkle_caps"` + CommitPhaseMerkleCaps []MerkleCapsRaw `json:"commit_phase_merkle_caps"` QueryRoundProofs []struct { InitialTreesProof struct { EvalsProofs []EvalProofRaw `json:"evals_proofs"`

@@ -46,6 +46,23 @@ PowWitness uint64 `json:"pow_witness"`

} `json:"opening_proof"` } `json:"proof"` PublicInputs []uint64 `json:"public_inputs"` +} + +type MerkleCapsRaw struct { + hashes [][]uint64 +} + +func (m *MerkleCapsRaw) UnmarshalJSON(data []byte) error { + var merkleCaps []map[string][]uint64 + if err := json.Unmarshal(data, &merkleCaps); err != nil { + panic(err) + } + + m.hashes = make([][]uint64, len(merkleCaps)) + for i := 0; i < len(merkleCaps); i++ { + m.hashes[i] = merkleCaps[i]["elements"] + } + return nil } type EvalProofRaw struct {

@@ -179,7 +196,7 @@ }

} func DeserializeFriProof(openingProofRaw struct { - CommitPhaseMerkleCaps []interface{} + CommitPhaseMerkleCaps []MerkleCapsRaw QueryRoundProofs []struct { InitialTreesProof struct { EvalsProofs []EvalProofRaw

@@ -197,6 +214,11 @@ }) FriProof {

var openingProof FriProof openingProof.PowWitness = NewFieldElement(openingProofRaw.PowWitness) openingProof.FinalPoly.Coeffs = utils.Uint64ArrayToQuadraticExtensionArray(openingProofRaw.FinalPoly.Coeffs) + + openingProof.CommitPhaseMerkleCaps = make([]MerkleCap, len(openingProofRaw.CommitPhaseMerkleCaps)) + for i := 0; i < len(openingProofRaw.CommitPhaseMerkleCaps); i++ { + openingProof.CommitPhaseMerkleCaps[i] = utils.Uint64ArrayToHashArray(openingProofRaw.CommitPhaseMerkleCaps[i].hashes) + } numQueryRoundProofs := len(openingProofRaw.QueryRoundProofs) openingProof.QueryRoundProofs = make([]FriQueryRound, numQueryRoundProofs)

@@ -249,7 +271,7 @@ PartialProducts [][]uint64

QuotientPolys [][]uint64 }(raw.Proof.Openings)) proofWithPis.Proof.OpeningProof = DeserializeFriProof(struct { - CommitPhaseMerkleCaps []interface{} + CommitPhaseMerkleCaps []MerkleCapsRaw QueryRoundProofs []struct { InitialTreesProof struct { EvalsProofs []EvalProofRaw
M plonky2_verifier/fri.go → plonky2_verifier/fri.go

@@ -336,6 +336,9 @@ arity := 1 << arityBits

if (len(evals)) != arity { panic("len(evals) ! arity") } + if arityBits > 8 { + panic("currently assuming that arityBits is <= 8") + } g := field.GoldilocksPrimitiveRootOfUnity(arityBits) gInv := goldilocks.NewElement(0)

@@ -346,10 +349,8 @@ // element's new index is the bit reverse of it's original index.

// TODO: Optimization - Since the size of the evals array should be constant (e.g. 2^arityBits), // we can just hard code the permutation. permutedEvals := make([]QuadraticExtension, len(evals)) - for i := uint(0); i < uint(len(evals)); i++ { - bitLen := bits.Len(i) - rightPadLen := arityBits - uint64(bitLen) - newIndex := bits.Reverse(i) << rightPadLen + for i := uint8(0); i < uint8(len(evals)); i++ { + newIndex := bits.Reverse8(i) >> arityBits permutedEvals[newIndex] = evals[i] }

@@ -366,10 +367,10 @@ xPoints := make([]QuadraticExtension, len(evals))

yPoints := permutedEvals // TODO: Make g_F a constant - g_F := NewFieldElement(g.Uint64()) + g_F := f.qeAPI.FieldToQE(NewFieldElement(g.Uint64())) xPoints[0] = f.qeAPI.FieldToQE(cosetStart) for i := 1; i < len(evals); i++ { - xPoints[i] = f.qeAPI.FieldToQE(f.fieldAPI.Mul(xPoints[i-1], g_F).(F)) + xPoints[i] = f.qeAPI.MulExtension(xPoints[i-1], g_F) } // TODO: This is n^2. Is there a way to do this better?

@@ -445,13 +446,25 @@ // First create the "leaf" lookup2 circuits

// The will use the least significant bits of the xIndexWithCosetBits array for i := 0; i < NUM_LEAF_LOOKUPS; i++ { leafLookups[i] = f.qeAPI.Lookup2( - xIndexWithinCosetBits[0], xIndexWithinCosetBits[1], - evals[i*NUM_LEAF_LOOKUPS], evals[i*NUM_LEAF_LOOKUPS+1], evals[i*NUM_LEAF_LOOKUPS+2], evals[i*NUM_LEAF_LOOKUPS+3], + xIndexWithinCosetBits[0], + xIndexWithinCosetBits[1], + evals[i*NUM_LEAF_LOOKUPS], + evals[i*NUM_LEAF_LOOKUPS+1], + evals[i*NUM_LEAF_LOOKUPS+2], + evals[i*NUM_LEAF_LOOKUPS+3], ) } // Use the most 2 significant bits of the xIndexWithCosetBits array for the "root" lookup - newEval := f.qeAPI.Lookup2(xIndexWithinCosetBits[2], xIndexWithinCosetBits[3], evals[0], evals[1], evals[2], evals[3]) + newEval := f.qeAPI.Lookup2( + xIndexWithinCosetBits[2], + xIndexWithinCosetBits[3], + leafLookups[0], + leafLookups[1], + leafLookups[2], + leafLookups[3], + ) + f.qeAPI.AssertIsEqual(newEval, oldEval) oldEval = f.computeEvaluation(

@@ -463,9 +476,10 @@ challenges.FriBetas[i],

) // Convert evals (array of QE) to fields by taking their 0th degree coefficients - fieldEvals := make([]F, len(evals)) + fieldEvals := make([]F, 0, 2*len(evals)) for j := 0; j < len(evals); j++ { - fieldEvals[j] = evals[j][0] + fieldEvals = append(fieldEvals, evals[j][0]) + fieldEvals = append(fieldEvals, evals[j][1]) } f.verifyMerkleProofToCapWithCapIndex( fieldEvals,

@@ -483,6 +497,7 @@

xIndexBits = cosetIndexBits } + subgroupX_QE = f.qeAPI.FieldToQE(subgroupX) finalPolyEval := f.finalPolyEval(proof.FinalPoly, subgroupX_QE) f.qeAPI.AssertIsEqual(oldEval, finalPolyEval)