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