github.com/consensys/gnark-crypto@v0.14.0/ecc/secp256k1/fr/element_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 fr 18 19 import ( 20 "crypto/rand" 21 "encoding/json" 22 "fmt" 23 "math/big" 24 "math/bits" 25 26 "testing" 27 28 "github.com/leanovate/gopter" 29 ggen "github.com/leanovate/gopter/gen" 30 "github.com/leanovate/gopter/prop" 31 32 "github.com/stretchr/testify/require" 33 ) 34 35 // ------------------------------------------------------------------------------------------------- 36 // benchmarks 37 // most benchmarks are rudimentary and should sample a large number of random inputs 38 // or be run multiple times to ensure it didn't measure the fastest path of the function 39 40 var benchResElement Element 41 42 func BenchmarkElementSelect(b *testing.B) { 43 var x, y Element 44 x.SetRandom() 45 y.SetRandom() 46 47 b.ResetTimer() 48 for i := 0; i < b.N; i++ { 49 benchResElement.Select(i%3, &x, &y) 50 } 51 } 52 53 func BenchmarkElementSetRandom(b *testing.B) { 54 var x Element 55 x.SetRandom() 56 57 b.ResetTimer() 58 for i := 0; i < b.N; i++ { 59 _, _ = x.SetRandom() 60 } 61 } 62 63 func BenchmarkElementSetBytes(b *testing.B) { 64 var x Element 65 x.SetRandom() 66 bb := x.Bytes() 67 b.ResetTimer() 68 69 for i := 0; i < b.N; i++ { 70 benchResElement.SetBytes(bb[:]) 71 } 72 73 } 74 75 func BenchmarkElementMulByConstants(b *testing.B) { 76 b.Run("mulBy3", func(b *testing.B) { 77 benchResElement.SetRandom() 78 b.ResetTimer() 79 for i := 0; i < b.N; i++ { 80 MulBy3(&benchResElement) 81 } 82 }) 83 b.Run("mulBy5", func(b *testing.B) { 84 benchResElement.SetRandom() 85 b.ResetTimer() 86 for i := 0; i < b.N; i++ { 87 MulBy5(&benchResElement) 88 } 89 }) 90 b.Run("mulBy13", func(b *testing.B) { 91 benchResElement.SetRandom() 92 b.ResetTimer() 93 for i := 0; i < b.N; i++ { 94 MulBy13(&benchResElement) 95 } 96 }) 97 } 98 99 func BenchmarkElementInverse(b *testing.B) { 100 var x Element 101 x.SetRandom() 102 benchResElement.SetRandom() 103 b.ResetTimer() 104 105 for i := 0; i < b.N; i++ { 106 benchResElement.Inverse(&x) 107 } 108 109 } 110 111 func BenchmarkElementButterfly(b *testing.B) { 112 var x Element 113 x.SetRandom() 114 benchResElement.SetRandom() 115 b.ResetTimer() 116 for i := 0; i < b.N; i++ { 117 Butterfly(&x, &benchResElement) 118 } 119 } 120 121 func BenchmarkElementExp(b *testing.B) { 122 var x Element 123 x.SetRandom() 124 benchResElement.SetRandom() 125 b1, _ := rand.Int(rand.Reader, Modulus()) 126 b.ResetTimer() 127 for i := 0; i < b.N; i++ { 128 benchResElement.Exp(x, b1) 129 } 130 } 131 132 func BenchmarkElementDouble(b *testing.B) { 133 benchResElement.SetRandom() 134 b.ResetTimer() 135 for i := 0; i < b.N; i++ { 136 benchResElement.Double(&benchResElement) 137 } 138 } 139 140 func BenchmarkElementAdd(b *testing.B) { 141 var x Element 142 x.SetRandom() 143 benchResElement.SetRandom() 144 b.ResetTimer() 145 for i := 0; i < b.N; i++ { 146 benchResElement.Add(&x, &benchResElement) 147 } 148 } 149 150 func BenchmarkElementSub(b *testing.B) { 151 var x Element 152 x.SetRandom() 153 benchResElement.SetRandom() 154 b.ResetTimer() 155 for i := 0; i < b.N; i++ { 156 benchResElement.Sub(&x, &benchResElement) 157 } 158 } 159 160 func BenchmarkElementNeg(b *testing.B) { 161 benchResElement.SetRandom() 162 b.ResetTimer() 163 for i := 0; i < b.N; i++ { 164 benchResElement.Neg(&benchResElement) 165 } 166 } 167 168 func BenchmarkElementDiv(b *testing.B) { 169 var x Element 170 x.SetRandom() 171 benchResElement.SetRandom() 172 b.ResetTimer() 173 for i := 0; i < b.N; i++ { 174 benchResElement.Div(&x, &benchResElement) 175 } 176 } 177 178 func BenchmarkElementFromMont(b *testing.B) { 179 benchResElement.SetRandom() 180 b.ResetTimer() 181 for i := 0; i < b.N; i++ { 182 benchResElement.fromMont() 183 } 184 } 185 186 func BenchmarkElementSquare(b *testing.B) { 187 benchResElement.SetRandom() 188 b.ResetTimer() 189 for i := 0; i < b.N; i++ { 190 benchResElement.Square(&benchResElement) 191 } 192 } 193 194 func BenchmarkElementSqrt(b *testing.B) { 195 var a Element 196 a.SetUint64(4) 197 a.Neg(&a) 198 b.ResetTimer() 199 for i := 0; i < b.N; i++ { 200 benchResElement.Sqrt(&a) 201 } 202 } 203 204 func BenchmarkElementMul(b *testing.B) { 205 x := Element{ 206 9902555850136342848, 207 8364476168144746616, 208 16616019711348246470, 209 11342065889886772165, 210 } 211 benchResElement.SetOne() 212 b.ResetTimer() 213 for i := 0; i < b.N; i++ { 214 benchResElement.Mul(&benchResElement, &x) 215 } 216 } 217 218 func BenchmarkElementCmp(b *testing.B) { 219 x := Element{ 220 9902555850136342848, 221 8364476168144746616, 222 16616019711348246470, 223 11342065889886772165, 224 } 225 benchResElement = x 226 benchResElement[0] = 0 227 b.ResetTimer() 228 for i := 0; i < b.N; i++ { 229 benchResElement.Cmp(&x) 230 } 231 } 232 233 func TestElementCmp(t *testing.T) { 234 var x, y Element 235 236 if x.Cmp(&y) != 0 { 237 t.Fatal("x == y") 238 } 239 240 one := One() 241 y.Sub(&y, &one) 242 243 if x.Cmp(&y) != -1 { 244 t.Fatal("x < y") 245 } 246 if y.Cmp(&x) != 1 { 247 t.Fatal("x < y") 248 } 249 250 x = y 251 if x.Cmp(&y) != 0 { 252 t.Fatal("x == y") 253 } 254 255 x.Sub(&x, &one) 256 if x.Cmp(&y) != -1 { 257 t.Fatal("x < y") 258 } 259 if y.Cmp(&x) != 1 { 260 t.Fatal("x < y") 261 } 262 } 263 func TestElementIsRandom(t *testing.T) { 264 for i := 0; i < 50; i++ { 265 var x, y Element 266 x.SetRandom() 267 y.SetRandom() 268 if x.Equal(&y) { 269 t.Fatal("2 random numbers are unlikely to be equal") 270 } 271 } 272 } 273 274 func TestElementIsUint64(t *testing.T) { 275 t.Parallel() 276 parameters := gopter.DefaultTestParameters() 277 if testing.Short() { 278 parameters.MinSuccessfulTests = nbFuzzShort 279 } else { 280 parameters.MinSuccessfulTests = nbFuzz 281 } 282 283 properties := gopter.NewProperties(parameters) 284 285 properties.Property("reduce should output a result smaller than modulus", prop.ForAll( 286 func(v uint64) bool { 287 var e Element 288 e.SetUint64(v) 289 290 if !e.IsUint64() { 291 return false 292 } 293 294 return e.Uint64() == v 295 }, 296 ggen.UInt64(), 297 )) 298 299 properties.TestingRun(t, gopter.ConsoleReporter(false)) 300 } 301 302 func TestElementNegZero(t *testing.T) { 303 var a, b Element 304 b.SetZero() 305 for a.IsZero() { 306 a.SetRandom() 307 } 308 a.Neg(&b) 309 if !a.IsZero() { 310 t.Fatal("neg(0) != 0") 311 } 312 } 313 314 // ------------------------------------------------------------------------------------------------- 315 // Gopter tests 316 // most of them are generated with a template 317 318 const ( 319 nbFuzzShort = 200 320 nbFuzz = 1000 321 ) 322 323 // special values to be used in tests 324 var staticTestValues []Element 325 326 func init() { 327 staticTestValues = append(staticTestValues, Element{}) // zero 328 staticTestValues = append(staticTestValues, One()) // one 329 staticTestValues = append(staticTestValues, rSquare) // r² 330 var e, one Element 331 one.SetOne() 332 e.Sub(&qElement, &one) 333 staticTestValues = append(staticTestValues, e) // q - 1 334 e.Double(&one) 335 staticTestValues = append(staticTestValues, e) // 2 336 337 { 338 a := qElement 339 a[0]-- 340 staticTestValues = append(staticTestValues, a) 341 } 342 staticTestValues = append(staticTestValues, Element{0}) 343 staticTestValues = append(staticTestValues, Element{0, 0}) 344 staticTestValues = append(staticTestValues, Element{1}) 345 staticTestValues = append(staticTestValues, Element{0, 1}) 346 staticTestValues = append(staticTestValues, Element{2}) 347 staticTestValues = append(staticTestValues, Element{0, 2}) 348 349 { 350 a := qElement 351 a[3]-- 352 staticTestValues = append(staticTestValues, a) 353 } 354 { 355 a := qElement 356 a[3]-- 357 a[0]++ 358 staticTestValues = append(staticTestValues, a) 359 } 360 361 { 362 a := qElement 363 a[3] = 0 364 staticTestValues = append(staticTestValues, a) 365 } 366 367 } 368 369 func TestElementReduce(t *testing.T) { 370 testValues := make([]Element, len(staticTestValues)) 371 copy(testValues, staticTestValues) 372 373 for i := range testValues { 374 s := testValues[i] 375 expected := s 376 reduce(&s) 377 _reduceGeneric(&expected) 378 if !s.Equal(&expected) { 379 t.Fatal("reduce failed: asm and generic impl don't match") 380 } 381 } 382 383 t.Parallel() 384 parameters := gopter.DefaultTestParameters() 385 if testing.Short() { 386 parameters.MinSuccessfulTests = nbFuzzShort 387 } else { 388 parameters.MinSuccessfulTests = nbFuzz 389 } 390 391 properties := gopter.NewProperties(parameters) 392 393 genA := genFull() 394 395 properties.Property("reduce should output a result smaller than modulus", prop.ForAll( 396 func(a Element) bool { 397 b := a 398 reduce(&a) 399 _reduceGeneric(&b) 400 return a.smallerThanModulus() && a.Equal(&b) 401 }, 402 genA, 403 )) 404 405 properties.TestingRun(t, gopter.ConsoleReporter(false)) 406 407 } 408 409 func TestElementEqual(t *testing.T) { 410 t.Parallel() 411 parameters := gopter.DefaultTestParameters() 412 if testing.Short() { 413 parameters.MinSuccessfulTests = nbFuzzShort 414 } else { 415 parameters.MinSuccessfulTests = nbFuzz 416 } 417 418 properties := gopter.NewProperties(parameters) 419 420 genA := gen() 421 genB := gen() 422 423 properties.Property("x.Equal(&y) iff x == y; likely false for random pairs", prop.ForAll( 424 func(a testPairElement, b testPairElement) bool { 425 return a.element.Equal(&b.element) == (a.element == b.element) 426 }, 427 genA, 428 genB, 429 )) 430 431 properties.Property("x.Equal(&y) if x == y", prop.ForAll( 432 func(a testPairElement) bool { 433 b := a.element 434 return a.element.Equal(&b) 435 }, 436 genA, 437 )) 438 439 properties.TestingRun(t, gopter.ConsoleReporter(false)) 440 } 441 442 func TestElementBytes(t *testing.T) { 443 t.Parallel() 444 parameters := gopter.DefaultTestParameters() 445 if testing.Short() { 446 parameters.MinSuccessfulTests = nbFuzzShort 447 } else { 448 parameters.MinSuccessfulTests = nbFuzz 449 } 450 451 properties := gopter.NewProperties(parameters) 452 453 genA := gen() 454 455 properties.Property("SetBytes(Bytes()) should stay constant", prop.ForAll( 456 func(a testPairElement) bool { 457 var b Element 458 bytes := a.element.Bytes() 459 b.SetBytes(bytes[:]) 460 return a.element.Equal(&b) 461 }, 462 genA, 463 )) 464 465 properties.TestingRun(t, gopter.ConsoleReporter(false)) 466 } 467 468 func TestElementInverseExp(t *testing.T) { 469 // inverse must be equal to exp^-2 470 exp := Modulus() 471 exp.Sub(exp, new(big.Int).SetUint64(2)) 472 473 invMatchExp := func(a testPairElement) bool { 474 var b Element 475 b.Set(&a.element) 476 a.element.Inverse(&a.element) 477 b.Exp(b, exp) 478 479 return a.element.Equal(&b) 480 } 481 482 t.Parallel() 483 parameters := gopter.DefaultTestParameters() 484 if testing.Short() { 485 parameters.MinSuccessfulTests = nbFuzzShort 486 } else { 487 parameters.MinSuccessfulTests = nbFuzz 488 } 489 properties := gopter.NewProperties(parameters) 490 genA := gen() 491 properties.Property("inv == exp^-2", prop.ForAll(invMatchExp, genA)) 492 properties.TestingRun(t, gopter.ConsoleReporter(false)) 493 494 parameters.MinSuccessfulTests = 1 495 properties = gopter.NewProperties(parameters) 496 properties.Property("inv(0) == 0", prop.ForAll(invMatchExp, ggen.OneConstOf(testPairElement{}))) 497 properties.TestingRun(t, gopter.ConsoleReporter(false)) 498 499 } 500 501 func mulByConstant(z *Element, c uint8) { 502 var y Element 503 y.SetUint64(uint64(c)) 504 z.Mul(z, &y) 505 } 506 507 func TestElementMulByConstants(t *testing.T) { 508 509 t.Parallel() 510 parameters := gopter.DefaultTestParameters() 511 if testing.Short() { 512 parameters.MinSuccessfulTests = nbFuzzShort 513 } else { 514 parameters.MinSuccessfulTests = nbFuzz 515 } 516 517 properties := gopter.NewProperties(parameters) 518 519 genA := gen() 520 521 implemented := []uint8{0, 1, 2, 3, 5, 13} 522 properties.Property("mulByConstant", prop.ForAll( 523 func(a testPairElement) bool { 524 for _, c := range implemented { 525 var constant Element 526 constant.SetUint64(uint64(c)) 527 528 b := a.element 529 b.Mul(&b, &constant) 530 531 aa := a.element 532 mulByConstant(&aa, c) 533 534 if !aa.Equal(&b) { 535 return false 536 } 537 } 538 539 return true 540 }, 541 genA, 542 )) 543 544 properties.Property("MulBy3(x) == Mul(x, 3)", prop.ForAll( 545 func(a testPairElement) bool { 546 var constant Element 547 constant.SetUint64(3) 548 549 b := a.element 550 b.Mul(&b, &constant) 551 552 MulBy3(&a.element) 553 554 return a.element.Equal(&b) 555 }, 556 genA, 557 )) 558 559 properties.Property("MulBy5(x) == Mul(x, 5)", prop.ForAll( 560 func(a testPairElement) bool { 561 var constant Element 562 constant.SetUint64(5) 563 564 b := a.element 565 b.Mul(&b, &constant) 566 567 MulBy5(&a.element) 568 569 return a.element.Equal(&b) 570 }, 571 genA, 572 )) 573 574 properties.Property("MulBy13(x) == Mul(x, 13)", prop.ForAll( 575 func(a testPairElement) bool { 576 var constant Element 577 constant.SetUint64(13) 578 579 b := a.element 580 b.Mul(&b, &constant) 581 582 MulBy13(&a.element) 583 584 return a.element.Equal(&b) 585 }, 586 genA, 587 )) 588 589 properties.TestingRun(t, gopter.ConsoleReporter(false)) 590 591 } 592 593 func TestElementLegendre(t *testing.T) { 594 t.Parallel() 595 parameters := gopter.DefaultTestParameters() 596 if testing.Short() { 597 parameters.MinSuccessfulTests = nbFuzzShort 598 } else { 599 parameters.MinSuccessfulTests = nbFuzz 600 } 601 602 properties := gopter.NewProperties(parameters) 603 604 genA := gen() 605 606 properties.Property("legendre should output same result than big.Int.Jacobi", prop.ForAll( 607 func(a testPairElement) bool { 608 return a.element.Legendre() == big.Jacobi(&a.bigint, Modulus()) 609 }, 610 genA, 611 )) 612 613 properties.TestingRun(t, gopter.ConsoleReporter(false)) 614 615 } 616 617 func TestElementBitLen(t *testing.T) { 618 t.Parallel() 619 parameters := gopter.DefaultTestParameters() 620 if testing.Short() { 621 parameters.MinSuccessfulTests = nbFuzzShort 622 } else { 623 parameters.MinSuccessfulTests = nbFuzz 624 } 625 626 properties := gopter.NewProperties(parameters) 627 628 genA := gen() 629 630 properties.Property("BitLen should output same result than big.Int.BitLen", prop.ForAll( 631 func(a testPairElement) bool { 632 return a.element.fromMont().BitLen() == a.bigint.BitLen() 633 }, 634 genA, 635 )) 636 637 properties.TestingRun(t, gopter.ConsoleReporter(false)) 638 639 } 640 641 func TestElementButterflies(t *testing.T) { 642 643 t.Parallel() 644 parameters := gopter.DefaultTestParameters() 645 if testing.Short() { 646 parameters.MinSuccessfulTests = nbFuzzShort 647 } else { 648 parameters.MinSuccessfulTests = nbFuzz 649 } 650 651 properties := gopter.NewProperties(parameters) 652 653 genA := gen() 654 655 properties.Property("butterfly0 == a -b; a +b", prop.ForAll( 656 func(a, b testPairElement) bool { 657 a0, b0 := a.element, b.element 658 659 _butterflyGeneric(&a.element, &b.element) 660 Butterfly(&a0, &b0) 661 662 return a.element.Equal(&a0) && b.element.Equal(&b0) 663 }, 664 genA, 665 genA, 666 )) 667 668 properties.TestingRun(t, gopter.ConsoleReporter(false)) 669 670 } 671 672 func TestElementLexicographicallyLargest(t *testing.T) { 673 t.Parallel() 674 parameters := gopter.DefaultTestParameters() 675 if testing.Short() { 676 parameters.MinSuccessfulTests = nbFuzzShort 677 } else { 678 parameters.MinSuccessfulTests = nbFuzz 679 } 680 681 properties := gopter.NewProperties(parameters) 682 683 genA := gen() 684 685 properties.Property("element.Cmp should match LexicographicallyLargest output", prop.ForAll( 686 func(a testPairElement) bool { 687 var negA Element 688 negA.Neg(&a.element) 689 690 cmpResult := a.element.Cmp(&negA) 691 lResult := a.element.LexicographicallyLargest() 692 693 if lResult && cmpResult == 1 { 694 return true 695 } 696 if !lResult && cmpResult != 1 { 697 return true 698 } 699 return false 700 }, 701 genA, 702 )) 703 704 properties.TestingRun(t, gopter.ConsoleReporter(false)) 705 706 } 707 708 func TestElementAdd(t *testing.T) { 709 t.Parallel() 710 parameters := gopter.DefaultTestParameters() 711 if testing.Short() { 712 parameters.MinSuccessfulTests = nbFuzzShort 713 } else { 714 parameters.MinSuccessfulTests = nbFuzz 715 } 716 717 properties := gopter.NewProperties(parameters) 718 719 genA := gen() 720 genB := gen() 721 722 properties.Property("Add: having the receiver as operand should output the same result", prop.ForAll( 723 func(a, b testPairElement) bool { 724 var c, d Element 725 d.Set(&a.element) 726 727 c.Add(&a.element, &b.element) 728 a.element.Add(&a.element, &b.element) 729 b.element.Add(&d, &b.element) 730 731 return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c) 732 }, 733 genA, 734 genB, 735 )) 736 737 properties.Property("Add: operation result must match big.Int result", prop.ForAll( 738 func(a, b testPairElement) bool { 739 { 740 var c Element 741 742 c.Add(&a.element, &b.element) 743 744 var d, e big.Int 745 d.Add(&a.bigint, &b.bigint).Mod(&d, Modulus()) 746 747 if c.BigInt(&e).Cmp(&d) != 0 { 748 return false 749 } 750 } 751 752 // fixed elements 753 // a is random 754 // r takes special values 755 testValues := make([]Element, len(staticTestValues)) 756 copy(testValues, staticTestValues) 757 758 for i := range testValues { 759 r := testValues[i] 760 var d, e, rb big.Int 761 r.BigInt(&rb) 762 763 var c Element 764 c.Add(&a.element, &r) 765 d.Add(&a.bigint, &rb).Mod(&d, Modulus()) 766 767 if c.BigInt(&e).Cmp(&d) != 0 { 768 return false 769 } 770 } 771 return true 772 }, 773 genA, 774 genB, 775 )) 776 777 properties.Property("Add: operation result must be smaller than modulus", prop.ForAll( 778 func(a, b testPairElement) bool { 779 var c Element 780 781 c.Add(&a.element, &b.element) 782 783 return c.smallerThanModulus() 784 }, 785 genA, 786 genB, 787 )) 788 789 specialValueTest := func() { 790 // test special values against special values 791 testValues := make([]Element, len(staticTestValues)) 792 copy(testValues, staticTestValues) 793 794 for i := range testValues { 795 a := testValues[i] 796 var aBig big.Int 797 a.BigInt(&aBig) 798 for j := range testValues { 799 b := testValues[j] 800 var bBig, d, e big.Int 801 b.BigInt(&bBig) 802 803 var c Element 804 c.Add(&a, &b) 805 d.Add(&aBig, &bBig).Mod(&d, Modulus()) 806 807 if c.BigInt(&e).Cmp(&d) != 0 { 808 t.Fatal("Add failed special test values") 809 } 810 } 811 } 812 } 813 814 properties.TestingRun(t, gopter.ConsoleReporter(false)) 815 specialValueTest() 816 817 } 818 819 func TestElementSub(t *testing.T) { 820 t.Parallel() 821 parameters := gopter.DefaultTestParameters() 822 if testing.Short() { 823 parameters.MinSuccessfulTests = nbFuzzShort 824 } else { 825 parameters.MinSuccessfulTests = nbFuzz 826 } 827 828 properties := gopter.NewProperties(parameters) 829 830 genA := gen() 831 genB := gen() 832 833 properties.Property("Sub: having the receiver as operand should output the same result", prop.ForAll( 834 func(a, b testPairElement) bool { 835 var c, d Element 836 d.Set(&a.element) 837 838 c.Sub(&a.element, &b.element) 839 a.element.Sub(&a.element, &b.element) 840 b.element.Sub(&d, &b.element) 841 842 return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c) 843 }, 844 genA, 845 genB, 846 )) 847 848 properties.Property("Sub: operation result must match big.Int result", prop.ForAll( 849 func(a, b testPairElement) bool { 850 { 851 var c Element 852 853 c.Sub(&a.element, &b.element) 854 855 var d, e big.Int 856 d.Sub(&a.bigint, &b.bigint).Mod(&d, Modulus()) 857 858 if c.BigInt(&e).Cmp(&d) != 0 { 859 return false 860 } 861 } 862 863 // fixed elements 864 // a is random 865 // r takes special values 866 testValues := make([]Element, len(staticTestValues)) 867 copy(testValues, staticTestValues) 868 869 for i := range testValues { 870 r := testValues[i] 871 var d, e, rb big.Int 872 r.BigInt(&rb) 873 874 var c Element 875 c.Sub(&a.element, &r) 876 d.Sub(&a.bigint, &rb).Mod(&d, Modulus()) 877 878 if c.BigInt(&e).Cmp(&d) != 0 { 879 return false 880 } 881 } 882 return true 883 }, 884 genA, 885 genB, 886 )) 887 888 properties.Property("Sub: operation result must be smaller than modulus", prop.ForAll( 889 func(a, b testPairElement) bool { 890 var c Element 891 892 c.Sub(&a.element, &b.element) 893 894 return c.smallerThanModulus() 895 }, 896 genA, 897 genB, 898 )) 899 900 specialValueTest := func() { 901 // test special values against special values 902 testValues := make([]Element, len(staticTestValues)) 903 copy(testValues, staticTestValues) 904 905 for i := range testValues { 906 a := testValues[i] 907 var aBig big.Int 908 a.BigInt(&aBig) 909 for j := range testValues { 910 b := testValues[j] 911 var bBig, d, e big.Int 912 b.BigInt(&bBig) 913 914 var c Element 915 c.Sub(&a, &b) 916 d.Sub(&aBig, &bBig).Mod(&d, Modulus()) 917 918 if c.BigInt(&e).Cmp(&d) != 0 { 919 t.Fatal("Sub failed special test values") 920 } 921 } 922 } 923 } 924 925 properties.TestingRun(t, gopter.ConsoleReporter(false)) 926 specialValueTest() 927 928 } 929 930 func TestElementMul(t *testing.T) { 931 t.Parallel() 932 parameters := gopter.DefaultTestParameters() 933 if testing.Short() { 934 parameters.MinSuccessfulTests = nbFuzzShort 935 } else { 936 parameters.MinSuccessfulTests = nbFuzz 937 } 938 939 properties := gopter.NewProperties(parameters) 940 941 genA := gen() 942 genB := gen() 943 944 properties.Property("Mul: having the receiver as operand should output the same result", prop.ForAll( 945 func(a, b testPairElement) bool { 946 var c, d Element 947 d.Set(&a.element) 948 949 c.Mul(&a.element, &b.element) 950 a.element.Mul(&a.element, &b.element) 951 b.element.Mul(&d, &b.element) 952 953 return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c) 954 }, 955 genA, 956 genB, 957 )) 958 959 properties.Property("Mul: operation result must match big.Int result", prop.ForAll( 960 func(a, b testPairElement) bool { 961 { 962 var c Element 963 964 c.Mul(&a.element, &b.element) 965 966 var d, e big.Int 967 d.Mul(&a.bigint, &b.bigint).Mod(&d, Modulus()) 968 969 if c.BigInt(&e).Cmp(&d) != 0 { 970 return false 971 } 972 } 973 974 // fixed elements 975 // a is random 976 // r takes special values 977 testValues := make([]Element, len(staticTestValues)) 978 copy(testValues, staticTestValues) 979 980 for i := range testValues { 981 r := testValues[i] 982 var d, e, rb big.Int 983 r.BigInt(&rb) 984 985 var c Element 986 c.Mul(&a.element, &r) 987 d.Mul(&a.bigint, &rb).Mod(&d, Modulus()) 988 989 // checking generic impl against asm path 990 var cGeneric Element 991 _mulGeneric(&cGeneric, &a.element, &r) 992 if !cGeneric.Equal(&c) { 993 // need to give context to failing error. 994 return false 995 } 996 997 if c.BigInt(&e).Cmp(&d) != 0 { 998 return false 999 } 1000 } 1001 return true 1002 }, 1003 genA, 1004 genB, 1005 )) 1006 1007 properties.Property("Mul: operation result must be smaller than modulus", prop.ForAll( 1008 func(a, b testPairElement) bool { 1009 var c Element 1010 1011 c.Mul(&a.element, &b.element) 1012 1013 return c.smallerThanModulus() 1014 }, 1015 genA, 1016 genB, 1017 )) 1018 1019 properties.Property("Mul: assembly implementation must be consistent with generic one", prop.ForAll( 1020 func(a, b testPairElement) bool { 1021 var c, d Element 1022 c.Mul(&a.element, &b.element) 1023 _mulGeneric(&d, &a.element, &b.element) 1024 return c.Equal(&d) 1025 }, 1026 genA, 1027 genB, 1028 )) 1029 1030 specialValueTest := func() { 1031 // test special values against special values 1032 testValues := make([]Element, len(staticTestValues)) 1033 copy(testValues, staticTestValues) 1034 1035 for i := range testValues { 1036 a := testValues[i] 1037 var aBig big.Int 1038 a.BigInt(&aBig) 1039 for j := range testValues { 1040 b := testValues[j] 1041 var bBig, d, e big.Int 1042 b.BigInt(&bBig) 1043 1044 var c Element 1045 c.Mul(&a, &b) 1046 d.Mul(&aBig, &bBig).Mod(&d, Modulus()) 1047 1048 // checking asm against generic impl 1049 var cGeneric Element 1050 _mulGeneric(&cGeneric, &a, &b) 1051 if !cGeneric.Equal(&c) { 1052 t.Fatal("Mul failed special test values: asm and generic impl don't match") 1053 } 1054 1055 if c.BigInt(&e).Cmp(&d) != 0 { 1056 t.Fatal("Mul failed special test values") 1057 } 1058 } 1059 } 1060 } 1061 1062 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1063 specialValueTest() 1064 1065 } 1066 1067 func TestElementDiv(t *testing.T) { 1068 t.Parallel() 1069 parameters := gopter.DefaultTestParameters() 1070 if testing.Short() { 1071 parameters.MinSuccessfulTests = nbFuzzShort 1072 } else { 1073 parameters.MinSuccessfulTests = nbFuzz 1074 } 1075 1076 properties := gopter.NewProperties(parameters) 1077 1078 genA := gen() 1079 genB := gen() 1080 1081 properties.Property("Div: having the receiver as operand should output the same result", prop.ForAll( 1082 func(a, b testPairElement) bool { 1083 var c, d Element 1084 d.Set(&a.element) 1085 1086 c.Div(&a.element, &b.element) 1087 a.element.Div(&a.element, &b.element) 1088 b.element.Div(&d, &b.element) 1089 1090 return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c) 1091 }, 1092 genA, 1093 genB, 1094 )) 1095 1096 properties.Property("Div: operation result must match big.Int result", prop.ForAll( 1097 func(a, b testPairElement) bool { 1098 { 1099 var c Element 1100 1101 c.Div(&a.element, &b.element) 1102 1103 var d, e big.Int 1104 d.ModInverse(&b.bigint, Modulus()) 1105 d.Mul(&d, &a.bigint).Mod(&d, Modulus()) 1106 1107 if c.BigInt(&e).Cmp(&d) != 0 { 1108 return false 1109 } 1110 } 1111 1112 // fixed elements 1113 // a is random 1114 // r takes special values 1115 testValues := make([]Element, len(staticTestValues)) 1116 copy(testValues, staticTestValues) 1117 1118 for i := range testValues { 1119 r := testValues[i] 1120 var d, e, rb big.Int 1121 r.BigInt(&rb) 1122 1123 var c Element 1124 c.Div(&a.element, &r) 1125 d.ModInverse(&rb, Modulus()) 1126 d.Mul(&d, &a.bigint).Mod(&d, Modulus()) 1127 1128 if c.BigInt(&e).Cmp(&d) != 0 { 1129 return false 1130 } 1131 } 1132 return true 1133 }, 1134 genA, 1135 genB, 1136 )) 1137 1138 properties.Property("Div: operation result must be smaller than modulus", prop.ForAll( 1139 func(a, b testPairElement) bool { 1140 var c Element 1141 1142 c.Div(&a.element, &b.element) 1143 1144 return c.smallerThanModulus() 1145 }, 1146 genA, 1147 genB, 1148 )) 1149 1150 specialValueTest := func() { 1151 // test special values against special values 1152 testValues := make([]Element, len(staticTestValues)) 1153 copy(testValues, staticTestValues) 1154 1155 for i := range testValues { 1156 a := testValues[i] 1157 var aBig big.Int 1158 a.BigInt(&aBig) 1159 for j := range testValues { 1160 b := testValues[j] 1161 var bBig, d, e big.Int 1162 b.BigInt(&bBig) 1163 1164 var c Element 1165 c.Div(&a, &b) 1166 d.ModInverse(&bBig, Modulus()) 1167 d.Mul(&d, &aBig).Mod(&d, Modulus()) 1168 1169 if c.BigInt(&e).Cmp(&d) != 0 { 1170 t.Fatal("Div failed special test values") 1171 } 1172 } 1173 } 1174 } 1175 1176 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1177 specialValueTest() 1178 1179 } 1180 1181 func TestElementExp(t *testing.T) { 1182 t.Parallel() 1183 parameters := gopter.DefaultTestParameters() 1184 if testing.Short() { 1185 parameters.MinSuccessfulTests = nbFuzzShort 1186 } else { 1187 parameters.MinSuccessfulTests = nbFuzz 1188 } 1189 1190 properties := gopter.NewProperties(parameters) 1191 1192 genA := gen() 1193 genB := gen() 1194 1195 properties.Property("Exp: having the receiver as operand should output the same result", prop.ForAll( 1196 func(a, b testPairElement) bool { 1197 var c, d Element 1198 d.Set(&a.element) 1199 1200 c.Exp(a.element, &b.bigint) 1201 a.element.Exp(a.element, &b.bigint) 1202 b.element.Exp(d, &b.bigint) 1203 1204 return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c) 1205 }, 1206 genA, 1207 genB, 1208 )) 1209 1210 properties.Property("Exp: operation result must match big.Int result", prop.ForAll( 1211 func(a, b testPairElement) bool { 1212 { 1213 var c Element 1214 1215 c.Exp(a.element, &b.bigint) 1216 1217 var d, e big.Int 1218 d.Exp(&a.bigint, &b.bigint, Modulus()) 1219 1220 if c.BigInt(&e).Cmp(&d) != 0 { 1221 return false 1222 } 1223 } 1224 1225 // fixed elements 1226 // a is random 1227 // r takes special values 1228 testValues := make([]Element, len(staticTestValues)) 1229 copy(testValues, staticTestValues) 1230 1231 for i := range testValues { 1232 r := testValues[i] 1233 var d, e, rb big.Int 1234 r.BigInt(&rb) 1235 1236 var c Element 1237 c.Exp(a.element, &rb) 1238 d.Exp(&a.bigint, &rb, Modulus()) 1239 1240 if c.BigInt(&e).Cmp(&d) != 0 { 1241 return false 1242 } 1243 } 1244 return true 1245 }, 1246 genA, 1247 genB, 1248 )) 1249 1250 properties.Property("Exp: operation result must be smaller than modulus", prop.ForAll( 1251 func(a, b testPairElement) bool { 1252 var c Element 1253 1254 c.Exp(a.element, &b.bigint) 1255 1256 return c.smallerThanModulus() 1257 }, 1258 genA, 1259 genB, 1260 )) 1261 1262 specialValueTest := func() { 1263 // test special values against special values 1264 testValues := make([]Element, len(staticTestValues)) 1265 copy(testValues, staticTestValues) 1266 1267 for i := range testValues { 1268 a := testValues[i] 1269 var aBig big.Int 1270 a.BigInt(&aBig) 1271 for j := range testValues { 1272 b := testValues[j] 1273 var bBig, d, e big.Int 1274 b.BigInt(&bBig) 1275 1276 var c Element 1277 c.Exp(a, &bBig) 1278 d.Exp(&aBig, &bBig, Modulus()) 1279 1280 if c.BigInt(&e).Cmp(&d) != 0 { 1281 t.Fatal("Exp failed special test values") 1282 } 1283 } 1284 } 1285 } 1286 1287 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1288 specialValueTest() 1289 1290 } 1291 1292 func TestElementSquare(t *testing.T) { 1293 t.Parallel() 1294 parameters := gopter.DefaultTestParameters() 1295 if testing.Short() { 1296 parameters.MinSuccessfulTests = nbFuzzShort 1297 } else { 1298 parameters.MinSuccessfulTests = nbFuzz 1299 } 1300 1301 properties := gopter.NewProperties(parameters) 1302 1303 genA := gen() 1304 1305 properties.Property("Square: having the receiver as operand should output the same result", prop.ForAll( 1306 func(a testPairElement) bool { 1307 1308 var b Element 1309 1310 b.Square(&a.element) 1311 a.element.Square(&a.element) 1312 return a.element.Equal(&b) 1313 }, 1314 genA, 1315 )) 1316 1317 properties.Property("Square: operation result must match big.Int result", prop.ForAll( 1318 func(a testPairElement) bool { 1319 var c Element 1320 c.Square(&a.element) 1321 1322 var d, e big.Int 1323 d.Mul(&a.bigint, &a.bigint).Mod(&d, Modulus()) 1324 1325 return c.BigInt(&e).Cmp(&d) == 0 1326 }, 1327 genA, 1328 )) 1329 1330 properties.Property("Square: operation result must be smaller than modulus", prop.ForAll( 1331 func(a testPairElement) bool { 1332 var c Element 1333 c.Square(&a.element) 1334 return c.smallerThanModulus() 1335 }, 1336 genA, 1337 )) 1338 1339 specialValueTest := func() { 1340 // test special values 1341 testValues := make([]Element, len(staticTestValues)) 1342 copy(testValues, staticTestValues) 1343 1344 for i := range testValues { 1345 a := testValues[i] 1346 var aBig big.Int 1347 a.BigInt(&aBig) 1348 var c Element 1349 c.Square(&a) 1350 1351 var d, e big.Int 1352 d.Mul(&aBig, &aBig).Mod(&d, Modulus()) 1353 1354 if c.BigInt(&e).Cmp(&d) != 0 { 1355 t.Fatal("Square failed special test values") 1356 } 1357 } 1358 } 1359 1360 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1361 specialValueTest() 1362 1363 } 1364 1365 func TestElementInverse(t *testing.T) { 1366 t.Parallel() 1367 parameters := gopter.DefaultTestParameters() 1368 if testing.Short() { 1369 parameters.MinSuccessfulTests = nbFuzzShort 1370 } else { 1371 parameters.MinSuccessfulTests = nbFuzz 1372 } 1373 1374 properties := gopter.NewProperties(parameters) 1375 1376 genA := gen() 1377 1378 properties.Property("Inverse: having the receiver as operand should output the same result", prop.ForAll( 1379 func(a testPairElement) bool { 1380 1381 var b Element 1382 1383 b.Inverse(&a.element) 1384 a.element.Inverse(&a.element) 1385 return a.element.Equal(&b) 1386 }, 1387 genA, 1388 )) 1389 1390 properties.Property("Inverse: operation result must match big.Int result", prop.ForAll( 1391 func(a testPairElement) bool { 1392 var c Element 1393 c.Inverse(&a.element) 1394 1395 var d, e big.Int 1396 d.ModInverse(&a.bigint, Modulus()) 1397 1398 return c.BigInt(&e).Cmp(&d) == 0 1399 }, 1400 genA, 1401 )) 1402 1403 properties.Property("Inverse: operation result must be smaller than modulus", prop.ForAll( 1404 func(a testPairElement) bool { 1405 var c Element 1406 c.Inverse(&a.element) 1407 return c.smallerThanModulus() 1408 }, 1409 genA, 1410 )) 1411 1412 specialValueTest := func() { 1413 // test special values 1414 testValues := make([]Element, len(staticTestValues)) 1415 copy(testValues, staticTestValues) 1416 1417 for i := range testValues { 1418 a := testValues[i] 1419 var aBig big.Int 1420 a.BigInt(&aBig) 1421 var c Element 1422 c.Inverse(&a) 1423 1424 var d, e big.Int 1425 d.ModInverse(&aBig, Modulus()) 1426 1427 if c.BigInt(&e).Cmp(&d) != 0 { 1428 t.Fatal("Inverse failed special test values") 1429 } 1430 } 1431 } 1432 1433 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1434 specialValueTest() 1435 1436 } 1437 1438 func TestElementSqrt(t *testing.T) { 1439 t.Parallel() 1440 parameters := gopter.DefaultTestParameters() 1441 if testing.Short() { 1442 parameters.MinSuccessfulTests = nbFuzzShort 1443 } else { 1444 parameters.MinSuccessfulTests = nbFuzz 1445 } 1446 1447 properties := gopter.NewProperties(parameters) 1448 1449 genA := gen() 1450 1451 properties.Property("Sqrt: having the receiver as operand should output the same result", prop.ForAll( 1452 func(a testPairElement) bool { 1453 1454 b := a.element 1455 1456 b.Sqrt(&a.element) 1457 a.element.Sqrt(&a.element) 1458 return a.element.Equal(&b) 1459 }, 1460 genA, 1461 )) 1462 1463 properties.Property("Sqrt: operation result must match big.Int result", prop.ForAll( 1464 func(a testPairElement) bool { 1465 var c Element 1466 c.Sqrt(&a.element) 1467 1468 var d, e big.Int 1469 d.ModSqrt(&a.bigint, Modulus()) 1470 1471 return c.BigInt(&e).Cmp(&d) == 0 1472 }, 1473 genA, 1474 )) 1475 1476 properties.Property("Sqrt: operation result must be smaller than modulus", prop.ForAll( 1477 func(a testPairElement) bool { 1478 var c Element 1479 c.Sqrt(&a.element) 1480 return c.smallerThanModulus() 1481 }, 1482 genA, 1483 )) 1484 1485 specialValueTest := func() { 1486 // test special values 1487 testValues := make([]Element, len(staticTestValues)) 1488 copy(testValues, staticTestValues) 1489 1490 for i := range testValues { 1491 a := testValues[i] 1492 var aBig big.Int 1493 a.BigInt(&aBig) 1494 var c Element 1495 c.Sqrt(&a) 1496 1497 var d, e big.Int 1498 d.ModSqrt(&aBig, Modulus()) 1499 1500 if c.BigInt(&e).Cmp(&d) != 0 { 1501 t.Fatal("Sqrt failed special test values") 1502 } 1503 } 1504 } 1505 1506 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1507 specialValueTest() 1508 1509 } 1510 1511 func TestElementDouble(t *testing.T) { 1512 t.Parallel() 1513 parameters := gopter.DefaultTestParameters() 1514 if testing.Short() { 1515 parameters.MinSuccessfulTests = nbFuzzShort 1516 } else { 1517 parameters.MinSuccessfulTests = nbFuzz 1518 } 1519 1520 properties := gopter.NewProperties(parameters) 1521 1522 genA := gen() 1523 1524 properties.Property("Double: having the receiver as operand should output the same result", prop.ForAll( 1525 func(a testPairElement) bool { 1526 1527 var b Element 1528 1529 b.Double(&a.element) 1530 a.element.Double(&a.element) 1531 return a.element.Equal(&b) 1532 }, 1533 genA, 1534 )) 1535 1536 properties.Property("Double: operation result must match big.Int result", prop.ForAll( 1537 func(a testPairElement) bool { 1538 var c Element 1539 c.Double(&a.element) 1540 1541 var d, e big.Int 1542 d.Lsh(&a.bigint, 1).Mod(&d, Modulus()) 1543 1544 return c.BigInt(&e).Cmp(&d) == 0 1545 }, 1546 genA, 1547 )) 1548 1549 properties.Property("Double: operation result must be smaller than modulus", prop.ForAll( 1550 func(a testPairElement) bool { 1551 var c Element 1552 c.Double(&a.element) 1553 return c.smallerThanModulus() 1554 }, 1555 genA, 1556 )) 1557 1558 specialValueTest := func() { 1559 // test special values 1560 testValues := make([]Element, len(staticTestValues)) 1561 copy(testValues, staticTestValues) 1562 1563 for i := range testValues { 1564 a := testValues[i] 1565 var aBig big.Int 1566 a.BigInt(&aBig) 1567 var c Element 1568 c.Double(&a) 1569 1570 var d, e big.Int 1571 d.Lsh(&aBig, 1).Mod(&d, Modulus()) 1572 1573 if c.BigInt(&e).Cmp(&d) != 0 { 1574 t.Fatal("Double failed special test values") 1575 } 1576 } 1577 } 1578 1579 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1580 specialValueTest() 1581 1582 } 1583 1584 func TestElementNeg(t *testing.T) { 1585 t.Parallel() 1586 parameters := gopter.DefaultTestParameters() 1587 if testing.Short() { 1588 parameters.MinSuccessfulTests = nbFuzzShort 1589 } else { 1590 parameters.MinSuccessfulTests = nbFuzz 1591 } 1592 1593 properties := gopter.NewProperties(parameters) 1594 1595 genA := gen() 1596 1597 properties.Property("Neg: having the receiver as operand should output the same result", prop.ForAll( 1598 func(a testPairElement) bool { 1599 1600 var b Element 1601 1602 b.Neg(&a.element) 1603 a.element.Neg(&a.element) 1604 return a.element.Equal(&b) 1605 }, 1606 genA, 1607 )) 1608 1609 properties.Property("Neg: operation result must match big.Int result", prop.ForAll( 1610 func(a testPairElement) bool { 1611 var c Element 1612 c.Neg(&a.element) 1613 1614 var d, e big.Int 1615 d.Neg(&a.bigint).Mod(&d, Modulus()) 1616 1617 return c.BigInt(&e).Cmp(&d) == 0 1618 }, 1619 genA, 1620 )) 1621 1622 properties.Property("Neg: operation result must be smaller than modulus", prop.ForAll( 1623 func(a testPairElement) bool { 1624 var c Element 1625 c.Neg(&a.element) 1626 return c.smallerThanModulus() 1627 }, 1628 genA, 1629 )) 1630 1631 specialValueTest := func() { 1632 // test special values 1633 testValues := make([]Element, len(staticTestValues)) 1634 copy(testValues, staticTestValues) 1635 1636 for i := range testValues { 1637 a := testValues[i] 1638 var aBig big.Int 1639 a.BigInt(&aBig) 1640 var c Element 1641 c.Neg(&a) 1642 1643 var d, e big.Int 1644 d.Neg(&aBig).Mod(&d, Modulus()) 1645 1646 if c.BigInt(&e).Cmp(&d) != 0 { 1647 t.Fatal("Neg failed special test values") 1648 } 1649 } 1650 } 1651 1652 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1653 specialValueTest() 1654 1655 } 1656 1657 func TestElementFixedExp(t *testing.T) { 1658 1659 t.Parallel() 1660 parameters := gopter.DefaultTestParameters() 1661 if testing.Short() { 1662 parameters.MinSuccessfulTests = nbFuzzShort 1663 } else { 1664 parameters.MinSuccessfulTests = nbFuzz 1665 } 1666 1667 properties := gopter.NewProperties(parameters) 1668 1669 var ( 1670 _bLegendreExponentElement *big.Int 1671 _bSqrtExponentElement *big.Int 1672 ) 1673 1674 _bLegendreExponentElement, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", 16) 1675 const sqrtExponentElement = "1fffffffffffffffffffffffffffffffd755db9cd5e9140777fa4bd19a06c82" 1676 _bSqrtExponentElement, _ = new(big.Int).SetString(sqrtExponentElement, 16) 1677 1678 genA := gen() 1679 1680 properties.Property(fmt.Sprintf("expBySqrtExp must match Exp(%s)", sqrtExponentElement), prop.ForAll( 1681 func(a testPairElement) bool { 1682 c := a.element 1683 d := a.element 1684 c.expBySqrtExp(c) 1685 d.Exp(d, _bSqrtExponentElement) 1686 return c.Equal(&d) 1687 }, 1688 genA, 1689 )) 1690 1691 properties.Property("expByLegendreExp must match Exp(7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0)", prop.ForAll( 1692 func(a testPairElement) bool { 1693 c := a.element 1694 d := a.element 1695 c.expByLegendreExp(c) 1696 d.Exp(d, _bLegendreExponentElement) 1697 return c.Equal(&d) 1698 }, 1699 genA, 1700 )) 1701 1702 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1703 } 1704 1705 func TestElementHalve(t *testing.T) { 1706 1707 t.Parallel() 1708 parameters := gopter.DefaultTestParameters() 1709 if testing.Short() { 1710 parameters.MinSuccessfulTests = nbFuzzShort 1711 } else { 1712 parameters.MinSuccessfulTests = nbFuzz 1713 } 1714 1715 properties := gopter.NewProperties(parameters) 1716 1717 genA := gen() 1718 var twoInv Element 1719 twoInv.SetUint64(2) 1720 twoInv.Inverse(&twoInv) 1721 1722 properties.Property("z.Halve must match z / 2", prop.ForAll( 1723 func(a testPairElement) bool { 1724 c := a.element 1725 d := a.element 1726 c.Halve() 1727 d.Mul(&d, &twoInv) 1728 return c.Equal(&d) 1729 }, 1730 genA, 1731 )) 1732 1733 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1734 } 1735 1736 func combineSelectionArguments(c int64, z int8) int { 1737 if z%3 == 0 { 1738 return 0 1739 } 1740 return int(c) 1741 } 1742 1743 func TestElementSelect(t *testing.T) { 1744 t.Parallel() 1745 parameters := gopter.DefaultTestParameters() 1746 if testing.Short() { 1747 parameters.MinSuccessfulTests = nbFuzzShort 1748 } else { 1749 parameters.MinSuccessfulTests = nbFuzz 1750 } 1751 1752 properties := gopter.NewProperties(parameters) 1753 1754 genA := genFull() 1755 genB := genFull() 1756 genC := ggen.Int64() //the condition 1757 genZ := ggen.Int8() //to make zeros artificially more likely 1758 1759 properties.Property("Select: must select correctly", prop.ForAll( 1760 func(a, b Element, cond int64, z int8) bool { 1761 condC := combineSelectionArguments(cond, z) 1762 1763 var c Element 1764 c.Select(condC, &a, &b) 1765 1766 if condC == 0 { 1767 return c.Equal(&a) 1768 } 1769 return c.Equal(&b) 1770 }, 1771 genA, 1772 genB, 1773 genC, 1774 genZ, 1775 )) 1776 1777 properties.Property("Select: having the receiver as operand should output the same result", prop.ForAll( 1778 func(a, b Element, cond int64, z int8) bool { 1779 condC := combineSelectionArguments(cond, z) 1780 1781 var c, d Element 1782 d.Set(&a) 1783 c.Select(condC, &a, &b) 1784 a.Select(condC, &a, &b) 1785 b.Select(condC, &d, &b) 1786 return a.Equal(&b) && a.Equal(&c) && b.Equal(&c) 1787 }, 1788 genA, 1789 genB, 1790 genC, 1791 genZ, 1792 )) 1793 1794 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1795 } 1796 1797 func TestElementSetInt64(t *testing.T) { 1798 1799 t.Parallel() 1800 parameters := gopter.DefaultTestParameters() 1801 if testing.Short() { 1802 parameters.MinSuccessfulTests = nbFuzzShort 1803 } else { 1804 parameters.MinSuccessfulTests = nbFuzz 1805 } 1806 1807 properties := gopter.NewProperties(parameters) 1808 1809 genA := gen() 1810 1811 properties.Property("z.SetInt64 must match z.SetString", prop.ForAll( 1812 func(a testPairElement, v int64) bool { 1813 c := a.element 1814 d := a.element 1815 1816 c.SetInt64(v) 1817 d.SetString(fmt.Sprintf("%v", v)) 1818 1819 return c.Equal(&d) 1820 }, 1821 genA, ggen.Int64(), 1822 )) 1823 1824 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1825 } 1826 1827 func TestElementSetInterface(t *testing.T) { 1828 1829 t.Parallel() 1830 parameters := gopter.DefaultTestParameters() 1831 if testing.Short() { 1832 parameters.MinSuccessfulTests = nbFuzzShort 1833 } else { 1834 parameters.MinSuccessfulTests = nbFuzz 1835 } 1836 1837 properties := gopter.NewProperties(parameters) 1838 1839 genA := gen() 1840 genInt := ggen.Int 1841 genInt8 := ggen.Int8 1842 genInt16 := ggen.Int16 1843 genInt32 := ggen.Int32 1844 genInt64 := ggen.Int64 1845 1846 genUint := ggen.UInt 1847 genUint8 := ggen.UInt8 1848 genUint16 := ggen.UInt16 1849 genUint32 := ggen.UInt32 1850 genUint64 := ggen.UInt64 1851 1852 properties.Property("z.SetInterface must match z.SetString with int8", prop.ForAll( 1853 func(a testPairElement, v int8) bool { 1854 c := a.element 1855 d := a.element 1856 1857 c.SetInterface(v) 1858 d.SetString(fmt.Sprintf("%v", v)) 1859 1860 return c.Equal(&d) 1861 }, 1862 genA, genInt8(), 1863 )) 1864 1865 properties.Property("z.SetInterface must match z.SetString with int16", prop.ForAll( 1866 func(a testPairElement, v int16) bool { 1867 c := a.element 1868 d := a.element 1869 1870 c.SetInterface(v) 1871 d.SetString(fmt.Sprintf("%v", v)) 1872 1873 return c.Equal(&d) 1874 }, 1875 genA, genInt16(), 1876 )) 1877 1878 properties.Property("z.SetInterface must match z.SetString with int32", prop.ForAll( 1879 func(a testPairElement, v int32) bool { 1880 c := a.element 1881 d := a.element 1882 1883 c.SetInterface(v) 1884 d.SetString(fmt.Sprintf("%v", v)) 1885 1886 return c.Equal(&d) 1887 }, 1888 genA, genInt32(), 1889 )) 1890 1891 properties.Property("z.SetInterface must match z.SetString with int64", prop.ForAll( 1892 func(a testPairElement, v int64) bool { 1893 c := a.element 1894 d := a.element 1895 1896 c.SetInterface(v) 1897 d.SetString(fmt.Sprintf("%v", v)) 1898 1899 return c.Equal(&d) 1900 }, 1901 genA, genInt64(), 1902 )) 1903 1904 properties.Property("z.SetInterface must match z.SetString with int", prop.ForAll( 1905 func(a testPairElement, v int) bool { 1906 c := a.element 1907 d := a.element 1908 1909 c.SetInterface(v) 1910 d.SetString(fmt.Sprintf("%v", v)) 1911 1912 return c.Equal(&d) 1913 }, 1914 genA, genInt(), 1915 )) 1916 1917 properties.Property("z.SetInterface must match z.SetString with uint8", prop.ForAll( 1918 func(a testPairElement, v uint8) bool { 1919 c := a.element 1920 d := a.element 1921 1922 c.SetInterface(v) 1923 d.SetString(fmt.Sprintf("%v", v)) 1924 1925 return c.Equal(&d) 1926 }, 1927 genA, genUint8(), 1928 )) 1929 1930 properties.Property("z.SetInterface must match z.SetString with uint16", prop.ForAll( 1931 func(a testPairElement, v uint16) bool { 1932 c := a.element 1933 d := a.element 1934 1935 c.SetInterface(v) 1936 d.SetString(fmt.Sprintf("%v", v)) 1937 1938 return c.Equal(&d) 1939 }, 1940 genA, genUint16(), 1941 )) 1942 1943 properties.Property("z.SetInterface must match z.SetString with uint32", prop.ForAll( 1944 func(a testPairElement, v uint32) bool { 1945 c := a.element 1946 d := a.element 1947 1948 c.SetInterface(v) 1949 d.SetString(fmt.Sprintf("%v", v)) 1950 1951 return c.Equal(&d) 1952 }, 1953 genA, genUint32(), 1954 )) 1955 1956 properties.Property("z.SetInterface must match z.SetString with uint64", prop.ForAll( 1957 func(a testPairElement, v uint64) bool { 1958 c := a.element 1959 d := a.element 1960 1961 c.SetInterface(v) 1962 d.SetString(fmt.Sprintf("%v", v)) 1963 1964 return c.Equal(&d) 1965 }, 1966 genA, genUint64(), 1967 )) 1968 1969 properties.Property("z.SetInterface must match z.SetString with uint", prop.ForAll( 1970 func(a testPairElement, v uint) bool { 1971 c := a.element 1972 d := a.element 1973 1974 c.SetInterface(v) 1975 d.SetString(fmt.Sprintf("%v", v)) 1976 1977 return c.Equal(&d) 1978 }, 1979 genA, genUint(), 1980 )) 1981 1982 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1983 1984 { 1985 assert := require.New(t) 1986 var e Element 1987 r, err := e.SetInterface(nil) 1988 assert.Nil(r) 1989 assert.Error(err) 1990 1991 var ptE *Element 1992 var ptB *big.Int 1993 1994 r, err = e.SetInterface(ptE) 1995 assert.Nil(r) 1996 assert.Error(err) 1997 ptE = new(Element).SetOne() 1998 r, err = e.SetInterface(ptE) 1999 assert.NoError(err) 2000 assert.True(r.IsOne()) 2001 2002 r, err = e.SetInterface(ptB) 2003 assert.Nil(r) 2004 assert.Error(err) 2005 2006 } 2007 } 2008 2009 func TestElementNegativeExp(t *testing.T) { 2010 t.Parallel() 2011 2012 parameters := gopter.DefaultTestParameters() 2013 if testing.Short() { 2014 parameters.MinSuccessfulTests = nbFuzzShort 2015 } else { 2016 parameters.MinSuccessfulTests = nbFuzz 2017 } 2018 2019 properties := gopter.NewProperties(parameters) 2020 2021 genA := gen() 2022 2023 properties.Property("x⁻ᵏ == 1/xᵏ", prop.ForAll( 2024 func(a, b testPairElement) bool { 2025 2026 var nb, d, e big.Int 2027 nb.Neg(&b.bigint) 2028 2029 var c Element 2030 c.Exp(a.element, &nb) 2031 2032 d.Exp(&a.bigint, &nb, Modulus()) 2033 2034 return c.BigInt(&e).Cmp(&d) == 0 2035 }, 2036 genA, genA, 2037 )) 2038 2039 properties.TestingRun(t, gopter.ConsoleReporter(false)) 2040 } 2041 2042 func TestElementNewElement(t *testing.T) { 2043 assert := require.New(t) 2044 2045 t.Parallel() 2046 2047 e := NewElement(1) 2048 assert.True(e.IsOne()) 2049 2050 e = NewElement(0) 2051 assert.True(e.IsZero()) 2052 } 2053 2054 func TestElementBatchInvert(t *testing.T) { 2055 assert := require.New(t) 2056 2057 t.Parallel() 2058 2059 // ensure batchInvert([x]) == invert(x) 2060 for i := int64(-1); i <= 2; i++ { 2061 var e, eInv Element 2062 e.SetInt64(i) 2063 eInv.Inverse(&e) 2064 2065 a := []Element{e} 2066 aInv := BatchInvert(a) 2067 2068 assert.True(aInv[0].Equal(&eInv), "batchInvert != invert") 2069 2070 } 2071 2072 // test x * x⁻¹ == 1 2073 tData := [][]int64{ 2074 {-1, 1, 2, 3}, 2075 {0, -1, 1, 2, 3, 0}, 2076 {0, -1, 1, 0, 2, 3, 0}, 2077 {-1, 1, 0, 2, 3}, 2078 {0, 0, 1}, 2079 {1, 0, 0}, 2080 {0, 0, 0}, 2081 } 2082 2083 for _, t := range tData { 2084 a := make([]Element, len(t)) 2085 for i := 0; i < len(a); i++ { 2086 a[i].SetInt64(t[i]) 2087 } 2088 2089 aInv := BatchInvert(a) 2090 2091 assert.True(len(aInv) == len(a)) 2092 2093 for i := 0; i < len(a); i++ { 2094 if a[i].IsZero() { 2095 assert.True(aInv[i].IsZero(), "0⁻¹ != 0") 2096 } else { 2097 assert.True(a[i].Mul(&a[i], &aInv[i]).IsOne(), "x * x⁻¹ != 1") 2098 } 2099 } 2100 } 2101 2102 parameters := gopter.DefaultTestParameters() 2103 if testing.Short() { 2104 parameters.MinSuccessfulTests = nbFuzzShort 2105 } else { 2106 parameters.MinSuccessfulTests = nbFuzz 2107 } 2108 2109 properties := gopter.NewProperties(parameters) 2110 2111 genA := gen() 2112 2113 properties.Property("batchInvert --> x * x⁻¹ == 1", prop.ForAll( 2114 func(tp testPairElement, r uint8) bool { 2115 2116 a := make([]Element, r) 2117 if r != 0 { 2118 a[0] = tp.element 2119 2120 } 2121 one := One() 2122 for i := 1; i < len(a); i++ { 2123 a[i].Add(&a[i-1], &one) 2124 } 2125 2126 aInv := BatchInvert(a) 2127 2128 assert.True(len(aInv) == len(a)) 2129 2130 for i := 0; i < len(a); i++ { 2131 if a[i].IsZero() { 2132 if !aInv[i].IsZero() { 2133 return false 2134 } 2135 } else { 2136 if !a[i].Mul(&a[i], &aInv[i]).IsOne() { 2137 return false 2138 } 2139 } 2140 } 2141 return true 2142 }, 2143 genA, ggen.UInt8(), 2144 )) 2145 2146 properties.TestingRun(t, gopter.ConsoleReporter(false)) 2147 } 2148 2149 func TestElementFromMont(t *testing.T) { 2150 2151 t.Parallel() 2152 parameters := gopter.DefaultTestParameters() 2153 if testing.Short() { 2154 parameters.MinSuccessfulTests = nbFuzzShort 2155 } else { 2156 parameters.MinSuccessfulTests = nbFuzz 2157 } 2158 2159 properties := gopter.NewProperties(parameters) 2160 2161 genA := gen() 2162 2163 properties.Property("Assembly implementation must be consistent with generic one", prop.ForAll( 2164 func(a testPairElement) bool { 2165 c := a.element 2166 d := a.element 2167 c.fromMont() 2168 _fromMontGeneric(&d) 2169 return c.Equal(&d) 2170 }, 2171 genA, 2172 )) 2173 2174 properties.Property("x.fromMont().toMont() == x", prop.ForAll( 2175 func(a testPairElement) bool { 2176 c := a.element 2177 c.fromMont().toMont() 2178 return c.Equal(&a.element) 2179 }, 2180 genA, 2181 )) 2182 2183 properties.TestingRun(t, gopter.ConsoleReporter(false)) 2184 } 2185 2186 func TestElementJSON(t *testing.T) { 2187 assert := require.New(t) 2188 2189 type S struct { 2190 A Element 2191 B [3]Element 2192 C *Element 2193 D *Element 2194 } 2195 2196 // encode to JSON 2197 var s S 2198 s.A.SetString("-1") 2199 s.B[2].SetUint64(42) 2200 s.D = new(Element).SetUint64(8000) 2201 2202 encoded, err := json.Marshal(&s) 2203 assert.NoError(err) 2204 // we may need to adjust "42" and "8000" values for some moduli; see Text() method for more details. 2205 formatValue := func(v int64) string { 2206 var a big.Int 2207 a.SetInt64(v) 2208 a.Mod(&a, Modulus()) 2209 const maxUint16 = 65535 2210 var aNeg big.Int 2211 aNeg.Neg(&a).Mod(&aNeg, Modulus()) 2212 if aNeg.Uint64() != 0 && aNeg.Uint64() <= maxUint16 { 2213 return "-" + aNeg.Text(10) 2214 } 2215 return a.Text(10) 2216 } 2217 expected := fmt.Sprintf("{\"A\":%s,\"B\":[0,0,%s],\"C\":null,\"D\":%s}", formatValue(-1), formatValue(42), formatValue(8000)) 2218 assert.Equal(expected, string(encoded)) 2219 2220 // decode valid 2221 var decoded S 2222 err = json.Unmarshal([]byte(expected), &decoded) 2223 assert.NoError(err) 2224 2225 assert.Equal(s, decoded, "element -> json -> element round trip failed") 2226 2227 // decode hex and string values 2228 withHexValues := "{\"A\":\"-1\",\"B\":[0,\"0x00000\",\"0x2A\"],\"C\":null,\"D\":\"8000\"}" 2229 2230 var decodedS S 2231 err = json.Unmarshal([]byte(withHexValues), &decodedS) 2232 assert.NoError(err) 2233 2234 assert.Equal(s, decodedS, " json with strings -> element failed") 2235 2236 } 2237 2238 type testPairElement struct { 2239 element Element 2240 bigint big.Int 2241 } 2242 2243 func gen() gopter.Gen { 2244 return func(genParams *gopter.GenParameters) *gopter.GenResult { 2245 var g testPairElement 2246 2247 g.element = Element{ 2248 genParams.NextUint64(), 2249 genParams.NextUint64(), 2250 genParams.NextUint64(), 2251 genParams.NextUint64(), 2252 } 2253 if qElement[3] != ^uint64(0) { 2254 g.element[3] %= (qElement[3] + 1) 2255 } 2256 2257 for !g.element.smallerThanModulus() { 2258 g.element = Element{ 2259 genParams.NextUint64(), 2260 genParams.NextUint64(), 2261 genParams.NextUint64(), 2262 genParams.NextUint64(), 2263 } 2264 if qElement[3] != ^uint64(0) { 2265 g.element[3] %= (qElement[3] + 1) 2266 } 2267 } 2268 2269 g.element.BigInt(&g.bigint) 2270 genResult := gopter.NewGenResult(g, gopter.NoShrinker) 2271 return genResult 2272 } 2273 } 2274 2275 func genFull() gopter.Gen { 2276 return func(genParams *gopter.GenParameters) *gopter.GenResult { 2277 2278 genRandomFq := func() Element { 2279 var g Element 2280 2281 g = Element{ 2282 genParams.NextUint64(), 2283 genParams.NextUint64(), 2284 genParams.NextUint64(), 2285 genParams.NextUint64(), 2286 } 2287 2288 if qElement[3] != ^uint64(0) { 2289 g[3] %= (qElement[3] + 1) 2290 } 2291 2292 for !g.smallerThanModulus() { 2293 g = Element{ 2294 genParams.NextUint64(), 2295 genParams.NextUint64(), 2296 genParams.NextUint64(), 2297 genParams.NextUint64(), 2298 } 2299 if qElement[3] != ^uint64(0) { 2300 g[3] %= (qElement[3] + 1) 2301 } 2302 } 2303 2304 return g 2305 } 2306 a := genRandomFq() 2307 2308 var carry uint64 2309 a[0], carry = bits.Add64(a[0], qElement[0], carry) 2310 a[1], carry = bits.Add64(a[1], qElement[1], carry) 2311 a[2], carry = bits.Add64(a[2], qElement[2], carry) 2312 a[3], _ = bits.Add64(a[3], qElement[3], carry) 2313 2314 genResult := gopter.NewGenResult(a, gopter.NoShrinker) 2315 return genResult 2316 } 2317 }