github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-378/internal/fptower/e12_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  // Code generated by consensys/gnark-crypto DO NOT EDIT
    16  
    17  package fptower
    18  
    19  import (
    20  	"math/big"
    21  	"testing"
    22  
    23  	"github.com/consensys/gnark-crypto/ecc/bls12-378/fp"
    24  	"github.com/leanovate/gopter"
    25  	"github.com/leanovate/gopter/prop"
    26  )
    27  
    28  // ------------------------------------------------------------
    29  // tests
    30  
    31  func TestE12Serialization(t *testing.T) {
    32  
    33  	t.Parallel()
    34  	parameters := gopter.DefaultTestParameters()
    35  	if testing.Short() {
    36  		parameters.MinSuccessfulTests = nbFuzzShort
    37  	} else {
    38  		parameters.MinSuccessfulTests = nbFuzz
    39  	}
    40  
    41  	properties := gopter.NewProperties(parameters)
    42  
    43  	genA := GenE12()
    44  
    45  	properties.Property("[BLS12-378] SetBytes(Bytes()) should stay constant", prop.ForAll(
    46  		func(a *E12) bool {
    47  			var b E12
    48  			buf := a.Bytes()
    49  			if err := b.SetBytes(buf[:]); err != nil {
    50  				return false
    51  			}
    52  			return a.Equal(&b)
    53  		},
    54  		genA,
    55  	))
    56  
    57  	properties.TestingRun(t, gopter.ConsoleReporter(false))
    58  }
    59  
    60  func TestE12ReceiverIsOperand(t *testing.T) {
    61  
    62  	parameters := gopter.DefaultTestParameters()
    63  	if testing.Short() {
    64  		parameters.MinSuccessfulTests = nbFuzzShort
    65  	} else {
    66  		parameters.MinSuccessfulTests = nbFuzz
    67  	}
    68  
    69  	properties := gopter.NewProperties(parameters)
    70  
    71  	genA := GenE12()
    72  	genB := GenE12()
    73  
    74  	properties.Property("[BLS12-378] Having the receiver as operand (addition) should output the same result", prop.ForAll(
    75  		func(a, b *E12) bool {
    76  			var c, d E12
    77  			d.Set(a)
    78  			c.Add(a, b)
    79  			a.Add(a, b)
    80  			b.Add(&d, b)
    81  			return a.Equal(b) && a.Equal(&c) && b.Equal(&c)
    82  		},
    83  		genA,
    84  		genB,
    85  	))
    86  
    87  	properties.Property("[BLS12-378] Having the receiver as operand (sub) should output the same result", prop.ForAll(
    88  		func(a, b *E12) bool {
    89  			var c, d E12
    90  			d.Set(a)
    91  			c.Sub(a, b)
    92  			a.Sub(a, b)
    93  			b.Sub(&d, b)
    94  			return a.Equal(b) && a.Equal(&c) && b.Equal(&c)
    95  		},
    96  		genA,
    97  		genB,
    98  	))
    99  
   100  	properties.Property("[BLS12-378] Having the receiver as operand (mul) should output the same result", prop.ForAll(
   101  		func(a, b *E12) bool {
   102  			var c, d E12
   103  			d.Set(a)
   104  			c.Mul(a, b)
   105  			a.Mul(a, b)
   106  			b.Mul(&d, b)
   107  			return a.Equal(b) && a.Equal(&c) && b.Equal(&c)
   108  		},
   109  		genA,
   110  		genB,
   111  	))
   112  
   113  	properties.Property("[BLS12-378] Having the receiver as operand (square) should output the same result", prop.ForAll(
   114  		func(a *E12) bool {
   115  			var b E12
   116  			b.Square(a)
   117  			a.Square(a)
   118  			return a.Equal(&b)
   119  		},
   120  		genA,
   121  	))
   122  
   123  	properties.Property("[BLS12-378] Having the receiver as operand (double) should output the same result", prop.ForAll(
   124  		func(a *E12) bool {
   125  			var b E12
   126  			b.Double(a)
   127  			a.Double(a)
   128  			return a.Equal(&b)
   129  		},
   130  		genA,
   131  	))
   132  
   133  	properties.Property("[BLS12-378] Having the receiver as operand (Inverse) should output the same result", prop.ForAll(
   134  		func(a *E12) bool {
   135  			var b E12
   136  			b.Inverse(a)
   137  			a.Inverse(a)
   138  			return a.Equal(&b)
   139  		},
   140  		genA,
   141  	))
   142  
   143  	properties.Property("[BLS12-378] Having the receiver as operand (Cyclotomic square) should output the same result", prop.ForAll(
   144  		func(a *E12) bool {
   145  			var b E12
   146  			b.CyclotomicSquare(a)
   147  			a.CyclotomicSquare(a)
   148  			return a.Equal(&b)
   149  		},
   150  		genA,
   151  	))
   152  
   153  	properties.Property("[BLS12-378] Having the receiver as operand (Conjugate) should output the same result", prop.ForAll(
   154  		func(a *E12) bool {
   155  			var b E12
   156  			b.Conjugate(a)
   157  			a.Conjugate(a)
   158  			return a.Equal(&b)
   159  		},
   160  		genA,
   161  	))
   162  
   163  	properties.Property("[BLS12-378] Having the receiver as operand (Frobenius) should output the same result", prop.ForAll(
   164  		func(a *E12) bool {
   165  			var b E12
   166  			b.Frobenius(a)
   167  			a.Frobenius(a)
   168  			return a.Equal(&b)
   169  		},
   170  		genA,
   171  	))
   172  
   173  	properties.Property("[BLS12-378] Having the receiver as operand (FrobeniusSquare) should output the same result", prop.ForAll(
   174  		func(a *E12) bool {
   175  			var b E12
   176  			b.FrobeniusSquare(a)
   177  			a.FrobeniusSquare(a)
   178  			return a.Equal(&b)
   179  		},
   180  		genA,
   181  	))
   182  
   183  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   184  }
   185  
   186  func TestE12Ops(t *testing.T) {
   187  
   188  	parameters := gopter.DefaultTestParameters()
   189  	if testing.Short() {
   190  		parameters.MinSuccessfulTests = nbFuzzShort
   191  	} else {
   192  		parameters.MinSuccessfulTests = nbFuzz
   193  	}
   194  
   195  	properties := gopter.NewProperties(parameters)
   196  
   197  	genA := GenE12()
   198  	genB := GenE12()
   199  	genExp := GenFp()
   200  
   201  	properties.Property("[BLS12-378] sub & add should leave an element invariant", prop.ForAll(
   202  		func(a, b *E12) bool {
   203  			var c E12
   204  			c.Set(a)
   205  			c.Add(&c, b).Sub(&c, b)
   206  			return c.Equal(a)
   207  		},
   208  		genA,
   209  		genB,
   210  	))
   211  
   212  	properties.Property("[BLS12-378] mul & inverse should leave an element invariant", prop.ForAll(
   213  		func(a, b *E12) bool {
   214  			var c, d E12
   215  			d.Inverse(b)
   216  			c.Set(a)
   217  			c.Mul(&c, b).Mul(&c, &d)
   218  			return c.Equal(a)
   219  		},
   220  		genA,
   221  		genB,
   222  	))
   223  
   224  	properties.Property("[BLS12-378] inverse twice should leave an element invariant", prop.ForAll(
   225  		func(a *E12) bool {
   226  			var b E12
   227  			b.Inverse(a).Inverse(&b)
   228  			return a.Equal(&b)
   229  		},
   230  		genA,
   231  	))
   232  
   233  	properties.Property("[BLS12-378] square and mul should output the same result", prop.ForAll(
   234  		func(a *E12) bool {
   235  			var b, c E12
   236  			b.Mul(a, a)
   237  			c.Square(a)
   238  			return b.Equal(&c)
   239  		},
   240  		genA,
   241  	))
   242  
   243  	properties.Property("[BLS12-378] a + pi(a), a-pi(a) should be real", prop.ForAll(
   244  		func(a *E12) bool {
   245  			var b, c, d E12
   246  			var e, f, g E6
   247  			b.Conjugate(a)
   248  			c.Add(a, &b)
   249  			d.Sub(a, &b)
   250  			e.Double(&a.C0)
   251  			f.Double(&a.C1)
   252  			return c.C1.Equal(&g) && d.C0.Equal(&g) && e.Equal(&c.C0) && f.Equal(&d.C1)
   253  		},
   254  		genA,
   255  	))
   256  
   257  	properties.Property("[BLS12-378] Torus-based Compress/decompress E12 elements in the cyclotomic subgroup", prop.ForAll(
   258  		func(a *E12) bool {
   259  			var b E12
   260  			b.Conjugate(a)
   261  			a.Inverse(a)
   262  			b.Mul(&b, a)
   263  			a.FrobeniusSquare(&b).Mul(a, &b)
   264  
   265  			c, _ := a.CompressTorus()
   266  			d := c.DecompressTorus()
   267  			return a.Equal(&d)
   268  		},
   269  		genA,
   270  	))
   271  
   272  	properties.Property("[BLS12-378] Torus-based batch Compress/decompress E12 elements in the cyclotomic subgroup", prop.ForAll(
   273  		func(a, e, f *E12) bool {
   274  			var b E12
   275  			b.Conjugate(a)
   276  			a.Inverse(a)
   277  			b.Mul(&b, a)
   278  			a.FrobeniusSquare(&b).Mul(a, &b)
   279  
   280  			e.CyclotomicSquare(a)
   281  			f.CyclotomicSquare(e)
   282  
   283  			c, _ := BatchCompressTorus([]E12{*a, *e, *f})
   284  			d, _ := BatchDecompressTorus(c)
   285  			return a.Equal(&d[0]) && e.Equal(&d[1]) && f.Equal(&d[2])
   286  		},
   287  		genA,
   288  		genA,
   289  		genA,
   290  	))
   291  
   292  	properties.Property("[BLS12-378] pi**12=id", prop.ForAll(
   293  		func(a *E12) bool {
   294  			var b E12
   295  			b.Frobenius(a).
   296  				Frobenius(&b).
   297  				Frobenius(&b).
   298  				Frobenius(&b).
   299  				Frobenius(&b).
   300  				Frobenius(&b).
   301  				Frobenius(&b).
   302  				Frobenius(&b).
   303  				Frobenius(&b).
   304  				Frobenius(&b).
   305  				Frobenius(&b).
   306  				Frobenius(&b)
   307  			return b.Equal(a)
   308  		},
   309  		genA,
   310  	))
   311  
   312  	properties.Property("[BLS12-378] (pi**2)**6=id", prop.ForAll(
   313  		func(a *E12) bool {
   314  			var b E12
   315  			b.FrobeniusSquare(a).
   316  				FrobeniusSquare(&b).
   317  				FrobeniusSquare(&b).
   318  				FrobeniusSquare(&b).
   319  				FrobeniusSquare(&b).
   320  				FrobeniusSquare(&b)
   321  			return b.Equal(a)
   322  		},
   323  		genA,
   324  	))
   325  
   326  	properties.Property("[BLS12-378] cyclotomic square (Granger-Scott) and square should be the same in the cyclotomic subgroup", prop.ForAll(
   327  		func(a *E12) bool {
   328  			var b, c, d E12
   329  			b.Conjugate(a)
   330  			a.Inverse(a)
   331  			b.Mul(&b, a)
   332  			a.FrobeniusSquare(&b).Mul(a, &b)
   333  			c.Square(a)
   334  			d.CyclotomicSquare(a)
   335  			return c.Equal(&d)
   336  		},
   337  		genA,
   338  	))
   339  
   340  	properties.Property("[BLS12-378] compressed cyclotomic square (Karabina) and square should be the same in the cyclotomic subgroup", prop.ForAll(
   341  		func(a *E12) bool {
   342  			var _a, b, c, d, _c, _d E12
   343  			_a.SetOne().Double(&_a)
   344  
   345  			// put a and _a in the cyclotomic subgroup
   346  			// a (g3 != 0 probably)
   347  			b.Conjugate(a)
   348  			a.Inverse(a)
   349  			b.Mul(&b, a)
   350  			a.FrobeniusSquare(&b).Mul(a, &b)
   351  			// _a (g3 == 0)
   352  			b.Conjugate(&_a)
   353  			_a.Inverse(&_a)
   354  			b.Mul(&b, &_a)
   355  			_a.FrobeniusSquare(&b).Mul(&_a, &b)
   356  
   357  			// case g3 != 0
   358  			c.Square(a)
   359  			d.CyclotomicSquareCompressed(a).DecompressKarabina(&d)
   360  
   361  			// case g3 == 0
   362  			_c.Square(&_a)
   363  			_d.CyclotomicSquareCompressed(&_a).DecompressKarabina(&_d)
   364  
   365  			return c.Equal(&d)
   366  		},
   367  		genA,
   368  	))
   369  
   370  	properties.Property("[BLS12-378] batch decompress and individual decompress (Karabina) should be the same", prop.ForAll(
   371  		func(a *E12) bool {
   372  			var _a, b E12
   373  			_a.SetOne().Double(&_a)
   374  
   375  			// put a and _a in the cyclotomic subgroup
   376  			// a (g3 !=0 probably)
   377  			b.Conjugate(a)
   378  			a.Inverse(a)
   379  			b.Mul(&b, a)
   380  			a.FrobeniusSquare(&b).Mul(a, &b)
   381  			// _a (g3 == 0)
   382  			b.Conjugate(&_a)
   383  			_a.Inverse(&_a)
   384  			b.Mul(&b, &_a)
   385  			_a.FrobeniusSquare(&b).Mul(&_a, &b)
   386  
   387  			var a2, a4, a17 E12
   388  			a2.Set(&_a)
   389  			a4.Set(a)
   390  			a17.Set(a)
   391  			a2.nSquareCompressed(2) // case g3 == 0
   392  			a4.nSquareCompressed(4)
   393  			a17.nSquareCompressed(17)
   394  			batch := BatchDecompressKarabina([]E12{a2, a4, a17})
   395  			a2.DecompressKarabina(&a2)
   396  			a4.DecompressKarabina(&a4)
   397  			a17.DecompressKarabina(&a17)
   398  
   399  			return a2.Equal(&batch[0]) && a4.Equal(&batch[1]) && a17.Equal(&batch[2])
   400  		},
   401  		genA,
   402  	))
   403  
   404  	properties.Property("[BLS12-378] Exp and CyclotomicExp results must be the same in the cyclotomic subgroup", prop.ForAll(
   405  		func(a *E12, e fp.Element) bool {
   406  			var b, c, d E12
   407  			// put in the cyclo subgroup
   408  			b.Conjugate(a)
   409  			a.Inverse(a)
   410  			b.Mul(&b, a)
   411  			a.FrobeniusSquare(&b).Mul(a, &b)
   412  
   413  			var _e big.Int
   414  			k := new(big.Int).SetUint64(12)
   415  			e.Exp(e, k)
   416  			e.BigInt(&_e)
   417  
   418  			c.Exp(*a, &_e)
   419  			d.CyclotomicExp(*a, &_e)
   420  
   421  			return c.Equal(&d)
   422  		},
   423  		genA,
   424  		genExp,
   425  	))
   426  
   427  	properties.Property("[BLS12-378] Frobenius of x in E12 should be equal to x^q", prop.ForAll(
   428  		func(a *E12) bool {
   429  			var b, c E12
   430  			q := fp.Modulus()
   431  			b.Frobenius(a)
   432  			c.Exp(*a, q)
   433  			return c.Equal(&b)
   434  		},
   435  		genA,
   436  	))
   437  
   438  	properties.Property("[BLS12-378] FrobeniusSquare of x in E12 should be equal to x^(q^2)", prop.ForAll(
   439  		func(a *E12) bool {
   440  			var b, c E12
   441  			q := fp.Modulus()
   442  			b.FrobeniusSquare(a)
   443  			c.Exp(*a, q).Exp(c, q)
   444  			return c.Equal(&b)
   445  		},
   446  		genA,
   447  	))
   448  
   449  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   450  
   451  }
   452  
   453  // ------------------------------------------------------------
   454  // benches
   455  
   456  func BenchmarkE12Add(b *testing.B) {
   457  	var a, c E12
   458  	_, _ = a.SetRandom()
   459  	_, _ = c.SetRandom()
   460  	b.ResetTimer()
   461  	for i := 0; i < b.N; i++ {
   462  		a.Add(&a, &c)
   463  	}
   464  }
   465  
   466  func BenchmarkE12Sub(b *testing.B) {
   467  	var a, c E12
   468  	_, _ = a.SetRandom()
   469  	_, _ = c.SetRandom()
   470  	b.ResetTimer()
   471  	for i := 0; i < b.N; i++ {
   472  		a.Sub(&a, &c)
   473  	}
   474  }
   475  
   476  func BenchmarkE12Mul(b *testing.B) {
   477  	var a, c E12
   478  	_, _ = a.SetRandom()
   479  	_, _ = c.SetRandom()
   480  	b.ResetTimer()
   481  	for i := 0; i < b.N; i++ {
   482  		a.Mul(&a, &c)
   483  	}
   484  }
   485  
   486  func BenchmarkE12Cyclosquare(b *testing.B) {
   487  	var a E12
   488  	_, _ = a.SetRandom()
   489  	b.ResetTimer()
   490  	for i := 0; i < b.N; i++ {
   491  		a.CyclotomicSquare(&a)
   492  	}
   493  }
   494  
   495  func BenchmarkE12Square(b *testing.B) {
   496  	var a E12
   497  	_, _ = a.SetRandom()
   498  	b.ResetTimer()
   499  	for i := 0; i < b.N; i++ {
   500  		a.Square(&a)
   501  	}
   502  }
   503  
   504  func BenchmarkE12Inverse(b *testing.B) {
   505  	var a E12
   506  	_, _ = a.SetRandom()
   507  	b.ResetTimer()
   508  	for i := 0; i < b.N; i++ {
   509  		a.Inverse(&a)
   510  	}
   511  }
   512  
   513  func BenchmarkE12Conjugate(b *testing.B) {
   514  	var a E12
   515  	_, _ = a.SetRandom()
   516  	b.ResetTimer()
   517  	for i := 0; i < b.N; i++ {
   518  		a.Conjugate(&a)
   519  	}
   520  }
   521  
   522  func BenchmarkE12Frobenius(b *testing.B) {
   523  	var a E12
   524  	_, _ = a.SetRandom()
   525  	b.ResetTimer()
   526  	for i := 0; i < b.N; i++ {
   527  		a.Frobenius(&a)
   528  	}
   529  }
   530  
   531  func BenchmarkE12FrobeniusSquare(b *testing.B) {
   532  	var a E12
   533  	_, _ = a.SetRandom()
   534  	b.ResetTimer()
   535  	for i := 0; i < b.N; i++ {
   536  		a.FrobeniusSquare(&a)
   537  	}
   538  }
   539  
   540  func BenchmarkE12Expt(b *testing.B) {
   541  	var a E12
   542  	_, _ = a.SetRandom()
   543  	b.ResetTimer()
   544  	for i := 0; i < b.N; i++ {
   545  		a.Expt(&a)
   546  	}
   547  }
   548  
   549  func TestE12Div(t *testing.T) {
   550  
   551  	parameters := gopter.DefaultTestParameters()
   552  	properties := gopter.NewProperties(parameters)
   553  
   554  	genA := GenE12()
   555  	genB := GenE12()
   556  
   557  	properties.Property("[BLS12-378] dividing then multiplying by the same element does nothing", prop.ForAll(
   558  		func(a, b *E12) bool {
   559  			var c E12
   560  			c.Div(a, b)
   561  			c.Mul(&c, b)
   562  			return c.Equal(a)
   563  		},
   564  		genA,
   565  		genB,
   566  	))
   567  
   568  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   569  }