github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-761/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 bw6761 18 19 import ( 20 "fmt" 21 "math/big" 22 "testing" 23 24 "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" 25 "github.com/consensys/gnark-crypto/ecc/bw6-761/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-761] 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-761] 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-761] 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-761] 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-761] 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-761] 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-761] 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-761] 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-761] 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-761] 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(6) 481 482 e.Exp(e, k) 483 var _e big.Int 484 e.BigInt(&_e) 485 486 b.Run("Naive windowed Exp", func(b *testing.B) { 487 b.ResetTimer() 488 for i := 0; i < b.N; i++ { 489 a.Exp(a, &_e) 490 } 491 }) 492 493 b.Run("2-NAF cyclotomic Exp", func(b *testing.B) { 494 b.ResetTimer() 495 for i := 0; i < b.N; i++ { 496 a.CyclotomicExp(a, &_e) 497 } 498 }) 499 500 b.Run("windowed 2-dim GLV Exp", func(b *testing.B) { 501 b.ResetTimer() 502 for i := 0; i < b.N; i++ { 503 a.ExpGLV(a, &_e) 504 } 505 }) 506 }