// // Copyright Coinbase, Inc. All Rights Reserved. // // SPDX-License-Identifier: Apache-2.0 // package bls12381 import ( crand "crypto/rand" "math/big" "math/rand" "testing" "github.com/stretchr/testify/require" "github.com/sonr-io/sonr/crypto/internal" ) func TestFpSetOne(t *testing.T) { var fp fp fp.SetOne() require.NotNil(t, fp) require.Equal(t, fp, r) } func TestFpSetUint64(t *testing.T) { var act fp act.SetUint64(1 << 60) require.NotNil(t, act) // Remember it will be in montgomery form require.Equal(t, act[0], uint64(0xf6ea9fde37db5e8c)) } func TestFpAdd(t *testing.T) { var lhs, rhs, exp, res fp lhs.SetOne() rhs.SetOne() exp.SetUint64(2) res.Add(&lhs, &rhs) require.NotNil(t, res) require.Equal(t, 1, res.Equal(&exp)) // Fuzz test for i := 0; i < 25; i++ { // Divide by 4 to prevent overflow false errors l := rand.Uint64() >> 2 r := rand.Uint64() >> 2 e := l + r lhs.SetUint64(l) rhs.SetUint64(r) exp.SetUint64(e) res.Add(&lhs, &rhs) require.NotNil(t, res) require.Equal(t, exp, res) } } func TestFpSub(t *testing.T) { var lhs, rhs, exp, res fp lhs.SetOne() rhs.SetOne() exp.SetZero() res.Sub(&lhs, &rhs) require.NotNil(t, res) require.Equal(t, 1, res.Equal(&exp)) // Fuzz test for i := 0; i < 25; i++ { // Divide by 4 to prevent overflow false errors l := rand.Uint64() >> 2 r := rand.Uint64() >> 2 if l < r { l, r = r, l } e := l - r lhs.SetUint64(l) rhs.SetUint64(r) exp.SetUint64(e) res.Sub(&lhs, &rhs) require.NotNil(t, res) require.Equal(t, exp, res) } } func TestFpMul(t *testing.T) { var lhs, rhs, exp, res fp lhs.SetOne() rhs.SetOne() exp.SetOne() res.Mul(&lhs, &rhs) require.NotNil(t, res) require.Equal(t, 1, res.Equal(&exp)) // Fuzz test for i := 0; i < 25; i++ { // Divide by 4 to prevent overflow false errors l := rand.Uint32() r := rand.Uint32() e := uint64(l) * uint64(r) lhs.SetUint64(uint64(l)) rhs.SetUint64(uint64(r)) exp.SetUint64(e) res.Mul(&lhs, &rhs) require.NotNil(t, res) require.Equal(t, exp, res) } } func TestFpDouble(t *testing.T) { var a, e, res fp a.SetUint64(2) e.SetUint64(4) require.Equal(t, &e, res.Double(&a)) for i := 0; i < 25; i++ { tv := rand.Uint32() ttv := uint64(tv) * 2 a.SetUint64(uint64(tv)) e.SetUint64(ttv) require.Equal(t, &e, res.Double(&a)) } } func TestFpSquare(t *testing.T) { var a, e, res fp a.SetUint64(4) e.SetUint64(16) require.Equal(t, 1, e.Equal(res.Square(&a))) a.SetUint64(2854263694) e.SetUint64(8146821234886525636) require.Equal(t, 1, e.Equal(res.Square(&a))) for i := 0; i < 25; i++ { j := rand.Uint32() exp := uint64(j) * uint64(j) e.SetUint64(exp) a.SetUint64(uint64(j)) require.Equal(t, 1, e.Equal(res.Square(&a)), "exp = %d, j = %d", exp, j) } } func TestFpNeg(t *testing.T) { var g, a, e fp g.SetLimbs(&[Limbs]uint64{7, 0, 0, 0, 0, 0}) a.SetOne() a.Neg(&a) e.SetRaw( &[Limbs]uint64{ 0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206, }, ) require.Equal(t, 1, e.Equal(&a)) a.Neg(&g) e.SetRaw( &[Limbs]uint64{ 0x21baffffffe90017, 0x445bffa5cba3ffed, 0xd028c5627db257bc, 0x14275ad5a2de0d96, 0x3e7434202365960e, 0x0249d4217f792796, }, ) require.Equal(t, e, a) } func TestFpExp(t *testing.T) { var a, e, by fp e.SetUint64(8) a.SetUint64(2) by.SetUint64(3) require.Equal(t, &e, a.Exp(&a, &by)) } func TestFpSqrt(t *testing.T) { var t1, t2, t3 fp t1.SetUint64(2) t2.Neg(&t1) t3.Square(&t1) _, wasSquare := t3.Sqrt(&t3) require.Equal(t, 1, wasSquare) require.Equal(t, 1, t1.Equal(&t3)|t2.Equal(&t3)) t1.SetUint64(5) _, wasSquare = t1.Sqrt(&t1) require.Equal(t, 0, wasSquare) } func TestFpInvert(t *testing.T) { var two, twoInv, a, lhs, rhs, rhsInv fp twoInv.SetRaw( &[Limbs]uint64{ 0x1804000000015554, 0x855000053ab00001, 0x633cb57c253c276f, 0x6e22d1ec31ebb502, 0xd3916126f2d14ca2, 0x17fbb8571a006596, }, ) two.SetUint64(2) _, inverted := a.Invert(&two) require.Equal(t, 1, inverted) require.Equal(t, &a, &twoInv) lhs.SetUint64(9) rhs.SetUint64(3) _, inverted = rhsInv.Invert(&rhs) require.Equal(t, 1, inverted) require.Equal(t, &rhs, lhs.Mul(&lhs, &rhsInv)) rhs.SetZero() _, inverted = lhs.Invert(&rhs) require.Equal(t, 0, inverted) } func TestFpCMove(t *testing.T) { var t1, t2, tt fp t1.SetUint64(5) t2.SetUint64(10) require.Equal(t, &t1, tt.CMove(&t1, &t2, 0)) require.Equal(t, &t2, tt.CMove(&t1, &t2, 1)) } func TestFpBytes(t *testing.T) { var t1, t2 fp t1.SetUint64(99) seq := t1.Bytes() _, suc := t2.SetBytes(&seq) require.Equal(t, 1, suc) require.Equal(t, t1, t2) for i := 0; i < 25; i++ { t1.SetUint64(rand.Uint64()) seq = t1.Bytes() _, suc = t2.SetBytes(&seq) require.Equal(t, 1, suc) require.Equal(t, t1, t2) } } func TestFpBigInt(t *testing.T) { var t1, t2, e fp t1.SetBigInt(big.NewInt(9999)) t2.SetBigInt(t1.BigInt()) require.Equal(t, t1, t2) e.SetRaw( &[Limbs]uint64{ 0x922af810e5e35f31, 0x6bc75973ed382d59, 0xd4716c9d4d491d42, 0x69d98d1ebeeb3f6e, 0x7e425d7b46d4a82b, 0x12d04b0965870e92, }, ) b := new( big.Int, ).SetBytes([]byte{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}) t1.SetBigInt(b) require.Equal(t, e, t1) e.Neg(&e) b.Neg(b) t1.SetBigInt(b) require.Equal(t, e, t1) } func TestFpSetBytesWideBigInt(t *testing.T) { var a fp var tv2 [96]byte for i := 0; i < 25; i++ { _, _ = crand.Read(tv2[:]) e := new(big.Int).SetBytes(tv2[:]) e.Mod(e, biModulus) tv := internal.ReverseScalarBytes(tv2[:]) copy(tv2[:], tv) a.SetBytesWide(&tv2) require.Equal(t, 0, e.Cmp(a.BigInt())) } } func TestFpToMontgomery(t *testing.T) { var v fp v.SetUint64(2) require.Equal( t, fp{ 0x321300000006554f, 0xb93c0018d6c40005, 0x57605e0db0ddbb51, 0x8b256521ed1f9bcb, 0x6cf28d7901622c03, 0x11ebab9dbb81e28c, }, v, ) } func TestFpFromMontgomery(t *testing.T) { var v fp e := fp{2, 0, 0, 0, 0, 0} v.SetUint64(2) v.fromMontgomery(&v) require.Equal(t, e, v) } func TestFpLexicographicallyLargest(t *testing.T) { require.Equal(t, 0, new(fp).SetZero().LexicographicallyLargest()) require.Equal(t, 0, new(fp).SetOne().LexicographicallyLargest()) require.Equal(t, 0, (&fp{ 0xa1fafffffffe5557, 0x995bfff976a3fffe, 0x03f41d24d174ceb4, 0xf6547998c1995dbd, 0x778a468f507a6034, 0x020559931f7f8103, }).LexicographicallyLargest()) require.Equal(t, 1, (&fp{ 0x1804000000015554, 0x855000053ab00001, 0x633cb57c253c276f, 0x6e22d1ec31ebb502, 0xd3916126f2d14ca2, 0x17fbb8571a006596, }).LexicographicallyLargest()) require.Equal(t, 1, (&fp{ 0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206, }).LexicographicallyLargest()) }