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.1.0-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 inputs file
174 inputsFile, err := ioutil.ReadFile("inputs.json")
175 panicErr(err)
176 // parse inputs from inputsFile
177 // var inputs []*big.Int
178 var inputs circuitcompiler.Inputs
179 json.Unmarshal([]byte(string(inputsFile)), &inputs)
180 panicErr(err)
181 // calculate wittness
182 w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
183 panicErr(err)
184
185 // R1CS to QAP
186 alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C)
187 fmt.Println("qap")
188 fmt.Println(alphas)
189 fmt.Println(betas)
190 fmt.Println(gammas)
191
192 // calculate trusted setup
193 setup, err := snark.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas)
194 panicErr(err)
195 fmt.Println("\nt:", setup.Toxic.T)
196
197 // remove setup.Toxic
198 var tsetup snark.Setup
199 tsetup.Pk = setup.Pk
200 tsetup.Vk = setup.Vk
201 tsetup.G1T = setup.G1T
202 tsetup.G2T = setup.G2T
203
204 // store setup to json
205 jsonData, err := json.Marshal(tsetup)
206 panicErr(err)
207 // store setup into file
208 jsonFile, err := os.Create("trustedsetup.json")
209 panicErr(err)
210 defer jsonFile.Close()
211 jsonFile.Write(jsonData)
212 jsonFile.Close()
213 fmt.Println("Trusted Setup data written to ", jsonFile.Name())
214 return nil
215}
216
217func GenerateProofs(context *cli.Context) error {
218 // open compiledcircuit.json
219 compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
220 panicErr(err)
221 var circuit circuitcompiler.Circuit
222 json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
223 panicErr(err)
224
225 // open trustedsetup.json
226 trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
227 panicErr(err)
228 var trustedsetup snark.Setup
229 json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
230 panicErr(err)
231
232 // read privateInputs file
233 privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
234 panicErr(err)
235 // read publicInputs file
236 publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
237 panicErr(err)
238 // parse inputs from inputsFile
239 var inputs circuitcompiler.Inputs
240 err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
241 panicErr(err)
242 err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
243 panicErr(err)
244
245 // calculate wittness
246 w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
247 panicErr(err)
248 fmt.Println("\nwitness", w)
249
250 // flat code to R1CS
251 // a, b, c := circuit.GenerateR1CS()
252 a := circuit.R1CS.A
253 b := circuit.R1CS.B
254 c := circuit.R1CS.C
255 // R1CS to QAP
256 alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
257 _, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
258 hx := snark.Utils.PF.DivisorPolynomial(px, zx)
259
260 fmt.Println(circuit)
261 fmt.Println(trustedsetup.G1T)
262 fmt.Println(hx)
263 fmt.Println(w)
264 proof, err := snark.GenerateProofs(circuit, trustedsetup, hx, w)
265 panicErr(err)
266
267 fmt.Println("\n proofs:")
268 fmt.Println(proof)
269
270 // store proofs to json
271 jsonData, err := json.Marshal(proof)
272 panicErr(err)
273 // store proof into file
274 jsonFile, err := os.Create("proofs.json")
275 panicErr(err)
276 defer jsonFile.Close()
277 jsonFile.Write(jsonData)
278 jsonFile.Close()
279 fmt.Println("Proofs data written to ", jsonFile.Name())
280 return nil
281}
282
283func VerifyProofs(context *cli.Context) error {
284 // open proofs.json
285 proofsFile, err := ioutil.ReadFile("proofs.json")
286 panicErr(err)
287 var proof snark.Proof
288 json.Unmarshal([]byte(string(proofsFile)), &proof)
289 panicErr(err)
290
291 // open compiledcircuit.json
292 compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
293 panicErr(err)
294 var circuit circuitcompiler.Circuit
295 json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
296 panicErr(err)
297
298 // open trustedsetup.json
299 trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
300 panicErr(err)
301 var trustedsetup snark.Setup
302 json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
303 panicErr(err)
304
305 // read publicInputs file
306 publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
307 panicErr(err)
308 var publicSignals []*big.Int
309 err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
310 panicErr(err)
311
312 verified := snark.VerifyProof(circuit, trustedsetup, proof, publicSignals, true)
313 if !verified {
314 fmt.Println("ERROR: proofs not verified")
315 } else {
316 fmt.Println("Proofs verified")
317 }
318 return nil
319}