mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-06 19:06:42 +01:00
Add NewFloor40Floor helper method
Also added tracerr.Wrap(...) to missing places.
This commit is contained in:
@@ -32,6 +32,8 @@ var (
|
||||
// ErrFloat40NotEnoughPrecission is used when the given *big.Int can
|
||||
// not be represented as Float40 due not enough precission
|
||||
ErrFloat40NotEnoughPrecission = errors.New("Float40 error, not enough precission")
|
||||
|
||||
thres = big.NewInt(0x08_00_00_00_00)
|
||||
)
|
||||
|
||||
// Float40 represents a float in a 64 bit format
|
||||
@@ -68,7 +70,7 @@ func (f40 Float40) BigInt() (*big.Int, error) {
|
||||
var f40Uint64 uint64 = uint64(f40) & 0x00_00_00_FF_FF_FF_FF_FF
|
||||
f40Bytes, err := f40.Bytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
e := f40Bytes[0] & 0xF8 >> 3 // take first 5 bits
|
||||
@@ -79,25 +81,48 @@ func (f40 Float40) BigInt() (*big.Int, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// NewFloat40 encodes a *big.Int integer as a Float40, returning error in case
|
||||
// of loss during the encoding.
|
||||
func NewFloat40(f *big.Int) (Float40, error) {
|
||||
// newFloat40ME takes a *big.Int integer and returns the m (mantissa) & e
|
||||
// (exponent) from the Float40 representation
|
||||
func newFloat40ME(f *big.Int) (*big.Int, *big.Int) {
|
||||
m := f
|
||||
e := big.NewInt(0)
|
||||
zero := big.NewInt(0)
|
||||
ten := big.NewInt(10)
|
||||
thres := big.NewInt(0x08_00_00_00_00)
|
||||
for new(big.Int).Mod(m, ten).Cmp(zero) == 0 && m.Cmp(thres) >= 0 {
|
||||
m = new(big.Int).Div(m, ten)
|
||||
e = new(big.Int).Add(e, big.NewInt(1))
|
||||
}
|
||||
return m, e
|
||||
}
|
||||
|
||||
// NewFloat40 encodes a *big.Int integer as a Float40, returning error in case
|
||||
// of loss during the encoding.
|
||||
func NewFloat40(f *big.Int) (Float40, error) {
|
||||
m, e := newFloat40ME(f)
|
||||
if e.Int64() > 31 {
|
||||
return 0, ErrFloat40E31
|
||||
return 0, tracerr.Wrap(ErrFloat40E31)
|
||||
}
|
||||
if m.Cmp(thres) >= 0 {
|
||||
return 0, ErrFloat40NotEnoughPrecission
|
||||
return 0, tracerr.Wrap(ErrFloat40NotEnoughPrecission)
|
||||
}
|
||||
r := new(big.Int).Add(m,
|
||||
new(big.Int).Mul(e, thres))
|
||||
return Float40(r.Uint64()), nil
|
||||
}
|
||||
|
||||
// NewFloat40Floor encodes a *big.Int integer as a Float40, rounding down in
|
||||
// case of loss during the encoding. It returns an error in case that the number
|
||||
// is too big (e>31). Warning: this method should not be used inside the
|
||||
// hermez-node, it's a helper for external usage to generate valid Float40
|
||||
// values.
|
||||
func NewFloat40Floor(f *big.Int) (Float40, error) {
|
||||
m, e := newFloat40ME(f)
|
||||
if e.Int64() > 31 {
|
||||
return 0, tracerr.Wrap(ErrFloat40E31)
|
||||
}
|
||||
|
||||
r := new(big.Int).Add(m,
|
||||
new(big.Int).Mul(e, thres))
|
||||
|
||||
return Float40(r.Uint64()), nil
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/hermeznetwork/tracerr"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -55,7 +56,44 @@ func TestExpectError(t *testing.T) {
|
||||
bi, ok := new(big.Int).SetString(test, 10)
|
||||
require.True(t, ok)
|
||||
_, err := NewFloat40(bi)
|
||||
assert.Equal(t, testVector[test], err)
|
||||
assert.Equal(t, testVector[test], tracerr.Unwrap(err))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFloat40Floor(t *testing.T) {
|
||||
testVector := map[string][]uint64{
|
||||
// []int contains [Float40 value, Flot40 Floor value], when
|
||||
// Float40 value is expected to be 0, is because is expected to
|
||||
// be an error
|
||||
"9922334455000000000000000000000000000000": {1040714485495, 1040714485495},
|
||||
"9922334455000000000000000000000000000001": {0, 6846188881046405121},
|
||||
"9922334454999999999999999999999999999999": {0, 6846188881046405119},
|
||||
"42949672950000000000000000000000000000000": {1069446856703, 1069446856703},
|
||||
"99223344556573838487575": {0, 16754928163869896727},
|
||||
"992233445500000000000000000000000000000000": {0, 0},
|
||||
"343597383670000000000000000000000000000000": {1099511627775, 1099511627775},
|
||||
"343597383680000000000000000000000000000000": {0, 1099511627776},
|
||||
"343597383690000000000000000000000000000000": {0, 1099511627777},
|
||||
"343597383700000000000000000000000000000000": {0, 0},
|
||||
}
|
||||
for test := range testVector {
|
||||
bi, ok := new(big.Int).SetString(test, 10)
|
||||
require.True(t, ok)
|
||||
f40, err := NewFloat40(bi)
|
||||
if f40 == 0 {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
assert.Equal(t, testVector[test][0], uint64(f40))
|
||||
|
||||
f40, err = NewFloat40Floor(bi)
|
||||
if f40 == 0 {
|
||||
assert.Equal(t, ErrFloat40E31, tracerr.Unwrap(err))
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
assert.Equal(t, testVector[test][1], uint64(f40))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ func L1TxFromDataAvailability(b []byte, nLevels uint32) (*L1Tx, error) {
|
||||
}
|
||||
l1tx.ToIdx = toIdx
|
||||
l1tx.EffectiveAmount, err = Float40FromBytes(amountBytes).BigInt()
|
||||
return &l1tx, err
|
||||
return &l1tx, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// BytesGeneric returns the generic representation of a L1Tx. This method is
|
||||
|
||||
@@ -15,12 +15,12 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// TXIDPrefixL1UserTx is the prefix that determines that the TxID is
|
||||
// for a L1UserTx
|
||||
// TxIDPrefixL1UserTx is the prefix that determines that the TxID is for
|
||||
// a L1UserTx
|
||||
//nolinter:gomnd
|
||||
TxIDPrefixL1UserTx = byte(0)
|
||||
|
||||
// TXIDPrefixL1CoordTx is the prefix that determines that the TxID is
|
||||
// TxIDPrefixL1CoordTx is the prefix that determines that the TxID is
|
||||
// for a L1CoordinatorTx
|
||||
//nolinter:gomnd
|
||||
TxIDPrefixL1CoordTx = byte(1)
|
||||
|
||||
Reference in New Issue
Block a user