pairing.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. // Copyright 2020 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package bls12381
  17. type pair struct {
  18. g1 *PointG1
  19. g2 *PointG2
  20. }
  21. func newPair(g1 *PointG1, g2 *PointG2) pair {
  22. return pair{g1, g2}
  23. }
  24. // Engine is BLS12-381 elliptic curve pairing engine
  25. type Engine struct {
  26. G1 *G1
  27. G2 *G2
  28. fp12 *fp12
  29. fp2 *fp2
  30. pairingEngineTemp
  31. pairs []pair
  32. }
  33. // NewPairingEngine creates new pairing engine instance.
  34. func NewPairingEngine() *Engine {
  35. fp2 := newFp2()
  36. fp6 := newFp6(fp2)
  37. fp12 := newFp12(fp6)
  38. g1 := NewG1()
  39. g2 := newG2(fp2)
  40. return &Engine{
  41. fp2: fp2,
  42. fp12: fp12,
  43. G1: g1,
  44. G2: g2,
  45. pairingEngineTemp: newEngineTemp(),
  46. }
  47. }
  48. type pairingEngineTemp struct {
  49. t2 [10]*fe2
  50. t12 [9]fe12
  51. }
  52. func newEngineTemp() pairingEngineTemp {
  53. t2 := [10]*fe2{}
  54. for i := 0; i < 10; i++ {
  55. t2[i] = &fe2{}
  56. }
  57. t12 := [9]fe12{}
  58. return pairingEngineTemp{t2, t12}
  59. }
  60. // AddPair adds a g1, g2 point pair to pairing engine
  61. func (e *Engine) AddPair(g1 *PointG1, g2 *PointG2) *Engine {
  62. p := newPair(g1, g2)
  63. if !e.isZero(p) {
  64. e.affine(p)
  65. e.pairs = append(e.pairs, p)
  66. }
  67. return e
  68. }
  69. // AddPairInv adds a G1, G2 point pair to pairing engine. G1 point is negated.
  70. func (e *Engine) AddPairInv(g1 *PointG1, g2 *PointG2) *Engine {
  71. e.G1.Neg(g1, g1)
  72. e.AddPair(g1, g2)
  73. return e
  74. }
  75. // Reset deletes added pairs.
  76. func (e *Engine) Reset() *Engine {
  77. e.pairs = []pair{}
  78. return e
  79. }
  80. func (e *Engine) isZero(p pair) bool {
  81. return e.G1.IsZero(p.g1) || e.G2.IsZero(p.g2)
  82. }
  83. func (e *Engine) affine(p pair) {
  84. e.G1.Affine(p.g1)
  85. e.G2.Affine(p.g2)
  86. }
  87. func (e *Engine) doublingStep(coeff *[3]fe2, r *PointG2) {
  88. // Adaptation of Formula 3 in https://eprint.iacr.org/2010/526.pdf
  89. fp2 := e.fp2
  90. t := e.t2
  91. fp2.mul(t[0], &r[0], &r[1])
  92. fp2.mulByFq(t[0], t[0], twoInv)
  93. fp2.square(t[1], &r[1])
  94. fp2.square(t[2], &r[2])
  95. fp2.double(t[7], t[2])
  96. fp2.add(t[7], t[7], t[2])
  97. fp2.mulByB(t[3], t[7])
  98. fp2.double(t[4], t[3])
  99. fp2.add(t[4], t[4], t[3])
  100. fp2.add(t[5], t[1], t[4])
  101. fp2.mulByFq(t[5], t[5], twoInv)
  102. fp2.add(t[6], &r[1], &r[2])
  103. fp2.square(t[6], t[6])
  104. fp2.add(t[7], t[2], t[1])
  105. fp2.sub(t[6], t[6], t[7])
  106. fp2.sub(&coeff[0], t[3], t[1])
  107. fp2.square(t[7], &r[0])
  108. fp2.sub(t[4], t[1], t[4])
  109. fp2.mul(&r[0], t[4], t[0])
  110. fp2.square(t[2], t[3])
  111. fp2.double(t[3], t[2])
  112. fp2.add(t[3], t[3], t[2])
  113. fp2.square(t[5], t[5])
  114. fp2.sub(&r[1], t[5], t[3])
  115. fp2.mul(&r[2], t[1], t[6])
  116. fp2.double(t[0], t[7])
  117. fp2.add(&coeff[1], t[0], t[7])
  118. fp2.neg(&coeff[2], t[6])
  119. }
  120. func (e *Engine) additionStep(coeff *[3]fe2, r, q *PointG2) {
  121. // Algorithm 12 in https://eprint.iacr.org/2010/526.pdf
  122. fp2 := e.fp2
  123. t := e.t2
  124. fp2.mul(t[0], &q[1], &r[2])
  125. fp2.neg(t[0], t[0])
  126. fp2.add(t[0], t[0], &r[1])
  127. fp2.mul(t[1], &q[0], &r[2])
  128. fp2.neg(t[1], t[1])
  129. fp2.add(t[1], t[1], &r[0])
  130. fp2.square(t[2], t[0])
  131. fp2.square(t[3], t[1])
  132. fp2.mul(t[4], t[1], t[3])
  133. fp2.mul(t[2], &r[2], t[2])
  134. fp2.mul(t[3], &r[0], t[3])
  135. fp2.double(t[5], t[3])
  136. fp2.sub(t[5], t[4], t[5])
  137. fp2.add(t[5], t[5], t[2])
  138. fp2.mul(&r[0], t[1], t[5])
  139. fp2.sub(t[2], t[3], t[5])
  140. fp2.mul(t[2], t[2], t[0])
  141. fp2.mul(t[3], &r[1], t[4])
  142. fp2.sub(&r[1], t[2], t[3])
  143. fp2.mul(&r[2], &r[2], t[4])
  144. fp2.mul(t[2], t[1], &q[1])
  145. fp2.mul(t[3], t[0], &q[0])
  146. fp2.sub(&coeff[0], t[3], t[2])
  147. fp2.neg(&coeff[1], t[0])
  148. coeff[2].set(t[1])
  149. }
  150. func (e *Engine) preCompute(ellCoeffs *[68][3]fe2, twistPoint *PointG2) {
  151. // Algorithm 5 in https://eprint.iacr.org/2019/077.pdf
  152. if e.G2.IsZero(twistPoint) {
  153. return
  154. }
  155. r := new(PointG2).Set(twistPoint)
  156. j := 0
  157. for i := x.BitLen() - 2; i >= 0; i-- {
  158. e.doublingStep(&ellCoeffs[j], r)
  159. if x.Bit(i) != 0 {
  160. j++
  161. ellCoeffs[j] = fe6{}
  162. e.additionStep(&ellCoeffs[j], r, twistPoint)
  163. }
  164. j++
  165. }
  166. }
  167. func (e *Engine) millerLoop(f *fe12) {
  168. pairs := e.pairs
  169. ellCoeffs := make([][68][3]fe2, len(pairs))
  170. for i := 0; i < len(pairs); i++ {
  171. e.preCompute(&ellCoeffs[i], pairs[i].g2)
  172. }
  173. fp12, fp2 := e.fp12, e.fp2
  174. t := e.t2
  175. f.one()
  176. j := 0
  177. for i := 62; /* x.BitLen() - 2 */ i >= 0; i-- {
  178. if i != 62 {
  179. fp12.square(f, f)
  180. }
  181. for i := 0; i <= len(pairs)-1; i++ {
  182. fp2.mulByFq(t[0], &ellCoeffs[i][j][2], &pairs[i].g1[1])
  183. fp2.mulByFq(t[1], &ellCoeffs[i][j][1], &pairs[i].g1[0])
  184. fp12.mulBy014Assign(f, &ellCoeffs[i][j][0], t[1], t[0])
  185. }
  186. if x.Bit(i) != 0 {
  187. j++
  188. for i := 0; i <= len(pairs)-1; i++ {
  189. fp2.mulByFq(t[0], &ellCoeffs[i][j][2], &pairs[i].g1[1])
  190. fp2.mulByFq(t[1], &ellCoeffs[i][j][1], &pairs[i].g1[0])
  191. fp12.mulBy014Assign(f, &ellCoeffs[i][j][0], t[1], t[0])
  192. }
  193. }
  194. j++
  195. }
  196. fp12.conjugate(f, f)
  197. }
  198. func (e *Engine) exp(c, a *fe12) {
  199. fp12 := e.fp12
  200. fp12.cyclotomicExp(c, a, x)
  201. fp12.conjugate(c, c)
  202. }
  203. func (e *Engine) finalExp(f *fe12) {
  204. fp12 := e.fp12
  205. t := e.t12
  206. // easy part
  207. fp12.frobeniusMap(&t[0], f, 6)
  208. fp12.inverse(&t[1], f)
  209. fp12.mul(&t[2], &t[0], &t[1])
  210. t[1].set(&t[2])
  211. fp12.frobeniusMapAssign(&t[2], 2)
  212. fp12.mulAssign(&t[2], &t[1])
  213. fp12.cyclotomicSquare(&t[1], &t[2])
  214. fp12.conjugate(&t[1], &t[1])
  215. // hard part
  216. e.exp(&t[3], &t[2])
  217. fp12.cyclotomicSquare(&t[4], &t[3])
  218. fp12.mul(&t[5], &t[1], &t[3])
  219. e.exp(&t[1], &t[5])
  220. e.exp(&t[0], &t[1])
  221. e.exp(&t[6], &t[0])
  222. fp12.mulAssign(&t[6], &t[4])
  223. e.exp(&t[4], &t[6])
  224. fp12.conjugate(&t[5], &t[5])
  225. fp12.mulAssign(&t[4], &t[5])
  226. fp12.mulAssign(&t[4], &t[2])
  227. fp12.conjugate(&t[5], &t[2])
  228. fp12.mulAssign(&t[1], &t[2])
  229. fp12.frobeniusMapAssign(&t[1], 3)
  230. fp12.mulAssign(&t[6], &t[5])
  231. fp12.frobeniusMapAssign(&t[6], 1)
  232. fp12.mulAssign(&t[3], &t[0])
  233. fp12.frobeniusMapAssign(&t[3], 2)
  234. fp12.mulAssign(&t[3], &t[1])
  235. fp12.mulAssign(&t[3], &t[6])
  236. fp12.mul(f, &t[3], &t[4])
  237. }
  238. func (e *Engine) calculate() *fe12 {
  239. f := e.fp12.one()
  240. if len(e.pairs) == 0 {
  241. return f
  242. }
  243. e.millerLoop(f)
  244. e.finalExp(f)
  245. return f
  246. }
  247. // Check computes pairing and checks if result is equal to one
  248. func (e *Engine) Check() bool {
  249. return e.calculate().isOne()
  250. }
  251. // Result computes pairing and returns target group element as result.
  252. func (e *Engine) Result() *E {
  253. r := e.calculate()
  254. e.Reset()
  255. return r
  256. }
  257. // GT returns target group instance.
  258. func (e *Engine) GT() *GT {
  259. return NewGT()
  260. }