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