arnaucube
arnaucube/go-snarkPublic Self-hosted repository
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/groth16"
 17	"github.com/arnaucube/go-snark/r1csqap"
 18	"github.com/urfave/cli"
 19)
 20
 21func panicErr(err error) {
 22	if err != nil {
 23		panic(err)
 24	}
 25}
 26
 27var commands = []cli.Command{
 28	{
 29		Name:    "compile",
 30		Aliases: []string{},
 31		Usage:   "compile a circuit",
 32		Action:  CompileCircuit,
 33	},
 34	{
 35		Name:    "trustedsetup",
 36		Aliases: []string{},
 37		Usage:   "generate trusted setup for a circuit",
 38		Action:  TrustedSetup,
 39	},
 40	{
 41		Name:    "genproofs",
 42		Aliases: []string{},
 43		Usage:   "generate the snark proofs",
 44		Action:  GenerateProofs,
 45	},
 46	{
 47		Name:    "verify",
 48		Aliases: []string{},
 49		Usage:   "verify the snark proofs",
 50		Action:  VerifyProofs,
 51	},
 52	{
 53		Name:    "groth16",
 54		Aliases: []string{},
 55		Usage:   "use groth16 protocol",
 56		Subcommands: []cli.Command{
 57			{
 58				Name:    "trustedsetup",
 59				Aliases: []string{},
 60				Usage:   "generate trusted setup for a circuit",
 61				Action:  Groth16TrustedSetup,
 62			},
 63			{
 64				Name:    "genproofs",
 65				Aliases: []string{},
 66				Usage:   "generate the snark proofs",
 67				Action:  Groth16GenerateProofs,
 68			},
 69			{
 70				Name:    "verify",
 71				Aliases: []string{},
 72				Usage:   "verify the snark proofs",
 73				Action:  Groth16VerifyProofs,
 74			},
 75		},
 76	},
 77}
 78
 79func main() {
 80	app := cli.NewApp()
 81	app.Name = "go-snarks-cli"
 82	app.Version = "0.0.3-alpha"
 83	app.Flags = []cli.Flag{
 84		cli.StringFlag{Name: "config"},
 85	}
 86	app.Commands = commands
 87
 88	err := app.Run(os.Args)
 89	if err != nil {
 90		log.Fatal(err)
 91	}
 92}
 93
 94func CompileCircuit(context *cli.Context) error {
 95	fmt.Println("cli")
 96
 97	circuitPath := context.Args().Get(0)
 98
 99	// read circuit file
100	circuitFile, err := os.Open(circuitPath)
101	panicErr(err)
102
103	// parse circuit code
104	parser := circuitcompiler.NewParser(bufio.NewReader(circuitFile))
105	circuit, err := parser.Parse()
106	panicErr(err)
107	fmt.Println("\ncircuit data:", circuit)
108
109	// read privateInputs file
110	privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
111	panicErr(err)
112	// read publicInputs file
113	publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
114	panicErr(err)
115
116	// parse inputs from inputsFile
117	var inputs circuitcompiler.Inputs
118	err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
119	panicErr(err)
120	err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
121	panicErr(err)
122
123	// calculate wittness
124	w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
125	panicErr(err)
126	fmt.Println("\nwitness", w)
127
128	// flat code to R1CS
129	fmt.Println("\ngenerating R1CS from flat code")
130	a, b, c := circuit.GenerateR1CS()
131	fmt.Println("\nR1CS:")
132	fmt.Println("a:", a)
133	fmt.Println("b:", b)
134	fmt.Println("c:", c)
135
136	// R1CS to QAP
137	alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
138	fmt.Println("qap")
139	fmt.Println(alphas)
140	fmt.Println(betas)
141	fmt.Println(gammas)
142
143	ax, bx, cx, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
144
145	hx := snark.Utils.PF.DivisorPolynomial(px, zx)
146
147	// hx==px/zx so px==hx*zx
148	// assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx))
149	if !r1csqap.BigArraysEqual(px, snark.Utils.PF.Mul(hx, zx)) {
150		panic(errors.New("px != hx*zx"))
151	}
152
153	// p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
154	abc := snark.Utils.PF.Sub(snark.Utils.PF.Mul(ax, bx), cx)
155	// assert.Equal(t, abc, px)
156	if !r1csqap.BigArraysEqual(abc, px) {
157		panic(errors.New("abc != px"))
158	}
159	hz := snark.Utils.PF.Mul(hx, zx)
160	if !r1csqap.BigArraysEqual(abc, hz) {
161		panic(errors.New("abc != hz"))
162	}
163	// assert.Equal(t, abc, hz)
164
165	div, rem := snark.Utils.PF.Div(px, zx)
166	if !r1csqap.BigArraysEqual(hx, div) {
167		panic(errors.New("hx != div"))
168	}
169	// assert.Equal(t, hx, div)
170	// assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
171	for _, r := range rem {
172		if !bytes.Equal(r.Bytes(), big.NewInt(int64(0)).Bytes()) {
173			panic(errors.New("error:error:  px/zx rem not equal to zeros"))
174		}
175	}
176
177	// store circuit to json
178	jsonData, err := json.Marshal(circuit)
179	panicErr(err)
180	// store setup into file
181	jsonFile, err := os.Create("compiledcircuit.json")
182	panicErr(err)
183	defer jsonFile.Close()
184	jsonFile.Write(jsonData)
185	jsonFile.Close()
186	fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
187
188	return nil
189}
190
191func TrustedSetup(context *cli.Context) error {
192	// open compiledcircuit.json
193	compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
194	panicErr(err)
195	var circuit circuitcompiler.Circuit
196	json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
197	panicErr(err)
198
199	// read privateInputs file
200	privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
201	panicErr(err)
202	// read publicInputs file
203	publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
204	panicErr(err)
205
206	// parse inputs from inputsFile
207	var inputs circuitcompiler.Inputs
208	err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
209	panicErr(err)
210	err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
211	panicErr(err)
212
213	// calculate wittness
214	w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
215	panicErr(err)
216
217	// R1CS to QAP
218	alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C)
219	fmt.Println("qap")
220	fmt.Println(alphas)
221	fmt.Println(betas)
222	fmt.Println(gammas)
223
224	// calculate trusted setup
225	setup, err := snark.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas)
226	panicErr(err)
227	fmt.Println("\nt:", setup.Toxic.T)
228
229	// remove setup.Toxic
230	var tsetup snark.Setup
231	tsetup.Pk = setup.Pk
232	tsetup.Vk = setup.Vk
233	tsetup.G1T = setup.G1T
234	tsetup.G2T = setup.G2T
235
236	// store setup to json
237	jsonData, err := json.Marshal(tsetup)
238	panicErr(err)
239	// store setup into file
240	jsonFile, err := os.Create("trustedsetup.json")
241	panicErr(err)
242	defer jsonFile.Close()
243	jsonFile.Write(jsonData)
244	jsonFile.Close()
245	fmt.Println("Trusted Setup data written to ", jsonFile.Name())
246	return nil
247}
248
249func GenerateProofs(context *cli.Context) error {
250	// open compiledcircuit.json
251	compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
252	panicErr(err)
253	var circuit circuitcompiler.Circuit
254	json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
255	panicErr(err)
256
257	// open trustedsetup.json
258	trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
259	panicErr(err)
260	var trustedsetup snark.Setup
261	json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
262	panicErr(err)
263
264	// read privateInputs file
265	privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
266	panicErr(err)
267	// read publicInputs file
268	publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
269	panicErr(err)
270	// parse inputs from inputsFile
271	var inputs circuitcompiler.Inputs
272	err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
273	panicErr(err)
274	err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
275	panicErr(err)
276
277	// calculate wittness
278	w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
279	panicErr(err)
280	fmt.Println("witness", w)
281
282	// flat code to R1CS
283	a := circuit.R1CS.A
284	b := circuit.R1CS.B
285	c := circuit.R1CS.C
286	// R1CS to QAP
287	alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(a, b, c)
288	_, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
289	hx := snark.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z)
290
291	fmt.Println(circuit)
292	fmt.Println(trustedsetup.G1T)
293	fmt.Println(hx)
294	fmt.Println(w)
295	proof, err := snark.GenerateProofs(circuit, trustedsetup, w, px)
296	panicErr(err)
297
298	fmt.Println("\n proofs:")
299	fmt.Println(proof)
300
301	// store proofs to json
302	jsonData, err := json.Marshal(proof)
303	panicErr(err)
304	// store proof into file
305	jsonFile, err := os.Create("proofs.json")
306	panicErr(err)
307	defer jsonFile.Close()
308	jsonFile.Write(jsonData)
309	jsonFile.Close()
310	fmt.Println("Proofs data written to ", jsonFile.Name())
311	return nil
312}
313
314func VerifyProofs(context *cli.Context) error {
315	// open proofs.json
316	proofsFile, err := ioutil.ReadFile("proofs.json")
317	panicErr(err)
318	var proof snark.Proof
319	json.Unmarshal([]byte(string(proofsFile)), &proof)
320	panicErr(err)
321
322	// open compiledcircuit.json
323	compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
324	panicErr(err)
325	var circuit circuitcompiler.Circuit
326	json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
327	panicErr(err)
328
329	// open trustedsetup.json
330	trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
331	panicErr(err)
332	var trustedsetup snark.Setup
333	json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
334	panicErr(err)
335
336	// read publicInputs file
337	publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
338	panicErr(err)
339	var publicSignals []*big.Int
340	err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
341	panicErr(err)
342
343	verified := snark.VerifyProof(circuit, trustedsetup, proof, publicSignals, true)
344	if !verified {
345		fmt.Println("ERROR: proofs not verified")
346	} else {
347		fmt.Println("Proofs verified")
348	}
349	return nil
350}
351
352func Groth16TrustedSetup(context *cli.Context) error {
353	// open compiledcircuit.json
354	compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
355	panicErr(err)
356	var circuit circuitcompiler.Circuit
357	json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
358	panicErr(err)
359
360	// read privateInputs file
361	privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
362	panicErr(err)
363	// read publicInputs file
364	publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
365	panicErr(err)
366
367	// parse inputs from inputsFile
368	var inputs circuitcompiler.Inputs
369	err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
370	panicErr(err)
371	err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
372	panicErr(err)
373
374	// calculate wittness
375	w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
376	panicErr(err)
377
378	// R1CS to QAP
379	alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C)
380	fmt.Println("qap")
381	fmt.Println(alphas)
382	fmt.Println(betas)
383	fmt.Println(gammas)
384
385	// calculate trusted setup
386	setup, err := groth16.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas)
387	panicErr(err)
388	fmt.Println("\nt:", setup.Toxic.T)
389
390	// remove setup.Toxic
391	var tsetup groth16.Setup
392	tsetup.Pk = setup.Pk
393	tsetup.Vk = setup.Vk
394
395	// store setup to json
396	jsonData, err := json.Marshal(tsetup)
397	panicErr(err)
398	// store setup into file
399	jsonFile, err := os.Create("trustedsetup.json")
400	panicErr(err)
401	defer jsonFile.Close()
402	jsonFile.Write(jsonData)
403	jsonFile.Close()
404	fmt.Println("Trusted Setup data written to ", jsonFile.Name())
405	return nil
406}
407
408func Groth16GenerateProofs(context *cli.Context) error {
409	// open compiledcircuit.json
410	compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
411	panicErr(err)
412	var circuit circuitcompiler.Circuit
413	json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
414	panicErr(err)
415
416	// open trustedsetup.json
417	trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
418	panicErr(err)
419	var trustedsetup groth16.Setup
420	json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
421	panicErr(err)
422
423	// read privateInputs file
424	privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
425	panicErr(err)
426	// read publicInputs file
427	publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
428	panicErr(err)
429	// parse inputs from inputsFile
430	var inputs circuitcompiler.Inputs
431	err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
432	panicErr(err)
433	err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
434	panicErr(err)
435
436	// calculate wittness
437	w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
438	panicErr(err)
439	fmt.Println("witness", w)
440
441	// flat code to R1CS
442	a := circuit.R1CS.A
443	b := circuit.R1CS.B
444	c := circuit.R1CS.C
445	// R1CS to QAP
446	alphas, betas, gammas, _ := groth16.Utils.PF.R1CSToQAP(a, b, c)
447	_, _, _, px := groth16.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
448	hx := groth16.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z)
449
450	fmt.Println(circuit)
451	fmt.Println(trustedsetup.Pk.PowersTauDelta)
452	fmt.Println(hx)
453	fmt.Println(w)
454	proof, err := groth16.GenerateProofs(circuit, trustedsetup, w, px)
455	panicErr(err)
456
457	fmt.Println("\n proofs:")
458	fmt.Println(proof)
459
460	// store proofs to json
461	jsonData, err := json.Marshal(proof)
462	panicErr(err)
463	// store proof into file
464	jsonFile, err := os.Create("proofs.json")
465	panicErr(err)
466	defer jsonFile.Close()
467	jsonFile.Write(jsonData)
468	jsonFile.Close()
469	fmt.Println("Proofs data written to ", jsonFile.Name())
470	return nil
471}
472
473func Groth16VerifyProofs(context *cli.Context) error {
474	// open proofs.json
475	proofsFile, err := ioutil.ReadFile("proofs.json")
476	panicErr(err)
477	var proof groth16.Proof
478	json.Unmarshal([]byte(string(proofsFile)), &proof)
479	panicErr(err)
480
481	// open compiledcircuit.json
482	compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
483	panicErr(err)
484	var circuit circuitcompiler.Circuit
485	json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
486	panicErr(err)
487
488	// open trustedsetup.json
489	trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
490	panicErr(err)
491	var trustedsetup groth16.Setup
492	json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
493	panicErr(err)
494
495	// read publicInputs file
496	publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
497	panicErr(err)
498	var publicSignals []*big.Int
499	err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
500	panicErr(err)
501
502	verified := groth16.VerifyProof(circuit, trustedsetup, proof, publicSignals, true)
503	if !verified {
504		fmt.Println("ERROR: proofs not verified")
505	} else {
506		fmt.Println("Proofs verified")
507	}
508	return nil
509}