github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-756/pairing_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  	"testing"
    23  
    24  	"github.com/consensys/gnark-crypto/ecc/bw6-756/fp"
    25  	"github.com/consensys/gnark-crypto/ecc/bw6-756/fr"
    26  	"github.com/leanovate/gopter"
    27  	"github.com/leanovate/gopter/prop"
    28  )
    29  
    30  // ------------------------------------------------------------
    31  // tests
    32  
    33  func TestPairing(t *testing.T) {
    34  
    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  	genA := GenE6()
    46  
    47  	genR1 := GenFr()
    48  	genR2 := GenFr()
    49  
    50  	properties.Property("[BW6-756] Having the receiver as operand (final expo) should output the same result", prop.ForAll(
    51  		func(a GT) bool {
    52  			b := FinalExponentiation(&a)
    53  			a = FinalExponentiation(&a)
    54  			return a.Equal(&b)
    55  		},
    56  		genA,
    57  	))
    58  
    59  	properties.Property("[BW6-756] Exponentiating FinalExpo(a) to r should output 1", prop.ForAll(
    60  		func(a GT) bool {
    61  			b := FinalExponentiation(&a)
    62  			return !a.IsInSubGroup() && b.IsInSubGroup()
    63  		},
    64  		genA,
    65  	))
    66  
    67  	properties.Property("[BW6-756] Exp, CyclotomicExp and ExpGLV results must be the same in GT (small and big exponents)", prop.ForAll(
    68  		func(a GT, e fr.Element) bool {
    69  
    70  			var res bool
    71  
    72  			// exponent > r
    73  			{
    74  				a = FinalExponentiation(&a)
    75  				var _e big.Int
    76  				_e.SetString("169893631828481842931290008859743243489098146141979830311893424751855271950692001433356165550548410610101138388623573573742608490725625288296502860183437011025036209791574001140592327223981416956942076610555083128655330944007957223952510233203018053264066056080064687038560794652180979019775788172491868553073169893631828481842931290008859743243489098146141979830311893424751855271950692001433356165550548410610101138388623573573742608490725625288296502860183437011025036209791574001140592327223981416956942076610555083128655330944007957223952510233203018053264066056080064687038560794652180979019775788172491868553073", 10)
    77  				var b, c, d GT
    78  				b.Exp(a, &_e)
    79  				c.ExpGLV(a, &_e)
    80  				d.CyclotomicExp(a, &_e)
    81  				res = b.Equal(&c) && c.Equal(&d)
    82  			}
    83  
    84  			// exponent < r
    85  			{
    86  				a = FinalExponentiation(&a)
    87  				var _e big.Int
    88  				e.BigInt(&_e)
    89  				var b, c, d GT
    90  				b.Exp(a, &_e)
    91  				c.ExpGLV(a, &_e)
    92  				d.CyclotomicExp(a, &_e)
    93  				res = res && b.Equal(&c) && c.Equal(&d)
    94  			}
    95  
    96  			return res
    97  		},
    98  		genA,
    99  		genR1,
   100  	))
   101  
   102  	properties.Property("[BW6-756] Expt(Expt) and Exp(t^2) should output the same result in the cyclotomic subgroup", prop.ForAll(
   103  		func(a GT) bool {
   104  			var b, c, d GT
   105  			b.Conjugate(&a)
   106  			a.Inverse(&a)
   107  			b.Mul(&b, &a)
   108  
   109  			a.Frobenius(&b).
   110  				Mul(&a, &b)
   111  
   112  			c.Expt(&a).Expt(&c)
   113  			d.Exp(a, &xGen).Exp(d, &xGen)
   114  			return c.Equal(&d)
   115  		},
   116  		genA,
   117  	))
   118  
   119  	properties.Property("[BW6-756] bilinearity", prop.ForAll(
   120  		func(a, b fr.Element) bool {
   121  
   122  			var res, resa, resb, resab, zero GT
   123  
   124  			var ag1 G1Affine
   125  			var bg2 G2Affine
   126  
   127  			var abigint, bbigint, ab big.Int
   128  
   129  			a.BigInt(&abigint)
   130  			b.BigInt(&bbigint)
   131  			ab.Mul(&abigint, &bbigint)
   132  
   133  			ag1.ScalarMultiplication(&g1GenAff, &abigint)
   134  			bg2.ScalarMultiplication(&g2GenAff, &bbigint)
   135  
   136  			res, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{g2GenAff})
   137  			resa, _ = Pair([]G1Affine{ag1}, []G2Affine{g2GenAff})
   138  			resb, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{bg2})
   139  
   140  			resab.Exp(res, &ab)
   141  			resa.Exp(resa, &bbigint)
   142  			resb.Exp(resb, &abigint)
   143  
   144  			return resab.Equal(&resa) && resab.Equal(&resb) && !res.Equal(&zero)
   145  
   146  		},
   147  		genR1,
   148  		genR2,
   149  	))
   150  
   151  	properties.Property("[BW6-756] PairingCheck", prop.ForAll(
   152  		func(a, b fr.Element) bool {
   153  
   154  			var g1GenAffNeg G1Affine
   155  			g1GenAffNeg.Neg(&g1GenAff)
   156  			tabP := []G1Affine{g1GenAff, g1GenAffNeg}
   157  			tabQ := []G2Affine{g2GenAff, g2GenAff}
   158  
   159  			res, _ := PairingCheck(tabP, tabQ)
   160  
   161  			return res
   162  		},
   163  		genR1,
   164  		genR2,
   165  	))
   166  
   167  	properties.Property("[BW6-756] Pair should output the same result with MillerLoop or MillerLoopFixedQ", prop.ForAll(
   168  		func(a, b fr.Element) bool {
   169  
   170  			var ag1 G1Affine
   171  			var bg2 G2Affine
   172  
   173  			var abigint, bbigint big.Int
   174  
   175  			a.BigInt(&abigint)
   176  			b.BigInt(&bbigint)
   177  
   178  			ag1.ScalarMultiplication(&g1GenAff, &abigint)
   179  			bg2.ScalarMultiplication(&g2GenAff, &bbigint)
   180  
   181  			P := []G1Affine{g1GenAff, ag1}
   182  			Q := []G2Affine{g2GenAff, bg2}
   183  
   184  			ml1, _ := MillerLoop(P, Q)
   185  			ml2, _ := MillerLoopFixedQ(
   186  				P,
   187  				[][2][len(LoopCounter) - 1]LineEvaluationAff{
   188  					PrecomputeLines(Q[0]),
   189  					PrecomputeLines(Q[1]),
   190  				})
   191  
   192  			res1 := FinalExponentiation(&ml1)
   193  			res2 := FinalExponentiation(&ml2)
   194  
   195  			return res1.Equal(&res2)
   196  		},
   197  		genR1,
   198  		genR2,
   199  	))
   200  
   201  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   202  }
   203  
   204  func TestMillerLoop(t *testing.T) {
   205  
   206  	t.Parallel()
   207  	parameters := gopter.DefaultTestParameters()
   208  	if testing.Short() {
   209  		parameters.MinSuccessfulTests = nbFuzzShort
   210  	} else {
   211  		parameters.MinSuccessfulTests = nbFuzz
   212  	}
   213  
   214  	properties := gopter.NewProperties(parameters)
   215  
   216  	genR1 := GenFr()
   217  	genR2 := GenFr()
   218  
   219  	properties.Property("[BW6-756] MillerLoop of pairs should be equal to the product of MillerLoops", prop.ForAll(
   220  		func(a, b fr.Element) bool {
   221  
   222  			var simpleProd, factorizedProd GT
   223  
   224  			var ag1 G1Affine
   225  			var bg2 G2Affine
   226  
   227  			var abigint, bbigint big.Int
   228  
   229  			a.BigInt(&abigint)
   230  			b.BigInt(&bbigint)
   231  
   232  			ag1.ScalarMultiplication(&g1GenAff, &abigint)
   233  			bg2.ScalarMultiplication(&g2GenAff, &bbigint)
   234  
   235  			P0 := []G1Affine{g1GenAff}
   236  			P1 := []G1Affine{ag1}
   237  			Q0 := []G2Affine{g2GenAff}
   238  			Q1 := []G2Affine{bg2}
   239  
   240  			// FE( ML(a,b) * ML(c,d) * ML(e,f) * ML(g,h) )
   241  			M1, _ := MillerLoop(P0, Q0)
   242  			M2, _ := MillerLoop(P1, Q0)
   243  			M3, _ := MillerLoop(P0, Q1)
   244  			M4, _ := MillerLoop(P1, Q1)
   245  			simpleProd.Mul(&M1, &M2).Mul(&simpleProd, &M3).Mul(&simpleProd, &M4)
   246  			simpleProd = FinalExponentiation(&simpleProd)
   247  
   248  			tabP := []G1Affine{g1GenAff, ag1, g1GenAff, ag1}
   249  			tabQ := []G2Affine{g2GenAff, g2GenAff, bg2, bg2}
   250  
   251  			// FE( ML([a,c,e,g] ; [b,d,f,h]) ) -> saves 3 squares in Fqk
   252  			factorizedProd, _ = Pair(tabP, tabQ)
   253  
   254  			return simpleProd.Equal(&factorizedProd)
   255  		},
   256  		genR1,
   257  		genR2,
   258  	))
   259  
   260  	properties.Property("[BW6-756] MillerLoop and MillerLoopFixedQ should skip pairs with a point at infinity", prop.ForAll(
   261  		func(a, b fr.Element) bool {
   262  
   263  			var one GT
   264  
   265  			var ag1, g1Inf G1Affine
   266  			var bg2, g2Inf G2Affine
   267  
   268  			var abigint, bbigint big.Int
   269  
   270  			one.SetOne()
   271  
   272  			a.BigInt(&abigint)
   273  			b.BigInt(&bbigint)
   274  
   275  			ag1.ScalarMultiplication(&g1GenAff, &abigint)
   276  			bg2.ScalarMultiplication(&g2GenAff, &bbigint)
   277  
   278  			g1Inf.FromJacobian(&g1Infinity)
   279  			g2Inf.FromJacobian(&g2Infinity)
   280  
   281  			// e([0,c] ; [b,d])
   282  			// -> should be equal to e(c,d)
   283  			tabP := []G1Affine{g1Inf, ag1}
   284  			tabQ := []G2Affine{g2GenAff, bg2}
   285  			res1, _ := Pair(tabP, tabQ)
   286  
   287  			// e([a,c] ; [0,d])
   288  			// -> should be equal to e(c,d)
   289  			tabP = []G1Affine{g1GenAff, ag1}
   290  			tabQ = []G2Affine{g2Inf, bg2}
   291  			res2, _ := Pair(tabP, tabQ)
   292  
   293  			// e([0,c] ; [b,d]) with fixed points b and d
   294  			// -> should be equal to e(c,d)
   295  			tabP = []G1Affine{g1Inf, ag1}
   296  			linesQ := [][2][len(LoopCounter) - 1]LineEvaluationAff{
   297  				PrecomputeLines(g2GenAff),
   298  				PrecomputeLines(bg2),
   299  			}
   300  			res3, _ := PairFixedQ(tabP, linesQ)
   301  
   302  			// e([a,c] ; [0,d]) with fixed points 0 and d
   303  			// -> should be equal to e(c,d)
   304  			tabP = []G1Affine{g1GenAff, ag1}
   305  			linesQ = [][2][len(LoopCounter) - 1]LineEvaluationAff{
   306  				PrecomputeLines(g2Inf),
   307  				PrecomputeLines(bg2),
   308  			}
   309  			res4, _ := PairFixedQ(tabP, linesQ)
   310  
   311  			// e([0,c] ; [d,0])
   312  			// -> should be equal to 1
   313  			tabP = []G1Affine{g1Inf, ag1}
   314  			tabQ = []G2Affine{bg2, g2Inf}
   315  			res5, _ := Pair(tabP, tabQ)
   316  
   317  			// e([0,c] ; [d,0]) with fixed points d and 0
   318  			// -> should be equal to 1
   319  			tabP = []G1Affine{g1Inf, ag1}
   320  			linesQ = [][2][len(LoopCounter) - 1]LineEvaluationAff{
   321  				PrecomputeLines(bg2),
   322  				PrecomputeLines(g2Inf),
   323  			}
   324  			res6, _ := PairFixedQ(tabP, linesQ)
   325  
   326  			// e([0,0])
   327  			// -> should be equal to 1
   328  			tabP = []G1Affine{g1Inf}
   329  			tabQ = []G2Affine{g2Inf}
   330  			res7, _ := Pair(tabP, tabQ)
   331  
   332  			// e([0,0]) with fixed point 0
   333  			// -> should be equal to 1
   334  			tabP = []G1Affine{g1Inf}
   335  			linesQ = [][2][len(LoopCounter) - 1]LineEvaluationAff{
   336  				PrecomputeLines(g2Inf),
   337  			}
   338  			res8, _ := PairFixedQ(tabP, linesQ)
   339  
   340  			return res1.Equal(&res2) && res2.Equal(&res3) && res3.Equal(&res4) &&
   341  				res5.Equal(&one) && res6.Equal(&one) && res7.Equal(&one) && res8.Equal(&one)
   342  		},
   343  		genR1,
   344  		genR2,
   345  	))
   346  
   347  	properties.Property("[BW6-756] compressed pairing", prop.ForAll(
   348  		func(a, b fr.Element) bool {
   349  
   350  			var ag1 G1Affine
   351  			var bg2 G2Affine
   352  
   353  			var abigint, bbigint big.Int
   354  
   355  			a.BigInt(&abigint)
   356  			b.BigInt(&bbigint)
   357  
   358  			ag1.ScalarMultiplication(&g1GenAff, &abigint)
   359  			bg2.ScalarMultiplication(&g2GenAff, &bbigint)
   360  
   361  			res, _ := Pair([]G1Affine{ag1}, []G2Affine{bg2})
   362  
   363  			compressed, _ := res.CompressTorus()
   364  			decompressed := compressed.DecompressTorus()
   365  
   366  			return decompressed.Equal(&res)
   367  
   368  		},
   369  		genR1,
   370  		genR2,
   371  	))
   372  
   373  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   374  }
   375  
   376  // ------------------------------------------------------------
   377  // benches
   378  
   379  func BenchmarkPairing(b *testing.B) {
   380  
   381  	var g1GenAff G1Affine
   382  	var g2GenAff G2Affine
   383  
   384  	g1GenAff.FromJacobian(&g1Gen)
   385  	g2GenAff.FromJacobian(&g2Gen)
   386  
   387  	b.ResetTimer()
   388  	for i := 0; i < b.N; i++ {
   389  		Pair([]G1Affine{g1GenAff}, []G2Affine{g2GenAff})
   390  	}
   391  }
   392  
   393  func BenchmarkMillerLoop(b *testing.B) {
   394  
   395  	var g1GenAff G1Affine
   396  	var g2GenAff G2Affine
   397  
   398  	g1GenAff.FromJacobian(&g1Gen)
   399  	g2GenAff.FromJacobian(&g2Gen)
   400  
   401  	b.ResetTimer()
   402  	for i := 0; i < b.N; i++ {
   403  		MillerLoop([]G1Affine{g1GenAff}, []G2Affine{g2GenAff})
   404  	}
   405  }
   406  
   407  func BenchmarkFinalExponentiation(b *testing.B) {
   408  
   409  	var a GT
   410  	a.SetRandom()
   411  
   412  	b.ResetTimer()
   413  	for i := 0; i < b.N; i++ {
   414  		FinalExponentiation(&a)
   415  	}
   416  
   417  }
   418  
   419  func BenchmarkMultiMiller(b *testing.B) {
   420  
   421  	var g1GenAff G1Affine
   422  	var g2GenAff G2Affine
   423  
   424  	g1GenAff.FromJacobian(&g1Gen)
   425  	g2GenAff.FromJacobian(&g2Gen)
   426  
   427  	n := 10
   428  	P := make([]G1Affine, n)
   429  	Q := make([]G2Affine, n)
   430  
   431  	for i := 2; i <= n; i++ {
   432  		for j := 0; j < i; j++ {
   433  			P[j].Set(&g1GenAff)
   434  			Q[j].Set(&g2GenAff)
   435  		}
   436  		b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) {
   437  			b.ResetTimer()
   438  			for i := 0; i < b.N; i++ {
   439  				MillerLoop(P, Q)
   440  			}
   441  		})
   442  	}
   443  }
   444  
   445  func BenchmarkMultiPair(b *testing.B) {
   446  
   447  	var g1GenAff G1Affine
   448  	var g2GenAff G2Affine
   449  
   450  	g1GenAff.FromJacobian(&g1Gen)
   451  	g2GenAff.FromJacobian(&g2Gen)
   452  
   453  	n := 10
   454  	P := make([]G1Affine, n)
   455  	Q := make([]G2Affine, n)
   456  
   457  	for i := 2; i <= n; i++ {
   458  		for j := 0; j < i; j++ {
   459  			P[j].Set(&g1GenAff)
   460  			Q[j].Set(&g2GenAff)
   461  		}
   462  		b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) {
   463  			b.ResetTimer()
   464  			for i := 0; i < b.N; i++ {
   465  				Pair(P, Q)
   466  			}
   467  		})
   468  	}
   469  }
   470  
   471  func BenchmarkExpGT(b *testing.B) {
   472  
   473  	var a GT
   474  	a.SetRandom()
   475  	a = FinalExponentiation(&a)
   476  
   477  	var e fp.Element
   478  	e.SetRandom()
   479  
   480  	k := new(big.Int).SetUint64(12)
   481  	e.Exp(e, k)
   482  	var _e big.Int
   483  	e.BigInt(&_e)
   484  
   485  	b.Run("Naive windowed Exp", func(b *testing.B) {
   486  		b.ResetTimer()
   487  		for i := 0; i < b.N; i++ {
   488  			a.Exp(a, &_e)
   489  		}
   490  	})
   491  
   492  	b.Run("2-NAF cyclotomic Exp", func(b *testing.B) {
   493  		b.ResetTimer()
   494  		for i := 0; i < b.N; i++ {
   495  			a.CyclotomicExp(a, &_e)
   496  		}
   497  	})
   498  
   499  	b.Run("windowed 2-dim GLV Exp", func(b *testing.B) {
   500  		b.ResetTimer()
   501  		for i := 0; i < b.N; i++ {
   502  			a.ExpGLV(a, &_e)
   503  		}
   504  	})
   505  }