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