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