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