github.com/consensys/gnark-crypto@v0.14.0/ecc/bls24-315/g2.go (about)

     1  // Copyright 2020 Consensys Software Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Code generated by consensys/gnark-crypto DO NOT EDIT
    16  
    17  package bls24315
    18  
    19  import (
    20  	"crypto/rand"
    21  	"github.com/consensys/gnark-crypto/ecc"
    22  	"github.com/consensys/gnark-crypto/ecc/bls24-315/fr"
    23  	"github.com/consensys/gnark-crypto/ecc/bls24-315/internal/fptower"
    24  	"github.com/consensys/gnark-crypto/internal/parallel"
    25  	"math/big"
    26  	"runtime"
    27  )
    28  
    29  // G2Affine is a point in affine coordinates (x,y)
    30  type G2Affine struct {
    31  	X, Y fptower.E4
    32  }
    33  
    34  // G2Jac is a point in Jacobian coordinates (x=X/Z², y=Y/Z³)
    35  type G2Jac struct {
    36  	X, Y, Z fptower.E4
    37  }
    38  
    39  // g2JacExtended is a point in extended Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²)
    40  type g2JacExtended struct {
    41  	X, Y, ZZ, ZZZ fptower.E4
    42  }
    43  
    44  // g2Proj point in projective coordinates
    45  type g2Proj struct {
    46  	x, y, z fptower.E4
    47  }
    48  
    49  // -------------------------------------------------------------------------------------------------
    50  // Affine coordinates
    51  
    52  // Set sets p to a in affine coordinates.
    53  func (p *G2Affine) Set(a *G2Affine) *G2Affine {
    54  	p.X, p.Y = a.X, a.Y
    55  	return p
    56  }
    57  
    58  // setInfinity sets p to the infinity point, which is encoded as (0,0).
    59  // N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B).
    60  func (p *G2Affine) setInfinity() *G2Affine {
    61  	p.X.SetZero()
    62  	p.Y.SetZero()
    63  	return p
    64  }
    65  
    66  // ScalarMultiplication computes and returns p = [s]a
    67  // where p and a are affine points.
    68  func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine {
    69  	var _p G2Jac
    70  	_p.FromAffine(a)
    71  	_p.mulGLV(&_p, s)
    72  	p.FromJacobian(&_p)
    73  	return p
    74  }
    75  
    76  // ScalarMultiplicationBase computes and returns p = [s]g
    77  // where g is the affine point generating the prime subgroup.
    78  func (p *G2Affine) ScalarMultiplicationBase(s *big.Int) *G2Affine {
    79  	var _p G2Jac
    80  	_p.mulGLV(&g2Gen, s)
    81  	p.FromJacobian(&_p)
    82  	return p
    83  }
    84  
    85  // Add adds two points in affine coordinates.
    86  // It uses the Jacobian addition with a.Z=b.Z=1 and converts the result to affine coordinates.
    87  //
    88  // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl
    89  func (p *G2Affine) Add(a, b *G2Affine) *G2Affine {
    90  	var q G2Jac
    91  	// a is infinity, return b
    92  	if a.IsInfinity() {
    93  		p.Set(b)
    94  		return p
    95  	}
    96  	// b is infinity, return a
    97  	if b.IsInfinity() {
    98  		p.Set(a)
    99  		return p
   100  	}
   101  	if a.X.Equal(&b.X) {
   102  		// if b == a, we double instead
   103  		if a.Y.Equal(&b.Y) {
   104  			q.DoubleMixed(a)
   105  			return p.FromJacobian(&q)
   106  		} else {
   107  			// if b == -a, we return 0
   108  			return p.setInfinity()
   109  		}
   110  	}
   111  	var H, HH, I, J, r, V fptower.E4
   112  	H.Sub(&b.X, &a.X)
   113  	HH.Square(&H)
   114  	I.Double(&HH).Double(&I)
   115  	J.Mul(&H, &I)
   116  	r.Sub(&b.Y, &a.Y)
   117  	r.Double(&r)
   118  	V.Mul(&a.X, &I)
   119  	q.X.Square(&r).
   120  		Sub(&q.X, &J).
   121  		Sub(&q.X, &V).
   122  		Sub(&q.X, &V)
   123  	q.Y.Sub(&V, &q.X).
   124  		Mul(&q.Y, &r)
   125  	J.Mul(&a.Y, &J).Double(&J)
   126  	q.Y.Sub(&q.Y, &J)
   127  	q.Z.Double(&H)
   128  
   129  	return p.FromJacobian(&q)
   130  }
   131  
   132  // Double doubles a point in affine coordinates.
   133  // It converts the point to Jacobian coordinates, doubles it using Jacobian
   134  // addition with a.Z=1, and converts it back to affine coordinates.
   135  //
   136  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl
   137  func (p *G2Affine) Double(a *G2Affine) *G2Affine {
   138  	var q G2Jac
   139  	q.FromAffine(a)
   140  	q.DoubleMixed(a)
   141  	p.FromJacobian(&q)
   142  	return p
   143  }
   144  
   145  // Sub subtracts two points in affine coordinates.
   146  // It uses a similar approach to Add, but negates the second point before adding.
   147  func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine {
   148  	var bneg G2Affine
   149  	bneg.Neg(b)
   150  	p.Add(a, &bneg)
   151  	return p
   152  }
   153  
   154  // Equal tests if two points in affine coordinates are equal.
   155  func (p *G2Affine) Equal(a *G2Affine) bool {
   156  	return p.X.Equal(&a.X) && p.Y.Equal(&a.Y)
   157  }
   158  
   159  // Neg sets p to the affine negative point -a = (a.X, -a.Y).
   160  func (p *G2Affine) Neg(a *G2Affine) *G2Affine {
   161  	p.X = a.X
   162  	p.Y.Neg(&a.Y)
   163  	return p
   164  }
   165  
   166  // FromJacobian converts a point p1 from Jacobian to affine coordinates.
   167  func (p *G2Affine) FromJacobian(p1 *G2Jac) *G2Affine {
   168  
   169  	var a, b fptower.E4
   170  
   171  	if p1.Z.IsZero() {
   172  		p.X.SetZero()
   173  		p.Y.SetZero()
   174  		return p
   175  	}
   176  
   177  	a.Inverse(&p1.Z)
   178  	b.Square(&a)
   179  	p.X.Mul(&p1.X, &b)
   180  	p.Y.Mul(&p1.Y, &b).Mul(&p.Y, &a)
   181  
   182  	return p
   183  }
   184  
   185  // String returns the string representation E(x,y) of the affine point p or "O" if it is infinity.
   186  func (p *G2Affine) String() string {
   187  	if p.IsInfinity() {
   188  		return "O"
   189  	}
   190  	return "E([" + p.X.String() + "," + p.Y.String() + "])"
   191  }
   192  
   193  // IsInfinity checks if the affine point p is infinity, which is encoded as (0,0).
   194  // N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B).
   195  func (p *G2Affine) IsInfinity() bool {
   196  	return p.X.IsZero() && p.Y.IsZero()
   197  }
   198  
   199  // IsOnCurve returns true if the affine point p in on the curve.
   200  func (p *G2Affine) IsOnCurve() bool {
   201  	var point G2Jac
   202  	point.FromAffine(p)
   203  	return point.IsOnCurve() // call this function to handle infinity point
   204  }
   205  
   206  // IsInSubGroup returns true if the affine point p is in the correct subgroup, false otherwise.
   207  func (p *G2Affine) IsInSubGroup() bool {
   208  	var _p G2Jac
   209  	_p.FromAffine(p)
   210  	return _p.IsInSubGroup()
   211  }
   212  
   213  // -------------------------------------------------------------------------------------------------
   214  // Jacobian coordinates
   215  
   216  // Set sets p to a in Jacobian coordinates.
   217  func (p *G2Jac) Set(q *G2Jac) *G2Jac {
   218  	p.X, p.Y, p.Z = q.X, q.Y, q.Z
   219  	return p
   220  }
   221  
   222  // Equal tests if two points in Jacobian coordinates are equal.
   223  func (p *G2Jac) Equal(q *G2Jac) bool {
   224  	// If one point is infinity, the other must also be infinity.
   225  	if p.Z.IsZero() {
   226  		return q.Z.IsZero()
   227  	}
   228  	// If the other point is infinity, return false since we can't
   229  	// the following checks would be incorrect.
   230  	if q.Z.IsZero() {
   231  		return false
   232  	}
   233  
   234  	var pZSquare, aZSquare fptower.E4
   235  	pZSquare.Square(&p.Z)
   236  	aZSquare.Square(&q.Z)
   237  
   238  	var lhs, rhs fptower.E4
   239  	lhs.Mul(&p.X, &aZSquare)
   240  	rhs.Mul(&q.X, &pZSquare)
   241  	if !lhs.Equal(&rhs) {
   242  		return false
   243  	}
   244  	lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &q.Z)
   245  	rhs.Mul(&q.Y, &pZSquare).Mul(&rhs, &p.Z)
   246  
   247  	return lhs.Equal(&rhs)
   248  }
   249  
   250  // Neg sets p to the Jacobian negative point -q = (q.X, -q.Y, q.Z).
   251  func (p *G2Jac) Neg(q *G2Jac) *G2Jac {
   252  	*p = *q
   253  	p.Y.Neg(&q.Y)
   254  	return p
   255  }
   256  
   257  // AddAssign sets p to p+a in Jacobian coordinates.
   258  //
   259  // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
   260  func (p *G2Jac) AddAssign(q *G2Jac) *G2Jac {
   261  
   262  	// p is infinity, return q
   263  	if p.Z.IsZero() {
   264  		p.Set(q)
   265  		return p
   266  	}
   267  
   268  	// q is infinity, return p
   269  	if q.Z.IsZero() {
   270  		return p
   271  	}
   272  
   273  	var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fptower.E4
   274  	Z1Z1.Square(&q.Z)
   275  	Z2Z2.Square(&p.Z)
   276  	U1.Mul(&q.X, &Z2Z2)
   277  	U2.Mul(&p.X, &Z1Z1)
   278  	S1.Mul(&q.Y, &p.Z).
   279  		Mul(&S1, &Z2Z2)
   280  	S2.Mul(&p.Y, &q.Z).
   281  		Mul(&S2, &Z1Z1)
   282  
   283  	// if p == q, we double instead
   284  	if U1.Equal(&U2) && S1.Equal(&S2) {
   285  		return p.DoubleAssign()
   286  	}
   287  
   288  	H.Sub(&U2, &U1)
   289  	I.Double(&H).
   290  		Square(&I)
   291  	J.Mul(&H, &I)
   292  	r.Sub(&S2, &S1).Double(&r)
   293  	V.Mul(&U1, &I)
   294  	p.X.Square(&r).
   295  		Sub(&p.X, &J).
   296  		Sub(&p.X, &V).
   297  		Sub(&p.X, &V)
   298  	p.Y.Sub(&V, &p.X).
   299  		Mul(&p.Y, &r)
   300  	S1.Mul(&S1, &J).Double(&S1)
   301  	p.Y.Sub(&p.Y, &S1)
   302  	p.Z.Add(&p.Z, &q.Z)
   303  	p.Z.Square(&p.Z).
   304  		Sub(&p.Z, &Z1Z1).
   305  		Sub(&p.Z, &Z2Z2).
   306  		Mul(&p.Z, &H)
   307  
   308  	return p
   309  }
   310  
   311  // SubAssign sets p to p-a in Jacobian coordinates.
   312  // It uses a similar approach to AddAssign, but negates the point a before adding.
   313  func (p *G2Jac) SubAssign(q *G2Jac) *G2Jac {
   314  	var tmp G2Jac
   315  	tmp.Set(q)
   316  	tmp.Y.Neg(&tmp.Y)
   317  	p.AddAssign(&tmp)
   318  	return p
   319  }
   320  
   321  // Double sets p to [2]q in Jacobian coordinates.
   322  //
   323  // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl
   324  func (p *G2Jac) DoubleMixed(a *G2Affine) *G2Jac {
   325  	var XX, YY, YYYY, S, M, T fptower.E4
   326  	XX.Square(&a.X)
   327  	YY.Square(&a.Y)
   328  	YYYY.Square(&YY)
   329  	S.Add(&a.X, &YY).
   330  		Square(&S).
   331  		Sub(&S, &XX).
   332  		Sub(&S, &YYYY).
   333  		Double(&S)
   334  	M.Double(&XX).
   335  		Add(&M, &XX) // -> + A, but A=0 here
   336  	T.Square(&M).
   337  		Sub(&T, &S).
   338  		Sub(&T, &S)
   339  	p.X.Set(&T)
   340  	p.Y.Sub(&S, &T).
   341  		Mul(&p.Y, &M)
   342  	YYYY.Double(&YYYY).
   343  		Double(&YYYY).
   344  		Double(&YYYY)
   345  	p.Y.Sub(&p.Y, &YYYY)
   346  	p.Z.Double(&a.Y)
   347  
   348  	return p
   349  }
   350  
   351  // AddMixed sets p to p+a in Jacobian coordinates, where a.Z = 1.
   352  //
   353  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl
   354  func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac {
   355  
   356  	//if a is infinity return p
   357  	if a.IsInfinity() {
   358  		return p
   359  	}
   360  	// p is infinity, return a
   361  	if p.Z.IsZero() {
   362  		p.X = a.X
   363  		p.Y = a.Y
   364  		p.Z.SetOne()
   365  		return p
   366  	}
   367  
   368  	var Z1Z1, U2, S2, H, HH, I, J, r, V fptower.E4
   369  	Z1Z1.Square(&p.Z)
   370  	U2.Mul(&a.X, &Z1Z1)
   371  	S2.Mul(&a.Y, &p.Z).
   372  		Mul(&S2, &Z1Z1)
   373  
   374  	// if p == a, we double instead
   375  	if U2.Equal(&p.X) && S2.Equal(&p.Y) {
   376  		return p.DoubleMixed(a)
   377  	}
   378  
   379  	H.Sub(&U2, &p.X)
   380  	HH.Square(&H)
   381  	I.Double(&HH).Double(&I)
   382  	J.Mul(&H, &I)
   383  	r.Sub(&S2, &p.Y).Double(&r)
   384  	V.Mul(&p.X, &I)
   385  	p.X.Square(&r).
   386  		Sub(&p.X, &J).
   387  		Sub(&p.X, &V).
   388  		Sub(&p.X, &V)
   389  	J.Mul(&J, &p.Y).Double(&J)
   390  	p.Y.Sub(&V, &p.X).
   391  		Mul(&p.Y, &r)
   392  	p.Y.Sub(&p.Y, &J)
   393  	p.Z.Add(&p.Z, &H)
   394  	p.Z.Square(&p.Z).
   395  		Sub(&p.Z, &Z1Z1).
   396  		Sub(&p.Z, &HH)
   397  
   398  	return p
   399  }
   400  
   401  // Double sets p to [2]q in Jacobian coordinates.
   402  //
   403  // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl
   404  func (p *G2Jac) Double(q *G2Jac) *G2Jac {
   405  	p.Set(q)
   406  	p.DoubleAssign()
   407  	return p
   408  }
   409  
   410  // DoubleAssign doubles p in Jacobian coordinates.
   411  //
   412  // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl
   413  func (p *G2Jac) DoubleAssign() *G2Jac {
   414  
   415  	var XX, YY, YYYY, ZZ, S, M, T fptower.E4
   416  
   417  	XX.Square(&p.X)
   418  	YY.Square(&p.Y)
   419  	YYYY.Square(&YY)
   420  	ZZ.Square(&p.Z)
   421  	S.Add(&p.X, &YY)
   422  	S.Square(&S).
   423  		Sub(&S, &XX).
   424  		Sub(&S, &YYYY).
   425  		Double(&S)
   426  	M.Double(&XX).Add(&M, &XX)
   427  	p.Z.Add(&p.Z, &p.Y).
   428  		Square(&p.Z).
   429  		Sub(&p.Z, &YY).
   430  		Sub(&p.Z, &ZZ)
   431  	T.Square(&M)
   432  	p.X = T
   433  	T.Double(&S)
   434  	p.X.Sub(&p.X, &T)
   435  	p.Y.Sub(&S, &p.X).
   436  		Mul(&p.Y, &M)
   437  	YYYY.Double(&YYYY).Double(&YYYY).Double(&YYYY)
   438  	p.Y.Sub(&p.Y, &YYYY)
   439  
   440  	return p
   441  }
   442  
   443  // ScalarMultiplication computes and returns p = [s]a
   444  // where p and a are Jacobian points.
   445  // using the GLV technique.
   446  // see https://www.iacr.org/archive/crypto2001/21390189.pdf
   447  func (p *G2Jac) ScalarMultiplication(q *G2Jac, s *big.Int) *G2Jac {
   448  	return p.mulGLV(q, s)
   449  }
   450  
   451  // ScalarMultiplicationBase computes and returns p = [s]g
   452  // where g is the prime subgroup generator.
   453  func (p *G2Jac) ScalarMultiplicationBase(s *big.Int) *G2Jac {
   454  	return p.mulGLV(&g2Gen, s)
   455  
   456  }
   457  
   458  // String converts p to affine coordinates and returns its string representation E(x,y) or "O" if it is infinity.
   459  func (p *G2Jac) String() string {
   460  	_p := G2Affine{}
   461  	_p.FromJacobian(p)
   462  	return _p.String()
   463  }
   464  
   465  // FromAffine converts a point a from affine to Jacobian coordinates.
   466  func (p *G2Jac) FromAffine(a *G2Affine) *G2Jac {
   467  	if a.IsInfinity() {
   468  		p.Z.SetZero()
   469  		p.X.SetOne()
   470  		p.Y.SetOne()
   471  		return p
   472  	}
   473  	p.Z.SetOne()
   474  	p.X.Set(&a.X)
   475  	p.Y.Set(&a.Y)
   476  	return p
   477  }
   478  
   479  // IsOnCurve returns true if the Jacobian point p in on the curve.
   480  func (p *G2Jac) IsOnCurve() bool {
   481  	var left, right, tmp, ZZ fptower.E4
   482  	left.Square(&p.Y)
   483  	right.Square(&p.X).Mul(&right, &p.X)
   484  	ZZ.Square(&p.Z)
   485  	tmp.Square(&ZZ).Mul(&tmp, &ZZ)
   486  	tmp.MulBybTwistCurveCoeff(&tmp)
   487  	right.Add(&right, &tmp)
   488  	return left.Equal(&right)
   489  }
   490  
   491  // IsInSubGroup returns true if p is on the r-torsion, false otherwise.
   492  // https://eprint.iacr.org/2021/1130.pdf, sec.4
   493  // and https://eprint.iacr.org/2022/352.pdf, sec. 4.2
   494  // ψ(p) = [x₀]P
   495  func (p *G2Jac) IsInSubGroup() bool {
   496  	var res, tmp G2Jac
   497  	tmp.psi(p)
   498  	res.ScalarMultiplication(p, &xGen).
   499  		AddAssign(&tmp)
   500  
   501  	return res.IsOnCurve() && res.Z.IsZero()
   502  
   503  }
   504  
   505  // mulWindowed computes the 2-bits windowed double-and-add scalar
   506  // multiplication p=[s]q in Jacobian coordinates.
   507  func (p *G2Jac) mulWindowed(q *G2Jac, s *big.Int) *G2Jac {
   508  
   509  	var res G2Jac
   510  	var ops [3]G2Jac
   511  
   512  	ops[0].Set(q)
   513  	if s.Sign() == -1 {
   514  		ops[0].Neg(&ops[0])
   515  	}
   516  	res.Set(&g2Infinity)
   517  	ops[1].Double(&ops[0])
   518  	ops[2].Set(&ops[0]).AddAssign(&ops[1])
   519  
   520  	b := s.Bytes()
   521  	for i := range b {
   522  		w := b[i]
   523  		mask := byte(0xc0)
   524  		for j := 0; j < 4; j++ {
   525  			res.DoubleAssign().DoubleAssign()
   526  			c := (w & mask) >> (6 - 2*j)
   527  			if c != 0 {
   528  				res.AddAssign(&ops[c-1])
   529  			}
   530  			mask = mask >> 2
   531  		}
   532  	}
   533  	p.Set(&res)
   534  
   535  	return p
   536  
   537  }
   538  
   539  // psi sets p to ψ(q) = u o π o u⁻¹ where u:E'→E is the isomorphism from the twist to the curve E and π is the Frobenius map.
   540  func (p *G2Jac) psi(q *G2Jac) *G2Jac {
   541  	p.Set(q)
   542  	p.X.Frobenius(&p.X).Mul(&p.X, &endo.u)
   543  	p.Y.Frobenius(&p.Y).Mul(&p.Y, &endo.v)
   544  	p.Z.Frobenius(&p.Z)
   545  	return p
   546  }
   547  
   548  // phi sets p to ϕ(a) where ϕ: (x,y) → (w x,y),
   549  // where w is a third root of unity.
   550  func (p *G2Jac) phi(q *G2Jac) *G2Jac {
   551  	p.Set(q)
   552  	p.X.MulByElement(&p.X, &thirdRootOneG2)
   553  	return p
   554  }
   555  
   556  // mulGLV computes the scalar multiplication using a windowed-GLV method
   557  //
   558  // see https://www.iacr.org/archive/crypto2001/21390189.pdf
   559  func (p *G2Jac) mulGLV(q *G2Jac, s *big.Int) *G2Jac {
   560  
   561  	var table [15]G2Jac
   562  	var res G2Jac
   563  	var k1, k2 fr.Element
   564  
   565  	res.Set(&g2Infinity)
   566  
   567  	// table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0*q
   568  	table[0].Set(q)
   569  	table[3].phi(q)
   570  
   571  	// split the scalar, modifies ±q, ϕ(q) accordingly
   572  	k := ecc.SplitScalar(s, &glvBasis)
   573  
   574  	if k[0].Sign() == -1 {
   575  		k[0].Neg(&k[0])
   576  		table[0].Neg(&table[0])
   577  	}
   578  	if k[1].Sign() == -1 {
   579  		k[1].Neg(&k[1])
   580  		table[3].Neg(&table[3])
   581  	}
   582  
   583  	// precompute table (2 bits sliding window)
   584  	// table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0 ⋅ q if b3b2b1b0 != 0
   585  	table[1].Double(&table[0])
   586  	table[2].Set(&table[1]).AddAssign(&table[0])
   587  	table[4].Set(&table[3]).AddAssign(&table[0])
   588  	table[5].Set(&table[3]).AddAssign(&table[1])
   589  	table[6].Set(&table[3]).AddAssign(&table[2])
   590  	table[7].Double(&table[3])
   591  	table[8].Set(&table[7]).AddAssign(&table[0])
   592  	table[9].Set(&table[7]).AddAssign(&table[1])
   593  	table[10].Set(&table[7]).AddAssign(&table[2])
   594  	table[11].Set(&table[7]).AddAssign(&table[3])
   595  	table[12].Set(&table[11]).AddAssign(&table[0])
   596  	table[13].Set(&table[11]).AddAssign(&table[1])
   597  	table[14].Set(&table[11]).AddAssign(&table[2])
   598  
   599  	// bounds on the lattice base vectors guarantee that k1, k2 are len(r)/2 or len(r)/2+1 bits long max
   600  	// this is because we use a probabilistic scalar decomposition that replaces a division by a right-shift
   601  	k1 = k1.SetBigInt(&k[0]).Bits()
   602  	k2 = k2.SetBigInt(&k[1]).Bits()
   603  
   604  	// we don't target constant-timeness so we check first if we increase the bounds or not
   605  	maxBit := k1.BitLen()
   606  	if k2.BitLen() > maxBit {
   607  		maxBit = k2.BitLen()
   608  	}
   609  	hiWordIndex := (maxBit - 1) / 64
   610  
   611  	// loop starts from len(k1)/2 or len(k1)/2+1 due to the bounds
   612  	for i := hiWordIndex; i >= 0; i-- {
   613  		mask := uint64(3) << 62
   614  		for j := 0; j < 32; j++ {
   615  			res.Double(&res).Double(&res)
   616  			b1 := (k1[i] & mask) >> (62 - 2*j)
   617  			b2 := (k2[i] & mask) >> (62 - 2*j)
   618  			if b1|b2 != 0 {
   619  				s := (b2<<2 | b1)
   620  				res.AddAssign(&table[s-1])
   621  			}
   622  			mask = mask >> 2
   623  		}
   624  	}
   625  
   626  	p.Set(&res)
   627  	return p
   628  }
   629  
   630  // ClearCofactor maps a point in curve to r-torsion
   631  func (p *G2Affine) ClearCofactor(a *G2Affine) *G2Affine {
   632  	var _p G2Jac
   633  	_p.FromAffine(a)
   634  	_p.ClearCofactor(&_p)
   635  	p.FromJacobian(&_p)
   636  	return p
   637  }
   638  
   639  // ClearCofactor maps a point in curve to r-torsion
   640  func (p *G2Jac) ClearCofactor(q *G2Jac) *G2Jac {
   641  	// https://eprint.iacr.org/2017/419.pdf, section 4.2
   642  	// multiply by (3x⁴-3)*cofacor
   643  
   644  	var xg, xxg, xxxg, xxxxg, res, t G2Jac
   645  	xg.ScalarMultiplication(q, &xGen).Neg(&xg).SubAssign(q)
   646  	xxg.ScalarMultiplication(&xg, &xGen).Neg(&xxg)
   647  	xxxg.ScalarMultiplication(&xxg, &xGen).Neg(&xxxg)
   648  	xxxxg.ScalarMultiplication(&xxxg, &xGen).Neg(&xxxxg)
   649  
   650  	res.Set(&xxxxg).
   651  		SubAssign(q)
   652  
   653  	t.Set(&xxxg).
   654  		psi(&t).
   655  		AddAssign(&res)
   656  
   657  	res.Set(&xxg).
   658  		psi(&res).
   659  		psi(&res).
   660  		AddAssign(&t)
   661  
   662  	t.Set(&xg).
   663  		psi(&t).
   664  		psi(&t).
   665  		psi(&t).
   666  		AddAssign(&res)
   667  
   668  	res.Double(q).
   669  		psi(&res).
   670  		psi(&res).
   671  		psi(&res).
   672  		psi(&res).
   673  		AddAssign(&t)
   674  
   675  	p.Set(&res)
   676  
   677  	return p
   678  
   679  }
   680  
   681  // -------------------------------------------------------------------------------------------------
   682  // extended Jacobian coordinates
   683  
   684  // Set sets p to a in extended Jacobian coordinates.
   685  func (p *g2JacExtended) Set(q *g2JacExtended) *g2JacExtended {
   686  	p.X, p.Y, p.ZZ, p.ZZZ = q.X, q.Y, q.ZZ, q.ZZZ
   687  	return p
   688  }
   689  
   690  // setInfinity sets p to the infinity point (1,1,0,0).
   691  func (p *g2JacExtended) setInfinity() *g2JacExtended {
   692  	p.X.SetOne()
   693  	p.Y.SetOne()
   694  	p.ZZ = fptower.E4{}
   695  	p.ZZZ = fptower.E4{}
   696  	return p
   697  }
   698  
   699  // IsInfinity checks if the p is infinity, i.e. p.ZZ=0.
   700  func (p *g2JacExtended) IsInfinity() bool {
   701  	return p.ZZ.IsZero()
   702  }
   703  
   704  // fromJacExtended converts an extended Jacobian point to an affine point.
   705  func (p *G2Affine) fromJacExtended(q *g2JacExtended) *G2Affine {
   706  	if q.ZZ.IsZero() {
   707  		p.X = fptower.E4{}
   708  		p.Y = fptower.E4{}
   709  		return p
   710  	}
   711  	p.X.Inverse(&q.ZZ).Mul(&p.X, &q.X)
   712  	p.Y.Inverse(&q.ZZZ).Mul(&p.Y, &q.Y)
   713  	return p
   714  }
   715  
   716  // fromJacExtended converts an extended Jacobian point to a Jacobian point.
   717  func (p *G2Jac) fromJacExtended(q *g2JacExtended) *G2Jac {
   718  	if q.ZZ.IsZero() {
   719  		p.Set(&g2Infinity)
   720  		return p
   721  	}
   722  	p.X.Mul(&q.ZZ, &q.X).Mul(&p.X, &q.ZZ)
   723  	p.Y.Mul(&q.ZZZ, &q.Y).Mul(&p.Y, &q.ZZZ)
   724  	p.Z.Set(&q.ZZZ)
   725  	return p
   726  }
   727  
   728  // unsafeFromJacExtended converts an extended Jacobian point, distinct from Infinity, to a Jacobian point.
   729  func (p *G2Jac) unsafeFromJacExtended(q *g2JacExtended) *G2Jac {
   730  	p.X.Square(&q.ZZ).Mul(&p.X, &q.X)
   731  	p.Y.Square(&q.ZZZ).Mul(&p.Y, &q.Y)
   732  	p.Z = q.ZZZ
   733  	return p
   734  }
   735  
   736  // add sets p to p+q in extended Jacobian coordinates.
   737  //
   738  // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-add-2008-s
   739  func (p *g2JacExtended) add(q *g2JacExtended) *g2JacExtended {
   740  	//if q is infinity return p
   741  	if q.ZZ.IsZero() {
   742  		return p
   743  	}
   744  	// p is infinity, return q
   745  	if p.ZZ.IsZero() {
   746  		p.Set(q)
   747  		return p
   748  	}
   749  
   750  	var A, B, U1, U2, S1, S2 fptower.E4
   751  
   752  	// p2: q, p1: p
   753  	U2.Mul(&q.X, &p.ZZ)
   754  	U1.Mul(&p.X, &q.ZZ)
   755  	A.Sub(&U2, &U1)
   756  	S2.Mul(&q.Y, &p.ZZZ)
   757  	S1.Mul(&p.Y, &q.ZZZ)
   758  	B.Sub(&S2, &S1)
   759  
   760  	if A.IsZero() {
   761  		if B.IsZero() {
   762  			return p.double(q)
   763  
   764  		}
   765  		p.ZZ = fptower.E4{}
   766  		p.ZZZ = fptower.E4{}
   767  		return p
   768  	}
   769  
   770  	var P, R, PP, PPP, Q, V fptower.E4
   771  	P.Sub(&U2, &U1)
   772  	R.Sub(&S2, &S1)
   773  	PP.Square(&P)
   774  	PPP.Mul(&P, &PP)
   775  	Q.Mul(&U1, &PP)
   776  	V.Mul(&S1, &PPP)
   777  
   778  	p.X.Square(&R).
   779  		Sub(&p.X, &PPP).
   780  		Sub(&p.X, &Q).
   781  		Sub(&p.X, &Q)
   782  	p.Y.Sub(&Q, &p.X).
   783  		Mul(&p.Y, &R).
   784  		Sub(&p.Y, &V)
   785  	p.ZZ.Mul(&p.ZZ, &q.ZZ).
   786  		Mul(&p.ZZ, &PP)
   787  	p.ZZZ.Mul(&p.ZZZ, &q.ZZZ).
   788  		Mul(&p.ZZZ, &PPP)
   789  
   790  	return p
   791  }
   792  
   793  // double sets p to [2]q in Jacobian extended coordinates.
   794  //
   795  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1
   796  // N.B.: since we consider any point on Z=0 as the point at infinity
   797  // this doubling formula works for infinity points as well.
   798  func (p *g2JacExtended) double(q *g2JacExtended) *g2JacExtended {
   799  	var U, V, W, S, XX, M fptower.E4
   800  
   801  	U.Double(&q.Y)
   802  	V.Square(&U)
   803  	W.Mul(&U, &V)
   804  	S.Mul(&q.X, &V)
   805  	XX.Square(&q.X)
   806  	M.Double(&XX).
   807  		Add(&M, &XX) // -> + A, but A=0 here
   808  	U.Mul(&W, &q.Y)
   809  
   810  	p.X.Square(&M).
   811  		Sub(&p.X, &S).
   812  		Sub(&p.X, &S)
   813  	p.Y.Sub(&S, &p.X).
   814  		Mul(&p.Y, &M).
   815  		Sub(&p.Y, &U)
   816  	p.ZZ.Mul(&V, &q.ZZ)
   817  	p.ZZZ.Mul(&W, &q.ZZZ)
   818  
   819  	return p
   820  }
   821  
   822  // addMixed sets p to p+q in extended Jacobian coordinates, where a.ZZ=1.
   823  //
   824  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s
   825  func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended {
   826  
   827  	//if a is infinity return p
   828  	if a.IsInfinity() {
   829  		return p
   830  	}
   831  	// p is infinity, return a
   832  	if p.ZZ.IsZero() {
   833  		p.X = a.X
   834  		p.Y = a.Y
   835  		p.ZZ.SetOne()
   836  		p.ZZZ.SetOne()
   837  		return p
   838  	}
   839  
   840  	var P, R fptower.E4
   841  
   842  	// p2: a, p1: p
   843  	P.Mul(&a.X, &p.ZZ)
   844  	P.Sub(&P, &p.X)
   845  
   846  	R.Mul(&a.Y, &p.ZZZ)
   847  	R.Sub(&R, &p.Y)
   848  
   849  	if P.IsZero() {
   850  		if R.IsZero() {
   851  			return p.doubleMixed(a)
   852  
   853  		}
   854  		p.ZZ = fptower.E4{}
   855  		p.ZZZ = fptower.E4{}
   856  		return p
   857  	}
   858  
   859  	var PP, PPP, Q, Q2, RR, X3, Y3 fptower.E4
   860  
   861  	PP.Square(&P)
   862  	PPP.Mul(&P, &PP)
   863  	Q.Mul(&p.X, &PP)
   864  	RR.Square(&R)
   865  	X3.Sub(&RR, &PPP)
   866  	Q2.Double(&Q)
   867  	p.X.Sub(&X3, &Q2)
   868  	Y3.Sub(&Q, &p.X).Mul(&Y3, &R)
   869  	R.Mul(&p.Y, &PPP)
   870  	p.Y.Sub(&Y3, &R)
   871  	p.ZZ.Mul(&p.ZZ, &PP)
   872  	p.ZZZ.Mul(&p.ZZZ, &PPP)
   873  
   874  	return p
   875  
   876  }
   877  
   878  // subMixed works the same as addMixed, but negates a.Y.
   879  //
   880  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s
   881  func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended {
   882  
   883  	//if a is infinity return p
   884  	if a.IsInfinity() {
   885  		return p
   886  	}
   887  	// p is infinity, return a
   888  	if p.ZZ.IsZero() {
   889  		p.X = a.X
   890  		p.Y.Neg(&a.Y)
   891  		p.ZZ.SetOne()
   892  		p.ZZZ.SetOne()
   893  		return p
   894  	}
   895  
   896  	var P, R fptower.E4
   897  
   898  	// p2: a, p1: p
   899  	P.Mul(&a.X, &p.ZZ)
   900  	P.Sub(&P, &p.X)
   901  
   902  	R.Mul(&a.Y, &p.ZZZ)
   903  	R.Neg(&R)
   904  	R.Sub(&R, &p.Y)
   905  
   906  	if P.IsZero() {
   907  		if R.IsZero() {
   908  			return p.doubleNegMixed(a)
   909  
   910  		}
   911  		p.ZZ = fptower.E4{}
   912  		p.ZZZ = fptower.E4{}
   913  		return p
   914  	}
   915  
   916  	var PP, PPP, Q, Q2, RR, X3, Y3 fptower.E4
   917  
   918  	PP.Square(&P)
   919  	PPP.Mul(&P, &PP)
   920  	Q.Mul(&p.X, &PP)
   921  	RR.Square(&R)
   922  	X3.Sub(&RR, &PPP)
   923  	Q2.Double(&Q)
   924  	p.X.Sub(&X3, &Q2)
   925  	Y3.Sub(&Q, &p.X).Mul(&Y3, &R)
   926  	R.Mul(&p.Y, &PPP)
   927  	p.Y.Sub(&Y3, &R)
   928  	p.ZZ.Mul(&p.ZZ, &PP)
   929  	p.ZZZ.Mul(&p.ZZZ, &PPP)
   930  
   931  	return p
   932  
   933  }
   934  
   935  // doubleNegMixed works the same as double, but negates q.Y.
   936  func (p *g2JacExtended) doubleNegMixed(a *G2Affine) *g2JacExtended {
   937  
   938  	var U, V, W, S, XX, M, S2, L fptower.E4
   939  
   940  	U.Double(&a.Y)
   941  	U.Neg(&U)
   942  	V.Square(&U)
   943  	W.Mul(&U, &V)
   944  	S.Mul(&a.X, &V)
   945  	XX.Square(&a.X)
   946  	M.Double(&XX).
   947  		Add(&M, &XX) // -> + A, but A=0 here
   948  	S2.Double(&S)
   949  	L.Mul(&W, &a.Y)
   950  
   951  	p.X.Square(&M).
   952  		Sub(&p.X, &S2)
   953  	p.Y.Sub(&S, &p.X).
   954  		Mul(&p.Y, &M).
   955  		Add(&p.Y, &L)
   956  	p.ZZ.Set(&V)
   957  	p.ZZZ.Set(&W)
   958  
   959  	return p
   960  }
   961  
   962  // doubleMixed sets p to [2]a in Jacobian extended coordinates, where a.ZZ=1.
   963  //
   964  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1
   965  func (p *g2JacExtended) doubleMixed(a *G2Affine) *g2JacExtended {
   966  
   967  	var U, V, W, S, XX, M, S2, L fptower.E4
   968  
   969  	U.Double(&a.Y)
   970  	V.Square(&U)
   971  	W.Mul(&U, &V)
   972  	S.Mul(&a.X, &V)
   973  	XX.Square(&a.X)
   974  	M.Double(&XX).
   975  		Add(&M, &XX) // -> + A, but A=0 here
   976  	S2.Double(&S)
   977  	L.Mul(&W, &a.Y)
   978  
   979  	p.X.Square(&M).
   980  		Sub(&p.X, &S2)
   981  	p.Y.Sub(&S, &p.X).
   982  		Mul(&p.Y, &M).
   983  		Sub(&p.Y, &L)
   984  	p.ZZ.Set(&V)
   985  	p.ZZZ.Set(&W)
   986  
   987  	return p
   988  }
   989  
   990  // -------------------------------------------------------------------------------------------------
   991  // Homogenous projective coordinates
   992  
   993  // Set sets p to a in projective coordinates.
   994  func (p *g2Proj) Set(q *g2Proj) *g2Proj {
   995  	p.x, p.y, p.z = q.x, q.y, q.z
   996  	return p
   997  }
   998  
   999  // Neg sets p to the projective negative point -q = (q.X, -q.Y).
  1000  func (p *g2Proj) Neg(q *g2Proj) *g2Proj {
  1001  	*p = *q
  1002  	p.y.Neg(&q.y)
  1003  	return p
  1004  }
  1005  
  1006  // FromAffine converts q in affine to p in projective coordinates.
  1007  func (p *g2Proj) FromAffine(a *G2Affine) *g2Proj {
  1008  	if a.X.IsZero() && a.Y.IsZero() {
  1009  		p.z.SetZero()
  1010  		p.x.SetOne()
  1011  		p.y.SetOne()
  1012  		return p
  1013  	}
  1014  	p.z.SetOne()
  1015  	p.x.Set(&a.X)
  1016  	p.y.Set(&a.Y)
  1017  	return p
  1018  }
  1019  
  1020  // BatchScalarMultiplicationG2 multiplies the same base by all scalars
  1021  // and return resulting points in affine coordinates
  1022  // uses a simple windowed-NAF-like multiplication algorithm.
  1023  func BatchScalarMultiplicationG2(base *G2Affine, scalars []fr.Element) []G2Affine {
  1024  	// approximate cost in group ops is
  1025  	// cost = 2^{c-1} + n(scalar.nbBits+nbChunks)
  1026  
  1027  	nbPoints := uint64(len(scalars))
  1028  	min := ^uint64(0)
  1029  	bestC := 0
  1030  	for c := 2; c <= 16; c++ {
  1031  		cost := uint64(1 << (c - 1)) // pre compute the table
  1032  		nbChunks := computeNbChunks(uint64(c))
  1033  		cost += nbPoints * (uint64(c) + 1) * nbChunks // doublings + point add
  1034  		if cost < min {
  1035  			min = cost
  1036  			bestC = c
  1037  		}
  1038  	}
  1039  	c := uint64(bestC) // window size
  1040  	nbChunks := int(computeNbChunks(c))
  1041  
  1042  	// last window may be slightly larger than c; in which case we need to compute one
  1043  	// extra element in the baseTable
  1044  	maxC := lastC(c)
  1045  	if c > maxC {
  1046  		maxC = c
  1047  	}
  1048  
  1049  	// precompute all powers of base for our window
  1050  	// note here that if performance is critical, we can implement as in the msmX methods
  1051  	// this allocation to be on the stack
  1052  	baseTable := make([]G2Jac, (1 << (maxC - 1)))
  1053  	baseTable[0].FromAffine(base)
  1054  	for i := 1; i < len(baseTable); i++ {
  1055  		baseTable[i] = baseTable[i-1]
  1056  		baseTable[i].AddMixed(base)
  1057  	}
  1058  	toReturn := make([]G2Affine, len(scalars))
  1059  
  1060  	// partition the scalars into digits
  1061  	digits, _ := partitionScalars(scalars, c, runtime.NumCPU())
  1062  
  1063  	// for each digit, take value in the base table, double it c time, voilà.
  1064  	parallel.Execute(len(scalars), func(start, end int) {
  1065  		var p G2Jac
  1066  		for i := start; i < end; i++ {
  1067  			p.Set(&g2Infinity)
  1068  			for chunk := nbChunks - 1; chunk >= 0; chunk-- {
  1069  				if chunk != nbChunks-1 {
  1070  					for j := uint64(0); j < c; j++ {
  1071  						p.DoubleAssign()
  1072  					}
  1073  				}
  1074  				offset := chunk * len(scalars)
  1075  				digit := digits[i+offset]
  1076  
  1077  				if digit == 0 {
  1078  					continue
  1079  				}
  1080  
  1081  				// if msbWindow bit is set, we need to subtract
  1082  				if digit&1 == 0 {
  1083  					// add
  1084  					p.AddAssign(&baseTable[(digit>>1)-1])
  1085  				} else {
  1086  					// sub
  1087  					t := baseTable[digit>>1]
  1088  					t.Neg(&t)
  1089  					p.AddAssign(&t)
  1090  				}
  1091  			}
  1092  
  1093  			// set our result point
  1094  			toReturn[i].FromJacobian(&p)
  1095  
  1096  		}
  1097  	})
  1098  	return toReturn
  1099  }
  1100  
  1101  // batchAddG2Affine adds affine points using the Montgomery batch inversion trick.
  1102  // Special cases (doubling, infinity) must be filtered out before this call.
  1103  func batchAddG2Affine[TP pG2Affine, TPP ppG2Affine, TC cG2Affine](R *TPP, P *TP, batchSize int) {
  1104  	var lambda, lambdain TC
  1105  
  1106  	// add part
  1107  	for j := 0; j < batchSize; j++ {
  1108  		lambdain[j].Sub(&(*P)[j].X, &(*R)[j].X)
  1109  	}
  1110  
  1111  	// invert denominator using montgomery batch invert technique
  1112  	{
  1113  		var accumulator fptower.E4
  1114  		lambda[0].SetOne()
  1115  		accumulator.Set(&lambdain[0])
  1116  
  1117  		for i := 1; i < batchSize; i++ {
  1118  			lambda[i] = accumulator
  1119  			accumulator.Mul(&accumulator, &lambdain[i])
  1120  		}
  1121  
  1122  		accumulator.Inverse(&accumulator)
  1123  
  1124  		for i := batchSize - 1; i > 0; i-- {
  1125  			lambda[i].Mul(&lambda[i], &accumulator)
  1126  			accumulator.Mul(&accumulator, &lambdain[i])
  1127  		}
  1128  		lambda[0].Set(&accumulator)
  1129  	}
  1130  
  1131  	var d fptower.E4
  1132  	var rr G2Affine
  1133  
  1134  	// add part
  1135  	for j := 0; j < batchSize; j++ {
  1136  		// computa lambda
  1137  		d.Sub(&(*P)[j].Y, &(*R)[j].Y)
  1138  		lambda[j].Mul(&lambda[j], &d)
  1139  
  1140  		// compute X, Y
  1141  		rr.X.Square(&lambda[j])
  1142  		rr.X.Sub(&rr.X, &(*R)[j].X)
  1143  		rr.X.Sub(&rr.X, &(*P)[j].X)
  1144  		d.Sub(&(*R)[j].X, &rr.X)
  1145  		rr.Y.Mul(&lambda[j], &d)
  1146  		rr.Y.Sub(&rr.Y, &(*R)[j].Y)
  1147  		(*R)[j].Set(&rr)
  1148  	}
  1149  }
  1150  
  1151  // RandomOnG2 produces a random point in G2
  1152  // using standard map-to-curve methods, which means the relative discrete log
  1153  // of the generated point with respect to the canonical generator is not known.
  1154  func RandomOnG2() (G2Affine, error) {
  1155  	if gBytes, err := randomFrSizedBytes(); err != nil {
  1156  		return G2Affine{}, err
  1157  	} else {
  1158  		return HashToG2(gBytes, []byte("random on g2"))
  1159  	}
  1160  }
  1161  
  1162  func randomFrSizedBytes() ([]byte, error) {
  1163  	res := make([]byte, fr.Bytes)
  1164  	_, err := rand.Read(res)
  1165  	return res, err
  1166  }