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