You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

509 lines
13 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. package main
  2. import (
  3. "bufio"
  4. "bytes"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "io/ioutil"
  9. "log"
  10. "math/big"
  11. "os"
  12. snark "github.com/arnaucube/go-snark"
  13. "github.com/arnaucube/go-snark/circuitcompiler"
  14. "github.com/arnaucube/go-snark/groth16"
  15. "github.com/arnaucube/go-snark/r1csqap"
  16. "github.com/urfave/cli"
  17. )
  18. func panicErr(err error) {
  19. if err != nil {
  20. panic(err)
  21. }
  22. }
  23. var commands = []cli.Command{
  24. {
  25. Name: "compile",
  26. Aliases: []string{},
  27. Usage: "compile a circuit",
  28. Action: CompileCircuit,
  29. },
  30. {
  31. Name: "trustedsetup",
  32. Aliases: []string{},
  33. Usage: "generate trusted setup for a circuit",
  34. Action: TrustedSetup,
  35. },
  36. {
  37. Name: "genproofs",
  38. Aliases: []string{},
  39. Usage: "generate the snark proofs",
  40. Action: GenerateProofs,
  41. },
  42. {
  43. Name: "verify",
  44. Aliases: []string{},
  45. Usage: "verify the snark proofs",
  46. Action: VerifyProofs,
  47. },
  48. {
  49. Name: "groth16",
  50. Aliases: []string{},
  51. Usage: "use groth16 protocol",
  52. Subcommands: []cli.Command{
  53. {
  54. Name: "trustedsetup",
  55. Aliases: []string{},
  56. Usage: "generate trusted setup for a circuit",
  57. Action: Groth16TrustedSetup,
  58. },
  59. {
  60. Name: "genproofs",
  61. Aliases: []string{},
  62. Usage: "generate the snark proofs",
  63. Action: Groth16GenerateProofs,
  64. },
  65. {
  66. Name: "verify",
  67. Aliases: []string{},
  68. Usage: "verify the snark proofs",
  69. Action: Groth16VerifyProofs,
  70. },
  71. },
  72. },
  73. }
  74. func main() {
  75. app := cli.NewApp()
  76. app.Name = "go-snarks-cli"
  77. app.Version = "0.0.3-alpha"
  78. app.Flags = []cli.Flag{
  79. cli.StringFlag{Name: "config"},
  80. }
  81. app.Commands = commands
  82. err := app.Run(os.Args)
  83. if err != nil {
  84. log.Fatal(err)
  85. }
  86. }
  87. func CompileCircuit(context *cli.Context) error {
  88. fmt.Println("cli")
  89. circuitPath := context.Args().Get(0)
  90. // read circuit file
  91. circuitFile, err := os.Open(circuitPath)
  92. panicErr(err)
  93. // parse circuit code
  94. parser := circuitcompiler.NewParser(bufio.NewReader(circuitFile))
  95. circuit, err := parser.Parse()
  96. panicErr(err)
  97. fmt.Println("\ncircuit data:", circuit)
  98. // read privateInputs file
  99. privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
  100. panicErr(err)
  101. // read publicInputs file
  102. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  103. panicErr(err)
  104. // parse inputs from inputsFile
  105. var inputs circuitcompiler.Inputs
  106. err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
  107. panicErr(err)
  108. err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
  109. panicErr(err)
  110. // calculate wittness
  111. w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
  112. panicErr(err)
  113. fmt.Println("\nwitness", w)
  114. // flat code to R1CS
  115. fmt.Println("\ngenerating R1CS from flat code")
  116. a, b, c := circuit.GenerateR1CS()
  117. fmt.Println("\nR1CS:")
  118. fmt.Println("a:", a)
  119. fmt.Println("b:", b)
  120. fmt.Println("c:", c)
  121. // R1CS to QAP
  122. alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
  123. fmt.Println("qap")
  124. fmt.Println(alphas)
  125. fmt.Println(betas)
  126. fmt.Println(gammas)
  127. ax, bx, cx, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
  128. hx := snark.Utils.PF.DivisorPolynomial(px, zx)
  129. // hx==px/zx so px==hx*zx
  130. // assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx))
  131. if !r1csqap.BigArraysEqual(px, snark.Utils.PF.Mul(hx, zx)) {
  132. panic(errors.New("px != hx*zx"))
  133. }
  134. // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
  135. abc := snark.Utils.PF.Sub(snark.Utils.PF.Mul(ax, bx), cx)
  136. // assert.Equal(t, abc, px)
  137. if !r1csqap.BigArraysEqual(abc, px) {
  138. panic(errors.New("abc != px"))
  139. }
  140. hz := snark.Utils.PF.Mul(hx, zx)
  141. if !r1csqap.BigArraysEqual(abc, hz) {
  142. panic(errors.New("abc != hz"))
  143. }
  144. // assert.Equal(t, abc, hz)
  145. div, rem := snark.Utils.PF.Div(px, zx)
  146. if !r1csqap.BigArraysEqual(hx, div) {
  147. panic(errors.New("hx != div"))
  148. }
  149. // assert.Equal(t, hx, div)
  150. // assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
  151. for _, r := range rem {
  152. if !bytes.Equal(r.Bytes(), big.NewInt(int64(0)).Bytes()) {
  153. panic(errors.New("error:error: px/zx rem not equal to zeros"))
  154. }
  155. }
  156. // store circuit to json
  157. jsonData, err := json.Marshal(circuit)
  158. panicErr(err)
  159. // store setup into file
  160. jsonFile, err := os.Create("compiledcircuit.json")
  161. panicErr(err)
  162. defer jsonFile.Close()
  163. jsonFile.Write(jsonData)
  164. jsonFile.Close()
  165. fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
  166. return nil
  167. }
  168. func TrustedSetup(context *cli.Context) error {
  169. // open compiledcircuit.json
  170. compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
  171. panicErr(err)
  172. var circuit circuitcompiler.Circuit
  173. json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
  174. panicErr(err)
  175. // read privateInputs file
  176. privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
  177. panicErr(err)
  178. // read publicInputs file
  179. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  180. panicErr(err)
  181. // parse inputs from inputsFile
  182. var inputs circuitcompiler.Inputs
  183. err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
  184. panicErr(err)
  185. err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
  186. panicErr(err)
  187. // calculate wittness
  188. w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
  189. panicErr(err)
  190. // R1CS to QAP
  191. alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C)
  192. fmt.Println("qap")
  193. fmt.Println(alphas)
  194. fmt.Println(betas)
  195. fmt.Println(gammas)
  196. // calculate trusted setup
  197. setup, err := snark.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas)
  198. panicErr(err)
  199. fmt.Println("\nt:", setup.Toxic.T)
  200. // remove setup.Toxic
  201. var tsetup snark.Setup
  202. tsetup.Pk = setup.Pk
  203. tsetup.Vk = setup.Vk
  204. tsetup.G1T = setup.G1T
  205. tsetup.G2T = setup.G2T
  206. // store setup to json
  207. jsonData, err := json.Marshal(tsetup)
  208. panicErr(err)
  209. // store setup into file
  210. jsonFile, err := os.Create("trustedsetup.json")
  211. panicErr(err)
  212. defer jsonFile.Close()
  213. jsonFile.Write(jsonData)
  214. jsonFile.Close()
  215. fmt.Println("Trusted Setup data written to ", jsonFile.Name())
  216. return nil
  217. }
  218. func GenerateProofs(context *cli.Context) error {
  219. // open compiledcircuit.json
  220. compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
  221. panicErr(err)
  222. var circuit circuitcompiler.Circuit
  223. json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
  224. panicErr(err)
  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. // read privateInputs file
  232. privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
  233. panicErr(err)
  234. // read publicInputs file
  235. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  236. panicErr(err)
  237. // parse inputs from inputsFile
  238. var inputs circuitcompiler.Inputs
  239. err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
  240. panicErr(err)
  241. err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
  242. panicErr(err)
  243. // calculate wittness
  244. w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
  245. panicErr(err)
  246. fmt.Println("witness", w)
  247. // flat code to R1CS
  248. a := circuit.R1CS.A
  249. b := circuit.R1CS.B
  250. c := circuit.R1CS.C
  251. // R1CS to QAP
  252. alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(a, b, c)
  253. _, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
  254. hx := snark.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z)
  255. fmt.Println(circuit)
  256. fmt.Println(trustedsetup.G1T)
  257. fmt.Println(hx)
  258. fmt.Println(w)
  259. proof, err := snark.GenerateProofs(circuit, trustedsetup, w, px)
  260. panicErr(err)
  261. fmt.Println("\n proofs:")
  262. fmt.Println(proof)
  263. // store proofs to json
  264. jsonData, err := json.Marshal(proof)
  265. panicErr(err)
  266. // store proof into file
  267. jsonFile, err := os.Create("proofs.json")
  268. panicErr(err)
  269. defer jsonFile.Close()
  270. jsonFile.Write(jsonData)
  271. jsonFile.Close()
  272. fmt.Println("Proofs data written to ", jsonFile.Name())
  273. return nil
  274. }
  275. func VerifyProofs(context *cli.Context) error {
  276. // open proofs.json
  277. proofsFile, err := ioutil.ReadFile("proofs.json")
  278. panicErr(err)
  279. var proof snark.Proof
  280. json.Unmarshal([]byte(string(proofsFile)), &proof)
  281. panicErr(err)
  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. // open trustedsetup.json
  289. trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
  290. panicErr(err)
  291. var trustedsetup snark.Setup
  292. json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
  293. panicErr(err)
  294. // read publicInputs file
  295. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  296. panicErr(err)
  297. var publicSignals []*big.Int
  298. err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
  299. panicErr(err)
  300. verified := snark.VerifyProof(circuit, trustedsetup, proof, publicSignals, true)
  301. if !verified {
  302. fmt.Println("ERROR: proofs not verified")
  303. } else {
  304. fmt.Println("Proofs verified")
  305. }
  306. return nil
  307. }
  308. func Groth16TrustedSetup(context *cli.Context) error {
  309. // open compiledcircuit.json
  310. compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
  311. panicErr(err)
  312. var circuit circuitcompiler.Circuit
  313. json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
  314. panicErr(err)
  315. // read privateInputs file
  316. privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
  317. panicErr(err)
  318. // read publicInputs file
  319. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  320. panicErr(err)
  321. // parse inputs from inputsFile
  322. var inputs circuitcompiler.Inputs
  323. err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
  324. panicErr(err)
  325. err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
  326. panicErr(err)
  327. // calculate wittness
  328. w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
  329. panicErr(err)
  330. // R1CS to QAP
  331. alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C)
  332. fmt.Println("qap")
  333. fmt.Println(alphas)
  334. fmt.Println(betas)
  335. fmt.Println(gammas)
  336. // calculate trusted setup
  337. setup, err := groth16.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas)
  338. panicErr(err)
  339. fmt.Println("\nt:", setup.Toxic.T)
  340. // remove setup.Toxic
  341. var tsetup groth16.Setup
  342. tsetup.Pk = setup.Pk
  343. tsetup.Vk = setup.Vk
  344. // store setup to json
  345. jsonData, err := json.Marshal(tsetup)
  346. panicErr(err)
  347. // store setup into file
  348. jsonFile, err := os.Create("trustedsetup.json")
  349. panicErr(err)
  350. defer jsonFile.Close()
  351. jsonFile.Write(jsonData)
  352. jsonFile.Close()
  353. fmt.Println("Trusted Setup data written to ", jsonFile.Name())
  354. return nil
  355. }
  356. func Groth16GenerateProofs(context *cli.Context) error {
  357. // open compiledcircuit.json
  358. compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
  359. panicErr(err)
  360. var circuit circuitcompiler.Circuit
  361. json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
  362. panicErr(err)
  363. // open trustedsetup.json
  364. trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
  365. panicErr(err)
  366. var trustedsetup groth16.Setup
  367. json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
  368. panicErr(err)
  369. // read privateInputs file
  370. privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
  371. panicErr(err)
  372. // read publicInputs file
  373. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  374. panicErr(err)
  375. // parse inputs from inputsFile
  376. var inputs circuitcompiler.Inputs
  377. err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
  378. panicErr(err)
  379. err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
  380. panicErr(err)
  381. // calculate wittness
  382. w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
  383. panicErr(err)
  384. fmt.Println("witness", w)
  385. // flat code to R1CS
  386. a := circuit.R1CS.A
  387. b := circuit.R1CS.B
  388. c := circuit.R1CS.C
  389. // R1CS to QAP
  390. alphas, betas, gammas, _ := groth16.Utils.PF.R1CSToQAP(a, b, c)
  391. _, _, _, px := groth16.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
  392. hx := groth16.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z)
  393. fmt.Println(circuit)
  394. fmt.Println(trustedsetup.Pk.PowersTauDelta)
  395. fmt.Println(hx)
  396. fmt.Println(w)
  397. proof, err := groth16.GenerateProofs(circuit, trustedsetup, w, px)
  398. panicErr(err)
  399. fmt.Println("\n proofs:")
  400. fmt.Println(proof)
  401. // store proofs to json
  402. jsonData, err := json.Marshal(proof)
  403. panicErr(err)
  404. // store proof into file
  405. jsonFile, err := os.Create("proofs.json")
  406. panicErr(err)
  407. defer jsonFile.Close()
  408. jsonFile.Write(jsonData)
  409. jsonFile.Close()
  410. fmt.Println("Proofs data written to ", jsonFile.Name())
  411. return nil
  412. }
  413. func Groth16VerifyProofs(context *cli.Context) error {
  414. // open proofs.json
  415. proofsFile, err := ioutil.ReadFile("proofs.json")
  416. panicErr(err)
  417. var proof groth16.Proof
  418. json.Unmarshal([]byte(string(proofsFile)), &proof)
  419. panicErr(err)
  420. // open compiledcircuit.json
  421. compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
  422. panicErr(err)
  423. var circuit circuitcompiler.Circuit
  424. json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
  425. panicErr(err)
  426. // open trustedsetup.json
  427. trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
  428. panicErr(err)
  429. var trustedsetup groth16.Setup
  430. json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
  431. panicErr(err)
  432. // read publicInputs file
  433. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  434. panicErr(err)
  435. var publicSignals []*big.Int
  436. err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
  437. panicErr(err)
  438. verified := groth16.VerifyProof(circuit, trustedsetup, proof, publicSignals, true)
  439. if !verified {
  440. fmt.Println("ERROR: proofs not verified")
  441. } else {
  442. fmt.Println("Proofs verified")
  443. }
  444. return nil
  445. }