plonk-simple.sage 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. F101 = Integers(101)
  2. E = EllipticCurve(F101, [0, 3])
  3. R.<X> = PolynomialRing(F101)
  4. # Extension field of points of 101, and solutions of x^2 + 2
  5. K.<X> = GF(101**2, modulus=X^2 + 2)
  6. # y^2 = x^3 + 3 in this curve defined over the extension field.
  7. # Needed for pairing.
  8. E2 = EllipticCurve(K, [0, 3])
  9. # Generator point because 1^3 + 3 = 4 which is sqrt of 2
  10. G = E([1, 2])
  11. G2 = E2([36, 31*X])
  12. assert G.order() == 17
  13. F17 = Integers(17)
  14. assert F17.square_roots_of_one() == (1, 16)
  15. # 16 == -1
  16. # so now we have the 4th roots of 1
  17. w = vector(F17, [1, 4, -1, -4])
  18. # omega = 4, omega^0 = 1, omega^1 = 4, omega^3 = -1 = 13, omega^3 = 13
  19. # so now we are still defining our reference string
  20. # we have 4 x labels for our permutation vector but we need 12
  21. # so we generate 2 cosets using quadratic non-residues in F
  22. # all 3 cosets should not share any value in common
  23. k1 = 2
  24. k2 = 3
  25. assert w == vector(F17, [1, 4, 16, 13])
  26. assert k1 * w == vector(F17, [2, 8, 15, 9])
  27. assert k2 * w == vector(F17, [3, 12, 14, 5])
  28. A = matrix(F17, [
  29. [1, 1, 1, 1],
  30. [4^0, 4^1, 4^2, 4^3],
  31. [16^0, 16^1, 16^2, 16^3],
  32. [13^0, 13^1, 13^2, 13^3]
  33. ])
  34. Ai = A.inverse()
  35. P.<x> = F17[]
  36. x = P.0
  37. # We only have 3 gates in this example for x^3 + x = 30
  38. # x x^2 x^3
  39. # x x x
  40. # x^2 x^3 0
  41. # public input: 30
  42. # we have 4 w values so the last column is empty (all set to 0 in this case)
  43. fa = P.lagrange_polynomial(zip([1, 4, 16, 13], [3, 9, 27, 0]))
  44. #fa = P(list(Ai * vector(F17, [3, 9, 27, 0])))
  45. assert fa(1) == 3
  46. assert fa(4) == 9
  47. assert fa(16) == 27
  48. assert fa(13) == 0
  49. fb = P(list(Ai * vector(F17, [3, 3, 3, 0])))
  50. assert fb(1) == 3
  51. assert fb(4) == 3
  52. assert fb(16) == 3
  53. assert fb(13) == 0
  54. fc = P(list(Ai * vector(F17, [9, 27, 0, 0])))
  55. assert fc(1) == 9
  56. assert fc(4) == 27
  57. assert fc(16) == 0
  58. assert fc(13) == 0
  59. # List of operations
  60. #
  61. # mul, mul, add/cons, null
  62. ql = P(list(Ai * vector(F17, [0, 0, 1, 0])))
  63. qr = P(list(Ai * vector(F17, [0, 0, 1, 0])))
  64. qm = P(list(Ai * vector(F17, [1, 1, 0, 0])))
  65. qo = P(list(Ai * vector(F17, [-1, -1, 0, 0])))
  66. qc = P(list(Ai * vector(F17, [0, 0, -30, 0])))
  67. # permutation/copy constraints
  68. # We are using the coset values here for a, b, c
  69. # 1 4 16 13
  70. # 2 8 15 9
  71. # 3 12 14 5
  72. # Applying the permutation for:
  73. # x x^2 x^3
  74. # x x x
  75. # x^2 x^3 0
  76. # then we get:
  77. # 2 3 12 13
  78. # 1 15 8 9
  79. # 4 16 14 5
  80. # We swap indices whenever there is an equality between wires:
  81. # a1 = b1
  82. # a2 = c1
  83. # ...
  84. sa = P(list(Ai * vector(F17, [2, 3, 12, 13])))
  85. sb = P(list(Ai * vector(F17, [1, 15, 8, 9])))
  86. sc = P(list(Ai * vector(F17, [4, 16, 14, 5])))
  87. # Setup phase complete
  88. # Prove phase
  89. # Round 1
  90. # Create vanishing polynomial which is zero for every root of unity.
  91. # That is Z(w_1) = Z(w_2) = ... = 0
  92. Z = x^4 - 1
  93. assert Z(1) == 0
  94. assert Z(4) == 0
  95. assert Z(16) == 0
  96. assert Z(13) == 0
  97. # 9 random blinding values. We will use:
  98. # 7, 4, 11, 12, 16, 2
  99. # 14, 11, 7 (used in round 2)
  100. # Blind our witness polynomials
  101. # The blinding factors will disappear at the evaluation points.
  102. a = (7*x + 4) * Z + fa
  103. b = (11*x + 12) * Z + fb
  104. c = (16*x + 2) * Z + fc
  105. # During the SRS phase we created a random s point and its powers
  106. s = 2
  107. # So now we evaluate a, b, c with these powers of G
  108. a_s = ZZ(a(s)) * G
  109. b_s = ZZ(b(s)) * G
  110. c_s = ZZ(c(s)) * G
  111. # Round 2
  112. # Random transcript challenges
  113. beta = 12
  114. gamma = 13
  115. # Build accumulation
  116. acc = 1
  117. accs = []
  118. for i in range(4):
  119. # w_{n + j} corresponds to b(w[i])
  120. # and w_{2n + j} is c(w[i])
  121. accs.append(acc)
  122. acc = acc * (
  123. (a(w[i]) + beta * w[i] + gamma)
  124. * (b(w[i]) + beta * k1 * w[i] + gamma)
  125. * (c(w[i]) + beta * k2 * w[i] + gamma) /
  126. (
  127. (a(w[i]) + beta * sa(w[i]) + gamma)
  128. * (b(w[i]) + beta * sb(w[i]) + gamma)
  129. * (c(w[i]) + beta * sc(w[i]) + gamma)
  130. ))
  131. assert accs == [1, 12, 10, 1]
  132. del accs
  133. acc = P(list(Ai * vector(F17, [1, 12, 10, 1])))
  134. Zx = (14*x^2 + 11*x + 7) * Z + acc
  135. # Evaluate z(x) at our secret point
  136. Z_s = ZZ(Zx(s)) * G
  137. # Round 3
  138. alpha = 15
  139. t1Z = a * b * qm + a * ql + b * qr + c * qo + qc
  140. t2Z = ((a + beta * x + gamma)
  141. * (b + beta * k1 * x + gamma)
  142. * (c + beta * k2 * x + gamma)) * Zx * alpha
  143. # w[1] is our first root of unity
  144. Zw = Zx(w[1] * x)
  145. t3Z = -((a + beta * sa + gamma)
  146. * (b + beta * sb + gamma)
  147. * (c + beta * sc + gamma)) * Zw * alpha
  148. # Lagrangian polynomial which evaluates to 1 at 1
  149. # L_1(w_1) = 1 and 0 on the other evaluation points
  150. L = P(list(Ai * vector(F17, [1, 0, 0, 0])))
  151. assert L(1) == 1
  152. # w_2 = 4
  153. assert L(4) == 0
  154. t4Z = (Zx - 1) * L * alpha^2
  155. tZ = t1Z + t2Z + t3Z + t4Z
  156. # and cancel out the factor Z now
  157. t = P(tZ / Z)
  158. # Split t into 3 parts
  159. # t(X) = t_lo(X) + X^n t_mid(X) + X^{2n} t_hi(X)
  160. t_list = t.list()
  161. t_lo = t_list[0:6]
  162. t_mid = t_list[6:12]
  163. t_hi = t_list[12:18]
  164. # and create the evaluations
  165. t_lo_s = ZZ(P(t_lo)(s)) * G
  166. t_mid_s = ZZ(P(t_mid)(s)) * G
  167. t_hi_s = ZZ(P(t_hi)(s)) * G
  168. # Round 4
  169. zeta = 5
  170. a_ = a(zeta)
  171. b_ = b(zeta)
  172. c_ = c(zeta)
  173. sa_ = sa(zeta)
  174. sb_ = sb(zeta)
  175. t_ = t(zeta)
  176. zw_ = Zx(zeta * w[1])
  177. l_ = L(zeta)
  178. assert a_ == 8
  179. assert b_ == 12
  180. assert c_ == 10
  181. assert sa_ == 0
  182. assert sb_ == 16
  183. assert t_ == 3
  184. assert zw_ == 14
  185. r1 = a_ * b_ * qm + a_ * ql + b_ * qr + c_ * qo + qc
  186. r2 = ((a_ + beta * zeta + gamma)
  187. * (b_ + beta * k1 * zeta + gamma)
  188. * (c_ + beta * k2 * zeta + gamma)) * Zx * alpha
  189. r3 = -((a_ + beta * sa_ + gamma)
  190. * (b_ + beta * sb_ + gamma)
  191. * beta * zw_ * sc * alpha)
  192. r4 = Zx * l_ * alpha^2
  193. r = r1 + r2 + r3 + r4
  194. r_ = r(zeta)
  195. assert r_ == 7
  196. # Round 5
  197. vega = 12
  198. v1 = P(t_lo)
  199. # Polynomial was in parts consisting of 6 powers
  200. v2 = zeta^6 * P(t_mid)
  201. v3 = zeta^12 * P(t_hi)
  202. v4 = -t_
  203. assert v4 == 14
  204. v5 = (
  205. vega * (r - r_)
  206. + vega^2 * (a - a_) + vega^3 * (b - b_) + vega^4 * (c - c_)
  207. + vega^5 * (sa - sa_) + vega^6 * (sb - sb_)
  208. )
  209. W = v1 + v2 + v3 + v4 + v5
  210. Wz = W / (x - zeta)
  211. # Calculate the opening proof
  212. Wzw = (Zx - zw_) / (x - zeta * w[1])
  213. # Compute evaluations of Wz and Wzw
  214. Wz_s = ZZ(Wz(s)) * G
  215. Wzw_s = ZZ(Wzw(s)) * G
  216. # Finished the proving algo
  217. proof = (a_s, b_s, c_s, Z_s, t_lo_s, t_mid_s, t_hi_s, Wz_s, Wzw_s,
  218. a_, b_, c_, sa_, sb_, r_, zw_)
  219. # Verification
  220. qm_s = ZZ(qm(s)) * G
  221. ql_s = ZZ(ql(s)) * G
  222. qr_s = ZZ(qr(s)) * G
  223. qo_s = ZZ(qo(s)) * G
  224. qc_s = ZZ(qc(s)) * G
  225. sa_s = ZZ(sa(s)) * G
  226. sb_s = ZZ(sb(s)) * G
  227. sc_s = ZZ(sc(s)) * G
  228. # Check all the points are on the curve.
  229. # y^2 = x^3 + 3
  230. # ...
  231. # Also check the scalar values are in the group for F17
  232. # ...
  233. # step 4: random upsilon
  234. upsilon = 4
  235. # step 5
  236. Z_z = F17(zeta^4 - 1)
  237. assert Z_z == 12
  238. # step 6
  239. # Calculate evaluation of L1 at zeta
  240. L1_z = F17((zeta^4 - 1) / (4 * (zeta - 1)))
  241. assert L1_z == 5
  242. # step 7
  243. # no public inputs in this example
  244. # step 8
  245. t_ = (r_ - (a_ + beta * sa_ + gamma)
  246. * (b_ + beta * sb_ + gamma)
  247. * (c_ + gamma) * zw_ * alpha
  248. - L1_z * alpha^2) / Z_z
  249. assert t_ == 3
  250. # step 9
  251. # qx_s are points, and we are multiplying them by scalars
  252. # so convert the values to integers first
  253. d1 = (ZZ(a_ * b_ * vega) * qm_s
  254. + ZZ(a_ * vega) * ql_s
  255. + ZZ(b_ * vega) * qr_s
  256. + ZZ(c_ * vega) * qo_s
  257. + vega * qc_s)
  258. d2 = ZZ((a_ + beta * zeta + gamma)
  259. * (b_ + beta * k1 * zeta + gamma)
  260. * (c_ + beta * k2 * zeta + gamma)
  261. * alpha * vega
  262. + L1_z * alpha^2 * vega
  263. + F17(upsilon)) * Z_s
  264. d3 = -ZZ((a_ + beta * sa_ + gamma)
  265. * (b_ + beta * sb_ + gamma)
  266. * alpha * vega * beta * zw_) * sc_s
  267. d = d1 + d2 + d3
  268. # step 10
  269. f = (t_lo_s + zeta^6 * t_mid_s + zeta^12 * t_hi_s
  270. + d
  271. + vega^2 * a_s + vega^3 * b_s + vega^4 * c_s
  272. + vega^5 * sa_s + vega^6 * sb_s)
  273. # step 11
  274. e = ZZ(t_ + vega * r_
  275. + vega^2 * a_ + vega^3 * b_ + vega^4 * c_
  276. + vega^5 * sa_ + vega^6 * sb_
  277. + upsilon * zw_) * G
  278. # step 12
  279. # construct points for the pairing check
  280. x1 = Wz_s + upsilon * Wzw_s
  281. x2 = s * G2
  282. y1 = zeta * Wz_s + ZZ(upsilon * zeta * w[1]) * Wzw_s + f - e
  283. y2 = G2
  284. # do the pairing check
  285. x1_ = E2(x1)
  286. x2_ = E2(x2)
  287. y1_ = E2(y1)
  288. y2_ = E2(y2)
  289. assert x1_.weil_pairing(x2_, 17) == y1_.weil_pairing(y2_, 17)