github.com/consensys/gnark-crypto@v0.14.0/ecc/bls24-317/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-317/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-317] 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-317] 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-317] 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-317] 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-317] 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-317] 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-317] 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-317] 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-317] 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-317] 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-317] 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-317] 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-317] 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-317] 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-317] 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-317] 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-317] 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-317] 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-317] (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-317] (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-317] 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-317] 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] Exp and CyclotomicExp results must be the same in the cyclotomic subgroup", prop.ForAll( 400 func(a *E24, e fp.Element) bool { 401 var b, c, d E24 402 // put in the cyclo subgroup 403 b.Conjugate(a) 404 a.Inverse(a) 405 b.Mul(&b, a) 406 a.FrobeniusQuad(&b).Mul(a, &b) 407 408 var _e big.Int 409 k := new(big.Int).SetUint64(24) 410 e.Exp(e, k) 411 e.BigInt(&_e) 412 413 c.Exp(*a, &_e) 414 d.CyclotomicExp(*a, &_e) 415 416 return c.Equal(&d) 417 }, 418 genA, 419 genExp, 420 )) 421 422 properties.Property("[BLS24-317] Frobenius of x in E24 should be equal to x^q", prop.ForAll( 423 func(a *E24) bool { 424 var b, c E24 425 q := fp.Modulus() 426 b.Frobenius(a) 427 c.Set(a) 428 c.Exp(c, q) 429 return c.Equal(&b) 430 }, 431 genA, 432 )) 433 434 properties.Property("[BLS24-317] FrobeniusSquare of x in E24 should be equal to x^(q^2)", prop.ForAll( 435 func(a *E24) bool { 436 var b, c E24 437 q := fp.Modulus() 438 b.FrobeniusSquare(a) 439 c.Exp(*a, q).Exp(c, q) 440 return c.Equal(&b) 441 }, 442 genA, 443 )) 444 445 properties.Property("[BLS24-317] FrobeniusQuad of x in E24 should be equal to x^(q^4)", prop.ForAll( 446 func(a *E24) bool { 447 var b, c E24 448 q := fp.Modulus() 449 b.FrobeniusQuad(a) 450 c.Exp(*a, q).Exp(c, q).Exp(c, q).Exp(c, q) 451 return c.Equal(&b) 452 }, 453 genA, 454 )) 455 456 properties.Property("[BLS24-317] MulBy014 and Mul by (c0, c1, 0, 0, c4, 0) should output the same result", prop.ForAll( 457 func(a, b *E24) bool { 458 var c E24 459 b.D0.C2.SetZero() 460 b.D1.C0.SetZero() 461 b.D1.C2.SetZero() 462 c.Mul(a, b) 463 a.MulBy014(&b.D0.C0, &b.D0.C1, &b.D1.C1) 464 return c.Equal(a) 465 }, 466 genA, 467 genA, 468 )) 469 470 properties.TestingRun(t, gopter.ConsoleReporter(false)) 471 472 } 473 474 // ------------------------------------------------------------ 475 // benches 476 477 func BenchmarkE24Add(b *testing.B) { 478 var a, c E24 479 a.SetRandom() 480 c.SetRandom() 481 b.ResetTimer() 482 for i := 0; i < b.N; i++ { 483 a.Add(&a, &c) 484 } 485 } 486 487 func BenchmarkE24Sub(b *testing.B) { 488 var a, c E24 489 a.SetRandom() 490 c.SetRandom() 491 b.ResetTimer() 492 for i := 0; i < b.N; i++ { 493 a.Sub(&a, &c) 494 } 495 } 496 497 func BenchmarkE24Mul(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.Mul(&a, &c) 504 } 505 } 506 507 func BenchmarkE24Cyclosquare(b *testing.B) { 508 var a E24 509 a.SetRandom() 510 b.ResetTimer() 511 for i := 0; i < b.N; i++ { 512 a.CyclotomicSquare(&a) 513 } 514 } 515 516 func BenchmarkE24Square(b *testing.B) { 517 var a E24 518 a.SetRandom() 519 b.ResetTimer() 520 for i := 0; i < b.N; i++ { 521 a.Square(&a) 522 } 523 } 524 525 func BenchmarkE24Inverse(b *testing.B) { 526 var a E24 527 a.SetRandom() 528 b.ResetTimer() 529 for i := 0; i < b.N; i++ { 530 a.Inverse(&a) 531 } 532 } 533 534 func BenchmarkE24Conjugate(b *testing.B) { 535 var a E24 536 a.SetRandom() 537 b.ResetTimer() 538 for i := 0; i < b.N; i++ { 539 a.Conjugate(&a) 540 } 541 } 542 543 func BenchmarkE24Frobenius(b *testing.B) { 544 var a E24 545 a.SetRandom() 546 b.ResetTimer() 547 for i := 0; i < b.N; i++ { 548 a.Frobenius(&a) 549 } 550 } 551 552 func BenchmarkE24FrobeniusSquare(b *testing.B) { 553 var a E24 554 a.SetRandom() 555 b.ResetTimer() 556 for i := 0; i < b.N; i++ { 557 a.FrobeniusSquare(&a) 558 } 559 } 560 561 func BenchmarkE24FrobeniusQuad(b *testing.B) { 562 var a E24 563 a.SetRandom() 564 b.ResetTimer() 565 for i := 0; i < b.N; i++ { 566 a.FrobeniusQuad(&a) 567 } 568 } 569 570 func BenchmarkE24Expt(b *testing.B) { 571 var a E24 572 a.SetRandom() 573 b.ResetTimer() 574 for i := 0; i < b.N; i++ { 575 a.Expt(&a) 576 } 577 }