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:
parent
0adbd60dfa
commit
d9dc061b4f
|
@ -34,6 +34,7 @@ BREAKING CHANGES
|
|||
* `gaiacli gov vote --voter`
|
||||
* [x/gov] Added tags sub-package, changed tags to use dash-case
|
||||
* [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
|
||||
* [types] sdk.NewCoin now takes sdk.Int, sdk.NewInt64Coin takes int64
|
||||
* [cli] #1551: Officially removed `--name` from CLI commands
|
||||
|
|
|
@ -173,7 +173,7 @@ func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.AccAddress
|
|||
accAuth.Coins = sdk.Coins{sdk.NewInt64Coin("steak", 100)}
|
||||
acc := gapp.NewGenesisAccount(&accAuth)
|
||||
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)
|
||||
|
|
|
@ -185,7 +185,7 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState
|
|||
}
|
||||
acc := NewGenesisAccount(&accAuth)
|
||||
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
|
||||
if len(genTx.Name) > 0 {
|
||||
|
@ -193,10 +193,10 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState
|
|||
validator := stake.NewValidator(genTx.Address,
|
||||
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
|
||||
var issuedDelShares sdk.Rat
|
||||
var issuedDelShares sdk.Dec
|
||||
validator, stakeData.Pool, issuedDelShares = validator.AddTokensFromDel(stakeData.Pool, freeFermionVal)
|
||||
stakeData.Validators = append(stakeData.Validators, validator)
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ func appStateFn(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage {
|
|||
|
||||
// Default genesis state
|
||||
stakeGenesis := stake.DefaultGenesisState()
|
||||
stakeGenesis.Pool.LooseTokens = sdk.NewRat(1000)
|
||||
stakeGenesis.Pool.LooseTokens = sdk.NewDec(1000)
|
||||
genesis := GenesisState{
|
||||
Accounts: genesisAccounts,
|
||||
StakeData: stakeGenesis,
|
||||
|
|
|
@ -132,7 +132,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
|
|||
|
||||
validator := executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags))
|
||||
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
|
||||
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)
|
||||
*/
|
||||
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) {
|
||||
|
|
|
@ -25,9 +25,9 @@ type VotingProcedure struct {
|
|||
|
||||
```go
|
||||
type TallyingProcedure struct {
|
||||
Threshold rational.Rational // 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
|
||||
GovernancePenalty sdk.Rat // Penalty if validator does not vote
|
||||
Threshold sdk.Dec // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
|
||||
Veto sdk.Dec // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
|
||||
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
|
||||
}
|
||||
```
|
||||
|
@ -81,7 +81,7 @@ This type is used in a temp map when tallying
|
|||
|
||||
```go
|
||||
type ValidatorGovInfo struct {
|
||||
Minus sdk.Rat
|
||||
Minus sdk.Dec
|
||||
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
|
||||
CurrentStatus ProposalStatus // Current status of the proposal
|
||||
|
||||
YesVotes sdk.Rat
|
||||
NoVotes sdk.Rat
|
||||
NoWithVetoVotes sdk.Rat
|
||||
AbstainVotes sdk.Rat
|
||||
YesVotes sdk.Dec
|
||||
NoVotes sdk.Dec
|
||||
NoWithVetoVotes sdk.Dec
|
||||
AbstainVotes sdk.Dec
|
||||
}
|
||||
```
|
||||
|
||||
We also mention a method to update the tally for a given proposal:
|
||||
|
||||
```go
|
||||
func (proposal Proposal) updateTally(vote byte, amount sdk.Rat)
|
||||
func (proposal Proposal) updateTally(vote byte, amount sdk.Dec)
|
||||
```
|
||||
|
||||
### Stores
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
The current annual inflation rate.
|
||||
|
||||
```golang
|
||||
type Inflation sdk.Rat
|
||||
type Inflation sdk.Dec
|
||||
```
|
||||
|
||||
### InflationLastTime
|
||||
|
|
|
@ -16,4 +16,3 @@ EndBlock() ValidatorSetChanges
|
|||
ClearTendermintUpdates()
|
||||
return vsc
|
||||
```
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ type Pool struct {
|
|||
LooseTokens int64 // tokens not associated with any bonded validator
|
||||
BondedTokens int64 // reserve of bonded tokens
|
||||
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)
|
||||
}
|
||||
|
@ -28,10 +28,10 @@ overall functioning of the stake module.
|
|||
|
||||
```golang
|
||||
type Params struct {
|
||||
InflationRateChange sdk.Rat // maximum annual change in inflation rate
|
||||
InflationMax sdk.Rat // maximum inflation rate
|
||||
InflationMin sdk.Rat // minimum inflation rate
|
||||
GoalBonded sdk.Rat // Goal of percent bonded atoms
|
||||
InflationRateChange sdk.Dec // maximum annual change in inflation rate
|
||||
InflationMax sdk.Dec // maximum inflation rate
|
||||
InflationMin sdk.Dec // minimum inflation rate
|
||||
GoalBonded sdk.Dec // Goal of percent bonded atoms
|
||||
|
||||
MaxValidators uint16 // maximum number of validators
|
||||
BondDenom string // bondable coin denomination
|
||||
|
@ -74,9 +74,9 @@ type Validator struct {
|
|||
Revoked bool // has the validator been revoked?
|
||||
|
||||
Status sdk.BondStatus // validator status (bonded/unbonding/unbonded)
|
||||
Tokens sdk.Rat // delegated tokens (incl. self-delegation)
|
||||
DelegatorShares sdk.Rat // total shares issued to a validator's delegators
|
||||
SlashRatio sdk.Rat // increases each time the validator is slashed
|
||||
Tokens sdk.Dec // delegated tokens (incl. self-delegation)
|
||||
DelegatorShares sdk.Dec // total shares issued to a validator's delegators
|
||||
SlashRatio sdk.Dec // increases each time the validator is slashed
|
||||
|
||||
Description Description // description terms for the validator
|
||||
|
||||
|
@ -88,10 +88,10 @@ type Validator struct {
|
|||
}
|
||||
|
||||
type CommissionInfo struct {
|
||||
Rate sdk.Rat // the commission rate of fees charged to any delegators
|
||||
Max sdk.Rat // maximum commission rate which this validator can ever charge
|
||||
ChangeRate sdk.Rat // maximum daily increase of the validator commission
|
||||
ChangeToday sdk.Rat // commission rate change today, reset each day (UTC time)
|
||||
Rate sdk.Dec // the commission rate of fees charged to any delegators
|
||||
Max sdk.Dec // maximum commission rate which this validator can ever charge
|
||||
ChangeRate sdk.Dec // maximum daily increase of the validator commission
|
||||
ChangeToday sdk.Dec // commission rate change today, reset each day (UTC time)
|
||||
LastChange int64 // unix timestamp of last commission change
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ the transaction is the owner of the bond.
|
|||
|
||||
```golang
|
||||
type Delegation struct {
|
||||
Shares sdk.Rat // delegation shares recieved
|
||||
Shares sdk.Dec // delegation shares recieved
|
||||
Height int64 // last height bond updated
|
||||
}
|
||||
```
|
||||
|
@ -178,8 +178,8 @@ the original redelegation has been completed.
|
|||
|
||||
```golang
|
||||
type Redelegation struct {
|
||||
SourceShares sdk.Rat // amount of source shares redelegating
|
||||
DestinationShares sdk.Rat // amount of destination shares created at redelegation
|
||||
SourceShares sdk.Dec // amount of source shares redelegating
|
||||
DestinationShares sdk.Dec // amount of destination shares created at redelegation
|
||||
CompleteTime int64 // unix time to complete redelegation
|
||||
}
|
||||
```
|
||||
|
|
|
@ -18,7 +18,7 @@ Other notes:
|
|||
- `sender` denotes the address of the sender of the transaction
|
||||
- `getXxx`, `setXxx`, and `removeXxx` functions are used to retrieve and
|
||||
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
|
||||
|
||||
|
@ -34,9 +34,9 @@ type TxCreateValidator struct {
|
|||
SelfDelegation coin.Coin
|
||||
|
||||
Description Description
|
||||
Commission sdk.Rat
|
||||
CommissionMax sdk.Rat
|
||||
CommissionMaxChange sdk.Rat
|
||||
Commission sdk.Dec
|
||||
CommissionMax sdk.Dec
|
||||
CommissionMaxChange sdk.Dec
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,7 +65,7 @@ If either the `Description` (excluding `DateBonded` which is constant),
|
|||
```golang
|
||||
type TxEditCandidacy struct {
|
||||
GovernancePubKey crypto.PubKey
|
||||
Commission sdk.Rat
|
||||
Commission sdk.Dec
|
||||
Description Description
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,7 @@ type TxRedelegate struct {
|
|||
DelegatorAddr Address
|
||||
ValidatorFrom Validator
|
||||
ValidatorTo Validator
|
||||
Shares sdk.Rat
|
||||
Shares sdk.Dec
|
||||
CompletedTime int64
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
// Validator implements sdk.Validator
|
||||
type Validator struct {
|
||||
Address sdk.AccAddress
|
||||
Power sdk.Rat
|
||||
Power sdk.Dec
|
||||
}
|
||||
|
||||
// Implements sdk.Validator
|
||||
|
@ -29,18 +29,18 @@ func (v Validator) GetPubKey() crypto.PubKey {
|
|||
}
|
||||
|
||||
// Implements sdk.Validator
|
||||
func (v Validator) GetTokens() sdk.Rat {
|
||||
return sdk.ZeroRat()
|
||||
func (v Validator) GetTokens() sdk.Dec {
|
||||
return sdk.ZeroDec()
|
||||
}
|
||||
|
||||
// Implements sdk.Validator
|
||||
func (v Validator) GetPower() sdk.Rat {
|
||||
func (v Validator) GetPower() sdk.Dec {
|
||||
return v.Power
|
||||
}
|
||||
|
||||
// Implements sdk.Validator
|
||||
func (v Validator) GetDelegatorShares() sdk.Rat {
|
||||
return sdk.ZeroRat()
|
||||
func (v Validator) GetDelegatorShares() sdk.Dec {
|
||||
return sdk.ZeroDec()
|
||||
}
|
||||
|
||||
// Implements sdk.Validator
|
||||
|
@ -93,8 +93,8 @@ func (vs *ValidatorSet) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey)
|
|||
}
|
||||
|
||||
// TotalPower implements sdk.ValidatorSet
|
||||
func (vs *ValidatorSet) TotalPower(ctx sdk.Context) sdk.Rat {
|
||||
res := sdk.ZeroRat()
|
||||
func (vs *ValidatorSet) TotalPower(ctx sdk.Context) sdk.Dec {
|
||||
res := sdk.ZeroDec()
|
||||
for _, val := range vs.Validators {
|
||||
res = res.Add(val.Power)
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ func (vs *ValidatorSet) RemoveValidator(addr sdk.AccAddress) {
|
|||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@ func TestValidatorSet(t *testing.T) {
|
|||
addr2 := []byte("addr2")
|
||||
|
||||
base := &mock.ValidatorSet{[]mock.Validator{
|
||||
{addr1, sdk.NewRat(1)},
|
||||
{addr2, sdk.NewRat(2)},
|
||||
{addr1, sdk.NewDec(1)},
|
||||
{addr2, sdk.NewDec(2)},
|
||||
}}
|
||||
|
||||
valset := NewValidatorSet(wire.NewCodec(), ctx.KVStore(key).Prefix([]byte("assoc")), base, 1, 5)
|
||||
|
|
|
@ -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`.
|
||||
|
||||
```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 {
|
||||
cdc: cdc,
|
||||
key: key,
|
||||
|
|
|
@ -23,7 +23,7 @@ func (keeper Keeper) update(ctx sdk.Context, val sdk.Validator, valset sdk.Valid
|
|||
// and recalculate voted power
|
||||
hash := ctx.BlockHeader().ValidatorsHash
|
||||
if !bytes.Equal(hash, info.Hash) {
|
||||
info.Power = sdk.ZeroRat()
|
||||
info.Power = sdk.ZeroDec()
|
||||
info.Hash = hash
|
||||
prefix := GetSignPrefix(p, keeper.cdc)
|
||||
store := ctx.KVStore(keeper.key)
|
||||
|
|
|
@ -13,12 +13,12 @@ type Keeper struct {
|
|||
|
||||
valset sdk.ValidatorSet
|
||||
|
||||
supermaj sdk.Rat
|
||||
supermaj sdk.Dec
|
||||
timeout int64
|
||||
}
|
||||
|
||||
// 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 {
|
||||
panic("Timeout should not be negative")
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ const (
|
|||
|
||||
// Info for each payload
|
||||
type Info struct {
|
||||
Power sdk.Rat
|
||||
Power sdk.Dec
|
||||
Hash []byte
|
||||
LastSigned int64
|
||||
Status InfoStatus
|
||||
|
@ -55,7 +55,7 @@ type Info struct {
|
|||
// EmptyInfo construct an empty Info
|
||||
func EmptyInfo(ctx sdk.Context) Info {
|
||||
return Info{
|
||||
Power: sdk.ZeroRat(),
|
||||
Power: sdk.ZeroDec(),
|
||||
Hash: ctx.BlockHeader().ValidatorsHash,
|
||||
LastSigned: ctx.BlockHeight(),
|
||||
Status: Pending,
|
||||
|
|
|
@ -107,9 +107,9 @@ func TestOracle(t *testing.T) {
|
|||
addr3 := []byte("addr3")
|
||||
addr4 := []byte("addr4")
|
||||
valset := &mock.ValidatorSet{[]mock.Validator{
|
||||
{addr1, sdk.NewRat(7)},
|
||||
{addr2, sdk.NewRat(7)},
|
||||
{addr3, sdk.NewRat(1)},
|
||||
{addr1, sdk.NewDec(7)},
|
||||
{addr2, sdk.NewDec(7)},
|
||||
{addr3, sdk.NewDec(1)},
|
||||
}}
|
||||
|
||||
key := sdk.NewKVStoreKey("testkey")
|
||||
|
@ -119,7 +119,7 @@ func TestOracle(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
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)
|
||||
|
||||
// Nonmock.Validator signed, transaction failed
|
||||
|
@ -171,7 +171,7 @@ func TestOracle(t *testing.T) {
|
|||
require.Equal(t, 1, getSequence(ctx, key))
|
||||
|
||||
// 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)
|
||||
require.Nil(t, err)
|
||||
ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz})
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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(),
|
||||
)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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))
|
||||
}
|
||||
|
||||
}
|
|
@ -42,9 +42,9 @@ type Validator interface {
|
|||
GetStatus() BondStatus // status of the validator
|
||||
GetOwner() AccAddress // owner AccAddress to receive/return validators coins
|
||||
GetPubKey() crypto.PubKey // validation pubkey
|
||||
GetPower() Rat // validation power
|
||||
GetTokens() Rat // validation tokens
|
||||
GetDelegatorShares() Rat // Total out standing delegator shares
|
||||
GetPower() Dec // validation power
|
||||
GetTokens() Dec // validation tokens
|
||||
GetDelegatorShares() Dec // Total out standing delegator shares
|
||||
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
|
||||
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(Context, crypto.PubKey, int64, int64, Rat)
|
||||
Slash(Context, crypto.PubKey, int64, int64, Dec)
|
||||
Revoke(Context, crypto.PubKey) // revoke a validator
|
||||
Unrevoke(Context, crypto.PubKey) // unrevoke a validator
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ type ValidatorSet interface {
|
|||
type Delegation interface {
|
||||
GetDelegator() AccAddress // delegator 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
|
||||
|
|
|
@ -23,13 +23,13 @@ package stake
|
|||
////_________________________________________________________________________
|
||||
|
||||
//// 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)
|
||||
|
||||
//// get absent prevote indexes
|
||||
//absents := ctx.AbsentValidators()
|
||||
|
||||
//TotalPower := sdk.ZeroRat()
|
||||
//TotalPower := sdk.ZeroDec()
|
||||
//i := int32(0)
|
||||
//iterator := store.SubspaceIterator(ValidatorsBondedKey)
|
||||
//for ; iterator.Valid(); iterator.Next() {
|
||||
|
|
|
@ -8,8 +8,8 @@ package stake
|
|||
//var candidatesIn [5]Candidate
|
||||
//for i, amt := range amts {
|
||||
//candidatesIn[i] = NewCandidate(addrVals[i], pks[i], Description{})
|
||||
//candidatesIn[i].BondedShares = sdk.NewRat(amt)
|
||||
//candidatesIn[i].DelegatorShares = sdk.NewRat(amt)
|
||||
//candidatesIn[i].BondedShares = sdk.NewDec(amt)
|
||||
//candidatesIn[i].DelegatorShares = sdk.NewDec(amt)
|
||||
//keeper.setCandidate(ctx, candidatesIn[i])
|
||||
//}
|
||||
|
||||
|
@ -18,7 +18,7 @@ package stake
|
|||
//require.Equal(t, 5, len(gotValidators))
|
||||
|
||||
//totPow := keeper.GetTotalPrecommitVotingPower(ctx)
|
||||
//exp := sdk.NewRat(11111)
|
||||
//exp := sdk.NewDec(11111)
|
||||
//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
|
||||
|
@ -26,6 +26,6 @@ package stake
|
|||
//totPow = keeper.GetTotalPrecommitVotingPower(ctx)
|
||||
|
||||
//// 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)
|
||||
//}
|
||||
|
|
|
@ -17,7 +17,7 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {}
|
|||
|
||||
//// calculate the proposer reward
|
||||
//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)
|
||||
|
||||
//toReservePool := coinsMulRat(collectedFees, params.ReservePoolFee)
|
||||
|
@ -34,10 +34,10 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {}
|
|||
//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
|
||||
//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}}
|
||||
//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
|
||||
//func CalculateAdjustmentChange(candidate Candidate, pool Pool, denoms []string, height int64) (Candidate, Pool) {
|
||||
|
||||
//heightRat := sdk.NewRat(height)
|
||||
//lastHeightRat := sdk.NewRat(height - 1)
|
||||
//heightRat := sdk.NewDec(height)
|
||||
//lastHeightRat := sdk.NewDec(height - 1)
|
||||
//candidateFeeCount := candidate.BondedShares.Mul(heightRat)
|
||||
//poolFeeCount := pool.BondedShares.Mul(heightRat)
|
||||
|
||||
//for i, denom := range denoms {
|
||||
//poolFeeSumReceived := sdk.NewRat(pool.FeeSumReceived.AmountOf(denom))
|
||||
//poolFeeRecent := sdk.NewRat(pool.FeeRecent.AmountOf(denom))
|
||||
//poolFeeSumReceived := sdk.NewDec(pool.FeeSumReceived.AmountOf(denom))
|
||||
//poolFeeRecent := sdk.NewDec(pool.FeeRecent.AmountOf(denom))
|
||||
//// calculate simple and projected pools
|
||||
//simplePool := candidateFeeCount.Quo(poolFeeCount).Mul(poolFeeSumReceived)
|
||||
//calc1 := candidate.PrevBondedShares.Mul(lastHeightRat).Quo(pool.PrevBondedShares.Mul(lastHeightRat)).Mul(poolFeeRecent)
|
||||
|
|
|
@ -23,8 +23,8 @@ package stake
|
|||
|
||||
//// fee information for a validator
|
||||
//type Validator struct {
|
||||
//Adjustments []sdk.Rat `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
|
||||
//Adjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms
|
||||
//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
|
||||
//type Params struct {
|
||||
//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 {
|
||||
|
@ -43,7 +43,7 @@ package stake
|
|||
//func defaultParams() Params {
|
||||
//return Params{
|
||||
//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
|
||||
//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
|
||||
//FeeAdjustments []sdk.Rat `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
|
||||
//FeeAdjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms
|
||||
//PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // XXX last recorded bonded shares
|
||||
//}
|
||||
|
||||
//func (p Pool) equal(p2 Pool) bool {
|
||||
|
@ -64,7 +64,7 @@ package stake
|
|||
//p.FeePool.IsEqual(p2.FeePool) &&
|
||||
//p.FeeSumReceived.IsEqual(p2.FeeSumReceived) &&
|
||||
//p.FeeRecent.IsEqual(p2.FeeRecent) &&
|
||||
//sdk.RatsEqual(p.FeeAdjustments, p2.FeeAdjustments) &&
|
||||
//sdk.DecsEqual(p.FeeAdjustments, p2.FeeAdjustments) &&
|
||||
//p.PrevBondedShares.Equal(p2.PrevBondedShares)
|
||||
//}
|
||||
|
||||
|
@ -75,8 +75,8 @@ package stake
|
|||
//FeePool: sdk.Coins(nil),
|
||||
//FeeSumReceived: sdk.Coins(nil),
|
||||
//FeeRecent: sdk.Coins(nil),
|
||||
//FeeAdjustments: []sdk.Rat{sdk.ZeroRat()},
|
||||
//PrevBondedShares: sdk.ZeroRat(),
|
||||
//FeeAdjustments: []sdk.Dec{sdk.ZeroDec()},
|
||||
//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
|
||||
//type PowerChange struct {
|
||||
//Height int64 `json:"height"` // block height at change
|
||||
//Power sdk.Rat `json:"power"` // total power at change
|
||||
//PrevPower sdk.Rat `json:"prev_power"` // total power at previous height-1
|
||||
//Power sdk.Dec `json:"power"` // total power at change
|
||||
//PrevPower sdk.Dec `json:"prev_power"` // total power at previous height-1
|
||||
//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
|
||||
//}
|
||||
|
|
|
@ -33,9 +33,9 @@ func DefaultGenesisState() GenesisState {
|
|||
VotingPeriod: 200,
|
||||
},
|
||||
TallyingProcedure: TallyingProcedure{
|
||||
Threshold: sdk.NewRat(1, 2),
|
||||
Veto: sdk.NewRat(1, 3),
|
||||
GovernancePenalty: sdk.NewRat(1, 100),
|
||||
Threshold: sdk.NewDecWithPrec(5, 1),
|
||||
Veto: sdk.NewDecWithPrec(334, 3),
|
||||
GovernancePenalty: sdk.NewDecWithPrec(1, 2),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,9 @@ type DepositProcedure struct {
|
|||
|
||||
// Procedure around Tallying votes in governance
|
||||
type TallyingProcedure struct {
|
||||
Threshold sdk.Rat `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
|
||||
GovernancePenalty sdk.Rat `json:"governance_penalty"` // Penalty if validator does not vote
|
||||
Threshold sdk.Dec `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
|
||||
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.Dec `json:"governance_penalty"` // Penalty if validator does not vote
|
||||
}
|
||||
|
||||
// Procedure around Voting in governance
|
||||
|
|
|
@ -297,19 +297,19 @@ func (status ProposalStatus) Format(s fmt.State, verb rune) {
|
|||
//-----------------------------------------------------------
|
||||
// Tally Results
|
||||
type TallyResult struct {
|
||||
Yes sdk.Rat `json:"yes"`
|
||||
Abstain sdk.Rat `json:"abstain"`
|
||||
No sdk.Rat `json:"no"`
|
||||
NoWithVeto sdk.Rat `json:"no_with_veto"`
|
||||
Yes sdk.Dec `json:"yes"`
|
||||
Abstain sdk.Dec `json:"abstain"`
|
||||
No sdk.Dec `json:"no"`
|
||||
NoWithVeto sdk.Dec `json:"no_with_veto"`
|
||||
}
|
||||
|
||||
// checks if two proposals are equal
|
||||
func EmptyTallyResult() TallyResult {
|
||||
return TallyResult{
|
||||
Yes: sdk.ZeroRat(),
|
||||
Abstain: sdk.ZeroRat(),
|
||||
No: sdk.ZeroRat(),
|
||||
NoWithVeto: sdk.ZeroRat(),
|
||||
Yes: sdk.ZeroDec(),
|
||||
Abstain: sdk.ZeroDec(),
|
||||
No: sdk.ZeroDec(),
|
||||
NoWithVeto: sdk.ZeroDec(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,20 +7,20 @@ import (
|
|||
// validatorGovInfo used for tallying
|
||||
type validatorGovInfo struct {
|
||||
Address sdk.AccAddress // sdk.AccAddress of the validator owner
|
||||
Power sdk.Rat // Power of a Validator
|
||||
DelegatorShares sdk.Rat // Total outstanding delegator shares
|
||||
Minus sdk.Rat // Minus of validator, used to compute validator's voting power
|
||||
Power sdk.Dec // Power of a Validator
|
||||
DelegatorShares sdk.Dec // Total outstanding delegator shares
|
||||
Minus sdk.Dec // Minus of validator, used to compute validator's voting power
|
||||
Vote VoteOption // Vote of the validator
|
||||
}
|
||||
|
||||
func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult, nonVoting []sdk.AccAddress) {
|
||||
results := make(map[VoteOption]sdk.Rat)
|
||||
results[OptionYes] = sdk.ZeroRat()
|
||||
results[OptionAbstain] = sdk.ZeroRat()
|
||||
results[OptionNo] = sdk.ZeroRat()
|
||||
results[OptionNoWithVeto] = sdk.ZeroRat()
|
||||
results := make(map[VoteOption]sdk.Dec)
|
||||
results[OptionYes] = sdk.ZeroDec()
|
||||
results[OptionAbstain] = sdk.ZeroDec()
|
||||
results[OptionNo] = sdk.ZeroDec()
|
||||
results[OptionNoWithVeto] = sdk.ZeroDec()
|
||||
|
||||
totalVotingPower := sdk.ZeroRat()
|
||||
totalVotingPower := sdk.ZeroDec()
|
||||
currValidators := make(map[string]validatorGovInfo)
|
||||
|
||||
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(),
|
||||
Power: validator.GetPower(),
|
||||
DelegatorShares: validator.GetDelegatorShares(),
|
||||
Minus: sdk.ZeroRat(),
|
||||
Minus: sdk.ZeroDec(),
|
||||
Vote: OptionEmpty,
|
||||
}
|
||||
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 totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroRat()) {
|
||||
if totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroDec()) {
|
||||
return false, tallyResults, nonVoting
|
||||
}
|
||||
// If more than 1/3 of voters veto, proposal fails
|
||||
|
|
|
@ -64,7 +64,7 @@ func getInitChainer(mapp *mock.App, keeper Keeper, stakeKeeper stake.Keeper) sdk
|
|||
mapp.InitChainer(ctx, req)
|
||||
|
||||
stakeGenesis := stake.DefaultGenesisState()
|
||||
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)
|
||||
stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000)
|
||||
|
||||
validators, err := stake.InitGenesis(ctx, stakeKeeper, stakeGenesis)
|
||||
if err != nil {
|
||||
|
|
|
@ -183,8 +183,8 @@ func (k Getter) GetUint(ctx sdk.Context, key string) (res sdk.Uint, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// GetRat is helper function for rat params
|
||||
func (k Getter) GetRat(ctx sdk.Context, key string) (res sdk.Rat, err error) {
|
||||
// GetDec is helper function for decimal params
|
||||
func (k Getter) GetDec(ctx sdk.Context, key string) (res sdk.Dec, err error) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
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
|
||||
}
|
||||
|
||||
// GetRatWithDefault is helper function for sdk.Rat params with default value
|
||||
func (k Getter) GetRatWithDefault(ctx sdk.Context, key string, def sdk.Rat) (res sdk.Rat) {
|
||||
// GetDecWithDefault is helper function for sdk.Dec params with default value
|
||||
func (k Getter) GetDecWithDefault(ctx sdk.Context, key string, def sdk.Dec) (res sdk.Dec) {
|
||||
store := ctx.KVStore(k.k.key)
|
||||
bz := store.Get([]byte(key))
|
||||
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
|
||||
func (k Setter) SetRat(ctx sdk.Context, key string, param sdk.Rat) {
|
||||
// SetDec is helper function for decimal params
|
||||
func (k Setter) SetDec(ctx sdk.Context, key string, param sdk.Dec) {
|
||||
if err := k.k.set(ctx, key, param); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ func TestGetter(t *testing.T) {
|
|||
{"uint64", uint64(1)},
|
||||
{"int", sdk.NewInt(1)},
|
||||
{"uint", sdk.NewUint(1)},
|
||||
{"rat", sdk.NewRat(1)},
|
||||
{"rat", sdk.NewDec(1)},
|
||||
}
|
||||
|
||||
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.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.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 err error
|
||||
|
@ -263,18 +263,18 @@ func TestGetter(t *testing.T) {
|
|||
assert.Equal(t, def9, res)
|
||||
|
||||
// Rat
|
||||
def10 := sdk.NewRat(0)
|
||||
res, err = g.GetRat(ctx, kvs[10].key)
|
||||
def10 := sdk.NewDec(0)
|
||||
res, err = g.GetDec(ctx, kvs[10].key)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kvs[10].param, res)
|
||||
|
||||
_, err = g.GetRat(ctx, "invalid")
|
||||
_, err = g.GetDec(ctx, "invalid")
|
||||
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)
|
||||
|
||||
res = g.GetRatWithDefault(ctx, "invalid", def10)
|
||||
res = g.GetDecWithDefault(ctx, "invalid", def10)
|
||||
assert.Equal(t, def10, res)
|
||||
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ func getInitChainer(mapp *mock.App, keeper stake.Keeper) sdk.InitChainer {
|
|||
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||
mapp.InitChainer(ctx, req)
|
||||
stakeGenesis := stake.DefaultGenesisState()
|
||||
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)
|
||||
stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000)
|
||||
validators, err := stake.InitGenesis(ctx, keeper, stakeGenesis)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -109,7 +109,7 @@ func TestSlashingMsgs(t *testing.T) {
|
|||
validator := checkValidator(t, mapp, stakeKeeper, addr1, true)
|
||||
require.Equal(t, addr1, validator.Owner)
|
||||
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())}
|
||||
|
||||
// no signing info yet
|
||||
|
|
|
@ -20,7 +20,7 @@ func TestCannotUnrevokeUnlessRevoked(t *testing.T) {
|
|||
require.True(t, got.IsOK())
|
||||
stake.EndBlocker(ctx, sk)
|
||||
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
|
||||
got = slh(ctx, NewMsgUnrevoke(addr))
|
||||
|
|
|
@ -31,7 +31,7 @@ func TestHandleDoubleSign(t *testing.T) {
|
|||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||
keeper.AddValidators(ctx, validatorUpdates)
|
||||
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
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true)
|
||||
|
@ -44,12 +44,12 @@ func TestHandleDoubleSign(t *testing.T) {
|
|||
// unrevoke to measure power
|
||||
sk.Unrevoke(ctx, val)
|
||||
// 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))})
|
||||
|
||||
// double sign past max age
|
||||
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,
|
||||
|
@ -67,7 +67,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
|||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||
keeper.AddValidators(ctx, validatorUpdates)
|
||||
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()))
|
||||
require.False(t, found)
|
||||
require.Equal(t, int64(0), info.StartHeight)
|
||||
|
@ -131,7 +131,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
|||
|
||||
// validator should have been slashed
|
||||
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())
|
||||
|
||||
// validator start height should have been changed
|
||||
|
@ -177,7 +177,7 @@ func TestHandleNewValidator(t *testing.T) {
|
|||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||
keeper.AddValidators(ctx, validatorUpdates)
|
||||
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
|
||||
ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 1)
|
||||
|
|
|
@ -30,9 +30,9 @@ func (k Keeper) SignedBlocksWindow(ctx sdk.Context) int64 {
|
|||
|
||||
// Downtime slashing thershold - default 50%
|
||||
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)
|
||||
return sdk.NewRat(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64()
|
||||
return sdk.NewDec(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64()
|
||||
}
|
||||
|
||||
// Double-sign unbond duration
|
||||
|
@ -46,13 +46,13 @@ func (k Keeper) DowntimeUnbondDuration(ctx sdk.Context) time.Duration {
|
|||
}
|
||||
|
||||
// SlashFractionDoubleSign - currently default 5%
|
||||
func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) sdk.Rat {
|
||||
return k.params.GetRatWithDefault(ctx, SlashFractionDoubleSignKey, defaultSlashFractionDoubleSign)
|
||||
func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) sdk.Dec {
|
||||
return k.params.GetDecWithDefault(ctx, SlashFractionDoubleSignKey, defaultSlashFractionDoubleSign)
|
||||
}
|
||||
|
||||
// SlashFractionDowntime - currently default 1%
|
||||
func (k Keeper) SlashFractionDowntime(ctx sdk.Context) sdk.Rat {
|
||||
return k.params.GetRatWithDefault(ctx, SlashFractionDowntimeKey, defaultSlashFractionDowntime)
|
||||
func (k Keeper) SlashFractionDowntime(ctx sdk.Context) sdk.Dec {
|
||||
return k.params.GetDecWithDefault(ctx, SlashFractionDowntimeKey, defaultSlashFractionDowntime)
|
||||
}
|
||||
|
||||
// declared as var because of keeper_test.go
|
||||
|
@ -72,9 +72,9 @@ var (
|
|||
// TODO Temporarily set to 10 minutes for testnets
|
||||
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))
|
||||
)
|
||||
|
|
|
@ -69,7 +69,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para
|
|||
sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace)
|
||||
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)
|
||||
require.Nil(t, err)
|
||||
|
|
|
@ -22,7 +22,7 @@ func TestBeginBlocker(t *testing.T) {
|
|||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||
keeper.AddValidators(ctx, validatorUpdates)
|
||||
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{
|
||||
Address: pk.Address(),
|
||||
|
|
|
@ -63,7 +63,7 @@ func getInitChainer(mapp *mock.App, keeper Keeper) sdk.InitChainer {
|
|||
mapp.InitChainer(ctx, req)
|
||||
|
||||
stakeGenesis := DefaultGenesisState()
|
||||
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)
|
||||
stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000)
|
||||
|
||||
validators, err := InitGenesis(ctx, keeper, stakeGenesis)
|
||||
if err != nil {
|
||||
|
@ -90,14 +90,14 @@ func checkValidator(t *testing.T, mapp *mock.App, keeper Keeper,
|
|||
|
||||
func checkDelegation(
|
||||
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{})
|
||||
delegation, found := keeper.GetDelegation(ctxCheck, delegatorAddr, validatorAddr)
|
||||
if expFound {
|
||||
require.True(t, found)
|
||||
require.True(sdk.RatEq(t, expShares, delegation.Shares))
|
||||
require.True(sdk.DecEq(t, expShares, delegation.Shares))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ func TestStakeMsgs(t *testing.T) {
|
|||
validator := checkValidator(t, mApp, keeper, addr1, true)
|
||||
require.Equal(t, addr1, validator.Owner)
|
||||
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
|
||||
createValidatorMsgOnBehalfOf := NewMsgCreateValidatorOnBehalfOf(addr1, addr2, priv2.PubKey(), bondCoin, description)
|
||||
|
@ -150,10 +150,10 @@ func TestStakeMsgs(t *testing.T) {
|
|||
validator = checkValidator(t, mApp, keeper, addr2, true)
|
||||
require.Equal(t, addr2, validator.Owner)
|
||||
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
|
||||
checkDelegation(t, mApp, keeper, addr1, addr1, true, sdk.NewRat(10))
|
||||
checkDelegation(t, mApp, keeper, addr1, addr1, true, sdk.NewDec(10))
|
||||
|
||||
// edit the validator
|
||||
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.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
|
||||
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)
|
||||
|
||||
// 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
|
||||
mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)})
|
||||
|
|
|
@ -239,27 +239,27 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command {
|
|||
func getShares(
|
||||
storeName string, cdc *wire.Codec, sharesAmountStr,
|
||||
sharesPercentStr string, delegatorAddr, validatorAddr sdk.AccAddress,
|
||||
) (sharesAmount sdk.Rat, err error) {
|
||||
) (sharesAmount sdk.Dec, err error) {
|
||||
switch {
|
||||
case sharesAmountStr != "" && sharesPercentStr != "":
|
||||
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
|
||||
case sharesAmountStr == "" && sharesPercentStr == "":
|
||||
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
|
||||
case sharesAmountStr != "":
|
||||
sharesAmount, err = sdk.NewRatFromDecimal(sharesAmountStr, types.MaxBondDenominatorPrecision)
|
||||
sharesAmount, err = sdk.NewDecFromStr(sharesAmountStr)
|
||||
if err != nil {
|
||||
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)")
|
||||
}
|
||||
case sharesPercentStr != "":
|
||||
var sharesPercent sdk.Rat
|
||||
sharesPercent, err = sdk.NewRatFromDecimal(sharesPercentStr, types.MaxBondDenominatorPrecision)
|
||||
var sharesPercent sdk.Dec
|
||||
sharesPercent, err = sdk.NewDecFromStr(sharesPercentStr)
|
||||
if err != nil {
|
||||
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)")
|
||||
}
|
||||
|
||||
|
|
|
@ -347,7 +347,7 @@ func delegationHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handle
|
|||
DelegatorAddr: delegation.DelegatorAddr,
|
||||
ValidatorAddr: delegation.ValidatorAddr,
|
||||
Height: delegation.Height,
|
||||
Shares: delegation.Shares.FloatString(),
|
||||
Shares: delegation.Shares.String(),
|
||||
}
|
||||
|
||||
output, err := cdc.MarshalJSON(outputDelegation)
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
authcliCtx "github.com/cosmos/cosmos-sdk/x/auth/client/context"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
|
@ -160,7 +159,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex
|
|||
return
|
||||
}
|
||||
|
||||
shares, err := sdk.NewRatFromDecimal(msg.SharesAmount, types.MaxBondDenominatorPrecision)
|
||||
shares, err := sdk.NewDecFromStr(msg.SharesAmount)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
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
|
||||
}
|
||||
|
||||
shares, err := sdk.NewRatFromDecimal(msg.SharesAmount, types.MaxBondDenominatorPrecision)
|
||||
shares, err := sdk.NewDecFromStr(msg.SharesAmount)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error())))
|
||||
|
|
|
@ -76,7 +76,7 @@ func getDelegatorDelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegat
|
|||
DelegatorAddr: delegation.DelegatorAddr,
|
||||
ValidatorAddr: delegation.ValidatorAddr,
|
||||
Height: delegation.Height,
|
||||
Shares: delegation.Shares.FloatString(),
|
||||
Shares: delegation.Shares.String(),
|
||||
}
|
||||
|
||||
return outputDelegation, http.StatusOK, "", nil
|
||||
|
|
|
@ -17,7 +17,7 @@ func TestInitGenesis(t *testing.T) {
|
|||
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
||||
|
||||
pool := keeper.GetPool(ctx)
|
||||
pool.BondedTokens = sdk.NewRat(2)
|
||||
pool.BondedTokens = sdk.NewDec(2)
|
||||
|
||||
params := keeper.GetParams(ctx)
|
||||
var delegations []Delegation
|
||||
|
@ -32,11 +32,11 @@ func TestInitGenesis(t *testing.T) {
|
|||
|
||||
// initialize the validators
|
||||
validators[0].Status = sdk.Bonded
|
||||
validators[0].Tokens = sdk.OneRat()
|
||||
validators[0].DelegatorShares = sdk.OneRat()
|
||||
validators[0].Tokens = sdk.OneDec()
|
||||
validators[0].DelegatorShares = sdk.OneDec()
|
||||
validators[1].Status = sdk.Bonded
|
||||
validators[1].Tokens = sdk.OneRat()
|
||||
validators[1].DelegatorShares = sdk.OneRat()
|
||||
validators[1].Tokens = sdk.OneDec()
|
||||
validators[1].DelegatorShares = sdk.OneDec()
|
||||
|
||||
genesisState = types.NewGenesisState(pool, params, validators, delegations)
|
||||
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
|
||||
pool := keeper.GetPool(ctx)
|
||||
pool.BondedTokens = sdk.NewRat(int64(200 + (size - 100)))
|
||||
pool.BondedTokens = sdk.NewDec(int64(200 + (size - 100)))
|
||||
|
||||
params := keeper.GetParams(ctx)
|
||||
delegations := []Delegation{}
|
||||
|
@ -80,11 +80,11 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) {
|
|||
|
||||
validators[i].Status = sdk.Bonded
|
||||
if i < 100 {
|
||||
validators[i].Tokens = sdk.NewRat(2)
|
||||
validators[i].DelegatorShares = sdk.NewRat(2)
|
||||
validators[i].Tokens = sdk.NewDec(2)
|
||||
validators[i].DelegatorShares = sdk.NewDec(2)
|
||||
} else {
|
||||
validators[i].Tokens = sdk.OneRat()
|
||||
validators[i].DelegatorShares = sdk.OneRat()
|
||||
validators[i].Tokens = sdk.OneDec()
|
||||
validators[i].DelegatorShares = sdk.OneDec()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ func TestValidatorByPowerIndex(t *testing.T) {
|
|||
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
||||
|
||||
// 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])
|
||||
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
||||
require.True(t, found)
|
||||
|
@ -110,7 +110,7 @@ func TestValidatorByPowerIndex(t *testing.T) {
|
|||
require.Equal(t, power2, power3)
|
||||
|
||||
// unbond self-delegation
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(1000000))
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(1000000))
|
||||
msgCompleteUnbonding := NewMsgCompleteUnbonding(validatorAddr, validatorAddr)
|
||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||
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, addr1, validator.Owner)
|
||||
assert.Equal(t, pk1, validator.PubKey)
|
||||
assert.Equal(t, sdk.NewRat(10), validator.BondedTokens())
|
||||
assert.Equal(t, sdk.NewRat(10), validator.DelegatorShares)
|
||||
assert.Equal(t, sdk.NewDec(10), validator.BondedTokens())
|
||||
assert.Equal(t, sdk.NewDec(10), validator.DelegatorShares)
|
||||
assert.Equal(t, Description{}, validator.Description)
|
||||
|
||||
// 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, addr2, validator.Owner)
|
||||
assert.Equal(t, pk2, validator.PubKey)
|
||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
|
||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
|
||||
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, validatorAddr, validator.Owner)
|
||||
assert.Equal(t, pk, validator.PubKey)
|
||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
|
||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
|
||||
assert.Equal(t, Description{}, validator.Description)
|
||||
|
||||
// one validator cannot be created twice even from different delegator
|
||||
|
@ -221,7 +221,7 @@ func TestIncrementsMsgDelegate(t *testing.T) {
|
|||
|
||||
pool := keeper.GetPool(ctx)
|
||||
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())
|
||||
|
||||
// just send the same msgbond multiple times
|
||||
|
@ -240,7 +240,7 @@ func TestIncrementsMsgDelegate(t *testing.T) {
|
|||
require.True(t, found)
|
||||
|
||||
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
|
||||
expDelegatorShares := int64(i+2) * bondAmount // (1 self delegation)
|
||||
|
@ -295,7 +295,7 @@ func TestIncrementsMsgUnbond(t *testing.T) {
|
|||
|
||||
// just send the same msgUnbond multiple times
|
||||
// TODO use decimals here
|
||||
unbondShares := sdk.NewRat(10)
|
||||
unbondShares := sdk.NewDec(10)
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
|
||||
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
|
||||
numUnbonds := 5
|
||||
|
@ -339,7 +339,7 @@ func TestIncrementsMsgUnbond(t *testing.T) {
|
|||
initBond,
|
||||
}
|
||||
for _, c := range errorCases {
|
||||
unbondShares := sdk.NewRat(int64(c))
|
||||
unbondShares := sdk.NewDec(int64(c))
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
|
||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||
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()
|
||||
|
||||
// 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)
|
||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||
require.False(t, got.IsOK(),
|
||||
"got: %v\nmsgUnbond: %v\nshares: %v\nleftBonded: %v\n", got, msgBeginUnbonding, unbondShares.String(), leftBonded)
|
||||
|
||||
// should be able to unbond just what we have
|
||||
unbondShares = sdk.NewRat(leftBonded)
|
||||
unbondShares = sdk.NewDec(leftBonded)
|
||||
msgBeginUnbonding = NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
|
||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||
require.True(t, got.IsOK(),
|
||||
|
@ -391,7 +391,7 @@ func TestMultipleMsgCreateValidator(t *testing.T) {
|
|||
for i, validatorAddr := range validatorAddrs {
|
||||
_, found := keeper.GetValidator(ctx, validatorAddr)
|
||||
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)
|
||||
got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||
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
|
||||
for i, delegatorAddr := range delegatorAddrs {
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewRat(10))
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewDec(10))
|
||||
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
|
||||
got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||
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)
|
||||
|
||||
// unbond the validators bond portion
|
||||
msgBeginUnbondingValidator := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(10))
|
||||
msgBeginUnbondingValidator := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(10))
|
||||
msgCompleteUnbondingValidator := NewMsgCompleteUnbonding(validatorAddr, validatorAddr)
|
||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper)
|
||||
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)
|
||||
|
||||
// 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)
|
||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingDelegator, keeper)
|
||||
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")
|
||||
|
||||
// begin unbonding
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(10))
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(10))
|
||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error")
|
||||
|
||||
|
@ -565,7 +565,7 @@ func TestRedelegationPeriod(t *testing.T) {
|
|||
bal1 := AccMapper.GetAccount(ctx, validatorAddr).GetCoins()
|
||||
|
||||
// begin redelegate
|
||||
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewRat(10))
|
||||
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewDec(10))
|
||||
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
||||
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")
|
||||
|
||||
// begin redelegate
|
||||
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewRat(10))
|
||||
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewDec(10))
|
||||
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error, %v", got)
|
||||
|
||||
// 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)
|
||||
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)))
|
||||
|
||||
// unbond the valdator-2
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewRat(30))
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewDec(30))
|
||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||
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)
|
||||
|
||||
// unbond valdator-2
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewRat(30))
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewDec(30))
|
||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||
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)
|
||||
|
||||
// unbond valdator-1
|
||||
msgBeginUnbonding = NewMsgBeginUnbonding(validatorAddr1, validatorAddr1, sdk.NewRat(50))
|
||||
msgBeginUnbonding = NewMsgBeginUnbonding(validatorAddr1, validatorAddr1, sdk.NewDec(50))
|
||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
|
||||
|
||||
|
@ -832,22 +832,22 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
|
|||
ctx = ctx.WithBlockHeight(1)
|
||||
|
||||
// begin unbonding 4 stake
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(del, valA, sdk.NewRat(4))
|
||||
msgBeginUnbonding := NewMsgBeginUnbonding(del, valA, sdk.NewDec(4))
|
||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
|
||||
|
||||
// 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)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgBeginRedelegate")
|
||||
|
||||
// destination delegation should have 6 shares
|
||||
delegation, found := keeper.GetDelegation(ctx, del, valB)
|
||||
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
|
||||
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, found := keeper.GetUnbondingDelegation(ctx, del, valA)
|
||||
|
@ -862,16 +862,16 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
|
|||
// destination delegation should have been slashed by half
|
||||
delegation, found = keeper.GetDelegation(ctx, del, valB)
|
||||
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, found := keeper.GetValidator(ctx, valA)
|
||||
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
|
||||
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, found = keeper.GetUnbondingDelegation(ctx, del, valA)
|
||||
|
@ -886,7 +886,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
|
|||
// destination delegation should be unchanged
|
||||
delegation, found = keeper.GetDelegation(ctx, del, valB)
|
||||
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
|
||||
// ergo validator should have been removed from the store
|
||||
|
|
|
@ -218,7 +218,7 @@ func (k Keeper) RemoveRedelegation(ctx sdk.Context, red types.Redelegation) {
|
|||
|
||||
// Perform a delegation, set/update everything necessary within the store.
|
||||
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
|
||||
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{
|
||||
DelegatorAddr: delegatorAddr,
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
_, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr)
|
||||
|
@ -365,7 +365,7 @@ func (k Keeper) CompleteUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr
|
|||
|
||||
// complete unbonding an unbonding record
|
||||
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
|
||||
if k.HasReceivingRedelegation(ctx, delegatorAddr, validatorSrcAddr) {
|
||||
|
|
|
@ -32,7 +32,7 @@ func TestDelegation(t *testing.T) {
|
|||
bond1to1 := types.Delegation{
|
||||
DelegatorAddr: addrDels[0],
|
||||
ValidatorAddr: addrVals[0],
|
||||
Shares: sdk.NewRat(9),
|
||||
Shares: sdk.NewDec(9),
|
||||
}
|
||||
|
||||
// check the empty keeper first
|
||||
|
@ -46,18 +46,18 @@ func TestDelegation(t *testing.T) {
|
|||
require.True(t, bond1to1.Equal(resBond))
|
||||
|
||||
// modify a records, save, and retrieve
|
||||
bond1to1.Shares = sdk.NewRat(99)
|
||||
bond1to1.Shares = sdk.NewDec(99)
|
||||
keeper.SetDelegation(ctx, bond1to1)
|
||||
resBond, found = keeper.GetDelegation(ctx, addrDels[0], addrVals[0])
|
||||
require.True(t, found)
|
||||
require.True(t, bond1to1.Equal(resBond))
|
||||
|
||||
// add some more records
|
||||
bond1to2 := types.Delegation{addrDels[0], addrVals[1], sdk.NewRat(9), 0}
|
||||
bond1to3 := types.Delegation{addrDels[0], addrVals[2], sdk.NewRat(9), 1}
|
||||
bond2to1 := types.Delegation{addrDels[1], addrVals[0], sdk.NewRat(9), 2}
|
||||
bond2to2 := types.Delegation{addrDels[1], addrVals[1], sdk.NewRat(9), 3}
|
||||
bond2to3 := types.Delegation{addrDels[1], addrVals[2], sdk.NewRat(9), 4}
|
||||
bond1to2 := types.Delegation{addrDels[0], addrVals[1], sdk.NewDec(9), 0}
|
||||
bond1to3 := types.Delegation{addrDels[0], addrVals[2], sdk.NewDec(9), 1}
|
||||
bond2to1 := types.Delegation{addrDels[1], addrVals[0], sdk.NewDec(9), 2}
|
||||
bond2to2 := types.Delegation{addrDels[1], addrVals[1], sdk.NewDec(9), 3}
|
||||
bond2to3 := types.Delegation{addrDels[1], addrVals[2], sdk.NewDec(9), 4}
|
||||
keeper.SetDelegation(ctx, bond1to2)
|
||||
keeper.SetDelegation(ctx, bond1to3)
|
||||
keeper.SetDelegation(ctx, bond2to1)
|
||||
|
@ -142,7 +142,7 @@ func TestUnbondingDelegation(t *testing.T) {
|
|||
func TestUnbondDelegation(t *testing.T) {
|
||||
ctx, _, keeper := CreateTestInput(t, false, 0)
|
||||
pool := keeper.GetPool(ctx)
|
||||
pool.LooseTokens = sdk.NewRat(10)
|
||||
pool.LooseTokens = sdk.NewDec(10)
|
||||
|
||||
//create a validator and a delegator to that validator
|
||||
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
|
||||
|
@ -163,8 +163,8 @@ func TestUnbondDelegation(t *testing.T) {
|
|||
keeper.SetDelegation(ctx, delegation)
|
||||
|
||||
var err error
|
||||
var amount sdk.Rat
|
||||
amount, err = keeper.unbond(ctx, addrDels[0], addrVals[0], sdk.NewRat(6))
|
||||
var amount sdk.Dec
|
||||
amount, err = keeper.unbond(ctx, addrDels[0], addrVals[0], sdk.NewDec(6))
|
||||
require.NoError(t, err)
|
||||
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],
|
||||
CreationHeight: 0,
|
||||
MinTime: time.Unix(0, 0),
|
||||
SharesSrc: sdk.NewRat(5),
|
||||
SharesDst: sdk.NewRat(5),
|
||||
SharesSrc: sdk.NewDec(5),
|
||||
SharesDst: sdk.NewDec(5),
|
||||
}
|
||||
|
||||
// set and retrieve a record
|
||||
|
@ -220,8 +220,8 @@ func TestRedelegation(t *testing.T) {
|
|||
ValidatorDstAddr: addrVals[1],
|
||||
CreationHeight: 0,
|
||||
MinTime: time.Unix(0, 0),
|
||||
SharesSrc: sdk.NewRat(5),
|
||||
SharesDst: sdk.NewRat(5),
|
||||
SharesSrc: sdk.NewDec(5),
|
||||
SharesDst: sdk.NewDec(5),
|
||||
}
|
||||
|
||||
// test shouldn't have and redelegations
|
||||
|
@ -242,8 +242,8 @@ func TestRedelegation(t *testing.T) {
|
|||
require.True(t, has)
|
||||
|
||||
// modify a records, save, and retrieve
|
||||
rd.SharesSrc = sdk.NewRat(21)
|
||||
rd.SharesDst = sdk.NewRat(21)
|
||||
rd.SharesSrc = sdk.NewDec(21)
|
||||
rd.SharesDst = sdk.NewDec(21)
|
||||
keeper.SetRedelegation(ctx, rd)
|
||||
|
||||
resBond, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||
|
|
|
@ -33,7 +33,7 @@ func TestPool(t *testing.T) {
|
|||
require.True(t, expPool.Equal(resPool))
|
||||
|
||||
//modify a params, save, and retrieve
|
||||
expPool.BondedTokens = sdk.NewRat(777)
|
||||
expPool.BondedTokens = sdk.NewDec(777)
|
||||
keeper.SetPool(ctx, expPool)
|
||||
resPool = keeper.GetPool(ctx)
|
||||
require.True(t, expPool.Equal(resPool))
|
||||
|
|
|
@ -69,7 +69,7 @@ func (k Keeper) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) sdk.Val
|
|||
}
|
||||
|
||||
// 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)
|
||||
return pool.BondedTokens
|
||||
}
|
||||
|
|
|
@ -20,15 +20,15 @@ import (
|
|||
// CONTRACT:
|
||||
// Infraction committed at the current height or at a past height,
|
||||
// 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")
|
||||
|
||||
if slashFactor.LT(sdk.ZeroRat()) {
|
||||
if slashFactor.LT(sdk.ZeroDec()) {
|
||||
panic(fmt.Errorf("attempted to slash with a negative slashFactor: %v", slashFactor))
|
||||
}
|
||||
|
||||
// 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/1471
|
||||
|
||||
|
@ -89,7 +89,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
|
|||
}
|
||||
|
||||
// Cannot decrease balance below zero
|
||||
tokensToBurn := sdk.MinRat(remainingSlashAmount, validator.Tokens)
|
||||
tokensToBurn := sdk.MinDec(remainingSlashAmount, validator.Tokens)
|
||||
|
||||
// Get the current pool
|
||||
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
|
||||
// insufficient stake remaining)
|
||||
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
|
||||
|
||||
// If unbonding started before this height, stake didn't contribute to infraction
|
||||
if unbondingDelegation.CreationHeight < infractionHeight {
|
||||
return sdk.ZeroRat()
|
||||
return sdk.ZeroDec()
|
||||
}
|
||||
|
||||
if unbondingDelegation.MinTime.Before(now) {
|
||||
// Unbonding delegation no longer eligible for slashing, skip it
|
||||
// TODO Settle and delete it automatically?
|
||||
return sdk.ZeroRat()
|
||||
return sdk.ZeroDec()
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// insufficient stake remaining)
|
||||
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
|
||||
|
||||
// If redelegation started before this height, stake didn't contribute to infraction
|
||||
if redelegation.CreationHeight < infractionHeight {
|
||||
return sdk.ZeroRat()
|
||||
return sdk.ZeroDec()
|
||||
}
|
||||
|
||||
if redelegation.MinTime.Before(now) {
|
||||
// Redelegation no longer eligible for slashing, skip it
|
||||
// TODO Delete it automatically?
|
||||
return sdk.ZeroRat()
|
||||
return sdk.ZeroDec()
|
||||
}
|
||||
|
||||
// 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
|
||||
// Possible since the redelegation may already
|
||||
|
|
|
@ -19,7 +19,7 @@ func setupHelper(t *testing.T, amt int64) (sdk.Context, Keeper, types.Params) {
|
|||
params := keeper.GetParams(ctx)
|
||||
pool := keeper.GetPool(ctx)
|
||||
numVals := 3
|
||||
pool.LooseTokens = sdk.NewRat(amt * int64(numVals))
|
||||
pool.LooseTokens = sdk.NewDec(amt * int64(numVals))
|
||||
|
||||
// add numVals validators
|
||||
for i := 0; i < numVals; i++ {
|
||||
|
@ -63,7 +63,7 @@ func TestRevocation(t *testing.T) {
|
|||
// tests slashUnbondingDelegation
|
||||
func TestSlashUnbondingDelegation(t *testing.T) {
|
||||
ctx, keeper, params := setupHelper(t, 10)
|
||||
fraction := sdk.NewRat(1, 2)
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
// set an unbonding delegation
|
||||
ubd := types.UnbondingDelegation{
|
||||
|
@ -106,7 +106,7 @@ func TestSlashUnbondingDelegation(t *testing.T) {
|
|||
// tests slashRedelegation
|
||||
func TestSlashRedelegation(t *testing.T) {
|
||||
ctx, keeper, params := setupHelper(t, 10)
|
||||
fraction := sdk.NewRat(1, 2)
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
// set a redelegation
|
||||
rd := types.Redelegation{
|
||||
|
@ -116,8 +116,8 @@ func TestSlashRedelegation(t *testing.T) {
|
|||
CreationHeight: 0,
|
||||
// expiration timestamp (beyond which the redelegation shouldn't be slashed)
|
||||
MinTime: time.Unix(0, 0),
|
||||
SharesSrc: sdk.NewRat(10),
|
||||
SharesDst: sdk.NewRat(10),
|
||||
SharesSrc: sdk.NewDec(10),
|
||||
SharesDst: sdk.NewDec(10),
|
||||
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 10),
|
||||
Balance: sdk.NewInt64Coin(params.BondDenom, 10),
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ func TestSlashRedelegation(t *testing.T) {
|
|||
del := types.Delegation{
|
||||
DelegatorAddr: addrDels[0],
|
||||
ValidatorAddr: addrVals[1],
|
||||
Shares: sdk.NewRat(10),
|
||||
Shares: sdk.NewDec(10),
|
||||
}
|
||||
keeper.SetDelegation(ctx, del)
|
||||
|
||||
|
@ -172,7 +172,7 @@ func TestSlashRedelegation(t *testing.T) {
|
|||
func TestSlashAtFutureHeight(t *testing.T) {
|
||||
ctx, keeper, _ := setupHelper(t, 10)
|
||||
pk := PKs[0]
|
||||
fraction := sdk.NewRat(1, 2)
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
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) {
|
||||
ctx, keeper, _ := setupHelper(t, 10)
|
||||
pk := PKs[0]
|
||||
fraction := sdk.NewRat(1, 2)
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
oldPool := keeper.GetPool(ctx)
|
||||
validator, found := keeper.GetValidatorByPubKey(ctx, pk)
|
||||
|
@ -193,16 +193,16 @@ func TestSlashAtCurrentHeight(t *testing.T) {
|
|||
newPool := keeper.GetPool(ctx)
|
||||
|
||||
// power decreased
|
||||
require.Equal(t, sdk.NewRat(5), validator.GetPower())
|
||||
require.Equal(t, sdk.NewDec(5), validator.GetPower())
|
||||
// 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
|
||||
func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||
ctx, keeper, params := setupHelper(t, 10)
|
||||
pk := PKs[0]
|
||||
fraction := sdk.NewRat(1, 2)
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
// set an unbonding delegation
|
||||
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
|
||||
// bonded at the time of discovery hadn't been bonded at the time of infraction
|
||||
// and wasn't slashed
|
||||
require.Equal(t, sdk.NewRat(7), validator.GetPower())
|
||||
require.Equal(t, sdk.NewDec(7), validator.GetPower())
|
||||
|
||||
// slash validator again
|
||||
ctx = ctx.WithBlockHeight(13)
|
||||
|
@ -256,7 +256,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
|
|||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
||||
require.True(t, found)
|
||||
// power decreased by 3 again
|
||||
require.Equal(t, sdk.NewRat(4), validator.GetPower())
|
||||
require.Equal(t, sdk.NewDec(4), validator.GetPower())
|
||||
|
||||
// slash validator again
|
||||
// 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)
|
||||
require.True(t, found)
|
||||
// power decreased by 3 again
|
||||
require.Equal(t, sdk.NewRat(1), validator.GetPower())
|
||||
require.Equal(t, sdk.NewDec(1), validator.GetPower())
|
||||
|
||||
// slash validator again
|
||||
// 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) {
|
||||
ctx, keeper, params := setupHelper(t, 10)
|
||||
pk := PKs[0]
|
||||
fraction := sdk.NewRat(1, 2)
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
// set a redelegation
|
||||
rd := types.Redelegation{
|
||||
|
@ -312,8 +312,8 @@ func TestSlashWithRedelegation(t *testing.T) {
|
|||
ValidatorDstAddr: addrVals[1],
|
||||
CreationHeight: 11,
|
||||
MinTime: time.Unix(0, 0),
|
||||
SharesSrc: sdk.NewRat(6),
|
||||
SharesDst: sdk.NewRat(6),
|
||||
SharesSrc: sdk.NewDec(6),
|
||||
SharesDst: sdk.NewDec(6),
|
||||
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6),
|
||||
Balance: sdk.NewInt64Coin(params.BondDenom, 6),
|
||||
}
|
||||
|
@ -323,13 +323,13 @@ func TestSlashWithRedelegation(t *testing.T) {
|
|||
del := types.Delegation{
|
||||
DelegatorAddr: addrDels[0],
|
||||
ValidatorAddr: addrVals[1],
|
||||
Shares: sdk.NewRat(6),
|
||||
Shares: sdk.NewDec(6),
|
||||
}
|
||||
keeper.SetDelegation(ctx, del)
|
||||
|
||||
// update bonded tokens
|
||||
pool := keeper.GetPool(ctx)
|
||||
pool.BondedTokens = pool.BondedTokens.Add(sdk.NewRat(6))
|
||||
pool.BondedTokens = pool.BondedTokens.Add(sdk.NewDec(6))
|
||||
keeper.SetPool(ctx, pool)
|
||||
|
||||
// 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
|
||||
// bonded at the time of discovery hadn't been bonded at the time of infraction
|
||||
// and wasn't slashed
|
||||
require.Equal(t, sdk.NewRat(8), validator.GetPower())
|
||||
require.Equal(t, sdk.NewDec(8), validator.GetPower())
|
||||
|
||||
// slash the validator again
|
||||
ctx = ctx.WithBlockHeight(12)
|
||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
||||
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
|
||||
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)
|
||||
require.True(t, found)
|
||||
// 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%
|
||||
ctx = ctx.WithBlockHeight(12)
|
||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
||||
require.True(t, found)
|
||||
keeper.Slash(ctx, pk, 10, 10, sdk.OneRat())
|
||||
keeper.Slash(ctx, pk, 10, 10, sdk.OneDec())
|
||||
|
||||
// read updating redelegation
|
||||
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
|
||||
_, found = keeper.GetValidatorByPubKey(ctx, pk)
|
||||
require.False(t, found)
|
||||
keeper.Slash(ctx, pk, 10, 10, sdk.OneRat())
|
||||
keeper.Slash(ctx, pk, 10, 10, sdk.OneDec())
|
||||
|
||||
// read updating redelegation
|
||||
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
|
||||
func TestSlashBoth(t *testing.T) {
|
||||
ctx, keeper, params := setupHelper(t, 10)
|
||||
fraction := sdk.NewRat(1, 2)
|
||||
fraction := sdk.NewDecWithPrec(5, 1)
|
||||
|
||||
// set a redelegation
|
||||
rdA := types.Redelegation{
|
||||
|
@ -434,8 +434,8 @@ func TestSlashBoth(t *testing.T) {
|
|||
CreationHeight: 11,
|
||||
// expiration timestamp (beyond which the redelegation shouldn't be slashed)
|
||||
MinTime: time.Unix(0, 0),
|
||||
SharesSrc: sdk.NewRat(6),
|
||||
SharesDst: sdk.NewRat(6),
|
||||
SharesSrc: sdk.NewDec(6),
|
||||
SharesDst: sdk.NewDec(6),
|
||||
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6),
|
||||
Balance: sdk.NewInt64Coin(params.BondDenom, 6),
|
||||
}
|
||||
|
@ -445,7 +445,7 @@ func TestSlashBoth(t *testing.T) {
|
|||
delA := types.Delegation{
|
||||
DelegatorAddr: addrDels[0],
|
||||
ValidatorAddr: addrVals[1],
|
||||
Shares: sdk.NewRat(6),
|
||||
Shares: sdk.NewDec(6),
|
||||
}
|
||||
keeper.SetDelegation(ctx, delA)
|
||||
|
||||
|
@ -483,5 +483,5 @@ func TestSlashBoth(t *testing.T) {
|
|||
validator, found = keeper.GetValidatorByPubKey(ctx, PKs[0])
|
||||
require.True(t, found)
|
||||
// power not decreased, all stake was bonded since
|
||||
require.Equal(t, sdk.NewRat(10), validator.GetPower())
|
||||
require.Equal(t, sdk.NewDec(10), validator.GetPower())
|
||||
}
|
||||
|
|
|
@ -77,10 +77,10 @@ func MakeTestCodec() *wire.Codec {
|
|||
// default params without inflation
|
||||
func ParamsNoInflation() types.Params {
|
||||
return types.Params{
|
||||
InflationRateChange: sdk.ZeroRat(),
|
||||
InflationMax: sdk.ZeroRat(),
|
||||
InflationMin: sdk.ZeroRat(),
|
||||
GoalBonded: sdk.NewRat(67, 100),
|
||||
InflationRateChange: sdk.ZeroDec(),
|
||||
InflationMax: sdk.ZeroDec(),
|
||||
InflationMin: sdk.ZeroDec(),
|
||||
GoalBonded: sdk.NewDecWithPrec(67, 2),
|
||||
MaxValidators: 100,
|
||||
BondDenom: "steak",
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context
|
|||
{keeper.GetParams(ctx).BondDenom, sdk.NewInt(initCoins)},
|
||||
})
|
||||
require.Nil(t, err)
|
||||
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewRat(initCoins))
|
||||
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewDec(initCoins))
|
||||
keeper.SetPool(ctx, pool)
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ func TestSetValidator(t *testing.T) {
|
|||
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
|
||||
validator, pool, _ = validator.AddTokensFromDel(pool, 10)
|
||||
require.Equal(t, sdk.Unbonded, validator.Status)
|
||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
|
||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
|
||||
keeper.SetPool(ctx, pool)
|
||||
keeper.UpdateValidator(ctx, validator)
|
||||
|
||||
|
@ -29,8 +29,8 @@ func TestSetValidator(t *testing.T) {
|
|||
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Equal(t, sdk.Bonded, validator.Status)
|
||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
|
||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
|
||||
|
||||
// Check each store for being saved
|
||||
resVal, found := keeper.GetValidator(ctx, addrVals[0])
|
||||
|
@ -56,8 +56,8 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) {
|
|||
pool := keeper.GetPool(ctx)
|
||||
|
||||
// create a random pool
|
||||
pool.LooseTokens = sdk.NewRat(10000)
|
||||
pool.BondedTokens = sdk.NewRat(1234)
|
||||
pool.LooseTokens = sdk.NewDec(10000)
|
||||
pool.BondedTokens = sdk.NewDec(1234)
|
||||
keeper.SetPool(ctx, pool)
|
||||
|
||||
// add a validator
|
||||
|
@ -76,7 +76,7 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) {
|
|||
require.True(t, keeper.validatorByPowerIndexExists(ctx, power))
|
||||
|
||||
// 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())
|
||||
keeper.SetPool(ctx, pool) // update the pool
|
||||
keeper.UpdateValidator(ctx, validator) // update the validator, possibly kicking it out
|
||||
|
@ -103,8 +103,8 @@ func TestCliffValidatorChange(t *testing.T) {
|
|||
keeper.SetParams(ctx, params)
|
||||
|
||||
// create a random pool
|
||||
pool.LooseTokens = sdk.NewRat(10000)
|
||||
pool.BondedTokens = sdk.NewRat(1234)
|
||||
pool.LooseTokens = sdk.NewDec(10000)
|
||||
pool.BondedTokens = sdk.NewDec(1234)
|
||||
keeper.SetPool(ctx, pool)
|
||||
|
||||
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)
|
||||
|
||||
// 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
|
||||
_, found := keeper.GetValidator(ctx, addrVals[0])
|
||||
require.False(t, found)
|
||||
|
@ -178,13 +178,13 @@ func TestValidatorBasics(t *testing.T) {
|
|||
for i, amt := range amts {
|
||||
validators[i] = types.NewValidator(addrVals[i], PKs[i], types.Description{})
|
||||
validators[i].Status = sdk.Unbonded
|
||||
validators[i].Tokens = sdk.ZeroRat()
|
||||
validators[i].Tokens = sdk.ZeroDec()
|
||||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
|
||||
keeper.SetPool(ctx, pool)
|
||||
}
|
||||
assert.True(sdk.RatEq(t, sdk.NewRat(9), validators[0].Tokens))
|
||||
assert.True(sdk.RatEq(t, sdk.NewRat(8), validators[1].Tokens))
|
||||
assert.True(sdk.RatEq(t, sdk.NewRat(7), validators[2].Tokens))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(9), validators[0].Tokens))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(8), validators[1].Tokens))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(7), validators[2].Tokens))
|
||||
|
||||
// check the empty keeper first
|
||||
_, found := keeper.GetValidator(ctx, addrVals[0])
|
||||
|
@ -193,7 +193,7 @@ func TestValidatorBasics(t *testing.T) {
|
|||
assert.Zero(t, len(resVals))
|
||||
|
||||
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
|
||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||
|
@ -205,15 +205,15 @@ func TestValidatorBasics(t *testing.T) {
|
|||
require.Equal(t, 1, len(resVals))
|
||||
assert.True(ValEq(t, validators[0], resVals[0]))
|
||||
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)
|
||||
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
|
||||
validators[0].Status = sdk.Bonded
|
||||
validators[0].Tokens = sdk.NewRat(10)
|
||||
validators[0].DelegatorShares = sdk.NewRat(10)
|
||||
validators[0].Tokens = sdk.NewDec(10)
|
||||
validators[0].DelegatorShares = sdk.NewDec(10)
|
||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||
resVal, found = keeper.GetValidator(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
|
@ -256,19 +256,19 @@ func GetValidatorSortingUnmixed(t *testing.T) {
|
|||
for i, amt := range amts {
|
||||
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
||||
validators[i].Status = sdk.Bonded
|
||||
validators[i].Tokens = sdk.NewRat(amt)
|
||||
validators[i].DelegatorShares = sdk.NewRat(amt)
|
||||
validators[i].Tokens = sdk.NewDec(amt)
|
||||
validators[i].DelegatorShares = sdk.NewDec(amt)
|
||||
keeper.UpdateValidator(ctx, validators[i])
|
||||
}
|
||||
|
||||
// first make sure everything made it in to the gotValidator group
|
||||
resValidators := keeper.GetValidatorsByPower(ctx)
|
||||
assert.Equal(t, n, len(resValidators))
|
||||
assert.Equal(t, sdk.NewRat(400), resValidators[0].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewRat(200), resValidators[1].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewRat(100), resValidators[2].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewRat(1), resValidators[3].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewRat(0), resValidators[4].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewDec(400), resValidators[0].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewDec(200), resValidators[1].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewDec(100), resValidators[2].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewDec(1), resValidators[3].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[4].Owner, resValidators[1].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)
|
||||
|
||||
// test a basic increase in voting power
|
||||
validators[3].Tokens = sdk.NewRat(500)
|
||||
validators[3].Tokens = sdk.NewDec(500)
|
||||
keeper.UpdateValidator(ctx, validators[3])
|
||||
resValidators = keeper.GetValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n)
|
||||
assert.True(ValEq(t, validators[3], resValidators[0]))
|
||||
|
||||
// test a decrease in voting power
|
||||
validators[3].Tokens = sdk.NewRat(300)
|
||||
validators[3].Tokens = sdk.NewDec(300)
|
||||
keeper.UpdateValidator(ctx, validators[3])
|
||||
resValidators = keeper.GetValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n)
|
||||
|
@ -291,7 +291,7 @@ func GetValidatorSortingUnmixed(t *testing.T) {
|
|||
assert.True(ValEq(t, validators[4], resValidators[1]))
|
||||
|
||||
// test equal voting power, different age
|
||||
validators[3].Tokens = sdk.NewRat(200)
|
||||
validators[3].Tokens = sdk.NewDec(200)
|
||||
ctx = ctx.WithBlockHeight(10)
|
||||
keeper.UpdateValidator(ctx, validators[3])
|
||||
resValidators = keeper.GetValidatorsByPower(ctx)
|
||||
|
@ -310,8 +310,8 @@ func GetValidatorSortingUnmixed(t *testing.T) {
|
|||
assert.True(ValEq(t, validators[4], resValidators[1]))
|
||||
|
||||
// change in voting power of both validators, both still in v-set, no age change
|
||||
validators[3].Tokens = sdk.NewRat(300)
|
||||
validators[4].Tokens = sdk.NewRat(300)
|
||||
validators[3].Tokens = sdk.NewDec(300)
|
||||
validators[4].Tokens = sdk.NewDec(300)
|
||||
keeper.UpdateValidator(ctx, validators[3])
|
||||
resValidators = keeper.GetValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n)
|
||||
|
@ -338,20 +338,20 @@ func GetValidatorSortingMixed(t *testing.T) {
|
|||
var validators [5]types.Validator
|
||||
for i, amt := range amts {
|
||||
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[1].Status = sdk.Bonded
|
||||
validators[2].Status = sdk.Bonded
|
||||
validators[0].Tokens = sdk.NewRat(amts[0])
|
||||
validators[1].Tokens = sdk.NewRat(amts[1])
|
||||
validators[2].Tokens = sdk.NewRat(amts[2])
|
||||
validators[0].Tokens = sdk.NewDec(amts[0])
|
||||
validators[1].Tokens = sdk.NewDec(amts[1])
|
||||
validators[2].Tokens = sdk.NewDec(amts[2])
|
||||
|
||||
validators[3].Status = sdk.Bonded
|
||||
validators[4].Status = sdk.Bonded
|
||||
validators[3].Tokens = sdk.NewRat(amts[3])
|
||||
validators[4].Tokens = sdk.NewRat(amts[4])
|
||||
validators[3].Tokens = sdk.NewDec(amts[3])
|
||||
validators[4].Tokens = sdk.NewDec(amts[4])
|
||||
|
||||
for i := range amts {
|
||||
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
|
||||
resValidators := keeper.GetValidatorsByPower(ctx)
|
||||
assert.Equal(t, n, len(resValidators))
|
||||
assert.Equal(t, sdk.NewRat(400), resValidators[0].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewRat(200), resValidators[1].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewRat(100), resValidators[2].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewRat(1), resValidators[3].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewRat(0), resValidators[4].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewDec(400), resValidators[0].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewDec(200), resValidators[1].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewDec(100), resValidators[2].BondedTokens(), "%v", resValidators)
|
||||
assert.Equal(t, sdk.NewDec(1), resValidators[3].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[4].Owner, resValidators[1].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]))
|
||||
|
||||
// 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)
|
||||
validators[3] = keeper.UpdateValidator(ctx, validators[3])
|
||||
resValidators = keeper.GetValidatorsByPower(ctx)
|
||||
|
@ -656,7 +656,7 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) {
|
|||
// test single value change
|
||||
// tendermintUpdate set: {} -> {c1'}
|
||||
validators[0].Status = sdk.Bonded
|
||||
validators[0].Tokens = sdk.NewRat(600)
|
||||
validators[0].Tokens = sdk.NewDec(600)
|
||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||
|
||||
updates := keeper.GetTendermintUpdates(ctx)
|
||||
|
@ -794,21 +794,21 @@ func TestGetTendermintUpdatesPowerDecrease(t *testing.T) {
|
|||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
||||
|
||||
// check initial power
|
||||
require.Equal(t, sdk.NewRat(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[0].GetPower().RoundInt64())
|
||||
require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[1].GetPower().RoundInt64())
|
||||
|
||||
// test multiple value change
|
||||
// tendermintUpdate set: {c1, c3} -> {c1', c3'}
|
||||
pool := keeper.GetPool(ctx)
|
||||
validators[0], pool, _ = validators[0].RemoveDelShares(pool, sdk.NewRat(20))
|
||||
validators[1], pool, _ = validators[1].RemoveDelShares(pool, sdk.NewRat(30))
|
||||
validators[0], pool, _ = validators[0].RemoveDelShares(pool, sdk.NewDec(20))
|
||||
validators[1], pool, _ = validators[1].RemoveDelShares(pool, sdk.NewDec(30))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||
|
||||
// power has changed
|
||||
require.Equal(t, sdk.NewRat(80).RoundInt64(), validators[0].GetPower().RoundInt64())
|
||||
require.Equal(t, sdk.NewRat(70).RoundInt64(), validators[1].GetPower().RoundInt64())
|
||||
require.Equal(t, sdk.NewDec(80).RoundInt64(), validators[0].GetPower().RoundInt64())
|
||||
require.Equal(t, sdk.NewDec(70).RoundInt64(), validators[1].GetPower().RoundInt64())
|
||||
|
||||
// Tendermint updates should reflect power change
|
||||
updates := keeper.GetTendermintUpdates(ctx)
|
||||
|
|
|
@ -31,7 +31,7 @@ func SupplyInvariants(ck bank.Keeper, k stake.Keeper, am auth.AccountMapper) sim
|
|||
pool := k.GetPool(ctx)
|
||||
|
||||
loose := sdk.ZeroInt()
|
||||
bonded := sdk.ZeroRat()
|
||||
bonded := sdk.ZeroDec()
|
||||
am.IterateAccounts(ctx, func(acc auth.Account) bool {
|
||||
loose = loose.Add(acc.GetCoins().AmountOf("steak"))
|
||||
return false
|
||||
|
@ -67,7 +67,7 @@ func PositivePowerInvariant(k stake.Keeper) simulation.Invariant {
|
|||
return func(t *testing.T, app *baseapp.BaseApp, log string) {
|
||||
ctx := app.NewContext(false, abci.Header{})
|
||||
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
|
||||
})
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.
|
|||
msg := stake.MsgBeginUnbonding{
|
||||
DelegatorAddr: delegatorAddress,
|
||||
ValidatorAddr: validatorAddress,
|
||||
SharesAmount: sdk.NewRatFromInt(amount),
|
||||
SharesAmount: sdk.NewDecFromInt(amount),
|
||||
}
|
||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||
ctx, write := ctx.CacheContext()
|
||||
|
@ -191,7 +191,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation
|
|||
DelegatorAddr: delegatorAddress,
|
||||
ValidatorSrcAddr: sourceValidatorAddress,
|
||||
ValidatorDstAddr: destValidatorAddress,
|
||||
SharesAmount: sdk.NewRatFromInt(amount),
|
||||
SharesAmount: sdk.NewDecFromInt(amount),
|
||||
}
|
||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||
ctx, write := ctx.CacheContext()
|
||||
|
@ -247,7 +247,7 @@ func Setup(mapp *mock.App, k stake.Keeper) simulation.RandSetup {
|
|||
return false
|
||||
})
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,12 +16,12 @@ import (
|
|||
type Delegation struct {
|
||||
DelegatorAddr sdk.AccAddress `json:"delegator_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
|
||||
}
|
||||
|
||||
type delegationValue struct {
|
||||
Shares sdk.Rat
|
||||
Shares sdk.Dec
|
||||
Height int64
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ var _ sdk.Delegation = Delegation{}
|
|||
// nolint - for sdk.Delegation
|
||||
func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr }
|
||||
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
|
||||
// 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
|
||||
InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started
|
||||
Balance sdk.Coin `json:"balance"` // current balance
|
||||
SharesSrc sdk.Rat `json:"shares_src"` // amount of source shares redelegating
|
||||
SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating
|
||||
SharesSrc sdk.Dec `json:"shares_src"` // amount of source shares redelegating
|
||||
SharesDst sdk.Dec `json:"shares_dst"` // amount of destination shares redelegating
|
||||
}
|
||||
|
||||
type redValue struct {
|
||||
|
@ -199,8 +199,8 @@ type redValue struct {
|
|||
MinTime time.Time
|
||||
InitialBalance sdk.Coin
|
||||
Balance sdk.Coin
|
||||
SharesSrc sdk.Rat
|
||||
SharesDst sdk.Rat
|
||||
SharesSrc sdk.Dec
|
||||
SharesDst sdk.Dec
|
||||
}
|
||||
|
||||
// return the redelegation without fields contained within the key for the store
|
||||
|
|
|
@ -12,19 +12,19 @@ func TestDelegationEqual(t *testing.T) {
|
|||
d1 := Delegation{
|
||||
DelegatorAddr: addr1,
|
||||
ValidatorAddr: addr2,
|
||||
Shares: sdk.NewRat(100),
|
||||
Shares: sdk.NewDec(100),
|
||||
}
|
||||
d2 := Delegation{
|
||||
DelegatorAddr: addr1,
|
||||
ValidatorAddr: addr2,
|
||||
Shares: sdk.NewRat(100),
|
||||
Shares: sdk.NewDec(100),
|
||||
}
|
||||
|
||||
ok := d1.Equal(d2)
|
||||
require.True(t, ok)
|
||||
|
||||
d2.ValidatorAddr = addr3
|
||||
d2.Shares = sdk.NewRat(200)
|
||||
d2.Shares = sdk.NewDec(200)
|
||||
|
||||
ok = d1.Equal(d2)
|
||||
require.False(t, ok)
|
||||
|
@ -34,7 +34,7 @@ func TestDelegationHumanReadableString(t *testing.T) {
|
|||
d := Delegation{
|
||||
DelegatorAddr: addr1,
|
||||
ValidatorAddr: addr2,
|
||||
Shares: sdk.NewRat(100),
|
||||
Shares: sdk.NewDec(100),
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
ud2.ValidatorAddr = addr3
|
||||
ud2.MinTime = time.Unix(20*20*2, 0)
|
||||
|
||||
ud2.MinTime = time.Unix(20*20*2, 0)
|
||||
ok = ud1.Equal(ud2)
|
||||
require.False(t, ok)
|
||||
}
|
||||
|
@ -92,8 +92,8 @@ func TestRedelegationEqual(t *testing.T) {
|
|||
ok := r1.Equal(r2)
|
||||
require.True(t, ok)
|
||||
|
||||
r2.SharesDst = sdk.NewRat(10)
|
||||
r2.SharesSrc = sdk.NewRat(20)
|
||||
r2.SharesDst = sdk.NewDec(10)
|
||||
r2.SharesSrc = sdk.NewDec(20)
|
||||
r2.MinTime = time.Unix(20*20*2, 0)
|
||||
|
||||
ok = r1.Equal(r2)
|
||||
|
@ -105,8 +105,8 @@ func TestRedelegationHumanReadableString(t *testing.T) {
|
|||
DelegatorAddr: addr1,
|
||||
ValidatorSrcAddr: addr2,
|
||||
ValidatorDstAddr: addr3,
|
||||
SharesDst: sdk.NewRat(10),
|
||||
SharesSrc: sdk.NewRat(20),
|
||||
SharesDst: sdk.NewDec(10),
|
||||
SharesSrc: sdk.NewDec(20),
|
||||
}
|
||||
|
||||
// NOTE: Being that the validator's keypair is random, we cannot test the
|
||||
|
|
|
@ -100,13 +100,6 @@ func ErrBadSharesAmount(codespace sdk.CodespaceType) sdk.Error {
|
|||
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 {
|
||||
return sdk.NewError(codespace, CodeInvalidDelegation, "shares percent must be >0 and <=1")
|
||||
}
|
||||
|
|
|
@ -23,30 +23,30 @@ func TestGetInflation(t *testing.T) {
|
|||
tests := []struct {
|
||||
name string
|
||||
setBondedTokens, setLooseTokens,
|
||||
setInflation, expectedChange sdk.Rat
|
||||
setInflation, expectedChange sdk.Dec
|
||||
}{
|
||||
// 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
|
||||
// (1 - (1/0.67))*(0.13/8667)
|
||||
{"test 2", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(20, 100),
|
||||
sdk.OneRat().Sub(sdk.OneRat().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)},
|
||||
{"test 2", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2),
|
||||
sdk.OneDec().Sub(sdk.OneDec().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrDec)},
|
||||
|
||||
// 50% bonded, starting at 10% inflation and being increased
|
||||
{"test 3", sdk.OneRat(), sdk.OneRat(), sdk.NewRat(10, 100),
|
||||
sdk.OneRat().Sub(sdk.NewRat(1, 2).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)},
|
||||
{"test 3", sdk.OneDec(), sdk.OneDec(), sdk.NewDecWithPrec(10, 2),
|
||||
sdk.OneDec().Sub(sdk.NewDecWithPrec(5, 1).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrDec)},
|
||||
|
||||
// test 7% minimum stop (testing with 100% bonded)
|
||||
{"test 4", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(7, 100), sdk.ZeroRat()},
|
||||
{"test 5", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(70001, 1000000), sdk.NewRat(-1, 1000000)},
|
||||
{"test 4", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), sdk.ZeroDec()},
|
||||
{"test 5", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(70001, 6), sdk.NewDecWithPrec(-1, 6)},
|
||||
|
||||
// test 20% maximum stop (testing with 0% bonded)
|
||||
{"test 6", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(20, 100), sdk.ZeroRat()},
|
||||
{"test 7", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(199999, 1000000), sdk.NewRat(1, 1000000)},
|
||||
{"test 6", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2), sdk.ZeroDec()},
|
||||
{"test 7", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(199999, 6), sdk.NewDecWithPrec(1, 6)},
|
||||
|
||||
// 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 {
|
||||
pool.BondedTokens, pool.LooseTokens = tc.setBondedTokens, tc.setLooseTokens
|
||||
|
@ -67,77 +67,80 @@ func TestProcessProvisions(t *testing.T) {
|
|||
|
||||
var (
|
||||
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
|
||||
for hr := 0; hr < 100; hr++ {
|
||||
var expProvisions sdk.Rat
|
||||
var expProvisions sdk.Dec
|
||||
_, expProvisions, pool = updateProvisions(t, pool, params, hr)
|
||||
cumulativeExpProvs = cumulativeExpProvs.Add(expProvisions)
|
||||
}
|
||||
|
||||
//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/////////////////////////////////////
|
||||
|
||||
// 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)
|
||||
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
|
||||
// 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)
|
||||
expProvisions := expInflation.Mul(pool.TokenSupply().Round(precision)).Quo(hrsPerYrRat)
|
||||
expProvisions := expInflation.Mul(pool.TokenSupply()).Quo(hrsPerYrDec)
|
||||
startTotalSupply := pool.TokenSupply()
|
||||
pool = pool.ProcessProvisions(params)
|
||||
|
||||
//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
|
||||
}
|
||||
|
||||
// Checks that The inflation will correctly increase or decrease after an update to the pool
|
||||
// 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)
|
||||
|
||||
switch {
|
||||
//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)):
|
||||
require.Equal(t, true, inflationChange.GT(sdk.ZeroRat()), msg)
|
||||
case pool.BondedRatio().LT(sdk.NewDecWithPrec(67, 2)) && updatedInflation.LT(sdk.NewDecWithPrec(20, 2)):
|
||||
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
|
||||
case pool.BondedRatio().LT(sdk.NewRat(67, 100)) && updatedInflation.Equal(sdk.NewRat(20, 100)):
|
||||
if previousInflation.Equal(sdk.NewRat(20, 100)) {
|
||||
case pool.BondedRatio().LT(sdk.NewDecWithPrec(67, 2)) && updatedInflation.Equal(sdk.NewDecWithPrec(20, 2)):
|
||||
if previousInflation.Equal(sdk.NewDecWithPrec(20, 2)) {
|
||||
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%)
|
||||
} 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%
|
||||
case pool.BondedRatio().GT(sdk.NewRat(67, 100)) && updatedInflation.LT(sdk.NewRat(20, 100)) && updatedInflation.GT(sdk.NewRat(7, 100)):
|
||||
require.Equal(t, true, inflationChange.LT(sdk.ZeroRat()), msg)
|
||||
case pool.BondedRatio().GT(sdk.NewDecWithPrec(67, 2)) &&
|
||||
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%.
|
||||
case pool.BondedRatio().GT(sdk.NewRat(67, 100)) && updatedInflation.Equal(sdk.NewRat(7, 100)):
|
||||
if previousInflation.Equal(sdk.NewRat(7, 100)) {
|
||||
case pool.BondedRatio().GT(sdk.NewDecWithPrec(67, 2)) &&
|
||||
updatedInflation.Equal(sdk.NewDecWithPrec(7, 2)):
|
||||
|
||||
if previousInflation.Equal(sdk.NewDecWithPrec(7, 2)) {
|
||||
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%)
|
||||
} else {
|
||||
require.Equal(t, true, inflationChange.LT(sdk.ZeroRat()), msg)
|
||||
require.Equal(t, true, inflationChange.LT(sdk.ZeroDec()), msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -11,18 +10,11 @@ import (
|
|||
// name to idetify transaction types
|
||||
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
|
||||
var _, _, _ sdk.Msg = &MsgCreateValidator{}, &MsgEditValidator{}, &MsgDelegate{}
|
||||
var _, _ sdk.Msg = &MsgBeginUnbonding{}, &MsgCompleteUnbonding{}
|
||||
var _, _ sdk.Msg = &MsgBeginRedelegate{}, &MsgCompleteRedelegate{}
|
||||
|
||||
// Initialize Int for the denominator
|
||||
var maximumBondingRationalDenominator = sdk.NewInt(int64(math.Pow10(MaxBondDenominatorPrecision)))
|
||||
|
||||
//______________________________________________________________________
|
||||
|
||||
// MsgCreateValidator - struct for unbonding transactions
|
||||
|
@ -211,11 +203,11 @@ type MsgBeginRedelegate struct {
|
|||
DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
|
||||
ValidatorSrcAddr sdk.AccAddress `json:"validator_src_addr"`
|
||||
ValidatorDstAddr sdk.AccAddress `json:"validator_dst_addr"`
|
||||
SharesAmount sdk.Rat `json:"shares_amount"`
|
||||
SharesAmount sdk.Dec `json:"shares_amount"`
|
||||
}
|
||||
|
||||
func NewMsgBeginRedelegate(delegatorAddr, validatorSrcAddr,
|
||||
validatorDstAddr sdk.AccAddress, sharesAmount sdk.Rat) MsgBeginRedelegate {
|
||||
validatorDstAddr sdk.AccAddress, sharesAmount sdk.Dec) MsgBeginRedelegate {
|
||||
|
||||
return MsgBeginRedelegate{
|
||||
DelegatorAddr: delegatorAddr,
|
||||
|
@ -261,12 +253,9 @@ func (msg MsgBeginRedelegate) ValidateBasic() sdk.Error {
|
|||
if msg.ValidatorDstAddr == nil {
|
||||
return ErrNilValidatorAddr(DefaultCodespace)
|
||||
}
|
||||
if msg.SharesAmount.LTE(sdk.ZeroRat()) {
|
||||
if msg.SharesAmount.LTE(sdk.ZeroDec()) {
|
||||
return ErrBadSharesAmount(DefaultCodespace)
|
||||
}
|
||||
if msg.SharesAmount.Denom().GT(maximumBondingRationalDenominator) {
|
||||
return ErrBadSharesPrecision(DefaultCodespace)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -322,10 +311,10 @@ func (msg MsgCompleteRedelegate) ValidateBasic() sdk.Error {
|
|||
type MsgBeginUnbonding struct {
|
||||
DelegatorAddr sdk.AccAddress `json:"delegator_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{
|
||||
DelegatorAddr: delegatorAddr,
|
||||
ValidatorAddr: validatorAddr,
|
||||
|
@ -362,12 +351,9 @@ func (msg MsgBeginUnbonding) ValidateBasic() sdk.Error {
|
|||
if msg.ValidatorAddr == nil {
|
||||
return ErrNilValidatorAddr(DefaultCodespace)
|
||||
}
|
||||
if msg.SharesAmount.LTE(sdk.ZeroRat()) {
|
||||
if msg.SharesAmount.LTE(sdk.ZeroDec()) {
|
||||
return ErrBadSharesAmount(DefaultCodespace)
|
||||
}
|
||||
if msg.SharesAmount.Denom().GT(maximumBondingRationalDenominator) {
|
||||
return ErrBadSharesPrecision(DefaultCodespace)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -143,15 +143,15 @@ func TestMsgBeginRedelegate(t *testing.T) {
|
|||
delegatorAddr sdk.AccAddress
|
||||
validatorSrcAddr sdk.AccAddress
|
||||
validatorDstAddr sdk.AccAddress
|
||||
sharesAmount sdk.Rat
|
||||
sharesAmount sdk.Dec
|
||||
expectPass bool
|
||||
}{
|
||||
{"regular", addr1, addr2, addr3, sdk.NewRat(1, 10), true},
|
||||
{"negative decimal", addr1, addr2, addr3, sdk.NewRat(-1, 10), false},
|
||||
{"zero amount", addr1, addr2, addr3, sdk.ZeroRat(), false},
|
||||
{"empty delegator", emptyAddr, addr1, addr3, sdk.NewRat(1, 10), false},
|
||||
{"empty source validator", addr1, emptyAddr, addr3, sdk.NewRat(1, 10), false},
|
||||
{"empty destination validator", addr1, addr2, emptyAddr, sdk.NewRat(1, 10), false},
|
||||
{"regular", addr1, addr2, addr3, sdk.NewDecWithPrec(1, 1), true},
|
||||
{"negative decimal", addr1, addr2, addr3, sdk.NewDecWithPrec(-1, 1), false},
|
||||
{"zero amount", addr1, addr2, addr3, sdk.ZeroDec(), false},
|
||||
{"empty delegator", emptyAddr, addr1, addr3, sdk.NewDecWithPrec(1, 1), false},
|
||||
{"empty source validator", addr1, emptyAddr, addr3, sdk.NewDecWithPrec(1, 1), false},
|
||||
{"empty destination validator", addr1, addr2, emptyAddr, sdk.NewDecWithPrec(1, 1), false},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
|
@ -195,14 +195,14 @@ func TestMsgBeginUnbonding(t *testing.T) {
|
|||
name string
|
||||
delegatorAddr sdk.AccAddress
|
||||
validatorAddr sdk.AccAddress
|
||||
sharesAmount sdk.Rat
|
||||
sharesAmount sdk.Dec
|
||||
expectPass bool
|
||||
}{
|
||||
{"regular", addr1, addr2, sdk.NewRat(1, 10), true},
|
||||
{"negative decimal", addr1, addr2, sdk.NewRat(-1, 10), false},
|
||||
{"zero amount", addr1, addr2, sdk.ZeroRat(), false},
|
||||
{"empty delegator", emptyAddr, addr1, sdk.NewRat(1, 10), false},
|
||||
{"empty validator", addr1, emptyAddr, sdk.NewRat(1, 10), false},
|
||||
{"regular", addr1, addr2, sdk.NewDecWithPrec(1, 1), true},
|
||||
{"negative decimal", addr1, addr2, sdk.NewDecWithPrec(-1, 1), false},
|
||||
{"zero amount", addr1, addr2, sdk.ZeroDec(), false},
|
||||
{"empty delegator", emptyAddr, addr1, sdk.NewDecWithPrec(1, 1), false},
|
||||
{"empty validator", addr1, emptyAddr, sdk.NewDecWithPrec(1, 1), false},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
|
|
|
@ -13,10 +13,10 @@ const defaultUnbondingTime time.Duration = 60 * 60 * 24 * 3 * time.Second
|
|||
|
||||
// Params defines the high level settings for staking
|
||||
type Params struct {
|
||||
InflationRateChange sdk.Rat `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
||||
InflationMax sdk.Rat `json:"inflation_max"` // maximum inflation rate
|
||||
InflationMin sdk.Rat `json:"inflation_min"` // minimum inflation rate
|
||||
GoalBonded sdk.Rat `json:"goal_bonded"` // Goal of percent bonded atoms
|
||||
InflationRateChange sdk.Dec `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
||||
InflationMax sdk.Dec `json:"inflation_max"` // maximum inflation rate
|
||||
InflationMin sdk.Dec `json:"inflation_min"` // minimum inflation rate
|
||||
GoalBonded sdk.Dec `json:"goal_bonded"` // Goal of percent bonded atoms
|
||||
|
||||
UnbondingTime time.Duration `json:"unbonding_time"`
|
||||
|
||||
|
@ -34,10 +34,10 @@ func (p Params) Equal(p2 Params) bool {
|
|||
// DefaultParams returns a default set of parameters.
|
||||
func DefaultParams() Params {
|
||||
return Params{
|
||||
InflationRateChange: sdk.NewRat(13, 100),
|
||||
InflationMax: sdk.NewRat(20, 100),
|
||||
InflationMin: sdk.NewRat(7, 100),
|
||||
GoalBonded: sdk.NewRat(67, 100),
|
||||
InflationRateChange: sdk.NewDecWithPrec(13, 2),
|
||||
InflationMax: sdk.NewDecWithPrec(20, 2),
|
||||
InflationMin: sdk.NewDecWithPrec(7, 2),
|
||||
GoalBonded: sdk.NewDecWithPrec(67, 2),
|
||||
UnbondingTime: defaultUnbondingTime,
|
||||
MaxValidators: 100,
|
||||
BondDenom: "steak",
|
||||
|
|
|
@ -10,15 +10,15 @@ import (
|
|||
|
||||
// Pool - dynamic parameters of the current state
|
||||
type Pool struct {
|
||||
LooseTokens sdk.Rat `json:"loose_tokens"` // tokens which are not bonded in a validator
|
||||
BondedTokens sdk.Rat `json:"bonded_tokens"` // reserve of bonded tokens
|
||||
InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed
|
||||
Inflation sdk.Rat `json:"inflation"` // current annual inflation rate
|
||||
LooseTokens sdk.Dec `json:"loose_tokens"` // tokens which are not bonded in a validator
|
||||
BondedTokens sdk.Dec `json:"bonded_tokens"` // reserve of bonded tokens
|
||||
InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time
|
||||
Inflation sdk.Dec `json:"inflation"` // current annual inflation rate
|
||||
|
||||
DateLastCommissionReset int64 `json:"date_last_commission_reset"` // unix timestamp for last commission accounting reset (daily)
|
||||
|
||||
// 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
|
||||
|
@ -31,48 +31,48 @@ func (p Pool) Equal(p2 Pool) bool {
|
|||
// initial pool for testing
|
||||
func InitialPool() Pool {
|
||||
return Pool{
|
||||
LooseTokens: sdk.ZeroRat(),
|
||||
BondedTokens: sdk.ZeroRat(),
|
||||
LooseTokens: sdk.ZeroDec(),
|
||||
BondedTokens: sdk.ZeroDec(),
|
||||
InflationLastTime: time.Unix(0, 0),
|
||||
Inflation: sdk.NewRat(7, 100),
|
||||
Inflation: sdk.NewDecWithPrec(7, 2),
|
||||
DateLastCommissionReset: 0,
|
||||
PrevBondedShares: sdk.ZeroRat(),
|
||||
PrevBondedShares: sdk.ZeroDec(),
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
//____________________________________________________________________
|
||||
|
||||
// get the bond ratio of the global state
|
||||
func (p Pool) BondedRatio() sdk.Rat {
|
||||
func (p Pool) BondedRatio() sdk.Dec {
|
||||
supply := p.TokenSupply()
|
||||
if supply.GT(sdk.ZeroRat()) {
|
||||
if supply.GT(sdk.ZeroDec()) {
|
||||
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.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))
|
||||
}
|
||||
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.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))
|
||||
}
|
||||
return p
|
||||
|
@ -82,14 +82,14 @@ func (p Pool) bondedTokensToLoose(bondedTokens sdk.Rat) Pool {
|
|||
// Inflation
|
||||
|
||||
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
|
||||
func (p Pool) ProcessProvisions(params Params) Pool {
|
||||
p.Inflation = p.NextInflation(params)
|
||||
provisions := p.Inflation.
|
||||
Mul(p.TokenSupply().Round(precision)).
|
||||
Quo(hrsPerYrRat)
|
||||
Mul(p.TokenSupply()).
|
||||
Quo(hrsPerYrDec)
|
||||
|
||||
// TODO add to the fees 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
|
||||
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
|
||||
// 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%.
|
||||
|
||||
// (1 - bondedRatio/GoalBonded) * InflationRateChange
|
||||
inflationRateChangePerYear := sdk.OneRat().
|
||||
Sub(p.BondedRatio().Round(precision).
|
||||
inflationRateChangePerYear := sdk.OneDec().
|
||||
Sub(p.BondedRatio().
|
||||
Quo(params.GoalBonded)).
|
||||
Mul(params.InflationRateChange)
|
||||
inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrRat)
|
||||
inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrDec)
|
||||
|
||||
// increase the new annual inflation for this next cycle
|
||||
inflation = p.Inflation.Add(inflationRateChange)
|
||||
|
@ -121,5 +121,5 @@ func (p Pool) NextInflation(params Params) (inflation sdk.Rat) {
|
|||
inflation = params.InflationMin
|
||||
}
|
||||
|
||||
return inflation.Round(precision)
|
||||
return inflation
|
||||
}
|
||||
|
|
|
@ -11,28 +11,28 @@ func TestPoolEqual(t *testing.T) {
|
|||
p1 := InitialPool()
|
||||
p2 := InitialPool()
|
||||
require.True(t, p1.Equal(p2))
|
||||
p2.BondedTokens = sdk.NewRat(3)
|
||||
p2.BondedTokens = sdk.NewDec(3)
|
||||
require.False(t, p1.Equal(p2))
|
||||
}
|
||||
|
||||
func TestAddBondedTokens(t *testing.T) {
|
||||
pool := InitialPool()
|
||||
pool.LooseTokens = sdk.NewRat(10)
|
||||
pool.BondedTokens = sdk.NewRat(10)
|
||||
pool.LooseTokens = sdk.NewDec(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.RatEq(t, sdk.NewRat(0), pool.LooseTokens))
|
||||
require.True(sdk.DecEq(t, sdk.NewDec(20), pool.BondedTokens))
|
||||
require.True(sdk.DecEq(t, sdk.NewDec(0), pool.LooseTokens))
|
||||
}
|
||||
|
||||
func TestRemoveBondedTokens(t *testing.T) {
|
||||
pool := InitialPool()
|
||||
pool.LooseTokens = sdk.NewRat(10)
|
||||
pool.BondedTokens = sdk.NewRat(10)
|
||||
pool.LooseTokens = sdk.NewDec(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.RatEq(t, sdk.NewRat(15), pool.LooseTokens))
|
||||
require.True(sdk.DecEq(t, sdk.NewDec(5), pool.BondedTokens))
|
||||
require.True(sdk.DecEq(t, sdk.NewDec(15), pool.LooseTokens))
|
||||
}
|
||||
|
|
|
@ -26,21 +26,21 @@ type Validator struct {
|
|||
Revoked bool `json:"revoked"` // has the validator been revoked from bonded status?
|
||||
|
||||
Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded)
|
||||
Tokens sdk.Rat `json:"tokens"` // delegated tokens (incl. self-delegation)
|
||||
DelegatorShares sdk.Rat `json:"delegator_shares"` // total shares issued to a validator's delegators
|
||||
Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation)
|
||||
DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators
|
||||
|
||||
Description Description `json:"description"` // description terms for the 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
|
||||
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
|
||||
CommissionMax sdk.Rat `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
|
||||
CommissionChangeToday sdk.Rat `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
|
||||
Commission sdk.Dec `json:"commission"` // XXX the commission rate of fees charged to any delegators
|
||||
CommissionMax sdk.Dec `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
|
||||
CommissionChangeRate sdk.Dec `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
|
||||
CommissionChangeToday sdk.Dec `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
|
||||
|
||||
// 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
|
||||
|
@ -50,17 +50,17 @@ func NewValidator(owner sdk.AccAddress, pubKey crypto.PubKey, description Descri
|
|||
PubKey: pubKey,
|
||||
Revoked: false,
|
||||
Status: sdk.Unbonded,
|
||||
Tokens: sdk.ZeroRat(),
|
||||
DelegatorShares: sdk.ZeroRat(),
|
||||
Tokens: sdk.ZeroDec(),
|
||||
DelegatorShares: sdk.ZeroDec(),
|
||||
Description: description,
|
||||
BondHeight: int64(0),
|
||||
BondIntraTxCounter: int16(0),
|
||||
ProposerRewardPool: sdk.Coins{},
|
||||
Commission: sdk.ZeroRat(),
|
||||
CommissionMax: sdk.ZeroRat(),
|
||||
CommissionChangeRate: sdk.ZeroRat(),
|
||||
CommissionChangeToday: sdk.ZeroRat(),
|
||||
LastBondedTokens: sdk.ZeroRat(),
|
||||
Commission: sdk.ZeroDec(),
|
||||
CommissionMax: sdk.ZeroDec(),
|
||||
CommissionChangeRate: sdk.ZeroDec(),
|
||||
CommissionChangeToday: sdk.ZeroDec(),
|
||||
LastBondedTokens: sdk.ZeroDec(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,17 +69,17 @@ type validatorValue struct {
|
|||
PubKey crypto.PubKey
|
||||
Revoked bool
|
||||
Status sdk.BondStatus
|
||||
Tokens sdk.Rat
|
||||
DelegatorShares sdk.Rat
|
||||
Tokens sdk.Dec
|
||||
DelegatorShares sdk.Dec
|
||||
Description Description
|
||||
BondHeight int64
|
||||
BondIntraTxCounter int16
|
||||
ProposerRewardPool sdk.Coins
|
||||
Commission sdk.Rat
|
||||
CommissionMax sdk.Rat
|
||||
CommissionChangeRate sdk.Rat
|
||||
CommissionChangeToday sdk.Rat
|
||||
LastBondedTokens sdk.Rat
|
||||
Commission sdk.Dec
|
||||
CommissionMax sdk.Dec
|
||||
CommissionChangeRate sdk.Dec
|
||||
CommissionChangeToday sdk.Dec
|
||||
LastBondedTokens sdk.Dec
|
||||
}
|
||||
|
||||
// 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("Revoked: %v\n", v.Revoked)
|
||||
resp += fmt.Sprintf("Status: %s\n", sdk.BondStatusToString(v.Status))
|
||||
resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.FloatString())
|
||||
resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares.FloatString())
|
||||
resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.String())
|
||||
resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares.String())
|
||||
resp += fmt.Sprintf("Description: %s\n", v.Description)
|
||||
resp += fmt.Sprintf("Bond Height: %d\n", v.BondHeight)
|
||||
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?
|
||||
|
||||
Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded)
|
||||
Tokens sdk.Rat `json:"tokens"` // delegated tokens (incl. self-delegation)
|
||||
DelegatorShares sdk.Rat `json:"delegator_shares"` // total shares issued to a validator's delegators
|
||||
Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation)
|
||||
DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators
|
||||
|
||||
Description Description `json:"description"` // description terms for the 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
|
||||
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
|
||||
CommissionMax sdk.Rat `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
|
||||
CommissionChangeToday sdk.Rat `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
|
||||
Commission sdk.Dec `json:"commission"` // XXX the commission rate of fees charged to any delegators
|
||||
CommissionMax sdk.Dec `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
|
||||
CommissionChangeRate sdk.Dec `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
|
||||
CommissionChangeToday sdk.Dec `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
|
||||
|
||||
// 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
|
||||
|
@ -364,7 +364,7 @@ func (v Validator) UpdateStatus(pool Pool, NewStatus sdk.BondStatus) (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 {
|
||||
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
|
||||
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
|
||||
exRate := v.DelegatorShareExRate()
|
||||
amountRat := sdk.NewRat(amount)
|
||||
amountDec := sdk.NewDec(amount)
|
||||
|
||||
if v.Status == sdk.Bonded {
|
||||
pool = pool.looseTokensToBonded(amountRat)
|
||||
pool = pool.looseTokensToBonded(amountDec)
|
||||
}
|
||||
|
||||
v.Tokens = v.Tokens.Add(amountRat)
|
||||
issuedShares := amountRat.Quo(exRate)
|
||||
v.Tokens = v.Tokens.Add(amountDec)
|
||||
issuedShares := amountDec.Quo(exRate)
|
||||
v.DelegatorShares = v.DelegatorShares.Add(issuedShares)
|
||||
|
||||
return v, pool, issuedShares
|
||||
}
|
||||
|
||||
// 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)
|
||||
v.Tokens = v.Tokens.Sub(issuedTokens)
|
||||
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.
|
||||
// UNITS: tokens/delegator-shares
|
||||
func (v Validator) DelegatorShareExRate() sdk.Rat {
|
||||
func (v Validator) DelegatorShareExRate() sdk.Dec {
|
||||
if v.DelegatorShares.IsZero() {
|
||||
return sdk.OneRat()
|
||||
return sdk.OneDec()
|
||||
}
|
||||
return v.Tokens.Quo(v.DelegatorShares)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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) GetOwner() sdk.AccAddress { return v.Owner }
|
||||
func (v Validator) GetPubKey() crypto.PubKey { return v.PubKey }
|
||||
func (v Validator) GetPower() sdk.Rat { return v.BondedTokens() }
|
||||
func (v Validator) GetTokens() sdk.Rat { return v.Tokens }
|
||||
func (v Validator) GetDelegatorShares() sdk.Rat { return v.DelegatorShares }
|
||||
func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() }
|
||||
func (v Validator) GetTokens() sdk.Dec { return v.Tokens }
|
||||
func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares }
|
||||
func (v Validator) GetBondHeight() int64 { return v.BondHeight }
|
||||
|
|
|
@ -75,19 +75,19 @@ func TestRemoveTokens(t *testing.T) {
|
|||
Owner: addr1,
|
||||
PubKey: pk1,
|
||||
Status: sdk.Bonded,
|
||||
Tokens: sdk.NewRat(100),
|
||||
DelegatorShares: sdk.NewRat(100),
|
||||
Tokens: sdk.NewDec(100),
|
||||
DelegatorShares: sdk.NewDec(100),
|
||||
}
|
||||
|
||||
pool := InitialPool()
|
||||
pool.LooseTokens = sdk.NewRat(10)
|
||||
pool.LooseTokens = sdk.NewDec(10)
|
||||
pool.BondedTokens = validator.BondedTokens()
|
||||
|
||||
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
||||
require.Equal(t, sdk.Bonded, validator.Status)
|
||||
|
||||
// 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), pool.BondedTokens.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(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(0), pool.BondedTokens.RoundInt64())
|
||||
require.Equal(t, int64(110), pool.LooseTokens.RoundInt64())
|
||||
|
@ -106,43 +106,43 @@ func TestRemoveTokens(t *testing.T) {
|
|||
|
||||
func TestAddTokensValidatorBonded(t *testing.T) {
|
||||
pool := InitialPool()
|
||||
pool.LooseTokens = sdk.NewRat(10)
|
||||
pool.LooseTokens = sdk.NewDec(10)
|
||||
validator := NewValidator(addr1, pk1, Description{})
|
||||
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
||||
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.RatEq(t, sdk.NewRat(10), validator.BondedTokens()))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), delShares))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens()))
|
||||
}
|
||||
|
||||
func TestAddTokensValidatorUnbonding(t *testing.T) {
|
||||
pool := InitialPool()
|
||||
pool.LooseTokens = sdk.NewRat(10)
|
||||
pool.LooseTokens = sdk.NewDec(10)
|
||||
validator := NewValidator(addr1, pk1, Description{})
|
||||
validator, pool = validator.UpdateStatus(pool, sdk.Unbonding)
|
||||
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.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
|
||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||
}
|
||||
|
||||
func TestAddTokensValidatorUnbonded(t *testing.T) {
|
||||
pool := InitialPool()
|
||||
pool.LooseTokens = sdk.NewRat(10)
|
||||
pool.LooseTokens = sdk.NewDec(10)
|
||||
validator := NewValidator(addr1, pk1, Description{})
|
||||
validator, pool = validator.UpdateStatus(pool, sdk.Unbonded)
|
||||
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.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
|
||||
|
@ -151,16 +151,16 @@ func TestRemoveDelShares(t *testing.T) {
|
|||
Owner: addr1,
|
||||
PubKey: pk1,
|
||||
Status: sdk.Bonded,
|
||||
Tokens: sdk.NewRat(100),
|
||||
DelegatorShares: sdk.NewRat(100),
|
||||
Tokens: sdk.NewDec(100),
|
||||
DelegatorShares: sdk.NewDec(100),
|
||||
}
|
||||
poolA := InitialPool()
|
||||
poolA.LooseTokens = sdk.NewRat(10)
|
||||
poolA.LooseTokens = sdk.NewDec(10)
|
||||
poolA.BondedTokens = valA.BondedTokens()
|
||||
require.Equal(t, valA.DelegatorShareExRate(), sdk.OneRat())
|
||||
require.Equal(t, valA.DelegatorShareExRate(), sdk.OneDec())
|
||||
|
||||
// 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(90), valB.DelegatorShares.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())
|
||||
|
||||
// conservation of tokens
|
||||
require.True(sdk.RatEq(t,
|
||||
require.True(sdk.DecEq(t,
|
||||
poolB.LooseTokens.Add(poolB.BondedTokens),
|
||||
poolA.LooseTokens.Add(poolA.BondedTokens)))
|
||||
|
||||
// specific case from random tests
|
||||
poolTokens := sdk.NewRat(5102)
|
||||
delShares := sdk.NewRat(115)
|
||||
poolTokens := sdk.NewDec(5102)
|
||||
delShares := sdk.NewDec(115)
|
||||
validator := Validator{
|
||||
Owner: addr1,
|
||||
PubKey: pk1,
|
||||
|
@ -183,22 +183,27 @@ func TestRemoveDelShares(t *testing.T) {
|
|||
DelegatorShares: delShares,
|
||||
}
|
||||
pool := Pool{
|
||||
BondedTokens: sdk.NewRat(248305),
|
||||
LooseTokens: sdk.NewRat(232147),
|
||||
BondedTokens: sdk.NewDec(248305),
|
||||
LooseTokens: sdk.NewDec(232147),
|
||||
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)
|
||||
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),
|
||||
pool.LooseTokens.Add(pool.BondedTokens)))
|
||||
}
|
||||
|
||||
func TestUpdateStatus(t *testing.T) {
|
||||
pool := InitialPool()
|
||||
pool.LooseTokens = sdk.NewRat(100)
|
||||
pool.LooseTokens = sdk.NewDec(100)
|
||||
|
||||
validator := NewValidator(addr1, pk1, Description{})
|
||||
validator, pool, _ = validator.AddTokensFromDel(pool, 100)
|
||||
|
@ -221,8 +226,8 @@ func TestUpdateStatus(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPossibleOverflow(t *testing.T) {
|
||||
poolTokens := sdk.NewRat(2159)
|
||||
delShares := sdk.NewRat(391432570689183511).Quo(sdk.NewRat(40113011844664))
|
||||
poolTokens := sdk.NewDec(2159)
|
||||
delShares := sdk.NewDec(391432570689183511).Quo(sdk.NewDec(40113011844664))
|
||||
validator := Validator{
|
||||
Owner: addr1,
|
||||
PubKey: pk1,
|
||||
|
@ -231,17 +236,17 @@ func TestPossibleOverflow(t *testing.T) {
|
|||
DelegatorShares: delShares,
|
||||
}
|
||||
pool := Pool{
|
||||
LooseTokens: sdk.NewRat(100),
|
||||
LooseTokens: sdk.NewDec(100),
|
||||
BondedTokens: poolTokens,
|
||||
InflationLastTime: time.Unix(0, 0),
|
||||
Inflation: sdk.NewRat(7, 100),
|
||||
Inflation: sdk.NewDecWithPrec(7, 2),
|
||||
}
|
||||
tokens := int64(71)
|
||||
msg := fmt.Sprintf("validator %#v", validator)
|
||||
newValidator, _, _ := validator.AddTokensFromDel(pool, tokens)
|
||||
|
||||
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",
|
||||
msg, newValidator.DelegatorShareExRate())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue