github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-633/g2_test.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 bw6633
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  	"math/rand/v2"
    23  	"testing"
    24  
    25  	"github.com/consensys/gnark-crypto/ecc/bw6-633/fp"
    26  
    27  	"github.com/consensys/gnark-crypto/ecc/bw6-633/fr"
    28  	"github.com/leanovate/gopter"
    29  	"github.com/leanovate/gopter/prop"
    30  )
    31  
    32  func TestG2AffineEndomorphism(t *testing.T) {
    33  	t.Parallel()
    34  	parameters := gopter.DefaultTestParameters()
    35  	if testing.Short() {
    36  		parameters.MinSuccessfulTests = nbFuzzShort
    37  	} else {
    38  		parameters.MinSuccessfulTests = nbFuzz
    39  	}
    40  
    41  	properties := gopter.NewProperties(parameters)
    42  
    43  	properties.Property("[BW6-633] check that phi(P) = lambdaGLV * P", prop.ForAll(
    44  		func(a fp.Element) bool {
    45  			var p, res1, res2 G2Jac
    46  			g := MapToG2(a)
    47  			p.FromAffine(&g)
    48  			res1.phi(&p)
    49  			res2.mulWindowed(&p, &lambdaGLV)
    50  
    51  			return p.IsInSubGroup() && res1.Equal(&res2)
    52  		},
    53  		GenFp(),
    54  	))
    55  
    56  	properties.Property("[BW6-633] check that phi^2(P) + phi(P) + P = 0", prop.ForAll(
    57  		func(a fp.Element) bool {
    58  			var p, res, tmp G2Jac
    59  			g := MapToG2(a)
    60  			p.FromAffine(&g)
    61  			tmp.phi(&p)
    62  			res.phi(&tmp).
    63  				AddAssign(&tmp).
    64  				AddAssign(&p)
    65  
    66  			return res.Z.IsZero()
    67  		},
    68  		GenFp(),
    69  	))
    70  
    71  	properties.TestingRun(t, gopter.ConsoleReporter(false))
    72  }
    73  
    74  func TestG2AffineIsOnCurve(t *testing.T) {
    75  	t.Parallel()
    76  	parameters := gopter.DefaultTestParameters()
    77  	if testing.Short() {
    78  		parameters.MinSuccessfulTests = nbFuzzShort
    79  	} else {
    80  		parameters.MinSuccessfulTests = nbFuzz
    81  	}
    82  
    83  	properties := gopter.NewProperties(parameters)
    84  
    85  	properties.Property("[BW6-633] g2Gen (affine) should be on the curve", prop.ForAll(
    86  		func(a fp.Element) bool {
    87  			var op1, op2 G2Affine
    88  			op1.FromJacobian(&g2Gen)
    89  			op2.Set(&op1)
    90  			op2.Y.Mul(&op2.Y, &a)
    91  			return op1.IsOnCurve() && !op2.IsOnCurve()
    92  		},
    93  		GenFp(),
    94  	))
    95  
    96  	properties.Property("[BW6-633] g2Gen (Jacobian) should be on the curve", prop.ForAll(
    97  		func(a fp.Element) bool {
    98  			var op1, op2, op3 G2Jac
    99  			op1.Set(&g2Gen)
   100  			op3.Set(&g2Gen)
   101  
   102  			op2 = fuzzG2Jac(&g2Gen, a)
   103  			op3.Y.Mul(&op3.Y, &a)
   104  			return op1.IsOnCurve() && op2.IsOnCurve() && !op3.IsOnCurve()
   105  		},
   106  		GenFp(),
   107  	))
   108  
   109  	properties.Property("[BW6-633] IsInSubGroup and MulBy subgroup order should be the same", prop.ForAll(
   110  		func(a fp.Element) bool {
   111  			var op1, op2 G2Jac
   112  			op1 = fuzzG2Jac(&g2Gen, a)
   113  			_r := fr.Modulus()
   114  			op2.ScalarMultiplication(&op1, _r)
   115  			return op1.IsInSubGroup() && op2.Z.IsZero()
   116  		},
   117  		GenFp(),
   118  	))
   119  
   120  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   121  }
   122  
   123  func TestG2AffineConversions(t *testing.T) {
   124  	t.Parallel()
   125  	parameters := gopter.DefaultTestParameters()
   126  	if testing.Short() {
   127  		parameters.MinSuccessfulTests = nbFuzzShort
   128  	} else {
   129  		parameters.MinSuccessfulTests = nbFuzz
   130  	}
   131  
   132  	properties := gopter.NewProperties(parameters)
   133  
   134  	properties.Property("[BW6-633] Affine representation should be independent of the Jacobian representative", prop.ForAll(
   135  		func(a fp.Element) bool {
   136  			g := fuzzG2Jac(&g2Gen, a)
   137  			var op1 G2Affine
   138  			op1.FromJacobian(&g)
   139  			return op1.X.Equal(&g2Gen.X) && op1.Y.Equal(&g2Gen.Y)
   140  		},
   141  		GenFp(),
   142  	))
   143  
   144  	properties.Property("[BW6-633] Affine representation should be independent of a Extended Jacobian representative", prop.ForAll(
   145  		func(a fp.Element) bool {
   146  			var g g2JacExtended
   147  			g.X.Set(&g2Gen.X)
   148  			g.Y.Set(&g2Gen.Y)
   149  			g.ZZ.Set(&g2Gen.Z)
   150  			g.ZZZ.Set(&g2Gen.Z)
   151  			gfuzz := fuzzg2JacExtended(&g, a)
   152  
   153  			var op1 G2Affine
   154  			op1.fromJacExtended(&gfuzz)
   155  			return op1.X.Equal(&g2Gen.X) && op1.Y.Equal(&g2Gen.Y)
   156  		},
   157  		GenFp(),
   158  	))
   159  
   160  	properties.Property("[BW6-633] Jacobian representation should be the same as the affine representative", prop.ForAll(
   161  		func(a fp.Element) bool {
   162  			var g G2Jac
   163  			var op1 G2Affine
   164  			op1.X.Set(&g2Gen.X)
   165  			op1.Y.Set(&g2Gen.Y)
   166  
   167  			var one fp.Element
   168  			one.SetOne()
   169  
   170  			g.FromAffine(&op1)
   171  
   172  			return g.X.Equal(&g2Gen.X) && g.Y.Equal(&g2Gen.Y) && g.Z.Equal(&one)
   173  		},
   174  		GenFp(),
   175  	))
   176  
   177  	properties.Property("[BW6-633] Converting affine symbol for infinity to Jacobian should output correct infinity in Jacobian", prop.ForAll(
   178  		func() bool {
   179  			var g G2Affine
   180  			g.X.SetZero()
   181  			g.Y.SetZero()
   182  			var op1 G2Jac
   183  			op1.FromAffine(&g)
   184  			var one, zero fp.Element
   185  			one.SetOne()
   186  			return op1.X.Equal(&one) && op1.Y.Equal(&one) && op1.Z.Equal(&zero)
   187  		},
   188  	))
   189  
   190  	properties.Property("[BW6-633] Converting infinity in extended Jacobian to affine should output infinity symbol in Affine", prop.ForAll(
   191  		func() bool {
   192  			var g G2Affine
   193  			var op1 g2JacExtended
   194  			var zero fp.Element
   195  			op1.X.Set(&g2Gen.X)
   196  			op1.Y.Set(&g2Gen.Y)
   197  			g.fromJacExtended(&op1)
   198  			return g.X.Equal(&zero) && g.Y.Equal(&zero)
   199  		},
   200  	))
   201  
   202  	properties.Property("[BW6-633] Converting infinity in extended Jacobian to Jacobian should output infinity in Jacobian", prop.ForAll(
   203  		func() bool {
   204  			var g G2Jac
   205  			var op1 g2JacExtended
   206  			var zero, one fp.Element
   207  			one.SetOne()
   208  			op1.X.Set(&g2Gen.X)
   209  			op1.Y.Set(&g2Gen.Y)
   210  			g.fromJacExtended(&op1)
   211  			return g.X.Equal(&one) && g.Y.Equal(&one) && g.Z.Equal(&zero)
   212  		},
   213  	))
   214  
   215  	properties.Property("[BW6-633] [Jacobian] Two representatives of the same class should be equal", prop.ForAll(
   216  		func(a, b fp.Element) bool {
   217  			op1 := fuzzG2Jac(&g2Gen, a)
   218  			op2 := fuzzG2Jac(&g2Gen, b)
   219  			return op1.Equal(&op2)
   220  		},
   221  		GenFp(),
   222  		GenFp(),
   223  	))
   224  
   225  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   226  }
   227  
   228  func TestG2AffineOps(t *testing.T) {
   229  	t.Parallel()
   230  	parameters := gopter.DefaultTestParameters()
   231  	parameters.MinSuccessfulTests = 10
   232  
   233  	properties := gopter.NewProperties(parameters)
   234  
   235  	genScalar := GenFr()
   236  
   237  	properties.Property("[BW6-633] Add(P,-P) should return the point at infinity", prop.ForAll(
   238  		func(s fr.Element) bool {
   239  			var op1, op2 G2Affine
   240  			var sInt big.Int
   241  			g := g2GenAff
   242  			s.BigInt(&sInt)
   243  			op1.ScalarMultiplication(&g, &sInt)
   244  			op2.Neg(&op1)
   245  
   246  			op1.Add(&op1, &op2)
   247  			return op1.IsInfinity()
   248  
   249  		},
   250  		GenFr(),
   251  	))
   252  
   253  	properties.Property("[BW6-633] Add(P,0) and Add(0,P) should return P", prop.ForAll(
   254  		func(s fr.Element) bool {
   255  			var op1, op2 G2Affine
   256  			var sInt big.Int
   257  			g := g2GenAff
   258  			s.BigInt(&sInt)
   259  			op1.ScalarMultiplication(&g, &sInt)
   260  			op2.setInfinity()
   261  
   262  			op1.Add(&op1, &op2)
   263  			op2.Add(&op2, &op1)
   264  			return op1.Equal(&op2)
   265  
   266  		},
   267  		GenFr(),
   268  	))
   269  
   270  	properties.Property("[BW6-633] Add should call double when adding the same point", prop.ForAll(
   271  		func(s fr.Element) bool {
   272  			var op1, op2 G2Affine
   273  			var sInt big.Int
   274  			g := g2GenAff
   275  			s.BigInt(&sInt)
   276  			op1.ScalarMultiplication(&g, &sInt)
   277  
   278  			op2.Double(&op1)
   279  			op1.Add(&op1, &op1)
   280  			return op1.Equal(&op2)
   281  
   282  		},
   283  		GenFr(),
   284  	))
   285  
   286  	properties.Property("[BW6-633] [2]G = double(G) + G - G", prop.ForAll(
   287  		func(s fr.Element) bool {
   288  			var sInt big.Int
   289  			g := g2GenAff
   290  			s.BigInt(&sInt)
   291  			g.ScalarMultiplication(&g, &sInt)
   292  			var op1, op2 G2Affine
   293  			op1.ScalarMultiplication(&g, big.NewInt(2))
   294  			op2.Double(&g)
   295  			op2.Add(&op2, &g)
   296  			op2.Sub(&op2, &g)
   297  			return op1.Equal(&op2)
   298  		},
   299  		GenFr(),
   300  	))
   301  
   302  	properties.Property("[BW6-633] [-s]G = -[s]G", prop.ForAll(
   303  		func(s fr.Element) bool {
   304  			g := g2GenAff
   305  			var gj G2Jac
   306  			var nbs, bs big.Int
   307  			s.BigInt(&bs)
   308  			nbs.Neg(&bs)
   309  
   310  			var res = true
   311  
   312  			// mulGLV
   313  			{
   314  				var op1, op2 G2Affine
   315  				op1.ScalarMultiplication(&g, &bs).Neg(&op1)
   316  				op2.ScalarMultiplication(&g, &nbs)
   317  				res = res && op1.Equal(&op2)
   318  			}
   319  
   320  			// mulWindowed
   321  			{
   322  				var op1, op2 G2Jac
   323  				op1.mulWindowed(&gj, &bs).Neg(&op1)
   324  				op2.mulWindowed(&gj, &nbs)
   325  				res = res && op1.Equal(&op2)
   326  			}
   327  
   328  			return res
   329  		},
   330  		GenFr(),
   331  	))
   332  
   333  	properties.Property("[BW6-633] [Jacobian] Add should call double when adding the same point", prop.ForAll(
   334  		func(a, b fp.Element) bool {
   335  			fop1 := fuzzG2Jac(&g2Gen, a)
   336  			fop2 := fuzzG2Jac(&g2Gen, b)
   337  			var op1, op2 G2Jac
   338  			op1.Set(&fop1).AddAssign(&fop2)
   339  			op2.Double(&fop2)
   340  			return op1.Equal(&op2)
   341  		},
   342  		GenFp(),
   343  		GenFp(),
   344  	))
   345  
   346  	properties.Property("[BW6-633] [Jacobian] Adding the opposite of a point to itself should output inf", prop.ForAll(
   347  		func(a, b fp.Element) bool {
   348  			fop1 := fuzzG2Jac(&g2Gen, a)
   349  			fop2 := fuzzG2Jac(&g2Gen, b)
   350  			fop2.Neg(&fop2)
   351  			fop1.AddAssign(&fop2)
   352  			return fop1.Equal(&g2Infinity)
   353  		},
   354  		GenFp(),
   355  		GenFp(),
   356  	))
   357  
   358  	properties.Property("[BW6-633] [Jacobian] Adding the inf to a point should not modify the point", prop.ForAll(
   359  		func(a fp.Element) bool {
   360  			fop1 := fuzzG2Jac(&g2Gen, a)
   361  			fop1.AddAssign(&g2Infinity)
   362  			var op2 G2Jac
   363  			op2.Set(&g2Infinity)
   364  			op2.AddAssign(&g2Gen)
   365  			return fop1.Equal(&g2Gen) && op2.Equal(&g2Gen)
   366  		},
   367  		GenFp(),
   368  	))
   369  
   370  	properties.Property("[BW6-633] [Jacobian Extended] addMixed (-G) should equal subMixed(G)", prop.ForAll(
   371  		func(a fp.Element) bool {
   372  			fop1 := fuzzG2Jac(&g2Gen, a)
   373  			var p1, p1Neg G2Affine
   374  			p1.FromJacobian(&fop1)
   375  			p1Neg = p1
   376  			p1Neg.Y.Neg(&p1Neg.Y)
   377  			var o1, o2 g2JacExtended
   378  			o1.addMixed(&p1Neg)
   379  			o2.subMixed(&p1)
   380  
   381  			return o1.X.Equal(&o2.X) &&
   382  				o1.Y.Equal(&o2.Y) &&
   383  				o1.ZZ.Equal(&o2.ZZ) &&
   384  				o1.ZZZ.Equal(&o2.ZZZ)
   385  		},
   386  		GenFp(),
   387  	))
   388  
   389  	properties.Property("[BW6-633] [Jacobian Extended] doubleMixed (-G) should equal doubleNegMixed(G)", prop.ForAll(
   390  		func(a fp.Element) bool {
   391  			fop1 := fuzzG2Jac(&g2Gen, a)
   392  			var p1, p1Neg G2Affine
   393  			p1.FromJacobian(&fop1)
   394  			p1Neg = p1
   395  			p1Neg.Y.Neg(&p1Neg.Y)
   396  			var o1, o2 g2JacExtended
   397  			o1.doubleMixed(&p1Neg)
   398  			o2.doubleNegMixed(&p1)
   399  
   400  			return o1.X.Equal(&o2.X) &&
   401  				o1.Y.Equal(&o2.Y) &&
   402  				o1.ZZ.Equal(&o2.ZZ) &&
   403  				o1.ZZZ.Equal(&o2.ZZZ)
   404  		},
   405  		GenFp(),
   406  	))
   407  
   408  	properties.Property("[BW6-633] [Jacobian] Addmix the negation to itself should output 0", prop.ForAll(
   409  		func(a fp.Element) bool {
   410  			fop1 := fuzzG2Jac(&g2Gen, a)
   411  			fop1.Neg(&fop1)
   412  			var op2 G2Affine
   413  			op2.FromJacobian(&g2Gen)
   414  			fop1.AddMixed(&op2)
   415  			return fop1.Equal(&g2Infinity)
   416  		},
   417  		GenFp(),
   418  	))
   419  
   420  	properties.Property("[BW6-633] scalar multiplication (double and add) should depend only on the scalar mod r", prop.ForAll(
   421  		func(s fr.Element) bool {
   422  
   423  			r := fr.Modulus()
   424  			var g G2Jac
   425  			g.ScalarMultiplication(&g2Gen, r)
   426  
   427  			var scalar, blindedScalar, rminusone big.Int
   428  			var op1, op2, op3, gneg G2Jac
   429  			rminusone.SetUint64(1).Sub(r, &rminusone)
   430  			op3.mulWindowed(&g2Gen, &rminusone)
   431  			gneg.Neg(&g2Gen)
   432  			s.BigInt(&scalar)
   433  			blindedScalar.Mul(&scalar, r).Add(&blindedScalar, &scalar)
   434  			op1.mulWindowed(&g2Gen, &scalar)
   435  			op2.mulWindowed(&g2Gen, &blindedScalar)
   436  
   437  			return op1.Equal(&op2) && g.Equal(&g2Infinity) && !op1.Equal(&g2Infinity) && gneg.Equal(&op3)
   438  
   439  		},
   440  		genScalar,
   441  	))
   442  
   443  	properties.Property("[BW6-633] scalar multiplication (GLV) should depend only on the scalar mod r", prop.ForAll(
   444  		func(s fr.Element) bool {
   445  
   446  			r := fr.Modulus()
   447  			var g G2Jac
   448  			g.mulGLV(&g2Gen, r)
   449  
   450  			var scalar, blindedScalar, rminusone big.Int
   451  			var op1, op2, op3, gneg G2Jac
   452  			rminusone.SetUint64(1).Sub(r, &rminusone)
   453  			op3.ScalarMultiplication(&g2Gen, &rminusone)
   454  			gneg.Neg(&g2Gen)
   455  			s.BigInt(&scalar)
   456  			blindedScalar.Mul(&scalar, r).Add(&blindedScalar, &scalar)
   457  			op1.ScalarMultiplication(&g2Gen, &scalar)
   458  			op2.ScalarMultiplication(&g2Gen, &blindedScalar)
   459  
   460  			return op1.Equal(&op2) && g.Equal(&g2Infinity) && !op1.Equal(&g2Infinity) && gneg.Equal(&op3)
   461  
   462  		},
   463  		genScalar,
   464  	))
   465  
   466  	properties.Property("[BW6-633] GLV and Double and Add should output the same result", prop.ForAll(
   467  		func(s fr.Element) bool {
   468  
   469  			var r big.Int
   470  			var op1, op2 G2Jac
   471  			s.BigInt(&r)
   472  			op1.mulWindowed(&g2Gen, &r)
   473  			op2.mulGLV(&g2Gen, &r)
   474  			return op1.Equal(&op2) && !op1.Equal(&g2Infinity)
   475  
   476  		},
   477  		genScalar,
   478  	))
   479  
   480  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   481  }
   482  
   483  func TestG2AffineCofactorCleaning(t *testing.T) {
   484  	t.Parallel()
   485  	parameters := gopter.DefaultTestParameters()
   486  	if testing.Short() {
   487  		parameters.MinSuccessfulTests = nbFuzzShort
   488  	} else {
   489  		parameters.MinSuccessfulTests = nbFuzz
   490  	}
   491  
   492  	properties := gopter.NewProperties(parameters)
   493  
   494  	properties.Property("[BW6-633] Clearing the cofactor of a random point should set it in the r-torsion", prop.ForAll(
   495  		func() bool {
   496  			var a, x, b fp.Element
   497  			a.SetRandom()
   498  
   499  			x.Square(&a).Mul(&x, &a).Add(&x, &bTwistCurveCoeff)
   500  
   501  			for x.Legendre() != 1 {
   502  				a.SetRandom()
   503  
   504  				x.Square(&a).Mul(&x, &a).Add(&x, &bTwistCurveCoeff)
   505  
   506  			}
   507  
   508  			b.Sqrt(&x)
   509  			var point, pointCleared, infinity G2Jac
   510  			point.X.Set(&a)
   511  			point.Y.Set(&b)
   512  			point.Z.SetOne()
   513  			pointCleared.ClearCofactor(&point)
   514  			infinity.Set(&g2Infinity)
   515  			return point.IsOnCurve() && pointCleared.IsInSubGroup() && !pointCleared.Equal(&infinity)
   516  		},
   517  	))
   518  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   519  
   520  }
   521  
   522  func TestG2AffineBatchScalarMultiplication(t *testing.T) {
   523  
   524  	parameters := gopter.DefaultTestParameters()
   525  	if testing.Short() {
   526  		parameters.MinSuccessfulTests = nbFuzzShort
   527  	} else {
   528  		parameters.MinSuccessfulTests = nbFuzzShort
   529  	}
   530  
   531  	properties := gopter.NewProperties(parameters)
   532  
   533  	genScalar := GenFr()
   534  
   535  	// size of the multiExps
   536  	const nbSamples = 10
   537  
   538  	properties.Property("[BW6-633] BatchScalarMultiplication should be consistent with individual scalar multiplications", prop.ForAll(
   539  		func(mixer fr.Element) bool {
   540  			// mixer ensures that all the words of a fpElement are set
   541  			var sampleScalars [nbSamples]fr.Element
   542  
   543  			for i := 1; i <= nbSamples; i++ {
   544  				sampleScalars[i-1].SetUint64(uint64(i)).
   545  					Mul(&sampleScalars[i-1], &mixer)
   546  			}
   547  
   548  			result := BatchScalarMultiplicationG2(&g2GenAff, sampleScalars[:])
   549  
   550  			if len(result) != len(sampleScalars) {
   551  				return false
   552  			}
   553  
   554  			for i := 0; i < len(result); i++ {
   555  				var expectedJac G2Jac
   556  				var expected G2Affine
   557  				var b big.Int
   558  				expectedJac.ScalarMultiplication(&g2Gen, sampleScalars[i].BigInt(&b))
   559  				expected.FromJacobian(&expectedJac)
   560  				if !result[i].Equal(&expected) {
   561  					return false
   562  				}
   563  			}
   564  			return true
   565  		},
   566  		genScalar,
   567  	))
   568  
   569  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   570  }
   571  
   572  // ------------------------------------------------------------
   573  // benches
   574  
   575  func BenchmarkG2JacIsInSubGroup(b *testing.B) {
   576  	var a G2Jac
   577  	a.Set(&g2Gen)
   578  	b.ResetTimer()
   579  	for i := 0; i < b.N; i++ {
   580  		a.IsInSubGroup()
   581  	}
   582  
   583  }
   584  
   585  func BenchmarkG2JacEqual(b *testing.B) {
   586  	var scalar fp.Element
   587  	if _, err := scalar.SetRandom(); err != nil {
   588  		b.Fatalf("failed to set scalar: %s", err)
   589  	}
   590  
   591  	var a G2Jac
   592  	a.ScalarMultiplication(&g2Gen, big.NewInt(42))
   593  
   594  	b.Run("equal", func(b *testing.B) {
   595  		var scalarSquared fp.Element
   596  		scalarSquared.Square(&scalar)
   597  
   598  		aZScaled := a
   599  		aZScaled.X.Mul(&aZScaled.X, &scalarSquared)
   600  		aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar)
   601  		aZScaled.Z.Mul(&aZScaled.Z, &scalar)
   602  
   603  		// Check the setup.
   604  		if !a.Equal(&aZScaled) {
   605  			b.Fatalf("invalid test setup")
   606  		}
   607  
   608  		b.ResetTimer()
   609  		for i := 0; i < b.N; i++ {
   610  			a.Equal(&aZScaled)
   611  		}
   612  	})
   613  
   614  	b.Run("not equal", func(b *testing.B) {
   615  		var aPlus1 G2Jac
   616  		aPlus1.AddAssign(&g2Gen)
   617  
   618  		// Check the setup.
   619  		if a.Equal(&aPlus1) {
   620  			b.Fatalf("invalid test setup")
   621  		}
   622  
   623  		b.ResetTimer()
   624  		for i := 0; i < b.N; i++ {
   625  			a.Equal(&aPlus1)
   626  		}
   627  	})
   628  }
   629  
   630  func BenchmarkBatchAddG2Affine(b *testing.B) {
   631  
   632  	var P, R pG2AffineC16
   633  	var RR ppG2AffineC16
   634  	ridx := make([]int, len(P))
   635  
   636  	// TODO P == R may produce skewed benches
   637  	fillBenchBasesG2(P[:])
   638  	fillBenchBasesG2(R[:])
   639  
   640  	for i := 0; i < len(ridx); i++ {
   641  		ridx[i] = i
   642  	}
   643  
   644  	// random permute
   645  	rand.Shuffle(len(ridx), func(i, j int) { ridx[i], ridx[j] = ridx[j], ridx[i] })
   646  
   647  	for i, ri := range ridx {
   648  		RR[i] = &R[ri]
   649  	}
   650  
   651  	b.ResetTimer()
   652  	for i := 0; i < b.N; i++ {
   653  		batchAddG2Affine[pG2AffineC16, ppG2AffineC16, cG2AffineC16](&RR, &P, len(P))
   654  	}
   655  }
   656  
   657  func BenchmarkG2AffineBatchScalarMultiplication(b *testing.B) {
   658  	// ensure every words of the scalars are filled
   659  	var mixer fr.Element
   660  	mixer.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487")
   661  
   662  	const pow = 15
   663  	const nbSamples = 1 << pow
   664  
   665  	var sampleScalars [nbSamples]fr.Element
   666  
   667  	for i := 1; i <= nbSamples; i++ {
   668  		sampleScalars[i-1].SetUint64(uint64(i)).
   669  			Mul(&sampleScalars[i-1], &mixer)
   670  	}
   671  
   672  	for i := 5; i <= pow; i++ {
   673  		using := 1 << i
   674  
   675  		b.Run(fmt.Sprintf("%d points", using), func(b *testing.B) {
   676  			b.ResetTimer()
   677  			for j := 0; j < b.N; j++ {
   678  				_ = BatchScalarMultiplicationG2(&g2GenAff, sampleScalars[:using])
   679  			}
   680  		})
   681  	}
   682  }
   683  
   684  func BenchmarkG2JacScalarMultiplication(b *testing.B) {
   685  
   686  	var scalar big.Int
   687  	r := fr.Modulus()
   688  	scalar.SetString("5243587517512619047944770508185965837690552500527637822603658699938581184513", 10)
   689  	scalar.Add(&scalar, r)
   690  
   691  	var doubleAndAdd G2Jac
   692  
   693  	b.Run("double and add", func(b *testing.B) {
   694  		b.ResetTimer()
   695  		for j := 0; j < b.N; j++ {
   696  			doubleAndAdd.mulWindowed(&g2Gen, &scalar)
   697  		}
   698  	})
   699  
   700  	var glv G2Jac
   701  	b.Run("GLV", func(b *testing.B) {
   702  		b.ResetTimer()
   703  		for j := 0; j < b.N; j++ {
   704  			glv.mulGLV(&g2Gen, &scalar)
   705  		}
   706  	})
   707  
   708  }
   709  
   710  func BenchmarkG2AffineCofactorClearing(b *testing.B) {
   711  	var a G2Jac
   712  	a.Set(&g2Gen)
   713  	for i := 0; i < b.N; i++ {
   714  		a.ClearCofactor(&a)
   715  	}
   716  }
   717  
   718  func BenchmarkG2JacAdd(b *testing.B) {
   719  	var a G2Jac
   720  	a.Double(&g2Gen)
   721  	b.ResetTimer()
   722  	for i := 0; i < b.N; i++ {
   723  		a.AddAssign(&g2Gen)
   724  	}
   725  }
   726  
   727  func BenchmarkG2JacAddMixed(b *testing.B) {
   728  	var a G2Jac
   729  	a.Double(&g2Gen)
   730  
   731  	var c G2Affine
   732  	c.FromJacobian(&g2Gen)
   733  	b.ResetTimer()
   734  	for i := 0; i < b.N; i++ {
   735  		a.AddMixed(&c)
   736  	}
   737  
   738  }
   739  
   740  func BenchmarkG2JacDouble(b *testing.B) {
   741  	var a G2Jac
   742  	a.Set(&g2Gen)
   743  	b.ResetTimer()
   744  	for i := 0; i < b.N; i++ {
   745  		a.DoubleAssign()
   746  	}
   747  
   748  }
   749  
   750  func BenchmarkG2JacExtAddMixed(b *testing.B) {
   751  	var a g2JacExtended
   752  	a.doubleMixed(&g2GenAff)
   753  
   754  	var c G2Affine
   755  	c.FromJacobian(&g2Gen)
   756  	b.ResetTimer()
   757  	for i := 0; i < b.N; i++ {
   758  		a.addMixed(&c)
   759  	}
   760  }
   761  
   762  func BenchmarkG2JacExtSubMixed(b *testing.B) {
   763  	var a g2JacExtended
   764  	a.doubleMixed(&g2GenAff)
   765  
   766  	var c G2Affine
   767  	c.FromJacobian(&g2Gen)
   768  	b.ResetTimer()
   769  	for i := 0; i < b.N; i++ {
   770  		a.subMixed(&c)
   771  	}
   772  }
   773  
   774  func BenchmarkG2JacExtDoubleMixed(b *testing.B) {
   775  	var a g2JacExtended
   776  	a.doubleMixed(&g2GenAff)
   777  
   778  	var c G2Affine
   779  	c.FromJacobian(&g2Gen)
   780  	b.ResetTimer()
   781  	for i := 0; i < b.N; i++ {
   782  		a.doubleMixed(&c)
   783  	}
   784  }
   785  
   786  func BenchmarkG2JacExtDoubleNegMixed(b *testing.B) {
   787  	var a g2JacExtended
   788  	a.doubleMixed(&g2GenAff)
   789  
   790  	var c G2Affine
   791  	c.FromJacobian(&g2Gen)
   792  	b.ResetTimer()
   793  	for i := 0; i < b.N; i++ {
   794  		a.doubleNegMixed(&c)
   795  	}
   796  }
   797  
   798  func BenchmarkG2JacExtAdd(b *testing.B) {
   799  	var a, c g2JacExtended
   800  	a.doubleMixed(&g2GenAff)
   801  	c.double(&a)
   802  
   803  	b.ResetTimer()
   804  	for i := 0; i < b.N; i++ {
   805  		a.add(&c)
   806  	}
   807  }
   808  
   809  func BenchmarkG2JacExtDouble(b *testing.B) {
   810  	var a g2JacExtended
   811  	a.doubleMixed(&g2GenAff)
   812  
   813  	b.ResetTimer()
   814  	for i := 0; i < b.N; i++ {
   815  		a.double(&a)
   816  	}
   817  }
   818  
   819  func BenchmarkG2AffineAdd(b *testing.B) {
   820  	var a G2Affine
   821  	a.Double(&g2GenAff)
   822  	b.ResetTimer()
   823  	for i := 0; i < b.N; i++ {
   824  		a.Add(&a, &g2GenAff)
   825  	}
   826  }
   827  
   828  func BenchmarkG2AffineDouble(b *testing.B) {
   829  	var a G2Affine
   830  	a.Double(&g2GenAff)
   831  	b.ResetTimer()
   832  	for i := 0; i < b.N; i++ {
   833  		a.Double(&a)
   834  	}
   835  }
   836  
   837  func fuzzG2Jac(p *G2Jac, f fp.Element) G2Jac {
   838  	var res G2Jac
   839  	res.X.Mul(&p.X, &f).Mul(&res.X, &f)
   840  	res.Y.Mul(&p.Y, &f).Mul(&res.Y, &f).Mul(&res.Y, &f)
   841  	res.Z.Mul(&p.Z, &f)
   842  	return res
   843  }
   844  
   845  func fuzzg2JacExtended(p *g2JacExtended, f fp.Element) g2JacExtended {
   846  	var res g2JacExtended
   847  	var ff, fff fp.Element
   848  	ff.Square(&f)
   849  	fff.Mul(&ff, &f)
   850  	res.X.Mul(&p.X, &ff)
   851  	res.Y.Mul(&p.Y, &fff)
   852  	res.ZZ.Mul(&p.ZZ, &ff)
   853  	res.ZZZ.Mul(&p.ZZZ, &fff)
   854  	return res
   855  }