From ce321173990c1f12a12fbdd5327588ffbc8358c7 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 30 Apr 2018 17:21:14 -0400 Subject: [PATCH] rational embedes bigRat --- baseapp/baseapp.go | 2 - cmd/gaia/app/app.go | 4 +- types/rational.go | 147 ++++++++++-------------------- types/rational_test.go | 76 +++++++-------- x/stake/client/cli/tx.go | 2 +- x/stake/handler.go | 6 +- x/stake/keeper.go | 56 ++++++------ x/stake/keeper_test.go | 25 +---- x/stake/msg.go | 2 +- x/stake/pool.go | 10 +- x/stake/pool_test.go | 85 +++++++++-------- x/stake/test_common.go | 35 ++++++- x/stake/tick.go | 2 +- x/stake/tick_test.go | 21 ++--- x/stake/types.go | 25 ++++- x/stake/view_slash_keeper_test.go | 8 -- 16 files changed, 231 insertions(+), 275 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 84a18aa06..51e96ae20 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -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. func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) { if app.initChainer == nil { - // TODO: should we have some default handling of validators? 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 // starts from this deliverState - return } diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index a9cf248e1..5ff532bff 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -106,8 +106,8 @@ func MakeCodec() *wire.Codec { func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { stateJSON := req.AppStateBytes - genesisState := new(GenesisState) - err := app.cdc.UnmarshalJSON(stateJSON, genesisState) + var genesisState GenesisState + err := app.cdc.UnmarshalJSON(stateJSON, &genesisState) if err != nil { panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 // return sdk.ErrGenesisParse("").TraceCause(err, "") diff --git a/types/rational.go b/types/rational.go index 9199520b2..2276ab4f2 100644 --- a/types/rational.go +++ b/types/rational.go @@ -1,6 +1,7 @@ package types import ( + "bytes" "fmt" "math/big" "strconv" @@ -13,68 +14,24 @@ import ( // __ /___...._____ _\o // __| |_ |_ -// Rat - extend big.Rat // NOTE: never use new(Rat) or else // we will panic unmarshalling into the // nil embedded big.Rat type Rat struct { - Num int64 `json:"num"` - Denom int64 `json:"denom"` - //*big.Rat `json:"rat"` + 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 -var ( - ZeroRat = NewRat(0) // Rat{big.NewRat(0, 1)} - OneRat = NewRat(1) // Rat{big.NewRat(1, 1)} -) +func ZeroRat() Rat { return Rat{*big.NewRat(0, 1)} } +func OneRat() Rat { return Rat{*big.NewRat(1, 1)} } // New - create a new Rat from integers -//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) { +func NewRat(Numerator int64, Denominator ...int64) Rat { + switch len(Denominator) { case 0: - return Rat{ - Num: num, - Denom: 1, - } + return Rat{*big.NewRat(Numerator, 1)} case 1: - return Rat{ - Num: num, - Denom: denom[0], - } + return Rat{*big.NewRat(Numerator, Denominator[0])} default: panic("improper use of New, can only have one denominator") } @@ -124,30 +81,17 @@ func NewRatFromDecimal(decimalStr string) (f Rat, err Error) { } //nolint -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 +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.Rat)) == 0 } // Equal - rationals are equal +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.Rat)).Cmp(&(r2.Rat)) == -1 } // Equal - rationals are equal +func (r Rat) Mul(r2 Rat) Rat { return Rat{*new(big.Rat).Mul(&(r.Rat), &(r2.Rat))} } // Mul - multiplication +func (r Rat) Quo(r2 Rat) Rat { return Rat{*new(big.Rat).Quo(&(r.Rat), &(r2.Rat))} } // Quo - quotient +func (r Rat) Add(r2 Rat) Rat { return Rat{*new(big.Rat).Add(&(r.Rat), &(r2.Rat))} } // Add - addition +func (r Rat) Sub(r2 Rat) Rat { return Rat{*new(big.Rat).Sub(&(r.Rat), &(r2.Rat))} } // Sub - subtraction +func (r Rat) String() string { return fmt.Sprintf("%v/%v", r.Num(), r.Denom()) } // Sub - subtraction var ( zero = big.NewInt(0) @@ -161,8 +105,8 @@ var ( // evaluate the rational using bankers rounding func (r Rat) EvaluateBig() *big.Int { - num := r.GetRat().Num() - denom := r.GetRat().Denom() + num := r.Rat.Num() + denom := r.Rat.Denom() d, rem := new(big.Int), new(big.Int) d.QuoRem(num, denom, rem) @@ -195,8 +139,8 @@ func (r Rat) Evaluate() int64 { // round Rat with the provided precisionFactor func (r Rat) Round(precisionFactor int64) Rat { - rTen := ToRat(new(big.Rat).Mul(r.GetRat(), big.NewRat(precisionFactor, 1))) - return ToRat(big.NewRat(rTen.Evaluate(), precisionFactor)) + rTen := Rat{*new(big.Rat).Mul(&(r.Rat), big.NewRat(precisionFactor, 1))} + return Rat{*big.NewRat(rTen.Evaluate(), precisionFactor)} } // 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 // we update for amino //type JSONCodec struct{} +//nolint //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) MarshalAmino() (string, error) { -//bz, err := r.MarshalText() -//if err != nil { -//return "", err -//} -//return fmt.Sprintf(`%s`, bz), nil -//} +//Wraps r.MarshalText() in quotes to make it a valid JSON string. +func (r Rat) MarshalJSON() ([]byte, error) { + bz, err := (&(r.Rat)).MarshalText() + if err != nil { + return nil, err + } + return []byte(fmt.Sprintf("\"%s\"", bz)), nil +} -//// 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)) -//} +// 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, have %v", string(data)) + } + data = bytes.Trim(data, `"`) + tempRat := big.NewRat(0, 1) + err = tempRat.UnmarshalText(data) + if err != nil { + return err + } + r.Rat = *tempRat + return nil +} diff --git a/types/rational_test.go b/types/rational_test.go index 5af63e8ec..2625db064 100644 --- a/types/rational_test.go +++ b/types/rational_test.go @@ -129,14 +129,14 @@ func TestArithmatic(t *testing.T) { } 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.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()) + 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.Rat, tc.r2.Rat) + 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) }) } 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 }{ {NewRat(333, 777), NewRat(429, 1000), 1000}, - {ToRat(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)}, NewRat(429, 1000), 1000}, + {Rat{*new(big.Rat).SetFrac(big3, big7)}, Rat{*big.NewRat(4285714286, 10000000000)}, 10000000000}, {NewRat(1, 2), NewRat(1, 2), 1000}, } @@ -209,47 +209,40 @@ func TestToLeftPadded(t *testing.T) { } } -//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 TestSerializationText(t *testing.T) { + r := NewRat(1, 3) -//bz, err := r.MarshalText() -//require.Nil(t, err) + bz, err := r.MarshalText() + require.NoError(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) -//} + r2 := NewRat(0, 1) + err = r2.UnmarshalText(bz) + require.NoError(t, err) + 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 := cdc.MarshalBinary(r) - require.Nil(t, err) - - //str, err := r.MarshalJSON() - //require.Nil(t, err) + bz, err := cdc.MarshalJSON(r) + require.NoError(t, err) r2 := NewRat(0, 1) - err = cdc.UnmarshalBinary([]byte(bz), &r2) - //panic(fmt.Sprintf("debug bz: %v\n", string(bz))) - require.Nil(t, err) - + err = cdc.UnmarshalJSON(bz, &r2) + require.NoError(t, err) assert.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2) } @@ -261,17 +254,14 @@ type testEmbedStruct struct { func TestEmbeddedStructSerializationGoWire(t *testing.T) { obj := testEmbedStruct{"foo", 10, NewRat(1, 3)} - - bz, err := cdc.MarshalBinary(obj) + bz, err := cdc.MarshalJSON(obj) require.Nil(t, err) var obj2 testEmbedStruct - obj2.Field3 = NewRat(0, 1) // ... needs to be initialized - err = cdc.UnmarshalBinary(bz, &obj2) + err = cdc.UnmarshalJSON(bz, &obj2) require.Nil(t, err) assert.Equal(t, obj.Field1, obj2.Field1) assert.Equal(t, obj.Field2, obj2.Field2) assert.True(t, obj.Field3.Equal(obj2.Field3), "original: %v, unmarshalled: %v", obj, obj2) - } diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index 188dba867..091701a70 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -166,7 +166,7 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command { if err != nil { 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)") } } diff --git a/x/stake/handler.go b/x/stake/handler.go index 2b55ba3b1..1408c5bb1 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -165,7 +165,7 @@ func delegate(ctx sdk.Context, k Keeper, delegatorAddr sdk.Address, bond = DelegatorBond{ DelegatorAddr: delegatorAddr, 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 { 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() } @@ -202,7 +202,7 @@ func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result { // test that there are enough shares to unbond if msg.Shares == "MAX" { - if !bond.Shares.GT(sdk.ZeroRat) { + if !bond.Shares.GT(sdk.ZeroRat()) { return ErrNotEnoughBondShares(k.codespace, msg.Shares).Result() } } else { diff --git a/x/stake/keeper.go b/x/stake/keeper.go index e53d5ce09..d9fa293f5 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -16,7 +16,7 @@ type Keeper struct { coinKeeper bank.Keeper // caches - gs Pool + pool Pool params Params // codespace @@ -41,7 +41,7 @@ func (k Keeper) getCounter(ctx sdk.Context) int16 { return 0 } var counter int16 - err := k.cdc.UnmarshalBinary(b, &counter) + err := k.cdc.UnmarshalJSON(b, &counter) if err != nil { panic(err) } @@ -51,7 +51,7 @@ func (k Keeper) getCounter(ctx sdk.Context) int16 { // set the current in-block validator operation counter func (k Keeper) setCounter(ctx sdk.Context, counter int16) { store := ctx.KVStore(k.storeKey) - bz, err := k.cdc.MarshalBinary(counter) + bz, err := k.cdc.MarshalJSON(counter) if err != nil { panic(err) } @@ -67,7 +67,7 @@ func (k Keeper) GetCandidate(ctx sdk.Context, addr sdk.Address) (candidate Candi if b == nil { return candidate, false } - err := k.cdc.UnmarshalBinary(b, &candidate) + err := k.cdc.UnmarshalJSON(b, &candidate) if err != nil { panic(err) } @@ -88,7 +88,7 @@ func (k Keeper) GetCandidates(ctx sdk.Context, maxRetrieve int16) (candidates Ca } bz := iterator.Value() var candidate Candidate - err := k.cdc.UnmarshalBinary(bz, &candidate) + err := k.cdc.UnmarshalJSON(bz, &candidate) if err != nil { panic(err) } @@ -112,7 +112,7 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { } // marshal the candidate record and add to the state - bz, err := k.cdc.MarshalBinary(candidate) + bz, err := k.cdc.MarshalJSON(candidate) if err != nil { panic(err) } @@ -145,7 +145,7 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { } // update the candidate record - bz, err = k.cdc.MarshalBinary(candidate) + bz, err = k.cdc.MarshalJSON(candidate) if err != nil { panic(err) } @@ -153,7 +153,7 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { // marshal the new validator record validator := candidate.validator() - bz, err = k.cdc.MarshalBinary(validator) + bz, err = k.cdc.MarshalJSON(validator) if err != nil { panic(err) } @@ -171,7 +171,7 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { setAcc = true } if setAcc { - bz, err = k.cdc.MarshalBinary(validator.abciValidator(k.cdc)) + bz, err = k.cdc.MarshalJSON(validator.abciValidator(k.cdc)) if err != nil { panic(err) } @@ -200,7 +200,7 @@ func (k Keeper) removeCandidate(ctx sdk.Context, address sdk.Address) { if store.Get(GetRecentValidatorKey(address)) == nil { return } - bz, err := k.cdc.MarshalBinary(candidate.validator().abciValidatorZero(k.cdc)) + bz, err := k.cdc.MarshalJSON(candidate.validator().abciValidatorZero(k.cdc)) if err != nil { panic(err) } @@ -242,7 +242,7 @@ func (k Keeper) GetValidators(ctx sdk.Context) (validators []Validator) { } bz := iterator.Value() var validator Validator - err := k.cdc.UnmarshalBinary(bz, &validator) + err := k.cdc.UnmarshalJSON(bz, &validator) if err != nil { 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 bz := iterator.Value() var validator Validator - err := k.cdc.UnmarshalBinary(bz, &validator) + err := k.cdc.UnmarshalJSON(bz, &validator) if err != nil { panic(err) } - bz, err = k.cdc.MarshalBinary(validator.abciValidatorZero(k.cdc)) + bz, err = k.cdc.MarshalJSON(validator.abciValidatorZero(k.cdc)) if err != nil { panic(err) } @@ -297,7 +297,7 @@ func (k Keeper) isNewValidator(ctx sdk.Context, store sdk.KVStore, address sdk.A } bz := iterator.Value() var val Validator - err := k.cdc.UnmarshalBinary(bz, &val) + err := k.cdc.UnmarshalJSON(bz, &val) if err != nil { panic(err) } @@ -330,7 +330,7 @@ func (k Keeper) getAccUpdateValidators(ctx sdk.Context) (updates []abci.Validato for ; iterator.Valid(); iterator.Next() { valBytes := iterator.Value() var val abci.Validator - err := k.cdc.UnmarshalBinary(valBytes, &val) + err := k.cdc.UnmarshalJSON(valBytes, &val) if err != nil { panic(err) } @@ -364,7 +364,7 @@ func (k Keeper) GetDelegatorBond(ctx sdk.Context, return bond, false } - err := k.cdc.UnmarshalBinary(delegatorBytes, &bond) + err := k.cdc.UnmarshalJSON(delegatorBytes, &bond) if err != nil { panic(err) } @@ -385,7 +385,7 @@ func (k Keeper) getBonds(ctx sdk.Context, maxRetrieve int16) (bonds []DelegatorB } bondBytes := iterator.Value() var bond DelegatorBond - err := k.cdc.UnmarshalBinary(bondBytes, &bond) + err := k.cdc.UnmarshalJSON(bondBytes, &bond) if err != nil { panic(err) } @@ -410,7 +410,7 @@ func (k Keeper) GetDelegatorBonds(ctx sdk.Context, delegator sdk.Address, maxRet } bondBytes := iterator.Value() var bond DelegatorBond - err := k.cdc.UnmarshalBinary(bondBytes, &bond) + err := k.cdc.UnmarshalJSON(bondBytes, &bond) if err != nil { 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) { store := ctx.KVStore(k.storeKey) - b, err := k.cdc.MarshalBinary(bond) + b, err := k.cdc.MarshalJSON(bond) if err != nil { panic(err) } @@ -439,7 +439,7 @@ func (k Keeper) removeDelegatorBond(ctx sdk.Context, bond DelegatorBond) { // load/save the global staking params func (k Keeper) GetParams(ctx sdk.Context) (params Params) { // check if cached before anything - if k.params != (Params{}) { + if !k.params.equal(Params{}) { return k.params } 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") } - err := k.cdc.UnmarshalBinary(b, ¶ms) + err := k.cdc.UnmarshalJSON(b, ¶ms) if err != nil { panic(err) } @@ -456,7 +456,7 @@ func (k Keeper) GetParams(ctx sdk.Context) (params Params) { } func (k Keeper) setParams(ctx sdk.Context, params Params) { store := ctx.KVStore(k.storeKey) - b, err := k.cdc.MarshalBinary(params) + b, err := k.cdc.MarshalJSON(params) if err != nil { panic(err) } @@ -467,17 +467,17 @@ func (k Keeper) setParams(ctx sdk.Context, params Params) { //_______________________________________________________________________ // 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 - if k.gs != (Pool{}) { - return k.gs + if !k.pool.equal(Pool{}) { + return k.pool } store := ctx.KVStore(k.storeKey) b := store.Get(PoolKey) if b == nil { panic("Stored pool should not have been nil") } - err := k.cdc.UnmarshalBinary(b, &gs) + err := k.cdc.UnmarshalJSON(b, &pool) if err != nil { 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) { store := ctx.KVStore(k.storeKey) - b, err := k.cdc.MarshalBinary(p) + b, err := k.cdc.MarshalJSON(p) if err != nil { panic(err) } store.Set(PoolKey, b) - k.gs = Pool{} // clear the cache + k.pool = Pool{} //clear the cache } diff --git a/x/stake/keeper_test.go b/x/stake/keeper_test.go index 3878b7bbb..8156071f1 100644 --- a/x/stake/keeper_test.go +++ b/x/stake/keeper_test.go @@ -1,7 +1,6 @@ package stake import ( - "bytes" "testing" 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 _, found := keeper.GetCandidate(ctx, addrVals[0]) assert.False(t, found) @@ -119,13 +109,6 @@ func TestBond(t *testing.T) { 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 _, found := keeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0]) assert.False(t, found) @@ -460,8 +443,8 @@ func TestGetAccUpdateValidators(t *testing.T) { require.Equal(t, 2, len(candidates)) 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[0].validator(), vals[1]) - assert.Equal(t, candidates[1].validator(), vals[0]) + assert.True(t, validatorsEqual(candidates[0].validator(), vals[1])) + assert.True(t, validatorsEqual(candidates[1].validator(), vals[0])) // test identical, // candidate set: {c1, c3} -> {c1, c3} @@ -654,10 +637,10 @@ func TestIsRecentValidator(t *testing.T) { keeper.setCandidate(ctx, candidatesIn[1]) validators = keeper.GetValidators(ctx) 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.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 assert.True(t, keeper.IsRecentValidator(ctx, candidatesIn[0].Address)) diff --git a/x/stake/msg.go b/x/stake/msg.go index 10cea3fa8..6e8101f96 100644 --- a/x/stake/msg.go +++ b/x/stake/msg.go @@ -204,7 +204,7 @@ func (msg MsgUnbond) ValidateBasic() sdk.Error { if err != nil { return ErrBadShares(DefaultCodespace) } - if rat.IsZero() || rat.LT(sdk.ZeroRat) { + if rat.IsZero() || rat.LT(sdk.ZeroRat()) { return ErrBadShares(DefaultCodespace) } } diff --git a/x/stake/pool.go b/x/stake/pool.go index 1e58fe28e..f0c7bfae5 100644 --- a/x/stake/pool.go +++ b/x/stake/pool.go @@ -9,13 +9,13 @@ func (p Pool) bondedRatio() sdk.Rat { if p.TotalSupply > 0 { return sdk.NewRat(p.BondedPool, p.TotalSupply) } - return sdk.ZeroRat + return sdk.ZeroRat() } // get the exchange rate of bonded token per issued share func (p Pool) bondedShareExRate() sdk.Rat { if p.BondedShares.IsZero() { - return sdk.OneRat + return sdk.OneRat() } 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 func (p Pool) unbondedShareExRate() sdk.Rat { if p.UnbondedShares.IsZero() { - return sdk.OneRat + return sdk.OneRat() } 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) { - 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.BondedShares = p.BondedShares.Add(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) { - 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.UnbondedPool += amount return p, issuedShares diff --git a/x/stake/pool_test.go b/x/stake/pool_test.go index cf1cd7ca2..316d57b96 100644 --- a/x/stake/pool_test.go +++ b/x/stake/pool_test.go @@ -22,7 +22,7 @@ func TestBondedRatio(t *testing.T) { pool.TotalSupply = 0 // avoids divide-by-zero - require.Equal(t, pool.bondedRatio(), sdk.ZeroRat) + require.Equal(t, pool.bondedRatio(), sdk.ZeroRat()) } func TestBondedShareExRate(t *testing.T) { @@ -33,10 +33,10 @@ func TestBondedShareExRate(t *testing.T) { // bonded pool / bonded shares require.Equal(t, pool.bondedShareExRate(), sdk.NewRat(3).Quo(sdk.NewRat(10))) - pool.BondedShares = sdk.ZeroRat + pool.BondedShares = sdk.ZeroRat() // avoids divide-by-zero - require.Equal(t, pool.bondedShareExRate(), sdk.OneRat) + require.Equal(t, pool.bondedShareExRate(), sdk.OneRat()) } func TestUnbondedShareExRate(t *testing.T) { @@ -47,24 +47,24 @@ func TestUnbondedShareExRate(t *testing.T) { // unbonded pool / unbonded shares require.Equal(t, pool.unbondedShareExRate(), sdk.NewRat(3).Quo(sdk.NewRat(10))) - pool.UnbondedShares = sdk.ZeroRat + pool.UnbondedShares = sdk.ZeroRat() // avoids divide-by-zero - require.Equal(t, pool.unbondedShareExRate(), sdk.OneRat) + require.Equal(t, pool.unbondedShareExRate(), sdk.OneRat()) } func TestBondedToUnbondedPool(t *testing.T) { ctx, _, keeper := createTestInput(t, false, 0) poolA := keeper.GetPool(ctx) - assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat) - assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat) + assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat()) + assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat()) candA := Candidate{ Status: Bonded, Address: addrs[0], PubKey: pks[0], - Assets: sdk.OneRat, - Liabilities: sdk.OneRat, + Assets: sdk.OneRat(), + Liabilities: sdk.OneRat(), } poolB, candB := poolA.bondedToUnbondedPool(candA) @@ -84,14 +84,14 @@ func TestUnbonbedtoBondedPool(t *testing.T) { ctx, _, keeper := createTestInput(t, false, 0) poolA := keeper.GetPool(ctx) - assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat) - assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat) + assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat()) + assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat()) candA := Candidate{ Status: Bonded, Address: addrs[0], PubKey: pks[0], - Assets: sdk.OneRat, - Liabilities: sdk.OneRat, + Assets: sdk.OneRat(), + Liabilities: sdk.OneRat(), } candA.Status = Unbonded poolB, candB := poolA.unbondedToBondedPool(candA) @@ -112,65 +112,64 @@ func TestAddTokensBonded(t *testing.T) { ctx, _, keeper := createTestInput(t, false, 0) poolA := keeper.GetPool(ctx) - assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat) + assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat()) 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 assert.Equal(t, poolB.BondedShares, poolA.BondedShares.Add(sharesB)) assert.Equal(t, poolB.BondedPool, poolA.BondedPool+10) // 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) { ctx, _, keeper := createTestInput(t, false, 0) 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)) - assert.Equal(t, poolB.bondedShareExRate(), sdk.OneRat) + assert.Equal(t, poolB.bondedShareExRate(), sdk.OneRat()) // correct changes to bonded shares and bonded pool assert.Equal(t, poolB.BondedShares, poolA.BondedShares.Sub(sdk.NewRat(10))) assert.Equal(t, poolB.BondedPool, poolA.BondedPool-tokensB) // 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) { ctx, _, keeper := createTestInput(t, false, 0) poolA := keeper.GetPool(ctx) - assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat) + assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat()) 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 assert.Equal(t, poolB.UnbondedShares, poolA.UnbondedShares.Add(sharesB)) assert.Equal(t, poolB.UnbondedPool, poolA.UnbondedPool+10) // 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) { ctx, _, keeper := createTestInput(t, false, 0) 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)) - assert.Equal(t, poolB.unbondedShareExRate(), sdk.OneRat) + assert.Equal(t, poolB.unbondedShareExRate(), sdk.OneRat()) // correct changes to unbonded shares and bonded pool assert.Equal(t, poolB.UnbondedShares, poolA.UnbondedShares.Sub(sdk.NewRat(10))) assert.Equal(t, poolB.UnbondedPool, poolA.UnbondedPool-tokensB) // 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) { @@ -186,9 +185,9 @@ func TestCandidateAddTokens(t *testing.T) { } poolA.BondedPool = candA.Assets.Evaluate() poolA.BondedShares = candA.Assets - assert.Equal(t, candA.delegatorShareExRate(), sdk.OneRat) - assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat) - assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat) + assert.Equal(t, candA.delegatorShareExRate(), sdk.OneRat()) + assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat()) + assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat()) poolB, candB, sharesB := poolA.candidateAddTokens(candA, 10) // shares were issued @@ -212,9 +211,9 @@ func TestCandidateRemoveShares(t *testing.T) { } poolA.BondedPool = candA.Assets.Evaluate() poolA.BondedShares = candA.Assets - assert.Equal(t, candA.delegatorShareExRate(), sdk.OneRat) - assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat) - assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat) + assert.Equal(t, candA.delegatorShareExRate(), sdk.OneRat()) + assert.Equal(t, poolA.bondedShareExRate(), sdk.OneRat()) + assert.Equal(t, poolA.unbondedShareExRate(), sdk.OneRat()) poolB, candB, coinsB := poolA.candidateRemoveShares(candA, sdk.NewRat(10)) // coins were created @@ -280,8 +279,8 @@ func randomCandidate(r *rand.Rand) Candidate { func randomSetup(r *rand.Rand, numCandidates int) (Pool, Candidates) { pool := Pool{ TotalSupply: 0, - BondedShares: sdk.ZeroRat, - UnbondedShares: sdk.ZeroRat, + BondedShares: sdk.ZeroRat(), + UnbondedShares: sdk.ZeroRat(), BondedPool: 0, UnbondedPool: 0, InflationLastTime: 0, @@ -380,29 +379,29 @@ func assertInvariants(t *testing.T, msg string, pMod.UnbondedPool, pMod.BondedPool, tokens) // 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", msg, pOrig, pMod, tokens) // 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", msg, pOrig, pMod, tokens) // 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", msg, pMod.bondedShareExRate().Evaluate()) // 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", msg, pMod.unbondedShareExRate().Evaluate()) for _, cMod := range cMods { // 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)", msg, cMod.delegatorShareExRate(), @@ -410,7 +409,7 @@ func assertInvariants(t *testing.T, msg string, ) // 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)", msg, cMod.Assets, @@ -420,7 +419,7 @@ func assertInvariants(t *testing.T, msg string, ) // 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)", msg, cMod.Liabilities, @@ -449,7 +448,7 @@ func TestPossibleOverflow(t *testing.T) { pool := Pool{ TotalSupply: 0, BondedShares: assets, - UnbondedShares: sdk.ZeroRat, + UnbondedShares: sdk.ZeroRat(), BondedPool: assets.Evaluate(), UnbondedPool: 0, InflationLastTime: 0, @@ -461,7 +460,7 @@ func TestPossibleOverflow(t *testing.T) { _, newCandidate, _ := pool.candidateAddTokens(cand, tokens) 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", msg, newCandidate.delegatorShareExRate()) } diff --git a/x/stake/test_common.go b/x/stake/test_common.go index 4a36feb95..4d11ea937 100644 --- a/x/stake/test_common.go +++ b/x/stake/test_common.go @@ -1,6 +1,7 @@ package stake import ( + "bytes" "encoding/hex" "testing" @@ -50,6 +51,30 @@ var ( 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 func defaultParams() Params { return Params{ @@ -66,8 +91,8 @@ func defaultParams() Params { func initialPool() Pool { return Pool{ TotalSupply: 0, - BondedShares: sdk.ZeroRat, - UnbondedShares: sdk.ZeroRat, + BondedShares: sdk.ZeroRat(), + UnbondedShares: sdk.ZeroRat(), BondedPool: 0, UnbondedPool: 0, InflationLastTime: 0, @@ -112,9 +137,9 @@ func makeTestCodec() *wire.Codec { func paramsNoInflation() Params { return Params{ - InflationRateChange: sdk.ZeroRat, - InflationMax: sdk.ZeroRat, - InflationMin: sdk.ZeroRat, + InflationRateChange: sdk.ZeroRat(), + InflationMax: sdk.ZeroRat(), + InflationMin: sdk.ZeroRat(), GoalBonded: sdk.NewRat(67, 100), MaxValidators: 100, BondDenom: "fermion", diff --git a/x/stake/tick.go b/x/stake/tick.go index 0b3dd1c83..9ca484061 100644 --- a/x/stake/tick.go +++ b/x/stake/tick.go @@ -62,7 +62,7 @@ func (k Keeper) nextInflation(ctx sdk.Context) (inflation sdk.Rat) { // 7% and 20%. // (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) // increase the new annual inflation for this next cycle diff --git a/x/stake/tick_test.go b/x/stake/tick_test.go index 105ee8981..f75cf65b5 100644 --- a/x/stake/tick_test.go +++ b/x/stake/tick_test.go @@ -29,22 +29,22 @@ func TestGetInflation(t *testing.T) { // 100% bonded, starting at 20% inflation and being reduced // (1 - (1/0.67))*(0.13/8667) {"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 {"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 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 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)}, // 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 { 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()) // 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 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)) // 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 - assert.Equal(t, int64(671734723), pool.TotalSupply) - assert.Equal(t, int64(271734723), pool.BondedPool) + assert.Equal(t, int64(611813022), pool.TotalSupply) + assert.Equal(t, int64(211813022), pool.BondedPool) assert.Equal(t, unbondedShares, pool.UnbondedPool) // 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()) } diff --git a/x/stake/types.go b/x/stake/types.go index 6e15acd96..741783fa1 100644 --- a/x/stake/types.go +++ b/x/stake/types.go @@ -28,6 +28,15 @@ type Params struct { 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 @@ -41,6 +50,16 @@ type Pool struct { 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 @@ -80,8 +99,8 @@ func NewCandidate(address sdk.Address, pubKey crypto.PubKey, description Descrip Status: Unbonded, Address: address, PubKey: pubKey, - Assets: sdk.ZeroRat, - Liabilities: sdk.ZeroRat, + Assets: sdk.ZeroRat(), + Liabilities: sdk.ZeroRat(), Description: description, ValidatorBondHeight: int64(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 func (c Candidate) delegatorShareExRate() sdk.Rat { if c.Liabilities.IsZero() { - return sdk.OneRat + return sdk.OneRat() } return c.Assets.Quo(c.Liabilities) } diff --git a/x/stake/view_slash_keeper_test.go b/x/stake/view_slash_keeper_test.go index a8b0e1071..738085910 100644 --- a/x/stake/view_slash_keeper_test.go +++ b/x/stake/view_slash_keeper_test.go @@ -1,7 +1,6 @@ package stake import ( - "bytes" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -37,13 +36,6 @@ func TestViewSlashBond(t *testing.T) { 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 _, found := viewSlashKeeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0]) assert.False(t, found)