Merge pull request #1819: rational -> decimal

* changelog

* ...

* decimal func working

* decimal complete, untested

* fixing tests

* decimal compile errors resolved

* test compile errors

* precision multiplier test

* 1% laptop battery

* fixed TestNewDecFromStr

* equalities working

* fix bankers round chop

* ...

* working, some decimal issues resolved

* fix rounding error

* rounding works

* decimal works

* ...

* deleted rational

* rational conversion working

* revert changelog

* code compiles (not tests)

* went through all NewDec, made sure they were converted from NewRat properly

* test debugging

* all testing bugs besides the json marshalling fixed

* json unmarshal

* lint

* document update

* fix lcd test

* cli test fix

* mostly undo Dece -> Rate

* val comments

* Efficiency improvements

This now caches all of the precision multipliers (as they were all
used in non-mutative functions), and caches the precisionInt calculation.
(Now it just copies the already calculated value)

* Cache another precisionInt() call.

* Improve banker rounding efficiency

* remove defer, make negation in-place.

* chris val comments

* bez comments

* Aditya comments

* ...

* val comments

* rebasing start

* ...

* compiling

* tests pass

* cli fix

* anton, cwgoes, val comments

* val and jae comments

* type

* undo reuse quo
This commit is contained in:
Rigel 2018-08-14 20:15:02 -04:00 committed by GitHub
parent 0adbd60dfa
commit d9dc061b4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
66 changed files with 1254 additions and 1213 deletions

View File

@ -34,6 +34,7 @@ BREAKING CHANGES
* `gaiacli gov vote --voter` * `gaiacli gov vote --voter`
* [x/gov] Added tags sub-package, changed tags to use dash-case * [x/gov] Added tags sub-package, changed tags to use dash-case
* [x/gov] Governance parameters are now stored in globalparams store * [x/gov] Governance parameters are now stored in globalparams store
* [core] \#1807 Switch from use of rational to decimal
* [lcd] \#1866 Updated lcd /slashing/signing_info endpoint to take cosmosvalpub instead of cosmosvaladdr * [lcd] \#1866 Updated lcd /slashing/signing_info endpoint to take cosmosvalpub instead of cosmosvaladdr
* [types] sdk.NewCoin now takes sdk.Int, sdk.NewInt64Coin takes int64 * [types] sdk.NewCoin now takes sdk.Int, sdk.NewInt64Coin takes int64
* [cli] #1551: Officially removed `--name` from CLI commands * [cli] #1551: Officially removed `--name` from CLI commands

View File

@ -173,7 +173,7 @@ func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.AccAddress
accAuth.Coins = sdk.Coins{sdk.NewInt64Coin("steak", 100)} accAuth.Coins = sdk.Coins{sdk.NewInt64Coin("steak", 100)}
acc := gapp.NewGenesisAccount(&accAuth) acc := gapp.NewGenesisAccount(&accAuth)
genesisState.Accounts = append(genesisState.Accounts, acc) genesisState.Accounts = append(genesisState.Accounts, acc)
genesisState.StakeData.Pool.LooseTokens = genesisState.StakeData.Pool.LooseTokens.Add(sdk.NewRat(100)) genesisState.StakeData.Pool.LooseTokens = genesisState.StakeData.Pool.LooseTokens.Add(sdk.NewDec(100))
} }
appState, err := wire.MarshalJSONIndent(cdc, genesisState) appState, err := wire.MarshalJSONIndent(cdc, genesisState)

View File

@ -185,7 +185,7 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState
} }
acc := NewGenesisAccount(&accAuth) acc := NewGenesisAccount(&accAuth)
genaccs[i] = acc genaccs[i] = acc
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewRat(freeFermionsAcc)) // increase the supply stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(freeFermionsAcc)) // increase the supply
// add the validator // add the validator
if len(genTx.Name) > 0 { if len(genTx.Name) > 0 {
@ -193,10 +193,10 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState
validator := stake.NewValidator(genTx.Address, validator := stake.NewValidator(genTx.Address,
sdk.MustGetAccPubKeyBech32(genTx.PubKey), desc) sdk.MustGetAccPubKeyBech32(genTx.PubKey), desc)
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewRat(freeFermionVal)) // increase the supply stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(freeFermionVal)) // increase the supply
// add some new shares to the validator // add some new shares to the validator
var issuedDelShares sdk.Rat var issuedDelShares sdk.Dec
validator, stakeData.Pool, issuedDelShares = validator.AddTokensFromDel(stakeData.Pool, freeFermionVal) validator, stakeData.Pool, issuedDelShares = validator.AddTokensFromDel(stakeData.Pool, freeFermionVal)
stakeData.Validators = append(stakeData.Validators, validator) stakeData.Validators = append(stakeData.Validators, validator)

View File

@ -48,7 +48,7 @@ func appStateFn(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage {
// Default genesis state // Default genesis state
stakeGenesis := stake.DefaultGenesisState() stakeGenesis := stake.DefaultGenesisState()
stakeGenesis.Pool.LooseTokens = sdk.NewRat(1000) stakeGenesis.Pool.LooseTokens = sdk.NewDec(1000)
genesis := GenesisState{ genesis := GenesisState{
Accounts: genesisAccounts, Accounts: genesisAccounts,
StakeData: stakeGenesis, StakeData: stakeGenesis,

View File

@ -132,7 +132,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
validator := executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags)) validator := executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags))
require.Equal(t, validator.Owner, barAddr) require.Equal(t, validator.Owner, barAddr)
require.True(sdk.RatEq(t, sdk.NewRat(2), validator.Tokens)) require.True(sdk.DecEq(t, sdk.NewDec(2), validator.Tokens))
// unbond a single share // unbond a single share
unbondStr := fmt.Sprintf("gaiacli stake unbond begin %v", flags) unbondStr := fmt.Sprintf("gaiacli stake unbond begin %v", flags)
@ -149,7 +149,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
require.Equal(t, int64(9), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc) require.Equal(t, int64(9), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc)
*/ */
validator = executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags)) validator = executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags))
require.Equal(t, "1/1", validator.Tokens.String()) require.Equal(t, "1.0000000000", validator.Tokens.String())
} }
func TestGaiaCLISubmitProposal(t *testing.T) { func TestGaiaCLISubmitProposal(t *testing.T) {

View File

@ -25,9 +25,9 @@ type VotingProcedure struct {
```go ```go
type TallyingProcedure struct { type TallyingProcedure struct {
Threshold rational.Rational // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5 Threshold sdk.Dec // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
Veto rational.Rational // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3 Veto sdk.Dec // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
GovernancePenalty sdk.Rat // Penalty if validator does not vote GovernancePenalty sdk.Dec // Penalty if validator does not vote
GracePeriod int64 // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply GracePeriod int64 // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply
} }
``` ```
@ -81,7 +81,7 @@ This type is used in a temp map when tallying
```go ```go
type ValidatorGovInfo struct { type ValidatorGovInfo struct {
Minus sdk.Rat Minus sdk.Dec
Vote Vote Vote Vote
} }
``` ```
@ -103,17 +103,17 @@ type Proposal struct {
VotingStartBlock int64 // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached VotingStartBlock int64 // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached
CurrentStatus ProposalStatus // Current status of the proposal CurrentStatus ProposalStatus // Current status of the proposal
YesVotes sdk.Rat YesVotes sdk.Dec
NoVotes sdk.Rat NoVotes sdk.Dec
NoWithVetoVotes sdk.Rat NoWithVetoVotes sdk.Dec
AbstainVotes sdk.Rat AbstainVotes sdk.Dec
} }
``` ```
We also mention a method to update the tally for a given proposal: We also mention a method to update the tally for a given proposal:
```go ```go
func (proposal Proposal) updateTally(vote byte, amount sdk.Rat) func (proposal Proposal) updateTally(vote byte, amount sdk.Dec)
``` ```
### Stores ### Stores

View File

@ -7,7 +7,7 @@
The current annual inflation rate. The current annual inflation rate.
```golang ```golang
type Inflation sdk.Rat type Inflation sdk.Dec
``` ```
### InflationLastTime ### InflationLastTime

View File

@ -16,4 +16,3 @@ EndBlock() ValidatorSetChanges
ClearTendermintUpdates() ClearTendermintUpdates()
return vsc return vsc
``` ```

View File

@ -13,7 +13,7 @@ type Pool struct {
LooseTokens int64 // tokens not associated with any bonded validator LooseTokens int64 // tokens not associated with any bonded validator
BondedTokens int64 // reserve of bonded tokens BondedTokens int64 // reserve of bonded tokens
InflationLastTime int64 // block which the last inflation was processed // TODO make time InflationLastTime int64 // block which the last inflation was processed // TODO make time
Inflation sdk.Rat // current annual inflation rate Inflation sdk.Dec // current annual inflation rate
DateLastCommissionReset int64 // unix timestamp for last commission accounting reset (daily) DateLastCommissionReset int64 // unix timestamp for last commission accounting reset (daily)
} }
@ -28,10 +28,10 @@ overall functioning of the stake module.
```golang ```golang
type Params struct { type Params struct {
InflationRateChange sdk.Rat // maximum annual change in inflation rate InflationRateChange sdk.Dec // maximum annual change in inflation rate
InflationMax sdk.Rat // maximum inflation rate InflationMax sdk.Dec // maximum inflation rate
InflationMin sdk.Rat // minimum inflation rate InflationMin sdk.Dec // minimum inflation rate
GoalBonded sdk.Rat // Goal of percent bonded atoms GoalBonded sdk.Dec // Goal of percent bonded atoms
MaxValidators uint16 // maximum number of validators MaxValidators uint16 // maximum number of validators
BondDenom string // bondable coin denomination BondDenom string // bondable coin denomination
@ -74,9 +74,9 @@ type Validator struct {
Revoked bool // has the validator been revoked? Revoked bool // has the validator been revoked?
Status sdk.BondStatus // validator status (bonded/unbonding/unbonded) Status sdk.BondStatus // validator status (bonded/unbonding/unbonded)
Tokens sdk.Rat // delegated tokens (incl. self-delegation) Tokens sdk.Dec // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Rat // total shares issued to a validator's delegators DelegatorShares sdk.Dec // total shares issued to a validator's delegators
SlashRatio sdk.Rat // increases each time the validator is slashed SlashRatio sdk.Dec // increases each time the validator is slashed
Description Description // description terms for the validator Description Description // description terms for the validator
@ -88,10 +88,10 @@ type Validator struct {
} }
type CommissionInfo struct { type CommissionInfo struct {
Rate sdk.Rat // the commission rate of fees charged to any delegators Rate sdk.Dec // the commission rate of fees charged to any delegators
Max sdk.Rat // maximum commission rate which this validator can ever charge Max sdk.Dec // maximum commission rate which this validator can ever charge
ChangeRate sdk.Rat // maximum daily increase of the validator commission ChangeRate sdk.Dec // maximum daily increase of the validator commission
ChangeToday sdk.Rat // commission rate change today, reset each day (UTC time) ChangeToday sdk.Dec // commission rate change today, reset each day (UTC time)
LastChange int64 // unix timestamp of last commission change LastChange int64 // unix timestamp of last commission change
} }
@ -117,7 +117,7 @@ the transaction is the owner of the bond.
```golang ```golang
type Delegation struct { type Delegation struct {
Shares sdk.Rat // delegation shares recieved Shares sdk.Dec // delegation shares recieved
Height int64 // last height bond updated Height int64 // last height bond updated
} }
``` ```
@ -178,8 +178,8 @@ the original redelegation has been completed.
```golang ```golang
type Redelegation struct { type Redelegation struct {
SourceShares sdk.Rat // amount of source shares redelegating SourceShares sdk.Dec // amount of source shares redelegating
DestinationShares sdk.Rat // amount of destination shares created at redelegation DestinationShares sdk.Dec // amount of destination shares created at redelegation
CompleteTime int64 // unix time to complete redelegation CompleteTime int64 // unix time to complete redelegation
} }
``` ```

View File

@ -18,7 +18,7 @@ Other notes:
- `sender` denotes the address of the sender of the transaction - `sender` denotes the address of the sender of the transaction
- `getXxx`, `setXxx`, and `removeXxx` functions are used to retrieve and - `getXxx`, `setXxx`, and `removeXxx` functions are used to retrieve and
modify objects from the store modify objects from the store
- `sdk.Rat` refers to a rational numeric type specified by the SDK. - `sdk.Dec` refers to a decimal type specified by the SDK.
### TxCreateValidator ### TxCreateValidator
@ -34,9 +34,9 @@ type TxCreateValidator struct {
SelfDelegation coin.Coin SelfDelegation coin.Coin
Description Description Description Description
Commission sdk.Rat Commission sdk.Dec
CommissionMax sdk.Rat CommissionMax sdk.Dec
CommissionMaxChange sdk.Rat CommissionMaxChange sdk.Dec
} }
@ -65,7 +65,7 @@ If either the `Description` (excluding `DateBonded` which is constant),
```golang ```golang
type TxEditCandidacy struct { type TxEditCandidacy struct {
GovernancePubKey crypto.PubKey GovernancePubKey crypto.PubKey
Commission sdk.Rat Commission sdk.Dec
Description Description Description Description
} }
@ -199,7 +199,7 @@ type TxRedelegate struct {
DelegatorAddr Address DelegatorAddr Address
ValidatorFrom Validator ValidatorFrom Validator
ValidatorTo Validator ValidatorTo Validator
Shares sdk.Rat Shares sdk.Dec
CompletedTime int64 CompletedTime int64
} }

View File

@ -10,7 +10,7 @@ import (
// Validator implements sdk.Validator // Validator implements sdk.Validator
type Validator struct { type Validator struct {
Address sdk.AccAddress Address sdk.AccAddress
Power sdk.Rat Power sdk.Dec
} }
// Implements sdk.Validator // Implements sdk.Validator
@ -29,18 +29,18 @@ func (v Validator) GetPubKey() crypto.PubKey {
} }
// Implements sdk.Validator // Implements sdk.Validator
func (v Validator) GetTokens() sdk.Rat { func (v Validator) GetTokens() sdk.Dec {
return sdk.ZeroRat() return sdk.ZeroDec()
} }
// Implements sdk.Validator // Implements sdk.Validator
func (v Validator) GetPower() sdk.Rat { func (v Validator) GetPower() sdk.Dec {
return v.Power return v.Power
} }
// Implements sdk.Validator // Implements sdk.Validator
func (v Validator) GetDelegatorShares() sdk.Rat { func (v Validator) GetDelegatorShares() sdk.Dec {
return sdk.ZeroRat() return sdk.ZeroDec()
} }
// Implements sdk.Validator // Implements sdk.Validator
@ -93,8 +93,8 @@ func (vs *ValidatorSet) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey)
} }
// TotalPower implements sdk.ValidatorSet // TotalPower implements sdk.ValidatorSet
func (vs *ValidatorSet) TotalPower(ctx sdk.Context) sdk.Rat { func (vs *ValidatorSet) TotalPower(ctx sdk.Context) sdk.Dec {
res := sdk.ZeroRat() res := sdk.ZeroDec()
for _, val := range vs.Validators { for _, val := range vs.Validators {
res = res.Add(val.Power) res = res.Add(val.Power)
} }
@ -122,7 +122,7 @@ func (vs *ValidatorSet) RemoveValidator(addr sdk.AccAddress) {
} }
// Implements sdk.ValidatorSet // Implements sdk.ValidatorSet
func (vs *ValidatorSet) Slash(ctx sdk.Context, pubkey crypto.PubKey, height int64, power int64, amt sdk.Rat) { func (vs *ValidatorSet) Slash(ctx sdk.Context, pubkey crypto.PubKey, height int64, power int64, amt sdk.Dec) {
panic("not implemented") panic("not implemented")
} }

View File

@ -32,8 +32,8 @@ func TestValidatorSet(t *testing.T) {
addr2 := []byte("addr2") addr2 := []byte("addr2")
base := &mock.ValidatorSet{[]mock.Validator{ base := &mock.ValidatorSet{[]mock.Validator{
{addr1, sdk.NewRat(1)}, {addr1, sdk.NewDec(1)},
{addr2, sdk.NewRat(2)}, {addr2, sdk.NewDec(2)},
}} }}
valset := NewValidatorSet(wire.NewCodec(), ctx.KVStore(key).Prefix([]byte("assoc")), base, 1, 5) valset := NewValidatorSet(wire.NewCodec(), ctx.KVStore(key).Prefix([]byte("assoc")), base, 1, 5)

View File

@ -38,7 +38,7 @@ func NewHandler(keeper Keeper) sdk.Handler {
In the previous example, the keeper has an `oracle.Keeper`. `oracle.Keeper`s are generated by `NewKeeper`. In the previous example, the keeper has an `oracle.Keeper`. `oracle.Keeper`s are generated by `NewKeeper`.
```go ```go
func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Rat, timeout int64) Keeper { func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Dec, timeout int64) Keeper {
return Keeper { return Keeper {
cdc: cdc, cdc: cdc,
key: key, key: key,

View File

@ -23,7 +23,7 @@ func (keeper Keeper) update(ctx sdk.Context, val sdk.Validator, valset sdk.Valid
// and recalculate voted power // and recalculate voted power
hash := ctx.BlockHeader().ValidatorsHash hash := ctx.BlockHeader().ValidatorsHash
if !bytes.Equal(hash, info.Hash) { if !bytes.Equal(hash, info.Hash) {
info.Power = sdk.ZeroRat() info.Power = sdk.ZeroDec()
info.Hash = hash info.Hash = hash
prefix := GetSignPrefix(p, keeper.cdc) prefix := GetSignPrefix(p, keeper.cdc)
store := ctx.KVStore(keeper.key) store := ctx.KVStore(keeper.key)

View File

@ -13,12 +13,12 @@ type Keeper struct {
valset sdk.ValidatorSet valset sdk.ValidatorSet
supermaj sdk.Rat supermaj sdk.Dec
timeout int64 timeout int64
} }
// NewKeeper constructs a new keeper // NewKeeper constructs a new keeper
func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Rat, timeout int64) Keeper { func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Dec, timeout int64) Keeper {
if timeout < 0 { if timeout < 0 {
panic("Timeout should not be negative") panic("Timeout should not be negative")
} }
@ -46,7 +46,7 @@ const (
// Info for each payload // Info for each payload
type Info struct { type Info struct {
Power sdk.Rat Power sdk.Dec
Hash []byte Hash []byte
LastSigned int64 LastSigned int64
Status InfoStatus Status InfoStatus
@ -55,7 +55,7 @@ type Info struct {
// EmptyInfo construct an empty Info // EmptyInfo construct an empty Info
func EmptyInfo(ctx sdk.Context) Info { func EmptyInfo(ctx sdk.Context) Info {
return Info{ return Info{
Power: sdk.ZeroRat(), Power: sdk.ZeroDec(),
Hash: ctx.BlockHeader().ValidatorsHash, Hash: ctx.BlockHeader().ValidatorsHash,
LastSigned: ctx.BlockHeight(), LastSigned: ctx.BlockHeight(),
Status: Pending, Status: Pending,

View File

@ -107,9 +107,9 @@ func TestOracle(t *testing.T) {
addr3 := []byte("addr3") addr3 := []byte("addr3")
addr4 := []byte("addr4") addr4 := []byte("addr4")
valset := &mock.ValidatorSet{[]mock.Validator{ valset := &mock.ValidatorSet{[]mock.Validator{
{addr1, sdk.NewRat(7)}, {addr1, sdk.NewDec(7)},
{addr2, sdk.NewRat(7)}, {addr2, sdk.NewDec(7)},
{addr3, sdk.NewRat(1)}, {addr3, sdk.NewDec(1)},
}} }}
key := sdk.NewKVStoreKey("testkey") key := sdk.NewKVStoreKey("testkey")
@ -119,7 +119,7 @@ func TestOracle(t *testing.T) {
require.Nil(t, err) require.Nil(t, err)
ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz}) ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz})
ork := NewKeeper(key, cdc, valset, sdk.NewRat(2, 3), 100) ork := NewKeeper(key, cdc, valset, sdk.NewDecWithPrec(667, 3), 100) // 66.7%
h := seqHandler(ork, key, sdk.CodespaceRoot) h := seqHandler(ork, key, sdk.CodespaceRoot)
// Nonmock.Validator signed, transaction failed // Nonmock.Validator signed, transaction failed
@ -171,7 +171,7 @@ func TestOracle(t *testing.T) {
require.Equal(t, 1, getSequence(ctx, key)) require.Equal(t, 1, getSequence(ctx, key))
// Should handle mock.Validator set change // Should handle mock.Validator set change
valset.AddValidator(mock.Validator{addr4, sdk.NewRat(12)}) valset.AddValidator(mock.Validator{addr4, sdk.NewDec(12)})
bz, err = json.Marshal(valset) bz, err = json.Marshal(valset)
require.Nil(t, err) require.Nil(t, err)
ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz}) ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz})

418
types/decimal.go Normal file
View File

@ -0,0 +1,418 @@
package types
import (
"encoding/json"
"fmt"
"math/big"
"strconv"
"strings"
"testing"
)
// NOTE: never use new(Dec) or else we will panic unmarshalling into the
// nil embedded big.Int
type Dec struct {
*big.Int `json:"int"`
}
// number of decimal places
const (
Precision = 10
// bytes required to represent the above precision
// ceil(log2(9999999999))
DecimalPrecisionBits = 34
)
var (
precisionReuse = new(big.Int).Exp(big.NewInt(10), big.NewInt(Precision), nil)
fivePrecision = new(big.Int).Quo(precisionReuse, big.NewInt(2))
precisionMultipliers []*big.Int
zeroInt = big.NewInt(0)
oneInt = big.NewInt(1)
tenInt = big.NewInt(10)
)
// Set precision multipliers
func init() {
precisionMultipliers = make([]*big.Int, Precision+1)
for i := 0; i <= Precision; i++ {
precisionMultipliers[i] = calcPrecisionMultiplier(int64(i))
}
}
func precisionInt() *big.Int {
return new(big.Int).Set(precisionReuse)
}
// nolint - common values
func ZeroDec() Dec { return Dec{new(big.Int).Set(zeroInt)} }
func OneDec() Dec { return Dec{precisionInt()} }
// calculate the precision multiplier
func calcPrecisionMultiplier(prec int64) *big.Int {
if prec > Precision {
panic(fmt.Sprintf("too much precision, maximum %v, provided %v", Precision, prec))
}
zerosToAdd := Precision - prec
multiplier := new(big.Int).Exp(tenInt, big.NewInt(zerosToAdd), nil)
return multiplier
}
// get the precision multiplier, do not mutate result
func precisionMultiplier(prec int64) *big.Int {
if prec > Precision {
panic(fmt.Sprintf("too much precision, maximum %v, provided %v", Precision, prec))
}
return precisionMultipliers[prec]
}
//______________________________________________________________________________________________
// create a new Dec from integer assuming whole number
func NewDec(i int64) Dec {
return NewDecWithPrec(i, 0)
}
// create a new Dec from integer with decimal place at prec
// CONTRACT: prec <= Precision
func NewDecWithPrec(i, prec int64) Dec {
return Dec{
new(big.Int).Mul(big.NewInt(i), precisionMultiplier(prec)),
}
}
// create a new Dec from big integer assuming whole numbers
// CONTRACT: prec <= Precision
func NewDecFromBigInt(i *big.Int) Dec {
return NewDecFromBigIntWithPrec(i, 0)
}
// create a new Dec from big integer assuming whole numbers
// CONTRACT: prec <= Precision
func NewDecFromBigIntWithPrec(i *big.Int, prec int64) Dec {
return Dec{
new(big.Int).Mul(i, precisionMultiplier(prec)),
}
}
// create a new Dec from big integer assuming whole numbers
// CONTRACT: prec <= Precision
func NewDecFromInt(i Int) Dec {
return NewDecFromIntWithPrec(i, 0)
}
// create a new Dec from big integer with decimal place at prec
// CONTRACT: prec <= Precision
func NewDecFromIntWithPrec(i Int, prec int64) Dec {
return Dec{
new(big.Int).Mul(i.BigInt(), precisionMultiplier(prec)),
}
}
// create a decimal from an input decimal string.
// valid must come in the form:
// (-) whole integers (.) decimal integers
// examples of acceptable input include:
// -123.456
// 456.7890
// 345
// -456789
//
// NOTE - An error will return if more decimal places
// are provided in the string than the constant Precision.
//
// CONTRACT - This function does not mutate the input str.
func NewDecFromStr(str string) (d Dec, err Error) {
if len(str) == 0 {
return d, ErrUnknownRequest("decimal string is empty")
}
// first extract any negative symbol
neg := false
if str[0] == '-' {
neg = true
str = str[1:]
}
if len(str) == 0 {
return d, ErrUnknownRequest("decimal string is empty")
}
strs := strings.Split(str, ".")
lenDecs := 0
combinedStr := strs[0]
if len(strs) == 2 {
lenDecs = len(strs[1])
if lenDecs == 0 || len(combinedStr) == 0 {
return d, ErrUnknownRequest("bad decimal length")
}
combinedStr = combinedStr + strs[1]
} else if len(strs) > 2 {
return d, ErrUnknownRequest("too many periods to be a decimal string")
}
if lenDecs > Precision {
return d, ErrUnknownRequest(
fmt.Sprintf("too much precision, maximum %v, len decimal %v", Precision, lenDecs))
}
// add some extra zero's to correct to the Precision factor
zerosToAdd := Precision - lenDecs
zeros := fmt.Sprintf(`%0`+strconv.Itoa(zerosToAdd)+`s`, "")
combinedStr = combinedStr + zeros
combined, ok := new(big.Int).SetString(combinedStr, 10)
if !ok {
return d, ErrUnknownRequest(fmt.Sprintf("bad string to integer conversion, combinedStr: %v", combinedStr))
}
if neg {
combined = new(big.Int).Neg(combined)
}
return Dec{combined}, nil
}
//______________________________________________________________________________________________
//nolint
func (d Dec) IsZero() bool { return (d.Int).Sign() == 0 } // Is equal to zero
func (d Dec) Equal(d2 Dec) bool { return (d.Int).Cmp(d2.Int) == 0 }
func (d Dec) GT(d2 Dec) bool { return (d.Int).Cmp(d2.Int) > 0 } // greater than
func (d Dec) GTE(d2 Dec) bool { return (d.Int).Cmp(d2.Int) >= 0 } // greater than or equal
func (d Dec) LT(d2 Dec) bool { return (d.Int).Cmp(d2.Int) < 0 } // less than
func (d Dec) LTE(d2 Dec) bool { return (d.Int).Cmp(d2.Int) <= 0 } // less than or equal
func (d Dec) Neg() Dec { return Dec{new(big.Int).Neg(d.Int)} } // reverse the decimal sign
// addition
func (d Dec) Add(d2 Dec) Dec {
res := new(big.Int).Add(d.Int, d2.Int)
if res.BitLen() > 255+DecimalPrecisionBits {
panic("Int overflow")
}
return Dec{res}
}
// subtraction
func (d Dec) Sub(d2 Dec) Dec {
res := new(big.Int).Sub(d.Int, d2.Int)
if res.BitLen() > 255+DecimalPrecisionBits {
panic("Int overflow")
}
return Dec{res}
}
// multiplication
func (d Dec) Mul(d2 Dec) Dec {
mul := new(big.Int).Mul(d.Int, d2.Int)
chopped := chopPrecisionAndRound(mul)
if chopped.BitLen() > 255+DecimalPrecisionBits {
panic("Int overflow")
}
return Dec{chopped}
}
// quotient
func (d Dec) Quo(d2 Dec) Dec {
// multiply precision twice
mul := new(big.Int).Mul(d.Int, precisionReuse)
mul.Mul(mul, precisionReuse)
quo := new(big.Int).Quo(mul, d2.Int)
chopped := chopPrecisionAndRound(quo)
if chopped.BitLen() > 255+DecimalPrecisionBits {
panic("Int overflow")
}
return Dec{chopped}
}
func (d Dec) String() string {
str := d.ToLeftPaddedWithDecimals(Precision)
placement := len(str) - Precision
if placement < 0 {
panic("too few decimal digits")
}
return str[:placement] + "." + str[placement:]
}
// TODO panic if negative or if totalDigits < len(initStr)???
// evaluate as an integer and return left padded string
func (d Dec) ToLeftPaddedWithDecimals(totalDigits int8) string {
intStr := d.Int.String()
fcode := `%0` + strconv.Itoa(int(totalDigits)) + `s`
return fmt.Sprintf(fcode, intStr)
}
// TODO panic if negative or if totalDigits < len(initStr)???
// evaluate as an integer and return left padded string
func (d Dec) ToLeftPadded(totalDigits int8) string {
chopped := chopPrecisionAndRound(d.Int)
intStr := chopped.String()
fcode := `%0` + strconv.Itoa(int(totalDigits)) + `s`
return fmt.Sprintf(fcode, intStr)
}
// ____
// __| |__ "chop 'em
// ` \ round!"
// ___|| ~ _ -bankers
// | | __
// | | | __|__|__
// |_____: / | $$$ |
// |________|
// nolint - go-cyclo
// Remove a Precision amount of rightmost digits and perform bankers rounding
// on the remainder (gaussian rounding) on the digits which have been removed.
//
// TODO We should make this function mutate the input. The functions here
// don't need to allocate different memory for chopped after computing the
// result
func chopPrecisionAndRound(d *big.Int) *big.Int {
// remove the negative and add it back when returning
if d.Sign() == -1 {
// make d positive, compute chopped value, and then un-mutate d
d = d.Neg(d)
d = chopPrecisionAndRound(d)
d = d.Neg(d)
return d
}
// get the trucated quotient and remainder
quo, rem := big.NewInt(0), big.NewInt(0)
quo, rem = quo.QuoRem(d, precisionReuse, rem)
if rem.Sign() == 0 { // remainder is zero
return quo
}
switch rem.Cmp(fivePrecision) {
case -1:
return quo
case 1:
return quo.Add(quo, oneInt)
default: // bankers rounding must take place
// always round to an even number
if quo.Bit(0) == 0 {
return quo
}
return quo.Add(quo, oneInt)
}
}
// RoundInt64 rounds the decimal using bankers rounding
func (d Dec) RoundInt64() int64 {
chopped := chopPrecisionAndRound(d.Int)
if !chopped.IsInt64() {
panic("Int64() out of bound")
}
return chopped.Int64()
}
// RoundInt round the decimal using bankers rounding
func (d Dec) RoundInt() Int {
return NewIntFromBigInt(chopPrecisionAndRound(d.Int))
}
//___________________________________________________________________________________
// reuse nil values
var (
nilAmino string
nilJSON []byte
)
func init() {
empty := new(big.Int)
bz, err := empty.MarshalText()
if err != nil {
panic("bad nil amino init")
}
nilAmino = string(bz)
nilJSON, err = json.Marshal(string(bz))
if err != nil {
panic("bad nil json init")
}
}
// wraps d.MarshalText()
func (d Dec) MarshalAmino() (string, error) {
if d.Int == nil {
return nilAmino, nil
}
bz, err := d.Int.MarshalText()
return string(bz), err
}
// requires a valid JSON string - strings quotes and calls UnmarshalText
func (d *Dec) UnmarshalAmino(text string) (err error) {
tempInt := new(big.Int)
err = tempInt.UnmarshalText([]byte(text))
if err != nil {
return err
}
d.Int = tempInt
return nil
}
// MarshalJSON defines custom encoding scheme
func (d Dec) MarshalJSON() ([]byte, error) {
if d.Int == nil {
return nilJSON, nil
}
bz, err := d.Int.MarshalText()
if err != nil {
return nil, err
}
return json.Marshal(string(bz))
}
// UnmarshalJSON defines custom decoding scheme
func (d *Dec) UnmarshalJSON(bz []byte) error {
if d.Int == nil {
d.Int = new(big.Int)
}
var text string
err := json.Unmarshal(bz, &text)
if err != nil {
return err
}
return d.Int.UnmarshalText([]byte(text))
}
//___________________________________________________________________________________
// helpers
// test if two decimal arrays are equal
func DecsEqual(d1s, d2s []Dec) bool {
if len(d1s) != len(d2s) {
return false
}
for i, d1 := range d1s {
if !d1.Equal(d2s[i]) {
return false
}
}
return true
}
// minimum decimal between two
func MinDec(d1, d2 Dec) Dec {
if d1.LT(d2) {
return d1
}
return d2
}
// intended to be used with require/assert: require.True(DecEq(...))
func DecEq(t *testing.T, exp, got Dec) (*testing.T, bool, string, Dec, Dec) {
return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp, got
}

301
types/decimal_test.go Normal file
View File

@ -0,0 +1,301 @@
package types
import (
"math/big"
"testing"
wire "github.com/cosmos/cosmos-sdk/wire"
"github.com/stretchr/testify/require"
)
// create a decimal from a decimal string (ex. "1234.5678")
func mustNewDecFromStr(t *testing.T, str string) (d Dec) {
d, err := NewDecFromStr(str)
require.NoError(t, err)
return d
}
//_______________________________________
func TestPrecisionMultiplier(t *testing.T) {
res := precisionMultiplier(5)
exp := big.NewInt(100000)
require.Equal(t, 0, res.Cmp(exp), "equality was incorrect, res %v, exp %v", res, exp)
}
func TestNewDecFromStr(t *testing.T) {
largeBigInt, success := new(big.Int).SetString("3144605511029693144278234343371835", 10)
require.True(t, success)
tests := []struct {
decimalStr string
expErr bool
exp Dec
}{
{"", true, Dec{}},
{"0.-75", true, Dec{}},
{"0", false, NewDec(0)},
{"1", false, NewDec(1)},
{"1.1", false, NewDecWithPrec(11, 1)},
{"0.75", false, NewDecWithPrec(75, 2)},
{"0.8", false, NewDecWithPrec(8, 1)},
{"0.11111", false, NewDecWithPrec(11111, 5)},
{"314460551102969.3144278234343371835", true, NewDec(3141203149163817869)},
{"314460551102969314427823434337.1835718092488231350",
true, NewDecFromBigIntWithPrec(largeBigInt, 4)},
{"314460551102969314427823434337.1835",
false, NewDecFromBigIntWithPrec(largeBigInt, 4)},
{".", true, Dec{}},
{".0", true, NewDec(0)},
{"1.", true, NewDec(1)},
{"foobar", true, Dec{}},
{"0.foobar", true, Dec{}},
{"0.foobar.", true, Dec{}},
}
for tcIndex, tc := range tests {
res, err := NewDecFromStr(tc.decimalStr)
if tc.expErr {
require.NotNil(t, err, "error expected, decimalStr %v, tc %v", tc.decimalStr, tcIndex)
} else {
require.Nil(t, err, "unexpected error, decimalStr %v, tc %v", tc.decimalStr, tcIndex)
require.True(t, res.Equal(tc.exp), "equality was incorrect, res %v, exp %v, tc %v", res, tc.exp, tcIndex)
}
// negative tc
res, err = NewDecFromStr("-" + tc.decimalStr)
if tc.expErr {
require.NotNil(t, err, "error expected, decimalStr %v, tc %v", tc.decimalStr, tcIndex)
} else {
require.Nil(t, err, "unexpected error, decimalStr %v, tc %v", tc.decimalStr, tcIndex)
exp := tc.exp.Mul(NewDec(-1))
require.True(t, res.Equal(exp), "equality was incorrect, res %v, exp %v, tc %v", res, exp, tcIndex)
}
}
}
func TestEqualities(t *testing.T) {
tests := []struct {
d1, d2 Dec
gt, lt, eq bool
}{
{NewDec(0), NewDec(0), false, false, true},
{NewDecWithPrec(0, 2), NewDecWithPrec(0, 4), false, false, true},
{NewDecWithPrec(100, 0), NewDecWithPrec(100, 0), false, false, true},
{NewDecWithPrec(-100, 0), NewDecWithPrec(-100, 0), false, false, true},
{NewDecWithPrec(-1, 1), NewDecWithPrec(-1, 1), false, false, true},
{NewDecWithPrec(3333, 3), NewDecWithPrec(3333, 3), false, false, true},
{NewDecWithPrec(0, 0), NewDecWithPrec(3333, 3), false, true, false},
{NewDecWithPrec(0, 0), NewDecWithPrec(100, 0), false, true, false},
{NewDecWithPrec(-1, 0), NewDecWithPrec(3333, 3), false, true, false},
{NewDecWithPrec(-1, 0), NewDecWithPrec(100, 0), false, true, false},
{NewDecWithPrec(1111, 3), NewDecWithPrec(100, 0), false, true, false},
{NewDecWithPrec(1111, 3), NewDecWithPrec(3333, 3), false, true, false},
{NewDecWithPrec(-3333, 3), NewDecWithPrec(-1111, 3), false, true, false},
{NewDecWithPrec(3333, 3), NewDecWithPrec(0, 0), true, false, false},
{NewDecWithPrec(100, 0), NewDecWithPrec(0, 0), true, false, false},
{NewDecWithPrec(3333, 3), NewDecWithPrec(-1, 0), true, false, false},
{NewDecWithPrec(100, 0), NewDecWithPrec(-1, 0), true, false, false},
{NewDecWithPrec(100, 0), NewDecWithPrec(1111, 3), true, false, false},
{NewDecWithPrec(3333, 3), NewDecWithPrec(1111, 3), true, false, false},
{NewDecWithPrec(-1111, 3), NewDecWithPrec(-3333, 3), true, false, false},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.gt, tc.d1.GT(tc.d2), "GT result is incorrect, tc %d", tcIndex)
require.Equal(t, tc.lt, tc.d1.LT(tc.d2), "LT result is incorrect, tc %d", tcIndex)
require.Equal(t, tc.eq, tc.d1.Equal(tc.d2), "equality result is incorrect, tc %d", tcIndex)
}
}
func TestDecsEqual(t *testing.T) {
tests := []struct {
d1s, d2s []Dec
eq bool
}{
{[]Dec{NewDec(0)}, []Dec{NewDec(0)}, true},
{[]Dec{NewDec(0)}, []Dec{NewDec(1)}, false},
{[]Dec{NewDec(0)}, []Dec{}, false},
{[]Dec{NewDec(0), NewDec(1)}, []Dec{NewDec(0), NewDec(1)}, true},
{[]Dec{NewDec(1), NewDec(0)}, []Dec{NewDec(1), NewDec(0)}, true},
{[]Dec{NewDec(1), NewDec(0)}, []Dec{NewDec(0), NewDec(1)}, false},
{[]Dec{NewDec(1), NewDec(0)}, []Dec{NewDec(1)}, false},
{[]Dec{NewDec(1), NewDec(2)}, []Dec{NewDec(2), NewDec(4)}, false},
{[]Dec{NewDec(3), NewDec(18)}, []Dec{NewDec(1), NewDec(6)}, false},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.eq, DecsEqual(tc.d1s, tc.d2s), "equality of decional arrays is incorrect, tc %d", tcIndex)
require.Equal(t, tc.eq, DecsEqual(tc.d2s, tc.d1s), "equality of decional arrays is incorrect (converse), tc %d", tcIndex)
}
}
func TestArithmetic(t *testing.T) {
tests := []struct {
d1, d2 Dec
expMul, expDiv, expAdd, expSub Dec
}{
// d1 d2 MUL DIV ADD SUB
{NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0)},
{NewDec(1), NewDec(0), NewDec(0), NewDec(0), NewDec(1), NewDec(1)},
{NewDec(0), NewDec(1), NewDec(0), NewDec(0), NewDec(1), NewDec(-1)},
{NewDec(0), NewDec(-1), NewDec(0), NewDec(0), NewDec(-1), NewDec(1)},
{NewDec(-1), NewDec(0), NewDec(0), NewDec(0), NewDec(-1), NewDec(-1)},
{NewDec(1), NewDec(1), NewDec(1), NewDec(1), NewDec(2), NewDec(0)},
{NewDec(-1), NewDec(-1), NewDec(1), NewDec(1), NewDec(-2), NewDec(0)},
{NewDec(1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(0), NewDec(2)},
{NewDec(-1), NewDec(1), NewDec(-1), NewDec(-1), NewDec(0), NewDec(-2)},
{NewDec(3), NewDec(7), NewDec(21), NewDecWithPrec(4285714286, 10), NewDec(10), NewDec(-4)},
{NewDec(2), NewDec(4), NewDec(8), NewDecWithPrec(5, 1), NewDec(6), NewDec(-2)},
{NewDec(100), NewDec(100), NewDec(10000), NewDec(1), NewDec(200), NewDec(0)},
{NewDecWithPrec(15, 1), NewDecWithPrec(15, 1), NewDecWithPrec(225, 2),
NewDec(1), NewDec(3), NewDec(0)},
{NewDecWithPrec(3333, 4), NewDecWithPrec(333, 4), NewDecWithPrec(1109889, 8),
NewDecWithPrec(10009009009, 9), NewDecWithPrec(3666, 4), NewDecWithPrec(3, 1)},
}
for tcIndex, tc := range tests {
resAdd := tc.d1.Add(tc.d2)
resSub := tc.d1.Sub(tc.d2)
resMul := tc.d1.Mul(tc.d2)
require.True(t, tc.expAdd.Equal(resAdd), "exp %v, res %v, tc %d", tc.expAdd, resAdd, tcIndex)
require.True(t, tc.expSub.Equal(resSub), "exp %v, res %v, tc %d", tc.expSub, resSub, tcIndex)
require.True(t, tc.expMul.Equal(resMul), "exp %v, res %v, tc %d", tc.expMul, resMul, tcIndex)
if tc.d2.IsZero() { // panic for divide by zero
require.Panics(t, func() { tc.d1.Quo(tc.d2) })
} else {
resDiv := tc.d1.Quo(tc.d2)
require.True(t, tc.expDiv.Equal(resDiv), "exp %v, res %v, tc %d", tc.expDiv.String(), resDiv.String(), tcIndex)
}
}
}
func TestBankerRoundChop(t *testing.T) {
tests := []struct {
d1 Dec
exp int64
}{
{mustNewDecFromStr(t, "0.25"), 0},
{mustNewDecFromStr(t, "0"), 0},
{mustNewDecFromStr(t, "1"), 1},
{mustNewDecFromStr(t, "0.75"), 1},
{mustNewDecFromStr(t, "0.5"), 0},
{mustNewDecFromStr(t, "7.5"), 8},
{mustNewDecFromStr(t, "1.5"), 2},
{mustNewDecFromStr(t, "2.5"), 2},
{mustNewDecFromStr(t, "0.545"), 1}, // 0.545-> 1 even though 5 is first decimal and 1 not even
{mustNewDecFromStr(t, "1.545"), 2},
}
for tcIndex, tc := range tests {
resNeg := tc.d1.Neg().RoundInt64()
require.Equal(t, -1*tc.exp, resNeg, "negative tc %d", tcIndex)
resPos := tc.d1.RoundInt64()
require.Equal(t, tc.exp, resPos, "positive tc %d", tcIndex)
}
}
func TestToLeftPadded(t *testing.T) {
tests := []struct {
dec Dec
digits int8
exp string
}{
{mustNewDecFromStr(t, "33.3"), 8, "00000033"},
{mustNewDecFromStr(t, "50"), 8, "00000050"},
{mustNewDecFromStr(t, "333"), 8, "00000333"},
{mustNewDecFromStr(t, "333"), 12, "000000000333"},
{mustNewDecFromStr(t, "0.3333"), 8, "00000000"},
}
for tcIndex, tc := range tests {
res := tc.dec.ToLeftPadded(tc.digits)
require.Equal(t, tc.exp, res, "incorrect left padding, tc %d", tcIndex)
}
}
var cdc = wire.NewCodec()
func TestZeroDeserializationJSON(t *testing.T) {
d := Dec{new(big.Int)}
err := cdc.UnmarshalJSON([]byte(`"0"`), &d)
require.Nil(t, err)
err = cdc.UnmarshalJSON([]byte(`"{}"`), &d)
require.NotNil(t, err)
}
func TestSerializationText(t *testing.T) {
d := mustNewDecFromStr(t, "0.333")
bz, err := d.MarshalText()
require.NoError(t, err)
d2 := Dec{new(big.Int)}
err = d2.UnmarshalText(bz)
require.NoError(t, err)
require.True(t, d.Equal(d2), "original: %v, unmarshalled: %v", d, d2)
}
func TestSerializationGoWireJSON(t *testing.T) {
d := mustNewDecFromStr(t, "0.333")
bz, err := cdc.MarshalJSON(d)
require.NoError(t, err)
d2 := Dec{new(big.Int)}
err = cdc.UnmarshalJSON(bz, &d2)
require.NoError(t, err)
require.True(t, d.Equal(d2), "original: %v, unmarshalled: %v", d, d2)
}
func TestSerializationGoWireBinary(t *testing.T) {
d := mustNewDecFromStr(t, "0.333")
bz, err := cdc.MarshalBinary(d)
require.NoError(t, err)
var d2 Dec
err = cdc.UnmarshalBinary(bz, &d2)
require.NoError(t, err)
require.True(t, d.Equal(d2), "original: %v, unmarshalled: %v", d, d2)
}
type testDEmbedStruct struct {
Field1 string `json:"f1"`
Field2 int `json:"f2"`
Field3 Dec `json:"f3"`
}
// TODO make work for UnmarshalJSON
func TestEmbeddedStructSerializationGoWire(t *testing.T) {
obj := testDEmbedStruct{"foo", 10, NewDecWithPrec(1, 3)}
bz, err := cdc.MarshalBinary(obj)
require.Nil(t, err)
var obj2 testDEmbedStruct
err = cdc.UnmarshalBinary(bz, &obj2)
require.Nil(t, err)
require.Equal(t, obj.Field1, obj2.Field1)
require.Equal(t, obj.Field2, obj2.Field2)
require.True(t, obj.Field3.Equal(obj2.Field3), "original: %v, unmarshalled: %v", obj, obj2)
}
func TestStringOverflow(t *testing.T) {
// two random 64 bit primes
dec1, err := NewDecFromStr("51643150036226787134389711697696177267")
require.NoError(t, err)
dec2, err := NewDecFromStr("-31798496660535729618459429845579852627")
require.NoError(t, err)
dec3 := dec1.Add(dec2)
require.Equal(t,
"19844653375691057515930281852116324640.0000000000",
dec3.String(),
)
}

View File

@ -1,262 +0,0 @@
package types
import (
"fmt"
"math/big"
"strconv"
"strings"
"testing"
)
// "that's one big rat!"
// ______
// / / /\ \____oo
// __ /___...._____ _\o
// __| |_ |_
// NOTE: never use new(Rat) or else
// we will panic unmarshalling into the
// nil embedded big.Rat
type Rat struct {
*big.Rat `json:"rat"`
}
// nolint - common values
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 getNumeratorDenominator(str []string, prec int) (numerator string, denom int64, err Error) {
switch len(str) {
case 1:
if len(str[0]) == 0 {
return "", 0, ErrUnknownRequest("not a decimal string")
}
numerator = str[0]
return numerator, 1, nil
case 2:
if len(str[0]) == 0 || len(str[1]) == 0 {
return "", 0, ErrUnknownRequest("not a decimal string")
}
if len(str[1]) > prec {
return "", 0, ErrUnknownRequest("string has too many decimals")
}
numerator = str[0] + str[1]
len := int64(len(str[1]))
denom = new(big.Int).Exp(big.NewInt(10), big.NewInt(len), nil).Int64()
return numerator, denom, nil
default:
return "", 0, ErrUnknownRequest("not a decimal string")
}
}
// create a rational from decimal string or integer string
// precision is the number of values after the decimal point which should be read
func NewRatFromDecimal(decimalStr string, prec int) (f Rat, err Error) {
// first extract any negative symbol
if len(decimalStr) == 0 {
return f, ErrUnknownRequest("decimal string is empty")
}
neg := false
if string(decimalStr[0]) == "-" {
neg = true
decimalStr = decimalStr[1:]
}
str := strings.Split(decimalStr, ".")
numStr, denom, err := getNumeratorDenominator(str, prec)
if err != nil {
return f, err
}
num, errConv := strconv.Atoi(numStr)
if errConv != nil && strings.HasSuffix(errConv.Error(), "value out of range") {
// resort to big int, don't make this default option for efficiency
numBig, success := new(big.Int).SetString(numStr, 10)
if success != true {
return f, ErrUnknownRequest("not a decimal string")
}
if neg {
numBig.Neg(numBig)
}
return NewRatFromBigInt(numBig, big.NewInt(denom)), nil
} else if errConv != nil {
return f, ErrUnknownRequest("not a decimal string")
}
if neg {
num *= -1
}
return NewRat(int64(num), denom), nil
}
// NewRatFromBigInt constructs Rat from big.Int
func NewRatFromBigInt(num *big.Int, denom ...*big.Int) Rat {
switch len(denom) {
case 0:
return Rat{new(big.Rat).SetInt(num)}
case 1:
return Rat{new(big.Rat).SetFrac(num, denom[0])}
default:
panic("improper use of NewRatFromBigInt, can only have one denominator")
}
}
// NewRatFromInt constructs Rat from Int
func NewRatFromInt(num Int, denom ...Int) Rat {
switch len(denom) {
case 0:
return Rat{new(big.Rat).SetInt(num.BigInt())}
case 1:
return Rat{new(big.Rat).SetFrac(num.BigInt(), denom[0].BigInt())}
default:
panic("improper use of NewRatFromBigInt, can only have one denominator")
}
}
//nolint
func (r Rat) Num() Int { return Int{r.Rat.Num()} } // Num - return the numerator
func (r Rat) Denom() Int { return Int{r.Rat.Denom()} } // Denom - return the denominator
func (r Rat) IsZero() bool { return r.Num().IsZero() } // IsZero - Is the Rat equal to zero
func (r Rat) Equal(r2 Rat) bool { return (r.Rat).Cmp(r2.Rat) == 0 }
func (r Rat) GT(r2 Rat) bool { return (r.Rat).Cmp(r2.Rat) == 1 } // greater than
func (r Rat) GTE(r2 Rat) bool { return !r.LT(r2) } // greater than or equal
func (r Rat) LT(r2 Rat) bool { return (r.Rat).Cmp(r2.Rat) == -1 } // less than
func (r Rat) LTE(r2 Rat) bool { return !r.GT(r2) } // less than or 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 r.Rat.String() }
func (r Rat) FloatString() string { return r.Rat.FloatString(10) } // a human-friendly string format. The last digit is rounded to nearest, with halves rounded away from zero.
var (
zero = big.NewInt(0)
one = big.NewInt(1)
two = big.NewInt(2)
five = big.NewInt(5)
nFive = big.NewInt(-5)
ten = big.NewInt(10)
)
// evaluate the rational using bankers rounding
func (r Rat) EvaluateBig() *big.Int {
num := r.Rat.Num()
denom := r.Rat.Denom()
d, rem := new(big.Int), new(big.Int)
d.QuoRem(num, denom, rem)
if rem.Cmp(zero) == 0 { // is the remainder zero
return d
}
// evaluate the remainder using bankers rounding
tenNum := new(big.Int).Mul(num, ten)
tenD := new(big.Int).Mul(d, ten)
remainderDigit := new(big.Int).Sub(new(big.Int).Quo(tenNum, denom), tenD) // get the first remainder digit
isFinalDigit := (new(big.Int).Rem(tenNum, denom).Cmp(zero) == 0) // is this the final digit in the remainder?
switch {
case isFinalDigit && (remainderDigit.Cmp(five) == 0 || remainderDigit.Cmp(nFive) == 0):
dRem2 := new(big.Int).Rem(d, two)
return new(big.Int).Add(d, dRem2) // always rounds to the even number
case remainderDigit.Cmp(five) != -1: //remainderDigit >= 5:
d.Add(d, one)
case remainderDigit.Cmp(nFive) != 1: //remainderDigit <= -5:
d.Sub(d, one)
}
return d
}
// RoundInt64 rounds the rational using bankers rounding
func (r Rat) RoundInt64() int64 {
return r.EvaluateBig().Int64()
}
// RoundInt round the rational using bankers rounding
func (r Rat) RoundInt() Int {
return NewIntFromBigInt(r.EvaluateBig())
}
// round Rat with the provided precisionFactor
func (r Rat) Round(precisionFactor int64) Rat {
rTen := Rat{new(big.Rat).Mul(r.Rat, big.NewRat(precisionFactor, 1))}
return Rat{big.NewRat(rTen.RoundInt64(), precisionFactor)}
}
// TODO panic if negative or if totalDigits < len(initStr)???
// evaluate as an integer and return left padded string
func (r Rat) ToLeftPadded(totalDigits int8) string {
intStr := r.EvaluateBig().String()
fcode := `%0` + strconv.Itoa(int(totalDigits)) + `s`
return fmt.Sprintf(fcode, intStr)
}
//___________________________________________________________________________________
//Wraps r.MarshalText().
func (r Rat) MarshalAmino() (string, error) {
if r.Rat == nil {
r.Rat = new(big.Rat)
}
bz, err := r.Rat.MarshalText()
return string(bz), err
}
// Requires a valid JSON string - strings quotes and calls UnmarshalText
func (r *Rat) UnmarshalAmino(text string) (err error) {
tempRat := big.NewRat(0, 1)
err = tempRat.UnmarshalText([]byte(text))
if err != nil {
return err
}
r.Rat = tempRat
return nil
}
//___________________________________________________________________________________
// helpers
// test if two rat arrays are equal
func RatsEqual(r1s, r2s []Rat) bool {
if len(r1s) != len(r2s) {
return false
}
for i, r1 := range r1s {
if !r1.Equal(r2s[i]) {
return false
}
}
return true
}
// intended to be used with require/assert: require.True(RatEq(...))
func RatEq(t *testing.T, exp, got Rat) (*testing.T, bool, string, Rat, Rat) {
return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp, got
}
// minimum rational between two
func MinRat(r1, r2 Rat) Rat {
if r1.LT(r2) {
return r1
}
return r2
}

View File

@ -1,402 +0,0 @@
package types
import (
"math/big"
"math/rand"
"testing"
wire "github.com/cosmos/cosmos-sdk/wire"
"github.com/stretchr/testify/require"
)
func TestNew(t *testing.T) {
require.Equal(t, NewRat(1), NewRat(1, 1))
require.Equal(t, NewRat(100), NewRat(100, 1))
require.Equal(t, NewRat(-1), NewRat(-1, 1))
require.Equal(t, NewRat(-100), NewRat(-100, 1))
require.Equal(t, NewRat(0), NewRat(0, 1))
// do not allow for more than 2 variables
require.Panics(t, func() { NewRat(1, 1, 1) })
}
func TestNewFromDecimal(t *testing.T) {
largeBigInt, success := new(big.Int).SetString("3109736052979742687701388262607869", 10)
require.True(t, success)
tests := []struct {
decimalStr string
expErr bool
exp Rat
}{
{"", true, Rat{}},
{"0", false, NewRat(0)},
{"1", false, NewRat(1)},
{"1.1", false, NewRat(11, 10)},
{"0.75", false, NewRat(3, 4)},
{"0.8", false, NewRat(4, 5)},
{"0.11111", true, NewRat(1111, 10000)},
{"628240629832763.5738930323617075341", true, NewRat(3141203149163817869, 5000)},
{"621947210595948537540277652521.5738930323617075341",
true, NewRatFromBigInt(largeBigInt, big.NewInt(5000))},
{"628240629832763.5738", false, NewRat(3141203149163817869, 5000)},
{"621947210595948537540277652521.5738",
false, NewRatFromBigInt(largeBigInt, big.NewInt(5000))},
{".", true, Rat{}},
{".0", true, Rat{}},
{"1.", true, Rat{}},
{"foobar", true, Rat{}},
{"0.foobar", true, Rat{}},
{"0.foobar.", true, Rat{}},
}
for tcIndex, tc := range tests {
res, err := NewRatFromDecimal(tc.decimalStr, 4)
if tc.expErr {
require.NotNil(t, err, tc.decimalStr, "error expected, tc #%d", tcIndex)
} else {
require.Nil(t, err, tc.decimalStr, "unexpected error, tc #%d", tcIndex)
require.True(t, res.Equal(tc.exp), tc.decimalStr, "equality was incorrect, tc #%d", tcIndex)
}
// negative tc
res, err = NewRatFromDecimal("-"+tc.decimalStr, 4)
if tc.expErr {
require.NotNil(t, err, tc.decimalStr, "error expected (negative case), tc #%d", tcIndex)
} else {
require.Nil(t, err, tc.decimalStr, "unexpected error (negative case), tc #%d", tcIndex)
require.True(t, res.Equal(tc.exp.Mul(NewRat(-1))), tc.decimalStr, "equality was incorrect (negative case), tc #%d", tcIndex)
}
}
}
func TestEqualities(t *testing.T) {
tests := []struct {
r1, r2 Rat
gt, lt, eq bool
}{
{NewRat(0), NewRat(0), false, false, true},
{NewRat(0, 100), NewRat(0, 10000), false, false, true},
{NewRat(100), NewRat(100), false, false, true},
{NewRat(-100), NewRat(-100), false, false, true},
{NewRat(-100, -1), NewRat(100), false, false, true},
{NewRat(-1, 1), NewRat(1, -1), false, false, true},
{NewRat(1, -1), NewRat(-1, 1), false, false, true},
{NewRat(3, 7), NewRat(3, 7), false, false, true},
{NewRat(0), NewRat(3, 7), false, true, false},
{NewRat(0), NewRat(100), false, true, false},
{NewRat(-1), NewRat(3, 7), false, true, false},
{NewRat(-1), NewRat(100), false, true, false},
{NewRat(1, 7), NewRat(100), false, true, false},
{NewRat(1, 7), NewRat(3, 7), false, true, false},
{NewRat(-3, 7), NewRat(-1, 7), false, true, false},
{NewRat(3, 7), NewRat(0), true, false, false},
{NewRat(100), NewRat(0), true, false, false},
{NewRat(3, 7), NewRat(-1), true, false, false},
{NewRat(100), NewRat(-1), true, false, false},
{NewRat(100), NewRat(1, 7), true, false, false},
{NewRat(3, 7), NewRat(1, 7), true, false, false},
{NewRat(-1, 7), NewRat(-3, 7), true, false, false},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.gt, tc.r1.GT(tc.r2), "GT result is incorrect, tc #%d", tcIndex)
require.Equal(t, tc.lt, tc.r1.LT(tc.r2), "LT result is incorrect, tc #%d", tcIndex)
require.Equal(t, tc.eq, tc.r1.Equal(tc.r2), "equality result is incorrect, tc #%d", tcIndex)
}
}
func TestArithmetic(t *testing.T) {
tests := []struct {
r1, r2 Rat
resMul, resDiv, resAdd, resSub Rat
}{
// r1 r2 MUL DIV ADD SUB
{NewRat(0), NewRat(0), NewRat(0), NewRat(0), NewRat(0), NewRat(0)},
{NewRat(1), NewRat(0), NewRat(0), NewRat(0), NewRat(1), NewRat(1)},
{NewRat(0), NewRat(1), NewRat(0), NewRat(0), NewRat(1), NewRat(-1)},
{NewRat(0), NewRat(-1), NewRat(0), NewRat(0), NewRat(-1), NewRat(1)},
{NewRat(-1), NewRat(0), NewRat(0), NewRat(0), NewRat(-1), NewRat(-1)},
{NewRat(1), NewRat(1), NewRat(1), NewRat(1), NewRat(2), NewRat(0)},
{NewRat(-1), NewRat(-1), NewRat(1), NewRat(1), NewRat(-2), NewRat(0)},
{NewRat(1), NewRat(-1), NewRat(-1), NewRat(-1), NewRat(0), NewRat(2)},
{NewRat(-1), NewRat(1), NewRat(-1), NewRat(-1), NewRat(0), NewRat(-2)},
{NewRat(3), NewRat(7), NewRat(21), NewRat(3, 7), NewRat(10), NewRat(-4)},
{NewRat(2), NewRat(4), NewRat(8), NewRat(1, 2), NewRat(6), NewRat(-2)},
{NewRat(100), NewRat(100), NewRat(10000), NewRat(1), NewRat(200), NewRat(0)},
{NewRat(3, 2), NewRat(3, 2), NewRat(9, 4), NewRat(1), NewRat(3), NewRat(0)},
{NewRat(3, 7), NewRat(7, 3), NewRat(1), NewRat(9, 49), NewRat(58, 21), NewRat(-40, 21)},
{NewRat(1, 21), NewRat(11, 5), NewRat(11, 105), NewRat(5, 231), NewRat(236, 105), NewRat(-226, 105)},
{NewRat(-21), NewRat(3, 7), NewRat(-9), NewRat(-49), NewRat(-144, 7), NewRat(-150, 7)},
{NewRat(100), NewRat(1, 7), NewRat(100, 7), NewRat(700), NewRat(701, 7), NewRat(699, 7)},
}
for tcIndex, tc := range tests {
require.True(t, tc.resMul.Equal(tc.r1.Mul(tc.r2)), "r1 %v, r2 %v. tc #%d", tc.r1.Rat, tc.r2.Rat, tcIndex)
require.True(t, tc.resAdd.Equal(tc.r1.Add(tc.r2)), "r1 %v, r2 %v. tc #%d", tc.r1.Rat, tc.r2.Rat, tcIndex)
require.True(t, tc.resSub.Equal(tc.r1.Sub(tc.r2)), "r1 %v, r2 %v. tc #%d", tc.r1.Rat, tc.r2.Rat, tcIndex)
if tc.r2.Num().IsZero() { // panic for divide by zero
require.Panics(t, func() { tc.r1.Quo(tc.r2) })
} else {
require.True(t, tc.resDiv.Equal(tc.r1.Quo(tc.r2)), "r1 %v, r2 %v. tc #%d", tc.r1.Rat, tc.r2.Rat, tcIndex)
}
}
}
func TestEvaluate(t *testing.T) {
tests := []struct {
r1 Rat
res int64
}{
{NewRat(0), 0},
{NewRat(1), 1},
{NewRat(1, 4), 0},
{NewRat(1, 2), 0},
{NewRat(3, 4), 1},
{NewRat(5, 6), 1},
{NewRat(3, 2), 2},
{NewRat(5, 2), 2},
{NewRat(6, 11), 1}, // 0.545-> 1 even though 5 is first decimal and 1 not even
{NewRat(17, 11), 2}, // 1.545
{NewRat(5, 11), 0},
{NewRat(16, 11), 1},
{NewRat(113, 12), 9},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.res, tc.r1.RoundInt64(), "%v. tc #%d", tc.r1, tcIndex)
require.Equal(t, tc.res*-1, tc.r1.Mul(NewRat(-1)).RoundInt64(), "%v. tc #%d", tc.r1.Mul(NewRat(-1)), tcIndex)
}
}
func TestRound(t *testing.T) {
many3 := "333333333333333333333333333333333333333333333"
many7 := "777777777777777777777777777777777777777777777"
big3, worked := new(big.Int).SetString(many3, 10)
require.True(t, worked)
big7, worked := new(big.Int).SetString(many7, 10)
require.True(t, worked)
tests := []struct {
r, res Rat
precFactor int64
}{
{NewRat(333, 777), NewRat(429, 1000), 1000},
{Rat{new(big.Rat).SetFrac(big3, big7)}, NewRat(429, 1000), 1000},
{Rat{new(big.Rat).SetFrac(big3, big7)}, Rat{big.NewRat(4285714286, 10000000000)}, 10000000000},
{NewRat(1, 2), NewRat(1, 2), 1000},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.res, tc.r.Round(tc.precFactor), "%v", tc.r, "incorrect rounding, tc #%d", tcIndex)
negR1, negRes := tc.r.Mul(NewRat(-1)), tc.res.Mul(NewRat(-1))
require.Equal(t, negRes, negR1.Round(tc.precFactor), "%v", negR1, "incorrect rounding (negative case), tc #%d", tcIndex)
}
}
func TestToLeftPadded(t *testing.T) {
tests := []struct {
rat Rat
digits int8
res string
}{
{NewRat(100, 3), 8, "00000033"},
{NewRat(1, 3), 8, "00000000"},
{NewRat(100, 2), 8, "00000050"},
{NewRat(1000, 3), 8, "00000333"},
{NewRat(1000, 3), 12, "000000000333"},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.res, tc.rat.ToLeftPadded(tc.digits), "incorrect left padding, tc #%d", tcIndex)
}
}
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)
require.Nil(t, err)
err = cdc.UnmarshalJSON([]byte(`"0/0"`), &r)
require.NotNil(t, err)
err = cdc.UnmarshalJSON([]byte(`"1/0"`), &r)
require.NotNil(t, err)
err = cdc.UnmarshalJSON([]byte(`"{}"`), &r)
require.NotNil(t, err)
}
func TestSerializationText(t *testing.T) {
r := NewRat(1, 3)
bz, err := r.MarshalText()
require.NoError(t, err)
var r2 = Rat{new(big.Rat)}
err = r2.UnmarshalText(bz)
require.NoError(t, err)
require.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2)
}
func TestSerializationGoWireJSON(t *testing.T) {
r := NewRat(1, 3)
bz, err := cdc.MarshalJSON(r)
require.NoError(t, err)
var r2 Rat
err = cdc.UnmarshalJSON(bz, &r2)
require.NoError(t, err)
require.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2)
}
func TestSerializationGoWireBinary(t *testing.T) {
r := NewRat(1, 3)
bz, err := cdc.MarshalBinary(r)
require.NoError(t, err)
var r2 Rat
err = cdc.UnmarshalBinary(bz, &r2)
require.NoError(t, err)
require.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2)
}
type testEmbedStruct struct {
Field1 string `json:"f1"`
Field2 int `json:"f2"`
Field3 Rat `json:"f3"`
}
func TestEmbeddedStructSerializationGoWire(t *testing.T) {
obj := testEmbedStruct{"foo", 10, NewRat(1, 3)}
bz, err := cdc.MarshalJSON(obj)
require.Nil(t, err)
var obj2 testEmbedStruct
err = cdc.UnmarshalJSON(bz, &obj2)
require.Nil(t, err)
require.Equal(t, obj.Field1, obj2.Field1)
require.Equal(t, obj.Field2, obj2.Field2)
require.True(t, obj.Field3.Equal(obj2.Field3), "original: %v, unmarshalled: %v", obj, obj2)
}
func TestRatsEqual(t *testing.T) {
tests := []struct {
r1s, r2s []Rat
eq bool
}{
{[]Rat{NewRat(0)}, []Rat{NewRat(0)}, true},
{[]Rat{NewRat(0)}, []Rat{NewRat(1)}, false},
{[]Rat{NewRat(0)}, []Rat{}, false},
{[]Rat{NewRat(0), NewRat(1)}, []Rat{NewRat(0), NewRat(1)}, true},
{[]Rat{NewRat(1), NewRat(0)}, []Rat{NewRat(1), NewRat(0)}, true},
{[]Rat{NewRat(1), NewRat(0)}, []Rat{NewRat(0), NewRat(1)}, false},
{[]Rat{NewRat(1), NewRat(0)}, []Rat{NewRat(1)}, false},
{[]Rat{NewRat(1), NewRat(2)}, []Rat{NewRat(2), NewRat(4)}, false},
{[]Rat{NewRat(3), NewRat(18)}, []Rat{NewRat(1), NewRat(6)}, false},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.eq, RatsEqual(tc.r1s, tc.r2s), "equality of rational arrays is incorrect, tc #%d", tcIndex)
require.Equal(t, tc.eq, RatsEqual(tc.r2s, tc.r1s), "equality of rational arrays is incorrect (converse), tc #%d", tcIndex)
}
}
func TestStringOverflow(t *testing.T) {
// two random 64 bit primes
rat1 := NewRat(5164315003622678713, 4389711697696177267)
rat2 := NewRat(-3179849666053572961, 8459429845579852627)
rat3 := rat1.Add(rat2)
require.Equal(t,
"29728537197630860939575850336935951464/37134458148982045574552091851127630409",
rat3.String(),
)
}
// Tests below uses randomness
// Since we are using *big.Rat as underlying value
// and (U/)Int is immutable value(see TestImmutability(U/)Int)
// it is safe to use randomness in the tests
func TestArithRat(t *testing.T) {
for i := 0; i < 20; i++ {
n1 := NewInt(int64(rand.Int31()))
d1 := NewInt(int64(rand.Int31()))
rat1 := NewRatFromInt(n1, d1)
n2 := NewInt(int64(rand.Int31()))
d2 := NewInt(int64(rand.Int31()))
rat2 := NewRatFromInt(n2, d2)
n1d2 := n1.Mul(d2)
n2d1 := n2.Mul(d1)
cases := []struct {
nres Int
dres Int
rres Rat
}{
{n1d2.Add(n2d1), d1.Mul(d2), rat1.Add(rat2)},
{n1d2.Sub(n2d1), d1.Mul(d2), rat1.Sub(rat2)},
{n1.Mul(n2), d1.Mul(d2), rat1.Mul(rat2)},
{n1d2, n2d1, rat1.Quo(rat2)},
}
for _, tc := range cases {
require.Equal(t, NewRatFromInt(tc.nres, tc.dres), tc.rres)
}
}
}
func TestCompRat(t *testing.T) {
for i := 0; i < 20; i++ {
n1 := NewInt(int64(rand.Int31()))
d1 := NewInt(int64(rand.Int31()))
rat1 := NewRatFromInt(n1, d1)
n2 := NewInt(int64(rand.Int31()))
d2 := NewInt(int64(rand.Int31()))
rat2 := NewRatFromInt(n2, d2)
n1d2 := n1.Mul(d2)
n2d1 := n2.Mul(d1)
cases := []struct {
ires bool
rres bool
}{
{n1d2.Equal(n2d1), rat1.Equal(rat2)},
{n1d2.GT(n2d1), rat1.GT(rat2)},
{n1d2.LT(n2d1), rat1.LT(rat2)},
{n1d2.GT(n2d1) || n1d2.Equal(n2d1), rat1.GTE(rat2)},
{n1d2.LT(n2d1) || n1d2.Equal(n2d1), rat1.LTE(rat2)},
}
for _, tc := range cases {
require.Equal(t, tc.ires, tc.rres)
}
}
}
func TestImmutabilityRat(t *testing.T) {
for i := 0; i < 20; i++ {
n := int64(rand.Int31())
r := NewRat(n)
z := ZeroRat()
o := OneRat()
r.Add(z)
r.Sub(z)
r.Mul(o)
r.Quo(o)
require.Equal(t, n, r.RoundInt64())
require.True(t, NewRat(n).Equal(r))
}
}

View File

@ -42,9 +42,9 @@ type Validator interface {
GetStatus() BondStatus // status of the validator GetStatus() BondStatus // status of the validator
GetOwner() AccAddress // owner AccAddress to receive/return validators coins GetOwner() AccAddress // owner AccAddress to receive/return validators coins
GetPubKey() crypto.PubKey // validation pubkey GetPubKey() crypto.PubKey // validation pubkey
GetPower() Rat // validation power GetPower() Dec // validation power
GetTokens() Rat // validation tokens GetTokens() Dec // validation tokens
GetDelegatorShares() Rat // Total out standing delegator shares GetDelegatorShares() Dec // Total out standing delegator shares
GetBondHeight() int64 // height in which the validator became active GetBondHeight() int64 // height in which the validator became active
} }
@ -68,10 +68,10 @@ type ValidatorSet interface {
Validator(Context, AccAddress) Validator // get a particular validator by owner AccAddress Validator(Context, AccAddress) Validator // get a particular validator by owner AccAddress
ValidatorByPubKey(Context, crypto.PubKey) Validator // get a particular validator by signing PubKey ValidatorByPubKey(Context, crypto.PubKey) Validator // get a particular validator by signing PubKey
TotalPower(Context) Rat // total power of the validator set TotalPower(Context) Dec // total power of the validator set
// slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction // slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction
Slash(Context, crypto.PubKey, int64, int64, Rat) Slash(Context, crypto.PubKey, int64, int64, Dec)
Revoke(Context, crypto.PubKey) // revoke a validator Revoke(Context, crypto.PubKey) // revoke a validator
Unrevoke(Context, crypto.PubKey) // unrevoke a validator Unrevoke(Context, crypto.PubKey) // unrevoke a validator
} }
@ -82,7 +82,7 @@ type ValidatorSet interface {
type Delegation interface { type Delegation interface {
GetDelegator() AccAddress // delegator AccAddress for the bond GetDelegator() AccAddress // delegator AccAddress for the bond
GetValidator() AccAddress // validator owner AccAddress for the bond GetValidator() AccAddress // validator owner AccAddress for the bond
GetBondShares() Rat // amount of validator's shares GetBondShares() Dec // amount of validator's shares
} }
// properties for the set of all delegations for a particular // properties for the set of all delegations for a particular

View File

@ -23,13 +23,13 @@ package stake
////_________________________________________________________________________ ////_________________________________________________________________________
//// cummulative power of the non-absent prevotes //// cummulative power of the non-absent prevotes
//func (k Keeper) GetTotalPrecommitVotingPower(ctx sdk.Context) sdk.Rat { //func (k Keeper) GetTotalPrecommitVotingPower(ctx sdk.Context) sdk.Dec {
//store := ctx.KVStore(k.storeKey) //store := ctx.KVStore(k.storeKey)
//// get absent prevote indexes //// get absent prevote indexes
//absents := ctx.AbsentValidators() //absents := ctx.AbsentValidators()
//TotalPower := sdk.ZeroRat() //TotalPower := sdk.ZeroDec()
//i := int32(0) //i := int32(0)
//iterator := store.SubspaceIterator(ValidatorsBondedKey) //iterator := store.SubspaceIterator(ValidatorsBondedKey)
//for ; iterator.Valid(); iterator.Next() { //for ; iterator.Valid(); iterator.Next() {

View File

@ -8,8 +8,8 @@ package stake
//var candidatesIn [5]Candidate //var candidatesIn [5]Candidate
//for i, amt := range amts { //for i, amt := range amts {
//candidatesIn[i] = NewCandidate(addrVals[i], pks[i], Description{}) //candidatesIn[i] = NewCandidate(addrVals[i], pks[i], Description{})
//candidatesIn[i].BondedShares = sdk.NewRat(amt) //candidatesIn[i].BondedShares = sdk.NewDec(amt)
//candidatesIn[i].DelegatorShares = sdk.NewRat(amt) //candidatesIn[i].DelegatorShares = sdk.NewDec(amt)
//keeper.setCandidate(ctx, candidatesIn[i]) //keeper.setCandidate(ctx, candidatesIn[i])
//} //}
@ -18,7 +18,7 @@ package stake
//require.Equal(t, 5, len(gotValidators)) //require.Equal(t, 5, len(gotValidators))
//totPow := keeper.GetTotalPrecommitVotingPower(ctx) //totPow := keeper.GetTotalPrecommitVotingPower(ctx)
//exp := sdk.NewRat(11111) //exp := sdk.NewDec(11111)
//require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow) //require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow)
//// set absent gotValidators to be the 1st and 3rd record sorted by pubKey address //// set absent gotValidators to be the 1st and 3rd record sorted by pubKey address
@ -26,6 +26,6 @@ package stake
//totPow = keeper.GetTotalPrecommitVotingPower(ctx) //totPow = keeper.GetTotalPrecommitVotingPower(ctx)
//// XXX verify that this order should infact exclude these two records //// XXX verify that this order should infact exclude these two records
//exp = sdk.NewRat(11100) //exp = sdk.NewDec(11100)
//require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow) //require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow)
//} //}

View File

@ -17,7 +17,7 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {}
//// calculate the proposer reward //// calculate the proposer reward
//precommitPower := k.GetTotalPrecommitVotingPower(ctx) //precommitPower := k.GetTotalPrecommitVotingPower(ctx)
//toProposer := coinsMulRat(collectedFees, (sdk.NewRat(1, 100).Add(sdk.NewRat(4, 100).Mul(precommitPower).Quo(pool.BondedShares)))) //toProposer := coinsMulRat(collectedFees, (sdk.NewDec(1, 100).Add(sdk.NewDec(4, 100).Mul(precommitPower).Quo(pool.BondedShares))))
//candidate.ProposerRewardPool = candidate.ProposerRewardPool.Plus(toProposer) //candidate.ProposerRewardPool = candidate.ProposerRewardPool.Plus(toProposer)
//toReservePool := coinsMulRat(collectedFees, params.ReservePoolFee) //toReservePool := coinsMulRat(collectedFees, params.ReservePoolFee)
@ -34,10 +34,10 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {}
//k.setPool(ctx, pool) //k.setPool(ctx, pool)
//} //}
//func coinsMulRat(coins sdk.Coins, rat sdk.Rat) sdk.Coins { //func coinsMulRat(coins sdk.Coins, rat sdk.Dec) sdk.Coins {
//var res sdk.Coins //var res sdk.Coins
//for _, coin := range coins { //for _, coin := range coins {
//coinMulAmt := rat.Mul(sdk.NewRat(coin.Amount)).Evaluate() //coinMulAmt := rat.Mul(sdk.NewDec(coin.Amount)).Evaluate()
//coinMul := sdk.Coins{{coin.Denom, coinMulAmt}} //coinMul := sdk.Coins{{coin.Denom, coinMulAmt}}
//res = res.Plus(coinMul) //res = res.Plus(coinMul)
//} //}
@ -49,14 +49,14 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {}
//// calculate adjustment changes for a candidate at a height //// calculate adjustment changes for a candidate at a height
//func CalculateAdjustmentChange(candidate Candidate, pool Pool, denoms []string, height int64) (Candidate, Pool) { //func CalculateAdjustmentChange(candidate Candidate, pool Pool, denoms []string, height int64) (Candidate, Pool) {
//heightRat := sdk.NewRat(height) //heightRat := sdk.NewDec(height)
//lastHeightRat := sdk.NewRat(height - 1) //lastHeightRat := sdk.NewDec(height - 1)
//candidateFeeCount := candidate.BondedShares.Mul(heightRat) //candidateFeeCount := candidate.BondedShares.Mul(heightRat)
//poolFeeCount := pool.BondedShares.Mul(heightRat) //poolFeeCount := pool.BondedShares.Mul(heightRat)
//for i, denom := range denoms { //for i, denom := range denoms {
//poolFeeSumReceived := sdk.NewRat(pool.FeeSumReceived.AmountOf(denom)) //poolFeeSumReceived := sdk.NewDec(pool.FeeSumReceived.AmountOf(denom))
//poolFeeRecent := sdk.NewRat(pool.FeeRecent.AmountOf(denom)) //poolFeeRecent := sdk.NewDec(pool.FeeRecent.AmountOf(denom))
//// calculate simple and projected pools //// calculate simple and projected pools
//simplePool := candidateFeeCount.Quo(poolFeeCount).Mul(poolFeeSumReceived) //simplePool := candidateFeeCount.Quo(poolFeeCount).Mul(poolFeeSumReceived)
//calc1 := candidate.PrevBondedShares.Mul(lastHeightRat).Quo(pool.PrevBondedShares.Mul(lastHeightRat)).Mul(poolFeeRecent) //calc1 := candidate.PrevBondedShares.Mul(lastHeightRat).Quo(pool.PrevBondedShares.Mul(lastHeightRat)).Mul(poolFeeRecent)

View File

@ -23,8 +23,8 @@ package stake
//// fee information for a validator //// fee information for a validator
//type Validator struct { //type Validator struct {
//Adjustments []sdk.Rat `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms //Adjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms
//PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // total shares of a global hold pools //PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // total shares of a global hold pools
//} //}
////_________________________________________________________________________ ////_________________________________________________________________________
@ -32,7 +32,7 @@ package stake
//// Params defines the high level settings for staking //// Params defines the high level settings for staking
//type Params struct { //type Params struct {
//FeeDenoms []string `json:"fee_denoms"` // accepted fee denoms //FeeDenoms []string `json:"fee_denoms"` // accepted fee denoms
//ReservePoolFee sdk.Rat `json:"reserve_pool_fee"` // percent of fees which go to reserve pool //ReservePoolFee sdk.Dec `json:"reserve_pool_fee"` // percent of fees which go to reserve pool
//} //}
//func (p Params) equal(p2 Params) bool { //func (p Params) equal(p2 Params) bool {
@ -43,7 +43,7 @@ package stake
//func defaultParams() Params { //func defaultParams() Params {
//return Params{ //return Params{
//FeeDenoms: []string{"steak"}, //FeeDenoms: []string{"steak"},
//ReservePoolFee: sdk.NewRat(5, 100), //ReservePoolFee: sdk.NewDec(5, 100),
//} //}
//} //}
@ -55,8 +55,8 @@ package stake
//FeePool sdk.Coins `json:"fee_pool"` // XXX fee pool for all the fee shares which have already been distributed //FeePool sdk.Coins `json:"fee_pool"` // XXX fee pool for all the fee shares which have already been distributed
//FeeSumReceived sdk.Coins `json:"fee_sum_received"` // XXX sum of all fees received, post reserve pool `json:"fee_sum_received"` //FeeSumReceived sdk.Coins `json:"fee_sum_received"` // XXX sum of all fees received, post reserve pool `json:"fee_sum_received"`
//FeeRecent sdk.Coins `json:"fee_recent"` // XXX most recent fee collected //FeeRecent sdk.Coins `json:"fee_recent"` // XXX most recent fee collected
//FeeAdjustments []sdk.Rat `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms //FeeAdjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms
//PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // XXX last recorded bonded shares //PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // XXX last recorded bonded shares
//} //}
//func (p Pool) equal(p2 Pool) bool { //func (p Pool) equal(p2 Pool) bool {
@ -64,7 +64,7 @@ package stake
//p.FeePool.IsEqual(p2.FeePool) && //p.FeePool.IsEqual(p2.FeePool) &&
//p.FeeSumReceived.IsEqual(p2.FeeSumReceived) && //p.FeeSumReceived.IsEqual(p2.FeeSumReceived) &&
//p.FeeRecent.IsEqual(p2.FeeRecent) && //p.FeeRecent.IsEqual(p2.FeeRecent) &&
//sdk.RatsEqual(p.FeeAdjustments, p2.FeeAdjustments) && //sdk.DecsEqual(p.FeeAdjustments, p2.FeeAdjustments) &&
//p.PrevBondedShares.Equal(p2.PrevBondedShares) //p.PrevBondedShares.Equal(p2.PrevBondedShares)
//} //}
@ -75,8 +75,8 @@ package stake
//FeePool: sdk.Coins(nil), //FeePool: sdk.Coins(nil),
//FeeSumReceived: sdk.Coins(nil), //FeeSumReceived: sdk.Coins(nil),
//FeeRecent: sdk.Coins(nil), //FeeRecent: sdk.Coins(nil),
//FeeAdjustments: []sdk.Rat{sdk.ZeroRat()}, //FeeAdjustments: []sdk.Dec{sdk.ZeroDec()},
//PrevBondedShares: sdk.ZeroRat(), //PrevBondedShares: sdk.ZeroDec(),
//} //}
//} //}
@ -85,8 +85,8 @@ package stake
//// Used in calculation of fee shares, added to a queue for each block where a power change occures //// Used in calculation of fee shares, added to a queue for each block where a power change occures
//type PowerChange struct { //type PowerChange struct {
//Height int64 `json:"height"` // block height at change //Height int64 `json:"height"` // block height at change
//Power sdk.Rat `json:"power"` // total power at change //Power sdk.Dec `json:"power"` // total power at change
//PrevPower sdk.Rat `json:"prev_power"` // total power at previous height-1 //PrevPower sdk.Dec `json:"prev_power"` // total power at previous height-1
//FeesIn sdk.Coins `json:"fees_in"` // fees in at block height //FeesIn sdk.Coins `json:"fees_in"` // fees in at block height
//PrevFeePool sdk.Coins `json:"prev_fee_pool"` // total fees in at previous block height //PrevFeePool sdk.Coins `json:"prev_fee_pool"` // total fees in at previous block height
//} //}

View File

@ -33,9 +33,9 @@ func DefaultGenesisState() GenesisState {
VotingPeriod: 200, VotingPeriod: 200,
}, },
TallyingProcedure: TallyingProcedure{ TallyingProcedure: TallyingProcedure{
Threshold: sdk.NewRat(1, 2), Threshold: sdk.NewDecWithPrec(5, 1),
Veto: sdk.NewRat(1, 3), Veto: sdk.NewDecWithPrec(334, 3),
GovernancePenalty: sdk.NewRat(1, 100), GovernancePenalty: sdk.NewDecWithPrec(1, 2),
}, },
} }
} }

View File

@ -12,9 +12,9 @@ type DepositProcedure struct {
// Procedure around Tallying votes in governance // Procedure around Tallying votes in governance
type TallyingProcedure struct { type TallyingProcedure struct {
Threshold sdk.Rat `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5 Threshold sdk.Dec `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
Veto sdk.Rat `json:"veto"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3 Veto sdk.Dec `json:"veto"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
GovernancePenalty sdk.Rat `json:"governance_penalty"` // Penalty if validator does not vote GovernancePenalty sdk.Dec `json:"governance_penalty"` // Penalty if validator does not vote
} }
// Procedure around Voting in governance // Procedure around Voting in governance

View File

@ -297,19 +297,19 @@ func (status ProposalStatus) Format(s fmt.State, verb rune) {
//----------------------------------------------------------- //-----------------------------------------------------------
// Tally Results // Tally Results
type TallyResult struct { type TallyResult struct {
Yes sdk.Rat `json:"yes"` Yes sdk.Dec `json:"yes"`
Abstain sdk.Rat `json:"abstain"` Abstain sdk.Dec `json:"abstain"`
No sdk.Rat `json:"no"` No sdk.Dec `json:"no"`
NoWithVeto sdk.Rat `json:"no_with_veto"` NoWithVeto sdk.Dec `json:"no_with_veto"`
} }
// checks if two proposals are equal // checks if two proposals are equal
func EmptyTallyResult() TallyResult { func EmptyTallyResult() TallyResult {
return TallyResult{ return TallyResult{
Yes: sdk.ZeroRat(), Yes: sdk.ZeroDec(),
Abstain: sdk.ZeroRat(), Abstain: sdk.ZeroDec(),
No: sdk.ZeroRat(), No: sdk.ZeroDec(),
NoWithVeto: sdk.ZeroRat(), NoWithVeto: sdk.ZeroDec(),
} }
} }

View File

@ -7,20 +7,20 @@ import (
// validatorGovInfo used for tallying // validatorGovInfo used for tallying
type validatorGovInfo struct { type validatorGovInfo struct {
Address sdk.AccAddress // sdk.AccAddress of the validator owner Address sdk.AccAddress // sdk.AccAddress of the validator owner
Power sdk.Rat // Power of a Validator Power sdk.Dec // Power of a Validator
DelegatorShares sdk.Rat // Total outstanding delegator shares DelegatorShares sdk.Dec // Total outstanding delegator shares
Minus sdk.Rat // Minus of validator, used to compute validator's voting power Minus sdk.Dec // Minus of validator, used to compute validator's voting power
Vote VoteOption // Vote of the validator Vote VoteOption // Vote of the validator
} }
func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult, nonVoting []sdk.AccAddress) { func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult, nonVoting []sdk.AccAddress) {
results := make(map[VoteOption]sdk.Rat) results := make(map[VoteOption]sdk.Dec)
results[OptionYes] = sdk.ZeroRat() results[OptionYes] = sdk.ZeroDec()
results[OptionAbstain] = sdk.ZeroRat() results[OptionAbstain] = sdk.ZeroDec()
results[OptionNo] = sdk.ZeroRat() results[OptionNo] = sdk.ZeroDec()
results[OptionNoWithVeto] = sdk.ZeroRat() results[OptionNoWithVeto] = sdk.ZeroDec()
totalVotingPower := sdk.ZeroRat() totalVotingPower := sdk.ZeroDec()
currValidators := make(map[string]validatorGovInfo) currValidators := make(map[string]validatorGovInfo)
keeper.vs.IterateValidatorsBonded(ctx, func(index int64, validator sdk.Validator) (stop bool) { keeper.vs.IterateValidatorsBonded(ctx, func(index int64, validator sdk.Validator) (stop bool) {
@ -28,7 +28,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
Address: validator.GetOwner(), Address: validator.GetOwner(),
Power: validator.GetPower(), Power: validator.GetPower(),
DelegatorShares: validator.GetDelegatorShares(), DelegatorShares: validator.GetDelegatorShares(),
Minus: sdk.ZeroRat(), Minus: sdk.ZeroDec(),
Vote: OptionEmpty, Vote: OptionEmpty,
} }
return false return false
@ -91,7 +91,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
} }
// If no one votes, proposal fails // If no one votes, proposal fails
if totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroRat()) { if totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroDec()) {
return false, tallyResults, nonVoting return false, tallyResults, nonVoting
} }
// If more than 1/3 of voters veto, proposal fails // If more than 1/3 of voters veto, proposal fails

View File

@ -64,7 +64,7 @@ func getInitChainer(mapp *mock.App, keeper Keeper, stakeKeeper stake.Keeper) sdk
mapp.InitChainer(ctx, req) mapp.InitChainer(ctx, req)
stakeGenesis := stake.DefaultGenesisState() stakeGenesis := stake.DefaultGenesisState()
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000) stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000)
validators, err := stake.InitGenesis(ctx, stakeKeeper, stakeGenesis) validators, err := stake.InitGenesis(ctx, stakeKeeper, stakeGenesis)
if err != nil { if err != nil {

View File

@ -183,8 +183,8 @@ func (k Getter) GetUint(ctx sdk.Context, key string) (res sdk.Uint, err error) {
return return
} }
// GetRat is helper function for rat params // GetDec is helper function for decimal params
func (k Getter) GetRat(ctx sdk.Context, key string) (res sdk.Rat, err error) { func (k Getter) GetDec(ctx sdk.Context, key string) (res sdk.Dec, err error) {
store := ctx.KVStore(k.k.key) store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key)) bz := store.Get([]byte(key))
err = k.k.cdc.UnmarshalBinary(bz, &res) err = k.k.cdc.UnmarshalBinary(bz, &res)
@ -301,8 +301,8 @@ func (k Getter) GetUintWithDefault(ctx sdk.Context, key string, def sdk.Uint) (r
return return
} }
// GetRatWithDefault is helper function for sdk.Rat params with default value // GetDecWithDefault is helper function for sdk.Dec params with default value
func (k Getter) GetRatWithDefault(ctx sdk.Context, key string, def sdk.Rat) (res sdk.Rat) { func (k Getter) GetDecWithDefault(ctx sdk.Context, key string, def sdk.Dec) (res sdk.Dec) {
store := ctx.KVStore(k.k.key) store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key)) bz := store.Get([]byte(key))
if bz == nil { if bz == nil {
@ -397,8 +397,8 @@ func (k Setter) SetUint(ctx sdk.Context, key string, param sdk.Uint) {
} }
} }
// SetRat is helper function for rat params // SetDec is helper function for decimal params
func (k Setter) SetRat(ctx sdk.Context, key string, param sdk.Rat) { func (k Setter) SetDec(ctx sdk.Context, key string, param sdk.Dec) {
if err := k.k.set(ctx, key, param); err != nil { if err := k.k.set(ctx, key, param); err != nil {
panic(err) panic(err)
} }

View File

@ -94,7 +94,7 @@ func TestGetter(t *testing.T) {
{"uint64", uint64(1)}, {"uint64", uint64(1)},
{"int", sdk.NewInt(1)}, {"int", sdk.NewInt(1)},
{"uint", sdk.NewUint(1)}, {"uint", sdk.NewUint(1)},
{"rat", sdk.NewRat(1)}, {"rat", sdk.NewDec(1)},
} }
assert.NotPanics(t, func() { s.SetString(ctx, kvs[0].key, "test") }) assert.NotPanics(t, func() { s.SetString(ctx, kvs[0].key, "test") })
@ -107,7 +107,7 @@ func TestGetter(t *testing.T) {
assert.NotPanics(t, func() { s.SetUint64(ctx, kvs[7].key, uint64(1)) }) assert.NotPanics(t, func() { s.SetUint64(ctx, kvs[7].key, uint64(1)) })
assert.NotPanics(t, func() { s.SetInt(ctx, kvs[8].key, sdk.NewInt(1)) }) assert.NotPanics(t, func() { s.SetInt(ctx, kvs[8].key, sdk.NewInt(1)) })
assert.NotPanics(t, func() { s.SetUint(ctx, kvs[9].key, sdk.NewUint(1)) }) assert.NotPanics(t, func() { s.SetUint(ctx, kvs[9].key, sdk.NewUint(1)) })
assert.NotPanics(t, func() { s.SetRat(ctx, kvs[10].key, sdk.NewRat(1)) }) assert.NotPanics(t, func() { s.SetDec(ctx, kvs[10].key, sdk.NewDec(1)) })
var res interface{} var res interface{}
var err error var err error
@ -263,18 +263,18 @@ func TestGetter(t *testing.T) {
assert.Equal(t, def9, res) assert.Equal(t, def9, res)
// Rat // Rat
def10 := sdk.NewRat(0) def10 := sdk.NewDec(0)
res, err = g.GetRat(ctx, kvs[10].key) res, err = g.GetDec(ctx, kvs[10].key)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, kvs[10].param, res) assert.Equal(t, kvs[10].param, res)
_, err = g.GetRat(ctx, "invalid") _, err = g.GetDec(ctx, "invalid")
assert.NotNil(t, err) assert.NotNil(t, err)
res = g.GetRatWithDefault(ctx, kvs[10].key, def10) res = g.GetDecWithDefault(ctx, kvs[10].key, def10)
assert.Equal(t, kvs[10].param, res) assert.Equal(t, kvs[10].param, res)
res = g.GetRatWithDefault(ctx, "invalid", def10) res = g.GetDecWithDefault(ctx, "invalid", def10)
assert.Equal(t, def10, res) assert.Equal(t, def10, res)
} }

View File

@ -58,7 +58,7 @@ func getInitChainer(mapp *mock.App, keeper stake.Keeper) sdk.InitChainer {
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
mapp.InitChainer(ctx, req) mapp.InitChainer(ctx, req)
stakeGenesis := stake.DefaultGenesisState() stakeGenesis := stake.DefaultGenesisState()
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000) stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000)
validators, err := stake.InitGenesis(ctx, keeper, stakeGenesis) validators, err := stake.InitGenesis(ctx, keeper, stakeGenesis)
if err != nil { if err != nil {
panic(err) panic(err)
@ -109,7 +109,7 @@ func TestSlashingMsgs(t *testing.T) {
validator := checkValidator(t, mapp, stakeKeeper, addr1, true) validator := checkValidator(t, mapp, stakeKeeper, addr1, true)
require.Equal(t, addr1, validator.Owner) require.Equal(t, addr1, validator.Owner)
require.Equal(t, sdk.Bonded, validator.Status) require.Equal(t, sdk.Bonded, validator.Status)
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens())) require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens()))
unrevokeMsg := MsgUnrevoke{ValidatorAddr: sdk.AccAddress(validator.PubKey.Address())} unrevokeMsg := MsgUnrevoke{ValidatorAddr: sdk.AccAddress(validator.PubKey.Address())}
// no signing info yet // no signing info yet

View File

@ -20,7 +20,7 @@ func TestCannotUnrevokeUnlessRevoked(t *testing.T) {
require.True(t, got.IsOK()) require.True(t, got.IsOK())
stake.EndBlocker(ctx, sk) stake.EndBlocker(ctx, sk)
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
// assert non-revoked validator can't be unrevoked // assert non-revoked validator can't be unrevoked
got = slh(ctx, NewMsgUnrevoke(addr)) got = slh(ctx, NewMsgUnrevoke(addr))

View File

@ -31,7 +31,7 @@ func TestHandleDoubleSign(t *testing.T) {
validatorUpdates := stake.EndBlocker(ctx, sk) validatorUpdates := stake.EndBlocker(ctx, sk)
keeper.AddValidators(ctx, validatorUpdates) keeper.AddValidators(ctx, validatorUpdates)
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
// handle a signature to set signing info // handle a signature to set signing info
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true)
@ -44,12 +44,12 @@ func TestHandleDoubleSign(t *testing.T) {
// unrevoke to measure power // unrevoke to measure power
sk.Unrevoke(ctx, val) sk.Unrevoke(ctx, val)
// power should be reduced // power should be reduced
require.Equal(t, sdk.NewRatFromInt(amt).Mul(sdk.NewRat(19).Quo(sdk.NewRat(20))), sk.Validator(ctx, addr).GetPower()) require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower())
ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.MaxEvidenceAge(ctx))}) ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.MaxEvidenceAge(ctx))})
// double sign past max age // double sign past max age
keeper.handleDoubleSign(ctx, val, 0, time.Unix(0, 0), amtInt) keeper.handleDoubleSign(ctx, val, 0, time.Unix(0, 0), amtInt)
require.Equal(t, sdk.NewRatFromInt(amt).Mul(sdk.NewRat(19).Quo(sdk.NewRat(20))), sk.Validator(ctx, addr).GetPower()) require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower())
} }
// Test a validator through uptime, downtime, revocation, // Test a validator through uptime, downtime, revocation,
@ -67,7 +67,7 @@ func TestHandleAbsentValidator(t *testing.T) {
validatorUpdates := stake.EndBlocker(ctx, sk) validatorUpdates := stake.EndBlocker(ctx, sk)
keeper.AddValidators(ctx, validatorUpdates) keeper.AddValidators(ctx, validatorUpdates)
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address())) info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
require.False(t, found) require.False(t, found)
require.Equal(t, int64(0), info.StartHeight) require.Equal(t, int64(0), info.StartHeight)
@ -131,7 +131,7 @@ func TestHandleAbsentValidator(t *testing.T) {
// validator should have been slashed // validator should have been slashed
pool = sk.GetPool(ctx) pool = sk.GetPool(ctx)
slashAmt := sdk.NewRat(amtInt).Mul(keeper.SlashFractionDowntime(ctx)).RoundInt64() slashAmt := sdk.NewDec(amtInt).Mul(keeper.SlashFractionDowntime(ctx)).RoundInt64()
require.Equal(t, int64(amtInt)-slashAmt, pool.BondedTokens.RoundInt64()) require.Equal(t, int64(amtInt)-slashAmt, pool.BondedTokens.RoundInt64())
// validator start height should have been changed // validator start height should have been changed
@ -177,7 +177,7 @@ func TestHandleNewValidator(t *testing.T) {
validatorUpdates := stake.EndBlocker(ctx, sk) validatorUpdates := stake.EndBlocker(ctx, sk)
keeper.AddValidators(ctx, validatorUpdates) keeper.AddValidators(ctx, validatorUpdates)
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.SubRaw(amt)}}) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.SubRaw(amt)}})
require.Equal(t, sdk.NewRat(amt), sk.Validator(ctx, addr).GetPower()) require.Equal(t, sdk.NewDec(amt), sk.Validator(ctx, addr).GetPower())
// 1000 first blocks not a validator // 1000 first blocks not a validator
ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 1) ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 1)

View File

@ -30,9 +30,9 @@ func (k Keeper) SignedBlocksWindow(ctx sdk.Context) int64 {
// Downtime slashing thershold - default 50% // Downtime slashing thershold - default 50%
func (k Keeper) MinSignedPerWindow(ctx sdk.Context) int64 { func (k Keeper) MinSignedPerWindow(ctx sdk.Context) int64 {
minSignedPerWindow := k.params.GetRatWithDefault(ctx, MinSignedPerWindowKey, defaultMinSignedPerWindow) minSignedPerWindow := k.params.GetDecWithDefault(ctx, MinSignedPerWindowKey, defaultMinSignedPerWindow)
signedBlocksWindow := k.SignedBlocksWindow(ctx) signedBlocksWindow := k.SignedBlocksWindow(ctx)
return sdk.NewRat(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64() return sdk.NewDec(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64()
} }
// Double-sign unbond duration // Double-sign unbond duration
@ -46,13 +46,13 @@ func (k Keeper) DowntimeUnbondDuration(ctx sdk.Context) time.Duration {
} }
// SlashFractionDoubleSign - currently default 5% // SlashFractionDoubleSign - currently default 5%
func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) sdk.Rat { func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) sdk.Dec {
return k.params.GetRatWithDefault(ctx, SlashFractionDoubleSignKey, defaultSlashFractionDoubleSign) return k.params.GetDecWithDefault(ctx, SlashFractionDoubleSignKey, defaultSlashFractionDoubleSign)
} }
// SlashFractionDowntime - currently default 1% // SlashFractionDowntime - currently default 1%
func (k Keeper) SlashFractionDowntime(ctx sdk.Context) sdk.Rat { func (k Keeper) SlashFractionDowntime(ctx sdk.Context) sdk.Dec {
return k.params.GetRatWithDefault(ctx, SlashFractionDowntimeKey, defaultSlashFractionDowntime) return k.params.GetDecWithDefault(ctx, SlashFractionDowntimeKey, defaultSlashFractionDowntime)
} }
// declared as var because of keeper_test.go // declared as var because of keeper_test.go
@ -72,9 +72,9 @@ var (
// TODO Temporarily set to 10 minutes for testnets // TODO Temporarily set to 10 minutes for testnets
defaultDowntimeUnbondDuration int64 = 60 * 10 defaultDowntimeUnbondDuration int64 = 60 * 10
defaultMinSignedPerWindow = sdk.NewRat(1, 2) defaultMinSignedPerWindow = sdk.NewDecWithPrec(5, 1)
defaultSlashFractionDoubleSign = sdk.NewRat(1).Quo(sdk.NewRat(20)) defaultSlashFractionDoubleSign = sdk.NewDec(1).Quo(sdk.NewDec(20))
defaultSlashFractionDowntime = sdk.NewRat(1).Quo(sdk.NewRat(100)) defaultSlashFractionDowntime = sdk.NewDec(1).Quo(sdk.NewDec(100))
) )

View File

@ -69,7 +69,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para
sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace) sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace)
genesis := stake.DefaultGenesisState() genesis := stake.DefaultGenesisState()
genesis.Pool.LooseTokens = sdk.NewRat(initCoins.MulRaw(int64(len(addrs))).Int64()) genesis.Pool.LooseTokens = sdk.NewDec(initCoins.MulRaw(int64(len(addrs))).Int64())
_, err = stake.InitGenesis(ctx, sk, genesis) _, err = stake.InitGenesis(ctx, sk, genesis)
require.Nil(t, err) require.Nil(t, err)

View File

@ -22,7 +22,7 @@ func TestBeginBlocker(t *testing.T) {
validatorUpdates := stake.EndBlocker(ctx, sk) validatorUpdates := stake.EndBlocker(ctx, sk)
keeper.AddValidators(ctx, validatorUpdates) keeper.AddValidators(ctx, validatorUpdates)
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
val := abci.Validator{ val := abci.Validator{
Address: pk.Address(), Address: pk.Address(),

View File

@ -63,7 +63,7 @@ func getInitChainer(mapp *mock.App, keeper Keeper) sdk.InitChainer {
mapp.InitChainer(ctx, req) mapp.InitChainer(ctx, req)
stakeGenesis := DefaultGenesisState() stakeGenesis := DefaultGenesisState()
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000) stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000)
validators, err := InitGenesis(ctx, keeper, stakeGenesis) validators, err := InitGenesis(ctx, keeper, stakeGenesis)
if err != nil { if err != nil {
@ -90,14 +90,14 @@ func checkValidator(t *testing.T, mapp *mock.App, keeper Keeper,
func checkDelegation( func checkDelegation(
t *testing.T, mapp *mock.App, keeper Keeper, delegatorAddr, t *testing.T, mapp *mock.App, keeper Keeper, delegatorAddr,
validatorAddr sdk.AccAddress, expFound bool, expShares sdk.Rat, validatorAddr sdk.AccAddress, expFound bool, expShares sdk.Dec,
) { ) {
ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{}) ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{})
delegation, found := keeper.GetDelegation(ctxCheck, delegatorAddr, validatorAddr) delegation, found := keeper.GetDelegation(ctxCheck, delegatorAddr, validatorAddr)
if expFound { if expFound {
require.True(t, found) require.True(t, found)
require.True(sdk.RatEq(t, expShares, delegation.Shares)) require.True(sdk.DecEq(t, expShares, delegation.Shares))
return return
} }
@ -138,7 +138,7 @@ func TestStakeMsgs(t *testing.T) {
validator := checkValidator(t, mApp, keeper, addr1, true) validator := checkValidator(t, mApp, keeper, addr1, true)
require.Equal(t, addr1, validator.Owner) require.Equal(t, addr1, validator.Owner)
require.Equal(t, sdk.Bonded, validator.Status) require.Equal(t, sdk.Bonded, validator.Status)
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens())) require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens()))
// addr1 create validator on behalf of addr2 // addr1 create validator on behalf of addr2
createValidatorMsgOnBehalfOf := NewMsgCreateValidatorOnBehalfOf(addr1, addr2, priv2.PubKey(), bondCoin, description) createValidatorMsgOnBehalfOf := NewMsgCreateValidatorOnBehalfOf(addr1, addr2, priv2.PubKey(), bondCoin, description)
@ -150,10 +150,10 @@ func TestStakeMsgs(t *testing.T) {
validator = checkValidator(t, mApp, keeper, addr2, true) validator = checkValidator(t, mApp, keeper, addr2, true)
require.Equal(t, addr2, validator.Owner) require.Equal(t, addr2, validator.Owner)
require.Equal(t, sdk.Bonded, validator.Status) require.Equal(t, sdk.Bonded, validator.Status)
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) require.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
// check the bond that should have been created as well // check the bond that should have been created as well
checkDelegation(t, mApp, keeper, addr1, addr1, true, sdk.NewRat(10)) checkDelegation(t, mApp, keeper, addr1, addr1, true, sdk.NewDec(10))
// edit the validator // edit the validator
description = NewDescription("bar_moniker", "", "", "") description = NewDescription("bar_moniker", "", "", "")
@ -169,14 +169,14 @@ func TestStakeMsgs(t *testing.T) {
mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{delegateMsg}, []int64{1}, []int64{1}, true, priv2) mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{delegateMsg}, []int64{1}, []int64{1}, true, priv2)
mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)}) mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)})
checkDelegation(t, mApp, keeper, addr2, addr1, true, sdk.NewRat(10)) checkDelegation(t, mApp, keeper, addr2, addr1, true, sdk.NewDec(10))
// begin unbonding // begin unbonding
beginUnbondingMsg := NewMsgBeginUnbonding(addr2, addr1, sdk.NewRat(10)) beginUnbondingMsg := NewMsgBeginUnbonding(addr2, addr1, sdk.NewDec(10))
mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{beginUnbondingMsg}, []int64{1}, []int64{2}, true, priv2) mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{beginUnbondingMsg}, []int64{1}, []int64{2}, true, priv2)
// delegation should exist anymore // delegation should exist anymore
checkDelegation(t, mApp, keeper, addr2, addr1, false, sdk.Rat{}) checkDelegation(t, mApp, keeper, addr2, addr1, false, sdk.Dec{})
// balance should be the same because bonding not yet complete // balance should be the same because bonding not yet complete
mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)}) mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)})

View File

@ -239,27 +239,27 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command {
func getShares( func getShares(
storeName string, cdc *wire.Codec, sharesAmountStr, storeName string, cdc *wire.Codec, sharesAmountStr,
sharesPercentStr string, delegatorAddr, validatorAddr sdk.AccAddress, sharesPercentStr string, delegatorAddr, validatorAddr sdk.AccAddress,
) (sharesAmount sdk.Rat, err error) { ) (sharesAmount sdk.Dec, err error) {
switch { switch {
case sharesAmountStr != "" && sharesPercentStr != "": case sharesAmountStr != "" && sharesPercentStr != "":
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both") return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
case sharesAmountStr == "" && sharesPercentStr == "": case sharesAmountStr == "" && sharesPercentStr == "":
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both") return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
case sharesAmountStr != "": case sharesAmountStr != "":
sharesAmount, err = sdk.NewRatFromDecimal(sharesAmountStr, types.MaxBondDenominatorPrecision) sharesAmount, err = sdk.NewDecFromStr(sharesAmountStr)
if err != nil { if err != nil {
return sharesAmount, err return sharesAmount, err
} }
if !sharesAmount.GT(sdk.ZeroRat()) { if !sharesAmount.GT(sdk.ZeroDec()) {
return sharesAmount, errors.Errorf("shares amount must be positive number (ex. 123, 1.23456789)") return sharesAmount, errors.Errorf("shares amount must be positive number (ex. 123, 1.23456789)")
} }
case sharesPercentStr != "": case sharesPercentStr != "":
var sharesPercent sdk.Rat var sharesPercent sdk.Dec
sharesPercent, err = sdk.NewRatFromDecimal(sharesPercentStr, types.MaxBondDenominatorPrecision) sharesPercent, err = sdk.NewDecFromStr(sharesPercentStr)
if err != nil { if err != nil {
return sharesAmount, err return sharesAmount, err
} }
if !sharesPercent.GT(sdk.ZeroRat()) || !sharesPercent.LTE(sdk.OneRat()) { if !sharesPercent.GT(sdk.ZeroDec()) || !sharesPercent.LTE(sdk.OneDec()) {
return sharesAmount, errors.Errorf("shares percent must be >0 and <=1 (ex. 0.01, 0.75, 1)") return sharesAmount, errors.Errorf("shares percent must be >0 and <=1 (ex. 0.01, 0.75, 1)")
} }

View File

@ -347,7 +347,7 @@ func delegationHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handle
DelegatorAddr: delegation.DelegatorAddr, DelegatorAddr: delegation.DelegatorAddr,
ValidatorAddr: delegation.ValidatorAddr, ValidatorAddr: delegation.ValidatorAddr,
Height: delegation.Height, Height: delegation.Height,
Shares: delegation.Shares.FloatString(), Shares: delegation.Shares.String(),
} }
output, err := cdc.MarshalJSON(outputDelegation) output, err := cdc.MarshalJSON(outputDelegation)

View File

@ -12,7 +12,6 @@ import (
"github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/wire"
authcliCtx "github.com/cosmos/cosmos-sdk/x/auth/client/context" authcliCtx "github.com/cosmos/cosmos-sdk/x/auth/client/context"
"github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/x/stake"
"github.com/cosmos/cosmos-sdk/x/stake/types"
"github.com/gorilla/mux" "github.com/gorilla/mux"
@ -160,7 +159,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex
return return
} }
shares, err := sdk.NewRatFromDecimal(msg.SharesAmount, types.MaxBondDenominatorPrecision) shares, err := sdk.NewDecFromStr(msg.SharesAmount)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error()))) w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error())))
@ -234,7 +233,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex
return return
} }
shares, err := sdk.NewRatFromDecimal(msg.SharesAmount, types.MaxBondDenominatorPrecision) shares, err := sdk.NewDecFromStr(msg.SharesAmount)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error()))) w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error())))

View File

@ -76,7 +76,7 @@ func getDelegatorDelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegat
DelegatorAddr: delegation.DelegatorAddr, DelegatorAddr: delegation.DelegatorAddr,
ValidatorAddr: delegation.ValidatorAddr, ValidatorAddr: delegation.ValidatorAddr,
Height: delegation.Height, Height: delegation.Height,
Shares: delegation.Shares.FloatString(), Shares: delegation.Shares.String(),
} }
return outputDelegation, http.StatusOK, "", nil return outputDelegation, http.StatusOK, "", nil

View File

@ -17,7 +17,7 @@ func TestInitGenesis(t *testing.T) {
ctx, _, keeper := keep.CreateTestInput(t, false, 1000) ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
pool := keeper.GetPool(ctx) pool := keeper.GetPool(ctx)
pool.BondedTokens = sdk.NewRat(2) pool.BondedTokens = sdk.NewDec(2)
params := keeper.GetParams(ctx) params := keeper.GetParams(ctx)
var delegations []Delegation var delegations []Delegation
@ -32,11 +32,11 @@ func TestInitGenesis(t *testing.T) {
// initialize the validators // initialize the validators
validators[0].Status = sdk.Bonded validators[0].Status = sdk.Bonded
validators[0].Tokens = sdk.OneRat() validators[0].Tokens = sdk.OneDec()
validators[0].DelegatorShares = sdk.OneRat() validators[0].DelegatorShares = sdk.OneDec()
validators[1].Status = sdk.Bonded validators[1].Status = sdk.Bonded
validators[1].Tokens = sdk.OneRat() validators[1].Tokens = sdk.OneDec()
validators[1].DelegatorShares = sdk.OneRat() validators[1].DelegatorShares = sdk.OneDec()
genesisState = types.NewGenesisState(pool, params, validators, delegations) genesisState = types.NewGenesisState(pool, params, validators, delegations)
vals, err := InitGenesis(ctx, keeper, genesisState) vals, err := InitGenesis(ctx, keeper, genesisState)
@ -69,7 +69,7 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) {
// Assigning 2 to the first 100 vals, 1 to the rest // Assigning 2 to the first 100 vals, 1 to the rest
pool := keeper.GetPool(ctx) pool := keeper.GetPool(ctx)
pool.BondedTokens = sdk.NewRat(int64(200 + (size - 100))) pool.BondedTokens = sdk.NewDec(int64(200 + (size - 100)))
params := keeper.GetParams(ctx) params := keeper.GetParams(ctx)
delegations := []Delegation{} delegations := []Delegation{}
@ -80,11 +80,11 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) {
validators[i].Status = sdk.Bonded validators[i].Status = sdk.Bonded
if i < 100 { if i < 100 {
validators[i].Tokens = sdk.NewRat(2) validators[i].Tokens = sdk.NewDec(2)
validators[i].DelegatorShares = sdk.NewRat(2) validators[i].DelegatorShares = sdk.NewDec(2)
} else { } else {
validators[i].Tokens = sdk.OneRat() validators[i].Tokens = sdk.OneDec()
validators[i].DelegatorShares = sdk.OneRat() validators[i].DelegatorShares = sdk.OneDec()
} }
} }

View File

@ -81,7 +81,7 @@ func TestValidatorByPowerIndex(t *testing.T) {
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got) require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
// slash and revoke the first validator // slash and revoke the first validator
keeper.Slash(ctx, keep.PKs[0], 0, initBond, sdk.NewRat(1, 2)) keeper.Slash(ctx, keep.PKs[0], 0, initBond, sdk.NewDecWithPrec(5, 1))
keeper.Revoke(ctx, keep.PKs[0]) keeper.Revoke(ctx, keep.PKs[0])
validator, found = keeper.GetValidator(ctx, validatorAddr) validator, found = keeper.GetValidator(ctx, validatorAddr)
require.True(t, found) require.True(t, found)
@ -110,7 +110,7 @@ func TestValidatorByPowerIndex(t *testing.T) {
require.Equal(t, power2, power3) require.Equal(t, power2, power3)
// unbond self-delegation // unbond self-delegation
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(1000000)) msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(1000000))
msgCompleteUnbonding := NewMsgCompleteUnbonding(validatorAddr, validatorAddr) msgCompleteUnbonding := NewMsgCompleteUnbonding(validatorAddr, validatorAddr)
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got) require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
@ -138,8 +138,8 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) {
assert.Equal(t, sdk.Bonded, validator.Status) assert.Equal(t, sdk.Bonded, validator.Status)
assert.Equal(t, addr1, validator.Owner) assert.Equal(t, addr1, validator.Owner)
assert.Equal(t, pk1, validator.PubKey) assert.Equal(t, pk1, validator.PubKey)
assert.Equal(t, sdk.NewRat(10), validator.BondedTokens()) assert.Equal(t, sdk.NewDec(10), validator.BondedTokens())
assert.Equal(t, sdk.NewRat(10), validator.DelegatorShares) assert.Equal(t, sdk.NewDec(10), validator.DelegatorShares)
assert.Equal(t, Description{}, validator.Description) assert.Equal(t, Description{}, validator.Description)
// two validators can't have the same owner address // two validators can't have the same owner address
@ -162,8 +162,8 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) {
assert.Equal(t, sdk.Bonded, validator.Status) assert.Equal(t, sdk.Bonded, validator.Status)
assert.Equal(t, addr2, validator.Owner) assert.Equal(t, addr2, validator.Owner)
assert.Equal(t, pk2, validator.PubKey) assert.Equal(t, pk2, validator.PubKey)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
assert.Equal(t, Description{}, validator.Description) assert.Equal(t, Description{}, validator.Description)
} }
@ -182,8 +182,8 @@ func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) {
assert.Equal(t, sdk.Bonded, validator.Status) assert.Equal(t, sdk.Bonded, validator.Status)
assert.Equal(t, validatorAddr, validator.Owner) assert.Equal(t, validatorAddr, validator.Owner)
assert.Equal(t, pk, validator.PubKey) assert.Equal(t, pk, validator.PubKey)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
assert.Equal(t, Description{}, validator.Description) assert.Equal(t, Description{}, validator.Description)
// one validator cannot be created twice even from different delegator // one validator cannot be created twice even from different delegator
@ -221,7 +221,7 @@ func TestIncrementsMsgDelegate(t *testing.T) {
pool := keeper.GetPool(ctx) pool := keeper.GetPool(ctx)
exRate := validator.DelegatorShareExRate() exRate := validator.DelegatorShareExRate()
require.True(t, exRate.Equal(sdk.OneRat()), "expected exRate 1 got %v", exRate) require.True(t, exRate.Equal(sdk.OneDec()), "expected exRate 1 got %v", exRate)
require.Equal(t, bondAmount, pool.BondedTokens.RoundInt64()) require.Equal(t, bondAmount, pool.BondedTokens.RoundInt64())
// just send the same msgbond multiple times // just send the same msgbond multiple times
@ -240,7 +240,7 @@ func TestIncrementsMsgDelegate(t *testing.T) {
require.True(t, found) require.True(t, found)
exRate := validator.DelegatorShareExRate() exRate := validator.DelegatorShareExRate()
require.True(t, exRate.Equal(sdk.OneRat()), "expected exRate 1 got %v, i = %v", exRate, i) require.True(t, exRate.Equal(sdk.OneDec()), "expected exRate 1 got %v, i = %v", exRate, i)
expBond := int64(i+1) * bondAmount expBond := int64(i+1) * bondAmount
expDelegatorShares := int64(i+2) * bondAmount // (1 self delegation) expDelegatorShares := int64(i+2) * bondAmount // (1 self delegation)
@ -295,7 +295,7 @@ func TestIncrementsMsgUnbond(t *testing.T) {
// just send the same msgUnbond multiple times // just send the same msgUnbond multiple times
// TODO use decimals here // TODO use decimals here
unbondShares := sdk.NewRat(10) unbondShares := sdk.NewDec(10)
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares) msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr) msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
numUnbonds := 5 numUnbonds := 5
@ -339,7 +339,7 @@ func TestIncrementsMsgUnbond(t *testing.T) {
initBond, initBond,
} }
for _, c := range errorCases { for _, c := range errorCases {
unbondShares := sdk.NewRat(int64(c)) unbondShares := sdk.NewDec(int64(c))
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares) msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.False(t, got.IsOK(), "expected unbond msg to fail") require.False(t, got.IsOK(), "expected unbond msg to fail")
@ -348,14 +348,14 @@ func TestIncrementsMsgUnbond(t *testing.T) {
leftBonded := initBond - int64(numUnbonds)*unbondShares.RoundInt64() leftBonded := initBond - int64(numUnbonds)*unbondShares.RoundInt64()
// should be unable to unbond one more than we have // should be unable to unbond one more than we have
unbondShares = sdk.NewRat(leftBonded + 1) unbondShares = sdk.NewDec(leftBonded + 1)
msgBeginUnbonding = NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares) msgBeginUnbonding = NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.False(t, got.IsOK(), require.False(t, got.IsOK(),
"got: %v\nmsgUnbond: %v\nshares: %v\nleftBonded: %v\n", got, msgBeginUnbonding, unbondShares.String(), leftBonded) "got: %v\nmsgUnbond: %v\nshares: %v\nleftBonded: %v\n", got, msgBeginUnbonding, unbondShares.String(), leftBonded)
// should be able to unbond just what we have // should be able to unbond just what we have
unbondShares = sdk.NewRat(leftBonded) unbondShares = sdk.NewDec(leftBonded)
msgBeginUnbonding = NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares) msgBeginUnbonding = NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), require.True(t, got.IsOK(),
@ -391,7 +391,7 @@ func TestMultipleMsgCreateValidator(t *testing.T) {
for i, validatorAddr := range validatorAddrs { for i, validatorAddr := range validatorAddrs {
_, found := keeper.GetValidator(ctx, validatorAddr) _, found := keeper.GetValidator(ctx, validatorAddr)
require.True(t, found) require.True(t, found)
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddrs[i], validatorAddr, sdk.NewRat(10)) // remove delegation msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddrs[i], validatorAddr, sdk.NewDec(10)) // remove delegation
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddrs[i], validatorAddr) msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddrs[i], validatorAddr)
got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
@ -436,7 +436,7 @@ func TestMultipleMsgDelegate(t *testing.T) {
// unbond them all // unbond them all
for i, delegatorAddr := range delegatorAddrs { for i, delegatorAddr := range delegatorAddrs {
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewRat(10)) msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewDec(10))
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr) msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
@ -467,7 +467,7 @@ func TestRevokeValidator(t *testing.T) {
validator, _ := keeper.GetValidator(ctx, validatorAddr) validator, _ := keeper.GetValidator(ctx, validatorAddr)
// unbond the validators bond portion // unbond the validators bond portion
msgBeginUnbondingValidator := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(10)) msgBeginUnbondingValidator := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(10))
msgCompleteUnbondingValidator := NewMsgCompleteUnbonding(validatorAddr, validatorAddr) msgCompleteUnbondingValidator := NewMsgCompleteUnbonding(validatorAddr, validatorAddr)
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper)
require.True(t, got.IsOK(), "expected no error") require.True(t, got.IsOK(), "expected no error")
@ -483,7 +483,7 @@ func TestRevokeValidator(t *testing.T) {
require.False(t, got.IsOK(), "expected error, got %v", got) require.False(t, got.IsOK(), "expected error, got %v", got)
// test that the delegator can still withdraw their bonds // test that the delegator can still withdraw their bonds
msgBeginUnbondingDelegator := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewRat(10)) msgBeginUnbondingDelegator := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewDec(10))
msgCompleteUnbondingDelegator := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr) msgCompleteUnbondingDelegator := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingDelegator, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingDelegator, keeper)
require.True(t, got.IsOK(), "expected no error") require.True(t, got.IsOK(), "expected no error")
@ -510,7 +510,7 @@ func TestUnbondingPeriod(t *testing.T) {
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
// begin unbonding // begin unbonding
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(10)) msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(10))
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected no error") require.True(t, got.IsOK(), "expected no error")
@ -565,7 +565,7 @@ func TestRedelegationPeriod(t *testing.T) {
bal1 := AccMapper.GetAccount(ctx, validatorAddr).GetCoins() bal1 := AccMapper.GetAccount(ctx, validatorAddr).GetCoins()
// begin redelegate // begin redelegate
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewRat(10)) msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewDec(10))
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
require.True(t, got.IsOK(), "expected no error, %v", got) require.True(t, got.IsOK(), "expected no error, %v", got)
@ -617,12 +617,12 @@ func TestTransitiveRedelegation(t *testing.T) {
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
// begin redelegate // begin redelegate
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewRat(10)) msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewDec(10))
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
require.True(t, got.IsOK(), "expected no error, %v", got) require.True(t, got.IsOK(), "expected no error, %v", got)
// cannot redelegation to next validator while first delegation exists // cannot redelegation to next validator while first delegation exists
msgBeginRedelegate = NewMsgBeginRedelegate(validatorAddr, validatorAddr2, validatorAddr3, sdk.NewRat(10)) msgBeginRedelegate = NewMsgBeginRedelegate(validatorAddr, validatorAddr2, validatorAddr3, sdk.NewDec(10))
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
require.True(t, !got.IsOK(), "expected an error, msg: %v", msgBeginRedelegate) require.True(t, !got.IsOK(), "expected an error, msg: %v", msgBeginRedelegate)
@ -663,7 +663,7 @@ func TestUnbondingWhenExcessValidators(t *testing.T) {
require.Equal(t, 2, len(keeper.GetValidatorsBonded(ctx))) require.Equal(t, 2, len(keeper.GetValidatorsBonded(ctx)))
// unbond the valdator-2 // unbond the valdator-2
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewRat(30)) msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewDec(30))
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding") require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
@ -785,7 +785,7 @@ func TestCliffValidator(t *testing.T) {
require.Equal(t, validatorAddr2.Bytes(), cliffVal) require.Equal(t, validatorAddr2.Bytes(), cliffVal)
// unbond valdator-2 // unbond valdator-2
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewRat(30)) msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewDec(30))
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding") require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
@ -798,7 +798,7 @@ func TestCliffValidator(t *testing.T) {
require.Equal(t, validatorAddr3.Bytes(), cliffVal) require.Equal(t, validatorAddr3.Bytes(), cliffVal)
// unbond valdator-1 // unbond valdator-1
msgBeginUnbonding = NewMsgBeginUnbonding(validatorAddr1, validatorAddr1, sdk.NewRat(50)) msgBeginUnbonding = NewMsgBeginUnbonding(validatorAddr1, validatorAddr1, sdk.NewDec(50))
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding") require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
@ -832,22 +832,22 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
ctx = ctx.WithBlockHeight(1) ctx = ctx.WithBlockHeight(1)
// begin unbonding 4 stake // begin unbonding 4 stake
msgBeginUnbonding := NewMsgBeginUnbonding(del, valA, sdk.NewRat(4)) msgBeginUnbonding := NewMsgBeginUnbonding(del, valA, sdk.NewDec(4))
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding") require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
// begin redelegate 6 stake // begin redelegate 6 stake
msgBeginRedelegate := NewMsgBeginRedelegate(del, valA, valB, sdk.NewRat(6)) msgBeginRedelegate := NewMsgBeginRedelegate(del, valA, valB, sdk.NewDec(6))
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
require.True(t, got.IsOK(), "expected no error on runMsgBeginRedelegate") require.True(t, got.IsOK(), "expected no error on runMsgBeginRedelegate")
// destination delegation should have 6 shares // destination delegation should have 6 shares
delegation, found := keeper.GetDelegation(ctx, del, valB) delegation, found := keeper.GetDelegation(ctx, del, valB)
require.True(t, found) require.True(t, found)
require.Equal(t, sdk.NewRat(6), delegation.Shares) require.Equal(t, sdk.NewDec(6), delegation.Shares)
// slash the validator by half // slash the validator by half
keeper.Slash(ctx, keep.PKs[0], 0, 20, sdk.NewRat(1, 2)) keeper.Slash(ctx, keep.PKs[0], 0, 20, sdk.NewDecWithPrec(5, 1))
// unbonding delegation should have been slashed by half // unbonding delegation should have been slashed by half
unbonding, found := keeper.GetUnbondingDelegation(ctx, del, valA) unbonding, found := keeper.GetUnbondingDelegation(ctx, del, valA)
@ -862,16 +862,16 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
// destination delegation should have been slashed by half // destination delegation should have been slashed by half
delegation, found = keeper.GetDelegation(ctx, del, valB) delegation, found = keeper.GetDelegation(ctx, del, valB)
require.True(t, found) require.True(t, found)
require.Equal(t, sdk.NewRat(3), delegation.Shares) require.Equal(t, sdk.NewDec(3), delegation.Shares)
// validator power should have been reduced by half // validator power should have been reduced by half
validator, found := keeper.GetValidator(ctx, valA) validator, found := keeper.GetValidator(ctx, valA)
require.True(t, found) require.True(t, found)
require.Equal(t, sdk.NewRat(5), validator.GetPower()) require.Equal(t, sdk.NewDec(5), validator.GetPower())
// slash the validator for an infraction committed after the unbonding and redelegation begin // slash the validator for an infraction committed after the unbonding and redelegation begin
ctx = ctx.WithBlockHeight(3) ctx = ctx.WithBlockHeight(3)
keeper.Slash(ctx, keep.PKs[0], 2, 10, sdk.NewRat(1, 2)) keeper.Slash(ctx, keep.PKs[0], 2, 10, sdk.NewDecWithPrec(5, 1))
// unbonding delegation should be unchanged // unbonding delegation should be unchanged
unbonding, found = keeper.GetUnbondingDelegation(ctx, del, valA) unbonding, found = keeper.GetUnbondingDelegation(ctx, del, valA)
@ -886,7 +886,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
// destination delegation should be unchanged // destination delegation should be unchanged
delegation, found = keeper.GetDelegation(ctx, del, valB) delegation, found = keeper.GetDelegation(ctx, del, valB)
require.True(t, found) require.True(t, found)
require.Equal(t, sdk.NewRat(3), delegation.Shares) require.Equal(t, sdk.NewDec(3), delegation.Shares)
// validator power should have been reduced to zero // validator power should have been reduced to zero
// ergo validator should have been removed from the store // ergo validator should have been removed from the store

View File

@ -218,7 +218,7 @@ func (k Keeper) RemoveRedelegation(ctx sdk.Context, red types.Redelegation) {
// Perform a delegation, set/update everything necessary within the store. // Perform a delegation, set/update everything necessary within the store.
func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt sdk.Coin, func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt sdk.Coin,
validator types.Validator, subtractAccount bool) (newShares sdk.Rat, err sdk.Error) { validator types.Validator, subtractAccount bool) (newShares sdk.Dec, err sdk.Error) {
// Get or create the delegator delegation // Get or create the delegator delegation
delegation, found := k.GetDelegation(ctx, delegatorAddr, validator.Owner) delegation, found := k.GetDelegation(ctx, delegatorAddr, validator.Owner)
@ -226,7 +226,7 @@ func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt
delegation = types.Delegation{ delegation = types.Delegation{
DelegatorAddr: delegatorAddr, DelegatorAddr: delegatorAddr,
ValidatorAddr: validator.Owner, ValidatorAddr: validator.Owner,
Shares: sdk.ZeroRat(), Shares: sdk.ZeroDec(),
} }
} }
@ -254,7 +254,7 @@ func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt
// unbond the the delegation return // unbond the the delegation return
func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress, func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress,
shares sdk.Rat) (amount sdk.Rat, err sdk.Error) { shares sdk.Dec) (amount sdk.Dec, err sdk.Error) {
// check if delegation has any shares in it unbond // check if delegation has any shares in it unbond
delegation, found := k.GetDelegation(ctx, delegatorAddr, validatorAddr) delegation, found := k.GetDelegation(ctx, delegatorAddr, validatorAddr)
@ -312,7 +312,7 @@ func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddr
//______________________________________________________________________________________________________ //______________________________________________________________________________________________________
// complete unbonding an unbonding record // complete unbonding an unbonding record
func (k Keeper) BeginUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Rat) sdk.Error { func (k Keeper) BeginUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Dec) sdk.Error {
// TODO quick fix, instead we should use an index, see https://github.com/cosmos/cosmos-sdk/issues/1402 // TODO quick fix, instead we should use an index, see https://github.com/cosmos/cosmos-sdk/issues/1402
_, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) _, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr)
@ -365,7 +365,7 @@ func (k Keeper) CompleteUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr
// complete unbonding an unbonding record // complete unbonding an unbonding record
func (k Keeper) BeginRedelegation(ctx sdk.Context, delegatorAddr, validatorSrcAddr, func (k Keeper) BeginRedelegation(ctx sdk.Context, delegatorAddr, validatorSrcAddr,
validatorDstAddr sdk.AccAddress, sharesAmount sdk.Rat) sdk.Error { validatorDstAddr sdk.AccAddress, sharesAmount sdk.Dec) sdk.Error {
// check if this is a transitive redelegation // check if this is a transitive redelegation
if k.HasReceivingRedelegation(ctx, delegatorAddr, validatorSrcAddr) { if k.HasReceivingRedelegation(ctx, delegatorAddr, validatorSrcAddr) {

View File

@ -32,7 +32,7 @@ func TestDelegation(t *testing.T) {
bond1to1 := types.Delegation{ bond1to1 := types.Delegation{
DelegatorAddr: addrDels[0], DelegatorAddr: addrDels[0],
ValidatorAddr: addrVals[0], ValidatorAddr: addrVals[0],
Shares: sdk.NewRat(9), Shares: sdk.NewDec(9),
} }
// check the empty keeper first // check the empty keeper first
@ -46,18 +46,18 @@ func TestDelegation(t *testing.T) {
require.True(t, bond1to1.Equal(resBond)) require.True(t, bond1to1.Equal(resBond))
// modify a records, save, and retrieve // modify a records, save, and retrieve
bond1to1.Shares = sdk.NewRat(99) bond1to1.Shares = sdk.NewDec(99)
keeper.SetDelegation(ctx, bond1to1) keeper.SetDelegation(ctx, bond1to1)
resBond, found = keeper.GetDelegation(ctx, addrDels[0], addrVals[0]) resBond, found = keeper.GetDelegation(ctx, addrDels[0], addrVals[0])
require.True(t, found) require.True(t, found)
require.True(t, bond1to1.Equal(resBond)) require.True(t, bond1to1.Equal(resBond))
// add some more records // add some more records
bond1to2 := types.Delegation{addrDels[0], addrVals[1], sdk.NewRat(9), 0} bond1to2 := types.Delegation{addrDels[0], addrVals[1], sdk.NewDec(9), 0}
bond1to3 := types.Delegation{addrDels[0], addrVals[2], sdk.NewRat(9), 1} bond1to3 := types.Delegation{addrDels[0], addrVals[2], sdk.NewDec(9), 1}
bond2to1 := types.Delegation{addrDels[1], addrVals[0], sdk.NewRat(9), 2} bond2to1 := types.Delegation{addrDels[1], addrVals[0], sdk.NewDec(9), 2}
bond2to2 := types.Delegation{addrDels[1], addrVals[1], sdk.NewRat(9), 3} bond2to2 := types.Delegation{addrDels[1], addrVals[1], sdk.NewDec(9), 3}
bond2to3 := types.Delegation{addrDels[1], addrVals[2], sdk.NewRat(9), 4} bond2to3 := types.Delegation{addrDels[1], addrVals[2], sdk.NewDec(9), 4}
keeper.SetDelegation(ctx, bond1to2) keeper.SetDelegation(ctx, bond1to2)
keeper.SetDelegation(ctx, bond1to3) keeper.SetDelegation(ctx, bond1to3)
keeper.SetDelegation(ctx, bond2to1) keeper.SetDelegation(ctx, bond2to1)
@ -142,7 +142,7 @@ func TestUnbondingDelegation(t *testing.T) {
func TestUnbondDelegation(t *testing.T) { func TestUnbondDelegation(t *testing.T) {
ctx, _, keeper := CreateTestInput(t, false, 0) ctx, _, keeper := CreateTestInput(t, false, 0)
pool := keeper.GetPool(ctx) pool := keeper.GetPool(ctx)
pool.LooseTokens = sdk.NewRat(10) pool.LooseTokens = sdk.NewDec(10)
//create a validator and a delegator to that validator //create a validator and a delegator to that validator
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
@ -163,8 +163,8 @@ func TestUnbondDelegation(t *testing.T) {
keeper.SetDelegation(ctx, delegation) keeper.SetDelegation(ctx, delegation)
var err error var err error
var amount sdk.Rat var amount sdk.Dec
amount, err = keeper.unbond(ctx, addrDels[0], addrVals[0], sdk.NewRat(6)) amount, err = keeper.unbond(ctx, addrDels[0], addrVals[0], sdk.NewDec(6))
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, int64(6), amount.RoundInt64()) // shares to be added to an unbonding delegation / redelegation require.Equal(t, int64(6), amount.RoundInt64()) // shares to be added to an unbonding delegation / redelegation
@ -190,8 +190,8 @@ func TestGetRedelegationsFromValidator(t *testing.T) {
ValidatorDstAddr: addrVals[1], ValidatorDstAddr: addrVals[1],
CreationHeight: 0, CreationHeight: 0,
MinTime: time.Unix(0, 0), MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(5), SharesSrc: sdk.NewDec(5),
SharesDst: sdk.NewRat(5), SharesDst: sdk.NewDec(5),
} }
// set and retrieve a record // set and retrieve a record
@ -220,8 +220,8 @@ func TestRedelegation(t *testing.T) {
ValidatorDstAddr: addrVals[1], ValidatorDstAddr: addrVals[1],
CreationHeight: 0, CreationHeight: 0,
MinTime: time.Unix(0, 0), MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(5), SharesSrc: sdk.NewDec(5),
SharesDst: sdk.NewRat(5), SharesDst: sdk.NewDec(5),
} }
// test shouldn't have and redelegations // test shouldn't have and redelegations
@ -242,8 +242,8 @@ func TestRedelegation(t *testing.T) {
require.True(t, has) require.True(t, has)
// modify a records, save, and retrieve // modify a records, save, and retrieve
rd.SharesSrc = sdk.NewRat(21) rd.SharesSrc = sdk.NewDec(21)
rd.SharesDst = sdk.NewRat(21) rd.SharesDst = sdk.NewDec(21)
keeper.SetRedelegation(ctx, rd) keeper.SetRedelegation(ctx, rd)
resBond, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) resBond, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])

View File

@ -33,7 +33,7 @@ func TestPool(t *testing.T) {
require.True(t, expPool.Equal(resPool)) require.True(t, expPool.Equal(resPool))
//modify a params, save, and retrieve //modify a params, save, and retrieve
expPool.BondedTokens = sdk.NewRat(777) expPool.BondedTokens = sdk.NewDec(777)
keeper.SetPool(ctx, expPool) keeper.SetPool(ctx, expPool)
resPool = keeper.GetPool(ctx) resPool = keeper.GetPool(ctx)
require.True(t, expPool.Equal(resPool)) require.True(t, expPool.Equal(resPool))

View File

@ -69,7 +69,7 @@ func (k Keeper) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) sdk.Val
} }
// total power from the bond // total power from the bond
func (k Keeper) TotalPower(ctx sdk.Context) sdk.Rat { func (k Keeper) TotalPower(ctx sdk.Context) sdk.Dec {
pool := k.GetPool(ctx) pool := k.GetPool(ctx)
return pool.BondedTokens return pool.BondedTokens
} }

View File

@ -20,15 +20,15 @@ import (
// CONTRACT: // CONTRACT:
// Infraction committed at the current height or at a past height, // Infraction committed at the current height or at a past height,
// not at a height in the future // not at a height in the future
func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, power int64, slashFactor sdk.Rat) { func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, power int64, slashFactor sdk.Dec) {
logger := ctx.Logger().With("module", "x/stake") logger := ctx.Logger().With("module", "x/stake")
if slashFactor.LT(sdk.ZeroRat()) { if slashFactor.LT(sdk.ZeroDec()) {
panic(fmt.Errorf("attempted to slash with a negative slashFactor: %v", slashFactor)) panic(fmt.Errorf("attempted to slash with a negative slashFactor: %v", slashFactor))
} }
// Amount of slashing = slash slashFactor * power at time of infraction // Amount of slashing = slash slashFactor * power at time of infraction
slashAmount := sdk.NewRat(power).Mul(slashFactor) slashAmount := sdk.NewDec(power).Mul(slashFactor)
// ref https://github.com/cosmos/cosmos-sdk/issues/1348 // ref https://github.com/cosmos/cosmos-sdk/issues/1348
// ref https://github.com/cosmos/cosmos-sdk/issues/1471 // ref https://github.com/cosmos/cosmos-sdk/issues/1471
@ -89,7 +89,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
} }
// Cannot decrease balance below zero // Cannot decrease balance below zero
tokensToBurn := sdk.MinRat(remainingSlashAmount, validator.Tokens) tokensToBurn := sdk.MinDec(remainingSlashAmount, validator.Tokens)
// Get the current pool // Get the current pool
pool := k.GetPool(ctx) pool := k.GetPool(ctx)
@ -150,23 +150,23 @@ func (k Keeper) setRevoked(ctx sdk.Context, pubkey crypto.PubKey, revoked bool)
// (the amount actually slashed may be less if there's // (the amount actually slashed may be less if there's
// insufficient stake remaining) // insufficient stake remaining)
func (k Keeper) slashUnbondingDelegation(ctx sdk.Context, unbondingDelegation types.UnbondingDelegation, func (k Keeper) slashUnbondingDelegation(ctx sdk.Context, unbondingDelegation types.UnbondingDelegation,
infractionHeight int64, slashFactor sdk.Rat) (slashAmount sdk.Rat) { infractionHeight int64, slashFactor sdk.Dec) (slashAmount sdk.Dec) {
now := ctx.BlockHeader().Time now := ctx.BlockHeader().Time
// If unbonding started before this height, stake didn't contribute to infraction // If unbonding started before this height, stake didn't contribute to infraction
if unbondingDelegation.CreationHeight < infractionHeight { if unbondingDelegation.CreationHeight < infractionHeight {
return sdk.ZeroRat() return sdk.ZeroDec()
} }
if unbondingDelegation.MinTime.Before(now) { if unbondingDelegation.MinTime.Before(now) {
// Unbonding delegation no longer eligible for slashing, skip it // Unbonding delegation no longer eligible for slashing, skip it
// TODO Settle and delete it automatically? // TODO Settle and delete it automatically?
return sdk.ZeroRat() return sdk.ZeroDec()
} }
// Calculate slash amount proportional to stake contributing to infraction // Calculate slash amount proportional to stake contributing to infraction
slashAmount = sdk.NewRatFromInt(unbondingDelegation.InitialBalance.Amount, sdk.OneInt()).Mul(slashFactor) slashAmount = sdk.NewDecFromInt(unbondingDelegation.InitialBalance.Amount).Mul(slashFactor)
// Don't slash more tokens than held // Don't slash more tokens than held
// Possible since the unbonding delegation may already // Possible since the unbonding delegation may already
@ -194,23 +194,23 @@ func (k Keeper) slashUnbondingDelegation(ctx sdk.Context, unbondingDelegation ty
// (the amount actually slashed may be less if there's // (the amount actually slashed may be less if there's
// insufficient stake remaining) // insufficient stake remaining)
func (k Keeper) slashRedelegation(ctx sdk.Context, validator types.Validator, redelegation types.Redelegation, func (k Keeper) slashRedelegation(ctx sdk.Context, validator types.Validator, redelegation types.Redelegation,
infractionHeight int64, slashFactor sdk.Rat) (slashAmount sdk.Rat) { infractionHeight int64, slashFactor sdk.Dec) (slashAmount sdk.Dec) {
now := ctx.BlockHeader().Time now := ctx.BlockHeader().Time
// If redelegation started before this height, stake didn't contribute to infraction // If redelegation started before this height, stake didn't contribute to infraction
if redelegation.CreationHeight < infractionHeight { if redelegation.CreationHeight < infractionHeight {
return sdk.ZeroRat() return sdk.ZeroDec()
} }
if redelegation.MinTime.Before(now) { if redelegation.MinTime.Before(now) {
// Redelegation no longer eligible for slashing, skip it // Redelegation no longer eligible for slashing, skip it
// TODO Delete it automatically? // TODO Delete it automatically?
return sdk.ZeroRat() return sdk.ZeroDec()
} }
// Calculate slash amount proportional to stake contributing to infraction // Calculate slash amount proportional to stake contributing to infraction
slashAmount = sdk.NewRatFromInt(redelegation.InitialBalance.Amount, sdk.OneInt()).Mul(slashFactor) slashAmount = sdk.NewDecFromInt(redelegation.InitialBalance.Amount).Mul(slashFactor)
// Don't slash more tokens than held // Don't slash more tokens than held
// Possible since the redelegation may already // Possible since the redelegation may already

View File

@ -19,7 +19,7 @@ func setupHelper(t *testing.T, amt int64) (sdk.Context, Keeper, types.Params) {
params := keeper.GetParams(ctx) params := keeper.GetParams(ctx)
pool := keeper.GetPool(ctx) pool := keeper.GetPool(ctx)
numVals := 3 numVals := 3
pool.LooseTokens = sdk.NewRat(amt * int64(numVals)) pool.LooseTokens = sdk.NewDec(amt * int64(numVals))
// add numVals validators // add numVals validators
for i := 0; i < numVals; i++ { for i := 0; i < numVals; i++ {
@ -63,7 +63,7 @@ func TestRevocation(t *testing.T) {
// tests slashUnbondingDelegation // tests slashUnbondingDelegation
func TestSlashUnbondingDelegation(t *testing.T) { func TestSlashUnbondingDelegation(t *testing.T) {
ctx, keeper, params := setupHelper(t, 10) ctx, keeper, params := setupHelper(t, 10)
fraction := sdk.NewRat(1, 2) fraction := sdk.NewDecWithPrec(5, 1)
// set an unbonding delegation // set an unbonding delegation
ubd := types.UnbondingDelegation{ ubd := types.UnbondingDelegation{
@ -106,7 +106,7 @@ func TestSlashUnbondingDelegation(t *testing.T) {
// tests slashRedelegation // tests slashRedelegation
func TestSlashRedelegation(t *testing.T) { func TestSlashRedelegation(t *testing.T) {
ctx, keeper, params := setupHelper(t, 10) ctx, keeper, params := setupHelper(t, 10)
fraction := sdk.NewRat(1, 2) fraction := sdk.NewDecWithPrec(5, 1)
// set a redelegation // set a redelegation
rd := types.Redelegation{ rd := types.Redelegation{
@ -116,8 +116,8 @@ func TestSlashRedelegation(t *testing.T) {
CreationHeight: 0, CreationHeight: 0,
// expiration timestamp (beyond which the redelegation shouldn't be slashed) // expiration timestamp (beyond which the redelegation shouldn't be slashed)
MinTime: time.Unix(0, 0), MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(10), SharesSrc: sdk.NewDec(10),
SharesDst: sdk.NewRat(10), SharesDst: sdk.NewDec(10),
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 10), InitialBalance: sdk.NewInt64Coin(params.BondDenom, 10),
Balance: sdk.NewInt64Coin(params.BondDenom, 10), Balance: sdk.NewInt64Coin(params.BondDenom, 10),
} }
@ -127,7 +127,7 @@ func TestSlashRedelegation(t *testing.T) {
del := types.Delegation{ del := types.Delegation{
DelegatorAddr: addrDels[0], DelegatorAddr: addrDels[0],
ValidatorAddr: addrVals[1], ValidatorAddr: addrVals[1],
Shares: sdk.NewRat(10), Shares: sdk.NewDec(10),
} }
keeper.SetDelegation(ctx, del) keeper.SetDelegation(ctx, del)
@ -172,7 +172,7 @@ func TestSlashRedelegation(t *testing.T) {
func TestSlashAtFutureHeight(t *testing.T) { func TestSlashAtFutureHeight(t *testing.T) {
ctx, keeper, _ := setupHelper(t, 10) ctx, keeper, _ := setupHelper(t, 10)
pk := PKs[0] pk := PKs[0]
fraction := sdk.NewRat(1, 2) fraction := sdk.NewDecWithPrec(5, 1)
require.Panics(t, func() { keeper.Slash(ctx, pk, 1, 10, fraction) }) require.Panics(t, func() { keeper.Slash(ctx, pk, 1, 10, fraction) })
} }
@ -180,7 +180,7 @@ func TestSlashAtFutureHeight(t *testing.T) {
func TestSlashAtCurrentHeight(t *testing.T) { func TestSlashAtCurrentHeight(t *testing.T) {
ctx, keeper, _ := setupHelper(t, 10) ctx, keeper, _ := setupHelper(t, 10)
pk := PKs[0] pk := PKs[0]
fraction := sdk.NewRat(1, 2) fraction := sdk.NewDecWithPrec(5, 1)
oldPool := keeper.GetPool(ctx) oldPool := keeper.GetPool(ctx)
validator, found := keeper.GetValidatorByPubKey(ctx, pk) validator, found := keeper.GetValidatorByPubKey(ctx, pk)
@ -193,16 +193,16 @@ func TestSlashAtCurrentHeight(t *testing.T) {
newPool := keeper.GetPool(ctx) newPool := keeper.GetPool(ctx)
// power decreased // power decreased
require.Equal(t, sdk.NewRat(5), validator.GetPower()) require.Equal(t, sdk.NewDec(5), validator.GetPower())
// pool bonded shares decreased // pool bonded shares decreased
require.Equal(t, sdk.NewRat(5).RoundInt64(), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) require.Equal(t, sdk.NewDec(5).RoundInt64(), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
} }
// tests Slash at a previous height with an unbonding delegation // tests Slash at a previous height with an unbonding delegation
func TestSlashWithUnbondingDelegation(t *testing.T) { func TestSlashWithUnbondingDelegation(t *testing.T) {
ctx, keeper, params := setupHelper(t, 10) ctx, keeper, params := setupHelper(t, 10)
pk := PKs[0] pk := PKs[0]
fraction := sdk.NewRat(1, 2) fraction := sdk.NewDecWithPrec(5, 1)
// set an unbonding delegation // set an unbonding delegation
ubd := types.UnbondingDelegation{ ubd := types.UnbondingDelegation{
@ -239,7 +239,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// was still bonded at the time of discovery and was slashed by half, 4 stake // was still bonded at the time of discovery and was slashed by half, 4 stake
// bonded at the time of discovery hadn't been bonded at the time of infraction // bonded at the time of discovery hadn't been bonded at the time of infraction
// and wasn't slashed // and wasn't slashed
require.Equal(t, sdk.NewRat(7), validator.GetPower()) require.Equal(t, sdk.NewDec(7), validator.GetPower())
// slash validator again // slash validator again
ctx = ctx.WithBlockHeight(13) ctx = ctx.WithBlockHeight(13)
@ -256,7 +256,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
validator, found = keeper.GetValidatorByPubKey(ctx, pk) validator, found = keeper.GetValidatorByPubKey(ctx, pk)
require.True(t, found) require.True(t, found)
// power decreased by 3 again // power decreased by 3 again
require.Equal(t, sdk.NewRat(4), validator.GetPower()) require.Equal(t, sdk.NewDec(4), validator.GetPower())
// slash validator again // slash validator again
// all originally bonded stake has been slashed, so this will have no effect // all originally bonded stake has been slashed, so this will have no effect
@ -276,7 +276,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
validator, found = keeper.GetValidatorByPubKey(ctx, pk) validator, found = keeper.GetValidatorByPubKey(ctx, pk)
require.True(t, found) require.True(t, found)
// power decreased by 3 again // power decreased by 3 again
require.Equal(t, sdk.NewRat(1), validator.GetPower()) require.Equal(t, sdk.NewDec(1), validator.GetPower())
// slash validator again // slash validator again
// all originally bonded stake has been slashed, so this will have no effect // all originally bonded stake has been slashed, so this will have no effect
@ -303,7 +303,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
func TestSlashWithRedelegation(t *testing.T) { func TestSlashWithRedelegation(t *testing.T) {
ctx, keeper, params := setupHelper(t, 10) ctx, keeper, params := setupHelper(t, 10)
pk := PKs[0] pk := PKs[0]
fraction := sdk.NewRat(1, 2) fraction := sdk.NewDecWithPrec(5, 1)
// set a redelegation // set a redelegation
rd := types.Redelegation{ rd := types.Redelegation{
@ -312,8 +312,8 @@ func TestSlashWithRedelegation(t *testing.T) {
ValidatorDstAddr: addrVals[1], ValidatorDstAddr: addrVals[1],
CreationHeight: 11, CreationHeight: 11,
MinTime: time.Unix(0, 0), MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(6), SharesSrc: sdk.NewDec(6),
SharesDst: sdk.NewRat(6), SharesDst: sdk.NewDec(6),
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6), InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6),
Balance: sdk.NewInt64Coin(params.BondDenom, 6), Balance: sdk.NewInt64Coin(params.BondDenom, 6),
} }
@ -323,13 +323,13 @@ func TestSlashWithRedelegation(t *testing.T) {
del := types.Delegation{ del := types.Delegation{
DelegatorAddr: addrDels[0], DelegatorAddr: addrDels[0],
ValidatorAddr: addrVals[1], ValidatorAddr: addrVals[1],
Shares: sdk.NewRat(6), Shares: sdk.NewDec(6),
} }
keeper.SetDelegation(ctx, del) keeper.SetDelegation(ctx, del)
// update bonded tokens // update bonded tokens
pool := keeper.GetPool(ctx) pool := keeper.GetPool(ctx)
pool.BondedTokens = pool.BondedTokens.Add(sdk.NewRat(6)) pool.BondedTokens = pool.BondedTokens.Add(sdk.NewDec(6))
keeper.SetPool(ctx, pool) keeper.SetPool(ctx, pool)
// slash validator // slash validator
@ -355,13 +355,13 @@ func TestSlashWithRedelegation(t *testing.T) {
// was still bonded at the time of discovery and was slashed by half, 4 stake // was still bonded at the time of discovery and was slashed by half, 4 stake
// bonded at the time of discovery hadn't been bonded at the time of infraction // bonded at the time of discovery hadn't been bonded at the time of infraction
// and wasn't slashed // and wasn't slashed
require.Equal(t, sdk.NewRat(8), validator.GetPower()) require.Equal(t, sdk.NewDec(8), validator.GetPower())
// slash the validator again // slash the validator again
ctx = ctx.WithBlockHeight(12) ctx = ctx.WithBlockHeight(12)
validator, found = keeper.GetValidatorByPubKey(ctx, pk) validator, found = keeper.GetValidatorByPubKey(ctx, pk)
require.True(t, found) require.True(t, found)
require.NotPanics(t, func() { keeper.Slash(ctx, pk, 10, 10, sdk.OneRat()) }) require.NotPanics(t, func() { keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) })
// read updating redelegation // read updating redelegation
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
@ -376,13 +376,13 @@ func TestSlashWithRedelegation(t *testing.T) {
validator, found = keeper.GetValidatorByPubKey(ctx, pk) validator, found = keeper.GetValidatorByPubKey(ctx, pk)
require.True(t, found) require.True(t, found)
// power decreased by 4 // power decreased by 4
require.Equal(t, sdk.NewRat(4), validator.GetPower()) require.Equal(t, sdk.NewDec(4), validator.GetPower())
// slash the validator again, by 100% // slash the validator again, by 100%
ctx = ctx.WithBlockHeight(12) ctx = ctx.WithBlockHeight(12)
validator, found = keeper.GetValidatorByPubKey(ctx, pk) validator, found = keeper.GetValidatorByPubKey(ctx, pk)
require.True(t, found) require.True(t, found)
keeper.Slash(ctx, pk, 10, 10, sdk.OneRat()) keeper.Slash(ctx, pk, 10, 10, sdk.OneDec())
// read updating redelegation // read updating redelegation
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
@ -404,7 +404,7 @@ func TestSlashWithRedelegation(t *testing.T) {
// validator no longer in the store // validator no longer in the store
_, found = keeper.GetValidatorByPubKey(ctx, pk) _, found = keeper.GetValidatorByPubKey(ctx, pk)
require.False(t, found) require.False(t, found)
keeper.Slash(ctx, pk, 10, 10, sdk.OneRat()) keeper.Slash(ctx, pk, 10, 10, sdk.OneDec())
// read updating redelegation // read updating redelegation
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
@ -424,7 +424,7 @@ func TestSlashWithRedelegation(t *testing.T) {
// tests Slash at a previous height with both an unbonding delegation and a redelegation // tests Slash at a previous height with both an unbonding delegation and a redelegation
func TestSlashBoth(t *testing.T) { func TestSlashBoth(t *testing.T) {
ctx, keeper, params := setupHelper(t, 10) ctx, keeper, params := setupHelper(t, 10)
fraction := sdk.NewRat(1, 2) fraction := sdk.NewDecWithPrec(5, 1)
// set a redelegation // set a redelegation
rdA := types.Redelegation{ rdA := types.Redelegation{
@ -434,8 +434,8 @@ func TestSlashBoth(t *testing.T) {
CreationHeight: 11, CreationHeight: 11,
// expiration timestamp (beyond which the redelegation shouldn't be slashed) // expiration timestamp (beyond which the redelegation shouldn't be slashed)
MinTime: time.Unix(0, 0), MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(6), SharesSrc: sdk.NewDec(6),
SharesDst: sdk.NewRat(6), SharesDst: sdk.NewDec(6),
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6), InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6),
Balance: sdk.NewInt64Coin(params.BondDenom, 6), Balance: sdk.NewInt64Coin(params.BondDenom, 6),
} }
@ -445,7 +445,7 @@ func TestSlashBoth(t *testing.T) {
delA := types.Delegation{ delA := types.Delegation{
DelegatorAddr: addrDels[0], DelegatorAddr: addrDels[0],
ValidatorAddr: addrVals[1], ValidatorAddr: addrVals[1],
Shares: sdk.NewRat(6), Shares: sdk.NewDec(6),
} }
keeper.SetDelegation(ctx, delA) keeper.SetDelegation(ctx, delA)
@ -483,5 +483,5 @@ func TestSlashBoth(t *testing.T) {
validator, found = keeper.GetValidatorByPubKey(ctx, PKs[0]) validator, found = keeper.GetValidatorByPubKey(ctx, PKs[0])
require.True(t, found) require.True(t, found)
// power not decreased, all stake was bonded since // power not decreased, all stake was bonded since
require.Equal(t, sdk.NewRat(10), validator.GetPower()) require.Equal(t, sdk.NewDec(10), validator.GetPower())
} }

View File

@ -77,10 +77,10 @@ func MakeTestCodec() *wire.Codec {
// default params without inflation // default params without inflation
func ParamsNoInflation() types.Params { func ParamsNoInflation() types.Params {
return types.Params{ return types.Params{
InflationRateChange: sdk.ZeroRat(), InflationRateChange: sdk.ZeroDec(),
InflationMax: sdk.ZeroRat(), InflationMax: sdk.ZeroDec(),
InflationMin: sdk.ZeroRat(), InflationMin: sdk.ZeroDec(),
GoalBonded: sdk.NewRat(67, 100), GoalBonded: sdk.NewDecWithPrec(67, 2),
MaxValidators: 100, MaxValidators: 100,
BondDenom: "steak", BondDenom: "steak",
} }
@ -119,7 +119,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context
{keeper.GetParams(ctx).BondDenom, sdk.NewInt(initCoins)}, {keeper.GetParams(ctx).BondDenom, sdk.NewInt(initCoins)},
}) })
require.Nil(t, err) require.Nil(t, err)
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewRat(initCoins)) pool.LooseTokens = pool.LooseTokens.Add(sdk.NewDec(initCoins))
keeper.SetPool(ctx, pool) keeper.SetPool(ctx, pool)
} }

View File

@ -20,8 +20,8 @@ func TestSetValidator(t *testing.T) {
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
validator, pool, _ = validator.AddTokensFromDel(pool, 10) validator, pool, _ = validator.AddTokensFromDel(pool, 10)
require.Equal(t, sdk.Unbonded, validator.Status) require.Equal(t, sdk.Unbonded, validator.Status)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
keeper.SetPool(ctx, pool) keeper.SetPool(ctx, pool)
keeper.UpdateValidator(ctx, validator) keeper.UpdateValidator(ctx, validator)
@ -29,8 +29,8 @@ func TestSetValidator(t *testing.T) {
validator, found := keeper.GetValidator(ctx, addrVals[0]) validator, found := keeper.GetValidator(ctx, addrVals[0])
require.True(t, found) require.True(t, found)
require.Equal(t, sdk.Bonded, validator.Status) require.Equal(t, sdk.Bonded, validator.Status)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
// Check each store for being saved // Check each store for being saved
resVal, found := keeper.GetValidator(ctx, addrVals[0]) resVal, found := keeper.GetValidator(ctx, addrVals[0])
@ -56,8 +56,8 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) {
pool := keeper.GetPool(ctx) pool := keeper.GetPool(ctx)
// create a random pool // create a random pool
pool.LooseTokens = sdk.NewRat(10000) pool.LooseTokens = sdk.NewDec(10000)
pool.BondedTokens = sdk.NewRat(1234) pool.BondedTokens = sdk.NewDec(1234)
keeper.SetPool(ctx, pool) keeper.SetPool(ctx, pool)
// add a validator // add a validator
@ -76,7 +76,7 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) {
require.True(t, keeper.validatorByPowerIndexExists(ctx, power)) require.True(t, keeper.validatorByPowerIndexExists(ctx, power))
// burn half the delegator shares // burn half the delegator shares
validator, pool, burned := validator.RemoveDelShares(pool, delSharesCreated.Quo(sdk.NewRat(2))) validator, pool, burned := validator.RemoveDelShares(pool, delSharesCreated.Quo(sdk.NewDec(2)))
require.Equal(t, int64(50), burned.RoundInt64()) require.Equal(t, int64(50), burned.RoundInt64())
keeper.SetPool(ctx, pool) // update the pool keeper.SetPool(ctx, pool) // update the pool
keeper.UpdateValidator(ctx, validator) // update the validator, possibly kicking it out keeper.UpdateValidator(ctx, validator) // update the validator, possibly kicking it out
@ -103,8 +103,8 @@ func TestCliffValidatorChange(t *testing.T) {
keeper.SetParams(ctx, params) keeper.SetParams(ctx, params)
// create a random pool // create a random pool
pool.LooseTokens = sdk.NewRat(10000) pool.LooseTokens = sdk.NewDec(10000)
pool.BondedTokens = sdk.NewRat(1234) pool.BondedTokens = sdk.NewDec(1234)
keeper.SetPool(ctx, pool) keeper.SetPool(ctx, pool)
validators := make([]types.Validator, numVals) validators := make([]types.Validator, numVals)
@ -161,7 +161,7 @@ func TestSlashToZeroPowerRemoved(t *testing.T) {
require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool) require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool)
// slash the validator by 100% // slash the validator by 100%
keeper.Slash(ctx, PKs[0], 0, 100, sdk.OneRat()) keeper.Slash(ctx, PKs[0], 0, 100, sdk.OneDec())
// validator should have been deleted // validator should have been deleted
_, found := keeper.GetValidator(ctx, addrVals[0]) _, found := keeper.GetValidator(ctx, addrVals[0])
require.False(t, found) require.False(t, found)
@ -178,13 +178,13 @@ func TestValidatorBasics(t *testing.T) {
for i, amt := range amts { for i, amt := range amts {
validators[i] = types.NewValidator(addrVals[i], PKs[i], types.Description{}) validators[i] = types.NewValidator(addrVals[i], PKs[i], types.Description{})
validators[i].Status = sdk.Unbonded validators[i].Status = sdk.Unbonded
validators[i].Tokens = sdk.ZeroRat() validators[i].Tokens = sdk.ZeroDec()
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
keeper.SetPool(ctx, pool) keeper.SetPool(ctx, pool)
} }
assert.True(sdk.RatEq(t, sdk.NewRat(9), validators[0].Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(9), validators[0].Tokens))
assert.True(sdk.RatEq(t, sdk.NewRat(8), validators[1].Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(8), validators[1].Tokens))
assert.True(sdk.RatEq(t, sdk.NewRat(7), validators[2].Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(7), validators[2].Tokens))
// check the empty keeper first // check the empty keeper first
_, found := keeper.GetValidator(ctx, addrVals[0]) _, found := keeper.GetValidator(ctx, addrVals[0])
@ -193,7 +193,7 @@ func TestValidatorBasics(t *testing.T) {
assert.Zero(t, len(resVals)) assert.Zero(t, len(resVals))
pool = keeper.GetPool(ctx) pool = keeper.GetPool(ctx)
assert.True(sdk.RatEq(t, sdk.ZeroRat(), pool.BondedTokens)) assert.True(sdk.DecEq(t, sdk.ZeroDec(), pool.BondedTokens))
// set and retrieve a record // set and retrieve a record
validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[0] = keeper.UpdateValidator(ctx, validators[0])
@ -205,15 +205,15 @@ func TestValidatorBasics(t *testing.T) {
require.Equal(t, 1, len(resVals)) require.Equal(t, 1, len(resVals))
assert.True(ValEq(t, validators[0], resVals[0])) assert.True(ValEq(t, validators[0], resVals[0]))
assert.Equal(t, sdk.Bonded, validators[0].Status) assert.Equal(t, sdk.Bonded, validators[0].Status)
assert.True(sdk.RatEq(t, sdk.NewRat(9), validators[0].BondedTokens())) assert.True(sdk.DecEq(t, sdk.NewDec(9), validators[0].BondedTokens()))
pool = keeper.GetPool(ctx) pool = keeper.GetPool(ctx)
assert.True(sdk.RatEq(t, pool.BondedTokens, validators[0].BondedTokens())) assert.True(sdk.DecEq(t, pool.BondedTokens, validators[0].BondedTokens()))
// modify a records, save, and retrieve // modify a records, save, and retrieve
validators[0].Status = sdk.Bonded validators[0].Status = sdk.Bonded
validators[0].Tokens = sdk.NewRat(10) validators[0].Tokens = sdk.NewDec(10)
validators[0].DelegatorShares = sdk.NewRat(10) validators[0].DelegatorShares = sdk.NewDec(10)
validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[0] = keeper.UpdateValidator(ctx, validators[0])
resVal, found = keeper.GetValidator(ctx, addrVals[0]) resVal, found = keeper.GetValidator(ctx, addrVals[0])
require.True(t, found) require.True(t, found)
@ -256,19 +256,19 @@ func GetValidatorSortingUnmixed(t *testing.T) {
for i, amt := range amts { for i, amt := range amts {
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
validators[i].Status = sdk.Bonded validators[i].Status = sdk.Bonded
validators[i].Tokens = sdk.NewRat(amt) validators[i].Tokens = sdk.NewDec(amt)
validators[i].DelegatorShares = sdk.NewRat(amt) validators[i].DelegatorShares = sdk.NewDec(amt)
keeper.UpdateValidator(ctx, validators[i]) keeper.UpdateValidator(ctx, validators[i])
} }
// first make sure everything made it in to the gotValidator group // first make sure everything made it in to the gotValidator group
resValidators := keeper.GetValidatorsByPower(ctx) resValidators := keeper.GetValidatorsByPower(ctx)
assert.Equal(t, n, len(resValidators)) assert.Equal(t, n, len(resValidators))
assert.Equal(t, sdk.NewRat(400), resValidators[0].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(400), resValidators[0].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(200), resValidators[1].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(200), resValidators[1].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(100), resValidators[2].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(100), resValidators[2].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(1), resValidators[3].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(1), resValidators[3].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(0), resValidators[4].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(0), resValidators[4].BondedTokens(), "%v", resValidators)
assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators) assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators)
assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators) assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators)
assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators) assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators)
@ -276,14 +276,14 @@ func GetValidatorSortingUnmixed(t *testing.T) {
assert.Equal(t, validators[0].Owner, resValidators[4].Owner, "%v", resValidators) assert.Equal(t, validators[0].Owner, resValidators[4].Owner, "%v", resValidators)
// test a basic increase in voting power // test a basic increase in voting power
validators[3].Tokens = sdk.NewRat(500) validators[3].Tokens = sdk.NewDec(500)
keeper.UpdateValidator(ctx, validators[3]) keeper.UpdateValidator(ctx, validators[3])
resValidators = keeper.GetValidatorsByPower(ctx) resValidators = keeper.GetValidatorsByPower(ctx)
require.Equal(t, len(resValidators), n) require.Equal(t, len(resValidators), n)
assert.True(ValEq(t, validators[3], resValidators[0])) assert.True(ValEq(t, validators[3], resValidators[0]))
// test a decrease in voting power // test a decrease in voting power
validators[3].Tokens = sdk.NewRat(300) validators[3].Tokens = sdk.NewDec(300)
keeper.UpdateValidator(ctx, validators[3]) keeper.UpdateValidator(ctx, validators[3])
resValidators = keeper.GetValidatorsByPower(ctx) resValidators = keeper.GetValidatorsByPower(ctx)
require.Equal(t, len(resValidators), n) require.Equal(t, len(resValidators), n)
@ -291,7 +291,7 @@ func GetValidatorSortingUnmixed(t *testing.T) {
assert.True(ValEq(t, validators[4], resValidators[1])) assert.True(ValEq(t, validators[4], resValidators[1]))
// test equal voting power, different age // test equal voting power, different age
validators[3].Tokens = sdk.NewRat(200) validators[3].Tokens = sdk.NewDec(200)
ctx = ctx.WithBlockHeight(10) ctx = ctx.WithBlockHeight(10)
keeper.UpdateValidator(ctx, validators[3]) keeper.UpdateValidator(ctx, validators[3])
resValidators = keeper.GetValidatorsByPower(ctx) resValidators = keeper.GetValidatorsByPower(ctx)
@ -310,8 +310,8 @@ func GetValidatorSortingUnmixed(t *testing.T) {
assert.True(ValEq(t, validators[4], resValidators[1])) assert.True(ValEq(t, validators[4], resValidators[1]))
// change in voting power of both validators, both still in v-set, no age change // change in voting power of both validators, both still in v-set, no age change
validators[3].Tokens = sdk.NewRat(300) validators[3].Tokens = sdk.NewDec(300)
validators[4].Tokens = sdk.NewRat(300) validators[4].Tokens = sdk.NewDec(300)
keeper.UpdateValidator(ctx, validators[3]) keeper.UpdateValidator(ctx, validators[3])
resValidators = keeper.GetValidatorsByPower(ctx) resValidators = keeper.GetValidatorsByPower(ctx)
require.Equal(t, len(resValidators), n) require.Equal(t, len(resValidators), n)
@ -338,20 +338,20 @@ func GetValidatorSortingMixed(t *testing.T) {
var validators [5]types.Validator var validators [5]types.Validator
for i, amt := range amts { for i, amt := range amts {
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
validators[i].DelegatorShares = sdk.NewRat(amt) validators[i].DelegatorShares = sdk.NewDec(amt)
} }
validators[0].Status = sdk.Bonded validators[0].Status = sdk.Bonded
validators[1].Status = sdk.Bonded validators[1].Status = sdk.Bonded
validators[2].Status = sdk.Bonded validators[2].Status = sdk.Bonded
validators[0].Tokens = sdk.NewRat(amts[0]) validators[0].Tokens = sdk.NewDec(amts[0])
validators[1].Tokens = sdk.NewRat(amts[1]) validators[1].Tokens = sdk.NewDec(amts[1])
validators[2].Tokens = sdk.NewRat(amts[2]) validators[2].Tokens = sdk.NewDec(amts[2])
validators[3].Status = sdk.Bonded validators[3].Status = sdk.Bonded
validators[4].Status = sdk.Bonded validators[4].Status = sdk.Bonded
validators[3].Tokens = sdk.NewRat(amts[3]) validators[3].Tokens = sdk.NewDec(amts[3])
validators[4].Tokens = sdk.NewRat(amts[4]) validators[4].Tokens = sdk.NewDec(amts[4])
for i := range amts { for i := range amts {
keeper.UpdateValidator(ctx, validators[i]) keeper.UpdateValidator(ctx, validators[i])
@ -375,11 +375,11 @@ func GetValidatorSortingMixed(t *testing.T) {
// first make sure everything made it in to the gotValidator group // first make sure everything made it in to the gotValidator group
resValidators := keeper.GetValidatorsByPower(ctx) resValidators := keeper.GetValidatorsByPower(ctx)
assert.Equal(t, n, len(resValidators)) assert.Equal(t, n, len(resValidators))
assert.Equal(t, sdk.NewRat(400), resValidators[0].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(400), resValidators[0].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(200), resValidators[1].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(200), resValidators[1].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(100), resValidators[2].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(100), resValidators[2].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(1), resValidators[3].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(1), resValidators[3].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(0), resValidators[4].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(0), resValidators[4].BondedTokens(), "%v", resValidators)
assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators) assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators)
assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators) assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators)
assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators) assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators)
@ -444,7 +444,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
assert.True(ValEq(t, validators[3], resValidators[1])) assert.True(ValEq(t, validators[3], resValidators[1]))
// validator 3 kicked out temporarily // validator 3 kicked out temporarily
validators[3], pool, _ = validators[3].RemoveDelShares(pool, sdk.NewRat(201)) validators[3], pool, _ = validators[3].RemoveDelShares(pool, sdk.NewDec(201))
keeper.SetPool(ctx, pool) keeper.SetPool(ctx, pool)
validators[3] = keeper.UpdateValidator(ctx, validators[3]) validators[3] = keeper.UpdateValidator(ctx, validators[3])
resValidators = keeper.GetValidatorsByPower(ctx) resValidators = keeper.GetValidatorsByPower(ctx)
@ -656,7 +656,7 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) {
// test single value change // test single value change
// tendermintUpdate set: {} -> {c1'} // tendermintUpdate set: {} -> {c1'}
validators[0].Status = sdk.Bonded validators[0].Status = sdk.Bonded
validators[0].Tokens = sdk.NewRat(600) validators[0].Tokens = sdk.NewDec(600)
validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[0] = keeper.UpdateValidator(ctx, validators[0])
updates := keeper.GetTendermintUpdates(ctx) updates := keeper.GetTendermintUpdates(ctx)
@ -794,21 +794,21 @@ func TestGetTendermintUpdatesPowerDecrease(t *testing.T) {
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
// check initial power // check initial power
require.Equal(t, sdk.NewRat(100).RoundInt64(), validators[0].GetPower().RoundInt64()) require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[0].GetPower().RoundInt64())
require.Equal(t, sdk.NewRat(100).RoundInt64(), validators[1].GetPower().RoundInt64()) require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[1].GetPower().RoundInt64())
// test multiple value change // test multiple value change
// tendermintUpdate set: {c1, c3} -> {c1', c3'} // tendermintUpdate set: {c1, c3} -> {c1', c3'}
pool := keeper.GetPool(ctx) pool := keeper.GetPool(ctx)
validators[0], pool, _ = validators[0].RemoveDelShares(pool, sdk.NewRat(20)) validators[0], pool, _ = validators[0].RemoveDelShares(pool, sdk.NewDec(20))
validators[1], pool, _ = validators[1].RemoveDelShares(pool, sdk.NewRat(30)) validators[1], pool, _ = validators[1].RemoveDelShares(pool, sdk.NewDec(30))
keeper.SetPool(ctx, pool) keeper.SetPool(ctx, pool)
validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[0] = keeper.UpdateValidator(ctx, validators[0])
validators[1] = keeper.UpdateValidator(ctx, validators[1]) validators[1] = keeper.UpdateValidator(ctx, validators[1])
// power has changed // power has changed
require.Equal(t, sdk.NewRat(80).RoundInt64(), validators[0].GetPower().RoundInt64()) require.Equal(t, sdk.NewDec(80).RoundInt64(), validators[0].GetPower().RoundInt64())
require.Equal(t, sdk.NewRat(70).RoundInt64(), validators[1].GetPower().RoundInt64()) require.Equal(t, sdk.NewDec(70).RoundInt64(), validators[1].GetPower().RoundInt64())
// Tendermint updates should reflect power change // Tendermint updates should reflect power change
updates := keeper.GetTendermintUpdates(ctx) updates := keeper.GetTendermintUpdates(ctx)

View File

@ -31,7 +31,7 @@ func SupplyInvariants(ck bank.Keeper, k stake.Keeper, am auth.AccountMapper) sim
pool := k.GetPool(ctx) pool := k.GetPool(ctx)
loose := sdk.ZeroInt() loose := sdk.ZeroInt()
bonded := sdk.ZeroRat() bonded := sdk.ZeroDec()
am.IterateAccounts(ctx, func(acc auth.Account) bool { am.IterateAccounts(ctx, func(acc auth.Account) bool {
loose = loose.Add(acc.GetCoins().AmountOf("steak")) loose = loose.Add(acc.GetCoins().AmountOf("steak"))
return false return false
@ -67,7 +67,7 @@ func PositivePowerInvariant(k stake.Keeper) simulation.Invariant {
return func(t *testing.T, app *baseapp.BaseApp, log string) { return func(t *testing.T, app *baseapp.BaseApp, log string) {
ctx := app.NewContext(false, abci.Header{}) ctx := app.NewContext(false, abci.Header{})
k.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) bool { k.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) bool {
require.True(t, validator.GetPower().GT(sdk.ZeroRat()), "validator with non-positive power stored") require.True(t, validator.GetPower().GT(sdk.ZeroDec()), "validator with non-positive power stored")
return false return false
}) })
} }

View File

@ -132,7 +132,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.
msg := stake.MsgBeginUnbonding{ msg := stake.MsgBeginUnbonding{
DelegatorAddr: delegatorAddress, DelegatorAddr: delegatorAddress,
ValidatorAddr: validatorAddress, ValidatorAddr: validatorAddress,
SharesAmount: sdk.NewRatFromInt(amount), SharesAmount: sdk.NewDecFromInt(amount),
} }
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
ctx, write := ctx.CacheContext() ctx, write := ctx.CacheContext()
@ -191,7 +191,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation
DelegatorAddr: delegatorAddress, DelegatorAddr: delegatorAddress,
ValidatorSrcAddr: sourceValidatorAddress, ValidatorSrcAddr: sourceValidatorAddress,
ValidatorDstAddr: destValidatorAddress, ValidatorDstAddr: destValidatorAddress,
SharesAmount: sdk.NewRatFromInt(amount), SharesAmount: sdk.NewDecFromInt(amount),
} }
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
ctx, write := ctx.CacheContext() ctx, write := ctx.CacheContext()
@ -247,7 +247,7 @@ func Setup(mapp *mock.App, k stake.Keeper) simulation.RandSetup {
return false return false
}) })
pool := k.GetPool(ctx) pool := k.GetPool(ctx)
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewRat(loose.Int64(), 1)) pool.LooseTokens = pool.LooseTokens.Add(sdk.NewDec(loose.Int64()))
k.SetPool(ctx, pool) k.SetPool(ctx, pool)
} }
} }

View File

@ -16,12 +16,12 @@ import (
type Delegation struct { type Delegation struct {
DelegatorAddr sdk.AccAddress `json:"delegator_addr"` DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
ValidatorAddr sdk.AccAddress `json:"validator_addr"` ValidatorAddr sdk.AccAddress `json:"validator_addr"`
Shares sdk.Rat `json:"shares"` Shares sdk.Dec `json:"shares"`
Height int64 `json:"height"` // Last height bond updated Height int64 `json:"height"` // Last height bond updated
} }
type delegationValue struct { type delegationValue struct {
Shares sdk.Rat Shares sdk.Dec
Height int64 Height int64
} }
@ -81,7 +81,7 @@ var _ sdk.Delegation = Delegation{}
// nolint - for sdk.Delegation // nolint - for sdk.Delegation
func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr } func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr }
func (d Delegation) GetValidator() sdk.AccAddress { return d.ValidatorAddr } func (d Delegation) GetValidator() sdk.AccAddress { return d.ValidatorAddr }
func (d Delegation) GetBondShares() sdk.Rat { return d.Shares } func (d Delegation) GetBondShares() sdk.Dec { return d.Shares }
// HumanReadableString returns a human readable string representation of a // HumanReadableString returns a human readable string representation of a
// Delegation. An error is returned if the Delegation's delegator or validator // Delegation. An error is returned if the Delegation's delegator or validator
@ -190,8 +190,8 @@ type Redelegation struct {
MinTime time.Time `json:"min_time"` // unix time for redelegation completion MinTime time.Time `json:"min_time"` // unix time for redelegation completion
InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started
Balance sdk.Coin `json:"balance"` // current balance Balance sdk.Coin `json:"balance"` // current balance
SharesSrc sdk.Rat `json:"shares_src"` // amount of source shares redelegating SharesSrc sdk.Dec `json:"shares_src"` // amount of source shares redelegating
SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating SharesDst sdk.Dec `json:"shares_dst"` // amount of destination shares redelegating
} }
type redValue struct { type redValue struct {
@ -199,8 +199,8 @@ type redValue struct {
MinTime time.Time MinTime time.Time
InitialBalance sdk.Coin InitialBalance sdk.Coin
Balance sdk.Coin Balance sdk.Coin
SharesSrc sdk.Rat SharesSrc sdk.Dec
SharesDst sdk.Rat SharesDst sdk.Dec
} }
// return the redelegation without fields contained within the key for the store // return the redelegation without fields contained within the key for the store

View File

@ -12,19 +12,19 @@ func TestDelegationEqual(t *testing.T) {
d1 := Delegation{ d1 := Delegation{
DelegatorAddr: addr1, DelegatorAddr: addr1,
ValidatorAddr: addr2, ValidatorAddr: addr2,
Shares: sdk.NewRat(100), Shares: sdk.NewDec(100),
} }
d2 := Delegation{ d2 := Delegation{
DelegatorAddr: addr1, DelegatorAddr: addr1,
ValidatorAddr: addr2, ValidatorAddr: addr2,
Shares: sdk.NewRat(100), Shares: sdk.NewDec(100),
} }
ok := d1.Equal(d2) ok := d1.Equal(d2)
require.True(t, ok) require.True(t, ok)
d2.ValidatorAddr = addr3 d2.ValidatorAddr = addr3
d2.Shares = sdk.NewRat(200) d2.Shares = sdk.NewDec(200)
ok = d1.Equal(d2) ok = d1.Equal(d2)
require.False(t, ok) require.False(t, ok)
@ -34,7 +34,7 @@ func TestDelegationHumanReadableString(t *testing.T) {
d := Delegation{ d := Delegation{
DelegatorAddr: addr1, DelegatorAddr: addr1,
ValidatorAddr: addr2, ValidatorAddr: addr2,
Shares: sdk.NewRat(100), Shares: sdk.NewDec(100),
} }
// NOTE: Being that the validator's keypair is random, we cannot test the // NOTE: Being that the validator's keypair is random, we cannot test the
@ -58,8 +58,8 @@ func TestUnbondingDelegationEqual(t *testing.T) {
require.True(t, ok) require.True(t, ok)
ud2.ValidatorAddr = addr3 ud2.ValidatorAddr = addr3
ud2.MinTime = time.Unix(20*20*2, 0)
ud2.MinTime = time.Unix(20*20*2, 0)
ok = ud1.Equal(ud2) ok = ud1.Equal(ud2)
require.False(t, ok) require.False(t, ok)
} }
@ -92,8 +92,8 @@ func TestRedelegationEqual(t *testing.T) {
ok := r1.Equal(r2) ok := r1.Equal(r2)
require.True(t, ok) require.True(t, ok)
r2.SharesDst = sdk.NewRat(10) r2.SharesDst = sdk.NewDec(10)
r2.SharesSrc = sdk.NewRat(20) r2.SharesSrc = sdk.NewDec(20)
r2.MinTime = time.Unix(20*20*2, 0) r2.MinTime = time.Unix(20*20*2, 0)
ok = r1.Equal(r2) ok = r1.Equal(r2)
@ -105,8 +105,8 @@ func TestRedelegationHumanReadableString(t *testing.T) {
DelegatorAddr: addr1, DelegatorAddr: addr1,
ValidatorSrcAddr: addr2, ValidatorSrcAddr: addr2,
ValidatorDstAddr: addr3, ValidatorDstAddr: addr3,
SharesDst: sdk.NewRat(10), SharesDst: sdk.NewDec(10),
SharesSrc: sdk.NewRat(20), SharesSrc: sdk.NewDec(20),
} }
// NOTE: Being that the validator's keypair is random, we cannot test the // NOTE: Being that the validator's keypair is random, we cannot test the

View File

@ -100,13 +100,6 @@ func ErrBadSharesAmount(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidDelegation, "shares must be > 0") return sdk.NewError(codespace, CodeInvalidDelegation, "shares must be > 0")
} }
func ErrBadSharesPrecision(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidDelegation,
fmt.Sprintf("shares denominator must be < %s, try reducing the number of decimal points",
maximumBondingRationalDenominator.String()),
)
}
func ErrBadSharesPercent(codespace sdk.CodespaceType) sdk.Error { func ErrBadSharesPercent(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidDelegation, "shares percent must be >0 and <=1") return sdk.NewError(codespace, CodeInvalidDelegation, "shares percent must be >0 and <=1")
} }

View File

@ -23,30 +23,30 @@ func TestGetInflation(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
setBondedTokens, setLooseTokens, setBondedTokens, setLooseTokens,
setInflation, expectedChange sdk.Rat setInflation, expectedChange sdk.Dec
}{ }{
// with 0% bonded atom supply the inflation should increase by InflationRateChange // with 0% bonded atom supply the inflation should increase by InflationRateChange
{"test 1", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(7, 100), params.InflationRateChange.Quo(hrsPerYrRat).Round(precision)}, {"test 1", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), params.InflationRateChange.Quo(hrsPerYrDec)},
// 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", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(20, 100), {"test 2", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2),
sdk.OneRat().Sub(sdk.OneRat().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)}, sdk.OneDec().Sub(sdk.OneDec().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrDec)},
// 50% bonded, starting at 10% inflation and being increased // 50% bonded, starting at 10% inflation and being increased
{"test 3", sdk.OneRat(), sdk.OneRat(), sdk.NewRat(10, 100), {"test 3", sdk.OneDec(), sdk.OneDec(), sdk.NewDecWithPrec(10, 2),
sdk.OneRat().Sub(sdk.NewRat(1, 2).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)}, sdk.OneDec().Sub(sdk.NewDecWithPrec(5, 1).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrDec)},
// test 7% minimum stop (testing with 100% bonded) // test 7% minimum stop (testing with 100% bonded)
{"test 4", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(7, 100), sdk.ZeroRat()}, {"test 4", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), sdk.ZeroDec()},
{"test 5", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(70001, 1000000), sdk.NewRat(-1, 1000000)}, {"test 5", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(70001, 6), sdk.NewDecWithPrec(-1, 6)},
// test 20% maximum stop (testing with 0% bonded) // test 20% maximum stop (testing with 0% bonded)
{"test 6", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(20, 100), sdk.ZeroRat()}, {"test 6", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2), sdk.ZeroDec()},
{"test 7", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(199999, 1000000), sdk.NewRat(1, 1000000)}, {"test 7", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(199999, 6), sdk.NewDecWithPrec(1, 6)},
// perfect balance shouldn't change inflation // perfect balance shouldn't change inflation
{"test 8", sdk.NewRat(67), sdk.NewRat(33), sdk.NewRat(15, 100), sdk.ZeroRat()}, {"test 8", sdk.NewDec(67), sdk.NewDec(33), sdk.NewDecWithPrec(15, 2), sdk.ZeroDec()},
} }
for _, tc := range tests { for _, tc := range tests {
pool.BondedTokens, pool.LooseTokens = tc.setBondedTokens, tc.setLooseTokens pool.BondedTokens, pool.LooseTokens = tc.setBondedTokens, tc.setLooseTokens
@ -67,77 +67,80 @@ func TestProcessProvisions(t *testing.T) {
var ( var (
initialTotalTokens int64 = 550000000 initialTotalTokens int64 = 550000000
cumulativeExpProvs = sdk.ZeroRat() cumulativeExpProvs = sdk.ZeroDec()
) )
pool.LooseTokens = sdk.NewRat(initialTotalTokens) pool.LooseTokens = sdk.NewDec(initialTotalTokens)
// process the provisions for a year // process the provisions for a year
for hr := 0; hr < 100; hr++ { for hr := 0; hr < 100; hr++ {
var expProvisions sdk.Rat var expProvisions sdk.Dec
_, expProvisions, pool = updateProvisions(t, pool, params, hr) _, expProvisions, pool = updateProvisions(t, pool, params, hr)
cumulativeExpProvs = cumulativeExpProvs.Add(expProvisions) cumulativeExpProvs = cumulativeExpProvs.Add(expProvisions)
} }
//get the pool and do the final value checks from checkFinalPoolValues //get the pool and do the final value checks from checkFinalPoolValues
checkFinalPoolValues(t, pool, sdk.NewRat(initialTotalTokens), cumulativeExpProvs) checkFinalPoolValues(t, pool, sdk.NewDec(initialTotalTokens), cumulativeExpProvs)
} }
//_________________________________________________________________________________________ //_________________________________________________________________________________________
////////////////////////////////HELPER FUNCTIONS BELOW///////////////////////////////////// ////////////////////////////////HELPER FUNCTIONS BELOW/////////////////////////////////////
// Final check on the global pool values for what the total tokens accumulated from each hour of provisions // Final check on the global pool values for what the total tokens accumulated from each hour of provisions
func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, cumulativeExpProvs sdk.Rat) { func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, cumulativeExpProvs sdk.Dec) {
calculatedTotalTokens := initialTotalTokens.Add(cumulativeExpProvs) calculatedTotalTokens := initialTotalTokens.Add(cumulativeExpProvs)
require.True(sdk.RatEq(t, calculatedTotalTokens, pool.TokenSupply())) require.True(sdk.DecEq(t, calculatedTotalTokens, pool.TokenSupply()))
} }
// Processes provisions are added to the pool correctly every hour // Processes provisions are added to the pool correctly every hour
// Returns expected Provisions, expected Inflation, and pool, to help with cumulative calculations back in main Tests // Returns expected Provisions, expected Inflation, and pool, to help with cumulative calculations back in main Tests
func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Rat, sdk.Rat, Pool) { func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Dec, sdk.Dec, Pool) {
expInflation := pool.NextInflation(params) expInflation := pool.NextInflation(params)
expProvisions := expInflation.Mul(pool.TokenSupply().Round(precision)).Quo(hrsPerYrRat) expProvisions := expInflation.Mul(pool.TokenSupply()).Quo(hrsPerYrDec)
startTotalSupply := pool.TokenSupply() startTotalSupply := pool.TokenSupply()
pool = pool.ProcessProvisions(params) pool = pool.ProcessProvisions(params)
//check provisions were added to pool //check provisions were added to pool
require.True(sdk.RatEq(t, startTotalSupply.Add(expProvisions), pool.TokenSupply())) require.True(sdk.DecEq(t, startTotalSupply.Add(expProvisions), pool.TokenSupply()))
return expInflation, expProvisions, pool return expInflation, expProvisions, pool
} }
// Checks that The inflation will correctly increase or decrease after an update to the pool // Checks that The inflation will correctly increase or decrease after an update to the pool
// nolint: gocyclo // nolint: gocyclo
func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation sdk.Rat, msg string) { func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation sdk.Dec, msg string) {
inflationChange := updatedInflation.Sub(previousInflation) inflationChange := updatedInflation.Sub(previousInflation)
switch { switch {
//BELOW 67% - Rate of change positive and increasing, while we are between 7% <= and < 20% inflation //BELOW 67% - Rate of change positive and increasing, while we are between 7% <= and < 20% inflation
case pool.BondedRatio().LT(sdk.NewRat(67, 100)) && updatedInflation.LT(sdk.NewRat(20, 100)): case pool.BondedRatio().LT(sdk.NewDecWithPrec(67, 2)) && updatedInflation.LT(sdk.NewDecWithPrec(20, 2)):
require.Equal(t, true, inflationChange.GT(sdk.ZeroRat()), msg) require.Equal(t, true, inflationChange.GT(sdk.ZeroDec()), msg)
//BELOW 67% - Rate of change should be 0 while inflation continually stays at 20% until we reach 67% bonded ratio //BELOW 67% - Rate of change should be 0 while inflation continually stays at 20% until we reach 67% bonded ratio
case pool.BondedRatio().LT(sdk.NewRat(67, 100)) && updatedInflation.Equal(sdk.NewRat(20, 100)): case pool.BondedRatio().LT(sdk.NewDecWithPrec(67, 2)) && updatedInflation.Equal(sdk.NewDecWithPrec(20, 2)):
if previousInflation.Equal(sdk.NewRat(20, 100)) { if previousInflation.Equal(sdk.NewDecWithPrec(20, 2)) {
require.Equal(t, true, inflationChange.IsZero(), msg) require.Equal(t, true, inflationChange.IsZero(), msg)
//This else statement covers the one off case where we first hit 20%, but we still needed a positive ROC to get to 67% bonded ratio (i.e. we went from 19.99999% to 20%) //This else statement covers the one off case where we first hit 20%, but we still needed a positive ROC to get to 67% bonded ratio (i.e. we went from 19.99999% to 20%)
} else { } else {
require.Equal(t, true, inflationChange.GT(sdk.ZeroRat()), msg) require.Equal(t, true, inflationChange.GT(sdk.ZeroDec()), msg)
} }
//ABOVE 67% - Rate of change should be negative while the bond is above 67, and should stay negative until we reach inflation of 7% //ABOVE 67% - Rate of change should be negative while the bond is above 67, and should stay negative until we reach inflation of 7%
case pool.BondedRatio().GT(sdk.NewRat(67, 100)) && updatedInflation.LT(sdk.NewRat(20, 100)) && updatedInflation.GT(sdk.NewRat(7, 100)): case pool.BondedRatio().GT(sdk.NewDecWithPrec(67, 2)) &&
require.Equal(t, true, inflationChange.LT(sdk.ZeroRat()), msg) updatedInflation.LT(sdk.NewDecWithPrec(20, 2)) && updatedInflation.GT(sdk.NewDecWithPrec(7, 2)):
require.Equal(t, true, inflationChange.LT(sdk.ZeroDec()), msg)
//ABOVE 67% - Rate of change should be 0 while inflation continually stays at 7%. //ABOVE 67% - Rate of change should be 0 while inflation continually stays at 7%.
case pool.BondedRatio().GT(sdk.NewRat(67, 100)) && updatedInflation.Equal(sdk.NewRat(7, 100)): case pool.BondedRatio().GT(sdk.NewDecWithPrec(67, 2)) &&
if previousInflation.Equal(sdk.NewRat(7, 100)) { updatedInflation.Equal(sdk.NewDecWithPrec(7, 2)):
if previousInflation.Equal(sdk.NewDecWithPrec(7, 2)) {
require.Equal(t, true, inflationChange.IsZero(), msg) require.Equal(t, true, inflationChange.IsZero(), msg)
//This else statement covers the one off case where we first hit 7%, but we still needed a negative ROC to continue to get down to 67%. (i.e. we went from 7.00001% to 7%) //This else statement covers the one off case where we first hit 7%, but we still needed a negative ROC to continue to get down to 67%. (i.e. we went from 7.00001% to 7%)
} else { } else {
require.Equal(t, true, inflationChange.LT(sdk.ZeroRat()), msg) require.Equal(t, true, inflationChange.LT(sdk.ZeroDec()), msg)
} }
} }
} }

View File

@ -1,7 +1,6 @@
package types package types
import ( import (
"math"
"reflect" "reflect"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
@ -11,18 +10,11 @@ import (
// name to idetify transaction types // name to idetify transaction types
const MsgType = "stake" const MsgType = "stake"
// Maximum amount of decimal points in the decimal representation of rationals
// used in MsgBeginUnbonding / MsgBeginRedelegate
const MaxBondDenominatorPrecision = 8
// Verify interface at compile time // Verify interface at compile time
var _, _, _ sdk.Msg = &MsgCreateValidator{}, &MsgEditValidator{}, &MsgDelegate{} var _, _, _ sdk.Msg = &MsgCreateValidator{}, &MsgEditValidator{}, &MsgDelegate{}
var _, _ sdk.Msg = &MsgBeginUnbonding{}, &MsgCompleteUnbonding{} var _, _ sdk.Msg = &MsgBeginUnbonding{}, &MsgCompleteUnbonding{}
var _, _ sdk.Msg = &MsgBeginRedelegate{}, &MsgCompleteRedelegate{} var _, _ sdk.Msg = &MsgBeginRedelegate{}, &MsgCompleteRedelegate{}
// Initialize Int for the denominator
var maximumBondingRationalDenominator = sdk.NewInt(int64(math.Pow10(MaxBondDenominatorPrecision)))
//______________________________________________________________________ //______________________________________________________________________
// MsgCreateValidator - struct for unbonding transactions // MsgCreateValidator - struct for unbonding transactions
@ -211,11 +203,11 @@ type MsgBeginRedelegate struct {
DelegatorAddr sdk.AccAddress `json:"delegator_addr"` DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
ValidatorSrcAddr sdk.AccAddress `json:"validator_src_addr"` ValidatorSrcAddr sdk.AccAddress `json:"validator_src_addr"`
ValidatorDstAddr sdk.AccAddress `json:"validator_dst_addr"` ValidatorDstAddr sdk.AccAddress `json:"validator_dst_addr"`
SharesAmount sdk.Rat `json:"shares_amount"` SharesAmount sdk.Dec `json:"shares_amount"`
} }
func NewMsgBeginRedelegate(delegatorAddr, validatorSrcAddr, func NewMsgBeginRedelegate(delegatorAddr, validatorSrcAddr,
validatorDstAddr sdk.AccAddress, sharesAmount sdk.Rat) MsgBeginRedelegate { validatorDstAddr sdk.AccAddress, sharesAmount sdk.Dec) MsgBeginRedelegate {
return MsgBeginRedelegate{ return MsgBeginRedelegate{
DelegatorAddr: delegatorAddr, DelegatorAddr: delegatorAddr,
@ -261,12 +253,9 @@ func (msg MsgBeginRedelegate) ValidateBasic() sdk.Error {
if msg.ValidatorDstAddr == nil { if msg.ValidatorDstAddr == nil {
return ErrNilValidatorAddr(DefaultCodespace) return ErrNilValidatorAddr(DefaultCodespace)
} }
if msg.SharesAmount.LTE(sdk.ZeroRat()) { if msg.SharesAmount.LTE(sdk.ZeroDec()) {
return ErrBadSharesAmount(DefaultCodespace) return ErrBadSharesAmount(DefaultCodespace)
} }
if msg.SharesAmount.Denom().GT(maximumBondingRationalDenominator) {
return ErrBadSharesPrecision(DefaultCodespace)
}
return nil return nil
} }
@ -322,10 +311,10 @@ func (msg MsgCompleteRedelegate) ValidateBasic() sdk.Error {
type MsgBeginUnbonding struct { type MsgBeginUnbonding struct {
DelegatorAddr sdk.AccAddress `json:"delegator_addr"` DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
ValidatorAddr sdk.AccAddress `json:"validator_addr"` ValidatorAddr sdk.AccAddress `json:"validator_addr"`
SharesAmount sdk.Rat `json:"shares_amount"` SharesAmount sdk.Dec `json:"shares_amount"`
} }
func NewMsgBeginUnbonding(delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Rat) MsgBeginUnbonding { func NewMsgBeginUnbonding(delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Dec) MsgBeginUnbonding {
return MsgBeginUnbonding{ return MsgBeginUnbonding{
DelegatorAddr: delegatorAddr, DelegatorAddr: delegatorAddr,
ValidatorAddr: validatorAddr, ValidatorAddr: validatorAddr,
@ -362,12 +351,9 @@ func (msg MsgBeginUnbonding) ValidateBasic() sdk.Error {
if msg.ValidatorAddr == nil { if msg.ValidatorAddr == nil {
return ErrNilValidatorAddr(DefaultCodespace) return ErrNilValidatorAddr(DefaultCodespace)
} }
if msg.SharesAmount.LTE(sdk.ZeroRat()) { if msg.SharesAmount.LTE(sdk.ZeroDec()) {
return ErrBadSharesAmount(DefaultCodespace) return ErrBadSharesAmount(DefaultCodespace)
} }
if msg.SharesAmount.Denom().GT(maximumBondingRationalDenominator) {
return ErrBadSharesPrecision(DefaultCodespace)
}
return nil return nil
} }

View File

@ -143,15 +143,15 @@ func TestMsgBeginRedelegate(t *testing.T) {
delegatorAddr sdk.AccAddress delegatorAddr sdk.AccAddress
validatorSrcAddr sdk.AccAddress validatorSrcAddr sdk.AccAddress
validatorDstAddr sdk.AccAddress validatorDstAddr sdk.AccAddress
sharesAmount sdk.Rat sharesAmount sdk.Dec
expectPass bool expectPass bool
}{ }{
{"regular", addr1, addr2, addr3, sdk.NewRat(1, 10), true}, {"regular", addr1, addr2, addr3, sdk.NewDecWithPrec(1, 1), true},
{"negative decimal", addr1, addr2, addr3, sdk.NewRat(-1, 10), false}, {"negative decimal", addr1, addr2, addr3, sdk.NewDecWithPrec(-1, 1), false},
{"zero amount", addr1, addr2, addr3, sdk.ZeroRat(), false}, {"zero amount", addr1, addr2, addr3, sdk.ZeroDec(), false},
{"empty delegator", emptyAddr, addr1, addr3, sdk.NewRat(1, 10), false}, {"empty delegator", emptyAddr, addr1, addr3, sdk.NewDecWithPrec(1, 1), false},
{"empty source validator", addr1, emptyAddr, addr3, sdk.NewRat(1, 10), false}, {"empty source validator", addr1, emptyAddr, addr3, sdk.NewDecWithPrec(1, 1), false},
{"empty destination validator", addr1, addr2, emptyAddr, sdk.NewRat(1, 10), false}, {"empty destination validator", addr1, addr2, emptyAddr, sdk.NewDecWithPrec(1, 1), false},
} }
for _, tc := range tests { for _, tc := range tests {
@ -195,14 +195,14 @@ func TestMsgBeginUnbonding(t *testing.T) {
name string name string
delegatorAddr sdk.AccAddress delegatorAddr sdk.AccAddress
validatorAddr sdk.AccAddress validatorAddr sdk.AccAddress
sharesAmount sdk.Rat sharesAmount sdk.Dec
expectPass bool expectPass bool
}{ }{
{"regular", addr1, addr2, sdk.NewRat(1, 10), true}, {"regular", addr1, addr2, sdk.NewDecWithPrec(1, 1), true},
{"negative decimal", addr1, addr2, sdk.NewRat(-1, 10), false}, {"negative decimal", addr1, addr2, sdk.NewDecWithPrec(-1, 1), false},
{"zero amount", addr1, addr2, sdk.ZeroRat(), false}, {"zero amount", addr1, addr2, sdk.ZeroDec(), false},
{"empty delegator", emptyAddr, addr1, sdk.NewRat(1, 10), false}, {"empty delegator", emptyAddr, addr1, sdk.NewDecWithPrec(1, 1), false},
{"empty validator", addr1, emptyAddr, sdk.NewRat(1, 10), false}, {"empty validator", addr1, emptyAddr, sdk.NewDecWithPrec(1, 1), false},
} }
for _, tc := range tests { for _, tc := range tests {

View File

@ -13,10 +13,10 @@ const defaultUnbondingTime time.Duration = 60 * 60 * 24 * 3 * time.Second
// Params defines the high level settings for staking // Params defines the high level settings for staking
type Params struct { type Params struct {
InflationRateChange sdk.Rat `json:"inflation_rate_change"` // maximum annual change in inflation rate InflationRateChange sdk.Dec `json:"inflation_rate_change"` // maximum annual change in inflation rate
InflationMax sdk.Rat `json:"inflation_max"` // maximum inflation rate InflationMax sdk.Dec `json:"inflation_max"` // maximum inflation rate
InflationMin sdk.Rat `json:"inflation_min"` // minimum inflation rate InflationMin sdk.Dec `json:"inflation_min"` // minimum inflation rate
GoalBonded sdk.Rat `json:"goal_bonded"` // Goal of percent bonded atoms GoalBonded sdk.Dec `json:"goal_bonded"` // Goal of percent bonded atoms
UnbondingTime time.Duration `json:"unbonding_time"` UnbondingTime time.Duration `json:"unbonding_time"`
@ -34,10 +34,10 @@ func (p Params) Equal(p2 Params) bool {
// DefaultParams returns a default set of parameters. // DefaultParams returns a default set of parameters.
func DefaultParams() Params { func DefaultParams() Params {
return Params{ return Params{
InflationRateChange: sdk.NewRat(13, 100), InflationRateChange: sdk.NewDecWithPrec(13, 2),
InflationMax: sdk.NewRat(20, 100), InflationMax: sdk.NewDecWithPrec(20, 2),
InflationMin: sdk.NewRat(7, 100), InflationMin: sdk.NewDecWithPrec(7, 2),
GoalBonded: sdk.NewRat(67, 100), GoalBonded: sdk.NewDecWithPrec(67, 2),
UnbondingTime: defaultUnbondingTime, UnbondingTime: defaultUnbondingTime,
MaxValidators: 100, MaxValidators: 100,
BondDenom: "steak", BondDenom: "steak",

View File

@ -10,15 +10,15 @@ import (
// Pool - dynamic parameters of the current state // Pool - dynamic parameters of the current state
type Pool struct { type Pool struct {
LooseTokens sdk.Rat `json:"loose_tokens"` // tokens which are not bonded in a validator LooseTokens sdk.Dec `json:"loose_tokens"` // tokens which are not bonded in a validator
BondedTokens sdk.Rat `json:"bonded_tokens"` // reserve of bonded tokens BondedTokens sdk.Dec `json:"bonded_tokens"` // reserve of bonded tokens
InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time
Inflation sdk.Rat `json:"inflation"` // current annual inflation rate Inflation sdk.Dec `json:"inflation"` // current annual inflation rate
DateLastCommissionReset int64 `json:"date_last_commission_reset"` // unix timestamp for last commission accounting reset (daily) DateLastCommissionReset int64 `json:"date_last_commission_reset"` // unix timestamp for last commission accounting reset (daily)
// Fee Related // Fee Related
PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // last recorded bonded shares - for fee calculations PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // last recorded bonded shares - for fee calculations
} }
// nolint // nolint
@ -31,48 +31,48 @@ func (p Pool) Equal(p2 Pool) bool {
// initial pool for testing // initial pool for testing
func InitialPool() Pool { func InitialPool() Pool {
return Pool{ return Pool{
LooseTokens: sdk.ZeroRat(), LooseTokens: sdk.ZeroDec(),
BondedTokens: sdk.ZeroRat(), BondedTokens: sdk.ZeroDec(),
InflationLastTime: time.Unix(0, 0), InflationLastTime: time.Unix(0, 0),
Inflation: sdk.NewRat(7, 100), Inflation: sdk.NewDecWithPrec(7, 2),
DateLastCommissionReset: 0, DateLastCommissionReset: 0,
PrevBondedShares: sdk.ZeroRat(), PrevBondedShares: sdk.ZeroDec(),
} }
} }
//____________________________________________________________________ //____________________________________________________________________
// Sum total of all staking tokens in the pool // Sum total of all staking tokens in the pool
func (p Pool) TokenSupply() sdk.Rat { func (p Pool) TokenSupply() sdk.Dec {
return p.LooseTokens.Add(p.BondedTokens) return p.LooseTokens.Add(p.BondedTokens)
} }
//____________________________________________________________________ //____________________________________________________________________
// get the bond ratio of the global state // get the bond ratio of the global state
func (p Pool) BondedRatio() sdk.Rat { func (p Pool) BondedRatio() sdk.Dec {
supply := p.TokenSupply() supply := p.TokenSupply()
if supply.GT(sdk.ZeroRat()) { if supply.GT(sdk.ZeroDec()) {
return p.BondedTokens.Quo(supply) return p.BondedTokens.Quo(supply)
} }
return sdk.ZeroRat() return sdk.ZeroDec()
} }
//_______________________________________________________________________ //_______________________________________________________________________
func (p Pool) looseTokensToBonded(bondedTokens sdk.Rat) Pool { func (p Pool) looseTokensToBonded(bondedTokens sdk.Dec) Pool {
p.BondedTokens = p.BondedTokens.Add(bondedTokens) p.BondedTokens = p.BondedTokens.Add(bondedTokens)
p.LooseTokens = p.LooseTokens.Sub(bondedTokens) p.LooseTokens = p.LooseTokens.Sub(bondedTokens)
if p.LooseTokens.LT(sdk.ZeroRat()) { if p.LooseTokens.LT(sdk.ZeroDec()) {
panic(fmt.Sprintf("sanity check: loose tokens negative, pool: %v", p)) panic(fmt.Sprintf("sanity check: loose tokens negative, pool: %v", p))
} }
return p return p
} }
func (p Pool) bondedTokensToLoose(bondedTokens sdk.Rat) Pool { func (p Pool) bondedTokensToLoose(bondedTokens sdk.Dec) Pool {
p.BondedTokens = p.BondedTokens.Sub(bondedTokens) p.BondedTokens = p.BondedTokens.Sub(bondedTokens)
p.LooseTokens = p.LooseTokens.Add(bondedTokens) p.LooseTokens = p.LooseTokens.Add(bondedTokens)
if p.BondedTokens.LT(sdk.ZeroRat()) { if p.BondedTokens.LT(sdk.ZeroDec()) {
panic(fmt.Sprintf("sanity check: bonded tokens negative, pool: %v", p)) panic(fmt.Sprintf("sanity check: bonded tokens negative, pool: %v", p))
} }
return p return p
@ -82,14 +82,14 @@ func (p Pool) bondedTokensToLoose(bondedTokens sdk.Rat) Pool {
// Inflation // Inflation
const precision = 10000 // increased to this precision for accuracy const precision = 10000 // increased to this precision for accuracy
var hrsPerYrRat = sdk.NewRat(8766) // as defined by a julian year of 365.25 days var hrsPerYrDec = sdk.NewDec(8766) // as defined by a julian year of 365.25 days
// process provisions for an hour period // process provisions for an hour period
func (p Pool) ProcessProvisions(params Params) Pool { func (p Pool) ProcessProvisions(params Params) Pool {
p.Inflation = p.NextInflation(params) p.Inflation = p.NextInflation(params)
provisions := p.Inflation. provisions := p.Inflation.
Mul(p.TokenSupply().Round(precision)). Mul(p.TokenSupply()).
Quo(hrsPerYrRat) Quo(hrsPerYrDec)
// TODO add to the fees provisions // TODO add to the fees provisions
p.LooseTokens = p.LooseTokens.Add(provisions) p.LooseTokens = p.LooseTokens.Add(provisions)
@ -97,7 +97,7 @@ func (p Pool) ProcessProvisions(params Params) Pool {
} }
// get the next inflation rate for the hour // get the next inflation rate for the hour
func (p Pool) NextInflation(params Params) (inflation sdk.Rat) { func (p Pool) NextInflation(params Params) (inflation sdk.Dec) {
// The target annual inflation rate is recalculated for each previsions cycle. The // The target annual inflation rate is recalculated for each previsions cycle. The
// inflation is also subject to a rate change (positive or negative) depending on // inflation is also subject to a rate change (positive or negative) depending on
@ -106,11 +106,11 @@ func (p Pool) NextInflation(params Params) (inflation sdk.Rat) {
// 7% and 20%. // 7% and 20%.
// (1 - bondedRatio/GoalBonded) * InflationRateChange // (1 - bondedRatio/GoalBonded) * InflationRateChange
inflationRateChangePerYear := sdk.OneRat(). inflationRateChangePerYear := sdk.OneDec().
Sub(p.BondedRatio().Round(precision). Sub(p.BondedRatio().
Quo(params.GoalBonded)). Quo(params.GoalBonded)).
Mul(params.InflationRateChange) Mul(params.InflationRateChange)
inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrRat) inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrDec)
// increase the new annual inflation for this next cycle // increase the new annual inflation for this next cycle
inflation = p.Inflation.Add(inflationRateChange) inflation = p.Inflation.Add(inflationRateChange)
@ -121,5 +121,5 @@ func (p Pool) NextInflation(params Params) (inflation sdk.Rat) {
inflation = params.InflationMin inflation = params.InflationMin
} }
return inflation.Round(precision) return inflation
} }

View File

@ -11,28 +11,28 @@ func TestPoolEqual(t *testing.T) {
p1 := InitialPool() p1 := InitialPool()
p2 := InitialPool() p2 := InitialPool()
require.True(t, p1.Equal(p2)) require.True(t, p1.Equal(p2))
p2.BondedTokens = sdk.NewRat(3) p2.BondedTokens = sdk.NewDec(3)
require.False(t, p1.Equal(p2)) require.False(t, p1.Equal(p2))
} }
func TestAddBondedTokens(t *testing.T) { func TestAddBondedTokens(t *testing.T) {
pool := InitialPool() pool := InitialPool()
pool.LooseTokens = sdk.NewRat(10) pool.LooseTokens = sdk.NewDec(10)
pool.BondedTokens = sdk.NewRat(10) pool.BondedTokens = sdk.NewDec(10)
pool = pool.looseTokensToBonded(sdk.NewRat(10)) pool = pool.looseTokensToBonded(sdk.NewDec(10))
require.True(sdk.RatEq(t, sdk.NewRat(20), pool.BondedTokens)) require.True(sdk.DecEq(t, sdk.NewDec(20), pool.BondedTokens))
require.True(sdk.RatEq(t, sdk.NewRat(0), pool.LooseTokens)) require.True(sdk.DecEq(t, sdk.NewDec(0), pool.LooseTokens))
} }
func TestRemoveBondedTokens(t *testing.T) { func TestRemoveBondedTokens(t *testing.T) {
pool := InitialPool() pool := InitialPool()
pool.LooseTokens = sdk.NewRat(10) pool.LooseTokens = sdk.NewDec(10)
pool.BondedTokens = sdk.NewRat(10) pool.BondedTokens = sdk.NewDec(10)
pool = pool.bondedTokensToLoose(sdk.NewRat(5)) pool = pool.bondedTokensToLoose(sdk.NewDec(5))
require.True(sdk.RatEq(t, sdk.NewRat(5), pool.BondedTokens)) require.True(sdk.DecEq(t, sdk.NewDec(5), pool.BondedTokens))
require.True(sdk.RatEq(t, sdk.NewRat(15), pool.LooseTokens)) require.True(sdk.DecEq(t, sdk.NewDec(15), pool.LooseTokens))
} }

View File

@ -26,21 +26,21 @@ type Validator struct {
Revoked bool `json:"revoked"` // has the validator been revoked from bonded status? Revoked bool `json:"revoked"` // has the validator been revoked from bonded status?
Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded) Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded)
Tokens sdk.Rat `json:"tokens"` // delegated tokens (incl. self-delegation) Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Rat `json:"delegator_shares"` // total shares issued to a validator's delegators DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators
Description Description `json:"description"` // description terms for the validator Description Description `json:"description"` // description terms for the validator
BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator
BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change
ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer
Commission sdk.Rat `json:"commission"` // XXX the commission rate of fees charged to any delegators Commission sdk.Dec `json:"commission"` // XXX the commission rate of fees charged to any delegators
CommissionMax sdk.Rat `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge CommissionMax sdk.Dec `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
CommissionChangeRate sdk.Rat `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission CommissionChangeRate sdk.Dec `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
CommissionChangeToday sdk.Rat `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time) CommissionChangeToday sdk.Dec `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
// fee related // fee related
LastBondedTokens sdk.Rat `json:"prev_bonded_tokens"` // Previous bonded tokens held LastBondedTokens sdk.Dec `json:"prev_bonded_tokens"` // Previous bonded tokens held
} }
// NewValidator - initialize a new validator // NewValidator - initialize a new validator
@ -50,17 +50,17 @@ func NewValidator(owner sdk.AccAddress, pubKey crypto.PubKey, description Descri
PubKey: pubKey, PubKey: pubKey,
Revoked: false, Revoked: false,
Status: sdk.Unbonded, Status: sdk.Unbonded,
Tokens: sdk.ZeroRat(), Tokens: sdk.ZeroDec(),
DelegatorShares: sdk.ZeroRat(), DelegatorShares: sdk.ZeroDec(),
Description: description, Description: description,
BondHeight: int64(0), BondHeight: int64(0),
BondIntraTxCounter: int16(0), BondIntraTxCounter: int16(0),
ProposerRewardPool: sdk.Coins{}, ProposerRewardPool: sdk.Coins{},
Commission: sdk.ZeroRat(), Commission: sdk.ZeroDec(),
CommissionMax: sdk.ZeroRat(), CommissionMax: sdk.ZeroDec(),
CommissionChangeRate: sdk.ZeroRat(), CommissionChangeRate: sdk.ZeroDec(),
CommissionChangeToday: sdk.ZeroRat(), CommissionChangeToday: sdk.ZeroDec(),
LastBondedTokens: sdk.ZeroRat(), LastBondedTokens: sdk.ZeroDec(),
} }
} }
@ -69,17 +69,17 @@ type validatorValue struct {
PubKey crypto.PubKey PubKey crypto.PubKey
Revoked bool Revoked bool
Status sdk.BondStatus Status sdk.BondStatus
Tokens sdk.Rat Tokens sdk.Dec
DelegatorShares sdk.Rat DelegatorShares sdk.Dec
Description Description Description Description
BondHeight int64 BondHeight int64
BondIntraTxCounter int16 BondIntraTxCounter int16
ProposerRewardPool sdk.Coins ProposerRewardPool sdk.Coins
Commission sdk.Rat Commission sdk.Dec
CommissionMax sdk.Rat CommissionMax sdk.Dec
CommissionChangeRate sdk.Rat CommissionChangeRate sdk.Dec
CommissionChangeToday sdk.Rat CommissionChangeToday sdk.Dec
LastBondedTokens sdk.Rat LastBondedTokens sdk.Dec
} }
// return the redelegation without fields contained within the key for the store // return the redelegation without fields contained within the key for the store
@ -159,8 +159,8 @@ func (v Validator) HumanReadableString() (string, error) {
resp += fmt.Sprintf("Validator: %s\n", bechVal) resp += fmt.Sprintf("Validator: %s\n", bechVal)
resp += fmt.Sprintf("Revoked: %v\n", v.Revoked) resp += fmt.Sprintf("Revoked: %v\n", v.Revoked)
resp += fmt.Sprintf("Status: %s\n", sdk.BondStatusToString(v.Status)) resp += fmt.Sprintf("Status: %s\n", sdk.BondStatusToString(v.Status))
resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.FloatString()) resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.String())
resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares.FloatString()) resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares.String())
resp += fmt.Sprintf("Description: %s\n", v.Description) resp += fmt.Sprintf("Description: %s\n", v.Description)
resp += fmt.Sprintf("Bond Height: %d\n", v.BondHeight) resp += fmt.Sprintf("Bond Height: %d\n", v.BondHeight)
resp += fmt.Sprintf("Proposer Reward Pool: %s\n", v.ProposerRewardPool.String()) resp += fmt.Sprintf("Proposer Reward Pool: %s\n", v.ProposerRewardPool.String())
@ -182,21 +182,21 @@ type BechValidator struct {
Revoked bool `json:"revoked"` // has the validator been revoked from bonded status? Revoked bool `json:"revoked"` // has the validator been revoked from bonded status?
Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded) Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded)
Tokens sdk.Rat `json:"tokens"` // delegated tokens (incl. self-delegation) Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Rat `json:"delegator_shares"` // total shares issued to a validator's delegators DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators
Description Description `json:"description"` // description terms for the validator Description Description `json:"description"` // description terms for the validator
BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator
BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change
ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer
Commission sdk.Rat `json:"commission"` // XXX the commission rate of fees charged to any delegators Commission sdk.Dec `json:"commission"` // XXX the commission rate of fees charged to any delegators
CommissionMax sdk.Rat `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge CommissionMax sdk.Dec `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
CommissionChangeRate sdk.Rat `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission CommissionChangeRate sdk.Dec `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
CommissionChangeToday sdk.Rat `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time) CommissionChangeToday sdk.Dec `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
// fee related // fee related
LastBondedTokens sdk.Rat `json:"prev_bonded_shares"` // last bonded token amount LastBondedTokens sdk.Dec `json:"prev_bonded_shares"` // last bonded token amount
} }
// get the bech validator from the the regular validator // get the bech validator from the the regular validator
@ -364,7 +364,7 @@ func (v Validator) UpdateStatus(pool Pool, NewStatus sdk.BondStatus) (Validator,
} }
// removes tokens from a validator // removes tokens from a validator
func (v Validator) RemoveTokens(pool Pool, tokens sdk.Rat) (Validator, Pool) { func (v Validator) RemoveTokens(pool Pool, tokens sdk.Dec) (Validator, Pool) {
if v.Status == sdk.Bonded { if v.Status == sdk.Bonded {
pool = pool.bondedTokensToLoose(tokens) pool = pool.bondedTokensToLoose(tokens)
} }
@ -376,25 +376,25 @@ func (v Validator) RemoveTokens(pool Pool, tokens sdk.Rat) (Validator, Pool) {
//_________________________________________________________________________________________________________ //_________________________________________________________________________________________________________
// AddTokensFromDel adds tokens to a validator // AddTokensFromDel adds tokens to a validator
func (v Validator) AddTokensFromDel(pool Pool, amount int64) (Validator, Pool, sdk.Rat) { func (v Validator) AddTokensFromDel(pool Pool, amount int64) (Validator, Pool, sdk.Dec) {
// bondedShare/delegatedShare // bondedShare/delegatedShare
exRate := v.DelegatorShareExRate() exRate := v.DelegatorShareExRate()
amountRat := sdk.NewRat(amount) amountDec := sdk.NewDec(amount)
if v.Status == sdk.Bonded { if v.Status == sdk.Bonded {
pool = pool.looseTokensToBonded(amountRat) pool = pool.looseTokensToBonded(amountDec)
} }
v.Tokens = v.Tokens.Add(amountRat) v.Tokens = v.Tokens.Add(amountDec)
issuedShares := amountRat.Quo(exRate) issuedShares := amountDec.Quo(exRate)
v.DelegatorShares = v.DelegatorShares.Add(issuedShares) v.DelegatorShares = v.DelegatorShares.Add(issuedShares)
return v, pool, issuedShares return v, pool, issuedShares
} }
// RemoveDelShares removes delegator shares from a validator. // RemoveDelShares removes delegator shares from a validator.
func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Rat) (Validator, Pool, sdk.Rat) { func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Dec) (Validator, Pool, sdk.Dec) {
issuedTokens := v.DelegatorShareExRate().Mul(delShares) issuedTokens := v.DelegatorShareExRate().Mul(delShares)
v.Tokens = v.Tokens.Sub(issuedTokens) v.Tokens = v.Tokens.Sub(issuedTokens)
v.DelegatorShares = v.DelegatorShares.Sub(delShares) v.DelegatorShares = v.DelegatorShares.Sub(delShares)
@ -408,19 +408,19 @@ func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Rat) (Validator, Poo
// DelegatorShareExRate gets the exchange rate of tokens over delegator shares. // DelegatorShareExRate gets the exchange rate of tokens over delegator shares.
// UNITS: tokens/delegator-shares // UNITS: tokens/delegator-shares
func (v Validator) DelegatorShareExRate() sdk.Rat { func (v Validator) DelegatorShareExRate() sdk.Dec {
if v.DelegatorShares.IsZero() { if v.DelegatorShares.IsZero() {
return sdk.OneRat() return sdk.OneDec()
} }
return v.Tokens.Quo(v.DelegatorShares) return v.Tokens.Quo(v.DelegatorShares)
} }
// Get the bonded tokens which the validator holds // Get the bonded tokens which the validator holds
func (v Validator) BondedTokens() sdk.Rat { func (v Validator) BondedTokens() sdk.Dec {
if v.Status == sdk.Bonded { if v.Status == sdk.Bonded {
return v.Tokens return v.Tokens
} }
return sdk.ZeroRat() return sdk.ZeroDec()
} }
//______________________________________________________________________ //______________________________________________________________________
@ -434,7 +434,7 @@ func (v Validator) GetMoniker() string { return v.Description.Moniker }
func (v Validator) GetStatus() sdk.BondStatus { return v.Status } func (v Validator) GetStatus() sdk.BondStatus { return v.Status }
func (v Validator) GetOwner() sdk.AccAddress { return v.Owner } func (v Validator) GetOwner() sdk.AccAddress { return v.Owner }
func (v Validator) GetPubKey() crypto.PubKey { return v.PubKey } func (v Validator) GetPubKey() crypto.PubKey { return v.PubKey }
func (v Validator) GetPower() sdk.Rat { return v.BondedTokens() } func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() }
func (v Validator) GetTokens() sdk.Rat { return v.Tokens } func (v Validator) GetTokens() sdk.Dec { return v.Tokens }
func (v Validator) GetDelegatorShares() sdk.Rat { return v.DelegatorShares } func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares }
func (v Validator) GetBondHeight() int64 { return v.BondHeight } func (v Validator) GetBondHeight() int64 { return v.BondHeight }

View File

@ -75,19 +75,19 @@ func TestRemoveTokens(t *testing.T) {
Owner: addr1, Owner: addr1,
PubKey: pk1, PubKey: pk1,
Status: sdk.Bonded, Status: sdk.Bonded,
Tokens: sdk.NewRat(100), Tokens: sdk.NewDec(100),
DelegatorShares: sdk.NewRat(100), DelegatorShares: sdk.NewDec(100),
} }
pool := InitialPool() pool := InitialPool()
pool.LooseTokens = sdk.NewRat(10) pool.LooseTokens = sdk.NewDec(10)
pool.BondedTokens = validator.BondedTokens() pool.BondedTokens = validator.BondedTokens()
validator, pool = validator.UpdateStatus(pool, sdk.Bonded) validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
require.Equal(t, sdk.Bonded, validator.Status) require.Equal(t, sdk.Bonded, validator.Status)
// remove tokens and test check everything // remove tokens and test check everything
validator, pool = validator.RemoveTokens(pool, sdk.NewRat(10)) validator, pool = validator.RemoveTokens(pool, sdk.NewDec(10))
require.Equal(t, int64(90), validator.Tokens.RoundInt64()) require.Equal(t, int64(90), validator.Tokens.RoundInt64())
require.Equal(t, int64(90), pool.BondedTokens.RoundInt64()) require.Equal(t, int64(90), pool.BondedTokens.RoundInt64())
require.Equal(t, int64(20), pool.LooseTokens.RoundInt64()) require.Equal(t, int64(20), pool.LooseTokens.RoundInt64())
@ -98,7 +98,7 @@ func TestRemoveTokens(t *testing.T) {
require.Equal(t, int64(0), pool.BondedTokens.RoundInt64()) require.Equal(t, int64(0), pool.BondedTokens.RoundInt64())
require.Equal(t, int64(110), pool.LooseTokens.RoundInt64()) require.Equal(t, int64(110), pool.LooseTokens.RoundInt64())
validator, pool = validator.RemoveTokens(pool, sdk.NewRat(10)) validator, pool = validator.RemoveTokens(pool, sdk.NewDec(10))
require.Equal(t, int64(80), validator.Tokens.RoundInt64()) require.Equal(t, int64(80), validator.Tokens.RoundInt64())
require.Equal(t, int64(0), pool.BondedTokens.RoundInt64()) require.Equal(t, int64(0), pool.BondedTokens.RoundInt64())
require.Equal(t, int64(110), pool.LooseTokens.RoundInt64()) require.Equal(t, int64(110), pool.LooseTokens.RoundInt64())
@ -106,43 +106,43 @@ func TestRemoveTokens(t *testing.T) {
func TestAddTokensValidatorBonded(t *testing.T) { func TestAddTokensValidatorBonded(t *testing.T) {
pool := InitialPool() pool := InitialPool()
pool.LooseTokens = sdk.NewRat(10) pool.LooseTokens = sdk.NewDec(10)
validator := NewValidator(addr1, pk1, Description{}) validator := NewValidator(addr1, pk1, Description{})
validator, pool = validator.UpdateStatus(pool, sdk.Bonded) validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
validator, pool, delShares := validator.AddTokensFromDel(pool, 10) validator, pool, delShares := validator.AddTokensFromDel(pool, 10)
require.Equal(t, sdk.OneRat(), validator.DelegatorShareExRate()) require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate())
assert.True(sdk.RatEq(t, sdk.NewRat(10), delShares)) assert.True(sdk.DecEq(t, sdk.NewDec(10), delShares))
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens())) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens()))
} }
func TestAddTokensValidatorUnbonding(t *testing.T) { func TestAddTokensValidatorUnbonding(t *testing.T) {
pool := InitialPool() pool := InitialPool()
pool.LooseTokens = sdk.NewRat(10) pool.LooseTokens = sdk.NewDec(10)
validator := NewValidator(addr1, pk1, Description{}) validator := NewValidator(addr1, pk1, Description{})
validator, pool = validator.UpdateStatus(pool, sdk.Unbonding) validator, pool = validator.UpdateStatus(pool, sdk.Unbonding)
validator, pool, delShares := validator.AddTokensFromDel(pool, 10) validator, pool, delShares := validator.AddTokensFromDel(pool, 10)
require.Equal(t, sdk.OneRat(), validator.DelegatorShareExRate()) require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate())
assert.True(sdk.RatEq(t, sdk.NewRat(10), delShares)) assert.True(sdk.DecEq(t, sdk.NewDec(10), delShares))
assert.Equal(t, sdk.Unbonding, validator.Status) assert.Equal(t, sdk.Unbonding, validator.Status)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
} }
func TestAddTokensValidatorUnbonded(t *testing.T) { func TestAddTokensValidatorUnbonded(t *testing.T) {
pool := InitialPool() pool := InitialPool()
pool.LooseTokens = sdk.NewRat(10) pool.LooseTokens = sdk.NewDec(10)
validator := NewValidator(addr1, pk1, Description{}) validator := NewValidator(addr1, pk1, Description{})
validator, pool = validator.UpdateStatus(pool, sdk.Unbonded) validator, pool = validator.UpdateStatus(pool, sdk.Unbonded)
validator, pool, delShares := validator.AddTokensFromDel(pool, 10) validator, pool, delShares := validator.AddTokensFromDel(pool, 10)
require.Equal(t, sdk.OneRat(), validator.DelegatorShareExRate()) require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate())
assert.True(sdk.RatEq(t, sdk.NewRat(10), delShares)) assert.True(sdk.DecEq(t, sdk.NewDec(10), delShares))
assert.Equal(t, sdk.Unbonded, validator.Status) assert.Equal(t, sdk.Unbonded, validator.Status)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
} }
// TODO refactor to make simpler like the AddToken tests above // TODO refactor to make simpler like the AddToken tests above
@ -151,16 +151,16 @@ func TestRemoveDelShares(t *testing.T) {
Owner: addr1, Owner: addr1,
PubKey: pk1, PubKey: pk1,
Status: sdk.Bonded, Status: sdk.Bonded,
Tokens: sdk.NewRat(100), Tokens: sdk.NewDec(100),
DelegatorShares: sdk.NewRat(100), DelegatorShares: sdk.NewDec(100),
} }
poolA := InitialPool() poolA := InitialPool()
poolA.LooseTokens = sdk.NewRat(10) poolA.LooseTokens = sdk.NewDec(10)
poolA.BondedTokens = valA.BondedTokens() poolA.BondedTokens = valA.BondedTokens()
require.Equal(t, valA.DelegatorShareExRate(), sdk.OneRat()) require.Equal(t, valA.DelegatorShareExRate(), sdk.OneDec())
// Remove delegator shares // Remove delegator shares
valB, poolB, coinsB := valA.RemoveDelShares(poolA, sdk.NewRat(10)) valB, poolB, coinsB := valA.RemoveDelShares(poolA, sdk.NewDec(10))
assert.Equal(t, int64(10), coinsB.RoundInt64()) assert.Equal(t, int64(10), coinsB.RoundInt64())
assert.Equal(t, int64(90), valB.DelegatorShares.RoundInt64()) assert.Equal(t, int64(90), valB.DelegatorShares.RoundInt64())
assert.Equal(t, int64(90), valB.BondedTokens().RoundInt64()) assert.Equal(t, int64(90), valB.BondedTokens().RoundInt64())
@ -168,13 +168,13 @@ func TestRemoveDelShares(t *testing.T) {
assert.Equal(t, int64(20), poolB.LooseTokens.RoundInt64()) assert.Equal(t, int64(20), poolB.LooseTokens.RoundInt64())
// conservation of tokens // conservation of tokens
require.True(sdk.RatEq(t, require.True(sdk.DecEq(t,
poolB.LooseTokens.Add(poolB.BondedTokens), poolB.LooseTokens.Add(poolB.BondedTokens),
poolA.LooseTokens.Add(poolA.BondedTokens))) poolA.LooseTokens.Add(poolA.BondedTokens)))
// specific case from random tests // specific case from random tests
poolTokens := sdk.NewRat(5102) poolTokens := sdk.NewDec(5102)
delShares := sdk.NewRat(115) delShares := sdk.NewDec(115)
validator := Validator{ validator := Validator{
Owner: addr1, Owner: addr1,
PubKey: pk1, PubKey: pk1,
@ -183,22 +183,27 @@ func TestRemoveDelShares(t *testing.T) {
DelegatorShares: delShares, DelegatorShares: delShares,
} }
pool := Pool{ pool := Pool{
BondedTokens: sdk.NewRat(248305), BondedTokens: sdk.NewDec(248305),
LooseTokens: sdk.NewRat(232147), LooseTokens: sdk.NewDec(232147),
InflationLastTime: time.Unix(0, 0), InflationLastTime: time.Unix(0, 0),
Inflation: sdk.NewRat(7, 100), Inflation: sdk.NewDecWithPrec(7, 2),
} }
shares := sdk.NewRat(29) shares := sdk.NewDec(29)
_, newPool, tokens := validator.RemoveDelShares(pool, shares) _, newPool, tokens := validator.RemoveDelShares(pool, shares)
require.True(sdk.RatEq(t, sdk.NewRat(147958, 115), tokens))
require.True(sdk.RatEq(t, exp, err := sdk.NewDecFromStr("1286.5913043477")
require.NoError(t, err)
require.True(sdk.DecEq(t, exp, tokens))
require.True(sdk.DecEq(t,
newPool.LooseTokens.Add(newPool.BondedTokens), newPool.LooseTokens.Add(newPool.BondedTokens),
pool.LooseTokens.Add(pool.BondedTokens))) pool.LooseTokens.Add(pool.BondedTokens)))
} }
func TestUpdateStatus(t *testing.T) { func TestUpdateStatus(t *testing.T) {
pool := InitialPool() pool := InitialPool()
pool.LooseTokens = sdk.NewRat(100) pool.LooseTokens = sdk.NewDec(100)
validator := NewValidator(addr1, pk1, Description{}) validator := NewValidator(addr1, pk1, Description{})
validator, pool, _ = validator.AddTokensFromDel(pool, 100) validator, pool, _ = validator.AddTokensFromDel(pool, 100)
@ -221,8 +226,8 @@ func TestUpdateStatus(t *testing.T) {
} }
func TestPossibleOverflow(t *testing.T) { func TestPossibleOverflow(t *testing.T) {
poolTokens := sdk.NewRat(2159) poolTokens := sdk.NewDec(2159)
delShares := sdk.NewRat(391432570689183511).Quo(sdk.NewRat(40113011844664)) delShares := sdk.NewDec(391432570689183511).Quo(sdk.NewDec(40113011844664))
validator := Validator{ validator := Validator{
Owner: addr1, Owner: addr1,
PubKey: pk1, PubKey: pk1,
@ -231,17 +236,17 @@ func TestPossibleOverflow(t *testing.T) {
DelegatorShares: delShares, DelegatorShares: delShares,
} }
pool := Pool{ pool := Pool{
LooseTokens: sdk.NewRat(100), LooseTokens: sdk.NewDec(100),
BondedTokens: poolTokens, BondedTokens: poolTokens,
InflationLastTime: time.Unix(0, 0), InflationLastTime: time.Unix(0, 0),
Inflation: sdk.NewRat(7, 100), Inflation: sdk.NewDecWithPrec(7, 2),
} }
tokens := int64(71) tokens := int64(71)
msg := fmt.Sprintf("validator %#v", validator) msg := fmt.Sprintf("validator %#v", validator)
newValidator, _, _ := validator.AddTokensFromDel(pool, tokens) newValidator, _, _ := validator.AddTokensFromDel(pool, tokens)
msg = fmt.Sprintf("Added %d tokens to %s", tokens, msg) msg = fmt.Sprintf("Added %d tokens to %s", tokens, msg)
require.False(t, newValidator.DelegatorShareExRate().LT(sdk.ZeroRat()), require.False(t, newValidator.DelegatorShareExRate().LT(sdk.ZeroDec()),
"Applying operation \"%s\" resulted in negative DelegatorShareExRate(): %v", "Applying operation \"%s\" resulted in negative DelegatorShareExRate(): %v",
msg, newValidator.DelegatorShareExRate()) msg, newValidator.DelegatorShareExRate())
} }