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