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.

259 lines
6.2 KiB

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/r1csqap"
  15. "github.com/urfave/cli"
  16. )
  17. func panicErr(err error) {
  18. if err != nil {
  19. panic(err)
  20. }
  21. }
  22. var commands = []cli.Command{
  23. {
  24. Name: "compile",
  25. Aliases: []string{},
  26. Usage: "compile a circuit",
  27. Action: CompileCircuit,
  28. },
  29. {
  30. Name: "genproofs",
  31. Aliases: []string{},
  32. Usage: "generate the snark proofs",
  33. Action: GenerateProofs,
  34. },
  35. {
  36. Name: "verify",
  37. Aliases: []string{},
  38. Usage: "verify the snark proofs",
  39. Action: VerifyProofs,
  40. },
  41. }
  42. func main() {
  43. app := cli.NewApp()
  44. app.Name = "go-snarks-cli"
  45. app.Version = "0.1.0-alpha"
  46. app.Flags = []cli.Flag{
  47. cli.StringFlag{Name: "config"},
  48. }
  49. app.Commands = commands
  50. err := app.Run(os.Args)
  51. if err != nil {
  52. log.Fatal(err)
  53. }
  54. }
  55. func CompileCircuit(context *cli.Context) error {
  56. fmt.Println("cli")
  57. circuitPath := context.Args().Get(0)
  58. // read circuit file
  59. circuitFile, err := os.Open(circuitPath)
  60. panicErr(err)
  61. // parse circuit code
  62. parser := circuitcompiler.NewParser(bufio.NewReader(circuitFile))
  63. circuit, err := parser.Parse()
  64. panicErr(err)
  65. fmt.Println("\ncircuit data:", circuit)
  66. // read inputs file
  67. inputsFile, err := ioutil.ReadFile("inputs.json")
  68. panicErr(err)
  69. // parse inputs from inputsFile
  70. var inputs []*big.Int
  71. json.Unmarshal([]byte(string(inputsFile)), &inputs)
  72. panicErr(err)
  73. // calculate wittness
  74. w, err := circuit.CalculateWitness(inputs)
  75. panicErr(err)
  76. fmt.Println("\nwitness", w)
  77. // flat code to R1CS
  78. fmt.Println("\ngenerating R1CS from flat code")
  79. a, b, c := circuit.GenerateR1CS()
  80. fmt.Println("\nR1CS:")
  81. fmt.Println("a:", a)
  82. fmt.Println("b:", b)
  83. fmt.Println("c:", c)
  84. // R1CS to QAP
  85. alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
  86. fmt.Println("qap")
  87. fmt.Println(alphas)
  88. fmt.Println(betas)
  89. fmt.Println(gammas)
  90. ax, bx, cx, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
  91. hx := snark.Utils.PF.DivisorPolynomial(px, zx)
  92. // hx==px/zx so px==hx*zx
  93. // assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx))
  94. if !r1csqap.BigArraysEqual(px, snark.Utils.PF.Mul(hx, zx)) {
  95. panic(errors.New("px != hx*zx"))
  96. }
  97. // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
  98. abc := snark.Utils.PF.Sub(snark.Utils.PF.Mul(ax, bx), cx)
  99. // assert.Equal(t, abc, px)
  100. if !r1csqap.BigArraysEqual(abc, px) {
  101. panic(errors.New("abc != px"))
  102. }
  103. hz := snark.Utils.PF.Mul(hx, zx)
  104. if !r1csqap.BigArraysEqual(abc, hz) {
  105. panic(errors.New("abc != hz"))
  106. }
  107. // assert.Equal(t, abc, hz)
  108. div, rem := snark.Utils.PF.Div(px, zx)
  109. if !r1csqap.BigArraysEqual(hx, div) {
  110. panic(errors.New("hx != div"))
  111. }
  112. // assert.Equal(t, hx, div)
  113. // assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
  114. for _, r := range rem {
  115. if !bytes.Equal(r.Bytes(), big.NewInt(int64(0)).Bytes()) {
  116. panic(errors.New("error:error: px/zx rem not equal to zeros"))
  117. }
  118. }
  119. // calculate trusted setup
  120. setup, err := snark.GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas, zx)
  121. panicErr(err)
  122. fmt.Println("\nt:", setup.Toxic.T)
  123. // store circuit to json
  124. jsonData, err := json.Marshal(circuit)
  125. panicErr(err)
  126. // store setup into file
  127. jsonFile, err := os.Create("compiledcircuit.json")
  128. panicErr(err)
  129. defer jsonFile.Close()
  130. jsonFile.Write(jsonData)
  131. jsonFile.Close()
  132. fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
  133. // remove setup.Toxic
  134. var tsetup snark.Setup
  135. tsetup.Pk = setup.Pk
  136. tsetup.Vk = setup.Vk
  137. tsetup.G1T = setup.G1T
  138. tsetup.G2T = setup.G2T
  139. // store setup to json
  140. jsonData, err = json.Marshal(tsetup)
  141. panicErr(err)
  142. // store setup into file
  143. jsonFile, err = os.Create("trustedsetup.json")
  144. panicErr(err)
  145. defer jsonFile.Close()
  146. jsonFile.Write(jsonData)
  147. jsonFile.Close()
  148. fmt.Println("Trusted Setup data written to ", jsonFile.Name())
  149. return nil
  150. }
  151. func GenerateProofs(context *cli.Context) error {
  152. // open compiledcircuit.json
  153. compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
  154. panicErr(err)
  155. var circuit circuitcompiler.Circuit
  156. json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
  157. panicErr(err)
  158. // open trustedsetup.json
  159. trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
  160. panicErr(err)
  161. var trustedsetup snark.Setup
  162. json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
  163. panicErr(err)
  164. // read inputs file
  165. inputsFile, err := ioutil.ReadFile("inputs.json")
  166. panicErr(err)
  167. // parse inputs from inputsFile
  168. var inputs []*big.Int
  169. json.Unmarshal([]byte(string(inputsFile)), &inputs)
  170. panicErr(err)
  171. // calculate wittness
  172. w, err := circuit.CalculateWitness(inputs)
  173. panicErr(err)
  174. fmt.Println("\nwitness", w)
  175. // flat code to R1CS
  176. a, b, c := circuit.GenerateR1CS()
  177. // R1CS to QAP
  178. alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
  179. _, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
  180. hx := snark.Utils.PF.DivisorPolynomial(px, zx)
  181. proof, err := snark.GenerateProofs(circuit, trustedsetup, hx, w)
  182. panicErr(err)
  183. fmt.Println("\n proofs:")
  184. fmt.Println(proof)
  185. fmt.Println("public signals:", proof.PublicSignals)
  186. // store proofs to json
  187. jsonData, err := json.Marshal(proof)
  188. panicErr(err)
  189. // store proof into file
  190. jsonFile, err := os.Create("proofs.json")
  191. panicErr(err)
  192. defer jsonFile.Close()
  193. jsonFile.Write(jsonData)
  194. jsonFile.Close()
  195. fmt.Println("Proofs data written to ", jsonFile.Name())
  196. return nil
  197. }
  198. func VerifyProofs(context *cli.Context) error {
  199. // open proofs.json
  200. proofsFile, err := ioutil.ReadFile("proofs.json")
  201. panicErr(err)
  202. var proof snark.Proof
  203. json.Unmarshal([]byte(string(proofsFile)), &proof)
  204. panicErr(err)
  205. // open compiledcircuit.json
  206. compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
  207. panicErr(err)
  208. var circuit circuitcompiler.Circuit
  209. json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
  210. panicErr(err)
  211. // open trustedsetup.json
  212. trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
  213. panicErr(err)
  214. var trustedsetup snark.Setup
  215. json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
  216. panicErr(err)
  217. verified := snark.VerifyProof(circuit, trustedsetup, proof, true)
  218. if !verified {
  219. fmt.Println("ERROR: proofs not verified")
  220. } else {
  221. fmt.Println("Proofs verified")
  222. }
  223. return nil
  224. }