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.

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