github.com/consensys/gnark-crypto@v0.14.0/ecc/bn254/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/bn254/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("[BN254] 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("[BN254] 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("[BN254] 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("[BN254] 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("[BN254] 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("[BN254] 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("[BN254] 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("[BN254] 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("[BN254] 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("[BN254] 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("[BN254] 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("[BN254] 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  		4332616871279656263,
   199  		10917124144477883021,
   200  		13281191951274694749,
   201  		3486998266802970665,
   202  	}
   203  	fpMaxValue[0]--
   204  
   205  	a.A0 = fpMaxValue
   206  	a.A1 = fpMaxValue
   207  	b.A0 = fpMaxValue
   208  	b.A1 = fpMaxValue
   209  
   210  	var c, d E2
   211  	d.Inverse(&b)
   212  	c.Set(&a)
   213  	c.Mul(&c, &b).Mul(&c, &d)
   214  	if !c.Equal(&a) {
   215  		t.Fatal("mul with max fp failed")
   216  	}
   217  }
   218  
   219  func TestE2Ops(t *testing.T) {
   220  
   221  	t.Parallel()
   222  	parameters := gopter.DefaultTestParameters()
   223  	if testing.Short() {
   224  		parameters.MinSuccessfulTests = nbFuzzShort
   225  	} else {
   226  		parameters.MinSuccessfulTests = nbFuzz
   227  	}
   228  
   229  	properties := gopter.NewProperties(parameters)
   230  
   231  	genA := GenE2()
   232  	genB := GenE2()
   233  	genfp := GenFp()
   234  
   235  	properties.Property("[BN254] sub & add should leave an element invariant", prop.ForAll(
   236  		func(a, b *E2) bool {
   237  			var c E2
   238  			c.Set(a)
   239  			c.Add(&c, b).Sub(&c, b)
   240  			return c.Equal(a)
   241  		},
   242  		genA,
   243  		genB,
   244  	))
   245  
   246  	properties.Property("[BN254] mul & inverse should leave an element invariant", prop.ForAll(
   247  		func(a, b *E2) bool {
   248  			var c, d E2
   249  			d.Inverse(b)
   250  			c.Set(a)
   251  			c.Mul(&c, b).Mul(&c, &d)
   252  			return c.Equal(a)
   253  		},
   254  		genA,
   255  		genB,
   256  	))
   257  
   258  	properties.Property("[BN254] BatchInvertE2 should output the same result as Inverse", prop.ForAll(
   259  		func(a, b, c *E2) bool {
   260  
   261  			batch := BatchInvertE2([]E2{*a, *b, *c})
   262  			a.Inverse(a)
   263  			b.Inverse(b)
   264  			c.Inverse(c)
   265  			return a.Equal(&batch[0]) && b.Equal(&batch[1]) && c.Equal(&batch[2])
   266  		},
   267  		genA,
   268  		genA,
   269  		genA,
   270  	))
   271  
   272  	properties.Property("[BN254] mulGeneric & mul should be equal", prop.ForAll(
   273  		func(a, b *E2) bool {
   274  			var c, d E2
   275  			mulGenericE2(&c, a, b)
   276  			d.Mul(a, b)
   277  			return d.Equal(&c)
   278  		},
   279  		genA,
   280  		genB,
   281  	))
   282  
   283  	properties.Property("[BN254] inverse twice should leave an element invariant", prop.ForAll(
   284  		func(a *E2) bool {
   285  			var b E2
   286  			b.Inverse(a).Inverse(&b)
   287  			return a.Equal(&b)
   288  		},
   289  		genA,
   290  	))
   291  
   292  	properties.Property("[BN254] neg twice should leave an element invariant", prop.ForAll(
   293  		func(a *E2) bool {
   294  			var b E2
   295  			b.Neg(a).Neg(&b)
   296  			return a.Equal(&b)
   297  		},
   298  		genA,
   299  	))
   300  
   301  	properties.Property("[BN254] square and mul should output the same result", prop.ForAll(
   302  		func(a *E2) bool {
   303  			var b, c E2
   304  			b.Mul(a, a)
   305  			c.Square(a)
   306  			return b.Equal(&c)
   307  		},
   308  		genA,
   309  	))
   310  
   311  	properties.Property("[BN254] MulByElement MulByElement inverse should leave an element invariant", prop.ForAll(
   312  		func(a *E2, b fp.Element) bool {
   313  			var c E2
   314  			var d fp.Element
   315  			d.Inverse(&b)
   316  			c.MulByElement(a, &b).MulByElement(&c, &d)
   317  			return c.Equal(a)
   318  		},
   319  		genA,
   320  		genfp,
   321  	))
   322  
   323  	properties.Property("[BN254] Double and mul by 2 should output the same result", prop.ForAll(
   324  		func(a *E2) bool {
   325  			var b E2
   326  			var c fp.Element
   327  			c.SetUint64(2)
   328  			b.Double(a)
   329  			a.MulByElement(a, &c)
   330  			return a.Equal(&b)
   331  		},
   332  		genA,
   333  	))
   334  
   335  	properties.Property("[BN254] Mulbynonres mulbynonresinv should leave the element invariant", prop.ForAll(
   336  		func(a *E2) bool {
   337  			var b E2
   338  			b.MulByNonResidue(a).MulByNonResidueInv(&b)
   339  			return a.Equal(&b)
   340  		},
   341  		genA,
   342  	))
   343  
   344  	properties.Property("[BN254] a + pi(a), a-pi(a) should be real", prop.ForAll(
   345  		func(a *E2) bool {
   346  			var b, c, d E2
   347  			var e, f fp.Element
   348  			b.Conjugate(a)
   349  			c.Add(a, &b)
   350  			d.Sub(a, &b)
   351  			e.Double(&a.A0)
   352  			f.Double(&a.A1)
   353  			return c.A1.IsZero() && d.A0.IsZero() && e.Equal(&c.A0) && f.Equal(&d.A1)
   354  		},
   355  		genA,
   356  	))
   357  
   358  	properties.Property("[BN254] Legendre on square should output 1", prop.ForAll(
   359  		func(a *E2) bool {
   360  			var b E2
   361  			b.Square(a)
   362  			c := b.Legendre()
   363  			return c == 1
   364  		},
   365  		genA,
   366  	))
   367  
   368  	properties.Property("[BN254] square(sqrt) should leave an element invariant", prop.ForAll(
   369  		func(a *E2) bool {
   370  			var b, c, d, e E2
   371  			b.Square(a)
   372  			c.Sqrt(&b)
   373  			d.Square(&c)
   374  			e.Neg(a)
   375  			return (c.Equal(a) || c.Equal(&e)) && d.Equal(&b)
   376  		},
   377  		genA,
   378  	))
   379  
   380  	properties.Property("[BN254] neg(E2) == neg(E2.A0, E2.A1)", prop.ForAll(
   381  		func(a *E2) bool {
   382  			var b, c E2
   383  			b.Neg(a)
   384  			c.A0.Neg(&a.A0)
   385  			c.A1.Neg(&a.A1)
   386  			return c.Equal(&b)
   387  		},
   388  		genA,
   389  	))
   390  
   391  	properties.Property("[BN254] Cmp and LexicographicallyLargest should be consistent", prop.ForAll(
   392  		func(a *E2) bool {
   393  			var negA E2
   394  			negA.Neg(a)
   395  			cmpResult := a.Cmp(&negA)
   396  			lResult := a.LexicographicallyLargest()
   397  			if lResult && cmpResult == 1 {
   398  				return true
   399  			}
   400  			if !lResult && cmpResult != 1 {
   401  				return true
   402  			}
   403  			return false
   404  		},
   405  		genA,
   406  	))
   407  
   408  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   409  
   410  }
   411  
   412  // ------------------------------------------------------------
   413  // benches
   414  
   415  func BenchmarkE2Add(b *testing.B) {
   416  	var a, c E2
   417  	_, _ = a.SetRandom()
   418  	_, _ = c.SetRandom()
   419  	b.ResetTimer()
   420  	for i := 0; i < b.N; i++ {
   421  		a.Add(&a, &c)
   422  	}
   423  }
   424  
   425  func BenchmarkE2Sub(b *testing.B) {
   426  	var a, c E2
   427  	_, _ = a.SetRandom()
   428  	_, _ = c.SetRandom()
   429  	b.ResetTimer()
   430  	for i := 0; i < b.N; i++ {
   431  		a.Sub(&a, &c)
   432  	}
   433  }
   434  
   435  func BenchmarkE2Mul(b *testing.B) {
   436  	var a, c E2
   437  	_, _ = a.SetRandom()
   438  	_, _ = c.SetRandom()
   439  	b.ResetTimer()
   440  	for i := 0; i < b.N; i++ {
   441  		a.Mul(&a, &c)
   442  	}
   443  }
   444  
   445  func BenchmarkE2MulByElement(b *testing.B) {
   446  	var a E2
   447  	var c fp.Element
   448  	_, _ = c.SetRandom()
   449  	_, _ = a.SetRandom()
   450  	b.ResetTimer()
   451  	for i := 0; i < b.N; i++ {
   452  		a.MulByElement(&a, &c)
   453  	}
   454  }
   455  
   456  func BenchmarkE2Square(b *testing.B) {
   457  	var a E2
   458  	_, _ = a.SetRandom()
   459  	b.ResetTimer()
   460  	for i := 0; i < b.N; i++ {
   461  		a.Square(&a)
   462  	}
   463  }
   464  
   465  func BenchmarkE2Sqrt(b *testing.B) {
   466  	var a E2
   467  	_, _ = a.SetRandom()
   468  	b.ResetTimer()
   469  	for i := 0; i < b.N; i++ {
   470  		a.Sqrt(&a)
   471  	}
   472  }
   473  
   474  func BenchmarkE2Exp(b *testing.B) {
   475  	var x E2
   476  	_, _ = x.SetRandom()
   477  	b1, _ := rand.Int(rand.Reader, fp.Modulus())
   478  	b.ResetTimer()
   479  	for i := 0; i < b.N; i++ {
   480  		x.Exp(x, b1)
   481  	}
   482  }
   483  
   484  func BenchmarkE2Inverse(b *testing.B) {
   485  	var a E2
   486  	_, _ = a.SetRandom()
   487  	b.ResetTimer()
   488  	for i := 0; i < b.N; i++ {
   489  		a.Inverse(&a)
   490  	}
   491  }
   492  
   493  func BenchmarkE2MulNonRes(b *testing.B) {
   494  	var a E2
   495  	_, _ = a.SetRandom()
   496  	b.ResetTimer()
   497  	for i := 0; i < b.N; i++ {
   498  		a.MulByNonResidue(&a)
   499  	}
   500  }
   501  
   502  func BenchmarkE2MulNonResInv(b *testing.B) {
   503  	var a E2
   504  	_, _ = a.SetRandom()
   505  	b.ResetTimer()
   506  	for i := 0; i < b.N; i++ {
   507  		a.MulByNonResidueInv(&a)
   508  	}
   509  }
   510  
   511  func BenchmarkE2Conjugate(b *testing.B) {
   512  	var a E2
   513  	_, _ = a.SetRandom()
   514  	b.ResetTimer()
   515  	for i := 0; i < b.N; i++ {
   516  		a.Conjugate(&a)
   517  	}
   518  }
   519  
   520  func TestE2Div(t *testing.T) {
   521  
   522  	parameters := gopter.DefaultTestParameters()
   523  	properties := gopter.NewProperties(parameters)
   524  
   525  	genA := GenE2()
   526  	genB := GenE2()
   527  
   528  	properties.Property("[BN254] dividing then multiplying by the same element does nothing", prop.ForAll(
   529  		func(a, b *E2) bool {
   530  			var c E2
   531  			c.Div(a, b)
   532  			c.Mul(&c, b)
   533  			return c.Equal(a)
   534  		},
   535  		genA,
   536  		genB,
   537  	))
   538  
   539  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   540  }