github.com/consensys/gnark-crypto@v0.14.0/ecc/bn254/internal/fptower/e2_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 fptower 18 19 import ( 20 "crypto/rand" 21 "testing" 22 23 "github.com/consensys/gnark-crypto/ecc/bn254/fp" 24 "github.com/leanovate/gopter" 25 "github.com/leanovate/gopter/prop" 26 ) 27 28 // ------------------------------------------------------------ 29 // tests 30 31 const ( 32 nbFuzzShort = 10 33 nbFuzz = 50 34 ) 35 36 func TestE2ReceiverIsOperand(t *testing.T) { 37 38 t.Parallel() 39 parameters := gopter.DefaultTestParameters() 40 if testing.Short() { 41 parameters.MinSuccessfulTests = nbFuzzShort 42 } else { 43 parameters.MinSuccessfulTests = nbFuzz 44 } 45 46 properties := gopter.NewProperties(parameters) 47 48 genA := GenE2() 49 genB := GenE2() 50 genfp := GenFp() 51 52 properties.Property("[BN254] Having the receiver as operand (addition) should output the same result", prop.ForAll( 53 func(a, b *E2) bool { 54 var c, d E2 55 d.Set(a) 56 c.Add(a, b) 57 a.Add(a, b) 58 b.Add(&d, b) 59 return a.Equal(b) && a.Equal(&c) && b.Equal(&c) 60 }, 61 genA, 62 genB, 63 )) 64 65 properties.Property("[BN254] Having the receiver as operand (sub) should output the same result", prop.ForAll( 66 func(a, b *E2) bool { 67 var c, d E2 68 d.Set(a) 69 c.Sub(a, b) 70 a.Sub(a, b) 71 b.Sub(&d, b) 72 return a.Equal(b) && a.Equal(&c) && b.Equal(&c) 73 }, 74 genA, 75 genB, 76 )) 77 78 properties.Property("[BN254] Having the receiver as operand (mul) should output the same result", prop.ForAll( 79 func(a, b *E2) bool { 80 var c, d E2 81 d.Set(a) 82 c.Mul(a, b) 83 a.Mul(a, b) 84 b.Mul(&d, b) 85 return a.Equal(b) && a.Equal(&c) && b.Equal(&c) 86 }, 87 genA, 88 genB, 89 )) 90 91 properties.Property("[BN254] Having the receiver as operand (square) should output the same result", prop.ForAll( 92 func(a *E2) bool { 93 var b E2 94 b.Square(a) 95 a.Square(a) 96 return a.Equal(&b) 97 }, 98 genA, 99 )) 100 101 properties.Property("[BN254] Having the receiver as operand (neg) should output the same result", prop.ForAll( 102 func(a *E2) bool { 103 var b E2 104 b.Neg(a) 105 a.Neg(a) 106 return a.Equal(&b) 107 }, 108 genA, 109 )) 110 111 properties.Property("[BN254] Having the receiver as operand (double) should output the same result", prop.ForAll( 112 func(a *E2) bool { 113 var b E2 114 b.Double(a) 115 a.Double(a) 116 return a.Equal(&b) 117 }, 118 genA, 119 )) 120 121 properties.Property("[BN254] Having the receiver as operand (mul by non residue) should output the same result", prop.ForAll( 122 func(a *E2) bool { 123 var b E2 124 b.MulByNonResidue(a) 125 a.MulByNonResidue(a) 126 return a.Equal(&b) 127 }, 128 genA, 129 )) 130 131 properties.Property("[BN254] Having the receiver as operand (mul by non residue inverse) should output the same result", prop.ForAll( 132 func(a *E2) bool { 133 var b E2 134 b.MulByNonResidueInv(a) 135 a.MulByNonResidueInv(a) 136 return a.Equal(&b) 137 }, 138 genA, 139 )) 140 141 properties.Property("[BN254] Having the receiver as operand (Inverse) should output the same result", prop.ForAll( 142 func(a *E2) bool { 143 var b E2 144 b.Inverse(a) 145 a.Inverse(a) 146 return a.Equal(&b) 147 }, 148 genA, 149 )) 150 151 properties.Property("[BN254] Having the receiver as operand (Conjugate) should output the same result", prop.ForAll( 152 func(a *E2) bool { 153 var b E2 154 b.Conjugate(a) 155 a.Conjugate(a) 156 return a.Equal(&b) 157 }, 158 genA, 159 )) 160 161 properties.Property("[BN254] Having the receiver as operand (mul by element) should output the same result", prop.ForAll( 162 func(a *E2, b fp.Element) bool { 163 var c E2 164 c.MulByElement(a, &b) 165 a.MulByElement(a, &b) 166 return a.Equal(&c) 167 }, 168 genA, 169 genfp, 170 )) 171 172 properties.Property("[BN254] Having the receiver as operand (Sqrt) should output the same result", prop.ForAll( 173 func(a *E2) bool { 174 var b, c, d, s E2 175 176 s.Square(a) 177 a.Set(&s) 178 b.Set(&s) 179 180 a.Sqrt(a) 181 b.Sqrt(&b) 182 183 c.Square(a) 184 d.Square(&b) 185 return c.Equal(&d) 186 }, 187 genA, 188 )) 189 190 properties.TestingRun(t, gopter.ConsoleReporter(false)) 191 192 } 193 194 func TestE2MulMaxed(t *testing.T) { 195 // let's pick a and b, with maxed A0 and A1 196 var a, b E2 197 fpMaxValue := fp.Element{ 198 4332616871279656263, 199 10917124144477883021, 200 13281191951274694749, 201 3486998266802970665, 202 } 203 fpMaxValue[0]-- 204 205 a.A0 = fpMaxValue 206 a.A1 = fpMaxValue 207 b.A0 = fpMaxValue 208 b.A1 = fpMaxValue 209 210 var c, d E2 211 d.Inverse(&b) 212 c.Set(&a) 213 c.Mul(&c, &b).Mul(&c, &d) 214 if !c.Equal(&a) { 215 t.Fatal("mul with max fp failed") 216 } 217 } 218 219 func TestE2Ops(t *testing.T) { 220 221 t.Parallel() 222 parameters := gopter.DefaultTestParameters() 223 if testing.Short() { 224 parameters.MinSuccessfulTests = nbFuzzShort 225 } else { 226 parameters.MinSuccessfulTests = nbFuzz 227 } 228 229 properties := gopter.NewProperties(parameters) 230 231 genA := GenE2() 232 genB := GenE2() 233 genfp := GenFp() 234 235 properties.Property("[BN254] sub & add should leave an element invariant", prop.ForAll( 236 func(a, b *E2) bool { 237 var c E2 238 c.Set(a) 239 c.Add(&c, b).Sub(&c, b) 240 return c.Equal(a) 241 }, 242 genA, 243 genB, 244 )) 245 246 properties.Property("[BN254] mul & inverse should leave an element invariant", prop.ForAll( 247 func(a, b *E2) bool { 248 var c, d E2 249 d.Inverse(b) 250 c.Set(a) 251 c.Mul(&c, b).Mul(&c, &d) 252 return c.Equal(a) 253 }, 254 genA, 255 genB, 256 )) 257 258 properties.Property("[BN254] BatchInvertE2 should output the same result as Inverse", prop.ForAll( 259 func(a, b, c *E2) bool { 260 261 batch := BatchInvertE2([]E2{*a, *b, *c}) 262 a.Inverse(a) 263 b.Inverse(b) 264 c.Inverse(c) 265 return a.Equal(&batch[0]) && b.Equal(&batch[1]) && c.Equal(&batch[2]) 266 }, 267 genA, 268 genA, 269 genA, 270 )) 271 272 properties.Property("[BN254] mulGeneric & mul should be equal", prop.ForAll( 273 func(a, b *E2) bool { 274 var c, d E2 275 mulGenericE2(&c, a, b) 276 d.Mul(a, b) 277 return d.Equal(&c) 278 }, 279 genA, 280 genB, 281 )) 282 283 properties.Property("[BN254] inverse twice should leave an element invariant", prop.ForAll( 284 func(a *E2) bool { 285 var b E2 286 b.Inverse(a).Inverse(&b) 287 return a.Equal(&b) 288 }, 289 genA, 290 )) 291 292 properties.Property("[BN254] neg twice should leave an element invariant", prop.ForAll( 293 func(a *E2) bool { 294 var b E2 295 b.Neg(a).Neg(&b) 296 return a.Equal(&b) 297 }, 298 genA, 299 )) 300 301 properties.Property("[BN254] square and mul should output the same result", prop.ForAll( 302 func(a *E2) bool { 303 var b, c E2 304 b.Mul(a, a) 305 c.Square(a) 306 return b.Equal(&c) 307 }, 308 genA, 309 )) 310 311 properties.Property("[BN254] MulByElement MulByElement inverse should leave an element invariant", prop.ForAll( 312 func(a *E2, b fp.Element) bool { 313 var c E2 314 var d fp.Element 315 d.Inverse(&b) 316 c.MulByElement(a, &b).MulByElement(&c, &d) 317 return c.Equal(a) 318 }, 319 genA, 320 genfp, 321 )) 322 323 properties.Property("[BN254] Double and mul by 2 should output the same result", prop.ForAll( 324 func(a *E2) bool { 325 var b E2 326 var c fp.Element 327 c.SetUint64(2) 328 b.Double(a) 329 a.MulByElement(a, &c) 330 return a.Equal(&b) 331 }, 332 genA, 333 )) 334 335 properties.Property("[BN254] Mulbynonres mulbynonresinv should leave the element invariant", prop.ForAll( 336 func(a *E2) bool { 337 var b E2 338 b.MulByNonResidue(a).MulByNonResidueInv(&b) 339 return a.Equal(&b) 340 }, 341 genA, 342 )) 343 344 properties.Property("[BN254] a + pi(a), a-pi(a) should be real", prop.ForAll( 345 func(a *E2) bool { 346 var b, c, d E2 347 var e, f fp.Element 348 b.Conjugate(a) 349 c.Add(a, &b) 350 d.Sub(a, &b) 351 e.Double(&a.A0) 352 f.Double(&a.A1) 353 return c.A1.IsZero() && d.A0.IsZero() && e.Equal(&c.A0) && f.Equal(&d.A1) 354 }, 355 genA, 356 )) 357 358 properties.Property("[BN254] Legendre on square should output 1", prop.ForAll( 359 func(a *E2) bool { 360 var b E2 361 b.Square(a) 362 c := b.Legendre() 363 return c == 1 364 }, 365 genA, 366 )) 367 368 properties.Property("[BN254] square(sqrt) should leave an element invariant", prop.ForAll( 369 func(a *E2) bool { 370 var b, c, d, e E2 371 b.Square(a) 372 c.Sqrt(&b) 373 d.Square(&c) 374 e.Neg(a) 375 return (c.Equal(a) || c.Equal(&e)) && d.Equal(&b) 376 }, 377 genA, 378 )) 379 380 properties.Property("[BN254] neg(E2) == neg(E2.A0, E2.A1)", prop.ForAll( 381 func(a *E2) bool { 382 var b, c E2 383 b.Neg(a) 384 c.A0.Neg(&a.A0) 385 c.A1.Neg(&a.A1) 386 return c.Equal(&b) 387 }, 388 genA, 389 )) 390 391 properties.Property("[BN254] Cmp and LexicographicallyLargest should be consistent", prop.ForAll( 392 func(a *E2) bool { 393 var negA E2 394 negA.Neg(a) 395 cmpResult := a.Cmp(&negA) 396 lResult := a.LexicographicallyLargest() 397 if lResult && cmpResult == 1 { 398 return true 399 } 400 if !lResult && cmpResult != 1 { 401 return true 402 } 403 return false 404 }, 405 genA, 406 )) 407 408 properties.TestingRun(t, gopter.ConsoleReporter(false)) 409 410 } 411 412 // ------------------------------------------------------------ 413 // benches 414 415 func BenchmarkE2Add(b *testing.B) { 416 var a, c E2 417 _, _ = a.SetRandom() 418 _, _ = c.SetRandom() 419 b.ResetTimer() 420 for i := 0; i < b.N; i++ { 421 a.Add(&a, &c) 422 } 423 } 424 425 func BenchmarkE2Sub(b *testing.B) { 426 var a, c E2 427 _, _ = a.SetRandom() 428 _, _ = c.SetRandom() 429 b.ResetTimer() 430 for i := 0; i < b.N; i++ { 431 a.Sub(&a, &c) 432 } 433 } 434 435 func BenchmarkE2Mul(b *testing.B) { 436 var a, c E2 437 _, _ = a.SetRandom() 438 _, _ = c.SetRandom() 439 b.ResetTimer() 440 for i := 0; i < b.N; i++ { 441 a.Mul(&a, &c) 442 } 443 } 444 445 func BenchmarkE2MulByElement(b *testing.B) { 446 var a E2 447 var c fp.Element 448 _, _ = c.SetRandom() 449 _, _ = a.SetRandom() 450 b.ResetTimer() 451 for i := 0; i < b.N; i++ { 452 a.MulByElement(&a, &c) 453 } 454 } 455 456 func BenchmarkE2Square(b *testing.B) { 457 var a E2 458 _, _ = a.SetRandom() 459 b.ResetTimer() 460 for i := 0; i < b.N; i++ { 461 a.Square(&a) 462 } 463 } 464 465 func BenchmarkE2Sqrt(b *testing.B) { 466 var a E2 467 _, _ = a.SetRandom() 468 b.ResetTimer() 469 for i := 0; i < b.N; i++ { 470 a.Sqrt(&a) 471 } 472 } 473 474 func BenchmarkE2Exp(b *testing.B) { 475 var x E2 476 _, _ = x.SetRandom() 477 b1, _ := rand.Int(rand.Reader, fp.Modulus()) 478 b.ResetTimer() 479 for i := 0; i < b.N; i++ { 480 x.Exp(x, b1) 481 } 482 } 483 484 func BenchmarkE2Inverse(b *testing.B) { 485 var a E2 486 _, _ = a.SetRandom() 487 b.ResetTimer() 488 for i := 0; i < b.N; i++ { 489 a.Inverse(&a) 490 } 491 } 492 493 func BenchmarkE2MulNonRes(b *testing.B) { 494 var a E2 495 _, _ = a.SetRandom() 496 b.ResetTimer() 497 for i := 0; i < b.N; i++ { 498 a.MulByNonResidue(&a) 499 } 500 } 501 502 func BenchmarkE2MulNonResInv(b *testing.B) { 503 var a E2 504 _, _ = a.SetRandom() 505 b.ResetTimer() 506 for i := 0; i < b.N; i++ { 507 a.MulByNonResidueInv(&a) 508 } 509 } 510 511 func BenchmarkE2Conjugate(b *testing.B) { 512 var a E2 513 _, _ = a.SetRandom() 514 b.ResetTimer() 515 for i := 0; i < b.N; i++ { 516 a.Conjugate(&a) 517 } 518 } 519 520 func TestE2Div(t *testing.T) { 521 522 parameters := gopter.DefaultTestParameters() 523 properties := gopter.NewProperties(parameters) 524 525 genA := GenE2() 526 genB := GenE2() 527 528 properties.Property("[BN254] dividing then multiplying by the same element does nothing", prop.ForAll( 529 func(a, b *E2) bool { 530 var c E2 531 c.Div(a, b) 532 c.Mul(&c, b) 533 return c.Equal(a) 534 }, 535 genA, 536 genB, 537 )) 538 539 properties.TestingRun(t, gopter.ConsoleReporter(false)) 540 }