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.

207 lines
3.9 KiB

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