package main import ( "fmt" . "gnark-ed25519/field" . "gnark-ed25519/plonky2_verifier" "gnark-ed25519/poseidon" "os" "time" "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/cs/r1cs" ) type BenchmarkLargeDummyFriCircuit struct { zeta QuadraticExtension openings FriOpenings friChallenges FriChallenges initialMerkleCaps []MerkleCap friProof FriProof } func (circuit *BenchmarkLargeDummyFriCircuit) Define(api frontend.API) error { commonCircuitData := DeserializeCommonCircuitData("./plonky2_verifier/data/dummy_2^14_gates/common_circuit_data.json") field := NewFieldAPI(api) qeAPI := NewQuadraticExtensionAPI(field, commonCircuitData.DegreeBits) poseidonChip := poseidon.NewPoseidonChip(api, field) friChip := NewFriChip(api, field, qeAPI, poseidonChip, &commonCircuitData.FriParams) friChip.VerifyFriProof( commonCircuitData.GetFriInstance(qeAPI, circuit.zeta, commonCircuitData.DegreeBits), circuit.openings, &circuit.friChallenges, circuit.initialMerkleCaps, &circuit.friProof, ) return nil } func compileCircuit() frontend.CompiledConstraintSystem { fmt.Println("compiling circuit", time.Now()) circuit := BenchmarkLargeDummyFriCircuit{} /* commonCircuitData := DeserializeCommonCircuitData("./plonky2_verifier/data/dummy_2^14_gates/common_circuit_data.json") circuit.zeta[0] = emulated.NewElement[EmulatedField](nil) circuit.zeta[1] = emulated.NewElement[EmulatedField](nil) fmt.Println("circuit zeta allocated") // Batch 0 has the following openings // Constants (config.num_constants + 1) // Sigmas (config.num_routed_wires) // Wires (config.num_wires) // Plonk_Z (config.num_challenges) // Partial Products (config.num_challenges * config.num_partial_products) // Quotient Polynomails (config.num_challenges * config.quotient_degree_factor) // Batch 1 has the following openings // Plonk_Z_next (config.num_challenges) circuit.openings.Batches = make([]FriOpeningBatch, 2) batch1Size := commonCircuitData.NumConstants + 1 + commonCircuitData.Config.NumRoutedWires + commonCircuitData.Config.NumWires + commonCircuitData.Config.NumChallenges + (commonCircuitData.Config.NumChallenges * commonCircuitData.NumPartialProducts) + (commonCircuitData.Config.NumChallenges * commonCircuitData.QuotientDegreeFactor) circuit.openings.Batches[0].Values = make([]QuadraticExtension, 0) for i := uint64(0); i < batch1Size; i++ { circuit.openings.Batches[0].Values = append(circuit.openings.Batches[0].Values, NewEmptyQuadraticExtension()) } batch2Size := commonCircuitData.Config.NumChallenges circuit.openings.Batches[1].Values = make([]QuadraticExtension, 0) for i := uint64(0); i < batch2Size; i++ { circuit.openings.Batches[1].Values = append(circuit.openings.Batches[1].Values, NewEmptyQuadraticExtension()) } fmt.Println("circuit openings allocated") circuit.friChallenges.FriAlpha = NewEmptyQuadraticExtension() circuit.friChallenges.FriPowResponse = emulated.NewElement[EmulatedField](nil) circuit.friChallenges.FriBetas = make([]QuadraticExtension, 0) for i := 0; i < len(commonCircuitData.FriParams.ReductionArityBits); i++ { circuit.friChallenges.FriBetas = append(circuit.friChallenges.FriBetas, NewEmptyQuadraticExtension()) } circuit.friChallenges.FriQueryIndicies = make([]F, 0) for i := uint64(0); i < commonCircuitData.FriParams.Config.NumQueryRounds; i++ { circuit.friChallenges.FriQueryIndicies = append(circuit.friChallenges.FriQueryIndicies, NewEmptyFieldElement()) } fmt.Println("circuit challenges allocated") // initial merkle caps is the merkle cap for // the constant/sigmas, wires, partial products, // and quotient composite polynomial // The merkle cap size is 2**cap_height hashes numMerkleCaps := 4 merkleCapSize := 1 << commonCircuitData.Config.FriConfig.CapHeight circuit.initialMerkleCaps = make([]MerkleCap, 0) for i := 0; i < numMerkleCaps; i++ { merkleCap := make([]Hash, 0) for j := 0; j < merkleCapSize; j++ { merkleCap = append(merkleCap, NewEmptyHash()) } circuit.initialMerkleCaps = append(circuit.initialMerkleCaps, merkleCap) } fmt.Println("circuit initialMerkleCaps allocated") // CommitPhaseMerkleCap is number of reduction_arity_bits // finalPoly has 2^(degreeBits - sum(arity_bits)) coefficients numCommitPhaseMerkleCaps := len(commonCircuitData.FriParams.ReductionArityBits) for i := 0; i < numCommitPhaseMerkleCaps; i++ { circuit.friProof.CommitPhaseMerkleCaps = make([]MerkleCap, 0) merkleCap := make([]Hash, 0) for j := 0; j < merkleCapSize; j++ { merkleCap = append(merkleCap, NewEmptyHash()) } circuit.friProof.CommitPhaseMerkleCaps = append(circuit.friProof.CommitPhaseMerkleCaps, merkleCap) } fmt.Println("circuit friproof CommitPhaseMerkleCaps allocated") friOracleInfo := commonCircuitData.FriOracles() circuit.friProof.QueryRoundProofs = make([]FriQueryRound, 0) for i := 0; i < int(commonCircuitData.FriParams.Config.NumQueryRounds); i++ { evalsProof := make([]EvalProof, 0) // Allocation for the initial trees proof for j := 0; j < len(friOracleInfo); j++ { leafSize := friOracleInfo[0].NumPolys merkleProofLen := commonCircuitData.DegreeBits + commonCircuitData.Config.FriConfig.RateBits - commonCircuitData.Config.FriConfig.CapHeight evalElements := make([]F, 0) for k := uint64(0); k < leafSize; k++ { evalElements = append(evalElements, NewEmptyFieldElement()) } merkleProofSiblings := make([]Hash, 0) for k := uint64(0); k < merkleProofLen; k++ { merkleProofSiblings = append(merkleProofSiblings, NewEmptyHash()) } evalsProof = append( evalsProof, EvalProof{ Elements: evalElements, MerkleProof: MerkleProof{merkleProofSiblings}, }, ) } // Allocation for the steps steps := make([]FriQueryStep, 0) codewordLenBits := commonCircuitData.DegreeBits + commonCircuitData.Config.FriConfig.RateBits for j := 0; j < len(commonCircuitData.FriParams.ReductionArityBits); j++ { arityBits := commonCircuitData.FriParams.ReductionArityBits[j] leafSize := 1 << int(arityBits) codewordLenBits -= arityBits merkleProofLen := codewordLenBits - commonCircuitData.Config.FriConfig.CapHeight evalQEs := make([]QuadraticExtension, 0) for k := 0; k < leafSize; k++ { evalQEs = append(evalQEs, NewEmptyQuadraticExtension()) } merkleProofSiblings := make([]Hash, 0) for k := uint64(0); k < merkleProofLen; k++ { merkleProofSiblings = append(merkleProofSiblings, NewEmptyHash()) } steps = append( steps, FriQueryStep{ Evals: evalQEs, MerkleProof: MerkleProof{merkleProofSiblings}, }, ) } circuit.friProof.QueryRoundProofs = append( circuit.friProof.QueryRoundProofs, FriQueryRound{ InitialTreesProof: FriInitialTreeProof{evalsProof}, Steps: steps, }, ) fmt.Println("circuit friproof QueryRoundProofs allocated for round", i) } // Final poly allocation finalPolyLenBit := commonCircuitData.DegreeBits for _, arityBit := range commonCircuitData.FriParams.ReductionArityBits { finalPolyLenBit -= arityBit } circuit.friProof.FinalPoly.Coeffs = make([]QuadraticExtension, 0) for i := 0; i < (1 << finalPolyLenBit); i++ { circuit.friProof.FinalPoly.Coeffs = append(circuit.friProof.FinalPoly.Coeffs, NewEmptyQuadraticExtension()) } fmt.Println("circuit friproof FinalPoly allocated") // PowWitness allocation circuit.friProof.PowWitness = NewEmptyFieldElement() fmt.Println("Partial witness allocation done") */ proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/dummy_2^14_gates/proof_with_public_inputs.json") verifierOnlyCircuitData := DeserializeVerifierOnlyCircuitData("./plonky2_verifier/data/dummy_2^14_gates/verifier_only_circuit_data.json") zeta := QuadraticExtension{ NewFieldElementFromString("17377750363769967882"), NewFieldElementFromString("11921191651424768462"), } friChallenges := FriChallenges{ FriAlpha: QuadraticExtension{ NewFieldElementFromString("16721004555774385479"), NewFieldElementFromString("10688151135543754663"), }, FriBetas: []QuadraticExtension{ { NewFieldElementFromString("3312441922957827805"), NewFieldElementFromString("15128092514958289671"), }, { NewFieldElementFromString("13630530769060141802"), NewFieldElementFromString("14559883974933163008"), }, { NewFieldElementFromString("16146508250083930687"), NewFieldElementFromString("5176346568444408396"), }, }, FriPowResponse: NewFieldElement(4389), FriQueryIndicies: []F{ NewFieldElementFromString("16334967868590615051"), NewFieldElementFromString("2911473540496037915"), NewFieldElementFromString("14887216056886344225"), NewFieldElementFromString("7808811227805914295"), NewFieldElementFromString("2018594961417375749"), NewFieldElementFromString("3733368398777208435"), NewFieldElementFromString("2623035669037055104"), NewFieldElementFromString("299243030573481514"), NewFieldElementFromString("7189789717962704433"), NewFieldElementFromString("14566344026886816268"), NewFieldElementFromString("12555390069003437453"), NewFieldElementFromString("17225508403199418233"), NewFieldElementFromString("5088797913879903292"), NewFieldElementFromString("9715691392773433023"), NewFieldElementFromString("7565836764713256165"), NewFieldElementFromString("1500143546029322929"), NewFieldElementFromString("1245802417104422080"), NewFieldElementFromString("6831959786661245110"), NewFieldElementFromString("17271054758535453780"), NewFieldElementFromString("6225460404576395409"), NewFieldElementFromString("15932661092896277351"), NewFieldElementFromString("12452534049198240575"), NewFieldElementFromString("4225199666055520177"), NewFieldElementFromString("13235091290587791090"), NewFieldElementFromString("2562357622728700774"), NewFieldElementFromString("17676678042980201498"), NewFieldElementFromString("5837067135702409874"), NewFieldElementFromString("11238419549114325157"), }, } initialMerkleCaps := []MerkleCap{ verifierOnlyCircuitData.ConstantSigmasCap, proofWithPis.Proof.WiresCap, proofWithPis.Proof.PlonkZsPartialProductsCap, proofWithPis.Proof.QuotientPolysCap, } circuit.zeta = zeta circuit.openings = proofWithPis.Proof.Openings.ToFriOpenings() circuit.friChallenges = friChallenges circuit.initialMerkleCaps = initialMerkleCaps circuit.friProof = proofWithPis.Proof.OpeningProof r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) if err != nil { fmt.Println("error in building circuit", err) os.Exit(1) } return r1cs } func createProof(r1cs frontend.CompiledConstraintSystem) groth16.Proof { proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/dummy_2^14_gates/proof_with_public_inputs.json") verifierOnlyCircuitData := DeserializeVerifierOnlyCircuitData("./plonky2_verifier/data/dummy_2^14_gates/verifier_only_circuit_data.json") zeta := QuadraticExtension{ NewFieldElementFromString("17377750363769967882"), NewFieldElementFromString("11921191651424768462"), } friChallenges := FriChallenges{ FriAlpha: QuadraticExtension{ NewFieldElementFromString("16721004555774385479"), NewFieldElementFromString("10688151135543754663"), }, FriBetas: []QuadraticExtension{ { NewFieldElementFromString("3312441922957827805"), NewFieldElementFromString("15128092514958289671"), }, { NewFieldElementFromString("13630530769060141802"), NewFieldElementFromString("14559883974933163008"), }, { NewFieldElementFromString("16146508250083930687"), NewFieldElementFromString("5176346568444408396"), }, }, FriPowResponse: NewFieldElement(4389), FriQueryIndicies: []F{ NewFieldElementFromString("16334967868590615051"), NewFieldElementFromString("2911473540496037915"), NewFieldElementFromString("14887216056886344225"), NewFieldElementFromString("7808811227805914295"), NewFieldElementFromString("2018594961417375749"), NewFieldElementFromString("3733368398777208435"), NewFieldElementFromString("2623035669037055104"), NewFieldElementFromString("299243030573481514"), NewFieldElementFromString("7189789717962704433"), NewFieldElementFromString("14566344026886816268"), NewFieldElementFromString("12555390069003437453"), NewFieldElementFromString("17225508403199418233"), NewFieldElementFromString("5088797913879903292"), NewFieldElementFromString("9715691392773433023"), NewFieldElementFromString("7565836764713256165"), NewFieldElementFromString("1500143546029322929"), NewFieldElementFromString("1245802417104422080"), NewFieldElementFromString("6831959786661245110"), NewFieldElementFromString("17271054758535453780"), NewFieldElementFromString("6225460404576395409"), NewFieldElementFromString("15932661092896277351"), NewFieldElementFromString("12452534049198240575"), NewFieldElementFromString("4225199666055520177"), NewFieldElementFromString("13235091290587791090"), NewFieldElementFromString("2562357622728700774"), NewFieldElementFromString("17676678042980201498"), NewFieldElementFromString("5837067135702409874"), NewFieldElementFromString("11238419549114325157"), }, } initialMerkleCaps := []MerkleCap{ verifierOnlyCircuitData.ConstantSigmasCap, proofWithPis.Proof.WiresCap, proofWithPis.Proof.PlonkZsPartialProductsCap, proofWithPis.Proof.QuotientPolysCap, } // Witness assignment := &BenchmarkLargeDummyFriCircuit{ zeta: zeta, openings: proofWithPis.Proof.Openings.ToFriOpenings(), friChallenges: friChallenges, initialMerkleCaps: initialMerkleCaps, friProof: proofWithPis.Proof.OpeningProof, } fmt.Println("Generating witness", time.Now()) witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField()) publicWitness, _ := witness.Public() pk, vk, err := groth16.Setup(r1cs) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Println("Creating proof", time.Now()) proof, err := groth16.Prove(r1cs, pk, witness) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Println("Verifying proof", time.Now()) err = groth16.Verify(proof, vk, publicWitness) if err != nil { fmt.Println(err) os.Exit(1) } return proof } func main() { r1cs := compileCircuit() fi, _ := os.Open("dummy_fri.r1cs") r1cs.WriteTo(fi) proof := createProof(r1cs) fmt.Println(proof.CurveID(), time.Now()) }