github.com/consensys/gnark-crypto@v0.14.0/ecc/bls24-315/internal/fptower/e24_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 package fptower 16 17 import ( 18 "math/big" 19 "testing" 20 21 "github.com/consensys/gnark-crypto/ecc/bls24-315/fp" 22 "github.com/leanovate/gopter" 23 "github.com/leanovate/gopter/prop" 24 ) 25 26 // ------------------------------------------------------------ 27 // tests 28 29 func TestE24Serialization(t *testing.T) { 30 31 parameters := gopter.DefaultTestParameters() 32 parameters.MinSuccessfulTests = 100 33 34 properties := gopter.NewProperties(parameters) 35 36 genA := GenE24() 37 38 properties.Property("[BLS24-315] SetBytes(Bytes()) should stay constant", prop.ForAll( 39 func(a *E24) bool { 40 var b E24 41 buf := a.Bytes() 42 if err := b.SetBytes(buf[:]); err != nil { 43 return false 44 } 45 return a.Equal(&b) 46 }, 47 genA, 48 )) 49 50 properties.TestingRun(t, gopter.ConsoleReporter(false)) 51 } 52 53 func TestE24ReceiverIsOperand(t *testing.T) { 54 55 parameters := gopter.DefaultTestParameters() 56 parameters.MinSuccessfulTests = 100 57 58 properties := gopter.NewProperties(parameters) 59 60 genA := GenE24() 61 genB := GenE24() 62 63 properties.Property("[BLS24-315] Having the receiver as operand (addition) should output the same result", prop.ForAll( 64 func(a, b *E24) bool { 65 var c, d E24 66 d.Set(a) 67 c.Add(a, b) 68 a.Add(a, b) 69 b.Add(&d, b) 70 return a.Equal(b) && a.Equal(&c) && b.Equal(&c) 71 }, 72 genA, 73 genB, 74 )) 75 76 properties.Property("[BLS24-315] Having the receiver as operand (sub) should output the same result", prop.ForAll( 77 func(a, b *E24) bool { 78 var c, d E24 79 d.Set(a) 80 c.Sub(a, b) 81 a.Sub(a, b) 82 b.Sub(&d, b) 83 return a.Equal(b) && a.Equal(&c) && b.Equal(&c) 84 }, 85 genA, 86 genB, 87 )) 88 89 properties.Property("[BLS24-315] Having the receiver as operand (mul) should output the same result", prop.ForAll( 90 func(a, b *E24) bool { 91 var c, d E24 92 d.Set(a) 93 c.Mul(a, b) 94 a.Mul(a, b) 95 b.Mul(&d, b) 96 return a.Equal(b) && a.Equal(&c) && b.Equal(&c) 97 }, 98 genA, 99 genB, 100 )) 101 102 properties.Property("[BLS24-315] Having the receiver as operand (square) should output the same result", prop.ForAll( 103 func(a *E24) bool { 104 var b E24 105 b.Square(a) 106 a.Square(a) 107 return a.Equal(&b) 108 }, 109 genA, 110 )) 111 112 properties.Property("[BLS24-315] Having the receiver as operand (double) should output the same result", prop.ForAll( 113 func(a *E24) bool { 114 var b E24 115 b.Double(a) 116 a.Double(a) 117 return a.Equal(&b) 118 }, 119 genA, 120 )) 121 122 properties.Property("[BLS24-315] Having the receiver as operand (Inverse) should output the same result", prop.ForAll( 123 func(a *E24) bool { 124 var b E24 125 b.Inverse(a) 126 a.Inverse(a) 127 return a.Equal(&b) 128 }, 129 genA, 130 )) 131 132 properties.Property("[BLS24-315] Having the receiver as operand (Cyclotomic square) should output the same result", prop.ForAll( 133 func(a *E24) bool { 134 var b E24 135 b.CyclotomicSquare(a) 136 a.CyclotomicSquare(a) 137 return a.Equal(&b) 138 }, 139 genA, 140 )) 141 142 properties.Property("[BLS24-315] Having the receiver as operand (Conjugate) should output the same result", prop.ForAll( 143 func(a *E24) bool { 144 var b E24 145 b.Conjugate(a) 146 a.Conjugate(a) 147 return a.Equal(&b) 148 }, 149 genA, 150 )) 151 152 properties.Property("[BLS24-315] Having the receiver as operand (Frobenius) should output the same result", prop.ForAll( 153 func(a *E24) bool { 154 var b E24 155 b.Frobenius(a) 156 a.Frobenius(a) 157 return a.Equal(&b) 158 }, 159 genA, 160 )) 161 162 properties.Property("[BLS24-315] Having the receiver as operand (FrobeniusSquare) should output the same result", prop.ForAll( 163 func(a *E24) bool { 164 var b E24 165 b.FrobeniusSquare(a) 166 a.FrobeniusSquare(a) 167 return a.Equal(&b) 168 }, 169 genA, 170 )) 171 172 properties.Property("[BLS24-315] Having the receiver as operand (FrobeniusQuad) should output the same result", prop.ForAll( 173 func(a *E24) bool { 174 var b E24 175 b.FrobeniusQuad(a) 176 a.FrobeniusQuad(a) 177 return a.Equal(&b) 178 }, 179 genA, 180 )) 181 182 properties.TestingRun(t, gopter.ConsoleReporter(false)) 183 } 184 185 func TestE24Ops(t *testing.T) { 186 187 parameters := gopter.DefaultTestParameters() 188 parameters.MinSuccessfulTests = 100 189 190 properties := gopter.NewProperties(parameters) 191 192 genA := GenE24() 193 genB := GenE24() 194 genExp := GenFp() 195 196 properties.Property("[BLS24-315] sub & add should leave an element invariant", prop.ForAll( 197 func(a, b *E24) bool { 198 var c E24 199 c.Set(a) 200 c.Add(&c, b).Sub(&c, b) 201 return c.Equal(a) 202 }, 203 genA, 204 genB, 205 )) 206 207 properties.Property("[BLS24-315] mul & inverse should leave an element invariant", prop.ForAll( 208 func(a, b *E24) bool { 209 var c, d E24 210 d.Inverse(b) 211 c.Set(a) 212 c.Mul(&c, b).Mul(&c, &d) 213 return c.Equal(a) 214 }, 215 genA, 216 genB, 217 )) 218 219 properties.Property("[BLS24-315] inverse twice should leave an element invariant", prop.ForAll( 220 func(a *E24) bool { 221 var b E24 222 b.Inverse(a).Inverse(&b) 223 return a.Equal(&b) 224 }, 225 genA, 226 )) 227 228 properties.Property("[BLS24-315] square and mul should output the same result", prop.ForAll( 229 func(a *E24) bool { 230 var b, c E24 231 b.Mul(a, a) 232 c.Square(a) 233 return b.Equal(&c) 234 }, 235 genA, 236 )) 237 238 properties.Property("[BLS24-315] a + pi(a), a-pi(a) should be real", prop.ForAll( 239 func(a *E24) bool { 240 var b, c, d E24 241 var e, f, g E12 242 b.Conjugate(a) 243 c.Add(a, &b) 244 d.Sub(a, &b) 245 e.Double(&a.D0) 246 f.Double(&a.D1) 247 return c.D1.Equal(&g) && d.D0.Equal(&g) && e.Equal(&c.D0) && f.Equal(&d.D1) 248 }, 249 genA, 250 )) 251 252 properties.Property("[BLS24-315] Torus-based Compress/decompress E24 elements in the cyclotomic subgroup", prop.ForAll( 253 func(a *E24) bool { 254 var b E24 255 b.Conjugate(a) 256 a.Inverse(a) 257 b.Mul(&b, a) 258 a.FrobeniusQuad(&b).Mul(a, &b) 259 260 c, _ := a.CompressTorus() 261 d := c.DecompressTorus() 262 return a.Equal(&d) 263 }, 264 genA, 265 )) 266 267 properties.Property("[BLS24-315] Torus-based batch Compress/decompress E24 elements in the cyclotomic subgroup", prop.ForAll( 268 func(a, e, f *E24) bool { 269 var b E24 270 b.Conjugate(a) 271 a.Inverse(a) 272 b.Mul(&b, a) 273 a.FrobeniusQuad(&b).Mul(a, &b) 274 275 e.CyclotomicSquare(a) 276 f.CyclotomicSquare(e) 277 278 c, _ := BatchCompressTorus([]E24{*a, *e, *f}) 279 d, _ := BatchDecompressTorus(c) 280 return a.Equal(&d[0]) && e.Equal(&d[1]) && f.Equal(&d[2]) 281 }, 282 genA, 283 genA, 284 genA, 285 )) 286 287 properties.Property("[BLS24-315] pi**24=id", prop.ForAll( 288 func(a *E24) bool { 289 var b E24 290 b.Frobenius(a). 291 Frobenius(&b). 292 Frobenius(&b). 293 Frobenius(&b). 294 Frobenius(&b). 295 Frobenius(&b). 296 Frobenius(&b). 297 Frobenius(&b). 298 Frobenius(&b). 299 Frobenius(&b). 300 Frobenius(&b). 301 Frobenius(&b). 302 Frobenius(&b). 303 Frobenius(&b). 304 Frobenius(&b). 305 Frobenius(&b). 306 Frobenius(&b). 307 Frobenius(&b). 308 Frobenius(&b). 309 Frobenius(&b). 310 Frobenius(&b). 311 Frobenius(&b). 312 Frobenius(&b). 313 Frobenius(&b) 314 return b.Equal(a) 315 }, 316 genA, 317 )) 318 319 properties.Property("[BLS24-315] (pi**2)**12=id", prop.ForAll( 320 func(a *E24) bool { 321 var b E24 322 b.FrobeniusSquare(a). 323 FrobeniusSquare(&b). 324 FrobeniusSquare(&b). 325 FrobeniusSquare(&b). 326 FrobeniusSquare(&b). 327 FrobeniusSquare(&b). 328 FrobeniusSquare(&b). 329 FrobeniusSquare(&b). 330 FrobeniusSquare(&b). 331 FrobeniusSquare(&b). 332 FrobeniusSquare(&b). 333 FrobeniusSquare(&b) 334 335 return b.Equal(a) 336 }, 337 genA, 338 )) 339 340 properties.Property("[BLS24-315] (pi**4)**6=id", prop.ForAll( 341 func(a *E24) bool { 342 var b E24 343 b.FrobeniusQuad(a). 344 FrobeniusQuad(&b). 345 FrobeniusQuad(&b). 346 FrobeniusQuad(&b). 347 FrobeniusQuad(&b). 348 FrobeniusQuad(&b) 349 350 return b.Equal(a) 351 }, 352 genA, 353 )) 354 355 properties.Property("[BLS24-315] cyclotomic square (Granger-Scott) and square should be the same in the cyclotomic subgroup", prop.ForAll( 356 func(a *E24) bool { 357 var b, c, d E24 358 b.Conjugate(a) 359 a.Inverse(a) 360 b.Mul(&b, a) 361 a.FrobeniusQuad(&b).Mul(a, &b) 362 c.Square(a) 363 d.CyclotomicSquare(a) 364 return c.Equal(&d) 365 }, 366 genA, 367 )) 368 369 properties.Property("[BLS24-315] compressed cyclotomic square (Karabina) and square should be the same in the cyclotomic subgroup", prop.ForAll( 370 func(a *E24) bool { 371 var _a, b, c, d, _c, _d E24 372 _a.SetOne().Double(&_a) 373 374 // put a and _a in the cyclotomic subgroup 375 // a (g3 != 0 probably) 376 b.Conjugate(a) 377 a.Inverse(a) 378 b.Mul(&b, a) 379 a.FrobeniusQuad(&b).Mul(a, &b) 380 // _a (g3 == 0) 381 b.Conjugate(&_a) 382 _a.Inverse(&_a) 383 b.Mul(&b, &_a) 384 _a.FrobeniusQuad(&b).Mul(&_a, &b) 385 386 // case g3 != 0 387 c.Square(a) 388 d.CyclotomicSquareCompressed(a).DecompressKarabina(&d) 389 390 // case g3 == 0 391 _c.Square(&_a) 392 _d.CyclotomicSquareCompressed(&_a).DecompressKarabina(&_d) 393 394 return c.Equal(&d) 395 }, 396 genA, 397 )) 398 399 properties.Property("[BLS24-315] batch decompress and individual decompress (Karabina) should be the same", prop.ForAll( 400 func(a *E24) bool { 401 var _a, b E24 402 _a.SetOne().Double(&_a) 403 404 // put a and _a in the cyclotomic subgroup 405 // a (g3 !=0 probably) 406 b.Conjugate(a) 407 a.Inverse(a) 408 b.Mul(&b, a) 409 a.FrobeniusQuad(&b).Mul(a, &b) 410 // _a (g3 == 0) 411 b.Conjugate(&_a) 412 _a.Inverse(&_a) 413 b.Mul(&b, &_a) 414 _a.FrobeniusQuad(&b).Mul(&_a, &b) 415 416 var a2, a4, a17 E24 417 a2.Set(&_a) 418 a4.Set(a) 419 a17.Set(a) 420 a2.nSquareCompressed(2) // case g3 == 0 421 a4.nSquareCompressed(4) 422 a17.nSquareCompressed(17) 423 batch := BatchDecompressKarabina([]E24{a2, a4, a17}) 424 a2.DecompressKarabina(&a2) 425 a4.DecompressKarabina(&a4) 426 a17.DecompressKarabina(&a17) 427 428 return a2.Equal(&batch[0]) && a4.Equal(&batch[1]) && a17.Equal(&batch[2]) 429 }, 430 genA, 431 )) 432 433 properties.Property("[BLS24-315] Exp and CyclotomicExp results must be the same in the cyclotomic subgroup", prop.ForAll( 434 func(a *E24, e fp.Element) bool { 435 var b, c, d E24 436 // put in the cyclo subgroup 437 b.Conjugate(a) 438 a.Inverse(a) 439 b.Mul(&b, a) 440 a.FrobeniusQuad(&b).Mul(a, &b) 441 442 var _e big.Int 443 k := new(big.Int).SetUint64(24) 444 e.Exp(e, k) 445 e.BigInt(&_e) 446 447 c.Exp(*a, &_e) 448 d.CyclotomicExp(*a, &_e) 449 450 return c.Equal(&d) 451 }, 452 genA, 453 genExp, 454 )) 455 456 properties.Property("[BLS24-315] Frobenius of x in E24 should be equal to x^q", prop.ForAll( 457 func(a *E24) bool { 458 var b, c E24 459 q := fp.Modulus() 460 b.Frobenius(a) 461 c.Set(a) 462 c.Exp(c, q) 463 return c.Equal(&b) 464 }, 465 genA, 466 )) 467 468 properties.Property("[BLS24-315] FrobeniusSquare of x in E24 should be equal to x^(q^2)", prop.ForAll( 469 func(a *E24) bool { 470 var b, c E24 471 q := fp.Modulus() 472 b.FrobeniusSquare(a) 473 c.Exp(*a, q).Exp(c, q) 474 return c.Equal(&b) 475 }, 476 genA, 477 )) 478 479 properties.Property("[BLS24-315] FrobeniusQuad of x in E24 should be equal to x^(q^4)", prop.ForAll( 480 func(a *E24) bool { 481 var b, c E24 482 q := fp.Modulus() 483 b.FrobeniusQuad(a) 484 c.Exp(*a, q).Exp(c, q).Exp(c, q).Exp(c, q) 485 return c.Equal(&b) 486 }, 487 genA, 488 )) 489 490 properties.TestingRun(t, gopter.ConsoleReporter(false)) 491 492 } 493 494 // ------------------------------------------------------------ 495 // benches 496 497 func BenchmarkE24Add(b *testing.B) { 498 var a, c E24 499 a.SetRandom() 500 c.SetRandom() 501 b.ResetTimer() 502 for i := 0; i < b.N; i++ { 503 a.Add(&a, &c) 504 } 505 } 506 507 func BenchmarkE24Sub(b *testing.B) { 508 var a, c E24 509 a.SetRandom() 510 c.SetRandom() 511 b.ResetTimer() 512 for i := 0; i < b.N; i++ { 513 a.Sub(&a, &c) 514 } 515 } 516 517 func BenchmarkE24Mul(b *testing.B) { 518 var a, c E24 519 a.SetRandom() 520 c.SetRandom() 521 b.ResetTimer() 522 for i := 0; i < b.N; i++ { 523 a.Mul(&a, &c) 524 } 525 } 526 527 func BenchmarkE24Cyclosquare(b *testing.B) { 528 var a E24 529 a.SetRandom() 530 b.ResetTimer() 531 for i := 0; i < b.N; i++ { 532 a.CyclotomicSquare(&a) 533 } 534 } 535 536 func BenchmarkE24Square(b *testing.B) { 537 var a E24 538 a.SetRandom() 539 b.ResetTimer() 540 for i := 0; i < b.N; i++ { 541 a.Square(&a) 542 } 543 } 544 545 func BenchmarkE24Inverse(b *testing.B) { 546 var a E24 547 a.SetRandom() 548 b.ResetTimer() 549 for i := 0; i < b.N; i++ { 550 a.Inverse(&a) 551 } 552 } 553 554 func BenchmarkE24Conjugate(b *testing.B) { 555 var a E24 556 a.SetRandom() 557 b.ResetTimer() 558 for i := 0; i < b.N; i++ { 559 a.Conjugate(&a) 560 } 561 } 562 563 func BenchmarkE24Frobenius(b *testing.B) { 564 var a E24 565 a.SetRandom() 566 b.ResetTimer() 567 for i := 0; i < b.N; i++ { 568 a.Frobenius(&a) 569 } 570 } 571 572 func BenchmarkE24FrobeniusSquare(b *testing.B) { 573 var a E24 574 a.SetRandom() 575 b.ResetTimer() 576 for i := 0; i < b.N; i++ { 577 a.FrobeniusSquare(&a) 578 } 579 } 580 581 func BenchmarkE24FrobeniusQuad(b *testing.B) { 582 var a E24 583 a.SetRandom() 584 b.ResetTimer() 585 for i := 0; i < b.N; i++ { 586 a.FrobeniusQuad(&a) 587 } 588 } 589 590 func BenchmarkE24Expt(b *testing.B) { 591 var a E24 592 a.SetRandom() 593 b.ResetTimer() 594 for i := 0; i < b.N; i++ { 595 a.Expt(&a) 596 } 597 }