github.com/consensys/gnark-crypto@v0.14.0/ecc/bls24-315/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-315/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-315] 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-315] 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-315] 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-315] 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-315] 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-315] 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-315] 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-315] 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-315] 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-315] 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-315] 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-315] 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-315] 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-315] 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-315] 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-315] 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-315] 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-315] 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-315] (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-315] (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-315] 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-315] 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] batch decompress and individual decompress (Karabina) should be the same", prop.ForAll(
   400  		func(a *E24) bool {
   401  			var _a, b E24
   402  			_a.SetOne().Double(&_a)
   403  
   404  			// put a and _a in the cyclotomic subgroup
   405  			// a (g3 !=0 probably)
   406  			b.Conjugate(a)
   407  			a.Inverse(a)
   408  			b.Mul(&b, a)
   409  			a.FrobeniusQuad(&b).Mul(a, &b)
   410  			// _a (g3 == 0)
   411  			b.Conjugate(&_a)
   412  			_a.Inverse(&_a)
   413  			b.Mul(&b, &_a)
   414  			_a.FrobeniusQuad(&b).Mul(&_a, &b)
   415  
   416  			var a2, a4, a17 E24
   417  			a2.Set(&_a)
   418  			a4.Set(a)
   419  			a17.Set(a)
   420  			a2.nSquareCompressed(2) // case g3 == 0
   421  			a4.nSquareCompressed(4)
   422  			a17.nSquareCompressed(17)
   423  			batch := BatchDecompressKarabina([]E24{a2, a4, a17})
   424  			a2.DecompressKarabina(&a2)
   425  			a4.DecompressKarabina(&a4)
   426  			a17.DecompressKarabina(&a17)
   427  
   428  			return a2.Equal(&batch[0]) && a4.Equal(&batch[1]) && a17.Equal(&batch[2])
   429  		},
   430  		genA,
   431  	))
   432  
   433  	properties.Property("[BLS24-315] Exp and CyclotomicExp results must be the same in the cyclotomic subgroup", prop.ForAll(
   434  		func(a *E24, e fp.Element) bool {
   435  			var b, c, d E24
   436  			// put in the cyclo subgroup
   437  			b.Conjugate(a)
   438  			a.Inverse(a)
   439  			b.Mul(&b, a)
   440  			a.FrobeniusQuad(&b).Mul(a, &b)
   441  
   442  			var _e big.Int
   443  			k := new(big.Int).SetUint64(24)
   444  			e.Exp(e, k)
   445  			e.BigInt(&_e)
   446  
   447  			c.Exp(*a, &_e)
   448  			d.CyclotomicExp(*a, &_e)
   449  
   450  			return c.Equal(&d)
   451  		},
   452  		genA,
   453  		genExp,
   454  	))
   455  
   456  	properties.Property("[BLS24-315] Frobenius of x in E24 should be equal to x^q", prop.ForAll(
   457  		func(a *E24) bool {
   458  			var b, c E24
   459  			q := fp.Modulus()
   460  			b.Frobenius(a)
   461  			c.Set(a)
   462  			c.Exp(c, q)
   463  			return c.Equal(&b)
   464  		},
   465  		genA,
   466  	))
   467  
   468  	properties.Property("[BLS24-315] FrobeniusSquare of x in E24 should be equal to x^(q^2)", prop.ForAll(
   469  		func(a *E24) bool {
   470  			var b, c E24
   471  			q := fp.Modulus()
   472  			b.FrobeniusSquare(a)
   473  			c.Exp(*a, q).Exp(c, q)
   474  			return c.Equal(&b)
   475  		},
   476  		genA,
   477  	))
   478  
   479  	properties.Property("[BLS24-315] FrobeniusQuad of x in E24 should be equal to x^(q^4)", prop.ForAll(
   480  		func(a *E24) bool {
   481  			var b, c E24
   482  			q := fp.Modulus()
   483  			b.FrobeniusQuad(a)
   484  			c.Exp(*a, q).Exp(c, q).Exp(c, q).Exp(c, q)
   485  			return c.Equal(&b)
   486  		},
   487  		genA,
   488  	))
   489  
   490  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   491  
   492  }
   493  
   494  // ------------------------------------------------------------
   495  // benches
   496  
   497  func BenchmarkE24Add(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.Add(&a, &c)
   504  	}
   505  }
   506  
   507  func BenchmarkE24Sub(b *testing.B) {
   508  	var a, c E24
   509  	a.SetRandom()
   510  	c.SetRandom()
   511  	b.ResetTimer()
   512  	for i := 0; i < b.N; i++ {
   513  		a.Sub(&a, &c)
   514  	}
   515  }
   516  
   517  func BenchmarkE24Mul(b *testing.B) {
   518  	var a, c E24
   519  	a.SetRandom()
   520  	c.SetRandom()
   521  	b.ResetTimer()
   522  	for i := 0; i < b.N; i++ {
   523  		a.Mul(&a, &c)
   524  	}
   525  }
   526  
   527  func BenchmarkE24Cyclosquare(b *testing.B) {
   528  	var a E24
   529  	a.SetRandom()
   530  	b.ResetTimer()
   531  	for i := 0; i < b.N; i++ {
   532  		a.CyclotomicSquare(&a)
   533  	}
   534  }
   535  
   536  func BenchmarkE24Square(b *testing.B) {
   537  	var a E24
   538  	a.SetRandom()
   539  	b.ResetTimer()
   540  	for i := 0; i < b.N; i++ {
   541  		a.Square(&a)
   542  	}
   543  }
   544  
   545  func BenchmarkE24Inverse(b *testing.B) {
   546  	var a E24
   547  	a.SetRandom()
   548  	b.ResetTimer()
   549  	for i := 0; i < b.N; i++ {
   550  		a.Inverse(&a)
   551  	}
   552  }
   553  
   554  func BenchmarkE24Conjugate(b *testing.B) {
   555  	var a E24
   556  	a.SetRandom()
   557  	b.ResetTimer()
   558  	for i := 0; i < b.N; i++ {
   559  		a.Conjugate(&a)
   560  	}
   561  }
   562  
   563  func BenchmarkE24Frobenius(b *testing.B) {
   564  	var a E24
   565  	a.SetRandom()
   566  	b.ResetTimer()
   567  	for i := 0; i < b.N; i++ {
   568  		a.Frobenius(&a)
   569  	}
   570  }
   571  
   572  func BenchmarkE24FrobeniusSquare(b *testing.B) {
   573  	var a E24
   574  	a.SetRandom()
   575  	b.ResetTimer()
   576  	for i := 0; i < b.N; i++ {
   577  		a.FrobeniusSquare(&a)
   578  	}
   579  }
   580  
   581  func BenchmarkE24FrobeniusQuad(b *testing.B) {
   582  	var a E24
   583  	a.SetRandom()
   584  	b.ResetTimer()
   585  	for i := 0; i < b.N; i++ {
   586  		a.FrobeniusQuad(&a)
   587  	}
   588  }
   589  
   590  func BenchmarkE24Expt(b *testing.B) {
   591  	var a E24
   592  	a.SetRandom()
   593  	b.ResetTimer()
   594  	for i := 0; i < b.N; i++ {
   595  		a.Expt(&a)
   596  	}
   597  }