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