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