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.0.1-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 privateInputs file
174	privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
175	panicErr(err)
176	// read publicInputs file
177	publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
178	panicErr(err)
179
180	// parse inputs from inputsFile
181	var inputs circuitcompiler.Inputs
182	err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
183	panicErr(err)
184	err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
185	panicErr(err)
186
187	// calculate wittness
188	w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
189	panicErr(err)
190
191	// R1CS to QAP
192	alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C)
193	fmt.Println("qap")
194	fmt.Println(alphas)
195	fmt.Println(betas)
196	fmt.Println(gammas)
197
198	// calculate trusted setup
199	setup, err := snark.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas)
200	panicErr(err)
201	fmt.Println("\nt:", setup.Toxic.T)
202
203	// remove setup.Toxic
204	var tsetup snark.Setup
205	tsetup.Pk = setup.Pk
206	tsetup.Vk = setup.Vk
207	tsetup.G1T = setup.G1T
208	tsetup.G2T = setup.G2T
209
210	// store setup to json
211	jsonData, err := json.Marshal(tsetup)
212	panicErr(err)
213	// store setup into file
214	jsonFile, err := os.Create("trustedsetup.json")
215	panicErr(err)
216	defer jsonFile.Close()
217	jsonFile.Write(jsonData)
218	jsonFile.Close()
219	fmt.Println("Trusted Setup data written to ", jsonFile.Name())
220	return nil
221}
222
223func GenerateProofs(context *cli.Context) error {
224	// open compiledcircuit.json
225	compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
226	panicErr(err)
227	var circuit circuitcompiler.Circuit
228	json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
229	panicErr(err)
230
231	// open trustedsetup.json
232	trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
233	panicErr(err)
234	var trustedsetup snark.Setup
235	json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
236	panicErr(err)
237
238	// read privateInputs file
239	privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
240	panicErr(err)
241	// read publicInputs file
242	publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
243	panicErr(err)
244	// parse inputs from inputsFile
245	var inputs circuitcompiler.Inputs
246	err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
247	panicErr(err)
248	err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
249	panicErr(err)
250
251	// calculate wittness
252	w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
253	panicErr(err)
254	fmt.Println("witness", w)
255
256	// flat code to R1CS
257	a := circuit.R1CS.A
258	b := circuit.R1CS.B
259	c := circuit.R1CS.C
260	// R1CS to QAP
261	alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(a, b, c)
262	_, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
263	hx := snark.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z)
264
265	fmt.Println(circuit)
266	fmt.Println(trustedsetup.G1T)
267	fmt.Println(hx)
268	fmt.Println(w)
269	proof, err := snark.GenerateProofs(circuit, trustedsetup, w, px)
270	panicErr(err)
271
272	fmt.Println("\n proofs:")
273	fmt.Println(proof)
274
275	// store proofs to json
276	jsonData, err := json.Marshal(proof)
277	panicErr(err)
278	// store proof into file
279	jsonFile, err := os.Create("proofs.json")
280	panicErr(err)
281	defer jsonFile.Close()
282	jsonFile.Write(jsonData)
283	jsonFile.Close()
284	fmt.Println("Proofs data written to ", jsonFile.Name())
285	return nil
286}
287
288func VerifyProofs(context *cli.Context) error {
289	// open proofs.json
290	proofsFile, err := ioutil.ReadFile("proofs.json")
291	panicErr(err)
292	var proof snark.Proof
293	json.Unmarshal([]byte(string(proofsFile)), &proof)
294	panicErr(err)
295
296	// open compiledcircuit.json
297	compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
298	panicErr(err)
299	var circuit circuitcompiler.Circuit
300	json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
301	panicErr(err)
302
303	// open trustedsetup.json
304	trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
305	panicErr(err)
306	var trustedsetup snark.Setup
307	json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
308	panicErr(err)
309
310	// read publicInputs file
311	publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
312	panicErr(err)
313	var publicSignals []*big.Int
314	err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
315	panicErr(err)
316
317	verified := snark.VerifyProof(circuit, trustedsetup, proof, publicSignals, true)
318	if !verified {
319		fmt.Println("ERROR: proofs not verified")
320	} else {
321		fmt.Println("Proofs verified")
322	}
323	return nil
324}