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: "genproofs",
35 Aliases: []string{},
36 Usage: "generate the snark proofs",
37 Action: GenerateProofs,
38 },
39 {
40 Name: "verify",
41 Aliases: []string{},
42 Usage: "verify the snark proofs",
43 Action: VerifyProofs,
44 },
45}
46
47func main() {
48 app := cli.NewApp()
49 app.Name = "go-snarks-cli"
50 app.Version = "0.1.0-alpha"
51 app.Flags = []cli.Flag{
52 cli.StringFlag{Name: "config"},
53 }
54 app.Commands = commands
55
56 err := app.Run(os.Args)
57 if err != nil {
58 log.Fatal(err)
59 }
60}
61
62func CompileCircuit(context *cli.Context) error {
63 fmt.Println("cli")
64
65 circuitPath := context.Args().Get(0)
66
67 // read circuit file
68 circuitFile, err := os.Open(circuitPath)
69 panicErr(err)
70
71 // parse circuit code
72 parser := circuitcompiler.NewParser(bufio.NewReader(circuitFile))
73 circuit, err := parser.Parse()
74 panicErr(err)
75 fmt.Println("\ncircuit data:", circuit)
76
77 // read inputs file
78 inputsFile, err := ioutil.ReadFile("inputs.json")
79 panicErr(err)
80
81 // parse inputs from inputsFile
82 var inputs []*big.Int
83 json.Unmarshal([]byte(string(inputsFile)), &inputs)
84 panicErr(err)
85
86 // calculate wittness
87 w, err := circuit.CalculateWitness(inputs)
88 panicErr(err)
89 fmt.Println("\nwitness", w)
90
91 // flat code to R1CS
92 fmt.Println("\ngenerating R1CS from flat code")
93 a, b, c := circuit.GenerateR1CS()
94 fmt.Println("\nR1CS:")
95 fmt.Println("a:", a)
96 fmt.Println("b:", b)
97 fmt.Println("c:", c)
98
99 // R1CS to QAP
100 alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
101 fmt.Println("qap")
102 fmt.Println(alphas)
103 fmt.Println(betas)
104 fmt.Println(gammas)
105
106 ax, bx, cx, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
107
108 hx := snark.Utils.PF.DivisorPolynomial(px, zx)
109
110 // hx==px/zx so px==hx*zx
111 // assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx))
112 if !r1csqap.BigArraysEqual(px, snark.Utils.PF.Mul(hx, zx)) {
113 panic(errors.New("px != hx*zx"))
114 }
115
116 // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
117 abc := snark.Utils.PF.Sub(snark.Utils.PF.Mul(ax, bx), cx)
118 // assert.Equal(t, abc, px)
119 if !r1csqap.BigArraysEqual(abc, px) {
120 panic(errors.New("abc != px"))
121 }
122 hz := snark.Utils.PF.Mul(hx, zx)
123 if !r1csqap.BigArraysEqual(abc, hz) {
124 panic(errors.New("abc != hz"))
125 }
126 // assert.Equal(t, abc, hz)
127
128 div, rem := snark.Utils.PF.Div(px, zx)
129 if !r1csqap.BigArraysEqual(hx, div) {
130 panic(errors.New("hx != div"))
131 }
132 // assert.Equal(t, hx, div)
133 // assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
134 for _, r := range rem {
135 if !bytes.Equal(r.Bytes(), big.NewInt(int64(0)).Bytes()) {
136 panic(errors.New("error:error: px/zx rem not equal to zeros"))
137 }
138 }
139
140 // calculate trusted setup
141 setup, err := snark.GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas, zx)
142 panicErr(err)
143 fmt.Println("\nt:", setup.Toxic.T)
144
145 // store circuit to json
146 jsonData, err := json.Marshal(circuit)
147 panicErr(err)
148 // store setup into file
149 jsonFile, err := os.Create("compiledcircuit.json")
150 panicErr(err)
151 defer jsonFile.Close()
152 jsonFile.Write(jsonData)
153 jsonFile.Close()
154 fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
155
156 // remove setup.Toxic
157 var tsetup snark.Setup
158 tsetup.Pk = setup.Pk
159 tsetup.Vk = setup.Vk
160 tsetup.G1T = setup.G1T
161 tsetup.G2T = setup.G2T
162
163 // store setup to json
164 jsonData, err = json.Marshal(tsetup)
165 panicErr(err)
166 // store setup into file
167 jsonFile, err = os.Create("trustedsetup.json")
168 panicErr(err)
169 defer jsonFile.Close()
170 jsonFile.Write(jsonData)
171 jsonFile.Close()
172 fmt.Println("Trusted Setup data written to ", jsonFile.Name())
173 return nil
174}
175
176func GenerateProofs(context *cli.Context) error {
177 // open compiledcircuit.json
178 compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
179 panicErr(err)
180 var circuit circuitcompiler.Circuit
181 json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
182 panicErr(err)
183
184 // open trustedsetup.json
185 trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
186 panicErr(err)
187 var trustedsetup snark.Setup
188 json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
189 panicErr(err)
190
191 // read inputs file
192 inputsFile, err := ioutil.ReadFile("inputs.json")
193 panicErr(err)
194 // parse inputs from inputsFile
195 var inputs []*big.Int
196 json.Unmarshal([]byte(string(inputsFile)), &inputs)
197 panicErr(err)
198 // calculate wittness
199 w, err := circuit.CalculateWitness(inputs)
200 panicErr(err)
201 fmt.Println("\nwitness", w)
202
203 // flat code to R1CS
204 a, b, c := circuit.GenerateR1CS()
205 // R1CS to QAP
206 alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
207 _, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
208 hx := snark.Utils.PF.DivisorPolynomial(px, zx)
209
210 proof, err := snark.GenerateProofs(circuit, trustedsetup, hx, w)
211 panicErr(err)
212
213 fmt.Println("\n proofs:")
214 fmt.Println(proof)
215 fmt.Println("public signals:", proof.PublicSignals)
216
217 // store proofs to json
218 jsonData, err := json.Marshal(proof)
219 panicErr(err)
220 // store proof into file
221 jsonFile, err := os.Create("proofs.json")
222 panicErr(err)
223 defer jsonFile.Close()
224 jsonFile.Write(jsonData)
225 jsonFile.Close()
226 fmt.Println("Proofs data written to ", jsonFile.Name())
227 return nil
228}
229
230func VerifyProofs(context *cli.Context) error {
231 // open proofs.json
232 proofsFile, err := ioutil.ReadFile("proofs.json")
233 panicErr(err)
234 var proof snark.Proof
235 json.Unmarshal([]byte(string(proofsFile)), &proof)
236 panicErr(err)
237
238 // open compiledcircuit.json
239 compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
240 panicErr(err)
241 var circuit circuitcompiler.Circuit
242 json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
243 panicErr(err)
244
245 // open trustedsetup.json
246 trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
247 panicErr(err)
248 var trustedsetup snark.Setup
249 json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
250 panicErr(err)
251
252 verified := snark.VerifyProof(circuit, trustedsetup, proof, true)
253 if !verified {
254 fmt.Println("ERROR: proofs not verified")
255 } else {
256 fmt.Println("Proofs verified")
257 }
258 return nil
259}