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/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}