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 inputs file
84 inputsFile, err := ioutil.ReadFile("inputs.json")
85 panicErr(err)
86
87 // parse inputs from inputsFile
88 // var inputs []*big.Int
89 var inputs circuitcompiler.Inputs
90 json.Unmarshal([]byte(string(inputsFile)), &inputs)
91 panicErr(err)
92
93 // calculate wittness
94 w, err := circuit.CalculateWitness(inputs.Private)
95 panicErr(err)
96 fmt.Println("\nwitness", w)
97
98 // flat code to R1CS
99 fmt.Println("\ngenerating R1CS from flat code")
100 a, b, c := circuit.GenerateR1CS()
101 fmt.Println("\nR1CS:")
102 fmt.Println("a:", a)
103 fmt.Println("b:", b)
104 fmt.Println("c:", c)
105
106 // R1CS to QAP
107 alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
108 fmt.Println("qap")
109 fmt.Println(alphas)
110 fmt.Println(betas)
111 fmt.Println(gammas)
112
113 ax, bx, cx, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
114
115 hx := snark.Utils.PF.DivisorPolynomial(px, zx)
116
117 // hx==px/zx so px==hx*zx
118 // assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx))
119 if !r1csqap.BigArraysEqual(px, snark.Utils.PF.Mul(hx, zx)) {
120 panic(errors.New("px != hx*zx"))
121 }
122
123 // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
124 abc := snark.Utils.PF.Sub(snark.Utils.PF.Mul(ax, bx), cx)
125 // assert.Equal(t, abc, px)
126 if !r1csqap.BigArraysEqual(abc, px) {
127 panic(errors.New("abc != px"))
128 }
129 hz := snark.Utils.PF.Mul(hx, zx)
130 if !r1csqap.BigArraysEqual(abc, hz) {
131 panic(errors.New("abc != hz"))
132 }
133 // assert.Equal(t, abc, hz)
134
135 div, rem := snark.Utils.PF.Div(px, zx)
136 if !r1csqap.BigArraysEqual(hx, div) {
137 panic(errors.New("hx != div"))
138 }
139 // assert.Equal(t, hx, div)
140 // assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
141 for _, r := range rem {
142 if !bytes.Equal(r.Bytes(), big.NewInt(int64(0)).Bytes()) {
143 panic(errors.New("error:error: px/zx rem not equal to zeros"))
144 }
145 }
146
147 // store circuit to json
148 jsonData, err := json.Marshal(circuit)
149 panicErr(err)
150 // store setup into file
151 jsonFile, err := os.Create("compiledcircuit.json")
152 panicErr(err)
153 defer jsonFile.Close()
154 jsonFile.Write(jsonData)
155 jsonFile.Close()
156 fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
157
158 return nil
159}
160
161func TrustedSetup(context *cli.Context) error {
162 // open compiledcircuit.json
163 compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
164 panicErr(err)
165 var circuit circuitcompiler.Circuit
166 json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
167 panicErr(err)
168
169 // read inputs file
170 inputsFile, err := ioutil.ReadFile("inputs.json")
171 panicErr(err)
172 // parse inputs from inputsFile
173 // var inputs []*big.Int
174 var inputs circuitcompiler.Inputs
175 json.Unmarshal([]byte(string(inputsFile)), &inputs)
176 panicErr(err)
177 // calculate wittness
178 w, err := circuit.CalculateWitness(inputs.Private)
179 panicErr(err)
180
181 // R1CS to QAP
182 alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C)
183 fmt.Println("qap")
184 fmt.Println(alphas)
185 fmt.Println(betas)
186 fmt.Println(gammas)
187
188 // calculate trusted setup
189 setup, err := snark.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas, zx)
190 panicErr(err)
191 fmt.Println("\nt:", setup.Toxic.T)
192
193 // remove setup.Toxic
194 var tsetup snark.Setup
195 tsetup.Pk = setup.Pk
196 tsetup.Vk = setup.Vk
197 tsetup.G1T = setup.G1T
198 tsetup.G2T = setup.G2T
199
200 // store setup to json
201 jsonData, err := json.Marshal(tsetup)
202 panicErr(err)
203 // store setup into file
204 jsonFile, err := os.Create("trustedsetup.json")
205 panicErr(err)
206 defer jsonFile.Close()
207 jsonFile.Write(jsonData)
208 jsonFile.Close()
209 fmt.Println("Trusted Setup data written to ", jsonFile.Name())
210 return nil
211}
212
213func GenerateProofs(context *cli.Context) error {
214 // open compiledcircuit.json
215 compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
216 panicErr(err)
217 var circuit circuitcompiler.Circuit
218 json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
219 panicErr(err)
220
221 // open trustedsetup.json
222 trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
223 panicErr(err)
224 var trustedsetup snark.Setup
225 json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
226 panicErr(err)
227
228 // read inputs file
229 inputsFile, err := ioutil.ReadFile("inputs.json")
230 panicErr(err)
231 // parse inputs from inputsFile
232 // var inputs []*big.Int
233 var inputs circuitcompiler.Inputs
234 json.Unmarshal([]byte(string(inputsFile)), &inputs)
235 panicErr(err)
236 // calculate wittness
237 w, err := circuit.CalculateWitness(inputs.Private)
238 panicErr(err)
239 fmt.Println("\nwitness", w)
240
241 // flat code to R1CS
242 // a, b, c := circuit.GenerateR1CS()
243 a := circuit.R1CS.A
244 b := circuit.R1CS.B
245 c := circuit.R1CS.C
246 // R1CS to QAP
247 alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
248 _, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
249 hx := snark.Utils.PF.DivisorPolynomial(px, zx)
250
251 fmt.Println(circuit)
252 fmt.Println(trustedsetup.G1T)
253 fmt.Println(hx)
254 fmt.Println(w)
255 proof, err := snark.GenerateProofs(circuit, trustedsetup, hx, w)
256 panicErr(err)
257
258 fmt.Println("\n proofs:")
259 fmt.Println(proof)
260
261 // store proofs to json
262 jsonData, err := json.Marshal(proof)
263 panicErr(err)
264 // store proof into file
265 jsonFile, err := os.Create("proofs.json")
266 panicErr(err)
267 defer jsonFile.Close()
268 jsonFile.Write(jsonData)
269 jsonFile.Close()
270 fmt.Println("Proofs data written to ", jsonFile.Name())
271 return nil
272}
273
274func VerifyProofs(context *cli.Context) error {
275 // open proofs.json
276 proofsFile, err := ioutil.ReadFile("proofs.json")
277 panicErr(err)
278 var proof snark.Proof
279 json.Unmarshal([]byte(string(proofsFile)), &proof)
280 panicErr(err)
281
282 // open compiledcircuit.json
283 compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
284 panicErr(err)
285 var circuit circuitcompiler.Circuit
286 json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
287 panicErr(err)
288
289 // open trustedsetup.json
290 trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
291 panicErr(err)
292 var trustedsetup snark.Setup
293 json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
294 panicErr(err)
295
296 // TODO read publicSignals from file
297 verified := snark.VerifyProof(circuit, trustedsetup, proof, publicSignals, true)
298 if !verified {
299 fmt.Println("ERROR: proofs not verified")
300 } else {
301 fmt.Println("Proofs verified")
302 }
303 return nil
304}