rational embedes bigRat

This commit is contained in:
rigelrozanski 2018-04-30 17:21:14 -04:00
parent b79ab072e7
commit ce32117399
16 changed files with 231 additions and 275 deletions

View File

@ -265,7 +265,6 @@ func (app *BaseApp) SetOption(req abci.RequestSetOption) (res abci.ResponseSetOp
// InitChain runs the initialization logic directly on the CommitMultiStore and commits it. // InitChain runs the initialization logic directly on the CommitMultiStore and commits it.
func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) { func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) {
if app.initChainer == nil { if app.initChainer == nil {
// TODO: should we have some default handling of validators?
return return
} }
@ -275,7 +274,6 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC
// NOTE: we don't commit, but BeginBlock for block 1 // NOTE: we don't commit, but BeginBlock for block 1
// starts from this deliverState // starts from this deliverState
return return
} }

View File

@ -106,8 +106,8 @@ func MakeCodec() *wire.Codec {
func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
stateJSON := req.AppStateBytes stateJSON := req.AppStateBytes
genesisState := new(GenesisState) var genesisState GenesisState
err := app.cdc.UnmarshalJSON(stateJSON, genesisState) err := app.cdc.UnmarshalJSON(stateJSON, &genesisState)
if err != nil { if err != nil {
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
// return sdk.ErrGenesisParse("").TraceCause(err, "") // return sdk.ErrGenesisParse("").TraceCause(err, "")

View File

@ -1,6 +1,7 @@
package types package types
import ( import (
"bytes"
"fmt" "fmt"
"math/big" "math/big"
"strconv" "strconv"
@ -13,68 +14,24 @@ import (
// __ /___...._____ _\o // __ /___...._____ _\o
// __| |_ |_ // __| |_ |_
// Rat - extend big.Rat
// NOTE: never use new(Rat) or else // NOTE: never use new(Rat) or else
// we will panic unmarshalling into the // we will panic unmarshalling into the
// nil embedded big.Rat // nil embedded big.Rat
type Rat struct { type Rat struct {
Num int64 `json:"num"` big.Rat `json:"rat"`
Denom int64 `json:"denom"`
//*big.Rat `json:"rat"`
} }
// RatInterface - big Rat with additional functionality
// NOTE: we only have one implementation of this interface
// and don't use it anywhere, but it might come in handy
// if we want to provide Rat types that include
// the units of the value in the type system.
//type RatInterface interface {
//GetRat() *big.Rat
//Num() int64
//Denom() int64
//GT(Rat) bool
//LT(Rat) bool
//Equal(Rat) bool
//IsZero() bool
//Inv() Rat
//Mul(Rat) Rat
//Quo(Rat) Rat
//Add(Rat) Rat
//Sub(Rat) Rat
//Round(int64) Rat
//Evaluate() int64
//}
//var _ Rat = Rat{} // enforce at compile time
// nolint - common values // nolint - common values
var ( func ZeroRat() Rat { return Rat{*big.NewRat(0, 1)} }
ZeroRat = NewRat(0) // Rat{big.NewRat(0, 1)} func OneRat() Rat { return Rat{*big.NewRat(1, 1)} }
OneRat = NewRat(1) // Rat{big.NewRat(1, 1)}
)
// New - create a new Rat from integers // New - create a new Rat from integers
//func NewRat(Numerator int64, Denominator ...int64) Rat { func NewRat(Numerator int64, Denominator ...int64) Rat {
//switch len(Denominator) { 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: case 0:
return Rat{ return Rat{*big.NewRat(Numerator, 1)}
Num: num,
Denom: 1,
}
case 1: case 1:
return Rat{ return Rat{*big.NewRat(Numerator, Denominator[0])}
Num: num,
Denom: denom[0],
}
default: default:
panic("improper use of New, can only have one denominator") panic("improper use of New, can only have one denominator")
} }
@ -124,30 +81,17 @@ func NewRatFromDecimal(decimalStr string) (f Rat, err Error) {
} }
//nolint //nolint
func ToRat(r *big.Rat) Rat { return NewRat(r.Num().Int64(), r.Denom().Int64()) } // GetRat - get big.Rat func (r Rat) Num() int64 { return r.Rat.Num().Int64() } // Num - return the numerator
func (r Rat) GetRat() *big.Rat { return big.NewRat(r.Num, r.Denom) } // GetRat - get big.Rat 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) 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) Equal(r2 Rat) bool { return (&(r.Rat)).Cmp(&(r2.Rat)) == 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) GT(r2 Rat) bool { return (&(r.Rat)).Cmp(&(r2.Rat)) == 1 } // Equal - rationals are equal
func (r Rat) LT(r2 Rat) bool { return r.GetRat().Cmp(r2.GetRat()) == -1 } // LT - less than func (r Rat) LT(r2 Rat) bool { return (&(r.Rat)).Cmp(&(r2.Rat)) == -1 } // Equal - rationals are equal
func (r Rat) Inv() Rat { return ToRat(new(big.Rat).Inv(r.GetRat())) } // Inv - inverse func (r Rat) Mul(r2 Rat) Rat { return Rat{*new(big.Rat).Mul(&(r.Rat), &(r2.Rat))} } // Mul - multiplication
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 Rat{*new(big.Rat).Quo(&(r.Rat), &(r2.Rat))} } // Quo - quotient
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 Rat{*new(big.Rat).Add(&(r.Rat), &(r2.Rat))} } // Add - addition
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 Rat{*new(big.Rat).Sub(&(r.Rat), &(r2.Rat))} } // Sub - subtraction
func (r Rat) Sub(r2 Rat) Rat { return ToRat(new(big.Rat).Sub(r.GetRat(), r2.GetRat())) } // Sub - subtraction func (r Rat) String() string { return fmt.Sprintf("%v/%v", r.Num(), r.Denom()) } // 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 ( var (
zero = big.NewInt(0) zero = big.NewInt(0)
@ -161,8 +105,8 @@ var (
// evaluate the rational using bankers rounding // evaluate the rational using bankers rounding
func (r Rat) EvaluateBig() *big.Int { func (r Rat) EvaluateBig() *big.Int {
num := r.GetRat().Num() num := r.Rat.Num()
denom := r.GetRat().Denom() denom := r.Rat.Denom()
d, rem := new(big.Int), new(big.Int) d, rem := new(big.Int), new(big.Int)
d.QuoRem(num, denom, rem) d.QuoRem(num, denom, rem)
@ -195,8 +139,8 @@ func (r Rat) Evaluate() int64 {
// round Rat with the provided precisionFactor // round Rat with the provided precisionFactor
func (r Rat) Round(precisionFactor int64) Rat { func (r Rat) Round(precisionFactor int64) Rat {
rTen := ToRat(new(big.Rat).Mul(r.GetRat(), big.NewRat(precisionFactor, 1))) rTen := Rat{*new(big.Rat).Mul(&(r.Rat), big.NewRat(precisionFactor, 1))}
return ToRat(big.NewRat(rTen.Evaluate(), precisionFactor)) return Rat{*big.NewRat(rTen.Evaluate(), precisionFactor)}
} }
// TODO panic if negative or if totalDigits < len(initStr)??? // TODO panic if negative or if totalDigits < len(initStr)???
@ -212,26 +156,33 @@ func (r Rat) ToLeftPadded(totalDigits int8) string {
// Hack to just use json.Marshal for everything until // Hack to just use json.Marshal for everything until
// we update for amino // we update for amino
//type JSONCodec struct{} //type JSONCodec struct{}
//nolint
//func (jc JSONCodec) MarshalJSON(o interface{}) ([]byte, error) { return json.Marshal(o) } //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) } //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. //Wraps r.MarshalText() in quotes to make it a valid JSON string.
//func (r Rat) MarshalAmino() (string, error) { func (r Rat) MarshalJSON() ([]byte, error) {
//bz, err := r.MarshalText() bz, err := (&(r.Rat)).MarshalText()
//if err != nil { if err != nil {
//return "", err return nil, err
//} }
//return fmt.Sprintf(`%s`, bz), nil return []byte(fmt.Sprintf("\"%s\"", bz)), nil
//} }
//// Requires a valid JSON string - strings quotes and calls UnmarshalText // Requires a valid JSON string - strings quotes and calls UnmarshalText
//func (r *Rat) UnmarshalAmino(data string) (err error) { func (r *Rat) UnmarshalJSON(data []byte) (err error) {
////quote := []byte(`"`) quote := []byte(`"`)
////if len(data) < 2 || if len(data) < 2 ||
////!bytes.HasPrefix(data, quote) || !bytes.HasPrefix(data, quote) ||
////!bytes.HasSuffix(data, quote) { !bytes.HasSuffix(data, quote) {
////return fmt.Errorf("JSON encoded Rat must be a quote-delimitted string") return fmt.Errorf("JSON encoded Rat must be a quote-delimitted string, have %v", string(data))
////} }
////data = bytes.Trim(data, `"`) data = bytes.Trim(data, `"`)
//return r.UnmarshalText([]byte(data)) tempRat := big.NewRat(0, 1)
//} err = tempRat.UnmarshalText(data)
if err != nil {
return err
}
r.Rat = *tempRat
return nil
}

View File

@ -129,14 +129,14 @@ func TestArithmatic(t *testing.T) {
} }
for _, tc := range tests { for _, tc := range tests {
assert.True(t, tc.resMul.Equal(tc.r1.Mul(tc.r2)), "r1 %v, r2 %v", tc.r1.GetRat(), tc.r2.GetRat()) assert.True(t, tc.resMul.Equal(tc.r1.Mul(tc.r2)), "r1 %v, r2 %v", tc.r1.Rat, tc.r2.Rat)
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.resAdd.Equal(tc.r1.Add(tc.r2)), "r1 %v, r2 %v", tc.r1.Rat, tc.r2.Rat)
assert.True(t, tc.resSub.Equal(tc.r1.Sub(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.Rat, tc.r2.Rat)
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) }) assert.Panics(t, func() { tc.r1.Quo(tc.r2) })
} else { } else {
assert.True(t, tc.resDiv.Equal(tc.r1.Quo(tc.r2)), "r1 %v, r2 %v", tc.r1.GetRat(), tc.r2.GetRat()) assert.True(t, tc.resDiv.Equal(tc.r1.Quo(tc.r2)), "r1 %v, r2 %v", tc.r1.Rat, tc.r2.Rat)
} }
} }
} }
@ -180,8 +180,8 @@ func TestRound(t *testing.T) {
precFactor int64 precFactor int64
}{ }{
{NewRat(333, 777), NewRat(429, 1000), 1000}, {NewRat(333, 777), NewRat(429, 1000), 1000},
{ToRat(new(big.Rat).SetFrac(big3, big7)), NewRat(429, 1000), 1000}, {Rat{*new(big.Rat).SetFrac(big3, big7)}, NewRat(429, 1000), 1000},
{ToRat(new(big.Rat).SetFrac(big3, big7)), ToRat(big.NewRat(4285714286, 10000000000)), 10000000000}, {Rat{*new(big.Rat).SetFrac(big3, big7)}, Rat{*big.NewRat(4285714286, 10000000000)}, 10000000000},
{NewRat(1, 2), NewRat(1, 2), 1000}, {NewRat(1, 2), NewRat(1, 2), 1000},
} }
@ -209,47 +209,40 @@ func TestToLeftPadded(t *testing.T) {
} }
} }
//func TestZeroSerializationJSON(t *testing.T) { func TestZeroSerializationJSON(t *testing.T) {
//r := NewRat(0, 1) r := NewRat(0, 1)
//err := r.UnmarshalJSON([]byte(`"0/1"`)) err := r.UnmarshalJSON([]byte(`"0/1"`))
//assert.Nil(t, err) assert.Nil(t, err)
//err = r.UnmarshalJSON([]byte(`"0/0"`)) err = r.UnmarshalJSON([]byte(`"0/0"`))
//assert.NotNil(t, err) assert.NotNil(t, err)
//err = r.UnmarshalJSON([]byte(`"1/0"`)) err = r.UnmarshalJSON([]byte(`"1/0"`))
//assert.NotNil(t, err) assert.NotNil(t, err)
//err = r.UnmarshalJSON([]byte(`"{}"`)) err = r.UnmarshalJSON([]byte(`"{}"`))
//assert.NotNil(t, err) assert.NotNil(t, err)
//} }
//func TestSerializationJSON(t *testing.T) { func TestSerializationText(t *testing.T) {
//r := NewRat(1, 3) r := NewRat(1, 3)
//bz, err := r.MarshalText() bz, err := r.MarshalText()
//require.Nil(t, err) require.NoError(t, err)
//r2 := NewRat(0, 1) r2 := NewRat(0, 1)
//err = r2.UnmarshalText(bz) err = r2.UnmarshalText(bz)
//require.Nil(t, err) require.NoError(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 var cdc = wire.NewCodec() //var jsonCdc JSONCodec // TODO wire.Codec
func TestSerializationGoWire(t *testing.T) { func TestSerializationGoWire(t *testing.T) {
r := NewRat(1, 3) r := NewRat(1, 3)
bz, err := cdc.MarshalJSON(r)
bz, err := cdc.MarshalBinary(r) require.NoError(t, err)
require.Nil(t, err)
//str, err := r.MarshalJSON()
//require.Nil(t, err)
r2 := NewRat(0, 1) r2 := NewRat(0, 1)
err = cdc.UnmarshalBinary([]byte(bz), &r2) err = cdc.UnmarshalJSON(bz, &r2)
//panic(fmt.Sprintf("debug bz: %v\n", string(bz))) require.NoError(t, err)
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)
} }
@ -261,17 +254,14 @@ type testEmbedStruct struct {
func TestEmbeddedStructSerializationGoWire(t *testing.T) { func TestEmbeddedStructSerializationGoWire(t *testing.T) {
obj := testEmbedStruct{"foo", 10, NewRat(1, 3)} obj := testEmbedStruct{"foo", 10, NewRat(1, 3)}
bz, err := cdc.MarshalJSON(obj)
bz, err := cdc.MarshalBinary(obj)
require.Nil(t, err) require.Nil(t, err)
var obj2 testEmbedStruct var obj2 testEmbedStruct
obj2.Field3 = NewRat(0, 1) // ... needs to be initialized err = cdc.UnmarshalJSON(bz, &obj2)
err = cdc.UnmarshalBinary(bz, &obj2)
require.Nil(t, err) require.Nil(t, err)
assert.Equal(t, obj.Field1, obj2.Field1) assert.Equal(t, obj.Field1, obj2.Field1)
assert.Equal(t, obj.Field2, obj2.Field2) assert.Equal(t, obj.Field2, obj2.Field2)
assert.True(t, obj.Field3.Equal(obj2.Field3), "original: %v, unmarshalled: %v", obj, obj2) assert.True(t, obj.Field3.Equal(obj2.Field3), "original: %v, unmarshalled: %v", obj, obj2)
} }

View File

@ -166,7 +166,7 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command {
if err != nil { if err != nil {
return err return err
} }
if !shares.GT(sdk.ZeroRat) { if !shares.GT(sdk.ZeroRat()) {
return fmt.Errorf("shares must be positive integer or decimal (ex. 123, 1.23456789)") return fmt.Errorf("shares must be positive integer or decimal (ex. 123, 1.23456789)")
} }
} }

View File

@ -165,7 +165,7 @@ func delegate(ctx sdk.Context, k Keeper, delegatorAddr sdk.Address,
bond = DelegatorBond{ bond = DelegatorBond{
DelegatorAddr: delegatorAddr, DelegatorAddr: delegatorAddr,
CandidateAddr: candidate.Address, CandidateAddr: candidate.Address,
Shares: sdk.ZeroRat, Shares: sdk.ZeroRat(),
} }
} }
@ -194,7 +194,7 @@ func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result {
if !found { if !found {
return ErrNoDelegatorForAddress(k.codespace).Result() return ErrNoDelegatorForAddress(k.codespace).Result()
} }
if !bond.Shares.GT(sdk.ZeroRat) { // bond shares < msg shares if !bond.Shares.GT(sdk.ZeroRat()) { // bond shares < msg shares
return ErrInsufficientFunds(k.codespace).Result() return ErrInsufficientFunds(k.codespace).Result()
} }
@ -202,7 +202,7 @@ func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result {
// test that there are enough shares to unbond // test that there are enough shares to unbond
if msg.Shares == "MAX" { if msg.Shares == "MAX" {
if !bond.Shares.GT(sdk.ZeroRat) { if !bond.Shares.GT(sdk.ZeroRat()) {
return ErrNotEnoughBondShares(k.codespace, msg.Shares).Result() return ErrNotEnoughBondShares(k.codespace, msg.Shares).Result()
} }
} else { } else {

View File

@ -16,7 +16,7 @@ type Keeper struct {
coinKeeper bank.Keeper coinKeeper bank.Keeper
// caches // caches
gs Pool pool Pool
params Params params Params
// codespace // codespace
@ -41,7 +41,7 @@ func (k Keeper) getCounter(ctx sdk.Context) int16 {
return 0 return 0
} }
var counter int16 var counter int16
err := k.cdc.UnmarshalBinary(b, &counter) err := k.cdc.UnmarshalJSON(b, &counter)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -51,7 +51,7 @@ func (k Keeper) getCounter(ctx sdk.Context) int16 {
// set the current in-block validator operation counter // set the current in-block validator operation counter
func (k Keeper) setCounter(ctx sdk.Context, counter int16) { func (k Keeper) setCounter(ctx sdk.Context, counter int16) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz, err := k.cdc.MarshalBinary(counter) bz, err := k.cdc.MarshalJSON(counter)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -67,7 +67,7 @@ func (k Keeper) GetCandidate(ctx sdk.Context, addr sdk.Address) (candidate Candi
if b == nil { if b == nil {
return candidate, false return candidate, false
} }
err := k.cdc.UnmarshalBinary(b, &candidate) err := k.cdc.UnmarshalJSON(b, &candidate)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -88,7 +88,7 @@ func (k Keeper) GetCandidates(ctx sdk.Context, maxRetrieve int16) (candidates Ca
} }
bz := iterator.Value() bz := iterator.Value()
var candidate Candidate var candidate Candidate
err := k.cdc.UnmarshalBinary(bz, &candidate) err := k.cdc.UnmarshalJSON(bz, &candidate)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -112,7 +112,7 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) {
} }
// marshal the candidate record and add to the state // marshal the candidate record and add to the state
bz, err := k.cdc.MarshalBinary(candidate) bz, err := k.cdc.MarshalJSON(candidate)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -145,7 +145,7 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) {
} }
// update the candidate record // update the candidate record
bz, err = k.cdc.MarshalBinary(candidate) bz, err = k.cdc.MarshalJSON(candidate)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -153,7 +153,7 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) {
// marshal the new validator record // marshal the new validator record
validator := candidate.validator() validator := candidate.validator()
bz, err = k.cdc.MarshalBinary(validator) bz, err = k.cdc.MarshalJSON(validator)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -171,7 +171,7 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) {
setAcc = true setAcc = true
} }
if setAcc { if setAcc {
bz, err = k.cdc.MarshalBinary(validator.abciValidator(k.cdc)) bz, err = k.cdc.MarshalJSON(validator.abciValidator(k.cdc))
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -200,7 +200,7 @@ func (k Keeper) removeCandidate(ctx sdk.Context, address sdk.Address) {
if store.Get(GetRecentValidatorKey(address)) == nil { if store.Get(GetRecentValidatorKey(address)) == nil {
return return
} }
bz, err := k.cdc.MarshalBinary(candidate.validator().abciValidatorZero(k.cdc)) bz, err := k.cdc.MarshalJSON(candidate.validator().abciValidatorZero(k.cdc))
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -242,7 +242,7 @@ func (k Keeper) GetValidators(ctx sdk.Context) (validators []Validator) {
} }
bz := iterator.Value() bz := iterator.Value()
var validator Validator var validator Validator
err := k.cdc.UnmarshalBinary(bz, &validator) err := k.cdc.UnmarshalJSON(bz, &validator)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -266,11 +266,11 @@ func (k Keeper) GetValidators(ctx sdk.Context) (validators []Validator) {
// get the zero abci validator from the ToKickOut iterator value // get the zero abci validator from the ToKickOut iterator value
bz := iterator.Value() bz := iterator.Value()
var validator Validator var validator Validator
err := k.cdc.UnmarshalBinary(bz, &validator) err := k.cdc.UnmarshalJSON(bz, &validator)
if err != nil { if err != nil {
panic(err) panic(err)
} }
bz, err = k.cdc.MarshalBinary(validator.abciValidatorZero(k.cdc)) bz, err = k.cdc.MarshalJSON(validator.abciValidatorZero(k.cdc))
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -297,7 +297,7 @@ func (k Keeper) isNewValidator(ctx sdk.Context, store sdk.KVStore, address sdk.A
} }
bz := iterator.Value() bz := iterator.Value()
var val Validator var val Validator
err := k.cdc.UnmarshalBinary(bz, &val) err := k.cdc.UnmarshalJSON(bz, &val)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -330,7 +330,7 @@ func (k Keeper) getAccUpdateValidators(ctx sdk.Context) (updates []abci.Validato
for ; iterator.Valid(); iterator.Next() { for ; iterator.Valid(); iterator.Next() {
valBytes := iterator.Value() valBytes := iterator.Value()
var val abci.Validator var val abci.Validator
err := k.cdc.UnmarshalBinary(valBytes, &val) err := k.cdc.UnmarshalJSON(valBytes, &val)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -364,7 +364,7 @@ func (k Keeper) GetDelegatorBond(ctx sdk.Context,
return bond, false return bond, false
} }
err := k.cdc.UnmarshalBinary(delegatorBytes, &bond) err := k.cdc.UnmarshalJSON(delegatorBytes, &bond)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -385,7 +385,7 @@ func (k Keeper) getBonds(ctx sdk.Context, maxRetrieve int16) (bonds []DelegatorB
} }
bondBytes := iterator.Value() bondBytes := iterator.Value()
var bond DelegatorBond var bond DelegatorBond
err := k.cdc.UnmarshalBinary(bondBytes, &bond) err := k.cdc.UnmarshalJSON(bondBytes, &bond)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -410,7 +410,7 @@ func (k Keeper) GetDelegatorBonds(ctx sdk.Context, delegator sdk.Address, maxRet
} }
bondBytes := iterator.Value() bondBytes := iterator.Value()
var bond DelegatorBond var bond DelegatorBond
err := k.cdc.UnmarshalBinary(bondBytes, &bond) err := k.cdc.UnmarshalJSON(bondBytes, &bond)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -422,7 +422,7 @@ func (k Keeper) GetDelegatorBonds(ctx sdk.Context, delegator sdk.Address, maxRet
func (k Keeper) setDelegatorBond(ctx sdk.Context, bond DelegatorBond) { func (k Keeper) setDelegatorBond(ctx sdk.Context, bond DelegatorBond) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
b, err := k.cdc.MarshalBinary(bond) b, err := k.cdc.MarshalJSON(bond)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -439,7 +439,7 @@ func (k Keeper) removeDelegatorBond(ctx sdk.Context, bond DelegatorBond) {
// load/save the global staking params // load/save the global staking params
func (k Keeper) GetParams(ctx sdk.Context) (params Params) { func (k Keeper) GetParams(ctx sdk.Context) (params Params) {
// check if cached before anything // check if cached before anything
if k.params != (Params{}) { if !k.params.equal(Params{}) {
return k.params return k.params
} }
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
@ -448,7 +448,7 @@ func (k Keeper) GetParams(ctx sdk.Context) (params Params) {
panic("Stored params should not have been nil") panic("Stored params should not have been nil")
} }
err := k.cdc.UnmarshalBinary(b, &params) err := k.cdc.UnmarshalJSON(b, &params)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -456,7 +456,7 @@ func (k Keeper) GetParams(ctx sdk.Context) (params Params) {
} }
func (k Keeper) setParams(ctx sdk.Context, params Params) { func (k Keeper) setParams(ctx sdk.Context, params Params) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
b, err := k.cdc.MarshalBinary(params) b, err := k.cdc.MarshalJSON(params)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -467,17 +467,17 @@ func (k Keeper) setParams(ctx sdk.Context, params Params) {
//_______________________________________________________________________ //_______________________________________________________________________
// load/save the pool // load/save the pool
func (k Keeper) GetPool(ctx sdk.Context) (gs Pool) { func (k Keeper) GetPool(ctx sdk.Context) (pool Pool) {
// check if cached before anything // check if cached before anything
if k.gs != (Pool{}) { if !k.pool.equal(Pool{}) {
return k.gs return k.pool
} }
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
b := store.Get(PoolKey) b := store.Get(PoolKey)
if b == nil { if b == nil {
panic("Stored pool should not have been nil") panic("Stored pool should not have been nil")
} }
err := k.cdc.UnmarshalBinary(b, &gs) err := k.cdc.UnmarshalJSON(b, &pool)
if err != nil { if err != nil {
panic(err) // This error should never occur big problem if does panic(err) // This error should never occur big problem if does
} }
@ -486,10 +486,10 @@ func (k Keeper) GetPool(ctx sdk.Context) (gs Pool) {
func (k Keeper) setPool(ctx sdk.Context, p Pool) { func (k Keeper) setPool(ctx sdk.Context, p Pool) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
b, err := k.cdc.MarshalBinary(p) b, err := k.cdc.MarshalJSON(p)
if err != nil { if err != nil {
panic(err) panic(err)
} }
store.Set(PoolKey, b) store.Set(PoolKey, b)
k.gs = Pool{} // clear the cache k.pool = Pool{} //clear the cache
} }

View File

@ -1,7 +1,6 @@
package stake package stake
import ( import (
"bytes"
"testing" "testing"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
@ -40,15 +39,6 @@ func TestCandidate(t *testing.T) {
} }
} }
candidatesEqual := func(c1, c2 Candidate) bool {
return c1.Status == c2.Status &&
c1.PubKey.Equals(c2.PubKey) &&
bytes.Equal(c1.Address, c2.Address) &&
c1.Assets.Equal(c2.Assets) &&
c1.Liabilities.Equal(c2.Liabilities) &&
c1.Description == c2.Description
}
// check the empty keeper first // check the empty keeper first
_, found := keeper.GetCandidate(ctx, addrVals[0]) _, found := keeper.GetCandidate(ctx, addrVals[0])
assert.False(t, found) assert.False(t, found)
@ -119,13 +109,6 @@ func TestBond(t *testing.T) {
Shares: sdk.NewRat(9), Shares: sdk.NewRat(9),
} }
bondsEqual := func(b1, b2 DelegatorBond) bool {
return bytes.Equal(b1.DelegatorAddr, b2.DelegatorAddr) &&
bytes.Equal(b1.CandidateAddr, b2.CandidateAddr) &&
b1.Height == b2.Height &&
b1.Shares == b2.Shares
}
// check the empty keeper first // check the empty keeper first
_, found := keeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0]) _, found := keeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0])
assert.False(t, found) assert.False(t, found)
@ -460,8 +443,8 @@ func TestGetAccUpdateValidators(t *testing.T) {
require.Equal(t, 2, len(candidates)) require.Equal(t, 2, len(candidates))
assert.Equal(t, candidates[0].validator().abciValidator(keeper.cdc), acc[0]) assert.Equal(t, candidates[0].validator().abciValidator(keeper.cdc), acc[0])
assert.Equal(t, candidates[1].validator().abciValidator(keeper.cdc), acc[1]) assert.Equal(t, candidates[1].validator().abciValidator(keeper.cdc), acc[1])
assert.Equal(t, candidates[0].validator(), vals[1]) assert.True(t, validatorsEqual(candidates[0].validator(), vals[1]))
assert.Equal(t, candidates[1].validator(), vals[0]) assert.True(t, validatorsEqual(candidates[1].validator(), vals[0]))
// test identical, // test identical,
// candidate set: {c1, c3} -> {c1, c3} // candidate set: {c1, c3} -> {c1, c3}
@ -654,10 +637,10 @@ func TestIsRecentValidator(t *testing.T) {
keeper.setCandidate(ctx, candidatesIn[1]) keeper.setCandidate(ctx, candidatesIn[1])
validators = keeper.GetValidators(ctx) validators = keeper.GetValidators(ctx)
require.Equal(t, 2, len(validators)) require.Equal(t, 2, len(validators))
assert.Equal(t, candidatesIn[0].validator(), validators[0]) assert.True(t, validatorsEqual(candidatesIn[0].validator(), validators[0]))
c1ValWithCounter := candidatesIn[1].validator() c1ValWithCounter := candidatesIn[1].validator()
c1ValWithCounter.Counter = int16(1) c1ValWithCounter.Counter = int16(1)
assert.Equal(t, c1ValWithCounter, validators[1]) assert.True(t, validatorsEqual(c1ValWithCounter, validators[1]))
// test a basic retrieve of something that should be a recent validator // test a basic retrieve of something that should be a recent validator
assert.True(t, keeper.IsRecentValidator(ctx, candidatesIn[0].Address)) assert.True(t, keeper.IsRecentValidator(ctx, candidatesIn[0].Address))

View File

@ -204,7 +204,7 @@ func (msg MsgUnbond) ValidateBasic() sdk.Error {
if err != nil { if err != nil {
return ErrBadShares(DefaultCodespace) return ErrBadShares(DefaultCodespace)
} }
if rat.IsZero() || rat.LT(sdk.ZeroRat) { if rat.IsZero() || rat.LT(sdk.ZeroRat()) {
return ErrBadShares(DefaultCodespace) return ErrBadShares(DefaultCodespace)
} }
} }

View File

@ -9,13 +9,13 @@ func (p Pool) bondedRatio() sdk.Rat {
if p.TotalSupply > 0 { if p.TotalSupply > 0 {
return sdk.NewRat(p.BondedPool, p.TotalSupply) return sdk.NewRat(p.BondedPool, p.TotalSupply)
} }
return sdk.ZeroRat return sdk.ZeroRat()
} }
// get the exchange rate of bonded token per issued share // get the exchange rate of bonded token per issued share
func (p Pool) bondedShareExRate() sdk.Rat { func (p Pool) bondedShareExRate() sdk.Rat {
if p.BondedShares.IsZero() { if p.BondedShares.IsZero() {
return sdk.OneRat return sdk.OneRat()
} }
return sdk.NewRat(p.BondedPool).Quo(p.BondedShares) return sdk.NewRat(p.BondedPool).Quo(p.BondedShares)
} }
@ -23,7 +23,7 @@ func (p Pool) bondedShareExRate() sdk.Rat {
// get the exchange rate of unbonded tokens held in candidates per issued share // get the exchange rate of unbonded tokens held in candidates per issued share
func (p Pool) unbondedShareExRate() sdk.Rat { func (p Pool) unbondedShareExRate() sdk.Rat {
if p.UnbondedShares.IsZero() { if p.UnbondedShares.IsZero() {
return sdk.OneRat return sdk.OneRat()
} }
return sdk.NewRat(p.UnbondedPool).Quo(p.UnbondedShares) return sdk.NewRat(p.UnbondedPool).Quo(p.UnbondedShares)
} }
@ -51,7 +51,7 @@ func (p Pool) unbondedToBondedPool(candidate Candidate) (Pool, Candidate) {
//_______________________________________________________________________ //_______________________________________________________________________
func (p Pool) addTokensBonded(amount int64) (p2 Pool, issuedShares sdk.Rat) { func (p Pool) addTokensBonded(amount int64) (p2 Pool, issuedShares sdk.Rat) {
issuedShares = sdk.NewRat(amount).Quo(p.bondedShareExRate()) // (tokens/shares)^-1 * tokens issuedShares = sdk.NewRat(amount).Quo(p.bondedShareExRate()) // tokens * (shares/tokens)
p.BondedPool += amount p.BondedPool += amount
p.BondedShares = p.BondedShares.Add(issuedShares) p.BondedShares = p.BondedShares.Add(issuedShares)
return p, issuedShares return p, issuedShares
@ -65,7 +65,7 @@ func (p Pool) removeSharesBonded(shares sdk.Rat) (p2 Pool, removedTokens int64)
} }
func (p Pool) addTokensUnbonded(amount int64) (p2 Pool, issuedShares sdk.Rat) { func (p Pool) addTokensUnbonded(amount int64) (p2 Pool, issuedShares sdk.Rat) {
issuedShares = p.unbondedShareExRate().Inv().Mul(sdk.NewRat(amount)) // (tokens/shares)^-1 * tokens issuedShares = sdk.NewRat(amount).Quo(p.unbondedShareExRate()) // tokens * (shares/tokens)
p.UnbondedShares = p.UnbondedShares.Add(issuedShares) p.UnbondedShares = p.UnbondedShares.Add(issuedShares)
p.UnbondedPool += amount p.UnbondedPool += amount
return p, issuedShares return p, issuedShares

View File

@ -22,7 +22,7 @@ func TestBondedRatio(t *testing.T) {
pool.TotalSupply = 0 pool.TotalSupply = 0
// avoids divide-by-zero // avoids divide-by-zero
require.Equal(t, pool.bondedRatio(), sdk.ZeroRat) require.Equal(t, pool.bondedRatio(), sdk.ZeroRat())
} }
func TestBondedShareExRate(t *testing.T) { func TestBondedShareExRate(t *testing.T) {
@ -33,10 +33,10 @@ func TestBondedShareExRate(t *testing.T) {
// bonded pool / bonded shares // bonded pool / bonded shares
require.Equal(t, pool.bondedShareExRate(), sdk.NewRat(3).Quo(sdk.NewRat(10))) require.Equal(t, pool.bondedShareExRate(), sdk.NewRat(3).Quo(sdk.NewRat(10)))
pool.BondedShares = sdk.ZeroRat pool.BondedShares = sdk.ZeroRat()
// avoids divide-by-zero // avoids divide-by-zero
require.Equal(t, pool.bondedShareExRate(), sdk.OneRat) require.Equal(t, pool.bondedShareExRate(), sdk.OneRat())
} }
func TestUnbondedShareExRate(t *testing.T) { func TestUnbondedShareExRate(t *testing.T) {
@ -47,24 +47,24 @@ func TestUnbondedShareExRate(t *testing.T) {
// unbonded pool / unbonded shares // unbonded pool / unbonded shares
require.Equal(t, pool.unbondedShareExRate(), sdk.NewRat(3).Quo(sdk.NewRat(10))) require.Equal(t, pool.unbondedShareExRate(), sdk.NewRat(3).Quo(sdk.NewRat(10)))
pool.UnbondedShares = sdk.ZeroRat pool.UnbondedShares = sdk.ZeroRat()
// avoids divide-by-zero // avoids divide-by-zero
require.Equal(t, pool.unbondedShareExRate(), sdk.OneRat) require.Equal(t, pool.unbondedShareExRate(), sdk.OneRat())
} }
func TestBondedToUnbondedPool(t *testing.T) { func TestBondedToUnbondedPool(t *testing.T) {
ctx, _, keeper := createTestInput(t, false, 0) ctx, _, keeper := createTestInput(t, false, 0)
poolA := keeper.GetPool(ctx) poolA := keeper.GetPool(ctx)
assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat) assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat())
assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat) assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat())
candA := Candidate{ candA := Candidate{
Status: Bonded, Status: Bonded,
Address: addrs[0], Address: addrs[0],
PubKey: pks[0], PubKey: pks[0],
Assets: sdk.OneRat, Assets: sdk.OneRat(),
Liabilities: sdk.OneRat, Liabilities: sdk.OneRat(),
} }
poolB, candB := poolA.bondedToUnbondedPool(candA) poolB, candB := poolA.bondedToUnbondedPool(candA)
@ -84,14 +84,14 @@ func TestUnbonbedtoBondedPool(t *testing.T) {
ctx, _, keeper := createTestInput(t, false, 0) ctx, _, keeper := createTestInput(t, false, 0)
poolA := keeper.GetPool(ctx) poolA := keeper.GetPool(ctx)
assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat) assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat())
assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat) assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat())
candA := Candidate{ candA := Candidate{
Status: Bonded, Status: Bonded,
Address: addrs[0], Address: addrs[0],
PubKey: pks[0], PubKey: pks[0],
Assets: sdk.OneRat, Assets: sdk.OneRat(),
Liabilities: sdk.OneRat, Liabilities: sdk.OneRat(),
} }
candA.Status = Unbonded candA.Status = Unbonded
poolB, candB := poolA.unbondedToBondedPool(candA) poolB, candB := poolA.unbondedToBondedPool(candA)
@ -112,65 +112,64 @@ func TestAddTokensBonded(t *testing.T) {
ctx, _, keeper := createTestInput(t, false, 0) ctx, _, keeper := createTestInput(t, false, 0)
poolA := keeper.GetPool(ctx) poolA := keeper.GetPool(ctx)
assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat) assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat())
poolB, sharesB := poolA.addTokensBonded(10) poolB, sharesB := poolA.addTokensBonded(10)
assert.Equal(t, poolB.bondedShareExRate(), sdk.OneRat) assert.Equal(t, poolB.bondedShareExRate(), sdk.OneRat())
// correct changes to bonded shares and bonded pool // correct changes to bonded shares and bonded pool
assert.Equal(t, poolB.BondedShares, poolA.BondedShares.Add(sharesB)) assert.Equal(t, poolB.BondedShares, poolA.BondedShares.Add(sharesB))
assert.Equal(t, poolB.BondedPool, poolA.BondedPool+10) assert.Equal(t, poolB.BondedPool, poolA.BondedPool+10)
// same number of bonded shares / tokens when exchange rate is one // same number of bonded shares / tokens when exchange rate is one
assert.Equal(t, poolB.BondedShares, sdk.NewRat(poolB.BondedPool)) assert.True(t, poolB.BondedShares.Equal(sdk.NewRat(poolB.BondedPool)))
} }
func TestRemoveSharesBonded(t *testing.T) { func TestRemoveSharesBonded(t *testing.T) {
ctx, _, keeper := createTestInput(t, false, 0) ctx, _, keeper := createTestInput(t, false, 0)
poolA := keeper.GetPool(ctx) poolA := keeper.GetPool(ctx)
assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat) assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat())
poolB, tokensB := poolA.removeSharesBonded(sdk.NewRat(10)) poolB, tokensB := poolA.removeSharesBonded(sdk.NewRat(10))
assert.Equal(t, poolB.bondedShareExRate(), sdk.OneRat) assert.Equal(t, poolB.bondedShareExRate(), sdk.OneRat())
// correct changes to bonded shares and bonded pool // correct changes to bonded shares and bonded pool
assert.Equal(t, poolB.BondedShares, poolA.BondedShares.Sub(sdk.NewRat(10))) assert.Equal(t, poolB.BondedShares, poolA.BondedShares.Sub(sdk.NewRat(10)))
assert.Equal(t, poolB.BondedPool, poolA.BondedPool-tokensB) assert.Equal(t, poolB.BondedPool, poolA.BondedPool-tokensB)
// same number of bonded shares / tokens when exchange rate is one // same number of bonded shares / tokens when exchange rate is one
assert.Equal(t, poolB.BondedShares, sdk.NewRat(poolB.BondedPool)) assert.True(t, poolB.BondedShares.Equal(sdk.NewRat(poolB.BondedPool)))
} }
func TestAddTokensUnbonded(t *testing.T) { func TestAddTokensUnbonded(t *testing.T) {
ctx, _, keeper := createTestInput(t, false, 0) ctx, _, keeper := createTestInput(t, false, 0)
poolA := keeper.GetPool(ctx) poolA := keeper.GetPool(ctx)
assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat) assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat())
poolB, sharesB := poolA.addTokensUnbonded(10) poolB, sharesB := poolA.addTokensUnbonded(10)
assert.Equal(t, poolB.unbondedShareExRate(), sdk.OneRat) assert.Equal(t, poolB.unbondedShareExRate(), sdk.OneRat())
// correct changes to unbonded shares and unbonded pool // correct changes to unbonded shares and unbonded pool
assert.Equal(t, poolB.UnbondedShares, poolA.UnbondedShares.Add(sharesB)) assert.Equal(t, poolB.UnbondedShares, poolA.UnbondedShares.Add(sharesB))
assert.Equal(t, poolB.UnbondedPool, poolA.UnbondedPool+10) assert.Equal(t, poolB.UnbondedPool, poolA.UnbondedPool+10)
// same number of unbonded shares / tokens when exchange rate is one // same number of unbonded shares / tokens when exchange rate is one
assert.Equal(t, poolB.UnbondedShares, sdk.NewRat(poolB.UnbondedPool)) assert.True(t, poolB.UnbondedShares.Equal(sdk.NewRat(poolB.UnbondedPool)))
} }
func TestRemoveSharesUnbonded(t *testing.T) { func TestRemoveSharesUnbonded(t *testing.T) {
ctx, _, keeper := createTestInput(t, false, 0) ctx, _, keeper := createTestInput(t, false, 0)
poolA := keeper.GetPool(ctx) poolA := keeper.GetPool(ctx)
assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat) assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat())
poolB, tokensB := poolA.removeSharesUnbonded(sdk.NewRat(10)) poolB, tokensB := poolA.removeSharesUnbonded(sdk.NewRat(10))
assert.Equal(t, poolB.unbondedShareExRate(), sdk.OneRat) assert.Equal(t, poolB.unbondedShareExRate(), sdk.OneRat())
// correct changes to unbonded shares and bonded pool // correct changes to unbonded shares and bonded pool
assert.Equal(t, poolB.UnbondedShares, poolA.UnbondedShares.Sub(sdk.NewRat(10))) assert.Equal(t, poolB.UnbondedShares, poolA.UnbondedShares.Sub(sdk.NewRat(10)))
assert.Equal(t, poolB.UnbondedPool, poolA.UnbondedPool-tokensB) assert.Equal(t, poolB.UnbondedPool, poolA.UnbondedPool-tokensB)
// same number of unbonded shares / tokens when exchange rate is one // same number of unbonded shares / tokens when exchange rate is one
assert.Equal(t, poolB.UnbondedShares, sdk.NewRat(poolB.UnbondedPool)) assert.True(t, poolB.UnbondedShares.Equal(sdk.NewRat(poolB.UnbondedPool)))
} }
func TestCandidateAddTokens(t *testing.T) { func TestCandidateAddTokens(t *testing.T) {
@ -186,9 +185,9 @@ func TestCandidateAddTokens(t *testing.T) {
} }
poolA.BondedPool = candA.Assets.Evaluate() poolA.BondedPool = candA.Assets.Evaluate()
poolA.BondedShares = candA.Assets poolA.BondedShares = candA.Assets
assert.Equal(t, candA.delegatorShareExRate(), sdk.OneRat) assert.Equal(t, candA.delegatorShareExRate(), sdk.OneRat())
assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat) assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat())
assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat) assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat())
poolB, candB, sharesB := poolA.candidateAddTokens(candA, 10) poolB, candB, sharesB := poolA.candidateAddTokens(candA, 10)
// shares were issued // shares were issued
@ -212,9 +211,9 @@ func TestCandidateRemoveShares(t *testing.T) {
} }
poolA.BondedPool = candA.Assets.Evaluate() poolA.BondedPool = candA.Assets.Evaluate()
poolA.BondedShares = candA.Assets poolA.BondedShares = candA.Assets
assert.Equal(t, candA.delegatorShareExRate(), sdk.OneRat) assert.Equal(t, candA.delegatorShareExRate(), sdk.OneRat())
assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat) assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat())
assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat) assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat())
poolB, candB, coinsB := poolA.candidateRemoveShares(candA, sdk.NewRat(10)) poolB, candB, coinsB := poolA.candidateRemoveShares(candA, sdk.NewRat(10))
// coins were created // coins were created
@ -280,8 +279,8 @@ func randomCandidate(r *rand.Rand) Candidate {
func randomSetup(r *rand.Rand, numCandidates int) (Pool, Candidates) { func randomSetup(r *rand.Rand, numCandidates int) (Pool, Candidates) {
pool := Pool{ pool := Pool{
TotalSupply: 0, TotalSupply: 0,
BondedShares: sdk.ZeroRat, BondedShares: sdk.ZeroRat(),
UnbondedShares: sdk.ZeroRat, UnbondedShares: sdk.ZeroRat(),
BondedPool: 0, BondedPool: 0,
UnbondedPool: 0, UnbondedPool: 0,
InflationLastTime: 0, InflationLastTime: 0,
@ -380,29 +379,29 @@ func assertInvariants(t *testing.T, msg string,
pMod.UnbondedPool, pMod.BondedPool, tokens) pMod.UnbondedPool, pMod.BondedPool, tokens)
// nonnegative bonded shares // nonnegative bonded shares
require.False(t, pMod.BondedShares.LT(sdk.ZeroRat), require.False(t, pMod.BondedShares.LT(sdk.ZeroRat()),
"Negative bonded shares - msg: %v\npOrig: %#v\npMod: %#v\ntokens: %v\n", "Negative bonded shares - msg: %v\npOrig: %#v\npMod: %#v\ntokens: %v\n",
msg, pOrig, pMod, tokens) msg, pOrig, pMod, tokens)
// nonnegative unbonded shares // nonnegative unbonded shares
require.False(t, pMod.UnbondedShares.LT(sdk.ZeroRat), require.False(t, pMod.UnbondedShares.LT(sdk.ZeroRat()),
"Negative unbonded shares - msg: %v\npOrig: %#v\npMod: %#v\ntokens: %v\n", "Negative unbonded shares - msg: %v\npOrig: %#v\npMod: %#v\ntokens: %v\n",
msg, pOrig, pMod, tokens) msg, pOrig, pMod, tokens)
// nonnegative bonded ex rate // nonnegative bonded ex rate
require.False(t, pMod.bondedShareExRate().LT(sdk.ZeroRat), require.False(t, pMod.bondedShareExRate().LT(sdk.ZeroRat()),
"Applying operation \"%s\" resulted in negative bondedShareExRate: %d", "Applying operation \"%s\" resulted in negative bondedShareExRate: %d",
msg, pMod.bondedShareExRate().Evaluate()) msg, pMod.bondedShareExRate().Evaluate())
// nonnegative unbonded ex rate // nonnegative unbonded ex rate
require.False(t, pMod.unbondedShareExRate().LT(sdk.ZeroRat), require.False(t, pMod.unbondedShareExRate().LT(sdk.ZeroRat()),
"Applying operation \"%s\" resulted in negative unbondedShareExRate: %d", "Applying operation \"%s\" resulted in negative unbondedShareExRate: %d",
msg, pMod.unbondedShareExRate().Evaluate()) msg, pMod.unbondedShareExRate().Evaluate())
for _, cMod := range cMods { for _, cMod := range cMods {
// nonnegative ex rate // nonnegative ex rate
require.False(t, cMod.delegatorShareExRate().LT(sdk.ZeroRat), require.False(t, cMod.delegatorShareExRate().LT(sdk.ZeroRat()),
"Applying operation \"%s\" resulted in negative candidate.delegatorShareExRate(): %v (candidate.Address: %s)", "Applying operation \"%s\" resulted in negative candidate.delegatorShareExRate(): %v (candidate.Address: %s)",
msg, msg,
cMod.delegatorShareExRate(), cMod.delegatorShareExRate(),
@ -410,7 +409,7 @@ func assertInvariants(t *testing.T, msg string,
) )
// nonnegative assets // nonnegative assets
require.False(t, cMod.Assets.LT(sdk.ZeroRat), require.False(t, cMod.Assets.LT(sdk.ZeroRat()),
"Applying operation \"%s\" resulted in negative candidate.Assets: %v (candidate.Liabilities: %v, candidate.delegatorShareExRate: %v, candidate.Address: %s)", "Applying operation \"%s\" resulted in negative candidate.Assets: %v (candidate.Liabilities: %v, candidate.delegatorShareExRate: %v, candidate.Address: %s)",
msg, msg,
cMod.Assets, cMod.Assets,
@ -420,7 +419,7 @@ func assertInvariants(t *testing.T, msg string,
) )
// nonnegative liabilities // nonnegative liabilities
require.False(t, cMod.Liabilities.LT(sdk.ZeroRat), require.False(t, cMod.Liabilities.LT(sdk.ZeroRat()),
"Applying operation \"%s\" resulted in negative candidate.Liabilities: %v (candidate.Assets: %v, candidate.delegatorShareExRate: %v, candidate.Address: %s)", "Applying operation \"%s\" resulted in negative candidate.Liabilities: %v (candidate.Assets: %v, candidate.delegatorShareExRate: %v, candidate.Address: %s)",
msg, msg,
cMod.Liabilities, cMod.Liabilities,
@ -449,7 +448,7 @@ func TestPossibleOverflow(t *testing.T) {
pool := Pool{ pool := Pool{
TotalSupply: 0, TotalSupply: 0,
BondedShares: assets, BondedShares: assets,
UnbondedShares: sdk.ZeroRat, UnbondedShares: sdk.ZeroRat(),
BondedPool: assets.Evaluate(), BondedPool: assets.Evaluate(),
UnbondedPool: 0, UnbondedPool: 0,
InflationLastTime: 0, InflationLastTime: 0,
@ -461,7 +460,7 @@ func TestPossibleOverflow(t *testing.T) {
_, newCandidate, _ := pool.candidateAddTokens(cand, tokens) _, newCandidate, _ := pool.candidateAddTokens(cand, tokens)
msg = fmt.Sprintf("Added %d tokens to %s", tokens, msg) msg = fmt.Sprintf("Added %d tokens to %s", tokens, msg)
require.False(t, newCandidate.delegatorShareExRate().LT(sdk.ZeroRat), require.False(t, newCandidate.delegatorShareExRate().LT(sdk.ZeroRat()),
"Applying operation \"%s\" resulted in negative delegatorShareExRate(): %v", "Applying operation \"%s\" resulted in negative delegatorShareExRate(): %v",
msg, newCandidate.delegatorShareExRate()) msg, newCandidate.delegatorShareExRate())
} }

View File

@ -1,6 +1,7 @@
package stake package stake
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"testing" "testing"
@ -50,6 +51,30 @@ var (
emptyPubkey crypto.PubKey emptyPubkey crypto.PubKey
) )
func validatorsEqual(b1, b2 Validator) bool {
return bytes.Equal(b1.Address, b2.Address) &&
b1.PubKey.Equals(b2.PubKey) &&
b1.Power.Equal(b2.Power) &&
b1.Height == b2.Height &&
b1.Counter == b2.Counter
}
func candidatesEqual(c1, c2 Candidate) bool {
return c1.Status == c2.Status &&
c1.PubKey.Equals(c2.PubKey) &&
bytes.Equal(c1.Address, c2.Address) &&
c1.Assets.Equal(c2.Assets) &&
c1.Liabilities.Equal(c2.Liabilities) &&
c1.Description == c2.Description
}
func bondsEqual(b1, b2 DelegatorBond) bool {
return bytes.Equal(b1.DelegatorAddr, b2.DelegatorAddr) &&
bytes.Equal(b1.CandidateAddr, b2.CandidateAddr) &&
b1.Height == b2.Height &&
b1.Shares.Equal(b2.Shares)
}
// default params for testing // default params for testing
func defaultParams() Params { func defaultParams() Params {
return Params{ return Params{
@ -66,8 +91,8 @@ func defaultParams() Params {
func initialPool() Pool { func initialPool() Pool {
return Pool{ return Pool{
TotalSupply: 0, TotalSupply: 0,
BondedShares: sdk.ZeroRat, BondedShares: sdk.ZeroRat(),
UnbondedShares: sdk.ZeroRat, UnbondedShares: sdk.ZeroRat(),
BondedPool: 0, BondedPool: 0,
UnbondedPool: 0, UnbondedPool: 0,
InflationLastTime: 0, InflationLastTime: 0,
@ -112,9 +137,9 @@ func makeTestCodec() *wire.Codec {
func paramsNoInflation() Params { func paramsNoInflation() Params {
return Params{ return Params{
InflationRateChange: sdk.ZeroRat, InflationRateChange: sdk.ZeroRat(),
InflationMax: sdk.ZeroRat, InflationMax: sdk.ZeroRat(),
InflationMin: sdk.ZeroRat, InflationMin: sdk.ZeroRat(),
GoalBonded: sdk.NewRat(67, 100), GoalBonded: sdk.NewRat(67, 100),
MaxValidators: 100, MaxValidators: 100,
BondDenom: "fermion", BondDenom: "fermion",

View File

@ -62,7 +62,7 @@ func (k Keeper) nextInflation(ctx sdk.Context) (inflation sdk.Rat) {
// 7% and 20%. // 7% and 20%.
// (1 - bondedRatio/GoalBonded) * InflationRateChange // (1 - bondedRatio/GoalBonded) * InflationRateChange
inflationRateChangePerYear := sdk.OneRat.Sub(pool.bondedRatio().Quo(params.GoalBonded)).Mul(params.InflationRateChange) inflationRateChangePerYear := sdk.OneRat().Sub(pool.bondedRatio().Quo(params.GoalBonded)).Mul(params.InflationRateChange)
inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrRat) inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrRat)
// increase the new annual inflation for this next cycle // increase the new annual inflation for this next cycle

View File

@ -29,22 +29,22 @@ func TestGetInflation(t *testing.T) {
// 100% bonded, starting at 20% inflation and being reduced // 100% bonded, starting at 20% inflation and being reduced
// (1 - (1/0.67))*(0.13/8667) // (1 - (1/0.67))*(0.13/8667)
{"test 2", 1, 1, sdk.NewRat(20, 100), {"test 2", 1, 1, sdk.NewRat(20, 100),
sdk.OneRat.Sub(sdk.OneRat.Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)}, sdk.OneRat().Sub(sdk.OneRat().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)},
// 50% bonded, starting at 10% inflation and being increased // 50% bonded, starting at 10% inflation and being increased
{"test 3", 1, 2, sdk.NewRat(10, 100), {"test 3", 1, 2, sdk.NewRat(10, 100),
sdk.OneRat.Sub(sdk.NewRat(1, 2).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)}, sdk.OneRat().Sub(sdk.NewRat(1, 2).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)},
// test 7% minimum stop (testing with 100% bonded) // test 7% minimum stop (testing with 100% bonded)
{"test 4", 1, 1, sdk.NewRat(7, 100), sdk.ZeroRat}, {"test 4", 1, 1, sdk.NewRat(7, 100), sdk.ZeroRat()},
{"test 5", 1, 1, sdk.NewRat(70001, 1000000), sdk.NewRat(-1, 1000000).Round(precision)}, {"test 5", 1, 1, sdk.NewRat(70001, 1000000), sdk.NewRat(-1, 1000000).Round(precision)},
// test 20% maximum stop (testing with 0% bonded) // test 20% maximum stop (testing with 0% bonded)
{"test 6", 0, 0, sdk.NewRat(20, 100), sdk.ZeroRat}, {"test 6", 0, 0, sdk.NewRat(20, 100), sdk.ZeroRat()},
{"test 7", 0, 0, sdk.NewRat(199999, 1000000), sdk.NewRat(1, 1000000).Round(precision)}, {"test 7", 0, 0, sdk.NewRat(199999, 1000000), sdk.NewRat(1, 1000000).Round(precision)},
// perfect balance shouldn't change inflation // perfect balance shouldn't change inflation
{"test 8", 67, 100, sdk.NewRat(15, 100), sdk.ZeroRat}, {"test 8", 67, 100, sdk.NewRat(15, 100), sdk.ZeroRat()},
} }
for _, tc := range tests { for _, tc := range tests {
pool.BondedPool, pool.TotalSupply = tc.setBondedPool, tc.setTotalSupply pool.BondedPool, pool.TotalSupply = tc.setBondedPool, tc.setTotalSupply
@ -97,7 +97,7 @@ func TestProcessProvisions(t *testing.T) {
assert.True(t, pool.bondedRatio().Equal(sdk.NewRat(bondedShares, totalSupply)), "%v", pool.bondedRatio()) assert.True(t, pool.bondedRatio().Equal(sdk.NewRat(bondedShares, totalSupply)), "%v", pool.bondedRatio())
// test the value of candidate shares // test the value of candidate shares
assert.True(t, pool.bondedShareExRate().Equal(sdk.OneRat), "%v", pool.bondedShareExRate()) assert.True(t, pool.bondedShareExRate().Equal(sdk.OneRat()), "%v", pool.bondedShareExRate())
initialSupply := pool.TotalSupply initialSupply := pool.TotalSupply
initialUnbonded := pool.TotalSupply - pool.BondedPool initialUnbonded := pool.TotalSupply - pool.BondedPool
@ -121,14 +121,13 @@ func TestProcessProvisions(t *testing.T) {
//panic(fmt.Sprintf("debug total %v, bonded %v, diff %v\n", p.TotalSupply, p.BondedPool, pool.TotalSupply-pool.BondedPool)) //panic(fmt.Sprintf("debug total %v, bonded %v, diff %v\n", p.TotalSupply, p.BondedPool, pool.TotalSupply-pool.BondedPool))
// initial bonded ratio ~ from 27% to 40% increase for bonded holders ownership of total supply // initial bonded ratio ~ from 27% to 40% increase for bonded holders ownership of total supply
assert.True(t, pool.bondedRatio().Equal(sdk.NewRat(271734723, 671734723)), "%v", pool.bondedRatio()) assert.True(t, pool.bondedRatio().Equal(sdk.NewRat(211813022, 611813022)), "%v", pool.bondedRatio())
// global supply // global supply
assert.Equal(t, int64(671734723), pool.TotalSupply) assert.Equal(t, int64(611813022), pool.TotalSupply)
assert.Equal(t, int64(271734723), pool.BondedPool) assert.Equal(t, int64(211813022), pool.BondedPool)
assert.Equal(t, unbondedShares, pool.UnbondedPool) assert.Equal(t, unbondedShares, pool.UnbondedPool)
// test the value of candidate shares // test the value of candidate shares
assert.True(t, pool.bondedShareExRate().Mul(sdk.NewRat(bondedShares)).Equal(sdk.NewRat(271734723)), "%v", pool.bondedShareExRate()) assert.True(t, pool.bondedShareExRate().Mul(sdk.NewRat(bondedShares)).Equal(sdk.NewRat(211813022)), "%v", pool.bondedShareExRate())
} }

View File

@ -28,6 +28,15 @@ type Params struct {
BondDenom string `json:"bond_denom"` // bondable coin denomination BondDenom string `json:"bond_denom"` // bondable coin denomination
} }
func (p Params) equal(p2 Params) bool {
return p.InflationRateChange.Equal(p2.InflationRateChange) &&
p.InflationMax.Equal(p2.InflationMax) &&
p.InflationMin.Equal(p2.InflationMin) &&
p.GoalBonded.Equal(p2.GoalBonded) &&
p.MaxValidators == p2.MaxValidators &&
p.BondDenom == p2.BondDenom
}
//_________________________________________________________________________ //_________________________________________________________________________
// Pool - dynamic parameters of the current state // Pool - dynamic parameters of the current state
@ -41,6 +50,16 @@ type Pool struct {
Inflation sdk.Rat `json:"inflation"` // current annual inflation rate Inflation sdk.Rat `json:"inflation"` // current annual inflation rate
} }
func (p Pool) equal(p2 Pool) bool {
return p.BondedShares.Equal(p2.BondedShares) &&
p.UnbondedShares.Equal(p2.UnbondedShares) &&
p.Inflation.Equal(p2.Inflation) &&
p.TotalSupply == p2.TotalSupply &&
p.BondedPool == p2.BondedPool &&
p.UnbondedPool == p2.UnbondedPool &&
p.InflationLastTime == p2.InflationLastTime
}
//_________________________________________________________________________ //_________________________________________________________________________
// CandidateStatus - status of a validator-candidate // CandidateStatus - status of a validator-candidate
@ -80,8 +99,8 @@ func NewCandidate(address sdk.Address, pubKey crypto.PubKey, description Descrip
Status: Unbonded, Status: Unbonded,
Address: address, Address: address,
PubKey: pubKey, PubKey: pubKey,
Assets: sdk.ZeroRat, Assets: sdk.ZeroRat(),
Liabilities: sdk.ZeroRat, Liabilities: sdk.ZeroRat(),
Description: description, Description: description,
ValidatorBondHeight: int64(0), ValidatorBondHeight: int64(0),
ValidatorBondCounter: int16(0), ValidatorBondCounter: int16(0),
@ -108,7 +127,7 @@ func NewDescription(moniker, identity, website, details string) Description {
// get the exchange rate of global pool shares over delegator shares // get the exchange rate of global pool shares over delegator shares
func (c Candidate) delegatorShareExRate() sdk.Rat { func (c Candidate) delegatorShareExRate() sdk.Rat {
if c.Liabilities.IsZero() { if c.Liabilities.IsZero() {
return sdk.OneRat return sdk.OneRat()
} }
return c.Assets.Quo(c.Liabilities) return c.Assets.Quo(c.Liabilities)
} }

View File

@ -1,7 +1,6 @@
package stake package stake
import ( import (
"bytes"
"testing" "testing"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
@ -37,13 +36,6 @@ func TestViewSlashBond(t *testing.T) {
viewSlashKeeper := NewViewSlashKeeper(keeper) viewSlashKeeper := NewViewSlashKeeper(keeper)
bondsEqual := func(b1, b2 DelegatorBond) bool {
return bytes.Equal(b1.DelegatorAddr, b2.DelegatorAddr) &&
bytes.Equal(b1.CandidateAddr, b2.CandidateAddr) &&
b1.Height == b2.Height &&
b1.Shares == b2.Shares
}
// check the empty keeper first // check the empty keeper first
_, found := viewSlashKeeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0]) _, found := viewSlashKeeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0])
assert.False(t, found) assert.False(t, found)