From a16fe09634057772466de29d71095b818fa0b149 Mon Sep 17 00:00:00 2001 From: Kevin Jue Date: Tue, 15 Nov 2022 17:50:45 -0800 Subject: [PATCH] fixed some bugs --- plonky2_verifier/deserialize.go | 28 ++++++++++++++++++++++--- plonky2_verifier/fri.go | 37 +++++++++++++++++++++++---------- 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/plonky2_verifier/deserialize.go b/plonky2_verifier/deserialize.go index d270ac8..062d80a 100644 --- a/plonky2_verifier/deserialize.go +++ b/plonky2_verifier/deserialize.go @@ -29,7 +29,7 @@ type ProofWithPublicInputsRaw struct { 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"` @@ -48,6 +48,23 @@ type ProofWithPublicInputsRaw struct { 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 { leafElements []uint64 merkleProof MerkleProofRaw @@ -179,7 +196,7 @@ func DeserializeOpeningSet(openingSetRaw struct { } func DeserializeFriProof(openingProofRaw struct { - CommitPhaseMerkleCaps []interface{} + CommitPhaseMerkleCaps []MerkleCapsRaw QueryRoundProofs []struct { InitialTreesProof struct { EvalsProofs []EvalProofRaw @@ -198,6 +215,11 @@ func DeserializeFriProof(openingProofRaw struct { 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 @@ func DeserializeProofWithPublicInputs(path string) ProofWithPublicInputs { QuotientPolys [][]uint64 }(raw.Proof.Openings)) proofWithPis.Proof.OpeningProof = DeserializeFriProof(struct { - CommitPhaseMerkleCaps []interface{} + CommitPhaseMerkleCaps []MerkleCapsRaw QueryRoundProofs []struct { InitialTreesProof struct { EvalsProofs []EvalProofRaw diff --git a/plonky2_verifier/fri.go b/plonky2_verifier/fri.go index 1a72d50..c0ea26d 100644 --- a/plonky2_verifier/fri.go +++ b/plonky2_verifier/fri.go @@ -336,6 +336,9 @@ func (f *FriChip) computeEvaluation( 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 @@ func (f *FriChip) computeEvaluation( // 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 @@ func (f *FriChip) computeEvaluation( 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 @@ func (f *FriChip) verifyQueryRound( // 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 @@ func (f *FriChip) verifyQueryRound( ) // 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 @@ func (f *FriChip) verifyQueryRound( xIndexBits = cosetIndexBits } + subgroupX_QE = f.qeAPI.FieldToQE(subgroupX) finalPolyEval := f.finalPolyEval(proof.FinalPoly, subgroupX_QE) f.qeAPI.AssertIsEqual(oldEval, finalPolyEval)