github.com/consensys/gnark-crypto@v0.14.0/ecc/bn254/g1_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/fp"
    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 TestG1AffineEndomorphism(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 fp.Element) bool {
    45  			var p, res1, res2 G1Jac
    46  			g := MapToG1(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("[BN254] check that phi^2(P) + phi(P) + P = 0", prop.ForAll(
    57  		func(a fp.Element) bool {
    58  			var p, res, tmp G1Jac
    59  			g := MapToG1(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 TestG1AffineIsOnCurve(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("[BN254] g1Gen (affine) should be on the curve", prop.ForAll(
    86  		func(a fp.Element) bool {
    87  			var op1, op2 G1Affine
    88  			op1.FromJacobian(&g1Gen)
    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("[BN254] g1Gen (Jacobian) should be on the curve", prop.ForAll(
    97  		func(a fp.Element) bool {
    98  			var op1, op2, op3 G1Jac
    99  			op1.Set(&g1Gen)
   100  			op3.Set(&g1Gen)
   101  
   102  			op2 = fuzzG1Jac(&g1Gen, a)
   103  			op3.Y.Mul(&op3.Y, &a)
   104  			return op1.IsOnCurve() && op2.IsOnCurve() && !op3.IsOnCurve()
   105  		},
   106  		GenFp(),
   107  	))
   108  
   109  	properties.Property("[BN254] IsInSubGroup and MulBy subgroup order should be the same", prop.ForAll(
   110  		func(a fp.Element) bool {
   111  			var op1, op2 G1Jac
   112  			op1 = fuzzG1Jac(&g1Gen, 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 TestG1AffineConversions(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("[BN254] Affine representation should be independent of the Jacobian representative", prop.ForAll(
   135  		func(a fp.Element) bool {
   136  			g := fuzzG1Jac(&g1Gen, a)
   137  			var op1 G1Affine
   138  			op1.FromJacobian(&g)
   139  			return op1.X.Equal(&g1Gen.X) && op1.Y.Equal(&g1Gen.Y)
   140  		},
   141  		GenFp(),
   142  	))
   143  
   144  	properties.Property("[BN254] Affine representation should be independent of a Extended Jacobian representative", prop.ForAll(
   145  		func(a fp.Element) bool {
   146  			var g g1JacExtended
   147  			g.X.Set(&g1Gen.X)
   148  			g.Y.Set(&g1Gen.Y)
   149  			g.ZZ.Set(&g1Gen.Z)
   150  			g.ZZZ.Set(&g1Gen.Z)
   151  			gfuzz := fuzzg1JacExtended(&g, a)
   152  
   153  			var op1 G1Affine
   154  			op1.fromJacExtended(&gfuzz)
   155  			return op1.X.Equal(&g1Gen.X) && op1.Y.Equal(&g1Gen.Y)
   156  		},
   157  		GenFp(),
   158  	))
   159  
   160  	properties.Property("[BN254] Jacobian representation should be the same as the affine representative", prop.ForAll(
   161  		func(a fp.Element) bool {
   162  			var g G1Jac
   163  			var op1 G1Affine
   164  			op1.X.Set(&g1Gen.X)
   165  			op1.Y.Set(&g1Gen.Y)
   166  
   167  			var one fp.Element
   168  			one.SetOne()
   169  
   170  			g.FromAffine(&op1)
   171  
   172  			return g.X.Equal(&g1Gen.X) && g.Y.Equal(&g1Gen.Y) && g.Z.Equal(&one)
   173  		},
   174  		GenFp(),
   175  	))
   176  
   177  	properties.Property("[BN254] Converting affine symbol for infinity to Jacobian should output correct infinity in Jacobian", prop.ForAll(
   178  		func() bool {
   179  			var g G1Affine
   180  			g.X.SetZero()
   181  			g.Y.SetZero()
   182  			var op1 G1Jac
   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("[BN254] Converting infinity in extended Jacobian to affine should output infinity symbol in Affine", prop.ForAll(
   191  		func() bool {
   192  			var g G1Affine
   193  			var op1 g1JacExtended
   194  			var zero fp.Element
   195  			op1.X.Set(&g1Gen.X)
   196  			op1.Y.Set(&g1Gen.Y)
   197  			g.fromJacExtended(&op1)
   198  			return g.X.Equal(&zero) && g.Y.Equal(&zero)
   199  		},
   200  	))
   201  
   202  	properties.Property("[BN254] Converting infinity in extended Jacobian to Jacobian should output infinity in Jacobian", prop.ForAll(
   203  		func() bool {
   204  			var g G1Jac
   205  			var op1 g1JacExtended
   206  			var zero, one fp.Element
   207  			one.SetOne()
   208  			op1.X.Set(&g1Gen.X)
   209  			op1.Y.Set(&g1Gen.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("[BN254] [Jacobian] Two representatives of the same class should be equal", prop.ForAll(
   216  		func(a, b fp.Element) bool {
   217  			op1 := fuzzG1Jac(&g1Gen, a)
   218  			op2 := fuzzG1Jac(&g1Gen, b)
   219  			return op1.Equal(&op2)
   220  		},
   221  		GenFp(),
   222  		GenFp(),
   223  	))
   224  	properties.Property("[BN254] BatchJacobianToAffineG1 and FromJacobian should output the same result", prop.ForAll(
   225  		func(a, b fp.Element) bool {
   226  			g1 := fuzzG1Jac(&g1Gen, a)
   227  			g2 := fuzzG1Jac(&g1Gen, b)
   228  			var op1, op2 G1Affine
   229  			op1.FromJacobian(&g1)
   230  			op2.FromJacobian(&g2)
   231  			baseTableAff := BatchJacobianToAffineG1([]G1Jac{g1, g2})
   232  			return op1.Equal(&baseTableAff[0]) && op2.Equal(&baseTableAff[1])
   233  		},
   234  		GenFp(),
   235  		GenFp(),
   236  	))
   237  
   238  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   239  }
   240  
   241  func TestG1AffineOps(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 G1Affine
   253  			var sInt big.Int
   254  			g := g1GenAff
   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 G1Affine
   269  			var sInt big.Int
   270  			g := g1GenAff
   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 G1Affine
   286  			var sInt big.Int
   287  			g := g1GenAff
   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 := g1GenAff
   303  			s.BigInt(&sInt)
   304  			g.ScalarMultiplication(&g, &sInt)
   305  			var op1, op2 G1Affine
   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 := g1GenAff
   318  			var gj G1Jac
   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 G1Affine
   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 G1Jac
   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 fp.Element) bool {
   348  			fop1 := fuzzG1Jac(&g1Gen, a)
   349  			fop2 := fuzzG1Jac(&g1Gen, b)
   350  			var op1, op2 G1Jac
   351  			op1.Set(&fop1).AddAssign(&fop2)
   352  			op2.Double(&fop2)
   353  			return op1.Equal(&op2)
   354  		},
   355  		GenFp(),
   356  		GenFp(),
   357  	))
   358  
   359  	properties.Property("[BN254] [Jacobian] Adding the opposite of a point to itself should output inf", prop.ForAll(
   360  		func(a, b fp.Element) bool {
   361  			fop1 := fuzzG1Jac(&g1Gen, a)
   362  			fop2 := fuzzG1Jac(&g1Gen, b)
   363  			fop2.Neg(&fop2)
   364  			fop1.AddAssign(&fop2)
   365  			return fop1.Equal(&g1Infinity)
   366  		},
   367  		GenFp(),
   368  		GenFp(),
   369  	))
   370  
   371  	properties.Property("[BN254] [Jacobian] Adding the inf to a point should not modify the point", prop.ForAll(
   372  		func(a fp.Element) bool {
   373  			fop1 := fuzzG1Jac(&g1Gen, a)
   374  			fop1.AddAssign(&g1Infinity)
   375  			var op2 G1Jac
   376  			op2.Set(&g1Infinity)
   377  			op2.AddAssign(&g1Gen)
   378  			return fop1.Equal(&g1Gen) && op2.Equal(&g1Gen)
   379  		},
   380  		GenFp(),
   381  	))
   382  
   383  	properties.Property("[BN254] [Jacobian Extended] addMixed (-G) should equal subMixed(G)", prop.ForAll(
   384  		func(a fp.Element) bool {
   385  			fop1 := fuzzG1Jac(&g1Gen, a)
   386  			var p1, p1Neg G1Affine
   387  			p1.FromJacobian(&fop1)
   388  			p1Neg = p1
   389  			p1Neg.Y.Neg(&p1Neg.Y)
   390  			var o1, o2 g1JacExtended
   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  		GenFp(),
   400  	))
   401  
   402  	properties.Property("[BN254] [Jacobian Extended] doubleMixed (-G) should equal doubleNegMixed(G)", prop.ForAll(
   403  		func(a fp.Element) bool {
   404  			fop1 := fuzzG1Jac(&g1Gen, a)
   405  			var p1, p1Neg G1Affine
   406  			p1.FromJacobian(&fop1)
   407  			p1Neg = p1
   408  			p1Neg.Y.Neg(&p1Neg.Y)
   409  			var o1, o2 g1JacExtended
   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  		GenFp(),
   419  	))
   420  
   421  	properties.Property("[BN254] [Jacobian] Addmix the negation to itself should output 0", prop.ForAll(
   422  		func(a fp.Element) bool {
   423  			fop1 := fuzzG1Jac(&g1Gen, a)
   424  			fop1.Neg(&fop1)
   425  			var op2 G1Affine
   426  			op2.FromJacobian(&g1Gen)
   427  			fop1.AddMixed(&op2)
   428  			return fop1.Equal(&g1Infinity)
   429  		},
   430  		GenFp(),
   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 G1Jac
   438  			g.ScalarMultiplication(&g1Gen, r)
   439  
   440  			var scalar, blindedScalar, rminusone big.Int
   441  			var op1, op2, op3, gneg G1Jac
   442  			rminusone.SetUint64(1).Sub(r, &rminusone)
   443  			op3.mulWindowed(&g1Gen, &rminusone)
   444  			gneg.Neg(&g1Gen)
   445  			s.BigInt(&scalar)
   446  			blindedScalar.Mul(&scalar, r).Add(&blindedScalar, &scalar)
   447  			op1.mulWindowed(&g1Gen, &scalar)
   448  			op2.mulWindowed(&g1Gen, &blindedScalar)
   449  
   450  			return op1.Equal(&op2) && g.Equal(&g1Infinity) && !op1.Equal(&g1Infinity) && gneg.Equal(&op3)
   451  
   452  		},
   453  		genScalar,
   454  	))
   455  
   456  	properties.Property("[BN254] scalar multiplication (GLV) should depend only on the scalar mod r", prop.ForAll(
   457  		func(s fr.Element) bool {
   458  
   459  			r := fr.Modulus()
   460  			var g G1Jac
   461  			g.mulGLV(&g1Gen, r)
   462  
   463  			var scalar, blindedScalar, rminusone big.Int
   464  			var op1, op2, op3, gneg G1Jac
   465  			rminusone.SetUint64(1).Sub(r, &rminusone)
   466  			op3.ScalarMultiplication(&g1Gen, &rminusone)
   467  			gneg.Neg(&g1Gen)
   468  			s.BigInt(&scalar)
   469  			blindedScalar.Mul(&scalar, r).Add(&blindedScalar, &scalar)
   470  			op1.ScalarMultiplication(&g1Gen, &scalar)
   471  			op2.ScalarMultiplication(&g1Gen, &blindedScalar)
   472  
   473  			return op1.Equal(&op2) && g.Equal(&g1Infinity) && !op1.Equal(&g1Infinity) && gneg.Equal(&op3)
   474  
   475  		},
   476  		genScalar,
   477  	))
   478  
   479  	properties.Property("[BN254] GLV and Double and Add should output the same result", prop.ForAll(
   480  		func(s fr.Element) bool {
   481  
   482  			var r big.Int
   483  			var op1, op2 G1Jac
   484  			s.BigInt(&r)
   485  			op1.mulWindowed(&g1Gen, &r)
   486  			op2.mulGLV(&g1Gen, &r)
   487  			return op1.Equal(&op2) && !op1.Equal(&g1Infinity)
   488  
   489  		},
   490  		genScalar,
   491  	))
   492  
   493  	properties.Property("[BN254] JointScalarMultiplicationBase and ScalarMultiplication should output the same results", prop.ForAll(
   494  		func(s1, s2 fr.Element) bool {
   495  
   496  			var op1, op2, temp G1Jac
   497  
   498  			op1.JointScalarMultiplicationBase(&g1GenAff, s1.BigInt(new(big.Int)), s2.BigInt(new(big.Int)))
   499  			temp.ScalarMultiplication(&g1Gen, s2.BigInt(new(big.Int)))
   500  			op2.ScalarMultiplication(&g1Gen, s1.BigInt(new(big.Int))).
   501  				AddAssign(&temp)
   502  
   503  			return op1.Equal(&op2)
   504  
   505  		},
   506  		genScalar,
   507  		genScalar,
   508  	))
   509  
   510  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   511  }
   512  
   513  func TestG1AffineBatchScalarMultiplication(t *testing.T) {
   514  
   515  	parameters := gopter.DefaultTestParameters()
   516  	if testing.Short() {
   517  		parameters.MinSuccessfulTests = nbFuzzShort
   518  	} else {
   519  		parameters.MinSuccessfulTests = nbFuzzShort
   520  	}
   521  
   522  	properties := gopter.NewProperties(parameters)
   523  
   524  	genScalar := GenFr()
   525  
   526  	// size of the multiExps
   527  	const nbSamples = 10
   528  
   529  	properties.Property("[BN254] BatchScalarMultiplication should be consistent with individual scalar multiplications", prop.ForAll(
   530  		func(mixer fr.Element) bool {
   531  			// mixer ensures that all the words of a fpElement are set
   532  			var sampleScalars [nbSamples]fr.Element
   533  
   534  			for i := 1; i <= nbSamples; i++ {
   535  				sampleScalars[i-1].SetUint64(uint64(i)).
   536  					Mul(&sampleScalars[i-1], &mixer)
   537  			}
   538  
   539  			result := BatchScalarMultiplicationG1(&g1GenAff, sampleScalars[:])
   540  
   541  			if len(result) != len(sampleScalars) {
   542  				return false
   543  			}
   544  
   545  			for i := 0; i < len(result); i++ {
   546  				var expectedJac G1Jac
   547  				var expected G1Affine
   548  				var b big.Int
   549  				expectedJac.ScalarMultiplication(&g1Gen, sampleScalars[i].BigInt(&b))
   550  				expected.FromJacobian(&expectedJac)
   551  				if !result[i].Equal(&expected) {
   552  					return false
   553  				}
   554  			}
   555  			return true
   556  		},
   557  		genScalar,
   558  	))
   559  
   560  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   561  }
   562  
   563  // ------------------------------------------------------------
   564  // benches
   565  
   566  func BenchmarkG1JacIsInSubGroup(b *testing.B) {
   567  	var a G1Jac
   568  	a.Set(&g1Gen)
   569  	b.ResetTimer()
   570  	for i := 0; i < b.N; i++ {
   571  		a.IsInSubGroup()
   572  	}
   573  
   574  }
   575  
   576  func BenchmarkG1JacEqual(b *testing.B) {
   577  	var scalar fp.Element
   578  	if _, err := scalar.SetRandom(); err != nil {
   579  		b.Fatalf("failed to set scalar: %s", err)
   580  	}
   581  
   582  	var a G1Jac
   583  	a.ScalarMultiplication(&g1Gen, big.NewInt(42))
   584  
   585  	b.Run("equal", func(b *testing.B) {
   586  		var scalarSquared fp.Element
   587  		scalarSquared.Square(&scalar)
   588  
   589  		aZScaled := a
   590  		aZScaled.X.Mul(&aZScaled.X, &scalarSquared)
   591  		aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar)
   592  		aZScaled.Z.Mul(&aZScaled.Z, &scalar)
   593  
   594  		// Check the setup.
   595  		if !a.Equal(&aZScaled) {
   596  			b.Fatalf("invalid test setup")
   597  		}
   598  
   599  		b.ResetTimer()
   600  		for i := 0; i < b.N; i++ {
   601  			a.Equal(&aZScaled)
   602  		}
   603  	})
   604  
   605  	b.Run("not equal", func(b *testing.B) {
   606  		var aPlus1 G1Jac
   607  		aPlus1.AddAssign(&g1Gen)
   608  
   609  		// Check the setup.
   610  		if a.Equal(&aPlus1) {
   611  			b.Fatalf("invalid test setup")
   612  		}
   613  
   614  		b.ResetTimer()
   615  		for i := 0; i < b.N; i++ {
   616  			a.Equal(&aPlus1)
   617  		}
   618  	})
   619  }
   620  
   621  func BenchmarkBatchAddG1Affine(b *testing.B) {
   622  
   623  	var P, R pG1AffineC16
   624  	var RR ppG1AffineC16
   625  	ridx := make([]int, len(P))
   626  
   627  	// TODO P == R may produce skewed benches
   628  	fillBenchBasesG1(P[:])
   629  	fillBenchBasesG1(R[:])
   630  
   631  	for i := 0; i < len(ridx); i++ {
   632  		ridx[i] = i
   633  	}
   634  
   635  	// random permute
   636  	rand.Shuffle(len(ridx), func(i, j int) { ridx[i], ridx[j] = ridx[j], ridx[i] })
   637  
   638  	for i, ri := range ridx {
   639  		RR[i] = &R[ri]
   640  	}
   641  
   642  	b.ResetTimer()
   643  	for i := 0; i < b.N; i++ {
   644  		batchAddG1Affine[pG1AffineC16, ppG1AffineC16, cG1AffineC16](&RR, &P, len(P))
   645  	}
   646  }
   647  
   648  func BenchmarkG1AffineBatchScalarMultiplication(b *testing.B) {
   649  	// ensure every words of the scalars are filled
   650  	var mixer fr.Element
   651  	mixer.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487")
   652  
   653  	const pow = 15
   654  	const nbSamples = 1 << pow
   655  
   656  	var sampleScalars [nbSamples]fr.Element
   657  
   658  	for i := 1; i <= nbSamples; i++ {
   659  		sampleScalars[i-1].SetUint64(uint64(i)).
   660  			Mul(&sampleScalars[i-1], &mixer)
   661  	}
   662  
   663  	for i := 5; i <= pow; i++ {
   664  		using := 1 << i
   665  
   666  		b.Run(fmt.Sprintf("%d points", using), func(b *testing.B) {
   667  			b.ResetTimer()
   668  			for j := 0; j < b.N; j++ {
   669  				_ = BatchScalarMultiplicationG1(&g1GenAff, sampleScalars[:using])
   670  			}
   671  		})
   672  	}
   673  }
   674  
   675  func BenchmarkG1JacScalarMultiplication(b *testing.B) {
   676  
   677  	var scalar big.Int
   678  	r := fr.Modulus()
   679  	scalar.SetString("5243587517512619047944770508185965837690552500527637822603658699938581184513", 10)
   680  	scalar.Add(&scalar, r)
   681  
   682  	var doubleAndAdd G1Jac
   683  
   684  	b.Run("double and add", func(b *testing.B) {
   685  		b.ResetTimer()
   686  		for j := 0; j < b.N; j++ {
   687  			doubleAndAdd.mulWindowed(&g1Gen, &scalar)
   688  		}
   689  	})
   690  
   691  	var glv G1Jac
   692  	b.Run("GLV", func(b *testing.B) {
   693  		b.ResetTimer()
   694  		for j := 0; j < b.N; j++ {
   695  			glv.mulGLV(&g1Gen, &scalar)
   696  		}
   697  	})
   698  
   699  }
   700  
   701  func BenchmarkG1JacAdd(b *testing.B) {
   702  	var a G1Jac
   703  	a.Double(&g1Gen)
   704  	b.ResetTimer()
   705  	for i := 0; i < b.N; i++ {
   706  		a.AddAssign(&g1Gen)
   707  	}
   708  }
   709  
   710  func BenchmarkG1JacAddMixed(b *testing.B) {
   711  	var a G1Jac
   712  	a.Double(&g1Gen)
   713  
   714  	var c G1Affine
   715  	c.FromJacobian(&g1Gen)
   716  	b.ResetTimer()
   717  	for i := 0; i < b.N; i++ {
   718  		a.AddMixed(&c)
   719  	}
   720  
   721  }
   722  
   723  func BenchmarkG1JacDouble(b *testing.B) {
   724  	var a G1Jac
   725  	a.Set(&g1Gen)
   726  	b.ResetTimer()
   727  	for i := 0; i < b.N; i++ {
   728  		a.DoubleAssign()
   729  	}
   730  
   731  }
   732  
   733  func BenchmarkG1JacExtAddMixed(b *testing.B) {
   734  	var a g1JacExtended
   735  	a.doubleMixed(&g1GenAff)
   736  
   737  	var c G1Affine
   738  	c.FromJacobian(&g1Gen)
   739  	b.ResetTimer()
   740  	for i := 0; i < b.N; i++ {
   741  		a.addMixed(&c)
   742  	}
   743  }
   744  
   745  func BenchmarkG1JacExtSubMixed(b *testing.B) {
   746  	var a g1JacExtended
   747  	a.doubleMixed(&g1GenAff)
   748  
   749  	var c G1Affine
   750  	c.FromJacobian(&g1Gen)
   751  	b.ResetTimer()
   752  	for i := 0; i < b.N; i++ {
   753  		a.subMixed(&c)
   754  	}
   755  }
   756  
   757  func BenchmarkG1JacExtDoubleMixed(b *testing.B) {
   758  	var a g1JacExtended
   759  	a.doubleMixed(&g1GenAff)
   760  
   761  	var c G1Affine
   762  	c.FromJacobian(&g1Gen)
   763  	b.ResetTimer()
   764  	for i := 0; i < b.N; i++ {
   765  		a.doubleMixed(&c)
   766  	}
   767  }
   768  
   769  func BenchmarkG1JacExtDoubleNegMixed(b *testing.B) {
   770  	var a g1JacExtended
   771  	a.doubleMixed(&g1GenAff)
   772  
   773  	var c G1Affine
   774  	c.FromJacobian(&g1Gen)
   775  	b.ResetTimer()
   776  	for i := 0; i < b.N; i++ {
   777  		a.doubleNegMixed(&c)
   778  	}
   779  }
   780  
   781  func BenchmarkG1JacExtAdd(b *testing.B) {
   782  	var a, c g1JacExtended
   783  	a.doubleMixed(&g1GenAff)
   784  	c.double(&a)
   785  
   786  	b.ResetTimer()
   787  	for i := 0; i < b.N; i++ {
   788  		a.add(&c)
   789  	}
   790  }
   791  
   792  func BenchmarkG1JacExtDouble(b *testing.B) {
   793  	var a g1JacExtended
   794  	a.doubleMixed(&g1GenAff)
   795  
   796  	b.ResetTimer()
   797  	for i := 0; i < b.N; i++ {
   798  		a.double(&a)
   799  	}
   800  }
   801  
   802  func BenchmarkG1AffineAdd(b *testing.B) {
   803  	var a G1Affine
   804  	a.Double(&g1GenAff)
   805  	b.ResetTimer()
   806  	for i := 0; i < b.N; i++ {
   807  		a.Add(&a, &g1GenAff)
   808  	}
   809  }
   810  
   811  func BenchmarkG1AffineDouble(b *testing.B) {
   812  	var a G1Affine
   813  	a.Double(&g1GenAff)
   814  	b.ResetTimer()
   815  	for i := 0; i < b.N; i++ {
   816  		a.Double(&a)
   817  	}
   818  }
   819  
   820  func fuzzG1Jac(p *G1Jac, f fp.Element) G1Jac {
   821  	var res G1Jac
   822  	res.X.Mul(&p.X, &f).Mul(&res.X, &f)
   823  	res.Y.Mul(&p.Y, &f).Mul(&res.Y, &f).Mul(&res.Y, &f)
   824  	res.Z.Mul(&p.Z, &f)
   825  	return res
   826  }
   827  
   828  func fuzzg1JacExtended(p *g1JacExtended, f fp.Element) g1JacExtended {
   829  	var res g1JacExtended
   830  	var ff, fff fp.Element
   831  	ff.Square(&f)
   832  	fff.Mul(&ff, &f)
   833  	res.X.Mul(&p.X, &ff)
   834  	res.Y.Mul(&p.Y, &fff)
   835  	res.ZZ.Mul(&p.ZZ, &ff)
   836  	res.ZZZ.Mul(&p.ZZZ, &fff)
   837  	return res
   838  }