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

     1  {{ $G1TAffine := print (toUpper .G1.PointName) "Affine" }}
     2  {{ $G1TJacobian := print (toUpper .G1.PointName) "Jac" }}
     3  {{ $G1TJacobianExtended := print (toLower .G1.PointName) "JacExtended" }}
     4  
     5  {{ $G2TAffine := print (toUpper .G2.PointName) "Affine" }}
     6  {{ $G2TJacobian := print (toUpper .G2.PointName) "Jac" }}
     7  {{ $G2TJacobianExtended := print (toLower .G2.PointName) "JacExtended" }}
     8  
     9  import (
    10  	"testing"
    11  	"math/rand/v2"
    12  	crand "crypto/rand"
    13  	"math/big"
    14  	"bytes"
    15  	"io"
    16  	"reflect"
    17  
    18  	"github.com/leanovate/gopter"
    19  	"github.com/leanovate/gopter/prop"
    20  
    21  	"github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr"
    22  	"github.com/consensys/gnark-crypto/ecc/{{.Name}}/fp"
    23  	"github.com/consensys/gnark-crypto/ecc/{{.Name}}/internal/fptower"
    24  )
    25  
    26  const (
    27  	nbFuzzShort = 10
    28  	nbFuzz = 100
    29  )
    30  
    31  func TestEncoder(t *testing.T) {
    32  	t.Parallel()
    33  	// TODO need proper fuzz testing here
    34  
    35  	var inA uint64
    36  	var inB fr.Element
    37  	var inC fp.Element
    38  	var inD G1Affine
    39  	var inE G1Affine
    40  	var inF G2Affine
    41  	var inG []G1Affine
    42  	var inH []G2Affine
    43  	var inI []fp.Element
    44  	var inJ []fr.Element
    45  	var inK fr.Vector
    46  	var inL [][]fr.Element
    47  	var inM [][]uint64
    48  
    49  	// set values of inputs
    50  	inA = rand.Uint64() //#nosec G404 weak rng is fine here
    51  	inB.SetRandom()
    52  	inC.SetRandom()
    53  	inD.ScalarMultiplication(&g1GenAff, new(big.Int).SetUint64(rand.Uint64())) //#nosec G404 weak rng is fine here
    54  	// inE --> infinity
    55  	inF.ScalarMultiplication(&g2GenAff, new(big.Int).SetUint64(rand.Uint64())) //#nosec G404 weak rng is fine here
    56  	inG = make([]G1Affine, 2)
    57  	inH = make([]G2Affine, 0)
    58  	inG[1] = inD
    59  	inI = make([]fp.Element, 3)
    60  	inI[2] = inD.X
    61  	inJ = make([]fr.Element, 0)
    62  	inK = make(fr.Vector, 42)
    63  	inK[41].SetUint64(42)
    64  	inL =[][]fr.Element {inJ, inK}
    65  	inM = [][]uint64{ {1, 2}, {4}, {} }
    66  
    67  	// encode them, compressed and raw
    68  	var buf, bufRaw bytes.Buffer
    69  	enc := NewEncoder(&buf)
    70  	encRaw := NewEncoder(&bufRaw, RawEncoding())
    71  	toEncode := []interface{}{inA, &inB, &inC, &inD, &inE, &inF, inG, inH, inI, inJ, inK, inL, inM}
    72  	for _, v := range toEncode {
    73  		if err := enc.Encode(v); err != nil {
    74  			t.Fatal(err)
    75  		}
    76  		if err := encRaw.Encode(v); err != nil {
    77  			t.Fatal(err)
    78  		}
    79  	}
    80  
    81  
    82  	testDecode := func(t *testing.T, r io.Reader, n int64) {
    83  		dec := NewDecoder(r)
    84  		var outA uint64
    85  		var outB fr.Element
    86  		var outC fp.Element
    87  		var outD G1Affine
    88  		var outE G1Affine
    89  		outE.X.SetOne()
    90  		outE.Y.SetUint64(42)
    91  		var outF G2Affine
    92  		var outG []G1Affine
    93  		var outH []G2Affine
    94  		var outI []fp.Element
    95  		var outJ []fr.Element
    96  		var outK fr.Vector
    97  		var outL [][]fr.Element
    98  		var outM [][]uint64
    99  
   100  		toDecode := []interface{}{&outA, &outB, &outC, &outD, &outE, &outF, &outG, &outH, &outI, &outJ, &outK, &outL, &outM}
   101  		for _, v := range toDecode {
   102  			if err := dec.Decode(v); err != nil {
   103  				t.Fatal(err)
   104  			}
   105  		}
   106  
   107  		// compare values
   108  		if inA != outA {
   109  			t.Fatal("didn't encode/decode uint64 value properly")
   110  		}
   111  
   112  		if !inB.Equal(&outB) || !inC.Equal(&outC) {
   113  			t.Fatal("decode(encode(Element) failed")
   114  		}
   115  		if !inD.Equal(&outD) || !inE.Equal(&outE) {
   116  			t.Fatal("decode(encode(G1Affine) failed")
   117  		}
   118  		if !inF.Equal(&outF) {
   119  			t.Fatal("decode(encode(G2Affine) failed")
   120  		}
   121  		if (len(inG) != len(outG)) || (len(inH) != len(outH)) {
   122  			t.Fatal("decode(encode(slice(points))) failed")
   123  		}
   124  		for i:=0; i<len(inG);i++ {
   125  			if !inG[i].Equal(&outG[i]) {
   126  				t.Fatal("decode(encode(slice(points))) failed")
   127  			}
   128  		}
   129  		if (len(inI) != len(outI)) || (len(inJ) != len(outJ)) {
   130  			t.Fatal("decode(encode(slice(elements))) failed")
   131  		}
   132  		for i:=0; i<len(inI);i++ {
   133  			if !inI[i].Equal(&outI[i]) {
   134  				t.Fatal("decode(encode(slice(elements))) failed")
   135  			}
   136  		}
   137  		if !reflect.DeepEqual(inK, outK) {
   138  			t.Fatal("decode(encode(vector)) failed")
   139  		}
   140  		if !reflect.DeepEqual(inL, outL) {
   141  			t.Fatal("decode(encode(sliceĀ²(elements))) failed")
   142  		}
   143  		if !reflect.DeepEqual(inM, outM) {
   144  			t.Fatal("decode(encode(sliceĀ²(uint64))) failed")
   145  		}
   146  		if n != dec.BytesRead() {
   147  			t.Fatal("bytes read don't match bytes written")
   148  		}
   149  	}
   150  
   151  	// decode them
   152  	testDecode(t, &buf, enc.BytesWritten())
   153  	testDecode(t, &bufRaw, encRaw.BytesWritten())
   154  
   155  
   156  }
   157  
   158  
   159  
   160  func TestIsCompressed(t *testing.T) {
   161  	t.Parallel()
   162  	var g1Inf, g1 G1Affine
   163  	var g2Inf, g2 G2Affine
   164  
   165  	g1 = g1GenAff
   166  	g2 = g2GenAff
   167  
   168  	{
   169  		b := g1Inf.Bytes()
   170  		if !isCompressed(b[0]) {
   171  			t.Fatal("g1Inf.Bytes() should be compressed")
   172  		}
   173  	}
   174  
   175  	{
   176  		b := g1Inf.RawBytes()
   177  		if isCompressed(b[0]) {
   178  			t.Fatal("g1Inf.RawBytes() should be uncompressed")
   179  		}
   180  	}
   181  
   182  	{
   183  		b := g1.Bytes()
   184  		if !isCompressed(b[0]) {
   185  			t.Fatal("g1.Bytes() should be compressed")
   186  		}
   187  	}
   188  
   189  	{
   190  		b := g1.RawBytes()
   191  		if isCompressed(b[0]) {
   192  			t.Fatal("g1.RawBytes() should be uncompressed")
   193  		}
   194  	}
   195  
   196  
   197  
   198  	{
   199  		b := g2Inf.Bytes()
   200  		if !isCompressed(b[0]) {
   201  			t.Fatal("g2Inf.Bytes() should be compressed")
   202  		}
   203  	}
   204  
   205  	{
   206  		b := g2Inf.RawBytes()
   207  		if isCompressed(b[0]) {
   208  			t.Fatal("g2Inf.RawBytes() should be uncompressed")
   209  		}
   210  	}
   211  
   212  	{
   213  		b := g2.Bytes()
   214  		if !isCompressed(b[0]) {
   215  			t.Fatal("g2.Bytes() should be compressed")
   216  		}
   217  	}
   218  
   219  	{
   220  		b := g2.RawBytes()
   221  		if isCompressed(b[0]) {
   222  			t.Fatal("g2.RawBytes() should be uncompressed")
   223  		}
   224  	}
   225  
   226  }
   227  
   228  {{- $sizeOfFp := mul .Fp.NbWords 8}}
   229  {{- $FpUnusedBits := .FpUnusedBits}}
   230  
   231  {{template "marshalpoint" dict "all" . "sizeOfFp" $sizeOfFp "CoordType" .G1.CoordType "PointName" .G1.PointName "TAffine" $G1TAffine "TJacobian" $G1TJacobian "TJacobianExtended" $G1TJacobianExtended "FrNbWords" .Fr.NbWords "CRange" .G1.CRange "FpUnusedBits" $FpUnusedBits}}
   232  {{template "marshalpoint" dict "all" . "sizeOfFp" $sizeOfFp  "CoordType" .G2.CoordType "PointName" .G2.PointName "TAffine" $G2TAffine "TJacobian" $G2TJacobian "TJacobianExtended" $G2TJacobianExtended "FrNbWords" .Fr.NbWords "CRange" .G2.CRange "FpUnusedBits" $FpUnusedBits}}
   233  
   234  
   235  {{define "marshalpoint"}}
   236  
   237  
   238  
   239  {{if ge $.FpUnusedBits 3}}
   240  func Test{{ $.TAffine }}InvalidBitMask(t *testing.T) {
   241  	t.Parallel()
   242  	var buf [SizeOf{{ $.TAffine }}Compressed]byte
   243  	crand.Read(buf[:])
   244  
   245  	var p {{ $.TAffine }}
   246  	buf[0] = 0b111 << 5
   247  	if _, err := p.SetBytes(buf[:]); err != ErrInvalidEncoding {
   248  		t.Fatal("should error on invalid bit mask")
   249  	}
   250  	buf[0] = 0b011 << 5
   251  	if _, err := p.SetBytes(buf[:]); err != ErrInvalidEncoding {
   252  		t.Fatal("should error on invalid bit mask")
   253  	}
   254  	buf[0] = 0b001 << 5
   255  	if _, err := p.SetBytes(buf[:]); err != ErrInvalidEncoding {
   256  		t.Fatal("should error on invalid bit mask")
   257  	}
   258  }
   259  {{- end}}
   260  
   261  
   262  func Test{{ $.TAffine }}Serialization(t *testing.T) {
   263  	t.Parallel()
   264  	// test round trip serialization of infinity
   265  	{
   266  		// compressed
   267  		{
   268  			var p1, p2 {{ $.TAffine }}
   269  			p2.X.SetRandom()
   270  			p2.Y.SetRandom()
   271  			buf := p1.Bytes()
   272  			n, err := p2.SetBytes(buf[:])
   273  			if err != nil {
   274  				t.Fatal(err)
   275  			}
   276  			if n != SizeOf{{ $.TAffine }}Compressed {
   277  				t.Fatal("invalid number of bytes consumed in buffer")
   278  			}
   279  			if !(p2.X.IsZero() && p2.Y.IsZero()) {
   280  				t.Fatal("deserialization of uncompressed infinity point is not infinity")
   281  			}
   282  		}
   283  
   284  		// uncompressed
   285  		{
   286  			var p1, p2 {{ $.TAffine }}
   287  			p2.X.SetRandom()
   288  			p2.Y.SetRandom()
   289  			buf := p1.RawBytes()
   290  			n, err := p2.SetBytes(buf[:])
   291  			if err != nil {
   292  				t.Fatal(err)
   293  			}
   294  			if n != SizeOf{{ $.TAffine }}Uncompressed {
   295  				t.Fatal("invalid number of bytes consumed in buffer")
   296  			}
   297  			if !(p2.X.IsZero() && p2.Y.IsZero()) {
   298  				t.Fatal("deserialization of uncompressed infinity point is not infinity")
   299  			}
   300  		}
   301  	}
   302  
   303  	parameters := gopter.DefaultTestParameters()
   304  	if testing.Short() {
   305  		parameters.MinSuccessfulTests = nbFuzzShort
   306  	} else {
   307  		parameters.MinSuccessfulTests = nbFuzz
   308  	}
   309  
   310  
   311  
   312  	properties := gopter.NewProperties(parameters)
   313  
   314  
   315  	properties.Property("[{{ toUpper $.PointName }}] Affine SetBytes(RawBytes) should stay the same", prop.ForAll(
   316  			func(a fp.Element) bool {
   317  				var start, end {{ $.TAffine }}
   318  				var ab big.Int
   319  				a.BigInt(&ab)
   320  				start.ScalarMultiplication(&{{ toLower .PointName }}GenAff, &ab)
   321  
   322  				buf := start.RawBytes()
   323  				n, err := end.SetBytes(buf[:])
   324  				if err != nil {
   325  					return false
   326  				}
   327  				if n != SizeOf{{ $.TAffine }}Uncompressed {
   328  					return false
   329  				}
   330  				return start.X.Equal(&end.X) && start.Y.Equal(&end.Y)
   331  		},
   332  		GenFp(),
   333  	))
   334  
   335  	properties.Property("[{{ toUpper $.PointName }}] Affine SetBytes(Bytes()) should stay the same", prop.ForAll(
   336  			func(a fp.Element) bool {
   337  				var start, end {{ $.TAffine }}
   338  				var ab big.Int
   339  				a.BigInt(&ab)
   340  				start.ScalarMultiplication(&{{ toLower .PointName }}GenAff, &ab)
   341  
   342  				buf := start.Bytes()
   343  				n, err := end.SetBytes(buf[:])
   344  				if err != nil {
   345  					return false
   346  				}
   347  				if n != SizeOf{{ $.TAffine }}Compressed {
   348  					return false
   349  				}
   350  				return start.X.Equal(&end.X) && start.Y.Equal(&end.Y)
   351  		},
   352  		GenFp(),
   353  	))
   354  
   355  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   356  }
   357  
   358  {{end}}
   359  
   360  
   361  // define Gopters generators
   362  
   363  // GenFr generates an Fr element
   364  func GenFr() gopter.Gen {
   365  	return func(genParams *gopter.GenParameters) *gopter.GenResult {
   366  		var elmt fr.Element
   367  
   368  		if _, err := elmt.SetRandom(); err != nil {
   369  			panic(err)
   370  		}
   371  
   372  		return gopter.NewGenResult(elmt, gopter.NoShrinker)
   373  	}
   374  }
   375  
   376  // GenFp generates an Fp element
   377  func GenFp() gopter.Gen {
   378  	return func(genParams *gopter.GenParameters) *gopter.GenResult {
   379  		var elmt fp.Element
   380  
   381  		if _, err := elmt.SetRandom(); err != nil {
   382  			panic(err)
   383  		}
   384  
   385  		return gopter.NewGenResult(elmt, gopter.NoShrinker)
   386  	}
   387  }
   388  
   389  {{/* // e3 e6 for bw6-xxx
   390  // e2 e4 e12 e24 for bls24
   391  // e2 e6 e12 else */}}
   392  
   393  {{if or (eq .Name "bw6-633") (eq .Name "bw6-761") (eq .Name "bw6-756")}}
   394  	// GenE3 generates an E3 elmt
   395  	func GenE3() gopter.Gen {
   396  		return gopter.CombineGens(
   397  			GenFp(),
   398  			GenFp(),
   399  			GenFp(),
   400  		).Map(func(values []interface{}) fptower.E3 {
   401  			return fptower.E3{A0: values[0].(fp.Element), A1: values[1].(fp.Element), A2: values[2].(fp.Element)}
   402  		})
   403  	}
   404  
   405  	// E6 generates an E6 elmt
   406  	func GenE6() gopter.Gen {
   407  		return gopter.CombineGens(
   408  			GenE3(),
   409  			GenE3(),
   410  		).Map(func(values []interface{}) fptower.E6 {
   411  			return fptower.E6{B0: values[0].(fptower.E3), B1: values[1].(fptower.E3)}
   412  		})
   413  	}
   414  {{ else }}
   415  	// GenE2 generates an fptower.E2 elmt
   416  	func GenE2() gopter.Gen {
   417  		return gopter.CombineGens(
   418  			GenFp(),
   419  			GenFp(),
   420  		).Map(func(values []interface{}) fptower.E2 {
   421  			return fptower.E2{A0: values[0].(fp.Element), A1: values[1].(fp.Element)}
   422  		})
   423  	}
   424  
   425      {{if or (eq .Name "bls24-315") (eq .Name "bls24-317")}}
   426  		// GenE4 generates an fptower.E4 elmt
   427  		func GenE4() gopter.Gen {
   428  			return gopter.CombineGens(
   429  				GenE2(),
   430  				GenE2(),
   431  			).Map(func(values []interface{}) fptower.E4 {
   432  				return fptower.E4{B0: values[0].(fptower.E2), B1: values[1].(fptower.E2)}
   433  			})
   434  		}
   435  
   436          // GenE12 generates an fptower.E12 elmt
   437          func GenE12() gopter.Gen {
   438              return gopter.CombineGens(
   439                  GenE4(),
   440                  GenE4(),
   441                  GenE4(),
   442              ).Map(func(values []interface{}) fptower.E12 {
   443                  return fptower.E12{C0: values[0].(fptower.E4), C1: values[1].(fptower.E4), C2: values[2].(fptower.E4)}
   444              })
   445          }
   446  
   447          // GenE24 generates an fptower.E24 elmt
   448          func GenE24() gopter.Gen {
   449              return gopter.CombineGens(
   450                  GenE12(),
   451                  GenE12(),
   452              ).Map(func(values []interface{}) fptower.E24 {
   453                  return fptower.E24{D0: values[0].(fptower.E12), D1: values[1].(fptower.E12)}
   454              })
   455          }
   456  	{{ else }}
   457  		// GenE6 generates an fptower.E6 elmt
   458  		func GenE6() gopter.Gen {
   459  			return gopter.CombineGens(
   460  				GenE2(),
   461  				GenE2(),
   462  				GenE2(),
   463  			).Map(func(values []interface{}) fptower.E6 {
   464  				return fptower.E6{B0: values[0].(fptower.E2), B1: values[1].(fptower.E2), B2: values[2].(fptower.E2)}
   465  			})
   466  		}
   467  
   468  		// GenE12 generates an fptower.E6 elmt
   469  		func GenE12() gopter.Gen {
   470  			return gopter.CombineGens(
   471  				GenE6(),
   472  				GenE6(),
   473  			).Map(func(values []interface{}) fptower.E12 {
   474  				return fptower.E12{C0: values[0].(fptower.E6), C1: values[1].(fptower.E6)}
   475  			})
   476  		}
   477  	{{ end }}
   478  {{ end }}
   479  
   480  
   481  
   482  // GenBigInt generates a big.Int
   483  func GenBigInt() gopter.Gen {
   484  	return func(genParams *gopter.GenParameters) *gopter.GenResult {
   485  		var s big.Int
   486  		var b [fp.Bytes]byte
   487  		_, err := crand.Read(b[:])
   488  		if err != nil {
   489  			panic(err)
   490  		}
   491  		s.SetBytes(b[:])
   492  		genResult := gopter.NewGenResult(s, gopter.NoShrinker)
   493  		return genResult
   494  	}
   495  }