Merge pull request #933 from cosmos/rigel/753-rational
rational extends big.Rat
This commit is contained in:
commit
c1daa081ef
|
@ -1,5 +1,11 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## UNRELEASED
|
||||||
|
|
||||||
|
BREAKING CHANGES
|
||||||
|
|
||||||
|
* types/rational now extends big.Rat
|
||||||
|
|
||||||
## 0.15.1 (April 29, 2018)
|
## 0.15.1 (April 29, 2018)
|
||||||
|
|
||||||
IMPROVEMENTS:
|
IMPROVEMENTS:
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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, "")
|
||||||
|
|
|
@ -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)???
|
||||||
|
@ -209,29 +153,29 @@ func (r Rat) ToLeftPadded(totalDigits int8) string {
|
||||||
|
|
||||||
//___________________________________________________________________________________
|
//___________________________________________________________________________________
|
||||||
|
|
||||||
// Hack to just use json.Marshal for everything until
|
|
||||||
// we update for amino
|
|
||||||
//type JSONCodec struct{}
|
|
||||||
//func (jc JSONCodec) MarshalJSON(o interface{}) ([]byte, error) { return json.Marshal(o) }
|
|
||||||
//func (jc JSONCodec) UnmarshalJSON(bz []byte, o interface{}) error { return json.Unmarshal(bz, o) }
|
|
||||||
|
|
||||||
//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
|
||||||
|
}
|
||||||
|
|
|
@ -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) {
|
|
||||||
//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)
|
|
||||||
|
|
||||||
//bz, err := r.MarshalText()
|
|
||||||
//require.Nil(t, err)
|
|
||||||
|
|
||||||
//r2 := NewRat(0, 1)
|
|
||||||
//err = r2.UnmarshalText(bz)
|
|
||||||
//require.Nil(t, err)
|
|
||||||
|
|
||||||
//assert.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2)
|
|
||||||
//}
|
|
||||||
|
|
||||||
var cdc = wire.NewCodec() //var jsonCdc JSONCodec // TODO wire.Codec
|
var cdc = wire.NewCodec() //var jsonCdc JSONCodec // TODO wire.Codec
|
||||||
|
|
||||||
|
func TestZeroSerializationJSON(t *testing.T) {
|
||||||
|
r := NewRat(0, 1)
|
||||||
|
err := cdc.UnmarshalJSON([]byte(`"0/1"`), &r)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
err = cdc.UnmarshalJSON([]byte(`"0/0"`), &r)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
err = cdc.UnmarshalJSON([]byte(`"1/0"`), &r)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
err = cdc.UnmarshalJSON([]byte(`"{}"`), &r)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSerializationText(t *testing.T) {
|
||||||
|
r := NewRat(1, 3)
|
||||||
|
|
||||||
|
bz, err := r.MarshalText()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
r2 := NewRat(0, 1)
|
||||||
|
err = r2.UnmarshalText(bz)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2)
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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, ¶ms)
|
err := k.cdc.UnmarshalJSON(b, ¶ms)
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -433,9 +432,6 @@ func assertInvariants(t *testing.T, msg string,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Re-enable once the overflow bug is fixed!
|
|
||||||
// ref https://github.com/cosmos/cosmos-sdk/issues/753
|
|
||||||
/*
|
|
||||||
func TestPossibleOverflow(t *testing.T) {
|
func TestPossibleOverflow(t *testing.T) {
|
||||||
assets := sdk.NewRat(2159)
|
assets := sdk.NewRat(2159)
|
||||||
liabilities := sdk.NewRat(391432570689183511).Quo(sdk.NewRat(40113011844664))
|
liabilities := sdk.NewRat(391432570689183511).Quo(sdk.NewRat(40113011844664))
|
||||||
|
@ -449,7 +445,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,11 +457,10 @@ 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())
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// run random operations in a random order on a random single-candidate state, assert invariants hold
|
// run random operations in a random order on a random single-candidate state, assert invariants hold
|
||||||
func TestSingleCandidateIntegrationInvariants(t *testing.T) {
|
func TestSingleCandidateIntegrationInvariants(t *testing.T) {
|
||||||
|
@ -480,9 +475,7 @@ func TestSingleCandidateIntegrationInvariants(t *testing.T) {
|
||||||
poolOrig, candidatesOrig,
|
poolOrig, candidatesOrig,
|
||||||
poolOrig, candidatesOrig, 0)
|
poolOrig, candidatesOrig, 0)
|
||||||
|
|
||||||
// TODO Increase iteration count once overflow bug is fixed
|
for j := 0; j < 5; j++ {
|
||||||
// ref https://github.com/cosmos/cosmos-sdk/issues/753
|
|
||||||
for j := 0; j < 4; j++ {
|
|
||||||
poolMod, candidateMod, tokens, msg := randomOperation(r)(r, poolOrig, candidatesOrig[0])
|
poolMod, candidateMod, tokens, msg := randomOperation(r)(r, poolOrig, candidatesOrig[0])
|
||||||
|
|
||||||
candidatesMod := make([]Candidate, len(candidatesOrig))
|
candidatesMod := make([]Candidate, len(candidatesOrig))
|
||||||
|
@ -512,9 +505,7 @@ func TestMultiCandidateIntegrationInvariants(t *testing.T) {
|
||||||
poolOrig, candidatesOrig,
|
poolOrig, candidatesOrig,
|
||||||
poolOrig, candidatesOrig, 0)
|
poolOrig, candidatesOrig, 0)
|
||||||
|
|
||||||
// TODO Increase iteration count once overflow bug is fixed
|
for j := 0; j < 5; j++ {
|
||||||
// ref https://github.com/cosmos/cosmos-sdk/issues/753
|
|
||||||
for j := 0; j < 3; j++ {
|
|
||||||
index := int(r.Int31n(int32(len(candidatesOrig))))
|
index := int(r.Int31n(int32(len(candidatesOrig))))
|
||||||
poolMod, candidateMod, tokens, msg := randomOperation(r)(r, poolOrig, candidatesOrig[index])
|
poolMod, candidateMod, tokens, msg := randomOperation(r)(r, poolOrig, candidatesOrig[index])
|
||||||
candidatesMod := make([]Candidate, len(candidatesOrig))
|
candidatesMod := make([]Candidate, len(candidatesOrig))
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue