Skip to content

Commit

Permalink
move bignumber random and umod to util package big.go
Browse files Browse the repository at this point in the history
  • Loading branch information
rohenaz committed Sep 3, 2024
1 parent 1643a5f commit 4bdd76e
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 137 deletions.
93 changes: 0 additions & 93 deletions primitives/bignumber/bignumber.go

This file was deleted.

12 changes: 0 additions & 12 deletions primitives/bignumber/bignumber_test.go

This file was deleted.

10 changes: 5 additions & 5 deletions primitives/ec/privatekey.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import (
"math/big"

base58 "github.com/bitcoin-sv/go-sdk/compat/base58"
bignumber "github.com/bitcoin-sv/go-sdk/primitives/bignumber"
crypto "github.com/bitcoin-sv/go-sdk/primitives/hash"
keyshares "github.com/bitcoin-sv/go-sdk/primitives/keyshares"
"github.com/bitcoin-sv/go-sdk/util"
)

var (
Expand Down Expand Up @@ -216,11 +216,11 @@ func (p *PrivateKey) ToPolynomial(threshold int) (*keyshares.Polynomial, error)
points = append(points, keyshares.NewPointInFiniteField(big.NewInt(0), p.D))

// Generate random points for the rest of the polynomial
pb := bignumber.NewBigNumber(curve.P)
for i := 1; i < threshold; i++ {
x := bignumber.Random(32).Umod(pb)
y := bignumber.Random(32).Umod(pb)
points = append(points, keyshares.NewPointInFiniteField(x.ToBigInt(), y.ToBigInt()))
x := util.Umod(util.NewRandomBigInt(32), curve.P)
y := util.Umod(util.NewRandomBigInt(32), curve.P)

points = append(points, keyshares.NewPointInFiniteField(x, y))
}
return keyshares.NewPolynomial(points, threshold), nil
}
Expand Down
8 changes: 3 additions & 5 deletions primitives/ec/privatekey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import (
"strings"
"testing"

bignumber "github.com/bitcoin-sv/go-sdk/primitives/bignumber"
keyshares "github.com/bitcoin-sv/go-sdk/primitives/keyshares"
"github.com/bitcoin-sv/go-sdk/util"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -227,12 +227,10 @@ func TestStaticKeyShares(t *testing.T) {

func TestUmod(t *testing.T) {
big, _ := new(big.Int).SetString("96062736363790697194862546171394473697392259359830162418218835520086413272341", 10)
bigg := bignumber.NewBigNumber(big)

pb := bignumber.NewBigNumber(keyshares.NewCurve().P)
umodded := bigg.Umod(pb)
umodded := util.Umod(big, keyshares.NewCurve().P)

require.Equal(t, umodded.ToBigInt(), big)
require.Equal(t, umodded, big)
}

func TestPolynomialDifferentThresholdsAndShares(t *testing.T) {
Expand Down
25 changes: 8 additions & 17 deletions primitives/keyshares/polynomial.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"strings"

base58 "github.com/bitcoin-sv/go-sdk/compat/base58"
bignumber "github.com/bitcoin-sv/go-sdk/primitives/bignumber"
"github.com/bitcoin-sv/go-sdk/util"
)

type Polynomial struct {
Expand Down Expand Up @@ -38,12 +38,9 @@ type PointInFiniteField struct {
func NewPointInFiniteField(x, y *big.Int) *PointInFiniteField {
curve := NewCurve()

pb := bignumber.NewBigNumber(curve.P)
xb := bignumber.NewBigNumber(x).Umod(pb)
yb := bignumber.NewBigNumber(y).Umod(pb)
return &PointInFiniteField{
X: xb.ToBigInt(),
Y: yb.ToBigInt(),
X: util.Umod(x, curve.P),
Y: util.Umod(y, curve.P),
}
}

Expand Down Expand Up @@ -81,38 +78,32 @@ func NewPolynomial(points []*PointInFiniteField, threshold int) *Polynomial {

func (p *Polynomial) ValueAt(x *big.Int) *big.Int {
P := NewCurve().P
pb := bignumber.NewBigNumber(P)
y := big.NewInt(0)

for i := 0; i < p.Threshold; i++ {
term := p.Points[i].Y
for j := 0; j < p.Threshold; j++ {
if i != j {
numerator := new(big.Int).Sub(x, p.Points[j].X)
nb := bignumber.NewBigNumber(numerator)
numerator = nb.Umod(pb).ToBigInt()
numerator = util.Umod(numerator, P)

denominator := new(big.Int).Sub(p.Points[i].X, p.Points[j].X)
db := bignumber.NewBigNumber(denominator)
denominator = db.Umod(pb).ToBigInt()
denominator = util.Umod(denominator, P)

denominatorInv := new(big.Int).ModInverse(denominator, P)
if denominatorInv == nil {
denominatorInv = new(big.Int).SetInt64(0)
}

fraction := new(big.Int).Mul(numerator, denominatorInv)
fb := bignumber.NewBigNumber(fraction)
fraction = fb.Umod(pb).ToBigInt()
fraction = util.Umod(fraction, P)

term = new(big.Int).Mul(term, fraction)
tb := bignumber.NewBigNumber(term)
term = tb.Umod(pb).ToBigInt()
term = util.Umod(term, P)
}
}
y = y.Add(y, term)
yb := bignumber.NewBigNumber(y)
y = yb.Umod(pb).ToBigInt()
y = util.Umod(y, P)
}
log.Printf("Value at x=%d: %v", x, y)
return y
Expand Down
10 changes: 5 additions & 5 deletions primitives/keyshares/polynomial_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"math/big"
"testing"

bignumber "github.com/bitcoin-sv/go-sdk/primitives/bignumber"
"github.com/bitcoin-sv/go-sdk/util"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -59,11 +59,11 @@ func TestPolynomialValueAt(t *testing.T) {
}
}

// Test BigNumber.Umod with Curve.P
// Test util.Umod with Curve.P
func TestUmod(t *testing.T) {
require.Equal(t, 100, bignumber.NewBigNumberFromInt(100).Umod(bignumber.NewBigNumber(NewCurve().P)).ToNumber())
require.Equal(t, 63, bignumber.NewBigNumber(NewCurve().P).Umod(bignumber.NewBigNumberFromInt(100)).ToNumber())
require.Equal(t, 63, bignumber.NewBigNumber(NewCurve().P).Umod(bignumber.NewBigNumberFromInt(-100)).ToNumber())
require.Equal(t, int64(100), util.Umod(big.NewInt(100), NewCurve().P).Int64())
require.Equal(t, int64(63), util.Umod(NewCurve().P, big.NewInt(100)).Int64())
require.Equal(t, int64(63), util.Umod(NewCurve().P, big.NewInt(-100)).Int64())
}

func TestValueAtStaticPoly(t *testing.T) {
Expand Down
63 changes: 63 additions & 0 deletions util/big.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package util

import (
"crypto/rand"
"math/big"
)

// Umod returns the unsigned modulus of x and y.
// It ensures the result is always non-negative.
func Umod(x *big.Int, y *big.Int) *big.Int {
// Ensure divisor y is not zero
if y.Sign() == 0 {
panic("division by zero")
}

// If the dividend x is zero, the modulus is zero
if x.Sign() == 0 {
return big.NewInt(0)
}

mod := new(big.Int)

// Handle cases where x is negative and y is positive
if x.Sign() < 0 && y.Sign() > 0 {
mod.Neg(x)
mod.Mod(mod, y)
mod.Neg(mod)
if mod.Sign() < 0 {
mod.Add(mod, y)
}
} else if x.Sign() > 0 && y.Sign() < 0 {
// Handle cases where x is positive and y is negative
mod.Mod(x, new(big.Int).Neg(y))
} else if x.Sign() < 0 && y.Sign() < 0 {
// Handle cases where both x and y are negative
mod.Neg(x)
mod.Mod(mod, new(big.Int).Neg(y))
mod.Neg(mod)
if mod.Sign() < 0 {
mod.Sub(mod, y)
}
} else {
// Both numbers are positive
mod.Mod(x, y)
}

// Ensure the result is non-negative
if mod.Sign() < 0 {
mod.Add(mod, new(big.Int).Abs(y))
}

return mod
}

func NewRandomBigInt(byteLen int) *big.Int {
b := make([]byte, byteLen)
_, err := rand.Read(b)
if err != nil {
panic(err)
}

return new(big.Int).SetBytes(b)
}

0 comments on commit 4bdd76e

Please sign in to comment.