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.

550 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
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/arnaucube/go-snark/wasm/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.G1T = setup.G1T
  246. tsetup.G2T = setup.G2T
  247. // store setup to json
  248. jsonData, err := json.Marshal(tsetup)
  249. panicErr(err)
  250. // store setup into file
  251. jsonFile, err := os.Create("trustedsetup.json")
  252. panicErr(err)
  253. defer jsonFile.Close()
  254. jsonFile.Write(jsonData)
  255. jsonFile.Close()
  256. fmt.Println("Trusted Setup data written to ", jsonFile.Name())
  257. if wasmFlag {
  258. tsetupString := utils.SetupToString(tsetup)
  259. jsonData, err := json.Marshal(tsetupString)
  260. panicErr(err)
  261. // store setup into file
  262. jsonFile, err := os.Create("trustedsetupString.json")
  263. panicErr(err)
  264. defer jsonFile.Close()
  265. jsonFile.Write(jsonData)
  266. jsonFile.Close()
  267. }
  268. return nil
  269. }
  270. func GenerateProofs(context *cli.Context) error {
  271. // open compiledcircuit.json
  272. compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
  273. panicErr(err)
  274. var circuit circuitcompiler.Circuit
  275. json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
  276. panicErr(err)
  277. // open trustedsetup.json
  278. trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
  279. panicErr(err)
  280. var trustedsetup snark.Setup
  281. json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
  282. panicErr(err)
  283. // read privateInputs file
  284. privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
  285. panicErr(err)
  286. // read publicInputs file
  287. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  288. panicErr(err)
  289. // parse inputs from inputsFile
  290. var inputs circuitcompiler.Inputs
  291. err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
  292. panicErr(err)
  293. err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
  294. panicErr(err)
  295. // calculate wittness
  296. w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
  297. panicErr(err)
  298. fmt.Println("witness", w)
  299. // flat code to R1CS
  300. a := circuit.R1CS.A
  301. b := circuit.R1CS.B
  302. c := circuit.R1CS.C
  303. // R1CS to QAP
  304. alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(a, b, c)
  305. _, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
  306. hx := snark.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z)
  307. fmt.Println(circuit)
  308. fmt.Println(trustedsetup.G1T)
  309. fmt.Println(hx)
  310. fmt.Println(w)
  311. proof, err := snark.GenerateProofs(circuit, trustedsetup, w, px)
  312. panicErr(err)
  313. fmt.Println("\n proofs:")
  314. fmt.Println(proof)
  315. // store proofs to json
  316. jsonData, err := json.Marshal(proof)
  317. panicErr(err)
  318. // store proof into file
  319. jsonFile, err := os.Create("proofs.json")
  320. panicErr(err)
  321. defer jsonFile.Close()
  322. jsonFile.Write(jsonData)
  323. jsonFile.Close()
  324. fmt.Println("Proofs data written to ", jsonFile.Name())
  325. return nil
  326. }
  327. func VerifyProofs(context *cli.Context) error {
  328. // open proofs.json
  329. proofsFile, err := ioutil.ReadFile("proofs.json")
  330. panicErr(err)
  331. var proof snark.Proof
  332. json.Unmarshal([]byte(string(proofsFile)), &proof)
  333. panicErr(err)
  334. // open trustedsetup.json
  335. trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
  336. panicErr(err)
  337. var trustedsetup snark.Setup
  338. json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
  339. panicErr(err)
  340. // read publicInputs file
  341. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  342. panicErr(err)
  343. var publicSignals []*big.Int
  344. err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
  345. panicErr(err)
  346. verified := snark.VerifyProof(trustedsetup, proof, publicSignals, true)
  347. if !verified {
  348. fmt.Println("ERROR: proofs not verified")
  349. } else {
  350. fmt.Println("Proofs verified")
  351. }
  352. return nil
  353. }
  354. func Groth16TrustedSetup(context *cli.Context) error {
  355. // open compiledcircuit.json
  356. compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
  357. panicErr(err)
  358. var circuit circuitcompiler.Circuit
  359. json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
  360. panicErr(err)
  361. // read privateInputs file
  362. privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
  363. panicErr(err)
  364. // read publicInputs file
  365. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  366. panicErr(err)
  367. // parse inputs from inputsFile
  368. var inputs circuitcompiler.Inputs
  369. err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
  370. panicErr(err)
  371. err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
  372. panicErr(err)
  373. // calculate wittness
  374. w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
  375. panicErr(err)
  376. // R1CS to QAP
  377. alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C)
  378. fmt.Println("qap")
  379. fmt.Println(alphas)
  380. fmt.Println(betas)
  381. fmt.Println(gammas)
  382. // calculate trusted setup
  383. setup, err := groth16.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas)
  384. panicErr(err)
  385. fmt.Println("\nt:", setup.Toxic.T)
  386. // remove setup.Toxic
  387. var tsetup groth16.Setup
  388. tsetup.Pk = setup.Pk
  389. tsetup.Vk = setup.Vk
  390. // store setup to json
  391. jsonData, err := json.Marshal(tsetup)
  392. panicErr(err)
  393. // store setup into file
  394. jsonFile, err := os.Create("trustedsetup.json")
  395. panicErr(err)
  396. defer jsonFile.Close()
  397. jsonFile.Write(jsonData)
  398. jsonFile.Close()
  399. fmt.Println("Trusted Setup data written to ", jsonFile.Name())
  400. return nil
  401. }
  402. func Groth16GenerateProofs(context *cli.Context) error {
  403. // open compiledcircuit.json
  404. compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
  405. panicErr(err)
  406. var circuit circuitcompiler.Circuit
  407. json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
  408. panicErr(err)
  409. // open trustedsetup.json
  410. trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
  411. panicErr(err)
  412. var trustedsetup groth16.Setup
  413. json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
  414. panicErr(err)
  415. // read privateInputs file
  416. privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
  417. panicErr(err)
  418. // read publicInputs file
  419. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  420. panicErr(err)
  421. // parse inputs from inputsFile
  422. var inputs circuitcompiler.Inputs
  423. err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
  424. panicErr(err)
  425. err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
  426. panicErr(err)
  427. // calculate wittness
  428. w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
  429. panicErr(err)
  430. fmt.Println("witness", w)
  431. // flat code to R1CS
  432. a := circuit.R1CS.A
  433. b := circuit.R1CS.B
  434. c := circuit.R1CS.C
  435. // R1CS to QAP
  436. alphas, betas, gammas, _ := groth16.Utils.PF.R1CSToQAP(a, b, c)
  437. _, _, _, px := groth16.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
  438. hx := groth16.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z)
  439. fmt.Println(circuit)
  440. fmt.Println(trustedsetup.Pk.PowersTauDelta)
  441. fmt.Println(hx)
  442. fmt.Println(w)
  443. proof, err := groth16.GenerateProofs(circuit, trustedsetup, w, px)
  444. panicErr(err)
  445. fmt.Println("\n proofs:")
  446. fmt.Println(proof)
  447. // store proofs to json
  448. jsonData, err := json.Marshal(proof)
  449. panicErr(err)
  450. // store proof into file
  451. jsonFile, err := os.Create("proofs.json")
  452. panicErr(err)
  453. defer jsonFile.Close()
  454. jsonFile.Write(jsonData)
  455. jsonFile.Close()
  456. fmt.Println("Proofs data written to ", jsonFile.Name())
  457. return nil
  458. }
  459. func Groth16VerifyProofs(context *cli.Context) error {
  460. // open proofs.json
  461. proofsFile, err := ioutil.ReadFile("proofs.json")
  462. panicErr(err)
  463. var proof groth16.Proof
  464. json.Unmarshal([]byte(string(proofsFile)), &proof)
  465. panicErr(err)
  466. // open trustedsetup.json
  467. trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
  468. panicErr(err)
  469. var trustedsetup groth16.Setup
  470. json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
  471. panicErr(err)
  472. // read publicInputs file
  473. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  474. panicErr(err)
  475. var publicSignals []*big.Int
  476. err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
  477. panicErr(err)
  478. verified := groth16.VerifyProof(trustedsetup, proof, publicSignals, true)
  479. if !verified {
  480. fmt.Println("ERROR: proofs not verified")
  481. } else {
  482. fmt.Println("Proofs verified")
  483. }
  484. return nil
  485. }