Skip to content

Commit

Permalink
rational to Exposed Fields
Browse files Browse the repository at this point in the history
  • Loading branch information
rigelrozanski committed Mar 28, 2018
1 parent 7da2789 commit db0a275
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 205 deletions.
1 change: 0 additions & 1 deletion types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ func ErrInsufficientCoins(msg string) Error {
func ErrInvalidCoins(msg string) Error {
return newError(CodeInvalidCoins, msg)
}

func ErrInvalidCoins(coins Coins) Error {
return newError(CodeInvalidCoins, coins.String())
}
Expand Down
131 changes: 75 additions & 56 deletions types/rational.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package types

import (
"bytes"
"encoding/json"
"fmt"
"math/big"
"strconv"
"strings"
Expand All @@ -20,7 +17,9 @@ import (
// we will panic unmarshalling into the
// nil embedded big.Rat
type Rat struct {
*big.Rat `json:"rat"`
Num int64 `json:"num"`
Denom int64 `json:"denom"`
//*big.Rat `json:"rat"`
}

// RatInterface - big Rat with additional functionality
Expand Down Expand Up @@ -48,17 +47,33 @@ type Rat struct {

// nolint - common values
var (
ZeroRat = Rat{big.NewRat(0, 1)}
OneRat = Rat{big.NewRat(1, 1)}
ZeroRat = NewRat(0) // Rat{big.NewRat(0, 1)}
OneRat = NewRat(1) // Rat{big.NewRat(1, 1)}
)

// New - create a new Rat from integers
func NewRat(Numerator int64, Denominator ...int64) Rat {
switch len(Denominator) {
//func NewRat(Numerator int64, Denominator ...int64) Rat {
//switch len(Denominator) {
//case 0:
//return Rat{big.NewRat(Numerator, 1)}
//case 1:
//return Rat{big.NewRat(Numerator, Denominator[0])}
//default:
//panic("improper use of New, can only have one denominator")
//}
//}
func NewRat(num int64, denom ...int64) Rat {
switch len(denom) {
case 0:
return Rat{big.NewRat(Numerator, 1)}
return Rat{
Num: num,
Denom: 1,
}
case 1:
return Rat{big.NewRat(Numerator, Denominator[0])}
return Rat{
Num: num,
Denom: denom[0],
}
default:
panic("improper use of New, can only have one denominator")
}
Expand Down Expand Up @@ -104,22 +119,34 @@ func NewRatFromDecimal(decimalStr string) (f Rat, err Error) {
num *= -1
}

return Rat{big.NewRat(int64(num), denom)}, nil
return NewRat(int64(num), denom), nil
}

//nolint
func (r Rat) GetRat() *big.Rat { return r.Rat } // GetRat - get big.Rat
func (r Rat) Num() int64 { return r.Rat.Num().Int64() } // Num - return the numerator
func (r Rat) Denom() int64 { return r.Rat.Denom().Int64() } // Denom - return the denominator
func (r Rat) IsZero() bool { return r.Num() == 0 } // IsZero - Is the Rat equal to zero
func (r Rat) Equal(r2 Rat) bool { return r.Rat.Cmp(r2.GetRat()) == 0 } // Equal - rationals are equal
func (r Rat) GT(r2 Rat) bool { return r.Rat.Cmp(r2.GetRat()) == 1 } // GT - greater than
func (r Rat) LT(r2 Rat) bool { return r.Rat.Cmp(r2.GetRat()) == -1 } // LT - less than
func (r Rat) Inv() Rat { return Rat{new(big.Rat).Inv(r.Rat)} } // Inv - inverse
func (r Rat) Mul(r2 Rat) Rat { return Rat{new(big.Rat).Mul(r.Rat, r2.GetRat())} } // Mul - multiplication
func (r Rat) Quo(r2 Rat) Rat { return Rat{new(big.Rat).Quo(r.Rat, r2.GetRat())} } // Quo - quotient
func (r Rat) Add(r2 Rat) Rat { return Rat{new(big.Rat).Add(r.Rat, r2.GetRat())} } // Add - addition
func (r Rat) Sub(r2 Rat) Rat { return Rat{new(big.Rat).Sub(r.Rat, r2.GetRat())} } // Sub - subtraction
func ToRat(r *big.Rat) Rat { return NewRat(r.Num().Int64(), r.Denom().Int64()) } // GetRat - get big.Rat
func (r Rat) GetRat() *big.Rat { return big.NewRat(r.Num, r.Denom) } // GetRat - get big.Rat
func (r Rat) IsZero() bool { return r.Num == 0 } // IsZero - Is the Rat equal to zero
func (r Rat) Equal(r2 Rat) bool { return r.GetRat().Cmp(r2.GetRat()) == 0 } // Equal - rationals are equal
func (r Rat) GT(r2 Rat) bool { return r.GetRat().Cmp(r2.GetRat()) == 1 } // GT - greater than
func (r Rat) LT(r2 Rat) bool { return r.GetRat().Cmp(r2.GetRat()) == -1 } // LT - less than
func (r Rat) Inv() Rat { return ToRat(new(big.Rat).Inv(r.GetRat())) } // Inv - inverse
func (r Rat) Mul(r2 Rat) Rat { return ToRat(new(big.Rat).Mul(r.GetRat(), r2.GetRat())) } // Mul - multiplication
func (r Rat) Quo(r2 Rat) Rat { return ToRat(new(big.Rat).Quo(r.GetRat(), r2.GetRat())) } // Quo - quotient
func (r Rat) Add(r2 Rat) Rat { return ToRat(new(big.Rat).Add(r.GetRat(), r2.GetRat())) } // Add - addition
func (r Rat) Sub(r2 Rat) Rat { return ToRat(new(big.Rat).Sub(r.GetRat(), r2.GetRat())) } // Sub - subtraction
//func (r Rat) GetRat() *big.Rat { return r.Rat } // GetRat - get big.Rat
//func (r Rat) Num() int64 { return r.Rat.Num().Int64() } // Num - return the numerator
//func (r Rat) Denom() int64 { return r.Rat.Denom().Int64() } // Denom - return the denominator
//func (r Rat) IsZero() bool { return r.Num() == 0 } // IsZero - Is the Rat equal to zero
//func (r Rat) Equal(r2 Rat) bool { return r.Rat.Cmp(r2.GetRat()) == 0 } // Equal - rationals are equal
//func (r Rat) GT(r2 Rat) bool { return r.Rat.Cmp(r2.GetRat()) == 1 } // GT - greater than
//func (r Rat) LT(r2 Rat) bool { return r.Rat.Cmp(r2.GetRat()) == -1 } // LT - less than
//func (r Rat) Inv() Rat { return Rat{new(big.Rat).Inv(r.Rat)} } // Inv - inverse
//func (r Rat) Mul(r2 Rat) Rat { return Rat{new(big.Rat).Mul(r.Rat, r2.GetRat())} } // Mul - multiplication
//func (r Rat) Quo(r2 Rat) Rat { return Rat{new(big.Rat).Quo(r.Rat, r2.GetRat())} } // Quo - quotient
//func (r Rat) Add(r2 Rat) Rat { return Rat{new(big.Rat).Add(r.Rat, r2.GetRat())} } // Add - addition
//func (r Rat) Sub(r2 Rat) Rat { return Rat{new(big.Rat).Sub(r.Rat, r2.GetRat())} } // Sub - subtraction
//func (r Rat) String() string { return fmt.Sprintf("%v/%v", r.Num(), r.Denom()) } // Sub - subtraction

var zero = big.NewInt(0)
var one = big.NewInt(1)
Expand All @@ -131,8 +158,8 @@ var ten = big.NewInt(10)
// EvaluateBig - evaluate the rational using bankers rounding
func (r Rat) EvaluateBig() *big.Int {

num := r.Rat.Num()
denom := r.Rat.Denom()
num := r.GetRat().Num()
denom := r.GetRat().Denom()

d, rem := new(big.Int), new(big.Int)
d.QuoRem(num, denom, rem)
Expand Down Expand Up @@ -165,43 +192,35 @@ func (r Rat) Evaluate() int64 {

// Round - round Rat with the provided precisionFactor
func (r Rat) Round(precisionFactor int64) Rat {
rTen := Rat{new(big.Rat).Mul(r.Rat, big.NewRat(precisionFactor, 1))}
return Rat{big.NewRat(rTen.Evaluate(), precisionFactor)}
rTen := ToRat(new(big.Rat).Mul(r.GetRat(), big.NewRat(precisionFactor, 1)))
return ToRat(big.NewRat(rTen.Evaluate(), precisionFactor))
}

//___________________________________________________________________________________

var ratCdc JSONCodec // TODO wire.Codec

// Hack to just use json.Marshal for everything until
// we update for amino
type JSONCodec struct{}

func (jc JSONCodec) MarshalJSON(o interface{}) ([]byte, error) {
return json.Marshal(o)
}

func (jc JSONCodec) UnmarshalJSON(bz []byte, o interface{}) error {
return json.Unmarshal(bz, o)
}
//type JSONCodec struct{}
//func (jc JSONCodec) MarshalJSON(o interface{}) ([]byte, error) { return json.Marshal(o) }
//func (jc JSONCodec) UnmarshalJSON(bz []byte, o interface{}) error { return json.Unmarshal(bz, o) }

// Wraps r.MarshalText() in quotes to make it a valid JSON string.
func (r Rat) MarshalJSON() ([]byte, error) {
bz, err := r.MarshalText()
if err != nil {
return bz, err
}
return []byte(fmt.Sprintf(`"%s"`, bz)), nil
}
//func (r Rat) MarshalAmino() (string, error) {
//bz, err := r.MarshalText()
//if err != nil {
//return "", err
//}
//return fmt.Sprintf(`%s`, bz), nil
//}

// Requires a valid JSON string - strings quotes and calls UnmarshalText
func (r *Rat) UnmarshalJSON(data []byte) (err error) {
quote := []byte(`"`)
if len(data) < 2 ||
!bytes.HasPrefix(data, quote) ||
!bytes.HasSuffix(data, quote) {
return fmt.Errorf("JSON encoded Rat must be a quote-delimitted string")
}
data = bytes.Trim(data, `"`)
return r.UnmarshalText(data)
}
//// Requires a valid JSON string - strings quotes and calls UnmarshalText
//func (r *Rat) UnmarshalAmino(data string) (err error) {
////quote := []byte(`"`)
////if len(data) < 2 ||
////!bytes.HasPrefix(data, quote) ||
////!bytes.HasSuffix(data, quote) {
////return fmt.Errorf("JSON encoded Rat must be a quote-delimitted string")
////}
////data = bytes.Trim(data, `"`)
//return r.UnmarshalText([]byte(data))
//}
68 changes: 36 additions & 32 deletions types/rational_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"math/big"
"testing"

wire "github.com/cosmos/cosmos-sdk/wire"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -132,7 +133,7 @@ func TestArithmatic(t *testing.T) {
assert.True(t, tc.resAdd.Equal(tc.r1.Add(tc.r2)), "r1 %v, r2 %v", tc.r1.GetRat(), tc.r2.GetRat())
assert.True(t, tc.resSub.Equal(tc.r1.Sub(tc.r2)), "r1 %v, r2 %v", tc.r1.GetRat(), tc.r2.GetRat())

if tc.r2.Num() == 0 { // panic for divide by zero
if tc.r2.Num == 0 { // panic for divide by zero
assert.Panics(t, func() { tc.r1.Quo(tc.r2) })
} else {
assert.True(t, tc.resDiv.Equal(tc.r1.Quo(tc.r2)), "r1 %v, r2 %v", tc.r1.GetRat(), tc.r2.GetRat())
Expand Down Expand Up @@ -175,58 +176,61 @@ func TestRound(t *testing.T) {
require.True(t, worked)

tests := []struct {
r1, res Rat
r, res Rat
precFactor int64
}{
{NewRat(333, 777), NewRat(429, 1000), 1000},
{Rat{new(big.Rat).SetFrac(big3, big7)}, NewRat(429, 1000), 1000},
{Rat{new(big.Rat).SetFrac(big3, big7)}, NewRat(4285714286, 10000000000), 10000000000},
{ToRat(new(big.Rat).SetFrac(big3, big7)), NewRat(429, 1000), 1000},
{ToRat(new(big.Rat).SetFrac(big3, big7)), ToRat(big.NewRat(4285714286, 10000000000)), 10000000000},
{NewRat(1, 2), NewRat(1, 2), 1000},
}

for _, tc := range tests {
assert.Equal(t, tc.res, tc.r1.Round(tc.precFactor), "%v", tc.r1)
negR1, negRes := tc.r1.Mul(NewRat(-1)), tc.res.Mul(NewRat(-1))
assert.Equal(t, tc.res, tc.r.Round(tc.precFactor), "%v", tc.r)
negR1, negRes := tc.r.Mul(NewRat(-1)), tc.res.Mul(NewRat(-1))
assert.Equal(t, negRes, negR1.Round(tc.precFactor), "%v", negR1)
}
}

func TestZeroSerializationJSON(t *testing.T) {
r := NewRat(0, 1)
err := r.UnmarshalJSON([]byte(`"0/1"`))
assert.Nil(t, err)
err = r.UnmarshalJSON([]byte(`"0/0"`))
assert.NotNil(t, err)
err = r.UnmarshalJSON([]byte(`"1/0"`))
assert.NotNil(t, err)
err = r.UnmarshalJSON([]byte(`"{}"`))
assert.NotNil(t, err)
}
//func TestZeroSerializationJSON(t *testing.T) {
//r := NewRat(0, 1)
//err := r.UnmarshalJSON([]byte(`"0/1"`))
//assert.Nil(t, err)
//err = r.UnmarshalJSON([]byte(`"0/0"`))
//assert.NotNil(t, err)
//err = r.UnmarshalJSON([]byte(`"1/0"`))
//assert.NotNil(t, err)
//err = r.UnmarshalJSON([]byte(`"{}"`))
//assert.NotNil(t, err)
//}

func TestSerializationJSON(t *testing.T) {
r := NewRat(1, 3)
//func TestSerializationJSON(t *testing.T) {
//r := NewRat(1, 3)

bz, err := r.MarshalText()
require.Nil(t, err)
//bz, err := r.MarshalText()
//require.Nil(t, err)

r2 := NewRat(0, 1)
err = r2.UnmarshalText(bz)
require.Nil(t, err)
//r2 := NewRat(0, 1)
//err = r2.UnmarshalText(bz)
//require.Nil(t, err)

assert.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2)
}
//assert.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2)
//}

var cdc = wire.NewCodec() //var jsonCdc JSONCodec // TODO wire.Codec

func TestSerializationGoWire(t *testing.T) {
r := NewRat(1, 3)

bz, err := ratCdc.MarshalJSON(r)
bz, err := cdc.MarshalBinary(r)
require.Nil(t, err)

bz, err = r.MarshalJSON()
require.Nil(t, err)
//str, err := r.MarshalJSON()
//require.Nil(t, err)

r2 := NewRat(0, 1)
err = ratCdc.UnmarshalJSON(bz, &r2)
err = cdc.UnmarshalBinary([]byte(bz), &r2)
//panic(fmt.Sprintf("debug bz: %v\n", string(bz)))
require.Nil(t, err)

assert.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2)
Expand All @@ -241,12 +245,12 @@ type testEmbedStruct struct {
func TestEmbeddedStructSerializationGoWire(t *testing.T) {
obj := testEmbedStruct{"foo", 10, NewRat(1, 3)}

bz, err := ratCdc.MarshalJSON(obj)
bz, err := cdc.MarshalJSON(obj)
require.Nil(t, err)

var obj2 testEmbedStruct
obj2.Field3 = NewRat(0, 1) // ... needs to be initialized
err = ratCdc.UnmarshalJSON(bz, &obj2)
err = cdc.UnmarshalJSON(bz, &obj2)
require.Nil(t, err)

assert.Equal(t, obj.Field1, obj2.Field1)
Expand Down
2 changes: 2 additions & 0 deletions types/tx_msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func NewStdFee(gas int64, amount ...Coin) StdFee {
}
}

// fee bytes for signing later
func (fee StdFee) Bytes() []byte {
// normalize. XXX
// this is a sign of something ugly
Expand Down Expand Up @@ -172,6 +173,7 @@ func NewTestMsg(addrs ...Address) *TestMsg {
}
}

//nolint
func (msg *TestMsg) Type() string { return "TestMsg" }
func (msg *TestMsg) Get(key interface{}) (value interface{}) { return nil }
func (msg *TestMsg) GetSignBytes() []byte {
Expand Down
3 changes: 2 additions & 1 deletion x/stake/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,8 @@ func (k Keeper) getParams(ctx sdk.Context) (params Params) {
store := ctx.KVStore(k.storeKey)
b := store.Get(ParamKey)
if b == nil {
return defaultParams()
k.params = defaultParams()
return k.params
}

err := k.cdc.UnmarshalJSON(b, &params)
Expand Down
2 changes: 1 addition & 1 deletion x/stake/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ func TestState(t *testing.T) {
keeper.setCandidate(ctx, candidate)
resCand, found := keeper.getCandidate(ctx, addrVal)
assert.True(t, found)
assert.True(t, candidatesEqual(candidate, resCand), "%#v \n %#v", resCand, candidate)
assert.True(t, candidatesEqual(candidate, resCand), "%v \n %v", resCand, candidate)

// modify a records, save, and retrieve
candidate.Liabilities = sdk.NewRat(99)
Expand Down
Loading

0 comments on commit db0a275

Please sign in to comment.