4.8-example-computation.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. # Algorithm:
  2. # if w { a * b } else { a + b }
  3. # Equation:
  4. # f(w, a, b) = w(ab) + (1 - w)(a + b) = v
  5. # w(ab) + a + b - w(ab) = v
  6. # w(ab - a - b) = v - a - b
  7. # Constraints:
  8. # 1: [1 a] [1 b] [1 m]
  9. # 2: [1 w] [1 m, -1 a, -1 b] = [1 v, -1 a, -1 b]
  10. # 3: [1 w] [1 w] [1 w]
  11. # f(1, 4, 2) = 8
  12. from bls_py import bls12381
  13. from bls_py import pairing
  14. from bls_py import ec
  15. from bls_py.fields import Fq, Fq2, Fq6, Fq12, bls12381_q as Q
  16. from finite_fields.modp import IntegersModP
  17. from finite_fields.polynomial import polynomialsOver
  18. import random
  19. n = bls12381.n
  20. g1 = ec.generator_Fq(bls12381)
  21. g2 = ec.generator_Fq2(bls12381)
  22. mod_field = IntegersModP(n)
  23. poly = polynomialsOver(mod_field).factory
  24. def lagrange(points):
  25. result = poly([0])
  26. for i, (x_i, y_i) in enumerate(points):
  27. p = poly([y_i])
  28. for j, (x_j, y_j) in enumerate(points):
  29. if i == j:
  30. continue
  31. p *= poly([-x_j, 1]) / (x_i - x_j)
  32. #print(poly)
  33. #print(poly(1), poly(2), poly(3))
  34. result += p
  35. return result
  36. left_variables = {
  37. "a": lagrange([
  38. (1, 1), (2, 0), (3, 0)
  39. ]),
  40. "w": lagrange([
  41. (1, 0), (2, 1), (3, 1)
  42. ])
  43. }
  44. right_variables = {
  45. "m": lagrange([
  46. (1, 0), (2, 1), (3, 0)
  47. ]),
  48. "a": lagrange([
  49. (1, 0), (2, -1), (3, 0)
  50. ]),
  51. "b": lagrange([
  52. (1, 1), (2, -1), (3, 0)
  53. ]),
  54. "w": lagrange([
  55. (1, 0), (2, 0), (3, 1)
  56. ]),
  57. }
  58. out_variables = {
  59. "m": lagrange([
  60. (1, 1), (2, 0), (3, 0)
  61. ]),
  62. "v": lagrange([
  63. (1, 0), (2, 1), (3, 0)
  64. ]),
  65. "a": lagrange([
  66. (1, 0), (2, -1), (3, 0)
  67. ]),
  68. "b": lagrange([
  69. (1, 0), (2, -1), (3, 0)
  70. ]),
  71. "w": lagrange([
  72. (1, 0), (2, 0), (3, 1)
  73. ]),
  74. }
  75. private_inputs = {
  76. "w": 1,
  77. "a": 3,
  78. "b": 2
  79. }
  80. private_inputs["m"] = private_inputs["a"] * private_inputs["b"]
  81. private_inputs["v"] = \
  82. private_inputs["w"] * (
  83. private_inputs["m"] - private_inputs["a"] - private_inputs["b"]) \
  84. + private_inputs["a"] + private_inputs["b"]
  85. assert private_inputs["v"] == 6
  86. left_variable_poly = (
  87. private_inputs["a"] * left_variables["a"]
  88. + private_inputs["w"] * left_variables["w"]
  89. )
  90. right_variable_poly = (
  91. private_inputs["m"] * right_variables["m"]
  92. + private_inputs["a"] * right_variables["a"]
  93. + private_inputs["b"] * right_variables["b"]
  94. + private_inputs["w"] * right_variables["w"]
  95. )
  96. out_variable_poly = (
  97. private_inputs["m"] * out_variables["m"]
  98. + private_inputs["v"] * out_variables["v"]
  99. + private_inputs["a"] * out_variables["a"]
  100. + private_inputs["b"] * out_variables["b"]
  101. + private_inputs["w"] * out_variables["w"]
  102. )
  103. # (x - 1)(x - 2)(x - 3)
  104. target_poly = poly([-1, 1]) * poly([-2, 1]) * poly([-3, 1])
  105. def poly_call(poly, x):
  106. result = mod_field(0)
  107. for degree, coeff in enumerate(poly):
  108. result += coeff * (x**degree)
  109. return result.n
  110. assert poly_call(target_poly, 1) == 0
  111. assert poly_call(target_poly, 2) == 0
  112. assert poly_call(target_poly, 3) == 0
  113. main_poly = left_variable_poly * right_variable_poly - out_variable_poly
  114. cofactor_poly = main_poly / target_poly
  115. assert (
  116. left_variable_poly * right_variable_poly == \
  117. cofactor_poly * target_poly + out_variable_poly
  118. )