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.

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