github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-378/internal/fptower/e2_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  	"crypto/rand"
    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  const (
    32  	nbFuzzShort = 10
    33  	nbFuzz      = 50
    34  )
    35  
    36  func TestE2ReceiverIsOperand(t *testing.T) {
    37  
    38  	t.Parallel()
    39  	parameters := gopter.DefaultTestParameters()
    40  	if testing.Short() {
    41  		parameters.MinSuccessfulTests = nbFuzzShort
    42  	} else {
    43  		parameters.MinSuccessfulTests = nbFuzz
    44  	}
    45  
    46  	properties := gopter.NewProperties(parameters)
    47  
    48  	genA := GenE2()
    49  	genB := GenE2()
    50  	genfp := GenFp()
    51  
    52  	properties.Property("[BLS12-378] Having the receiver as operand (addition) should output the same result", prop.ForAll(
    53  		func(a, b *E2) bool {
    54  			var c, d E2
    55  			d.Set(a)
    56  			c.Add(a, b)
    57  			a.Add(a, b)
    58  			b.Add(&d, b)
    59  			return a.Equal(b) && a.Equal(&c) && b.Equal(&c)
    60  		},
    61  		genA,
    62  		genB,
    63  	))
    64  
    65  	properties.Property("[BLS12-378] Having the receiver as operand (sub) should output the same result", prop.ForAll(
    66  		func(a, b *E2) bool {
    67  			var c, d E2
    68  			d.Set(a)
    69  			c.Sub(a, b)
    70  			a.Sub(a, b)
    71  			b.Sub(&d, b)
    72  			return a.Equal(b) && a.Equal(&c) && b.Equal(&c)
    73  		},
    74  		genA,
    75  		genB,
    76  	))
    77  
    78  	properties.Property("[BLS12-378] Having the receiver as operand (mul) should output the same result", prop.ForAll(
    79  		func(a, b *E2) bool {
    80  			var c, d E2
    81  			d.Set(a)
    82  			c.Mul(a, b)
    83  			a.Mul(a, b)
    84  			b.Mul(&d, b)
    85  			return a.Equal(b) && a.Equal(&c) && b.Equal(&c)
    86  		},
    87  		genA,
    88  		genB,
    89  	))
    90  
    91  	properties.Property("[BLS12-378] Having the receiver as operand (square) should output the same result", prop.ForAll(
    92  		func(a *E2) bool {
    93  			var b E2
    94  			b.Square(a)
    95  			a.Square(a)
    96  			return a.Equal(&b)
    97  		},
    98  		genA,
    99  	))
   100  
   101  	properties.Property("[BLS12-378] Having the receiver as operand (neg) should output the same result", prop.ForAll(
   102  		func(a *E2) bool {
   103  			var b E2
   104  			b.Neg(a)
   105  			a.Neg(a)
   106  			return a.Equal(&b)
   107  		},
   108  		genA,
   109  	))
   110  
   111  	properties.Property("[BLS12-378] Having the receiver as operand (double) should output the same result", prop.ForAll(
   112  		func(a *E2) bool {
   113  			var b E2
   114  			b.Double(a)
   115  			a.Double(a)
   116  			return a.Equal(&b)
   117  		},
   118  		genA,
   119  	))
   120  
   121  	properties.Property("[BLS12-378] Having the receiver as operand (mul by non residue) should output the same result", prop.ForAll(
   122  		func(a *E2) bool {
   123  			var b E2
   124  			b.MulByNonResidue(a)
   125  			a.MulByNonResidue(a)
   126  			return a.Equal(&b)
   127  		},
   128  		genA,
   129  	))
   130  
   131  	properties.Property("[BLS12-378] Having the receiver as operand (mul by non residue inverse) should output the same result", prop.ForAll(
   132  		func(a *E2) bool {
   133  			var b E2
   134  			b.MulByNonResidueInv(a)
   135  			a.MulByNonResidueInv(a)
   136  			return a.Equal(&b)
   137  		},
   138  		genA,
   139  	))
   140  
   141  	properties.Property("[BLS12-378] Having the receiver as operand (Inverse) should output the same result", prop.ForAll(
   142  		func(a *E2) bool {
   143  			var b E2
   144  			b.Inverse(a)
   145  			a.Inverse(a)
   146  			return a.Equal(&b)
   147  		},
   148  		genA,
   149  	))
   150  
   151  	properties.Property("[BLS12-378] Having the receiver as operand (Conjugate) should output the same result", prop.ForAll(
   152  		func(a *E2) bool {
   153  			var b E2
   154  			b.Conjugate(a)
   155  			a.Conjugate(a)
   156  			return a.Equal(&b)
   157  		},
   158  		genA,
   159  	))
   160  
   161  	properties.Property("[BLS12-378] Having the receiver as operand (mul by element) should output the same result", prop.ForAll(
   162  		func(a *E2, b fp.Element) bool {
   163  			var c E2
   164  			c.MulByElement(a, &b)
   165  			a.MulByElement(a, &b)
   166  			return a.Equal(&c)
   167  		},
   168  		genA,
   169  		genfp,
   170  	))
   171  
   172  	properties.Property("[BLS12-378] Having the receiver as operand (Sqrt) should output the same result", prop.ForAll(
   173  		func(a *E2) bool {
   174  			var b, c, d, s E2
   175  
   176  			s.Square(a)
   177  			a.Set(&s)
   178  			b.Set(&s)
   179  
   180  			a.Sqrt(a)
   181  			b.Sqrt(&b)
   182  
   183  			c.Square(a)
   184  			d.Square(&b)
   185  			return c.Equal(&d)
   186  		},
   187  		genA,
   188  	))
   189  
   190  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   191  
   192  }
   193  
   194  func TestE2MulMaxed(t *testing.T) {
   195  	// let's pick a and b, with maxed A0 and A1
   196  	var a, b E2
   197  	fpMaxValue := fp.Element{
   198  		11045256207009841153,
   199  		14886639130118979584,
   200  		10956628289047010687,
   201  		9513184293603517222,
   202  		6038022134869067682,
   203  		283357621510263184,
   204  	}
   205  	fpMaxValue[0]--
   206  
   207  	a.A0 = fpMaxValue
   208  	a.A1 = fpMaxValue
   209  	b.A0 = fpMaxValue
   210  	b.A1 = fpMaxValue
   211  
   212  	var c, d E2
   213  	d.Inverse(&b)
   214  	c.Set(&a)
   215  	c.Mul(&c, &b).Mul(&c, &d)
   216  	if !c.Equal(&a) {
   217  		t.Fatal("mul with max fp failed")
   218  	}
   219  }
   220  
   221  func TestE2Ops(t *testing.T) {
   222  
   223  	t.Parallel()
   224  	parameters := gopter.DefaultTestParameters()
   225  	if testing.Short() {
   226  		parameters.MinSuccessfulTests = nbFuzzShort
   227  	} else {
   228  		parameters.MinSuccessfulTests = nbFuzz
   229  	}
   230  
   231  	properties := gopter.NewProperties(parameters)
   232  
   233  	genA := GenE2()
   234  	genB := GenE2()
   235  	genfp := GenFp()
   236  
   237  	properties.Property("[BLS12-378] sub & add should leave an element invariant", prop.ForAll(
   238  		func(a, b *E2) bool {
   239  			var c E2
   240  			c.Set(a)
   241  			c.Add(&c, b).Sub(&c, b)
   242  			return c.Equal(a)
   243  		},
   244  		genA,
   245  		genB,
   246  	))
   247  
   248  	properties.Property("[BLS12-378] mul & inverse should leave an element invariant", prop.ForAll(
   249  		func(a, b *E2) bool {
   250  			var c, d E2
   251  			d.Inverse(b)
   252  			c.Set(a)
   253  			c.Mul(&c, b).Mul(&c, &d)
   254  			return c.Equal(a)
   255  		},
   256  		genA,
   257  		genB,
   258  	))
   259  
   260  	properties.Property("[BLS12-378] BatchInvertE2 should output the same result as Inverse", prop.ForAll(
   261  		func(a, b, c *E2) bool {
   262  
   263  			batch := BatchInvertE2([]E2{*a, *b, *c})
   264  			a.Inverse(a)
   265  			b.Inverse(b)
   266  			c.Inverse(c)
   267  			return a.Equal(&batch[0]) && b.Equal(&batch[1]) && c.Equal(&batch[2])
   268  		},
   269  		genA,
   270  		genA,
   271  		genA,
   272  	))
   273  
   274  	properties.Property("[BLS12-378] inverse twice should leave an element invariant", prop.ForAll(
   275  		func(a *E2) bool {
   276  			var b E2
   277  			b.Inverse(a).Inverse(&b)
   278  			return a.Equal(&b)
   279  		},
   280  		genA,
   281  	))
   282  
   283  	properties.Property("[BLS12-378] neg twice should leave an element invariant", prop.ForAll(
   284  		func(a *E2) bool {
   285  			var b E2
   286  			b.Neg(a).Neg(&b)
   287  			return a.Equal(&b)
   288  		},
   289  		genA,
   290  	))
   291  
   292  	properties.Property("[BLS12-378] square and mul should output the same result", prop.ForAll(
   293  		func(a *E2) bool {
   294  			var b, c E2
   295  			b.Mul(a, a)
   296  			c.Square(a)
   297  			return b.Equal(&c)
   298  		},
   299  		genA,
   300  	))
   301  
   302  	properties.Property("[BLS12-378] MulByElement MulByElement inverse should leave an element invariant", prop.ForAll(
   303  		func(a *E2, b fp.Element) bool {
   304  			var c E2
   305  			var d fp.Element
   306  			d.Inverse(&b)
   307  			c.MulByElement(a, &b).MulByElement(&c, &d)
   308  			return c.Equal(a)
   309  		},
   310  		genA,
   311  		genfp,
   312  	))
   313  
   314  	properties.Property("[BLS12-378] Double and mul by 2 should output the same result", prop.ForAll(
   315  		func(a *E2) bool {
   316  			var b E2
   317  			var c fp.Element
   318  			c.SetUint64(2)
   319  			b.Double(a)
   320  			a.MulByElement(a, &c)
   321  			return a.Equal(&b)
   322  		},
   323  		genA,
   324  	))
   325  
   326  	properties.Property("[BLS12-378] Mulbynonres mulbynonresinv should leave the element invariant", prop.ForAll(
   327  		func(a *E2) bool {
   328  			var b E2
   329  			b.MulByNonResidue(a).MulByNonResidueInv(&b)
   330  			return a.Equal(&b)
   331  		},
   332  		genA,
   333  	))
   334  
   335  	properties.Property("[BLS12-378] a + pi(a), a-pi(a) should be real", prop.ForAll(
   336  		func(a *E2) bool {
   337  			var b, c, d E2
   338  			var e, f fp.Element
   339  			b.Conjugate(a)
   340  			c.Add(a, &b)
   341  			d.Sub(a, &b)
   342  			e.Double(&a.A0)
   343  			f.Double(&a.A1)
   344  			return c.A1.IsZero() && d.A0.IsZero() && e.Equal(&c.A0) && f.Equal(&d.A1)
   345  		},
   346  		genA,
   347  	))
   348  
   349  	properties.Property("[BLS12-378] Legendre on square should output 1", prop.ForAll(
   350  		func(a *E2) bool {
   351  			var b E2
   352  			b.Square(a)
   353  			c := b.Legendre()
   354  			return c == 1
   355  		},
   356  		genA,
   357  	))
   358  
   359  	properties.Property("[BLS12-378] square(sqrt) should leave an element invariant", prop.ForAll(
   360  		func(a *E2) bool {
   361  			var b, c, d, e E2
   362  			b.Square(a)
   363  			c.Sqrt(&b)
   364  			d.Square(&c)
   365  			e.Neg(a)
   366  			return (c.Equal(a) || c.Equal(&e)) && d.Equal(&b)
   367  		},
   368  		genA,
   369  	))
   370  
   371  	properties.Property("[BLS12-378] neg(E2) == neg(E2.A0, E2.A1)", prop.ForAll(
   372  		func(a *E2) bool {
   373  			var b, c E2
   374  			b.Neg(a)
   375  			c.A0.Neg(&a.A0)
   376  			c.A1.Neg(&a.A1)
   377  			return c.Equal(&b)
   378  		},
   379  		genA,
   380  	))
   381  
   382  	properties.Property("[BLS12-378] Cmp and LexicographicallyLargest should be consistent", prop.ForAll(
   383  		func(a *E2) bool {
   384  			var negA E2
   385  			negA.Neg(a)
   386  			cmpResult := a.Cmp(&negA)
   387  			lResult := a.LexicographicallyLargest()
   388  			if lResult && cmpResult == 1 {
   389  				return true
   390  			}
   391  			if !lResult && cmpResult != 1 {
   392  				return true
   393  			}
   394  			return false
   395  		},
   396  		genA,
   397  	))
   398  
   399  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   400  
   401  }
   402  
   403  // ------------------------------------------------------------
   404  // benches
   405  
   406  func BenchmarkE2Add(b *testing.B) {
   407  	var a, c E2
   408  	_, _ = a.SetRandom()
   409  	_, _ = c.SetRandom()
   410  	b.ResetTimer()
   411  	for i := 0; i < b.N; i++ {
   412  		a.Add(&a, &c)
   413  	}
   414  }
   415  
   416  func BenchmarkE2Sub(b *testing.B) {
   417  	var a, c E2
   418  	_, _ = a.SetRandom()
   419  	_, _ = c.SetRandom()
   420  	b.ResetTimer()
   421  	for i := 0; i < b.N; i++ {
   422  		a.Sub(&a, &c)
   423  	}
   424  }
   425  
   426  func BenchmarkE2Mul(b *testing.B) {
   427  	var a, c E2
   428  	_, _ = a.SetRandom()
   429  	_, _ = c.SetRandom()
   430  	b.ResetTimer()
   431  	for i := 0; i < b.N; i++ {
   432  		a.Mul(&a, &c)
   433  	}
   434  }
   435  
   436  func BenchmarkE2MulByElement(b *testing.B) {
   437  	var a E2
   438  	var c fp.Element
   439  	_, _ = c.SetRandom()
   440  	_, _ = a.SetRandom()
   441  	b.ResetTimer()
   442  	for i := 0; i < b.N; i++ {
   443  		a.MulByElement(&a, &c)
   444  	}
   445  }
   446  
   447  func BenchmarkE2Square(b *testing.B) {
   448  	var a E2
   449  	_, _ = a.SetRandom()
   450  	b.ResetTimer()
   451  	for i := 0; i < b.N; i++ {
   452  		a.Square(&a)
   453  	}
   454  }
   455  
   456  func BenchmarkE2Sqrt(b *testing.B) {
   457  	var a E2
   458  	_, _ = a.SetRandom()
   459  	b.ResetTimer()
   460  	for i := 0; i < b.N; i++ {
   461  		a.Sqrt(&a)
   462  	}
   463  }
   464  
   465  func BenchmarkE2Exp(b *testing.B) {
   466  	var x E2
   467  	_, _ = x.SetRandom()
   468  	b1, _ := rand.Int(rand.Reader, fp.Modulus())
   469  	b.ResetTimer()
   470  	for i := 0; i < b.N; i++ {
   471  		x.Exp(x, b1)
   472  	}
   473  }
   474  
   475  func BenchmarkE2Inverse(b *testing.B) {
   476  	var a E2
   477  	_, _ = a.SetRandom()
   478  	b.ResetTimer()
   479  	for i := 0; i < b.N; i++ {
   480  		a.Inverse(&a)
   481  	}
   482  }
   483  
   484  func BenchmarkE2MulNonRes(b *testing.B) {
   485  	var a E2
   486  	_, _ = a.SetRandom()
   487  	b.ResetTimer()
   488  	for i := 0; i < b.N; i++ {
   489  		a.MulByNonResidue(&a)
   490  	}
   491  }
   492  
   493  func BenchmarkE2MulNonResInv(b *testing.B) {
   494  	var a E2
   495  	_, _ = a.SetRandom()
   496  	b.ResetTimer()
   497  	for i := 0; i < b.N; i++ {
   498  		a.MulByNonResidueInv(&a)
   499  	}
   500  }
   501  
   502  func BenchmarkE2Conjugate(b *testing.B) {
   503  	var a E2
   504  	_, _ = a.SetRandom()
   505  	b.ResetTimer()
   506  	for i := 0; i < b.N; i++ {
   507  		a.Conjugate(&a)
   508  	}
   509  }
   510  
   511  func TestE2Div(t *testing.T) {
   512  
   513  	parameters := gopter.DefaultTestParameters()
   514  	properties := gopter.NewProperties(parameters)
   515  
   516  	genA := GenE2()
   517  	genB := GenE2()
   518  
   519  	properties.Property("[BLS12-378] dividing then multiplying by the same element does nothing", prop.ForAll(
   520  		func(a, b *E2) bool {
   521  			var c E2
   522  			c.Div(a, b)
   523  			c.Mul(&c, b)
   524  			return c.Equal(a)
   525  		},
   526  		genA,
   527  		genB,
   528  	))
   529  
   530  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   531  }