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.

161 lines
4.8 KiB

  1. import unittest, operator
  2. load("ipa.sage")
  3. # Halo paper: https://eprint.iacr.org/2019/1021.pdf
  4. # Bulletproofs paper: https://eprint.iacr.org/2017/1066.pdf
  5. # Ethereum elliptic curve
  6. p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
  7. a = 0
  8. b = 7
  9. Fp = GF(p)
  10. E = EllipticCurve(Fp, [a,b])
  11. GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
  12. GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
  13. g = E(GX,GY)
  14. n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
  15. h = 1
  16. q = g.order()
  17. Fq = GF(q)
  18. # simplier curve values
  19. # p = 19
  20. # Fp = GF(p)
  21. # E = EllipticCurve(Fp,[0,3])
  22. # g = E(1, 2)
  23. # q = g.order()
  24. # Fq = GF(q)
  25. print(E)
  26. print(Fq)
  27. assert is_prime(p)
  28. assert is_prime(q)
  29. assert g * q == 0
  30. class TestUtils(unittest.TestCase):
  31. def test_vecs(self):
  32. a = [1, 2, 3, 4, 5]
  33. b = [1, 2, 3, 4, 5]
  34. c = vec_scalar_mul_field(a, 10)
  35. assert c == [10, 20, 30, 40, 50]
  36. c = inner_product_field(a, b)
  37. assert c == 55
  38. # check that <a, b> with b = (1, x, x^2, ..., x^{d-1}) is the same
  39. # than evaluating p(x) with coefficients a_i, at x
  40. a = [Fq(1), Fq(2), Fq(3), Fq(4), Fq(5), Fq(6), Fq(7), Fq(8)]
  41. z = Fq(3)
  42. b = powers_of(z, 8)
  43. c = inner_product_field(a, b)
  44. x = PolynomialRing(Fq, 'x').gen()
  45. px = 1 + 2*x + 3*x^2 + 4*x^3 + 5*x^4 + 6*x^5 + 7*x^6 + 8*x^7
  46. assert c == px(x=z)
  47. class TestIPA_bulletproofs(unittest.TestCase):
  48. def test_inner_product(self):
  49. d = 8
  50. ipa = IPA_bulletproofs(Fq, E, g, d)
  51. # prover
  52. # p(x) = 1 + 2x + 3x² + 4x³ + 5x⁴ + 6x⁵ + 7x⁶ + 8x⁷
  53. a = [ipa.F(1), ipa.F(2), ipa.F(3), ipa.F(4), ipa.F(5), ipa.F(6), ipa.F(7), ipa.F(8)]
  54. x = ipa.F(3)
  55. b = powers_of(x, ipa.d) # = b
  56. # prover
  57. P = ipa.commit(a, b)
  58. print("commit", P)
  59. v = ipa.evaluate(a, b)
  60. print("v", v)
  61. # verifier
  62. # r = int(ipa.F.random_element())
  63. # verifier generate random challenges {uᵢ} ∈ 𝕀 and U ∈ 𝔾
  64. U = ipa.E.random_element()
  65. k = int(math.log(d, 2))
  66. u = [None] * k
  67. for j in reversed(range(0, k)):
  68. u[j] = ipa.F.random_element()
  69. while (u[j] == 0): # prevent u[j] from being 0
  70. u[j] = ipa.F.random_element()
  71. P = P + int(inner_product_field(a, b)) * U
  72. # prover
  73. a_ipa, b_ipa, G_ipa, H_ipa, L, R = ipa.ipa(a, b, u, U)
  74. # verifier
  75. print("P", P)
  76. print("a_ipa", a_ipa)
  77. verif = ipa.verify(P, a_ipa, v, b, u, U, L, R, b_ipa, G_ipa, H_ipa)
  78. print("Verification:", verif)
  79. assert verif == True
  80. class TestIPA_halo(unittest.TestCase):
  81. def test_homomorphic_property(self):
  82. ipa = IPA_halo(Fq, E, g, 5)
  83. a = [1, 2, 3, 4, 5]
  84. b = [1, 2, 3, 4, 5]
  85. c = vec_add(a, b)
  86. assert c == [2,4,6,8,10]
  87. r = int(ipa.F.random_element())
  88. s = int(ipa.F.random_element())
  89. vc_a = ipa.commit(a, r)
  90. vc_b = ipa.commit(b, s)
  91. # com(a, r) + com(b, s) == com(a+b, r+s)
  92. expected_vc_c = ipa.commit(vec_add(a, b), r+s)
  93. vc_c = vc_a + vc_b
  94. assert vc_c == expected_vc_c
  95. def test_inner_product(self):
  96. d = 8
  97. ipa = IPA_halo(Fq, E, g, d)
  98. # prover
  99. # p(x) = 1 + 2x + 3x² + 4x³ + 5x⁴ + 6x⁵ + 7x⁶ + 8x⁷
  100. a = [ipa.F(1), ipa.F(2), ipa.F(3), ipa.F(4), ipa.F(5), ipa.F(6), ipa.F(7), ipa.F(8)]
  101. x = ipa.F(3)
  102. x_powers = powers_of(x, ipa.d) # = b
  103. # verifier
  104. r = int(ipa.F.random_element())
  105. # prover
  106. P = ipa.commit(a, r)
  107. print("commit", P)
  108. v = ipa.evaluate(a, x_powers)
  109. print("v", v)
  110. # verifier generate random challenges {uᵢ} ∈ 𝕀 and U ∈ 𝔾
  111. U = ipa.E.random_element()
  112. k = int(math.log(ipa.d, 2))
  113. u = [None] * k
  114. for j in reversed(range(0, k)):
  115. u[j] = ipa.F.random_element()
  116. while (u[j] == 0): # prevent u[j] from being 0
  117. u[j] = ipa.F.random_element()
  118. P = P + int(v) * U
  119. # prover
  120. a_ipa, b_ipa, G_ipa, lj, rj, L, R = ipa.ipa(a, x_powers, u, U)
  121. # verifier
  122. print("P", P)
  123. print("a_ipa", a_ipa)
  124. print("\n Verify:")
  125. verif = ipa.verify(P, a_ipa, v, x_powers, r, u, U, lj, rj, L, R)
  126. assert verif == True
  127. if __name__ == '__main__':
  128. unittest.main()