github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-761/internal/fptower/e6_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/bw6-761/fp" 22 "github.com/leanovate/gopter" 23 "github.com/leanovate/gopter/prop" 24 ) 25 26 // ------------------------------------------------------------ 27 // tests 28 29 func TestE6Serialization(t *testing.T) { 30 31 parameters := gopter.DefaultTestParameters() 32 parameters.MinSuccessfulTests = 100 33 34 properties := gopter.NewProperties(parameters) 35 36 genA := GenE6() 37 38 properties.Property("[BW6-761] SetBytes(Bytes()) should stay constant", prop.ForAll( 39 func(a *E6) bool { 40 var b E6 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 TestE6ReceiverIsOperand(t *testing.T) { 54 55 parameters := gopter.DefaultTestParameters() 56 parameters.MinSuccessfulTests = 100 57 58 properties := gopter.NewProperties(parameters) 59 60 genA := GenE6() 61 genB := GenE6() 62 63 properties.Property("[BW6-761] Having the receiver as operand (addition) should output the same result", prop.ForAll( 64 func(a, b *E6) bool { 65 var c, d E6 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("[BW6-761] Having the receiver as operand (sub) should output the same result", prop.ForAll( 77 func(a, b *E6) bool { 78 var c, d E6 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("[BW6-761] Having the receiver as operand (mul) should output the same result", prop.ForAll( 90 func(a, b *E6) bool { 91 var c, d E6 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("[BW6-761] Having the receiver as operand (square) should output the same result", prop.ForAll( 103 func(a *E6) bool { 104 var b E6 105 b.Square(a) 106 a.Square(a) 107 return a.Equal(&b) 108 }, 109 genA, 110 )) 111 112 properties.Property("[BW6-761] Having the receiver as operand (double) should output the same result", prop.ForAll( 113 func(a *E6) bool { 114 var b E6 115 b.Double(a) 116 a.Double(a) 117 return a.Equal(&b) 118 }, 119 genA, 120 )) 121 122 properties.Property("[BW6-761] Having the receiver as operand (Inverse) should output the same result", prop.ForAll( 123 func(a *E6) bool { 124 var b E6 125 b.Inverse(a) 126 a.Inverse(a) 127 return a.Equal(&b) 128 }, 129 genA, 130 )) 131 132 properties.Property("[BW6-761] Having the receiver as operand (Cyclotomic square) should output the same result", prop.ForAll( 133 func(a *E6) bool { 134 var b E6 135 b.CyclotomicSquare(a) 136 a.CyclotomicSquare(a) 137 return a.Equal(&b) 138 }, 139 genA, 140 )) 141 142 properties.Property("[BW6-761] Having the receiver as operand (Conjugate) should output the same result", prop.ForAll( 143 func(a *E6) bool { 144 var b E6 145 b.Conjugate(a) 146 a.Conjugate(a) 147 return a.Equal(&b) 148 }, 149 genA, 150 )) 151 152 properties.Property("[BW6-761] Having the receiver as operand (Frobenius) should output the same result", prop.ForAll( 153 func(a *E6) bool { 154 var b E6 155 b.Frobenius(a) 156 a.Frobenius(a) 157 return a.Equal(&b) 158 }, 159 genA, 160 )) 161 162 properties.TestingRun(t, gopter.ConsoleReporter(false)) 163 } 164 165 func TestE6Ops(t *testing.T) { 166 167 parameters := gopter.DefaultTestParameters() 168 parameters.MinSuccessfulTests = 100 169 170 properties := gopter.NewProperties(parameters) 171 172 genA := GenE6() 173 genB := GenE6() 174 genExp := GenFp() 175 176 properties.Property("[BW6-761] sub & add should leave an element invariant", prop.ForAll( 177 func(a, b *E6) bool { 178 var c E6 179 c.Set(a) 180 c.Add(&c, b).Sub(&c, b) 181 return c.Equal(a) 182 }, 183 genA, 184 genB, 185 )) 186 187 properties.Property("[BW6-761] mul & inverse should leave an element invariant", prop.ForAll( 188 func(a, b *E6) bool { 189 var c, d E6 190 d.Inverse(b) 191 c.Set(a) 192 c.Mul(&c, b).Mul(&c, &d) 193 return c.Equal(a) 194 }, 195 genA, 196 genB, 197 )) 198 199 properties.Property("[BW6-761] inverse twice should leave an element invariant", prop.ForAll( 200 func(a *E6) bool { 201 var b E6 202 b.Inverse(a).Inverse(&b) 203 return a.Equal(&b) 204 }, 205 genA, 206 )) 207 208 properties.Property("[BW6-761] square and mul should output the same result", prop.ForAll( 209 func(a *E6) bool { 210 var b, c E6 211 b.Mul(a, a) 212 c.Square(a) 213 return b.Equal(&c) 214 }, 215 genA, 216 )) 217 218 properties.Property("[BW6-761] a + pi(a), a-pi(a) should be real", prop.ForAll( 219 func(a *E6) bool { 220 var b, c, d E6 221 var e, f, g E3 222 b.Conjugate(a) 223 c.Add(a, &b) 224 d.Sub(a, &b) 225 e.Double(&a.B0) 226 f.Double(&a.B1) 227 return c.B1.Equal(&g) && d.B0.Equal(&g) && e.Equal(&c.B0) && f.Equal(&d.B1) 228 }, 229 genA, 230 )) 231 232 properties.Property("[BW6-761] Torus-based Compress/decompress E6 elements in the cyclotomic subgroup", prop.ForAll( 233 func(a *E6) bool { 234 var b E6 235 b.Conjugate(a) 236 a.Inverse(a) 237 b.Mul(&b, a) 238 a.Frobenius(&b).Mul(a, &b) 239 240 c, _ := a.CompressTorus() 241 d := c.DecompressTorus() 242 return a.Equal(&d) 243 }, 244 genA, 245 )) 246 247 properties.Property("[BW6-761] Torus-based batch Compress/decompress E6 elements in the cyclotomic subgroup", prop.ForAll( 248 func(a, e, f *E6) bool { 249 var b E6 250 b.Conjugate(a) 251 a.Inverse(a) 252 b.Mul(&b, a) 253 a.Frobenius(&b).Mul(a, &b) 254 255 e.CyclotomicSquare(a) 256 f.CyclotomicSquare(e) 257 258 c, _ := BatchCompressTorus([]E6{*a, *e, *f}) 259 d, _ := BatchDecompressTorus(c) 260 return a.Equal(&d[0]) && e.Equal(&d[1]) && f.Equal(&d[2]) 261 }, 262 genA, 263 genA, 264 genA, 265 )) 266 267 properties.Property("[BW6-761] pi**12=id", prop.ForAll( 268 func(a *E6) bool { 269 var b E6 270 b.Frobenius(a). 271 Frobenius(&b). 272 Frobenius(&b). 273 Frobenius(&b). 274 Frobenius(&b). 275 Frobenius(&b). 276 Frobenius(&b). 277 Frobenius(&b). 278 Frobenius(&b). 279 Frobenius(&b). 280 Frobenius(&b). 281 Frobenius(&b) 282 return b.Equal(a) 283 }, 284 genA, 285 )) 286 287 properties.Property("[BW6-761] cyclotomic square (Granger-Scott) and square should be the same in the cyclotomic subgroup", prop.ForAll( 288 func(a *E6) bool { 289 var b, c, d E6 290 b.Conjugate(a) 291 a.Inverse(a) 292 b.Mul(&b, a) 293 a.Frobenius(&b).Mul(a, &b) 294 c.Square(a) 295 d.CyclotomicSquare(a) 296 return c.Equal(&d) 297 }, 298 genA, 299 )) 300 301 properties.Property("[BW6-761] compressed cyclotomic square (Karabina) and square should be the same in the cyclotomic subgroup", prop.ForAll( 302 func(a *E6) bool { 303 var _a, b, c, d, _c, _d E6 304 _a.SetOne().Double(&_a) 305 306 // put a and _a in the cyclotomic subgroup 307 // a (g3 != 0 probably) 308 b.Conjugate(a) 309 a.Inverse(a) 310 b.Mul(&b, a) 311 a.Frobenius(&b).Mul(a, &b) 312 // _a (g3 == 0) 313 b.Conjugate(&_a) 314 _a.Inverse(&_a) 315 b.Mul(&b, &_a) 316 _a.Frobenius(&b).Mul(&_a, &b) 317 318 // case g3 != 0 319 c.Square(a) 320 d.CyclotomicSquareCompressed(a).DecompressKarabina(&d) 321 322 // case g3 == 0 323 _c.Square(&_a) 324 _d.CyclotomicSquareCompressed(&_a).DecompressKarabina(&_d) 325 326 return c.Equal(&d) 327 }, 328 genA, 329 )) 330 331 properties.Property("[BW6-761] Exp and CyclotomicExp results must be the same in the cyclotomic subgroup", prop.ForAll( 332 func(a *E6, e fp.Element) bool { 333 var b, c, d E6 334 // put in the cyclo subgroup 335 b.Conjugate(a) 336 a.Inverse(a) 337 b.Mul(&b, a) 338 a.Frobenius(&b).Mul(a, &b) 339 340 var _e big.Int 341 k := new(big.Int).SetUint64(6) 342 e.Exp(e, k) 343 e.BigInt(&_e) 344 345 c.Exp(*a, &_e) 346 d.CyclotomicExp(*a, &_e) 347 348 return c.Equal(&d) 349 }, 350 genA, 351 genExp, 352 )) 353 354 properties.Property("[BW6-761] Frobenius of x in E6 should be equal to x^q", prop.ForAll( 355 func(a *E6) bool { 356 var b, c E6 357 q := fp.Modulus() 358 b.Frobenius(a) 359 c.Exp(*a, q) 360 return c.Equal(&b) 361 }, 362 genA, 363 )) 364 365 properties.TestingRun(t, gopter.ConsoleReporter(false)) 366 367 } 368 369 // ------------------------------------------------------------ 370 // benches 371 372 func BenchmarkE6Add(b *testing.B) { 373 var a, c E6 374 a.SetRandom() 375 c.SetRandom() 376 b.ResetTimer() 377 for i := 0; i < b.N; i++ { 378 a.Add(&a, &c) 379 } 380 } 381 382 func BenchmarkE6Sub(b *testing.B) { 383 var a, c E6 384 a.SetRandom() 385 c.SetRandom() 386 b.ResetTimer() 387 for i := 0; i < b.N; i++ { 388 a.Sub(&a, &c) 389 } 390 } 391 392 func BenchmarkE6Mul(b *testing.B) { 393 var a, c E6 394 a.SetRandom() 395 c.SetRandom() 396 b.ResetTimer() 397 for i := 0; i < b.N; i++ { 398 a.Mul(&a, &c) 399 } 400 } 401 402 func BenchmarkE6Cyclosquare(b *testing.B) { 403 var a E6 404 a.SetRandom() 405 b.ResetTimer() 406 for i := 0; i < b.N; i++ { 407 a.CyclotomicSquare(&a) 408 } 409 } 410 411 func BenchmarkE6Square(b *testing.B) { 412 var a E6 413 a.SetRandom() 414 b.ResetTimer() 415 for i := 0; i < b.N; i++ { 416 a.Square(&a) 417 } 418 } 419 420 func BenchmarkE6Inverse(b *testing.B) { 421 var a E6 422 a.SetRandom() 423 b.ResetTimer() 424 for i := 0; i < b.N; i++ { 425 a.Inverse(&a) 426 } 427 } 428 429 func BenchmarkE6Conjugate(b *testing.B) { 430 var a E6 431 a.SetRandom() 432 b.ResetTimer() 433 for i := 0; i < b.N; i++ { 434 a.Conjugate(&a) 435 } 436 } 437 438 func BenchmarkE6Frobenius(b *testing.B) { 439 var a E6 440 a.SetRandom() 441 b.ResetTimer() 442 for i := 0; i < b.N; i++ { 443 a.Frobenius(&a) 444 } 445 } 446 447 func BenchmarkE6Expt(b *testing.B) { 448 var a, c E6 449 a.SetRandom() 450 b.ResetTimer() 451 c.Conjugate(&a) 452 a.Inverse(&a) 453 c.Mul(&c, &a) 454 455 a.Frobenius(&c). 456 Mul(&a, &c) 457 458 for i := 0; i < b.N; i++ { 459 a.Expt(&a) 460 } 461 }