plonk-simple.sage 7.8 KB

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