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.

329 lines
9.8 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
  1. package snark
  2. import (
  3. "bytes"
  4. "fmt"
  5. "math/big"
  6. "strings"
  7. "testing"
  8. "time"
  9. "github.com/arnaucube/go-snark/circuitcompiler"
  10. "github.com/arnaucube/go-snark/r1csqap"
  11. "github.com/stretchr/testify/assert"
  12. )
  13. func TestZkFromFlatCircuitCode(t *testing.T) {
  14. // compile circuit and get the R1CS
  15. // circuit function
  16. // y = x^3 + x + 5
  17. flatCode := `
  18. func test(private s0, public s1):
  19. s2 = s0 * s0
  20. s3 = s2 * s0
  21. s4 = s3 + s0
  22. s5 = s4 + 5
  23. equals(s1, s5)
  24. out = 1 * 1
  25. `
  26. fmt.Print("\nflat code of the circuit:")
  27. fmt.Println(flatCode)
  28. // parse the code
  29. parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
  30. circuit, err := parser.Parse()
  31. assert.Nil(t, err)
  32. // fmt.Println("\ncircuit data:", circuit)
  33. // circuitJson, _ := json.Marshal(circuit)
  34. // fmt.Println("circuit:", string(circuitJson))
  35. b3 := big.NewInt(int64(3))
  36. privateInputs := []*big.Int{b3}
  37. b35 := big.NewInt(int64(35))
  38. publicSignals := []*big.Int{b35}
  39. // wittness
  40. w, err := circuit.CalculateWitness(privateInputs, publicSignals)
  41. assert.Nil(t, err)
  42. // flat code to R1CS
  43. fmt.Println("\ngenerating R1CS from flat code")
  44. a, b, c := circuit.GenerateR1CS()
  45. fmt.Println("\nR1CS:")
  46. fmt.Println("a:", a)
  47. fmt.Println("b:", b)
  48. fmt.Println("c:", c)
  49. // R1CS to QAP
  50. // TODO zxQAP is not used and is an old impl, TODO remove
  51. alphas, betas, gammas, zxQAP := Utils.PF.R1CSToQAP(a, b, c)
  52. fmt.Println("qap")
  53. assert.Equal(t, 8, len(alphas))
  54. assert.Equal(t, 8, len(alphas))
  55. assert.Equal(t, 8, len(alphas))
  56. assert.Equal(t, 7, len(zxQAP))
  57. assert.True(t, !bytes.Equal(alphas[1][1].Bytes(), big.NewInt(int64(0)).Bytes()))
  58. ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
  59. assert.Equal(t, 7, len(ax))
  60. assert.Equal(t, 7, len(bx))
  61. assert.Equal(t, 7, len(cx))
  62. assert.Equal(t, 13, len(px))
  63. hxQAP := Utils.PF.DivisorPolynomial(px, zxQAP)
  64. assert.Equal(t, 7, len(hxQAP))
  65. // hx==px/zx so px==hx*zx
  66. assert.Equal(t, px, Utils.PF.Mul(hxQAP, zxQAP))
  67. // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
  68. abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx)
  69. assert.Equal(t, abc, px)
  70. hzQAP := Utils.PF.Mul(hxQAP, zxQAP)
  71. assert.Equal(t, abc, hzQAP)
  72. div, rem := Utils.PF.Div(px, zxQAP)
  73. assert.Equal(t, hxQAP, div)
  74. assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(6))
  75. // calculate trusted setup
  76. setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas)
  77. assert.Nil(t, err)
  78. fmt.Println("\nt:", setup.Toxic.T)
  79. // zx and setup.Pk.Z should be the same (currently not, the correct one is the calculation used inside GenerateTrustedSetup function), the calculation is repeated. TODO avoid repeating calculation
  80. assert.Equal(t, zxQAP, setup.Pk.Z)
  81. hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z)
  82. assert.Equal(t, hx, hxQAP)
  83. // assert.Equal(t, hxQAP, hx)
  84. div, rem = Utils.PF.Div(px, setup.Pk.Z)
  85. assert.Equal(t, hx, div)
  86. assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(6))
  87. assert.Equal(t, px, Utils.PF.Mul(hxQAP, zxQAP))
  88. // hx==px/zx so px==hx*zx
  89. assert.Equal(t, px, Utils.PF.Mul(hx, setup.Pk.Z))
  90. // check length of polynomials H(x) and Z(x)
  91. assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1)
  92. assert.Equal(t, len(hxQAP), len(px)-len(zxQAP)+1)
  93. proof, err := GenerateProofs(*circuit, setup, w, px)
  94. assert.Nil(t, err)
  95. // fmt.Println("\n proofs:")
  96. // fmt.Println(proof)
  97. // fmt.Println("public signals:", proof.PublicSignals)
  98. fmt.Println("\nsignals:", circuit.Signals)
  99. fmt.Println("witness:", w)
  100. b35Verif := big.NewInt(int64(35))
  101. publicSignalsVerif := []*big.Int{b35Verif}
  102. before := time.Now()
  103. assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true))
  104. fmt.Println("verify proof time elapsed:", time.Since(before))
  105. // check that with another public input the verification returns false
  106. bOtherWrongPublic := big.NewInt(int64(34))
  107. wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
  108. assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, true))
  109. }
  110. func TestZkMultiplication(t *testing.T) {
  111. flatCode := `
  112. func test(private a, private b, public c):
  113. d = a * b
  114. equals(c, d)
  115. out = 1 * 1
  116. `
  117. fmt.Println("flat code", flatCode)
  118. // parse the code
  119. parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
  120. circuit, err := parser.Parse()
  121. assert.Nil(t, err)
  122. b3 := big.NewInt(int64(3))
  123. b4 := big.NewInt(int64(4))
  124. privateInputs := []*big.Int{b3, b4}
  125. b12 := big.NewInt(int64(12))
  126. publicSignals := []*big.Int{b12}
  127. // wittness
  128. w, err := circuit.CalculateWitness(privateInputs, publicSignals)
  129. assert.Nil(t, err)
  130. // flat code to R1CS
  131. fmt.Println("\ngenerating R1CS from flat code")
  132. a, b, c := circuit.GenerateR1CS()
  133. fmt.Println("\nR1CS:")
  134. fmt.Println("a:", a)
  135. fmt.Println("b:", b)
  136. fmt.Println("c:", c)
  137. // R1CS to QAP
  138. // TODO zxQAP is not used and is an old impl. TODO remove
  139. alphas, betas, gammas, zxQAP := Utils.PF.R1CSToQAP(a, b, c)
  140. assert.Equal(t, 6, len(alphas))
  141. assert.Equal(t, 6, len(betas))
  142. assert.Equal(t, 6, len(betas))
  143. assert.Equal(t, 5, len(zxQAP))
  144. assert.True(t, !bytes.Equal(alphas[1][1].Bytes(), big.NewInt(int64(0)).Bytes()))
  145. ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
  146. assert.Equal(t, 4, len(ax))
  147. assert.Equal(t, 4, len(bx))
  148. assert.Equal(t, 4, len(cx))
  149. assert.Equal(t, 7, len(px))
  150. hxQAP := Utils.PF.DivisorPolynomial(px, zxQAP)
  151. assert.Equal(t, 3, len(hxQAP))
  152. // hx==px/zx so px==hx*zx
  153. assert.Equal(t, px, Utils.PF.Mul(hxQAP, zxQAP))
  154. // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
  155. abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx)
  156. assert.Equal(t, abc, px)
  157. hzQAP := Utils.PF.Mul(hxQAP, zxQAP)
  158. assert.Equal(t, abc, hzQAP)
  159. div, rem := Utils.PF.Div(px, zxQAP)
  160. assert.Equal(t, hxQAP, div)
  161. assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
  162. // calculate trusted setup
  163. setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas)
  164. assert.Nil(t, err)
  165. // fmt.Println("\nt:", setup.Toxic.T)
  166. // zx and setup.Pk.Z should be the same (currently not, the correct one is the calculation used inside GenerateTrustedSetup function), the calculation is repeated. TODO avoid repeating calculation
  167. assert.Equal(t, zxQAP, setup.Pk.Z)
  168. hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z)
  169. assert.Equal(t, 3, len(hx))
  170. assert.Equal(t, hx, hxQAP)
  171. div, rem = Utils.PF.Div(px, setup.Pk.Z)
  172. assert.Equal(t, hx, div)
  173. assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
  174. assert.Equal(t, px, Utils.PF.Mul(hxQAP, zxQAP))
  175. // hx==px/zx so px==hx*zx
  176. assert.Equal(t, px, Utils.PF.Mul(hx, setup.Pk.Z))
  177. // check length of polynomials H(x) and Z(x)
  178. assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1)
  179. assert.Equal(t, len(hxQAP), len(px)-len(zxQAP)+1)
  180. proof, err := GenerateProofs(*circuit, setup, w, px)
  181. assert.Nil(t, err)
  182. // fmt.Println("\n proofs:")
  183. // fmt.Println(proof)
  184. // fmt.Println("public signals:", proof.PublicSignals)
  185. fmt.Println("\n", circuit.Signals)
  186. fmt.Println("witness", w)
  187. b12Verif := big.NewInt(int64(12))
  188. publicSignalsVerif := []*big.Int{b12Verif}
  189. before := time.Now()
  190. assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true))
  191. fmt.Println("verify proof time elapsed:", time.Since(before))
  192. // check that with another public input the verification returns false
  193. bOtherWrongPublic := big.NewInt(int64(11))
  194. wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
  195. assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, true))
  196. }
  197. func TestMinimalFlow(t *testing.T) {
  198. // circuit function
  199. // y = x^3 + x + 5
  200. flatCode := `
  201. func test(private s0, public s1):
  202. s2 = s0 * s0
  203. s3 = s2 * s0
  204. s4 = s3 + s0
  205. s5 = s4 + 5
  206. equals(s1, s5)
  207. out = 1 * 1
  208. `
  209. fmt.Print("\nflat code of the circuit:")
  210. fmt.Println(flatCode)
  211. // parse the code
  212. parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
  213. circuit, err := parser.Parse()
  214. assert.Nil(t, err)
  215. b3 := big.NewInt(int64(3))
  216. privateInputs := []*big.Int{b3}
  217. b35 := big.NewInt(int64(35))
  218. publicSignals := []*big.Int{b35}
  219. // wittness
  220. w, err := circuit.CalculateWitness(privateInputs, publicSignals)
  221. assert.Nil(t, err)
  222. // flat code to R1CS
  223. fmt.Println("\ngenerating R1CS from flat code")
  224. a, b, c := circuit.GenerateR1CS()
  225. fmt.Println("\nR1CS:")
  226. fmt.Println("a:", a)
  227. fmt.Println("b:", b)
  228. fmt.Println("c:", c)
  229. // R1CS to QAP
  230. // TODO zxQAP is not used and is an old impl, TODO remove
  231. alphas, betas, gammas, _ := Utils.PF.R1CSToQAP(a, b, c)
  232. fmt.Println("qap")
  233. assert.Equal(t, 8, len(alphas))
  234. assert.Equal(t, 8, len(alphas))
  235. assert.Equal(t, 8, len(alphas))
  236. assert.True(t, !bytes.Equal(alphas[1][1].Bytes(), big.NewInt(int64(0)).Bytes()))
  237. ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
  238. assert.Equal(t, 7, len(ax))
  239. assert.Equal(t, 7, len(bx))
  240. assert.Equal(t, 7, len(cx))
  241. assert.Equal(t, 13, len(px))
  242. // calculate trusted setup
  243. setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas)
  244. assert.Nil(t, err)
  245. fmt.Println("\nt:", setup.Toxic.T)
  246. hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z)
  247. div, rem := Utils.PF.Div(px, setup.Pk.Z)
  248. assert.Equal(t, hx, div)
  249. assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(6))
  250. // hx==px/zx so px==hx*zx
  251. assert.Equal(t, px, Utils.PF.Mul(hx, setup.Pk.Z))
  252. // check length of polynomials H(x) and Z(x)
  253. assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1)
  254. proof, err := GenerateProofs(*circuit, setup, w, px)
  255. assert.Nil(t, err)
  256. // fmt.Println("\n proofs:")
  257. // fmt.Println(proof)
  258. // fmt.Println("public signals:", proof.PublicSignals)
  259. fmt.Println("\nsignals:", circuit.Signals)
  260. fmt.Println("witness:", w)
  261. b35Verif := big.NewInt(int64(35))
  262. publicSignalsVerif := []*big.Int{b35Verif}
  263. before := time.Now()
  264. assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true))
  265. fmt.Println("verify proof time elapsed:", time.Since(before))
  266. // check that with another public input the verification returns false
  267. bOtherWrongPublic := big.NewInt(int64(34))
  268. wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
  269. assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, true))
  270. }