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	// read circuit file
 66	circuitFile, err := os.Open("test.circuit")
 67	panicErr(err)
 68
 69	// parse circuit code
 70	parser := circuitcompiler.NewParser(bufio.NewReader(circuitFile))
 71	circuit, err := parser.Parse()
 72	panicErr(err)
 73	fmt.Println("\ncircuit data:", circuit)
 74
 75	// read inputs file
 76	inputsFile, err := ioutil.ReadFile("inputs.json")
 77	panicErr(err)
 78
 79	// parse inputs from inputsFile
 80	var inputs []*big.Int
 81	json.Unmarshal([]byte(string(inputsFile)), &inputs)
 82	panicErr(err)
 83
 84	// calculate wittness
 85	w, err := circuit.CalculateWitness(inputs)
 86	panicErr(err)
 87	fmt.Println("\nwitness", w)
 88
 89	// flat code to R1CS
 90	fmt.Println("\ngenerating R1CS from flat code")
 91	a, b, c := circuit.GenerateR1CS()
 92	fmt.Println("\nR1CS:")
 93	fmt.Println("a:", a)
 94	fmt.Println("b:", b)
 95	fmt.Println("c:", c)
 96
 97	// R1CS to QAP
 98	alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
 99	fmt.Println("qap")
100	fmt.Println(alphas)
101	fmt.Println(betas)
102	fmt.Println(gammas)
103
104	ax, bx, cx, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
105
106	hx := snark.Utils.PF.DivisorPolynomial(px, zx)
107
108	// hx==px/zx so px==hx*zx
109	// assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx))
110	if !r1csqap.BigArraysEqual(px, snark.Utils.PF.Mul(hx, zx)) {
111		panic(errors.New("px != hx*zx"))
112	}
113
114	// p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
115	abc := snark.Utils.PF.Sub(snark.Utils.PF.Mul(ax, bx), cx)
116	// assert.Equal(t, abc, px)
117	if !r1csqap.BigArraysEqual(abc, px) {
118		panic(errors.New("abc != px"))
119	}
120	hz := snark.Utils.PF.Mul(hx, zx)
121	if !r1csqap.BigArraysEqual(abc, hz) {
122		panic(errors.New("abc != hz"))
123	}
124	// assert.Equal(t, abc, hz)
125
126	div, rem := snark.Utils.PF.Div(px, zx)
127	if !r1csqap.BigArraysEqual(hx, div) {
128		panic(errors.New("hx != div"))
129	}
130	// assert.Equal(t, hx, div)
131	// assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
132	for _, r := range rem {
133		if !bytes.Equal(r.Bytes(), big.NewInt(int64(0)).Bytes()) {
134			panic(errors.New("error:error:  px/zx rem not equal to zeros"))
135		}
136	}
137
138	// calculate trusted setup
139	setup, err := snark.GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas, zx)
140	panicErr(err)
141	fmt.Println("\nt:", setup.Toxic.T)
142
143	// store circuit to json
144	jsonData, err := json.Marshal(circuit)
145	panicErr(err)
146	// store setup into file
147	jsonFile, err := os.Create("compiledcircuit.json")
148	panicErr(err)
149	defer jsonFile.Close()
150	jsonFile.Write(jsonData)
151	jsonFile.Close()
152	fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
153	// store setup to json
154	jsonData, err = json.Marshal(setup)
155	panicErr(err)
156	// store setup into file
157	jsonFile, err = os.Create("trustedsetup.json")
158	panicErr(err)
159	defer jsonFile.Close()
160	jsonFile.Write(jsonData)
161	jsonFile.Close()
162	fmt.Println("Trusted Setup data written to ", jsonFile.Name())
163	return nil
164}
165
166func GenerateProofs(context *cli.Context) error {
167	// open compiledcircuit.json
168	compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
169	panicErr(err)
170	var circuit circuitcompiler.Circuit
171	json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
172	panicErr(err)
173
174	// open trustedsetup.json
175	trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
176	panicErr(err)
177	var trustedsetup snark.Setup
178	json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
179	panicErr(err)
180
181	// read inputs file
182	inputsFile, err := ioutil.ReadFile("inputs.json")
183	panicErr(err)
184	// parse inputs from inputsFile
185	var inputs []*big.Int
186	json.Unmarshal([]byte(string(inputsFile)), &inputs)
187	panicErr(err)
188	// calculate wittness
189	w, err := circuit.CalculateWitness(inputs)
190	panicErr(err)
191	fmt.Println("\nwitness", w)
192
193	// flat code to R1CS
194	a, b, c := circuit.GenerateR1CS()
195	// R1CS to QAP
196	alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
197	_, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
198	hx := snark.Utils.PF.DivisorPolynomial(px, zx)
199
200	proof, err := snark.GenerateProofs(circuit, trustedsetup, hx, w)
201	panicErr(err)
202
203	fmt.Println("\n proofs:")
204	fmt.Println(proof)
205
206	// store proofs to json
207	jsonData, err := json.Marshal(proof)
208	panicErr(err)
209	// store proof into file
210	jsonFile, err := os.Create("proofs.json")
211	panicErr(err)
212	defer jsonFile.Close()
213	jsonFile.Write(jsonData)
214	jsonFile.Close()
215	fmt.Println("Proofs data written to ", jsonFile.Name())
216	return nil
217}
218
219func VerifyProofs(context *cli.Context) error {
220	// open proofs.json
221	proofsFile, err := ioutil.ReadFile("proofs.json")
222	panicErr(err)
223	var proof snark.Proof
224	json.Unmarshal([]byte(string(proofsFile)), &proof)
225	panicErr(err)
226
227	// open compiledcircuit.json
228	compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
229	panicErr(err)
230	var circuit circuitcompiler.Circuit
231	json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
232	panicErr(err)
233
234	// open trustedsetup.json
235	trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
236	panicErr(err)
237	var trustedsetup snark.Setup
238	json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
239	panicErr(err)
240
241	verified := snark.VerifyProof(circuit, trustedsetup, proof, true)
242	if !verified {
243		fmt.Println("ERROR: proofs not verified")
244	} else {
245		fmt.Println("Proofs verified")
246	}
247	return nil
248}