github.com/cloudflare/circl@v1.5.0/ecc/bls12381/ff/scalar_test.go (about)

     1  package ff_test
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/rand"
     6  	"math/big"
     7  	"testing"
     8  
     9  	"github.com/cloudflare/circl/ecc/bls12381/ff"
    10  	"github.com/cloudflare/circl/internal/test"
    11  )
    12  
    13  func randomScalar(t testing.TB) *ff.Scalar {
    14  	t.Helper()
    15  	s := new(ff.Scalar)
    16  	err := s.Random(rand.Reader)
    17  	if err != nil {
    18  		t.Error(err)
    19  	}
    20  	return s
    21  }
    22  
    23  func TestScalar(t *testing.T) {
    24  	const testTimes = 1 << 10
    25  	t.Run("marshal", func(t *testing.T) {
    26  		for i := 0; i < testTimes; i++ {
    27  			var y ff.Scalar
    28  			x := randomScalar(t)
    29  
    30  			bytes, err := x.MarshalBinary()
    31  			if err != nil {
    32  				test.ReportError(t, x, y, x)
    33  			}
    34  			err = y.UnmarshalBinary(bytes)
    35  			if err != nil {
    36  				test.ReportError(t, x, y, x)
    37  			}
    38  			if x.IsEqual(&y) == 0 {
    39  				test.ReportError(t, x, y, x)
    40  			}
    41  		}
    42  	})
    43  	t.Run("no_alias", func(t *testing.T) {
    44  		var want, got ff.Scalar
    45  		x := randomScalar(t)
    46  		got.Set(x)
    47  		got.Sqr(&got)
    48  		want.Set(x)
    49  		want.Mul(&want, &want)
    50  		if got.IsEqual(&want) == 0 {
    51  			test.ReportError(t, got, want, x)
    52  		}
    53  	})
    54  	t.Run("mul_inv", func(t *testing.T) {
    55  		var z ff.Scalar
    56  		for i := 0; i < testTimes; i++ {
    57  			x := randomScalar(t)
    58  			y := randomScalar(t)
    59  			// x*y*x^1 - y = 0
    60  			z.Inv(x)
    61  			z.Mul(&z, y)
    62  			z.Mul(&z, x)
    63  			z.Sub(&z, y)
    64  			got := z.IsZero()
    65  			want := 1
    66  			if got != want {
    67  				test.ReportError(t, got, want, x, y)
    68  			}
    69  		}
    70  	})
    71  	t.Run("mul_sqr", func(t *testing.T) {
    72  		var l0, l1, r0, r1 ff.Scalar
    73  		for i := 0; i < testTimes; i++ {
    74  			x := randomScalar(t)
    75  			y := randomScalar(t)
    76  
    77  			// (x+y)(x-y) = (x^2-y^2)
    78  			l0.Add(x, y)
    79  			l1.Sub(x, y)
    80  			l0.Mul(&l0, &l1)
    81  			r0.Sqr(x)
    82  			r1.Sqr(y)
    83  			r0.Sub(&r0, &r1)
    84  			got := &l0
    85  			want := &r0
    86  			if got.IsEqual(want) == 0 {
    87  				test.ReportError(t, got, want, x, y)
    88  			}
    89  		}
    90  	})
    91  	t.Run("bytes", func(t *testing.T) {
    92  		var data [100]byte
    93  		_, _ = rand.Read(data[:])
    94  
    95  		var a, b ff.Scalar
    96  		var bigA, bigOrder big.Int
    97  		bigOrder.SetBytes(ff.ScalarOrder())
    98  
    99  		for i := 0; i < 100; i++ {
   100  			a.SetBytes(data[:i])
   101  
   102  			bigA.SetBytes(data[:i])
   103  			bigA.Mod(&bigA, &bigOrder)
   104  			bytesA := bigA.Bytes()
   105  			b.SetBytes(bytesA)
   106  
   107  			if a.IsEqual(&b) == 0 {
   108  				test.ReportError(t, a, b)
   109  			}
   110  
   111  			got, err := a.MarshalBinary()
   112  			test.CheckNoErr(t, err, "MarshalBinary failed")
   113  			want, err := b.MarshalBinary()
   114  			test.CheckNoErr(t, err, "MarshalBinary failed")
   115  
   116  			if !bytes.Equal(got, want) {
   117  				test.ReportError(t, got, want)
   118  			}
   119  		}
   120  	})
   121  }
   122  
   123  func BenchmarkScalar(b *testing.B) {
   124  	x := randomScalar(b)
   125  	y := randomScalar(b)
   126  	z := randomScalar(b)
   127  
   128  	b.Run("Add", func(b *testing.B) {
   129  		for i := 0; i < b.N; i++ {
   130  			z.Add(x, y)
   131  		}
   132  	})
   133  	b.Run("Mul", func(b *testing.B) {
   134  		for i := 0; i < b.N; i++ {
   135  			z.Mul(x, y)
   136  		}
   137  	})
   138  	b.Run("Sqr", func(b *testing.B) {
   139  		for i := 0; i < b.N; i++ {
   140  			z.Sqr(x)
   141  		}
   142  	})
   143  	b.Run("Inv", func(b *testing.B) {
   144  		for i := 0; i < b.N; i++ {
   145  			z.Inv(x)
   146  		}
   147  	})
   148  }