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.

319 lines
8.0 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
  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 privateInputs file
  73. privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
  74. panicErr(err)
  75. // read publicInputs file
  76. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  77. panicErr(err)
  78. // parse inputs from inputsFile
  79. var inputs circuitcompiler.Inputs
  80. err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
  81. panicErr(err)
  82. err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
  83. panicErr(err)
  84. // calculate wittness
  85. w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
  86. panicErr(err)
  87. fmt.Println("\nwitness", w)
  88. // flat code to R1CS
  89. fmt.Println("\ngenerating R1CS from flat code")
  90. a, b, c := circuit.GenerateR1CS()
  91. fmt.Println("\nR1CS:")
  92. fmt.Println("a:", a)
  93. fmt.Println("b:", b)
  94. fmt.Println("c:", c)
  95. // R1CS to QAP
  96. alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
  97. fmt.Println("qap")
  98. fmt.Println(alphas)
  99. fmt.Println(betas)
  100. fmt.Println(gammas)
  101. ax, bx, cx, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
  102. hx := snark.Utils.PF.DivisorPolynomial(px, zx)
  103. // hx==px/zx so px==hx*zx
  104. // assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx))
  105. if !r1csqap.BigArraysEqual(px, snark.Utils.PF.Mul(hx, zx)) {
  106. panic(errors.New("px != hx*zx"))
  107. }
  108. // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
  109. abc := snark.Utils.PF.Sub(snark.Utils.PF.Mul(ax, bx), cx)
  110. // assert.Equal(t, abc, px)
  111. if !r1csqap.BigArraysEqual(abc, px) {
  112. panic(errors.New("abc != px"))
  113. }
  114. hz := snark.Utils.PF.Mul(hx, zx)
  115. if !r1csqap.BigArraysEqual(abc, hz) {
  116. panic(errors.New("abc != hz"))
  117. }
  118. // assert.Equal(t, abc, hz)
  119. div, rem := snark.Utils.PF.Div(px, zx)
  120. if !r1csqap.BigArraysEqual(hx, div) {
  121. panic(errors.New("hx != div"))
  122. }
  123. // assert.Equal(t, hx, div)
  124. // assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
  125. for _, r := range rem {
  126. if !bytes.Equal(r.Bytes(), big.NewInt(int64(0)).Bytes()) {
  127. panic(errors.New("error:error: px/zx rem not equal to zeros"))
  128. }
  129. }
  130. // store circuit to json
  131. jsonData, err := json.Marshal(circuit)
  132. panicErr(err)
  133. // store setup into file
  134. jsonFile, err := os.Create("compiledcircuit.json")
  135. panicErr(err)
  136. defer jsonFile.Close()
  137. jsonFile.Write(jsonData)
  138. jsonFile.Close()
  139. fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
  140. return nil
  141. }
  142. func TrustedSetup(context *cli.Context) error {
  143. // open compiledcircuit.json
  144. compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
  145. panicErr(err)
  146. var circuit circuitcompiler.Circuit
  147. json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
  148. panicErr(err)
  149. // read inputs file
  150. inputsFile, err := ioutil.ReadFile("inputs.json")
  151. panicErr(err)
  152. // parse inputs from inputsFile
  153. // var inputs []*big.Int
  154. var inputs circuitcompiler.Inputs
  155. json.Unmarshal([]byte(string(inputsFile)), &inputs)
  156. panicErr(err)
  157. // calculate wittness
  158. w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
  159. panicErr(err)
  160. // R1CS to QAP
  161. alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C)
  162. fmt.Println("qap")
  163. fmt.Println(alphas)
  164. fmt.Println(betas)
  165. fmt.Println(gammas)
  166. // calculate trusted setup
  167. setup, err := snark.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas)
  168. panicErr(err)
  169. fmt.Println("\nt:", setup.Toxic.T)
  170. // remove setup.Toxic
  171. var tsetup snark.Setup
  172. tsetup.Pk = setup.Pk
  173. tsetup.Vk = setup.Vk
  174. tsetup.G1T = setup.G1T
  175. tsetup.G2T = setup.G2T
  176. // store setup to json
  177. jsonData, err := json.Marshal(tsetup)
  178. panicErr(err)
  179. // store setup into file
  180. jsonFile, err := os.Create("trustedsetup.json")
  181. panicErr(err)
  182. defer jsonFile.Close()
  183. jsonFile.Write(jsonData)
  184. jsonFile.Close()
  185. fmt.Println("Trusted Setup data written to ", jsonFile.Name())
  186. return nil
  187. }
  188. func GenerateProofs(context *cli.Context) error {
  189. // open compiledcircuit.json
  190. compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
  191. panicErr(err)
  192. var circuit circuitcompiler.Circuit
  193. json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
  194. panicErr(err)
  195. // open trustedsetup.json
  196. trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
  197. panicErr(err)
  198. var trustedsetup snark.Setup
  199. json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
  200. panicErr(err)
  201. // read privateInputs file
  202. privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
  203. panicErr(err)
  204. // read publicInputs file
  205. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  206. panicErr(err)
  207. // parse inputs from inputsFile
  208. var inputs circuitcompiler.Inputs
  209. err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
  210. panicErr(err)
  211. err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
  212. panicErr(err)
  213. // calculate wittness
  214. w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
  215. panicErr(err)
  216. fmt.Println("\nwitness", w)
  217. // flat code to R1CS
  218. // a, b, c := circuit.GenerateR1CS()
  219. a := circuit.R1CS.A
  220. b := circuit.R1CS.B
  221. c := circuit.R1CS.C
  222. // R1CS to QAP
  223. alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
  224. _, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
  225. hx := snark.Utils.PF.DivisorPolynomial(px, zx)
  226. fmt.Println(circuit)
  227. fmt.Println(trustedsetup.G1T)
  228. fmt.Println(hx)
  229. fmt.Println(w)
  230. proof, err := snark.GenerateProofs(circuit, trustedsetup, hx, w)
  231. panicErr(err)
  232. fmt.Println("\n proofs:")
  233. fmt.Println(proof)
  234. // store proofs to json
  235. jsonData, err := json.Marshal(proof)
  236. panicErr(err)
  237. // store proof into file
  238. jsonFile, err := os.Create("proofs.json")
  239. panicErr(err)
  240. defer jsonFile.Close()
  241. jsonFile.Write(jsonData)
  242. jsonFile.Close()
  243. fmt.Println("Proofs data written to ", jsonFile.Name())
  244. return nil
  245. }
  246. func VerifyProofs(context *cli.Context) error {
  247. // open proofs.json
  248. proofsFile, err := ioutil.ReadFile("proofs.json")
  249. panicErr(err)
  250. var proof snark.Proof
  251. json.Unmarshal([]byte(string(proofsFile)), &proof)
  252. panicErr(err)
  253. // open compiledcircuit.json
  254. compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
  255. panicErr(err)
  256. var circuit circuitcompiler.Circuit
  257. json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
  258. panicErr(err)
  259. // open trustedsetup.json
  260. trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
  261. panicErr(err)
  262. var trustedsetup snark.Setup
  263. json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
  264. panicErr(err)
  265. // read publicInputs file
  266. publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
  267. panicErr(err)
  268. var publicSignals []*big.Int
  269. err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
  270. panicErr(err)
  271. verified := snark.VerifyProof(circuit, trustedsetup, proof, publicSignals, true)
  272. if !verified {
  273. fmt.Println("ERROR: proofs not verified")
  274. } else {
  275. fmt.Println("Proofs verified")
  276. }
  277. return nil
  278. }