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