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