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.

248 lines
6.0 KiB

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