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.

223 lines
4.2 KiB

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