github.com/consensys/gnark-crypto@v0.14.0/ecc/stark-curve/marshal_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  // FOO
    16  
    17  package starkcurve
    18  
    19  import (
    20  	"bytes"
    21  	"io"
    22  	"math/big"
    23  	"math/rand"
    24  	"testing"
    25  
    26  	"github.com/leanovate/gopter"
    27  	"github.com/leanovate/gopter/prop"
    28  
    29  	"github.com/consensys/gnark-crypto/ecc/stark-curve/fp"
    30  	"github.com/consensys/gnark-crypto/ecc/stark-curve/fr"
    31  )
    32  
    33  func TestEncoder(t *testing.T) {
    34  	t.Parallel()
    35  	// TODO need proper fuzz testing here
    36  
    37  	var inA uint64
    38  	var inB fr.Element
    39  	var inC fp.Element
    40  	var inD G1Affine
    41  	var inE G1Affine
    42  	var inG []G1Affine
    43  	var inI []fp.Element
    44  	var inJ []fr.Element
    45  
    46  	// set values of inputs
    47  	inA = rand.Uint64() //#nosec G404 weak rng is fine here
    48  	inB.SetRandom()
    49  	inC.SetRandom()
    50  	inD.ScalarMultiplication(&g1GenAff, new(big.Int).SetUint64(rand.Uint64())) //#nosec G404 weak rng is fine here
    51  	// inE --> infinity
    52  	inG = make([]G1Affine, 2)
    53  	inG[1] = inD
    54  	inI = make([]fp.Element, 3)
    55  	inI[2] = inD.X
    56  	inJ = make([]fr.Element, 0)
    57  
    58  	// encode them, compressed and raw
    59  	var buf, bufRaw bytes.Buffer
    60  	enc := NewEncoder(&buf)
    61  	encRaw := NewEncoder(&bufRaw, RawEncoding())
    62  	toEncode := []interface{}{inA, &inB, &inC, &inD, &inE, inG, inI, inJ}
    63  	for _, v := range toEncode {
    64  		if err := enc.Encode(v); err != nil {
    65  			t.Fatal(err)
    66  		}
    67  		if err := encRaw.Encode(v); err != nil {
    68  			t.Fatal(err)
    69  		}
    70  	}
    71  
    72  	testDecode := func(t *testing.T, r io.Reader, n int64) {
    73  		dec := NewDecoder(r)
    74  		var outA uint64
    75  		var outB fr.Element
    76  		var outC fp.Element
    77  		var outD G1Affine
    78  		var outE G1Affine
    79  		outE.X.SetOne()
    80  		outE.Y.SetUint64(42)
    81  		var outG []G1Affine
    82  		var outI []fp.Element
    83  		var outJ []fr.Element
    84  
    85  		toDecode := []interface{}{&outA, &outB, &outC, &outD, &outE, &outG, &outI, &outJ}
    86  		for _, v := range toDecode {
    87  			if err := dec.Decode(v); err != nil {
    88  				t.Fatal(err)
    89  			}
    90  		}
    91  
    92  		// compare values
    93  		if inA != outA {
    94  			t.Fatal("didn't encode/decode uint64 value properly")
    95  		}
    96  
    97  		if !inB.Equal(&outB) || !inC.Equal(&outC) {
    98  			t.Fatal("decode(encode(Element) failed")
    99  		}
   100  		if !inD.Equal(&outD) || !inE.Equal(&outE) {
   101  			t.Fatal("decode(encode(G1Affine) failed")
   102  		}
   103  		for i := 0; i < len(inG); i++ {
   104  			if !inG[i].Equal(&outG[i]) {
   105  				t.Fatal("decode(encode(slice(points))) failed")
   106  			}
   107  		}
   108  		if (len(inI) != len(outI)) || (len(inJ) != len(outJ)) {
   109  			t.Fatal("decode(encode(slice(elements))) failed")
   110  		}
   111  		for i := 0; i < len(inI); i++ {
   112  			if !inI[i].Equal(&outI[i]) {
   113  				t.Fatal("decode(encode(slice(elements))) failed")
   114  			}
   115  		}
   116  		if n != dec.BytesRead() {
   117  			t.Fatal("bytes read don't match bytes written")
   118  		}
   119  	}
   120  
   121  	// decode them
   122  	testDecode(t, &buf, enc.BytesWritten())
   123  	testDecode(t, &bufRaw, encRaw.BytesWritten())
   124  
   125  }
   126  
   127  func TestIsCompressed(t *testing.T) {
   128  	t.Parallel()
   129  	var g1Inf, g1 G1Affine
   130  
   131  	g1 = g1GenAff
   132  
   133  	{
   134  		b := g1Inf.Bytes()
   135  		if !isCompressed(b[0]) {
   136  			t.Fatal("g1Inf.Bytes() should be compressed")
   137  		}
   138  	}
   139  
   140  	{
   141  		b := g1Inf.RawBytes()
   142  		if isCompressed(b[0]) {
   143  			t.Fatal("g1Inf.RawBytes() should be uncompressed")
   144  		}
   145  	}
   146  
   147  	{
   148  		b := g1.Bytes()
   149  		if !isCompressed(b[0]) {
   150  			t.Fatal("g1.Bytes() should be compressed")
   151  		}
   152  	}
   153  
   154  	{
   155  		b := g1.RawBytes()
   156  		if isCompressed(b[0]) {
   157  			t.Fatal("g1.RawBytes() should be uncompressed")
   158  		}
   159  	}
   160  
   161  }
   162  
   163  func TestG1AffineSerialization(t *testing.T) {
   164  	t.Parallel()
   165  	// test round trip serialization of infinity
   166  	{
   167  		// compressed
   168  		{
   169  			var p1, p2 G1Affine
   170  			p2.X.SetRandom()
   171  			p2.Y.SetRandom()
   172  			buf := p1.Bytes()
   173  			n, err := p2.SetBytes(buf[:])
   174  			if err != nil {
   175  				t.Fatal(err)
   176  			}
   177  			if n != SizeOfG1AffineCompressed {
   178  				t.Fatal("invalid number of bytes consumed in buffer")
   179  			}
   180  			if !(p2.X.IsZero() && p2.Y.IsZero()) {
   181  				t.Fatal("deserialization of uncompressed infinity point is not infinity")
   182  			}
   183  		}
   184  
   185  		// uncompressed
   186  		{
   187  			var p1, p2 G1Affine
   188  			p2.X.SetRandom()
   189  			p2.Y.SetRandom()
   190  			buf := p1.RawBytes()
   191  			n, err := p2.SetBytes(buf[:])
   192  			if err != nil {
   193  				t.Fatal(err)
   194  			}
   195  			if n != SizeOfG1AffineUncompressed {
   196  				t.Fatal("invalid number of bytes consumed in buffer")
   197  			}
   198  			if !(p2.X.IsZero() && p2.Y.IsZero()) {
   199  				t.Fatal("deserialization of uncompressed infinity point is not infinity")
   200  			}
   201  		}
   202  	}
   203  
   204  	parameters := gopter.DefaultTestParameters()
   205  	if testing.Short() {
   206  		parameters.MinSuccessfulTests = nbFuzzShort
   207  	} else {
   208  		parameters.MinSuccessfulTests = nbFuzz
   209  	}
   210  
   211  	properties := gopter.NewProperties(parameters)
   212  
   213  	properties.Property("[G1] Affine SetBytes(RawBytes) should stay the same", prop.ForAll(
   214  		func(a fp.Element) bool {
   215  			var start, end G1Affine
   216  			var ab big.Int
   217  			a.BigInt(&ab)
   218  			start.ScalarMultiplication(&g1GenAff, &ab)
   219  
   220  			buf := start.RawBytes()
   221  			n, err := end.SetBytes(buf[:])
   222  			if err != nil {
   223  				return false
   224  			}
   225  			if n != SizeOfG1AffineUncompressed {
   226  				return false
   227  			}
   228  			return start.X.Equal(&end.X) && start.Y.Equal(&end.Y)
   229  		},
   230  		GenFp(),
   231  	))
   232  
   233  	properties.Property("[G1] Affine SetBytes(Bytes()) should stay the same", prop.ForAll(
   234  		func(a fp.Element) bool {
   235  			var start, end G1Affine
   236  			var ab big.Int
   237  			a.BigInt(&ab)
   238  			start.ScalarMultiplication(&g1GenAff, &ab)
   239  
   240  			buf := start.Bytes()
   241  			n, err := end.SetBytes(buf[:])
   242  			if err != nil {
   243  				return false
   244  			}
   245  			if n != SizeOfG1AffineCompressed {
   246  				return false
   247  			}
   248  			return start.X.Equal(&end.X) && start.Y.Equal(&end.Y)
   249  		},
   250  		GenFp(),
   251  	))
   252  
   253  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   254  }