go-snark/cli/main.go
cli/main.goRaw
1package main
2
3import (
4 "bufio"
5 "bytes"
6 "encoding/json"
7 "errors"
8 "fmt"
9 "io/ioutil"
10 "log"
11 "math/big"
12 "os"
13
14 snark "github.com/arnaucube/go-snark"
15 "github.com/arnaucube/go-snark/circuitcompiler"
16 "github.com/arnaucube/go-snark/r1csqap"
17 "github.com/urfave/cli"
18)
19
20func panicErr(err error) {
21 if err != nil {
22 panic(err)
23 }
24}
25
26var commands = []cli.Command{
27 {
28 Name: "compile",
29 Aliases: []string{},
30 Usage: "compile a circuit",
31 Action: CompileCircuit,
32 },
33 {
34 Name: "trustedsetup",
35 Aliases: []string{},
36 Usage: "generate trusted setup for a circuit",
37 Action: TrustedSetup,
38 },
39 {
40 Name: "genproofs",
41 Aliases: []string{},
42 Usage: "generate the snark proofs",
43 Action: GenerateProofs,
44 },
45 {
46 Name: "verify",
47 Aliases: []string{},
48 Usage: "verify the snark proofs",
49 Action: VerifyProofs,
50 },
51}
52
53func main() {
54 app := cli.NewApp()
55 app.Name = "go-snarks-cli"
56 app.Version = "0.0.1-alpha"
57 app.Flags = []cli.Flag{
58 cli.StringFlag{Name: "config"},
59 }
60 app.Commands = commands
61
62 err := app.Run(os.Args)
63 if err != nil {
64 log.Fatal(err)
65 }
66}
67
68func CompileCircuit(context *cli.Context) error {
69 fmt.Println("cli")
70
71 circuitPath := context.Args().Get(0)
72
73 // read circuit file
74 circuitFile, err := os.Open(circuitPath)
75 panicErr(err)
76
77 // parse circuit code
78 parser := circuitcompiler.NewParser(bufio.NewReader(circuitFile))
79 circuit, err := parser.Parse()
80 panicErr(err)
81 fmt.Println("\ncircuit data:", circuit)
82
83 // read privateInputs file
84 privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
85 panicErr(err)
86 // read publicInputs file
87 publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
88 panicErr(err)
89
90 // parse inputs from inputsFile
91 var inputs circuitcompiler.Inputs
92 err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
93 panicErr(err)
94 err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
95 panicErr(err)
96
97 // calculate wittness
98 w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
99 panicErr(err)
100 fmt.Println("\nwitness", w)
101
102 // flat code to R1CS
103 fmt.Println("\ngenerating R1CS from flat code")
104 a, b, c := circuit.GenerateR1CS()
105 fmt.Println("\nR1CS:")
106 fmt.Println("a:", a)
107 fmt.Println("b:", b)
108 fmt.Println("c:", c)
109
110 // R1CS to QAP
111 alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
112 fmt.Println("qap")
113 fmt.Println(alphas)
114 fmt.Println(betas)
115 fmt.Println(gammas)
116
117 ax, bx, cx, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
118
119 hx := snark.Utils.PF.DivisorPolynomial(px, zx)
120
121 // hx==px/zx so px==hx*zx
122 // assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx))
123 if !r1csqap.BigArraysEqual(px, snark.Utils.PF.Mul(hx, zx)) {
124 panic(errors.New("px != hx*zx"))
125 }
126
127 // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
128 abc := snark.Utils.PF.Sub(snark.Utils.PF.Mul(ax, bx), cx)
129 // assert.Equal(t, abc, px)
130 if !r1csqap.BigArraysEqual(abc, px) {
131 panic(errors.New("abc != px"))
132 }
133 hz := snark.Utils.PF.Mul(hx, zx)
134 if !r1csqap.BigArraysEqual(abc, hz) {
135 panic(errors.New("abc != hz"))
136 }
137 // assert.Equal(t, abc, hz)
138
139 div, rem := snark.Utils.PF.Div(px, zx)
140 if !r1csqap.BigArraysEqual(hx, div) {
141 panic(errors.New("hx != div"))
142 }
143 // assert.Equal(t, hx, div)
144 // assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
145 for _, r := range rem {
146 if !bytes.Equal(r.Bytes(), big.NewInt(int64(0)).Bytes()) {
147 panic(errors.New("error:error: px/zx rem not equal to zeros"))
148 }
149 }
150
151 // store circuit to json
152 jsonData, err := json.Marshal(circuit)
153 panicErr(err)
154 // store setup into file
155 jsonFile, err := os.Create("compiledcircuit.json")
156 panicErr(err)
157 defer jsonFile.Close()
158 jsonFile.Write(jsonData)
159 jsonFile.Close()
160 fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
161
162 return nil
163}
164
165func TrustedSetup(context *cli.Context) error {
166 // open compiledcircuit.json
167 compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
168 panicErr(err)
169 var circuit circuitcompiler.Circuit
170 json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
171 panicErr(err)
172
173 // read privateInputs file
174 privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
175 panicErr(err)
176 // read publicInputs file
177 publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
178 panicErr(err)
179
180 // parse inputs from inputsFile
181 var inputs circuitcompiler.Inputs
182 err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
183 panicErr(err)
184 err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
185 panicErr(err)
186
187 // calculate wittness
188 w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
189 panicErr(err)
190
191 // R1CS to QAP
192 alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C)
193 fmt.Println("qap")
194 fmt.Println(alphas)
195 fmt.Println(betas)
196 fmt.Println(gammas)
197
198 // calculate trusted setup
199 setup, err := snark.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas)
200 panicErr(err)
201 fmt.Println("\nt:", setup.Toxic.T)
202
203 // remove setup.Toxic
204 var tsetup snark.Setup
205 tsetup.Pk = setup.Pk
206 tsetup.Vk = setup.Vk
207 tsetup.G1T = setup.G1T
208 tsetup.G2T = setup.G2T
209
210 // store setup to json
211 jsonData, err := json.Marshal(tsetup)
212 panicErr(err)
213 // store setup into file
214 jsonFile, err := os.Create("trustedsetup.json")
215 panicErr(err)
216 defer jsonFile.Close()
217 jsonFile.Write(jsonData)
218 jsonFile.Close()
219 fmt.Println("Trusted Setup data written to ", jsonFile.Name())
220 return nil
221}
222
223func GenerateProofs(context *cli.Context) error {
224 // open compiledcircuit.json
225 compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
226 panicErr(err)
227 var circuit circuitcompiler.Circuit
228 json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
229 panicErr(err)
230
231 // open trustedsetup.json
232 trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
233 panicErr(err)
234 var trustedsetup snark.Setup
235 json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
236 panicErr(err)
237
238 // read privateInputs file
239 privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
240 panicErr(err)
241 // read publicInputs file
242 publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
243 panicErr(err)
244 // parse inputs from inputsFile
245 var inputs circuitcompiler.Inputs
246 err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
247 panicErr(err)
248 err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
249 panicErr(err)
250
251 // calculate wittness
252 w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
253 panicErr(err)
254 fmt.Println("witness", w)
255
256 // flat code to R1CS
257 a := circuit.R1CS.A
258 b := circuit.R1CS.B
259 c := circuit.R1CS.C
260 // R1CS to QAP
261 alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(a, b, c)
262 _, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
263 hx := snark.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z)
264
265 fmt.Println(circuit)
266 fmt.Println(trustedsetup.G1T)
267 fmt.Println(hx)
268 fmt.Println(w)
269 proof, err := snark.GenerateProofs(circuit, trustedsetup, w, px)
270 panicErr(err)
271
272 fmt.Println("\n proofs:")
273 fmt.Println(proof)
274
275 // store proofs to json
276 jsonData, err := json.Marshal(proof)
277 panicErr(err)
278 // store proof into file
279 jsonFile, err := os.Create("proofs.json")
280 panicErr(err)
281 defer jsonFile.Close()
282 jsonFile.Write(jsonData)
283 jsonFile.Close()
284 fmt.Println("Proofs data written to ", jsonFile.Name())
285 return nil
286}
287
288func VerifyProofs(context *cli.Context) error {
289 // open proofs.json
290 proofsFile, err := ioutil.ReadFile("proofs.json")
291 panicErr(err)
292 var proof snark.Proof
293 json.Unmarshal([]byte(string(proofsFile)), &proof)
294 panicErr(err)
295
296 // open compiledcircuit.json
297 compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
298 panicErr(err)
299 var circuit circuitcompiler.Circuit
300 json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
301 panicErr(err)
302
303 // open trustedsetup.json
304 trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
305 panicErr(err)
306 var trustedsetup snark.Setup
307 json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
308 panicErr(err)
309
310 // read publicInputs file
311 publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
312 panicErr(err)
313 var publicSignals []*big.Int
314 err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
315 panicErr(err)
316
317 verified := snark.VerifyProof(circuit, trustedsetup, proof, publicSignals, true)
318 if !verified {
319 fmt.Println("ERROR: proofs not verified")
320 } else {
321 fmt.Println("Proofs verified")
322 }
323 return nil
324}