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  }