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.

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