github.com/consensys/gnark-crypto@v0.14.0/internal/generator/tower/template/fq12over6over2/tests/fq12.go.tmpl (about)

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