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