diff --git a/plonky2_verifier/challenger.go b/plonky2_verifier/challenger.go index 1010661..ccf5063 100644 --- a/plonky2_verifier/challenger.go +++ b/plonky2_verifier/challenger.go @@ -55,6 +55,22 @@ func (c *ChallengerChip) ObserveCap(cap []Hash) { } } +func (c *ChallengerChip) ObserveExtensionElement(element QuadraticExtension) { + c.ObserveElements(element[:]) +} + +func (c *ChallengerChip) ObserveExtensionElements(elements []QuadraticExtension) { + for i := 0; i < len(elements); i++ { + c.ObserveExtensionElement(elements[i]) + } +} + +func (c *ChallengerChip) ObserveOpenings(openings FriOpenings) { + for i := 0; i < len(openings.Batches); i++ { + c.ObserveExtensionElements(openings.Batches[i].values) + } +} + func (c *ChallengerChip) GetChallenge() F { if len(c.inputBuffer) != 0 || len(c.outputBuffer) == 0 { c.duplexing() @@ -66,14 +82,53 @@ func (c *ChallengerChip) GetChallenge() F { return challenge } -func (c *ChallengerChip) GetNChallenges(n int) []F { +func (c *ChallengerChip) GetNChallenges(n uint64) []F { challenges := make([]F, n) - for i := 0; i < n; i++ { + for i := uint64(0); i < n; i++ { challenges[i] = c.GetChallenge() } return challenges } +func (c *ChallengerChip) GetExtensionChallenge() QuadraticExtension { + values := c.GetNChallenges(2) + return QuadraticExtension{values[0], values[1]} +} + +func (c *ChallengerChip) GetHash() Hash { + return [4]F{c.GetChallenge(), c.GetChallenge(), c.GetChallenge(), c.GetChallenge()} +} + +func (c *ChallengerChip) GetFriChallenges(commitPhaseMerkleCaps []MerkleCap, finalPoly PolynomialCoeffs, powWitness F, degreeBits uint64, config FriConfig) FriChallenges { + numFriQueries := config.NumQueryRounds + ldeSize := 1 << (degreeBits + config.RateBits) + friAlpha := c.GetExtensionChallenge() + + var friBetas []QuadraticExtension + for i := 0; i < len(commitPhaseMerkleCaps); i++ { + c.ObserveCap(commitPhaseMerkleCaps[i]) + friBetas = append(friBetas, c.GetExtensionChallenge()) + } + + c.ObserveExtensionElements(finalPoly.Coeffs) + + hash := c.GetHash() + powInputs := append(hash[:], powWitness) + + friPowResponse := c.poseidonChip.HashNoPad(powInputs)[0] + friQueryIndices := c.GetNChallenges(numFriQueries) + + // need to modulo lde size on fri query indices + _ = ldeSize + + return FriChallenges{ + FriAlpha: friAlpha, + FriBetas: friBetas, + FriPowResponse: friPowResponse, + FriQueryIndicies: friQueryIndices, + } +} + func clearBuffer(buffer []F) []F { return make([]F, 0) } diff --git a/plonky2_verifier/challenger_test.go b/plonky2_verifier/challenger_test.go index 7516d3e..b6ba54a 100644 --- a/plonky2_verifier/challenger_test.go +++ b/plonky2_verifier/challenger_test.go @@ -48,9 +48,9 @@ func (circuit *TestChallengerCircuit) Define(api frontend.API) error { challengerChip.ObserveHash(publicInputHash) challengerChip.ObserveCap(wiresCap[:]) - nbChallenges := 2 - plonkBetas := challengerChip.GetNChallenges(nbChallenges) - plonkGammas := challengerChip.GetNChallenges(nbChallenges) + numChallenges := uint64(2) + plonkBetas := challengerChip.GetNChallenges(numChallenges) + plonkGammas := challengerChip.GetNChallenges(numChallenges) expectedPlonkBetas := [2]frontend.Variable{ frontend.Variable("4678728155650926271"), diff --git a/plonky2_verifier/fri.go b/plonky2_verifier/fri.go new file mode 100644 index 0000000..7e66fdc --- /dev/null +++ b/plonky2_verifier/fri.go @@ -0,0 +1,25 @@ +package plonky2_verifier + +import ( + . "gnark-ed25519/field" +) + +type FriOpeningBatch struct { + values []QuadraticExtension +} + +type FriOpenings struct { + Batches []FriOpeningBatch +} + +func (c *OpeningSet) ToFriOpenings() FriOpenings { + values := c.Constants + values = append(values, c.PlonkSigmas...) + values = append(values, c.Wires...) + values = append(values, c.PlonkZs...) + values = append(values, c.PartialProducts...) + values = append(values, c.QuotientPolys...) + zetaBatch := FriOpeningBatch{values: values} + zetaNextBatch := FriOpeningBatch{values: c.PlonkZsNext} + return FriOpenings{Batches: []FriOpeningBatch{zetaBatch, zetaNextBatch}} +} diff --git a/plonky2_verifier/proof.go b/plonky2_verifier/structs.go similarity index 88% rename from plonky2_verifier/proof.go rename to plonky2_verifier/structs.go index b13e822..f5c5be1 100644 --- a/plonky2_verifier/proof.go +++ b/plonky2_verifier/structs.go @@ -105,5 +105,19 @@ type CommonCircuitData struct { KIs []F NumPartialProducts uint64 CircuitDigest Hash - // TODO: add SelectorsInfo and Gates +} + +type ProofChallenges struct { + PlonkBetas []F + PlonkGammas []F + PlonkAlphas []F + PlonkZeta QuadraticExtension + FriChallenges FriChallenges +} + +type FriChallenges struct { + FriAlpha QuadraticExtension + FriBetas []QuadraticExtension + FriPowResponse F + FriQueryIndicies []F } diff --git a/plonky2_verifier/verifier.go b/plonky2_verifier/verifier.go index c9f3d48..8e2e9a6 100644 --- a/plonky2_verifier/verifier.go +++ b/plonky2_verifier/verifier.go @@ -1,43 +1,58 @@ package plonky2_verifier -// import ( -// . "gnark-ed25519/field" -// "gnark-ed25519/poseidon" - -// "github.com/consensys/gnark/frontend" -// ) - -// type VerifierChip struct { -// api frontend.API -// field frontend.API -// poseidonChip poseidon.PoseidonChip -// } - -// func (c *VerifierChip) GetPublicInputsHash(publicInputs []F) poseidon.HashOutput { -// return c.poseidonChip.HashNoPad(publicInputs) -// } - -// func (c *VerifierChip) GetChallenges(proofWithPis ProofWithPublicInputs, publicInputsHash Hash, commonData CommonCircuitData) { -// config := commonData.Config -// numChallenges := int(config.NumChallenges) -// challenger := NewChallengerChip(c.api, c.field, c.poseidonChip) - -// challenger.ObserveHash(commonData.CircuitDigest) -// challenger.ObserveHash(publicInputsHash) -// challenger.ObserveCap(proofWithPis.Proof.WiresCap) -// plonkBetas := challenger.GetNChallenges(numChallenges) -// plonkGammas := challenger.GetNChallenges(numChallenges) - -// challenger.ObserveCap(proofWithPis.Proof.PlonkZsPartialProductsCap) -// plonkAlphas := challenger.GetNChallenges(numChallenges) - -// challenger.ObserveCap(proofWithPis.Proof.QuotientPolysCap) -// plonkZeta := challenger.GetNChallenges(numChallenges) - -// challenger.ObserveOpenings(proofWithPis.Proof.Openings) -// } - -// func (c *VerifierChip) Verify(proofWithPis ProofWithPublicInputs, verifierData VerifierOnlyCircuitData, commonData CommonCircuitData) { -// publicInputsHash := c.GetPublicInputsHash(proofWithPis.PublicInputs) -// challenges := c.GetChallenges(proofWithPis, publicInputsHash, commonData) -// } +import ( + . "gnark-ed25519/field" + "gnark-ed25519/poseidon" + + "github.com/consensys/gnark/frontend" +) + +type VerifierChip struct { + api frontend.API + field frontend.API + poseidonChip poseidon.PoseidonChip +} + +func (c *VerifierChip) GetPublicInputsHash(publicInputs []F) Hash { + return c.poseidonChip.HashNoPad(publicInputs) +} + +func (c *VerifierChip) GetChallenges(proofWithPis ProofWithPublicInputs, publicInputsHash Hash, commonData CommonCircuitData) ProofChallenges { + config := commonData.Config + numChallenges := config.NumChallenges + challenger := NewChallengerChip(c.api, c.field, c.poseidonChip) + + challenger.ObserveHash(commonData.CircuitDigest) + challenger.ObserveHash(publicInputsHash) + challenger.ObserveCap(proofWithPis.Proof.WiresCap) + plonkBetas := challenger.GetNChallenges(numChallenges) + plonkGammas := challenger.GetNChallenges(numChallenges) + + challenger.ObserveCap(proofWithPis.Proof.PlonkZsPartialProductsCap) + plonkAlphas := challenger.GetNChallenges(numChallenges) + + challenger.ObserveCap(proofWithPis.Proof.QuotientPolysCap) + plonkZeta := challenger.GetExtensionChallenge() + + _, _, _, _ = plonkAlphas, plonkBetas, plonkGammas, plonkZeta + + challenger.ObserveOpenings(proofWithPis.Proof.Openings.ToFriOpenings()) + + return ProofChallenges{ + PlonkBetas: plonkBetas, + PlonkGammas: plonkGammas, + PlonkAlphas: plonkAlphas, + PlonkZeta: plonkZeta, + FriChallenges: challenger.GetFriChallenges( + proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps, + proofWithPis.Proof.OpeningProof.FinalPoly, + proofWithPis.Proof.OpeningProof.PowWitness, + commonData.DegreeBits, config.FriConfig, + ), + } +} + +func (c *VerifierChip) Verify(proofWithPis ProofWithPublicInputs, verifierData VerifierOnlyCircuitData, commonData CommonCircuitData) { + publicInputsHash := c.GetPublicInputsHash(proofWithPis.PublicInputs) + _ = c.GetChallenges(proofWithPis, publicInputsHash, commonData) +} diff --git a/utils/utils.go b/utils/utils.go index b4d30d8..43c82da 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -5,7 +5,6 @@ import ( "math/big" "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/std/math/emulated" ) func StrArrayToBigIntArray(input []string) []big.Int { @@ -29,7 +28,7 @@ func StrArrayToFrontendVariableArray(input []string) []frontend.Variable { func Uint64ArrayToFArray(input []uint64) []F { var output []F for i := 0; i < len(input); i++ { - output = append(output, emulated.NewElement[emulated.Goldilocks](input[i])) + output = append(output, NewFieldElement(input[i])) } return output }