github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-756/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 bw6756
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  	"math/rand/v2"
    23  	"testing"
    24  
    25  	"github.com/consensys/gnark-crypto/ecc/bw6-756/fp"
    26  
    27  	"github.com/consensys/gnark-crypto/ecc/bw6-756/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("[BW6-756] 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("[BW6-756] 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("[BW6-756] 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("[BW6-756] 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("[BW6-756] 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("[BW6-756] 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("[BW6-756] 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("[BW6-756] 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("[BW6-756] 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("[BW6-756] 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("[BW6-756] 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("[BW6-756] [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("[BW6-756] 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("[BW6-756] 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("[BW6-756] 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("[BW6-756] 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("[BW6-756] [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("[BW6-756] [-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("[BW6-756] [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("[BW6-756] [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("[BW6-756] [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("[BW6-756] [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("[BW6-756] [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("[BW6-756] [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("[BW6-756] 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("[BW6-756] 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("[BW6-756] 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("[BW6-756] 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 TestG1AffineCofactorCleaning(t *testing.T) {
   514  	t.Parallel()
   515  	parameters := gopter.DefaultTestParameters()
   516  	if testing.Short() {
   517  		parameters.MinSuccessfulTests = nbFuzzShort
   518  	} else {
   519  		parameters.MinSuccessfulTests = nbFuzz
   520  	}
   521  
   522  	properties := gopter.NewProperties(parameters)
   523  
   524  	properties.Property("[BW6-756] Clearing the cofactor of a random point should set it in the r-torsion", prop.ForAll(
   525  		func() bool {
   526  			var a, x, b fp.Element
   527  			a.SetRandom()
   528  
   529  			x.Square(&a).Mul(&x, &a).Add(&x, &bCurveCoeff)
   530  
   531  			for x.Legendre() != 1 {
   532  				a.SetRandom()
   533  
   534  				x.Square(&a).Mul(&x, &a).Add(&x, &bCurveCoeff)
   535  
   536  			}
   537  
   538  			b.Sqrt(&x)
   539  			var point, pointCleared, infinity G1Jac
   540  			point.X.Set(&a)
   541  			point.Y.Set(&b)
   542  			point.Z.SetOne()
   543  			pointCleared.ClearCofactor(&point)
   544  			infinity.Set(&g1Infinity)
   545  			return point.IsOnCurve() && pointCleared.IsInSubGroup() && !pointCleared.Equal(&infinity)
   546  		},
   547  	))
   548  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   549  
   550  }
   551  
   552  func TestG1AffineBatchScalarMultiplication(t *testing.T) {
   553  
   554  	parameters := gopter.DefaultTestParameters()
   555  	if testing.Short() {
   556  		parameters.MinSuccessfulTests = nbFuzzShort
   557  	} else {
   558  		parameters.MinSuccessfulTests = nbFuzzShort
   559  	}
   560  
   561  	properties := gopter.NewProperties(parameters)
   562  
   563  	genScalar := GenFr()
   564  
   565  	// size of the multiExps
   566  	const nbSamples = 10
   567  
   568  	properties.Property("[BW6-756] BatchScalarMultiplication should be consistent with individual scalar multiplications", prop.ForAll(
   569  		func(mixer fr.Element) bool {
   570  			// mixer ensures that all the words of a fpElement are set
   571  			var sampleScalars [nbSamples]fr.Element
   572  
   573  			for i := 1; i <= nbSamples; i++ {
   574  				sampleScalars[i-1].SetUint64(uint64(i)).
   575  					Mul(&sampleScalars[i-1], &mixer)
   576  			}
   577  
   578  			result := BatchScalarMultiplicationG1(&g1GenAff, sampleScalars[:])
   579  
   580  			if len(result) != len(sampleScalars) {
   581  				return false
   582  			}
   583  
   584  			for i := 0; i < len(result); i++ {
   585  				var expectedJac G1Jac
   586  				var expected G1Affine
   587  				var b big.Int
   588  				expectedJac.ScalarMultiplication(&g1Gen, sampleScalars[i].BigInt(&b))
   589  				expected.FromJacobian(&expectedJac)
   590  				if !result[i].Equal(&expected) {
   591  					return false
   592  				}
   593  			}
   594  			return true
   595  		},
   596  		genScalar,
   597  	))
   598  
   599  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   600  }
   601  
   602  // ------------------------------------------------------------
   603  // benches
   604  
   605  func BenchmarkG1JacIsInSubGroup(b *testing.B) {
   606  	var a G1Jac
   607  	a.Set(&g1Gen)
   608  	b.ResetTimer()
   609  	for i := 0; i < b.N; i++ {
   610  		a.IsInSubGroup()
   611  	}
   612  
   613  }
   614  
   615  func BenchmarkG1JacEqual(b *testing.B) {
   616  	var scalar fp.Element
   617  	if _, err := scalar.SetRandom(); err != nil {
   618  		b.Fatalf("failed to set scalar: %s", err)
   619  	}
   620  
   621  	var a G1Jac
   622  	a.ScalarMultiplication(&g1Gen, big.NewInt(42))
   623  
   624  	b.Run("equal", func(b *testing.B) {
   625  		var scalarSquared fp.Element
   626  		scalarSquared.Square(&scalar)
   627  
   628  		aZScaled := a
   629  		aZScaled.X.Mul(&aZScaled.X, &scalarSquared)
   630  		aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar)
   631  		aZScaled.Z.Mul(&aZScaled.Z, &scalar)
   632  
   633  		// Check the setup.
   634  		if !a.Equal(&aZScaled) {
   635  			b.Fatalf("invalid test setup")
   636  		}
   637  
   638  		b.ResetTimer()
   639  		for i := 0; i < b.N; i++ {
   640  			a.Equal(&aZScaled)
   641  		}
   642  	})
   643  
   644  	b.Run("not equal", func(b *testing.B) {
   645  		var aPlus1 G1Jac
   646  		aPlus1.AddAssign(&g1Gen)
   647  
   648  		// Check the setup.
   649  		if a.Equal(&aPlus1) {
   650  			b.Fatalf("invalid test setup")
   651  		}
   652  
   653  		b.ResetTimer()
   654  		for i := 0; i < b.N; i++ {
   655  			a.Equal(&aPlus1)
   656  		}
   657  	})
   658  }
   659  
   660  func BenchmarkBatchAddG1Affine(b *testing.B) {
   661  
   662  	var P, R pG1AffineC16
   663  	var RR ppG1AffineC16
   664  	ridx := make([]int, len(P))
   665  
   666  	// TODO P == R may produce skewed benches
   667  	fillBenchBasesG1(P[:])
   668  	fillBenchBasesG1(R[:])
   669  
   670  	for i := 0; i < len(ridx); i++ {
   671  		ridx[i] = i
   672  	}
   673  
   674  	// random permute
   675  	rand.Shuffle(len(ridx), func(i, j int) { ridx[i], ridx[j] = ridx[j], ridx[i] })
   676  
   677  	for i, ri := range ridx {
   678  		RR[i] = &R[ri]
   679  	}
   680  
   681  	b.ResetTimer()
   682  	for i := 0; i < b.N; i++ {
   683  		batchAddG1Affine[pG1AffineC16, ppG1AffineC16, cG1AffineC16](&RR, &P, len(P))
   684  	}
   685  }
   686  
   687  func BenchmarkG1AffineBatchScalarMultiplication(b *testing.B) {
   688  	// ensure every words of the scalars are filled
   689  	var mixer fr.Element
   690  	mixer.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487")
   691  
   692  	const pow = 15
   693  	const nbSamples = 1 << pow
   694  
   695  	var sampleScalars [nbSamples]fr.Element
   696  
   697  	for i := 1; i <= nbSamples; i++ {
   698  		sampleScalars[i-1].SetUint64(uint64(i)).
   699  			Mul(&sampleScalars[i-1], &mixer)
   700  	}
   701  
   702  	for i := 5; i <= pow; i++ {
   703  		using := 1 << i
   704  
   705  		b.Run(fmt.Sprintf("%d points", using), func(b *testing.B) {
   706  			b.ResetTimer()
   707  			for j := 0; j < b.N; j++ {
   708  				_ = BatchScalarMultiplicationG1(&g1GenAff, sampleScalars[:using])
   709  			}
   710  		})
   711  	}
   712  }
   713  
   714  func BenchmarkG1JacScalarMultiplication(b *testing.B) {
   715  
   716  	var scalar big.Int
   717  	r := fr.Modulus()
   718  	scalar.SetString("5243587517512619047944770508185965837690552500527637822603658699938581184513", 10)
   719  	scalar.Add(&scalar, r)
   720  
   721  	var doubleAndAdd G1Jac
   722  
   723  	b.Run("double and add", func(b *testing.B) {
   724  		b.ResetTimer()
   725  		for j := 0; j < b.N; j++ {
   726  			doubleAndAdd.mulWindowed(&g1Gen, &scalar)
   727  		}
   728  	})
   729  
   730  	var glv G1Jac
   731  	b.Run("GLV", func(b *testing.B) {
   732  		b.ResetTimer()
   733  		for j := 0; j < b.N; j++ {
   734  			glv.mulGLV(&g1Gen, &scalar)
   735  		}
   736  	})
   737  
   738  }
   739  
   740  func BenchmarkG1AffineCofactorClearing(b *testing.B) {
   741  	var a G1Jac
   742  	a.Set(&g1Gen)
   743  	for i := 0; i < b.N; i++ {
   744  		a.ClearCofactor(&a)
   745  	}
   746  }
   747  
   748  func BenchmarkG1JacAdd(b *testing.B) {
   749  	var a G1Jac
   750  	a.Double(&g1Gen)
   751  	b.ResetTimer()
   752  	for i := 0; i < b.N; i++ {
   753  		a.AddAssign(&g1Gen)
   754  	}
   755  }
   756  
   757  func BenchmarkG1JacAddMixed(b *testing.B) {
   758  	var a G1Jac
   759  	a.Double(&g1Gen)
   760  
   761  	var c G1Affine
   762  	c.FromJacobian(&g1Gen)
   763  	b.ResetTimer()
   764  	for i := 0; i < b.N; i++ {
   765  		a.AddMixed(&c)
   766  	}
   767  
   768  }
   769  
   770  func BenchmarkG1JacDouble(b *testing.B) {
   771  	var a G1Jac
   772  	a.Set(&g1Gen)
   773  	b.ResetTimer()
   774  	for i := 0; i < b.N; i++ {
   775  		a.DoubleAssign()
   776  	}
   777  
   778  }
   779  
   780  func BenchmarkG1JacExtAddMixed(b *testing.B) {
   781  	var a g1JacExtended
   782  	a.doubleMixed(&g1GenAff)
   783  
   784  	var c G1Affine
   785  	c.FromJacobian(&g1Gen)
   786  	b.ResetTimer()
   787  	for i := 0; i < b.N; i++ {
   788  		a.addMixed(&c)
   789  	}
   790  }
   791  
   792  func BenchmarkG1JacExtSubMixed(b *testing.B) {
   793  	var a g1JacExtended
   794  	a.doubleMixed(&g1GenAff)
   795  
   796  	var c G1Affine
   797  	c.FromJacobian(&g1Gen)
   798  	b.ResetTimer()
   799  	for i := 0; i < b.N; i++ {
   800  		a.subMixed(&c)
   801  	}
   802  }
   803  
   804  func BenchmarkG1JacExtDoubleMixed(b *testing.B) {
   805  	var a g1JacExtended
   806  	a.doubleMixed(&g1GenAff)
   807  
   808  	var c G1Affine
   809  	c.FromJacobian(&g1Gen)
   810  	b.ResetTimer()
   811  	for i := 0; i < b.N; i++ {
   812  		a.doubleMixed(&c)
   813  	}
   814  }
   815  
   816  func BenchmarkG1JacExtDoubleNegMixed(b *testing.B) {
   817  	var a g1JacExtended
   818  	a.doubleMixed(&g1GenAff)
   819  
   820  	var c G1Affine
   821  	c.FromJacobian(&g1Gen)
   822  	b.ResetTimer()
   823  	for i := 0; i < b.N; i++ {
   824  		a.doubleNegMixed(&c)
   825  	}
   826  }
   827  
   828  func BenchmarkG1JacExtAdd(b *testing.B) {
   829  	var a, c g1JacExtended
   830  	a.doubleMixed(&g1GenAff)
   831  	c.double(&a)
   832  
   833  	b.ResetTimer()
   834  	for i := 0; i < b.N; i++ {
   835  		a.add(&c)
   836  	}
   837  }
   838  
   839  func BenchmarkG1JacExtDouble(b *testing.B) {
   840  	var a g1JacExtended
   841  	a.doubleMixed(&g1GenAff)
   842  
   843  	b.ResetTimer()
   844  	for i := 0; i < b.N; i++ {
   845  		a.double(&a)
   846  	}
   847  }
   848  
   849  func BenchmarkG1AffineAdd(b *testing.B) {
   850  	var a G1Affine
   851  	a.Double(&g1GenAff)
   852  	b.ResetTimer()
   853  	for i := 0; i < b.N; i++ {
   854  		a.Add(&a, &g1GenAff)
   855  	}
   856  }
   857  
   858  func BenchmarkG1AffineDouble(b *testing.B) {
   859  	var a G1Affine
   860  	a.Double(&g1GenAff)
   861  	b.ResetTimer()
   862  	for i := 0; i < b.N; i++ {
   863  		a.Double(&a)
   864  	}
   865  }
   866  
   867  func fuzzG1Jac(p *G1Jac, f fp.Element) G1Jac {
   868  	var res G1Jac
   869  	res.X.Mul(&p.X, &f).Mul(&res.X, &f)
   870  	res.Y.Mul(&p.Y, &f).Mul(&res.Y, &f).Mul(&res.Y, &f)
   871  	res.Z.Mul(&p.Z, &f)
   872  	return res
   873  }
   874  
   875  func fuzzg1JacExtended(p *g1JacExtended, f fp.Element) g1JacExtended {
   876  	var res g1JacExtended
   877  	var ff, fff fp.Element
   878  	ff.Square(&f)
   879  	fff.Mul(&ff, &f)
   880  	res.X.Mul(&p.X, &ff)
   881  	res.Y.Mul(&p.Y, &fff)
   882  	res.ZZ.Mul(&p.ZZ, &ff)
   883  	res.ZZZ.Mul(&p.ZZZ, &fff)
   884  	return res
   885  }