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.

235 lines
4.4 KiB

  1. package bn128
  2. import (
  3. "math/big"
  4. "github.com/arnaucube/go-snark/fields"
  5. )
  6. // G2 is ...
  7. type G2 struct {
  8. F fields.Fq2
  9. G [3][2]*big.Int
  10. }
  11. // NewG2 is ...
  12. func NewG2(f fields.Fq2, g [2][2]*big.Int) G2 {
  13. var g2 G2
  14. g2.F = f
  15. g2.G = [3][2]*big.Int{
  16. g[0],
  17. g[1],
  18. g2.F.One(),
  19. }
  20. return g2
  21. }
  22. // Zero is ...
  23. func (g2 G2) Zero() [3][2]*big.Int {
  24. return [3][2]*big.Int{g2.F.Zero(), g2.F.One(), g2.F.Zero()}
  25. }
  26. // IsZero is ...
  27. func (g2 G2) IsZero(p [3][2]*big.Int) bool {
  28. return g2.F.IsZero(p[2])
  29. }
  30. // Add is ...
  31. func (g2 G2) Add(p1, p2 [3][2]*big.Int) [3][2]*big.Int {
  32. // https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
  33. // https://github.com/zcash/zcash/blob/master/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp#L208
  34. // http://hyperelliptic.org/EFD/g2p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
  35. if g2.IsZero(p1) {
  36. return p2
  37. }
  38. if g2.IsZero(p2) {
  39. return p1
  40. }
  41. x1 := p1[0]
  42. y1 := p1[1]
  43. z1 := p1[2]
  44. x2 := p2[0]
  45. y2 := p2[1]
  46. z2 := p2[2]
  47. z1z1 := g2.F.Square(z1)
  48. z2z2 := g2.F.Square(z2)
  49. u1 := g2.F.Mul(x1, z2z2)
  50. u2 := g2.F.Mul(x2, z1z1)
  51. t0 := g2.F.Mul(z2, z2z2)
  52. s1 := g2.F.Mul(y1, t0)
  53. t1 := g2.F.Mul(z1, z1z1)
  54. s2 := g2.F.Mul(y2, t1)
  55. h := g2.F.Sub(u2, u1)
  56. t2 := g2.F.Add(h, h)
  57. i := g2.F.Square(t2)
  58. j := g2.F.Mul(h, i)
  59. t3 := g2.F.Sub(s2, s1)
  60. r := g2.F.Add(t3, t3)
  61. v := g2.F.Mul(u1, i)
  62. t4 := g2.F.Square(r)
  63. t5 := g2.F.Add(v, v)
  64. t6 := g2.F.Sub(t4, j)
  65. x3 := g2.F.Sub(t6, t5)
  66. t7 := g2.F.Sub(v, x3)
  67. t8 := g2.F.Mul(s1, j)
  68. t9 := g2.F.Add(t8, t8)
  69. t10 := g2.F.Mul(r, t7)
  70. y3 := g2.F.Sub(t10, t9)
  71. t11 := g2.F.Add(z1, z2)
  72. t12 := g2.F.Square(t11)
  73. t13 := g2.F.Sub(t12, z1z1)
  74. t14 := g2.F.Sub(t13, z2z2)
  75. z3 := g2.F.Mul(t14, h)
  76. return [3][2]*big.Int{x3, y3, z3}
  77. }
  78. // Neg is ...
  79. func (g2 G2) Neg(p [3][2]*big.Int) [3][2]*big.Int {
  80. return [3][2]*big.Int{
  81. p[0],
  82. g2.F.Neg(p[1]),
  83. p[2],
  84. }
  85. }
  86. // Sub is ...
  87. func (g2 G2) Sub(a, b [3][2]*big.Int) [3][2]*big.Int {
  88. return g2.Add(a, g2.Neg(b))
  89. }
  90. // Double is ...
  91. func (g2 G2) Double(p [3][2]*big.Int) [3][2]*big.Int {
  92. // https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
  93. // http://hyperelliptic.org/EFD/g2p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
  94. // https://github.com/zcash/zcash/blob/master/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp#L325
  95. if g2.IsZero(p) {
  96. return p
  97. }
  98. a := g2.F.Square(p[0])
  99. b := g2.F.Square(p[1])
  100. c := g2.F.Square(b)
  101. t0 := g2.F.Add(p[0], b)
  102. t1 := g2.F.Square(t0)
  103. t2 := g2.F.Sub(t1, a)
  104. t3 := g2.F.Sub(t2, c)
  105. d := g2.F.Double(t3)
  106. e := g2.F.Add(g2.F.Add(a, a), a)
  107. f := g2.F.Square(e)
  108. t4 := g2.F.Double(d)
  109. x3 := g2.F.Sub(f, t4)
  110. t5 := g2.F.Sub(d, x3)
  111. twoC := g2.F.Add(c, c)
  112. fourC := g2.F.Add(twoC, twoC)
  113. t6 := g2.F.Add(fourC, fourC)
  114. t7 := g2.F.Mul(e, t5)
  115. y3 := g2.F.Sub(t7, t6)
  116. t8 := g2.F.Mul(p[1], p[2])
  117. z3 := g2.F.Double(t8)
  118. return [3][2]*big.Int{x3, y3, z3}
  119. }
  120. // MulScalar is ...
  121. func (g2 G2) MulScalar(p [3][2]*big.Int, e *big.Int) [3][2]*big.Int {
  122. // https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Double-and-add
  123. q := [3][2]*big.Int{g2.F.Zero(), g2.F.Zero(), g2.F.Zero()}
  124. d := g2.F.F.Copy(e) // d := e
  125. r := p
  126. /*
  127. here are three possible implementations:
  128. */
  129. /* index decreasing: */
  130. for i := d.BitLen() - 1; i >= 0; i-- {
  131. q = g2.Double(q)
  132. if d.Bit(i) == 1 {
  133. q = g2.Add(q, r)
  134. }
  135. }
  136. /* index increasing: */
  137. // for i := 0; i <= d.BitLen(); i++ {
  138. // if d.Bit(i) == 1 {
  139. // q = g2.Add(q, r)
  140. // }
  141. // r = g2.Double(r)
  142. // }
  143. // foundone := false
  144. // for i := d.BitLen(); i >= 0; i-- {
  145. // if foundone {
  146. // q = g2.Double(q)
  147. // }
  148. // if d.Bit(i) == 1 {
  149. // foundone = true
  150. // q = g2.Add(q, r)
  151. // }
  152. // }
  153. return q
  154. }
  155. // Affine is ...
  156. func (g2 G2) Affine(p [3][2]*big.Int) [3][2]*big.Int {
  157. if g2.IsZero(p) {
  158. return g2.Zero()
  159. }
  160. zinv := g2.F.Inverse(p[2])
  161. zinv2 := g2.F.Square(zinv)
  162. x := g2.F.Mul(p[0], zinv2)
  163. zinv3 := g2.F.Mul(zinv2, zinv)
  164. y := g2.F.Mul(p[1], zinv3)
  165. return [3][2]*big.Int{
  166. g2.F.Affine(x),
  167. g2.F.Affine(y),
  168. g2.F.One(),
  169. }
  170. }
  171. // Equal is ...
  172. func (g2 G2) Equal(p1, p2 [3][2]*big.Int) bool {
  173. if g2.IsZero(p1) {
  174. return g2.IsZero(p2)
  175. }
  176. if g2.IsZero(p2) {
  177. return g2.IsZero(p1)
  178. }
  179. z1z1 := g2.F.Square(p1[2])
  180. z2z2 := g2.F.Square(p2[2])
  181. u1 := g2.F.Mul(p1[0], z2z2)
  182. u2 := g2.F.Mul(p2[0], z1z1)
  183. z1cub := g2.F.Mul(p1[2], z1z1)
  184. z2cub := g2.F.Mul(p2[2], z2z2)
  185. s1 := g2.F.Mul(p1[1], z2cub)
  186. s2 := g2.F.Mul(p2[1], z1cub)
  187. return g2.F.Equal(u1, u2) && g2.F.Equal(s1, s2)
  188. }