gnark-plonky2-verifier/benchmark.go
benchmark.goRaw
1package main
2
3import (
4 "bytes"
5 "flag"
6 "fmt"
7 "math/big"
8 "os"
9 "time"
10
11 "github.com/succinctlabs/gnark-plonky2-verifier/field"
12 "github.com/succinctlabs/gnark-plonky2-verifier/verifier"
13 "github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
14 "github.com/succinctlabs/gnark-plonky2-verifier/verifier/utils"
15
16 "github.com/consensys/gnark-crypto/ecc"
17 "github.com/consensys/gnark/backend/groth16"
18 "github.com/consensys/gnark/constraint"
19 "github.com/consensys/gnark/frontend"
20 "github.com/consensys/gnark/frontend/cs/r1cs"
21 "github.com/consensys/gnark/profile"
22)
23
24type BenchmarkPlonky2VerifierCircuit struct {
25 Proof common.Proof
26 PublicInputs []field.F `gnark:",public"`
27
28 verifierChip *verifier.VerifierChip `gnark:"-"`
29 plonky2CircuitName string `gnark:"-"`
30}
31
32func (circuit *BenchmarkPlonky2VerifierCircuit) Define(api frontend.API) error {
33 circuitDirname := "./verifier/data/" + circuit.plonky2CircuitName + "/"
34 commonCircuitData := utils.DeserializeCommonCircuitData(circuitDirname + "common_circuit_data.json")
35 verifierOnlyCircuitData := utils.DeserializeVerifierOnlyCircuitData(circuitDirname + "verifier_only_circuit_data.json")
36
37 circuit.verifierChip = verifier.NewVerifierChip(api, commonCircuitData)
38
39 circuit.verifierChip.Verify(circuit.Proof, circuit.PublicInputs, verifierOnlyCircuitData, commonCircuitData)
40
41 return nil
42}
43
44func compileCircuit(plonky2Circuit string, profileCircuit bool, serialize bool, outputSolidity bool) (constraint.ConstraintSystem, groth16.ProvingKey, groth16.VerifyingKey) {
45 circuit := BenchmarkPlonky2VerifierCircuit{
46 plonky2CircuitName: plonky2Circuit,
47 }
48 proofWithPis := utils.DeserializeProofWithPublicInputs("./verifier/data/" + plonky2Circuit + "/proof_with_public_inputs.json")
49 circuit.Proof = proofWithPis.Proof
50 circuit.PublicInputs = proofWithPis.PublicInputs
51
52 var p *profile.Profile
53 if profileCircuit {
54 p = profile.Start()
55 }
56 r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
57 if err != nil {
58 fmt.Println("error in building circuit", err)
59 os.Exit(1)
60 }
61
62 if profileCircuit {
63 p.Stop()
64 p.Top()
65 println("r1cs.GetNbCoefficients(): ", r1cs.GetNbCoefficients())
66 println("r1cs.GetNbConstraints(): ", r1cs.GetNbConstraints())
67 println("r1cs.GetNbSecretVariables(): ", r1cs.GetNbSecretVariables())
68 println("r1cs.GetNbPublicVariables(): ", r1cs.GetNbPublicVariables())
69 println("r1cs.GetNbInternalVariables(): ", r1cs.GetNbInternalVariables())
70 }
71
72 // Don't serialize the circuit for now, since it takes up too much memory
73 /*
74 if serialize {
75 fR1CS, _ := os.Create("circuit")
76 r1cs.WriteTo(fR1CS)
77 fR1CS.Close()
78 }
79 */
80
81 fmt.Println("Running circuit setup", time.Now())
82 pk, vk, err := groth16.Setup(r1cs)
83 if err != nil {
84 fmt.Println(err)
85 os.Exit(1)
86 }
87
88 if serialize {
89 fPK, _ := os.Create("proving.key")
90 pk.WriteTo(fPK)
91 fPK.Close()
92
93 fVK, _ := os.Create("verifying.key")
94 vk.WriteTo(fVK)
95 fVK.Close()
96 }
97
98 if outputSolidity {
99 fSolidity, _ := os.Create("proof.sol")
100 err = vk.ExportSolidity(fSolidity)
101 }
102
103 return r1cs, pk, vk
104}
105
106func createProof(plonky2Circuit string, r1cs constraint.ConstraintSystem, pk groth16.ProvingKey, vk groth16.VerifyingKey, serialize bool) groth16.Proof {
107 proofWithPis := utils.DeserializeProofWithPublicInputs("./verifier/data/" + plonky2Circuit + "/proof_with_public_inputs.json")
108
109 // Witness
110 assignment := &BenchmarkPlonky2VerifierCircuit{
111 Proof: proofWithPis.Proof,
112 PublicInputs: proofWithPis.PublicInputs,
113 }
114
115 fmt.Println("Generating witness", time.Now())
116 witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
117 publicWitness, _ := witness.Public()
118 if serialize {
119 fWitness, _ := os.Create("witness")
120 witness.WriteTo(fWitness)
121 fWitness.Close()
122 }
123
124 fmt.Println("Creating proof", time.Now())
125 proof, err := groth16.Prove(r1cs, pk, witness)
126 if err != nil {
127 fmt.Println(err)
128 os.Exit(1)
129 }
130 if serialize {
131 fProof, _ := os.Create("proof.proof")
132 proof.WriteTo(fProof)
133 fProof.Close()
134 }
135
136 fmt.Println("Verifying proof", time.Now())
137 err = groth16.Verify(proof, vk, publicWitness)
138 if err != nil {
139 fmt.Println(err)
140 os.Exit(1)
141 }
142
143 const fpSize = 4 * 8
144 var buf bytes.Buffer
145 proof.WriteRawTo(&buf)
146 proofBytes := buf.Bytes()
147
148 var (
149 a [2]*big.Int
150 b [2][2]*big.Int
151 c [2]*big.Int
152 )
153
154 // proof.Ar, proof.Bs, proof.Krs
155 a[0] = new(big.Int).SetBytes(proofBytes[fpSize*0 : fpSize*1])
156 a[1] = new(big.Int).SetBytes(proofBytes[fpSize*1 : fpSize*2])
157 b[0][0] = new(big.Int).SetBytes(proofBytes[fpSize*2 : fpSize*3])
158 b[0][1] = new(big.Int).SetBytes(proofBytes[fpSize*3 : fpSize*4])
159 b[1][0] = new(big.Int).SetBytes(proofBytes[fpSize*4 : fpSize*5])
160 b[1][1] = new(big.Int).SetBytes(proofBytes[fpSize*5 : fpSize*6])
161 c[0] = new(big.Int).SetBytes(proofBytes[fpSize*6 : fpSize*7])
162 c[1] = new(big.Int).SetBytes(proofBytes[fpSize*7 : fpSize*8])
163
164 println("a[0] is ", a[0].String())
165 println("a[1] is ", a[1].String())
166
167 println("b[0][0] is ", b[0][0].String())
168 println("b[0][1] is ", b[0][1].String())
169 println("b[1][0] is ", b[1][0].String())
170 println("b[1][1] is ", b[1][1].String())
171
172 println("c[0] is ", c[0].String())
173 println("c[1] is ", c[1].String())
174
175 return proof
176}
177
178func main() {
179 plonky2Circuit := flag.String("plonky2-circuit", "", "plonky2 circuit to benchmark")
180 profileCircuit := flag.Bool("profile", false, "profile the circuit")
181 serialize := flag.Bool("serialize", false, "serialize the circuit")
182 outputSolidity := flag.Bool("solidity", false, "output solidity code for the circuit")
183
184 flag.Parse()
185
186 if plonky2Circuit == nil || *plonky2Circuit == "" {
187 fmt.Println("Please provide a plonky2 circuit to benchmark")
188 os.Exit(1)
189 }
190
191 r1cs, pk, vk := compileCircuit(*plonky2Circuit, *profileCircuit, *serialize, *outputSolidity)
192 createProof(*plonky2Circuit, r1cs, pk, vk, *serialize)
193}