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`
|
* `gaiacli gov vote --voter`
|
||||||
* [x/gov] Added tags sub-package, changed tags to use dash-case
|
* [x/gov] Added tags sub-package, changed tags to use dash-case
|
||||||
* [x/gov] Governance parameters are now stored in globalparams store
|
* [x/gov] Governance parameters are now stored in globalparams store
|
||||||
|
* [core] \#1807 Switch from use of rational to decimal
|
||||||
* [lcd] \#1866 Updated lcd /slashing/signing_info endpoint to take cosmosvalpub instead of cosmosvaladdr
|
* [lcd] \#1866 Updated lcd /slashing/signing_info endpoint to take cosmosvalpub instead of cosmosvaladdr
|
||||||
* [types] sdk.NewCoin now takes sdk.Int, sdk.NewInt64Coin takes int64
|
* [types] sdk.NewCoin now takes sdk.Int, sdk.NewInt64Coin takes int64
|
||||||
* [cli] #1551: Officially removed `--name` from CLI commands
|
* [cli] #1551: Officially removed `--name` from CLI commands
|
||||||
|
|
|
@ -173,7 +173,7 @@ func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.AccAddress
|
||||||
accAuth.Coins = sdk.Coins{sdk.NewInt64Coin("steak", 100)}
|
accAuth.Coins = sdk.Coins{sdk.NewInt64Coin("steak", 100)}
|
||||||
acc := gapp.NewGenesisAccount(&accAuth)
|
acc := gapp.NewGenesisAccount(&accAuth)
|
||||||
genesisState.Accounts = append(genesisState.Accounts, acc)
|
genesisState.Accounts = append(genesisState.Accounts, acc)
|
||||||
genesisState.StakeData.Pool.LooseTokens = genesisState.StakeData.Pool.LooseTokens.Add(sdk.NewRat(100))
|
genesisState.StakeData.Pool.LooseTokens = genesisState.StakeData.Pool.LooseTokens.Add(sdk.NewDec(100))
|
||||||
}
|
}
|
||||||
|
|
||||||
appState, err := wire.MarshalJSONIndent(cdc, genesisState)
|
appState, err := wire.MarshalJSONIndent(cdc, genesisState)
|
||||||
|
|
|
@ -185,7 +185,7 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState
|
||||||
}
|
}
|
||||||
acc := NewGenesisAccount(&accAuth)
|
acc := NewGenesisAccount(&accAuth)
|
||||||
genaccs[i] = acc
|
genaccs[i] = acc
|
||||||
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewRat(freeFermionsAcc)) // increase the supply
|
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(freeFermionsAcc)) // increase the supply
|
||||||
|
|
||||||
// add the validator
|
// add the validator
|
||||||
if len(genTx.Name) > 0 {
|
if len(genTx.Name) > 0 {
|
||||||
|
@ -193,10 +193,10 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState
|
||||||
validator := stake.NewValidator(genTx.Address,
|
validator := stake.NewValidator(genTx.Address,
|
||||||
sdk.MustGetAccPubKeyBech32(genTx.PubKey), desc)
|
sdk.MustGetAccPubKeyBech32(genTx.PubKey), desc)
|
||||||
|
|
||||||
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewRat(freeFermionVal)) // increase the supply
|
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(freeFermionVal)) // increase the supply
|
||||||
|
|
||||||
// add some new shares to the validator
|
// add some new shares to the validator
|
||||||
var issuedDelShares sdk.Rat
|
var issuedDelShares sdk.Dec
|
||||||
validator, stakeData.Pool, issuedDelShares = validator.AddTokensFromDel(stakeData.Pool, freeFermionVal)
|
validator, stakeData.Pool, issuedDelShares = validator.AddTokensFromDel(stakeData.Pool, freeFermionVal)
|
||||||
stakeData.Validators = append(stakeData.Validators, validator)
|
stakeData.Validators = append(stakeData.Validators, validator)
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ func appStateFn(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage {
|
||||||
|
|
||||||
// Default genesis state
|
// Default genesis state
|
||||||
stakeGenesis := stake.DefaultGenesisState()
|
stakeGenesis := stake.DefaultGenesisState()
|
||||||
stakeGenesis.Pool.LooseTokens = sdk.NewRat(1000)
|
stakeGenesis.Pool.LooseTokens = sdk.NewDec(1000)
|
||||||
genesis := GenesisState{
|
genesis := GenesisState{
|
||||||
Accounts: genesisAccounts,
|
Accounts: genesisAccounts,
|
||||||
StakeData: stakeGenesis,
|
StakeData: stakeGenesis,
|
||||||
|
|
|
@ -132,7 +132,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
|
||||||
|
|
||||||
validator := executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags))
|
validator := executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags))
|
||||||
require.Equal(t, validator.Owner, barAddr)
|
require.Equal(t, validator.Owner, barAddr)
|
||||||
require.True(sdk.RatEq(t, sdk.NewRat(2), validator.Tokens))
|
require.True(sdk.DecEq(t, sdk.NewDec(2), validator.Tokens))
|
||||||
|
|
||||||
// unbond a single share
|
// unbond a single share
|
||||||
unbondStr := fmt.Sprintf("gaiacli stake unbond begin %v", flags)
|
unbondStr := fmt.Sprintf("gaiacli stake unbond begin %v", flags)
|
||||||
|
@ -149,7 +149,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
|
||||||
require.Equal(t, int64(9), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc)
|
require.Equal(t, int64(9), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc)
|
||||||
*/
|
*/
|
||||||
validator = executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags))
|
validator = executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags))
|
||||||
require.Equal(t, "1/1", validator.Tokens.String())
|
require.Equal(t, "1.0000000000", validator.Tokens.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGaiaCLISubmitProposal(t *testing.T) {
|
func TestGaiaCLISubmitProposal(t *testing.T) {
|
||||||
|
|
|
@ -25,9 +25,9 @@ type VotingProcedure struct {
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type TallyingProcedure struct {
|
type TallyingProcedure struct {
|
||||||
Threshold rational.Rational // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
|
Threshold sdk.Dec // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
|
||||||
Veto rational.Rational // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
|
Veto sdk.Dec // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
|
||||||
GovernancePenalty sdk.Rat // Penalty if validator does not vote
|
GovernancePenalty sdk.Dec // Penalty if validator does not vote
|
||||||
GracePeriod int64 // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply
|
GracePeriod int64 // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -81,7 +81,7 @@ This type is used in a temp map when tallying
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type ValidatorGovInfo struct {
|
type ValidatorGovInfo struct {
|
||||||
Minus sdk.Rat
|
Minus sdk.Dec
|
||||||
Vote Vote
|
Vote Vote
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -103,17 +103,17 @@ type Proposal struct {
|
||||||
VotingStartBlock int64 // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached
|
VotingStartBlock int64 // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached
|
||||||
CurrentStatus ProposalStatus // Current status of the proposal
|
CurrentStatus ProposalStatus // Current status of the proposal
|
||||||
|
|
||||||
YesVotes sdk.Rat
|
YesVotes sdk.Dec
|
||||||
NoVotes sdk.Rat
|
NoVotes sdk.Dec
|
||||||
NoWithVetoVotes sdk.Rat
|
NoWithVetoVotes sdk.Dec
|
||||||
AbstainVotes sdk.Rat
|
AbstainVotes sdk.Dec
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
We also mention a method to update the tally for a given proposal:
|
We also mention a method to update the tally for a given proposal:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (proposal Proposal) updateTally(vote byte, amount sdk.Rat)
|
func (proposal Proposal) updateTally(vote byte, amount sdk.Dec)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Stores
|
### Stores
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
The current annual inflation rate.
|
The current annual inflation rate.
|
||||||
|
|
||||||
```golang
|
```golang
|
||||||
type Inflation sdk.Rat
|
type Inflation sdk.Dec
|
||||||
```
|
```
|
||||||
|
|
||||||
### InflationLastTime
|
### InflationLastTime
|
||||||
|
|
|
@ -16,4 +16,3 @@ EndBlock() ValidatorSetChanges
|
||||||
ClearTendermintUpdates()
|
ClearTendermintUpdates()
|
||||||
return vsc
|
return vsc
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ type Pool struct {
|
||||||
LooseTokens int64 // tokens not associated with any bonded validator
|
LooseTokens int64 // tokens not associated with any bonded validator
|
||||||
BondedTokens int64 // reserve of bonded tokens
|
BondedTokens int64 // reserve of bonded tokens
|
||||||
InflationLastTime int64 // block which the last inflation was processed // TODO make time
|
InflationLastTime int64 // block which the last inflation was processed // TODO make time
|
||||||
Inflation sdk.Rat // current annual inflation rate
|
Inflation sdk.Dec // current annual inflation rate
|
||||||
|
|
||||||
DateLastCommissionReset int64 // unix timestamp for last commission accounting reset (daily)
|
DateLastCommissionReset int64 // unix timestamp for last commission accounting reset (daily)
|
||||||
}
|
}
|
||||||
|
@ -28,10 +28,10 @@ overall functioning of the stake module.
|
||||||
|
|
||||||
```golang
|
```golang
|
||||||
type Params struct {
|
type Params struct {
|
||||||
InflationRateChange sdk.Rat // maximum annual change in inflation rate
|
InflationRateChange sdk.Dec // maximum annual change in inflation rate
|
||||||
InflationMax sdk.Rat // maximum inflation rate
|
InflationMax sdk.Dec // maximum inflation rate
|
||||||
InflationMin sdk.Rat // minimum inflation rate
|
InflationMin sdk.Dec // minimum inflation rate
|
||||||
GoalBonded sdk.Rat // Goal of percent bonded atoms
|
GoalBonded sdk.Dec // Goal of percent bonded atoms
|
||||||
|
|
||||||
MaxValidators uint16 // maximum number of validators
|
MaxValidators uint16 // maximum number of validators
|
||||||
BondDenom string // bondable coin denomination
|
BondDenom string // bondable coin denomination
|
||||||
|
@ -74,9 +74,9 @@ type Validator struct {
|
||||||
Revoked bool // has the validator been revoked?
|
Revoked bool // has the validator been revoked?
|
||||||
|
|
||||||
Status sdk.BondStatus // validator status (bonded/unbonding/unbonded)
|
Status sdk.BondStatus // validator status (bonded/unbonding/unbonded)
|
||||||
Tokens sdk.Rat // delegated tokens (incl. self-delegation)
|
Tokens sdk.Dec // delegated tokens (incl. self-delegation)
|
||||||
DelegatorShares sdk.Rat // total shares issued to a validator's delegators
|
DelegatorShares sdk.Dec // total shares issued to a validator's delegators
|
||||||
SlashRatio sdk.Rat // increases each time the validator is slashed
|
SlashRatio sdk.Dec // increases each time the validator is slashed
|
||||||
|
|
||||||
Description Description // description terms for the validator
|
Description Description // description terms for the validator
|
||||||
|
|
||||||
|
@ -88,10 +88,10 @@ type Validator struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommissionInfo struct {
|
type CommissionInfo struct {
|
||||||
Rate sdk.Rat // the commission rate of fees charged to any delegators
|
Rate sdk.Dec // the commission rate of fees charged to any delegators
|
||||||
Max sdk.Rat // maximum commission rate which this validator can ever charge
|
Max sdk.Dec // maximum commission rate which this validator can ever charge
|
||||||
ChangeRate sdk.Rat // maximum daily increase of the validator commission
|
ChangeRate sdk.Dec // maximum daily increase of the validator commission
|
||||||
ChangeToday sdk.Rat // commission rate change today, reset each day (UTC time)
|
ChangeToday sdk.Dec // commission rate change today, reset each day (UTC time)
|
||||||
LastChange int64 // unix timestamp of last commission change
|
LastChange int64 // unix timestamp of last commission change
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ the transaction is the owner of the bond.
|
||||||
|
|
||||||
```golang
|
```golang
|
||||||
type Delegation struct {
|
type Delegation struct {
|
||||||
Shares sdk.Rat // delegation shares recieved
|
Shares sdk.Dec // delegation shares recieved
|
||||||
Height int64 // last height bond updated
|
Height int64 // last height bond updated
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -178,8 +178,8 @@ the original redelegation has been completed.
|
||||||
|
|
||||||
```golang
|
```golang
|
||||||
type Redelegation struct {
|
type Redelegation struct {
|
||||||
SourceShares sdk.Rat // amount of source shares redelegating
|
SourceShares sdk.Dec // amount of source shares redelegating
|
||||||
DestinationShares sdk.Rat // amount of destination shares created at redelegation
|
DestinationShares sdk.Dec // amount of destination shares created at redelegation
|
||||||
CompleteTime int64 // unix time to complete redelegation
|
CompleteTime int64 // unix time to complete redelegation
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -18,7 +18,7 @@ Other notes:
|
||||||
- `sender` denotes the address of the sender of the transaction
|
- `sender` denotes the address of the sender of the transaction
|
||||||
- `getXxx`, `setXxx`, and `removeXxx` functions are used to retrieve and
|
- `getXxx`, `setXxx`, and `removeXxx` functions are used to retrieve and
|
||||||
modify objects from the store
|
modify objects from the store
|
||||||
- `sdk.Rat` refers to a rational numeric type specified by the SDK.
|
- `sdk.Dec` refers to a decimal type specified by the SDK.
|
||||||
|
|
||||||
### TxCreateValidator
|
### TxCreateValidator
|
||||||
|
|
||||||
|
@ -34,9 +34,9 @@ type TxCreateValidator struct {
|
||||||
SelfDelegation coin.Coin
|
SelfDelegation coin.Coin
|
||||||
|
|
||||||
Description Description
|
Description Description
|
||||||
Commission sdk.Rat
|
Commission sdk.Dec
|
||||||
CommissionMax sdk.Rat
|
CommissionMax sdk.Dec
|
||||||
CommissionMaxChange sdk.Rat
|
CommissionMaxChange sdk.Dec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ If either the `Description` (excluding `DateBonded` which is constant),
|
||||||
```golang
|
```golang
|
||||||
type TxEditCandidacy struct {
|
type TxEditCandidacy struct {
|
||||||
GovernancePubKey crypto.PubKey
|
GovernancePubKey crypto.PubKey
|
||||||
Commission sdk.Rat
|
Commission sdk.Dec
|
||||||
Description Description
|
Description Description
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ type TxRedelegate struct {
|
||||||
DelegatorAddr Address
|
DelegatorAddr Address
|
||||||
ValidatorFrom Validator
|
ValidatorFrom Validator
|
||||||
ValidatorTo Validator
|
ValidatorTo Validator
|
||||||
Shares sdk.Rat
|
Shares sdk.Dec
|
||||||
CompletedTime int64
|
CompletedTime int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
// Validator implements sdk.Validator
|
// Validator implements sdk.Validator
|
||||||
type Validator struct {
|
type Validator struct {
|
||||||
Address sdk.AccAddress
|
Address sdk.AccAddress
|
||||||
Power sdk.Rat
|
Power sdk.Dec
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements sdk.Validator
|
// Implements sdk.Validator
|
||||||
|
@ -29,18 +29,18 @@ func (v Validator) GetPubKey() crypto.PubKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements sdk.Validator
|
// Implements sdk.Validator
|
||||||
func (v Validator) GetTokens() sdk.Rat {
|
func (v Validator) GetTokens() sdk.Dec {
|
||||||
return sdk.ZeroRat()
|
return sdk.ZeroDec()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements sdk.Validator
|
// Implements sdk.Validator
|
||||||
func (v Validator) GetPower() sdk.Rat {
|
func (v Validator) GetPower() sdk.Dec {
|
||||||
return v.Power
|
return v.Power
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements sdk.Validator
|
// Implements sdk.Validator
|
||||||
func (v Validator) GetDelegatorShares() sdk.Rat {
|
func (v Validator) GetDelegatorShares() sdk.Dec {
|
||||||
return sdk.ZeroRat()
|
return sdk.ZeroDec()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements sdk.Validator
|
// Implements sdk.Validator
|
||||||
|
@ -93,8 +93,8 @@ func (vs *ValidatorSet) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TotalPower implements sdk.ValidatorSet
|
// TotalPower implements sdk.ValidatorSet
|
||||||
func (vs *ValidatorSet) TotalPower(ctx sdk.Context) sdk.Rat {
|
func (vs *ValidatorSet) TotalPower(ctx sdk.Context) sdk.Dec {
|
||||||
res := sdk.ZeroRat()
|
res := sdk.ZeroDec()
|
||||||
for _, val := range vs.Validators {
|
for _, val := range vs.Validators {
|
||||||
res = res.Add(val.Power)
|
res = res.Add(val.Power)
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ func (vs *ValidatorSet) RemoveValidator(addr sdk.AccAddress) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements sdk.ValidatorSet
|
// Implements sdk.ValidatorSet
|
||||||
func (vs *ValidatorSet) Slash(ctx sdk.Context, pubkey crypto.PubKey, height int64, power int64, amt sdk.Rat) {
|
func (vs *ValidatorSet) Slash(ctx sdk.Context, pubkey crypto.PubKey, height int64, power int64, amt sdk.Dec) {
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ func TestValidatorSet(t *testing.T) {
|
||||||
addr2 := []byte("addr2")
|
addr2 := []byte("addr2")
|
||||||
|
|
||||||
base := &mock.ValidatorSet{[]mock.Validator{
|
base := &mock.ValidatorSet{[]mock.Validator{
|
||||||
{addr1, sdk.NewRat(1)},
|
{addr1, sdk.NewDec(1)},
|
||||||
{addr2, sdk.NewRat(2)},
|
{addr2, sdk.NewDec(2)},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
valset := NewValidatorSet(wire.NewCodec(), ctx.KVStore(key).Prefix([]byte("assoc")), base, 1, 5)
|
valset := NewValidatorSet(wire.NewCodec(), ctx.KVStore(key).Prefix([]byte("assoc")), base, 1, 5)
|
||||||
|
|
|
@ -38,7 +38,7 @@ func NewHandler(keeper Keeper) sdk.Handler {
|
||||||
In the previous example, the keeper has an `oracle.Keeper`. `oracle.Keeper`s are generated by `NewKeeper`.
|
In the previous example, the keeper has an `oracle.Keeper`. `oracle.Keeper`s are generated by `NewKeeper`.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Rat, timeout int64) Keeper {
|
func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Dec, timeout int64) Keeper {
|
||||||
return Keeper {
|
return Keeper {
|
||||||
cdc: cdc,
|
cdc: cdc,
|
||||||
key: key,
|
key: key,
|
||||||
|
|
|
@ -23,7 +23,7 @@ func (keeper Keeper) update(ctx sdk.Context, val sdk.Validator, valset sdk.Valid
|
||||||
// and recalculate voted power
|
// and recalculate voted power
|
||||||
hash := ctx.BlockHeader().ValidatorsHash
|
hash := ctx.BlockHeader().ValidatorsHash
|
||||||
if !bytes.Equal(hash, info.Hash) {
|
if !bytes.Equal(hash, info.Hash) {
|
||||||
info.Power = sdk.ZeroRat()
|
info.Power = sdk.ZeroDec()
|
||||||
info.Hash = hash
|
info.Hash = hash
|
||||||
prefix := GetSignPrefix(p, keeper.cdc)
|
prefix := GetSignPrefix(p, keeper.cdc)
|
||||||
store := ctx.KVStore(keeper.key)
|
store := ctx.KVStore(keeper.key)
|
||||||
|
|
|
@ -13,12 +13,12 @@ type Keeper struct {
|
||||||
|
|
||||||
valset sdk.ValidatorSet
|
valset sdk.ValidatorSet
|
||||||
|
|
||||||
supermaj sdk.Rat
|
supermaj sdk.Dec
|
||||||
timeout int64
|
timeout int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewKeeper constructs a new keeper
|
// NewKeeper constructs a new keeper
|
||||||
func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Rat, timeout int64) Keeper {
|
func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Dec, timeout int64) Keeper {
|
||||||
if timeout < 0 {
|
if timeout < 0 {
|
||||||
panic("Timeout should not be negative")
|
panic("Timeout should not be negative")
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ const (
|
||||||
|
|
||||||
// Info for each payload
|
// Info for each payload
|
||||||
type Info struct {
|
type Info struct {
|
||||||
Power sdk.Rat
|
Power sdk.Dec
|
||||||
Hash []byte
|
Hash []byte
|
||||||
LastSigned int64
|
LastSigned int64
|
||||||
Status InfoStatus
|
Status InfoStatus
|
||||||
|
@ -55,7 +55,7 @@ type Info struct {
|
||||||
// EmptyInfo construct an empty Info
|
// EmptyInfo construct an empty Info
|
||||||
func EmptyInfo(ctx sdk.Context) Info {
|
func EmptyInfo(ctx sdk.Context) Info {
|
||||||
return Info{
|
return Info{
|
||||||
Power: sdk.ZeroRat(),
|
Power: sdk.ZeroDec(),
|
||||||
Hash: ctx.BlockHeader().ValidatorsHash,
|
Hash: ctx.BlockHeader().ValidatorsHash,
|
||||||
LastSigned: ctx.BlockHeight(),
|
LastSigned: ctx.BlockHeight(),
|
||||||
Status: Pending,
|
Status: Pending,
|
||||||
|
|
|
@ -107,9 +107,9 @@ func TestOracle(t *testing.T) {
|
||||||
addr3 := []byte("addr3")
|
addr3 := []byte("addr3")
|
||||||
addr4 := []byte("addr4")
|
addr4 := []byte("addr4")
|
||||||
valset := &mock.ValidatorSet{[]mock.Validator{
|
valset := &mock.ValidatorSet{[]mock.Validator{
|
||||||
{addr1, sdk.NewRat(7)},
|
{addr1, sdk.NewDec(7)},
|
||||||
{addr2, sdk.NewRat(7)},
|
{addr2, sdk.NewDec(7)},
|
||||||
{addr3, sdk.NewRat(1)},
|
{addr3, sdk.NewDec(1)},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
key := sdk.NewKVStoreKey("testkey")
|
key := sdk.NewKVStoreKey("testkey")
|
||||||
|
@ -119,7 +119,7 @@ func TestOracle(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz})
|
ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz})
|
||||||
|
|
||||||
ork := NewKeeper(key, cdc, valset, sdk.NewRat(2, 3), 100)
|
ork := NewKeeper(key, cdc, valset, sdk.NewDecWithPrec(667, 3), 100) // 66.7%
|
||||||
h := seqHandler(ork, key, sdk.CodespaceRoot)
|
h := seqHandler(ork, key, sdk.CodespaceRoot)
|
||||||
|
|
||||||
// Nonmock.Validator signed, transaction failed
|
// Nonmock.Validator signed, transaction failed
|
||||||
|
@ -171,7 +171,7 @@ func TestOracle(t *testing.T) {
|
||||||
require.Equal(t, 1, getSequence(ctx, key))
|
require.Equal(t, 1, getSequence(ctx, key))
|
||||||
|
|
||||||
// Should handle mock.Validator set change
|
// Should handle mock.Validator set change
|
||||||
valset.AddValidator(mock.Validator{addr4, sdk.NewRat(12)})
|
valset.AddValidator(mock.Validator{addr4, sdk.NewDec(12)})
|
||||||
bz, err = json.Marshal(valset)
|
bz, err = json.Marshal(valset)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz})
|
ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz})
|
||||||
|
|
|
@ -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
|
GetStatus() BondStatus // status of the validator
|
||||||
GetOwner() AccAddress // owner AccAddress to receive/return validators coins
|
GetOwner() AccAddress // owner AccAddress to receive/return validators coins
|
||||||
GetPubKey() crypto.PubKey // validation pubkey
|
GetPubKey() crypto.PubKey // validation pubkey
|
||||||
GetPower() Rat // validation power
|
GetPower() Dec // validation power
|
||||||
GetTokens() Rat // validation tokens
|
GetTokens() Dec // validation tokens
|
||||||
GetDelegatorShares() Rat // Total out standing delegator shares
|
GetDelegatorShares() Dec // Total out standing delegator shares
|
||||||
GetBondHeight() int64 // height in which the validator became active
|
GetBondHeight() int64 // height in which the validator became active
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,10 +68,10 @@ type ValidatorSet interface {
|
||||||
|
|
||||||
Validator(Context, AccAddress) Validator // get a particular validator by owner AccAddress
|
Validator(Context, AccAddress) Validator // get a particular validator by owner AccAddress
|
||||||
ValidatorByPubKey(Context, crypto.PubKey) Validator // get a particular validator by signing PubKey
|
ValidatorByPubKey(Context, crypto.PubKey) Validator // get a particular validator by signing PubKey
|
||||||
TotalPower(Context) Rat // total power of the validator set
|
TotalPower(Context) Dec // total power of the validator set
|
||||||
|
|
||||||
// slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction
|
// slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction
|
||||||
Slash(Context, crypto.PubKey, int64, int64, Rat)
|
Slash(Context, crypto.PubKey, int64, int64, Dec)
|
||||||
Revoke(Context, crypto.PubKey) // revoke a validator
|
Revoke(Context, crypto.PubKey) // revoke a validator
|
||||||
Unrevoke(Context, crypto.PubKey) // unrevoke a validator
|
Unrevoke(Context, crypto.PubKey) // unrevoke a validator
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ type ValidatorSet interface {
|
||||||
type Delegation interface {
|
type Delegation interface {
|
||||||
GetDelegator() AccAddress // delegator AccAddress for the bond
|
GetDelegator() AccAddress // delegator AccAddress for the bond
|
||||||
GetValidator() AccAddress // validator owner AccAddress for the bond
|
GetValidator() AccAddress // validator owner AccAddress for the bond
|
||||||
GetBondShares() Rat // amount of validator's shares
|
GetBondShares() Dec // amount of validator's shares
|
||||||
}
|
}
|
||||||
|
|
||||||
// properties for the set of all delegations for a particular
|
// properties for the set of all delegations for a particular
|
||||||
|
|
|
@ -23,13 +23,13 @@ package stake
|
||||||
////_________________________________________________________________________
|
////_________________________________________________________________________
|
||||||
|
|
||||||
//// cummulative power of the non-absent prevotes
|
//// cummulative power of the non-absent prevotes
|
||||||
//func (k Keeper) GetTotalPrecommitVotingPower(ctx sdk.Context) sdk.Rat {
|
//func (k Keeper) GetTotalPrecommitVotingPower(ctx sdk.Context) sdk.Dec {
|
||||||
//store := ctx.KVStore(k.storeKey)
|
//store := ctx.KVStore(k.storeKey)
|
||||||
|
|
||||||
//// get absent prevote indexes
|
//// get absent prevote indexes
|
||||||
//absents := ctx.AbsentValidators()
|
//absents := ctx.AbsentValidators()
|
||||||
|
|
||||||
//TotalPower := sdk.ZeroRat()
|
//TotalPower := sdk.ZeroDec()
|
||||||
//i := int32(0)
|
//i := int32(0)
|
||||||
//iterator := store.SubspaceIterator(ValidatorsBondedKey)
|
//iterator := store.SubspaceIterator(ValidatorsBondedKey)
|
||||||
//for ; iterator.Valid(); iterator.Next() {
|
//for ; iterator.Valid(); iterator.Next() {
|
||||||
|
|
|
@ -8,8 +8,8 @@ package stake
|
||||||
//var candidatesIn [5]Candidate
|
//var candidatesIn [5]Candidate
|
||||||
//for i, amt := range amts {
|
//for i, amt := range amts {
|
||||||
//candidatesIn[i] = NewCandidate(addrVals[i], pks[i], Description{})
|
//candidatesIn[i] = NewCandidate(addrVals[i], pks[i], Description{})
|
||||||
//candidatesIn[i].BondedShares = sdk.NewRat(amt)
|
//candidatesIn[i].BondedShares = sdk.NewDec(amt)
|
||||||
//candidatesIn[i].DelegatorShares = sdk.NewRat(amt)
|
//candidatesIn[i].DelegatorShares = sdk.NewDec(amt)
|
||||||
//keeper.setCandidate(ctx, candidatesIn[i])
|
//keeper.setCandidate(ctx, candidatesIn[i])
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ package stake
|
||||||
//require.Equal(t, 5, len(gotValidators))
|
//require.Equal(t, 5, len(gotValidators))
|
||||||
|
|
||||||
//totPow := keeper.GetTotalPrecommitVotingPower(ctx)
|
//totPow := keeper.GetTotalPrecommitVotingPower(ctx)
|
||||||
//exp := sdk.NewRat(11111)
|
//exp := sdk.NewDec(11111)
|
||||||
//require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow)
|
//require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow)
|
||||||
|
|
||||||
//// set absent gotValidators to be the 1st and 3rd record sorted by pubKey address
|
//// set absent gotValidators to be the 1st and 3rd record sorted by pubKey address
|
||||||
|
@ -26,6 +26,6 @@ package stake
|
||||||
//totPow = keeper.GetTotalPrecommitVotingPower(ctx)
|
//totPow = keeper.GetTotalPrecommitVotingPower(ctx)
|
||||||
|
|
||||||
//// XXX verify that this order should infact exclude these two records
|
//// XXX verify that this order should infact exclude these two records
|
||||||
//exp = sdk.NewRat(11100)
|
//exp = sdk.NewDec(11100)
|
||||||
//require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow)
|
//require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow)
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -17,7 +17,7 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {}
|
||||||
|
|
||||||
//// calculate the proposer reward
|
//// calculate the proposer reward
|
||||||
//precommitPower := k.GetTotalPrecommitVotingPower(ctx)
|
//precommitPower := k.GetTotalPrecommitVotingPower(ctx)
|
||||||
//toProposer := coinsMulRat(collectedFees, (sdk.NewRat(1, 100).Add(sdk.NewRat(4, 100).Mul(precommitPower).Quo(pool.BondedShares))))
|
//toProposer := coinsMulRat(collectedFees, (sdk.NewDec(1, 100).Add(sdk.NewDec(4, 100).Mul(precommitPower).Quo(pool.BondedShares))))
|
||||||
//candidate.ProposerRewardPool = candidate.ProposerRewardPool.Plus(toProposer)
|
//candidate.ProposerRewardPool = candidate.ProposerRewardPool.Plus(toProposer)
|
||||||
|
|
||||||
//toReservePool := coinsMulRat(collectedFees, params.ReservePoolFee)
|
//toReservePool := coinsMulRat(collectedFees, params.ReservePoolFee)
|
||||||
|
@ -34,10 +34,10 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {}
|
||||||
//k.setPool(ctx, pool)
|
//k.setPool(ctx, pool)
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//func coinsMulRat(coins sdk.Coins, rat sdk.Rat) sdk.Coins {
|
//func coinsMulRat(coins sdk.Coins, rat sdk.Dec) sdk.Coins {
|
||||||
//var res sdk.Coins
|
//var res sdk.Coins
|
||||||
//for _, coin := range coins {
|
//for _, coin := range coins {
|
||||||
//coinMulAmt := rat.Mul(sdk.NewRat(coin.Amount)).Evaluate()
|
//coinMulAmt := rat.Mul(sdk.NewDec(coin.Amount)).Evaluate()
|
||||||
//coinMul := sdk.Coins{{coin.Denom, coinMulAmt}}
|
//coinMul := sdk.Coins{{coin.Denom, coinMulAmt}}
|
||||||
//res = res.Plus(coinMul)
|
//res = res.Plus(coinMul)
|
||||||
//}
|
//}
|
||||||
|
@ -49,14 +49,14 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {}
|
||||||
//// calculate adjustment changes for a candidate at a height
|
//// calculate adjustment changes for a candidate at a height
|
||||||
//func CalculateAdjustmentChange(candidate Candidate, pool Pool, denoms []string, height int64) (Candidate, Pool) {
|
//func CalculateAdjustmentChange(candidate Candidate, pool Pool, denoms []string, height int64) (Candidate, Pool) {
|
||||||
|
|
||||||
//heightRat := sdk.NewRat(height)
|
//heightRat := sdk.NewDec(height)
|
||||||
//lastHeightRat := sdk.NewRat(height - 1)
|
//lastHeightRat := sdk.NewDec(height - 1)
|
||||||
//candidateFeeCount := candidate.BondedShares.Mul(heightRat)
|
//candidateFeeCount := candidate.BondedShares.Mul(heightRat)
|
||||||
//poolFeeCount := pool.BondedShares.Mul(heightRat)
|
//poolFeeCount := pool.BondedShares.Mul(heightRat)
|
||||||
|
|
||||||
//for i, denom := range denoms {
|
//for i, denom := range denoms {
|
||||||
//poolFeeSumReceived := sdk.NewRat(pool.FeeSumReceived.AmountOf(denom))
|
//poolFeeSumReceived := sdk.NewDec(pool.FeeSumReceived.AmountOf(denom))
|
||||||
//poolFeeRecent := sdk.NewRat(pool.FeeRecent.AmountOf(denom))
|
//poolFeeRecent := sdk.NewDec(pool.FeeRecent.AmountOf(denom))
|
||||||
//// calculate simple and projected pools
|
//// calculate simple and projected pools
|
||||||
//simplePool := candidateFeeCount.Quo(poolFeeCount).Mul(poolFeeSumReceived)
|
//simplePool := candidateFeeCount.Quo(poolFeeCount).Mul(poolFeeSumReceived)
|
||||||
//calc1 := candidate.PrevBondedShares.Mul(lastHeightRat).Quo(pool.PrevBondedShares.Mul(lastHeightRat)).Mul(poolFeeRecent)
|
//calc1 := candidate.PrevBondedShares.Mul(lastHeightRat).Quo(pool.PrevBondedShares.Mul(lastHeightRat)).Mul(poolFeeRecent)
|
||||||
|
|
|
@ -23,8 +23,8 @@ package stake
|
||||||
|
|
||||||
//// fee information for a validator
|
//// fee information for a validator
|
||||||
//type Validator struct {
|
//type Validator struct {
|
||||||
//Adjustments []sdk.Rat `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms
|
//Adjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms
|
||||||
//PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // total shares of a global hold pools
|
//PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // total shares of a global hold pools
|
||||||
//}
|
//}
|
||||||
|
|
||||||
////_________________________________________________________________________
|
////_________________________________________________________________________
|
||||||
|
@ -32,7 +32,7 @@ package stake
|
||||||
//// Params defines the high level settings for staking
|
//// Params defines the high level settings for staking
|
||||||
//type Params struct {
|
//type Params struct {
|
||||||
//FeeDenoms []string `json:"fee_denoms"` // accepted fee denoms
|
//FeeDenoms []string `json:"fee_denoms"` // accepted fee denoms
|
||||||
//ReservePoolFee sdk.Rat `json:"reserve_pool_fee"` // percent of fees which go to reserve pool
|
//ReservePoolFee sdk.Dec `json:"reserve_pool_fee"` // percent of fees which go to reserve pool
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//func (p Params) equal(p2 Params) bool {
|
//func (p Params) equal(p2 Params) bool {
|
||||||
|
@ -43,7 +43,7 @@ package stake
|
||||||
//func defaultParams() Params {
|
//func defaultParams() Params {
|
||||||
//return Params{
|
//return Params{
|
||||||
//FeeDenoms: []string{"steak"},
|
//FeeDenoms: []string{"steak"},
|
||||||
//ReservePoolFee: sdk.NewRat(5, 100),
|
//ReservePoolFee: sdk.NewDec(5, 100),
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
@ -55,8 +55,8 @@ package stake
|
||||||
//FeePool sdk.Coins `json:"fee_pool"` // XXX fee pool for all the fee shares which have already been distributed
|
//FeePool sdk.Coins `json:"fee_pool"` // XXX fee pool for all the fee shares which have already been distributed
|
||||||
//FeeSumReceived sdk.Coins `json:"fee_sum_received"` // XXX sum of all fees received, post reserve pool `json:"fee_sum_received"`
|
//FeeSumReceived sdk.Coins `json:"fee_sum_received"` // XXX sum of all fees received, post reserve pool `json:"fee_sum_received"`
|
||||||
//FeeRecent sdk.Coins `json:"fee_recent"` // XXX most recent fee collected
|
//FeeRecent sdk.Coins `json:"fee_recent"` // XXX most recent fee collected
|
||||||
//FeeAdjustments []sdk.Rat `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms
|
//FeeAdjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms
|
||||||
//PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // XXX last recorded bonded shares
|
//PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // XXX last recorded bonded shares
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//func (p Pool) equal(p2 Pool) bool {
|
//func (p Pool) equal(p2 Pool) bool {
|
||||||
|
@ -64,7 +64,7 @@ package stake
|
||||||
//p.FeePool.IsEqual(p2.FeePool) &&
|
//p.FeePool.IsEqual(p2.FeePool) &&
|
||||||
//p.FeeSumReceived.IsEqual(p2.FeeSumReceived) &&
|
//p.FeeSumReceived.IsEqual(p2.FeeSumReceived) &&
|
||||||
//p.FeeRecent.IsEqual(p2.FeeRecent) &&
|
//p.FeeRecent.IsEqual(p2.FeeRecent) &&
|
||||||
//sdk.RatsEqual(p.FeeAdjustments, p2.FeeAdjustments) &&
|
//sdk.DecsEqual(p.FeeAdjustments, p2.FeeAdjustments) &&
|
||||||
//p.PrevBondedShares.Equal(p2.PrevBondedShares)
|
//p.PrevBondedShares.Equal(p2.PrevBondedShares)
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
@ -75,8 +75,8 @@ package stake
|
||||||
//FeePool: sdk.Coins(nil),
|
//FeePool: sdk.Coins(nil),
|
||||||
//FeeSumReceived: sdk.Coins(nil),
|
//FeeSumReceived: sdk.Coins(nil),
|
||||||
//FeeRecent: sdk.Coins(nil),
|
//FeeRecent: sdk.Coins(nil),
|
||||||
//FeeAdjustments: []sdk.Rat{sdk.ZeroRat()},
|
//FeeAdjustments: []sdk.Dec{sdk.ZeroDec()},
|
||||||
//PrevBondedShares: sdk.ZeroRat(),
|
//PrevBondedShares: sdk.ZeroDec(),
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
@ -85,8 +85,8 @@ package stake
|
||||||
//// Used in calculation of fee shares, added to a queue for each block where a power change occures
|
//// Used in calculation of fee shares, added to a queue for each block where a power change occures
|
||||||
//type PowerChange struct {
|
//type PowerChange struct {
|
||||||
//Height int64 `json:"height"` // block height at change
|
//Height int64 `json:"height"` // block height at change
|
||||||
//Power sdk.Rat `json:"power"` // total power at change
|
//Power sdk.Dec `json:"power"` // total power at change
|
||||||
//PrevPower sdk.Rat `json:"prev_power"` // total power at previous height-1
|
//PrevPower sdk.Dec `json:"prev_power"` // total power at previous height-1
|
||||||
//FeesIn sdk.Coins `json:"fees_in"` // fees in at block height
|
//FeesIn sdk.Coins `json:"fees_in"` // fees in at block height
|
||||||
//PrevFeePool sdk.Coins `json:"prev_fee_pool"` // total fees in at previous block height
|
//PrevFeePool sdk.Coins `json:"prev_fee_pool"` // total fees in at previous block height
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -33,9 +33,9 @@ func DefaultGenesisState() GenesisState {
|
||||||
VotingPeriod: 200,
|
VotingPeriod: 200,
|
||||||
},
|
},
|
||||||
TallyingProcedure: TallyingProcedure{
|
TallyingProcedure: TallyingProcedure{
|
||||||
Threshold: sdk.NewRat(1, 2),
|
Threshold: sdk.NewDecWithPrec(5, 1),
|
||||||
Veto: sdk.NewRat(1, 3),
|
Veto: sdk.NewDecWithPrec(334, 3),
|
||||||
GovernancePenalty: sdk.NewRat(1, 100),
|
GovernancePenalty: sdk.NewDecWithPrec(1, 2),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,9 @@ type DepositProcedure struct {
|
||||||
|
|
||||||
// Procedure around Tallying votes in governance
|
// Procedure around Tallying votes in governance
|
||||||
type TallyingProcedure struct {
|
type TallyingProcedure struct {
|
||||||
Threshold sdk.Rat `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
|
Threshold sdk.Dec `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
|
||||||
Veto sdk.Rat `json:"veto"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
|
Veto sdk.Dec `json:"veto"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
|
||||||
GovernancePenalty sdk.Rat `json:"governance_penalty"` // Penalty if validator does not vote
|
GovernancePenalty sdk.Dec `json:"governance_penalty"` // Penalty if validator does not vote
|
||||||
}
|
}
|
||||||
|
|
||||||
// Procedure around Voting in governance
|
// Procedure around Voting in governance
|
||||||
|
|
|
@ -297,19 +297,19 @@ func (status ProposalStatus) Format(s fmt.State, verb rune) {
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
// Tally Results
|
// Tally Results
|
||||||
type TallyResult struct {
|
type TallyResult struct {
|
||||||
Yes sdk.Rat `json:"yes"`
|
Yes sdk.Dec `json:"yes"`
|
||||||
Abstain sdk.Rat `json:"abstain"`
|
Abstain sdk.Dec `json:"abstain"`
|
||||||
No sdk.Rat `json:"no"`
|
No sdk.Dec `json:"no"`
|
||||||
NoWithVeto sdk.Rat `json:"no_with_veto"`
|
NoWithVeto sdk.Dec `json:"no_with_veto"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks if two proposals are equal
|
// checks if two proposals are equal
|
||||||
func EmptyTallyResult() TallyResult {
|
func EmptyTallyResult() TallyResult {
|
||||||
return TallyResult{
|
return TallyResult{
|
||||||
Yes: sdk.ZeroRat(),
|
Yes: sdk.ZeroDec(),
|
||||||
Abstain: sdk.ZeroRat(),
|
Abstain: sdk.ZeroDec(),
|
||||||
No: sdk.ZeroRat(),
|
No: sdk.ZeroDec(),
|
||||||
NoWithVeto: sdk.ZeroRat(),
|
NoWithVeto: sdk.ZeroDec(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,20 +7,20 @@ import (
|
||||||
// validatorGovInfo used for tallying
|
// validatorGovInfo used for tallying
|
||||||
type validatorGovInfo struct {
|
type validatorGovInfo struct {
|
||||||
Address sdk.AccAddress // sdk.AccAddress of the validator owner
|
Address sdk.AccAddress // sdk.AccAddress of the validator owner
|
||||||
Power sdk.Rat // Power of a Validator
|
Power sdk.Dec // Power of a Validator
|
||||||
DelegatorShares sdk.Rat // Total outstanding delegator shares
|
DelegatorShares sdk.Dec // Total outstanding delegator shares
|
||||||
Minus sdk.Rat // Minus of validator, used to compute validator's voting power
|
Minus sdk.Dec // Minus of validator, used to compute validator's voting power
|
||||||
Vote VoteOption // Vote of the validator
|
Vote VoteOption // Vote of the validator
|
||||||
}
|
}
|
||||||
|
|
||||||
func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult, nonVoting []sdk.AccAddress) {
|
func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult, nonVoting []sdk.AccAddress) {
|
||||||
results := make(map[VoteOption]sdk.Rat)
|
results := make(map[VoteOption]sdk.Dec)
|
||||||
results[OptionYes] = sdk.ZeroRat()
|
results[OptionYes] = sdk.ZeroDec()
|
||||||
results[OptionAbstain] = sdk.ZeroRat()
|
results[OptionAbstain] = sdk.ZeroDec()
|
||||||
results[OptionNo] = sdk.ZeroRat()
|
results[OptionNo] = sdk.ZeroDec()
|
||||||
results[OptionNoWithVeto] = sdk.ZeroRat()
|
results[OptionNoWithVeto] = sdk.ZeroDec()
|
||||||
|
|
||||||
totalVotingPower := sdk.ZeroRat()
|
totalVotingPower := sdk.ZeroDec()
|
||||||
currValidators := make(map[string]validatorGovInfo)
|
currValidators := make(map[string]validatorGovInfo)
|
||||||
|
|
||||||
keeper.vs.IterateValidatorsBonded(ctx, func(index int64, validator sdk.Validator) (stop bool) {
|
keeper.vs.IterateValidatorsBonded(ctx, func(index int64, validator sdk.Validator) (stop bool) {
|
||||||
|
@ -28,7 +28,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
|
||||||
Address: validator.GetOwner(),
|
Address: validator.GetOwner(),
|
||||||
Power: validator.GetPower(),
|
Power: validator.GetPower(),
|
||||||
DelegatorShares: validator.GetDelegatorShares(),
|
DelegatorShares: validator.GetDelegatorShares(),
|
||||||
Minus: sdk.ZeroRat(),
|
Minus: sdk.ZeroDec(),
|
||||||
Vote: OptionEmpty,
|
Vote: OptionEmpty,
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -91,7 +91,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no one votes, proposal fails
|
// If no one votes, proposal fails
|
||||||
if totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroRat()) {
|
if totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroDec()) {
|
||||||
return false, tallyResults, nonVoting
|
return false, tallyResults, nonVoting
|
||||||
}
|
}
|
||||||
// If more than 1/3 of voters veto, proposal fails
|
// If more than 1/3 of voters veto, proposal fails
|
||||||
|
|
|
@ -64,7 +64,7 @@ func getInitChainer(mapp *mock.App, keeper Keeper, stakeKeeper stake.Keeper) sdk
|
||||||
mapp.InitChainer(ctx, req)
|
mapp.InitChainer(ctx, req)
|
||||||
|
|
||||||
stakeGenesis := stake.DefaultGenesisState()
|
stakeGenesis := stake.DefaultGenesisState()
|
||||||
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)
|
stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000)
|
||||||
|
|
||||||
validators, err := stake.InitGenesis(ctx, stakeKeeper, stakeGenesis)
|
validators, err := stake.InitGenesis(ctx, stakeKeeper, stakeGenesis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -183,8 +183,8 @@ func (k Getter) GetUint(ctx sdk.Context, key string) (res sdk.Uint, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRat is helper function for rat params
|
// GetDec is helper function for decimal params
|
||||||
func (k Getter) GetRat(ctx sdk.Context, key string) (res sdk.Rat, err error) {
|
func (k Getter) GetDec(ctx sdk.Context, key string) (res sdk.Dec, err error) {
|
||||||
store := ctx.KVStore(k.k.key)
|
store := ctx.KVStore(k.k.key)
|
||||||
bz := store.Get([]byte(key))
|
bz := store.Get([]byte(key))
|
||||||
err = k.k.cdc.UnmarshalBinary(bz, &res)
|
err = k.k.cdc.UnmarshalBinary(bz, &res)
|
||||||
|
@ -301,8 +301,8 @@ func (k Getter) GetUintWithDefault(ctx sdk.Context, key string, def sdk.Uint) (r
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRatWithDefault is helper function for sdk.Rat params with default value
|
// GetDecWithDefault is helper function for sdk.Dec params with default value
|
||||||
func (k Getter) GetRatWithDefault(ctx sdk.Context, key string, def sdk.Rat) (res sdk.Rat) {
|
func (k Getter) GetDecWithDefault(ctx sdk.Context, key string, def sdk.Dec) (res sdk.Dec) {
|
||||||
store := ctx.KVStore(k.k.key)
|
store := ctx.KVStore(k.k.key)
|
||||||
bz := store.Get([]byte(key))
|
bz := store.Get([]byte(key))
|
||||||
if bz == nil {
|
if bz == nil {
|
||||||
|
@ -397,8 +397,8 @@ func (k Setter) SetUint(ctx sdk.Context, key string, param sdk.Uint) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRat is helper function for rat params
|
// SetDec is helper function for decimal params
|
||||||
func (k Setter) SetRat(ctx sdk.Context, key string, param sdk.Rat) {
|
func (k Setter) SetDec(ctx sdk.Context, key string, param sdk.Dec) {
|
||||||
if err := k.k.set(ctx, key, param); err != nil {
|
if err := k.k.set(ctx, key, param); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ func TestGetter(t *testing.T) {
|
||||||
{"uint64", uint64(1)},
|
{"uint64", uint64(1)},
|
||||||
{"int", sdk.NewInt(1)},
|
{"int", sdk.NewInt(1)},
|
||||||
{"uint", sdk.NewUint(1)},
|
{"uint", sdk.NewUint(1)},
|
||||||
{"rat", sdk.NewRat(1)},
|
{"rat", sdk.NewDec(1)},
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.NotPanics(t, func() { s.SetString(ctx, kvs[0].key, "test") })
|
assert.NotPanics(t, func() { s.SetString(ctx, kvs[0].key, "test") })
|
||||||
|
@ -107,7 +107,7 @@ func TestGetter(t *testing.T) {
|
||||||
assert.NotPanics(t, func() { s.SetUint64(ctx, kvs[7].key, uint64(1)) })
|
assert.NotPanics(t, func() { s.SetUint64(ctx, kvs[7].key, uint64(1)) })
|
||||||
assert.NotPanics(t, func() { s.SetInt(ctx, kvs[8].key, sdk.NewInt(1)) })
|
assert.NotPanics(t, func() { s.SetInt(ctx, kvs[8].key, sdk.NewInt(1)) })
|
||||||
assert.NotPanics(t, func() { s.SetUint(ctx, kvs[9].key, sdk.NewUint(1)) })
|
assert.NotPanics(t, func() { s.SetUint(ctx, kvs[9].key, sdk.NewUint(1)) })
|
||||||
assert.NotPanics(t, func() { s.SetRat(ctx, kvs[10].key, sdk.NewRat(1)) })
|
assert.NotPanics(t, func() { s.SetDec(ctx, kvs[10].key, sdk.NewDec(1)) })
|
||||||
|
|
||||||
var res interface{}
|
var res interface{}
|
||||||
var err error
|
var err error
|
||||||
|
@ -263,18 +263,18 @@ func TestGetter(t *testing.T) {
|
||||||
assert.Equal(t, def9, res)
|
assert.Equal(t, def9, res)
|
||||||
|
|
||||||
// Rat
|
// Rat
|
||||||
def10 := sdk.NewRat(0)
|
def10 := sdk.NewDec(0)
|
||||||
res, err = g.GetRat(ctx, kvs[10].key)
|
res, err = g.GetDec(ctx, kvs[10].key)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, kvs[10].param, res)
|
assert.Equal(t, kvs[10].param, res)
|
||||||
|
|
||||||
_, err = g.GetRat(ctx, "invalid")
|
_, err = g.GetDec(ctx, "invalid")
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
res = g.GetRatWithDefault(ctx, kvs[10].key, def10)
|
res = g.GetDecWithDefault(ctx, kvs[10].key, def10)
|
||||||
assert.Equal(t, kvs[10].param, res)
|
assert.Equal(t, kvs[10].param, res)
|
||||||
|
|
||||||
res = g.GetRatWithDefault(ctx, "invalid", def10)
|
res = g.GetDecWithDefault(ctx, "invalid", def10)
|
||||||
assert.Equal(t, def10, res)
|
assert.Equal(t, def10, res)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ func getInitChainer(mapp *mock.App, keeper stake.Keeper) sdk.InitChainer {
|
||||||
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||||
mapp.InitChainer(ctx, req)
|
mapp.InitChainer(ctx, req)
|
||||||
stakeGenesis := stake.DefaultGenesisState()
|
stakeGenesis := stake.DefaultGenesisState()
|
||||||
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)
|
stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000)
|
||||||
validators, err := stake.InitGenesis(ctx, keeper, stakeGenesis)
|
validators, err := stake.InitGenesis(ctx, keeper, stakeGenesis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -109,7 +109,7 @@ func TestSlashingMsgs(t *testing.T) {
|
||||||
validator := checkValidator(t, mapp, stakeKeeper, addr1, true)
|
validator := checkValidator(t, mapp, stakeKeeper, addr1, true)
|
||||||
require.Equal(t, addr1, validator.Owner)
|
require.Equal(t, addr1, validator.Owner)
|
||||||
require.Equal(t, sdk.Bonded, validator.Status)
|
require.Equal(t, sdk.Bonded, validator.Status)
|
||||||
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens()))
|
require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens()))
|
||||||
unrevokeMsg := MsgUnrevoke{ValidatorAddr: sdk.AccAddress(validator.PubKey.Address())}
|
unrevokeMsg := MsgUnrevoke{ValidatorAddr: sdk.AccAddress(validator.PubKey.Address())}
|
||||||
|
|
||||||
// no signing info yet
|
// no signing info yet
|
||||||
|
|
|
@ -20,7 +20,7 @@ func TestCannotUnrevokeUnlessRevoked(t *testing.T) {
|
||||||
require.True(t, got.IsOK())
|
require.True(t, got.IsOK())
|
||||||
stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
||||||
require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
||||||
|
|
||||||
// assert non-revoked validator can't be unrevoked
|
// assert non-revoked validator can't be unrevoked
|
||||||
got = slh(ctx, NewMsgUnrevoke(addr))
|
got = slh(ctx, NewMsgUnrevoke(addr))
|
||||||
|
|
|
@ -31,7 +31,7 @@ func TestHandleDoubleSign(t *testing.T) {
|
||||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||||
keeper.AddValidators(ctx, validatorUpdates)
|
keeper.AddValidators(ctx, validatorUpdates)
|
||||||
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
||||||
require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
||||||
|
|
||||||
// handle a signature to set signing info
|
// handle a signature to set signing info
|
||||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true)
|
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true)
|
||||||
|
@ -44,12 +44,12 @@ func TestHandleDoubleSign(t *testing.T) {
|
||||||
// unrevoke to measure power
|
// unrevoke to measure power
|
||||||
sk.Unrevoke(ctx, val)
|
sk.Unrevoke(ctx, val)
|
||||||
// power should be reduced
|
// power should be reduced
|
||||||
require.Equal(t, sdk.NewRatFromInt(amt).Mul(sdk.NewRat(19).Quo(sdk.NewRat(20))), sk.Validator(ctx, addr).GetPower())
|
require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower())
|
||||||
ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.MaxEvidenceAge(ctx))})
|
ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.MaxEvidenceAge(ctx))})
|
||||||
|
|
||||||
// double sign past max age
|
// double sign past max age
|
||||||
keeper.handleDoubleSign(ctx, val, 0, time.Unix(0, 0), amtInt)
|
keeper.handleDoubleSign(ctx, val, 0, time.Unix(0, 0), amtInt)
|
||||||
require.Equal(t, sdk.NewRatFromInt(amt).Mul(sdk.NewRat(19).Quo(sdk.NewRat(20))), sk.Validator(ctx, addr).GetPower())
|
require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test a validator through uptime, downtime, revocation,
|
// Test a validator through uptime, downtime, revocation,
|
||||||
|
@ -67,7 +67,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||||
keeper.AddValidators(ctx, validatorUpdates)
|
keeper.AddValidators(ctx, validatorUpdates)
|
||||||
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
||||||
require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
||||||
info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
|
info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
require.Equal(t, int64(0), info.StartHeight)
|
require.Equal(t, int64(0), info.StartHeight)
|
||||||
|
@ -131,7 +131,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||||
|
|
||||||
// validator should have been slashed
|
// validator should have been slashed
|
||||||
pool = sk.GetPool(ctx)
|
pool = sk.GetPool(ctx)
|
||||||
slashAmt := sdk.NewRat(amtInt).Mul(keeper.SlashFractionDowntime(ctx)).RoundInt64()
|
slashAmt := sdk.NewDec(amtInt).Mul(keeper.SlashFractionDowntime(ctx)).RoundInt64()
|
||||||
require.Equal(t, int64(amtInt)-slashAmt, pool.BondedTokens.RoundInt64())
|
require.Equal(t, int64(amtInt)-slashAmt, pool.BondedTokens.RoundInt64())
|
||||||
|
|
||||||
// validator start height should have been changed
|
// validator start height should have been changed
|
||||||
|
@ -177,7 +177,7 @@ func TestHandleNewValidator(t *testing.T) {
|
||||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||||
keeper.AddValidators(ctx, validatorUpdates)
|
keeper.AddValidators(ctx, validatorUpdates)
|
||||||
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.SubRaw(amt)}})
|
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.SubRaw(amt)}})
|
||||||
require.Equal(t, sdk.NewRat(amt), sk.Validator(ctx, addr).GetPower())
|
require.Equal(t, sdk.NewDec(amt), sk.Validator(ctx, addr).GetPower())
|
||||||
|
|
||||||
// 1000 first blocks not a validator
|
// 1000 first blocks not a validator
|
||||||
ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 1)
|
ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 1)
|
||||||
|
|
|
@ -30,9 +30,9 @@ func (k Keeper) SignedBlocksWindow(ctx sdk.Context) int64 {
|
||||||
|
|
||||||
// Downtime slashing thershold - default 50%
|
// Downtime slashing thershold - default 50%
|
||||||
func (k Keeper) MinSignedPerWindow(ctx sdk.Context) int64 {
|
func (k Keeper) MinSignedPerWindow(ctx sdk.Context) int64 {
|
||||||
minSignedPerWindow := k.params.GetRatWithDefault(ctx, MinSignedPerWindowKey, defaultMinSignedPerWindow)
|
minSignedPerWindow := k.params.GetDecWithDefault(ctx, MinSignedPerWindowKey, defaultMinSignedPerWindow)
|
||||||
signedBlocksWindow := k.SignedBlocksWindow(ctx)
|
signedBlocksWindow := k.SignedBlocksWindow(ctx)
|
||||||
return sdk.NewRat(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64()
|
return sdk.NewDec(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Double-sign unbond duration
|
// Double-sign unbond duration
|
||||||
|
@ -46,13 +46,13 @@ func (k Keeper) DowntimeUnbondDuration(ctx sdk.Context) time.Duration {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SlashFractionDoubleSign - currently default 5%
|
// SlashFractionDoubleSign - currently default 5%
|
||||||
func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) sdk.Rat {
|
func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) sdk.Dec {
|
||||||
return k.params.GetRatWithDefault(ctx, SlashFractionDoubleSignKey, defaultSlashFractionDoubleSign)
|
return k.params.GetDecWithDefault(ctx, SlashFractionDoubleSignKey, defaultSlashFractionDoubleSign)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SlashFractionDowntime - currently default 1%
|
// SlashFractionDowntime - currently default 1%
|
||||||
func (k Keeper) SlashFractionDowntime(ctx sdk.Context) sdk.Rat {
|
func (k Keeper) SlashFractionDowntime(ctx sdk.Context) sdk.Dec {
|
||||||
return k.params.GetRatWithDefault(ctx, SlashFractionDowntimeKey, defaultSlashFractionDowntime)
|
return k.params.GetDecWithDefault(ctx, SlashFractionDowntimeKey, defaultSlashFractionDowntime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// declared as var because of keeper_test.go
|
// declared as var because of keeper_test.go
|
||||||
|
@ -72,9 +72,9 @@ var (
|
||||||
// TODO Temporarily set to 10 minutes for testnets
|
// TODO Temporarily set to 10 minutes for testnets
|
||||||
defaultDowntimeUnbondDuration int64 = 60 * 10
|
defaultDowntimeUnbondDuration int64 = 60 * 10
|
||||||
|
|
||||||
defaultMinSignedPerWindow = sdk.NewRat(1, 2)
|
defaultMinSignedPerWindow = sdk.NewDecWithPrec(5, 1)
|
||||||
|
|
||||||
defaultSlashFractionDoubleSign = sdk.NewRat(1).Quo(sdk.NewRat(20))
|
defaultSlashFractionDoubleSign = sdk.NewDec(1).Quo(sdk.NewDec(20))
|
||||||
|
|
||||||
defaultSlashFractionDowntime = sdk.NewRat(1).Quo(sdk.NewRat(100))
|
defaultSlashFractionDowntime = sdk.NewDec(1).Quo(sdk.NewDec(100))
|
||||||
)
|
)
|
||||||
|
|
|
@ -69,7 +69,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para
|
||||||
sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace)
|
sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace)
|
||||||
genesis := stake.DefaultGenesisState()
|
genesis := stake.DefaultGenesisState()
|
||||||
|
|
||||||
genesis.Pool.LooseTokens = sdk.NewRat(initCoins.MulRaw(int64(len(addrs))).Int64())
|
genesis.Pool.LooseTokens = sdk.NewDec(initCoins.MulRaw(int64(len(addrs))).Int64())
|
||||||
|
|
||||||
_, err = stake.InitGenesis(ctx, sk, genesis)
|
_, err = stake.InitGenesis(ctx, sk, genesis)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
|
@ -22,7 +22,7 @@ func TestBeginBlocker(t *testing.T) {
|
||||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||||
keeper.AddValidators(ctx, validatorUpdates)
|
keeper.AddValidators(ctx, validatorUpdates)
|
||||||
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
|
||||||
require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
||||||
|
|
||||||
val := abci.Validator{
|
val := abci.Validator{
|
||||||
Address: pk.Address(),
|
Address: pk.Address(),
|
||||||
|
|
|
@ -63,7 +63,7 @@ func getInitChainer(mapp *mock.App, keeper Keeper) sdk.InitChainer {
|
||||||
mapp.InitChainer(ctx, req)
|
mapp.InitChainer(ctx, req)
|
||||||
|
|
||||||
stakeGenesis := DefaultGenesisState()
|
stakeGenesis := DefaultGenesisState()
|
||||||
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)
|
stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000)
|
||||||
|
|
||||||
validators, err := InitGenesis(ctx, keeper, stakeGenesis)
|
validators, err := InitGenesis(ctx, keeper, stakeGenesis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -90,14 +90,14 @@ func checkValidator(t *testing.T, mapp *mock.App, keeper Keeper,
|
||||||
|
|
||||||
func checkDelegation(
|
func checkDelegation(
|
||||||
t *testing.T, mapp *mock.App, keeper Keeper, delegatorAddr,
|
t *testing.T, mapp *mock.App, keeper Keeper, delegatorAddr,
|
||||||
validatorAddr sdk.AccAddress, expFound bool, expShares sdk.Rat,
|
validatorAddr sdk.AccAddress, expFound bool, expShares sdk.Dec,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{})
|
ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{})
|
||||||
delegation, found := keeper.GetDelegation(ctxCheck, delegatorAddr, validatorAddr)
|
delegation, found := keeper.GetDelegation(ctxCheck, delegatorAddr, validatorAddr)
|
||||||
if expFound {
|
if expFound {
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.True(sdk.RatEq(t, expShares, delegation.Shares))
|
require.True(sdk.DecEq(t, expShares, delegation.Shares))
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ func TestStakeMsgs(t *testing.T) {
|
||||||
validator := checkValidator(t, mApp, keeper, addr1, true)
|
validator := checkValidator(t, mApp, keeper, addr1, true)
|
||||||
require.Equal(t, addr1, validator.Owner)
|
require.Equal(t, addr1, validator.Owner)
|
||||||
require.Equal(t, sdk.Bonded, validator.Status)
|
require.Equal(t, sdk.Bonded, validator.Status)
|
||||||
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens()))
|
require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens()))
|
||||||
|
|
||||||
// addr1 create validator on behalf of addr2
|
// addr1 create validator on behalf of addr2
|
||||||
createValidatorMsgOnBehalfOf := NewMsgCreateValidatorOnBehalfOf(addr1, addr2, priv2.PubKey(), bondCoin, description)
|
createValidatorMsgOnBehalfOf := NewMsgCreateValidatorOnBehalfOf(addr1, addr2, priv2.PubKey(), bondCoin, description)
|
||||||
|
@ -150,10 +150,10 @@ func TestStakeMsgs(t *testing.T) {
|
||||||
validator = checkValidator(t, mApp, keeper, addr2, true)
|
validator = checkValidator(t, mApp, keeper, addr2, true)
|
||||||
require.Equal(t, addr2, validator.Owner)
|
require.Equal(t, addr2, validator.Owner)
|
||||||
require.Equal(t, sdk.Bonded, validator.Status)
|
require.Equal(t, sdk.Bonded, validator.Status)
|
||||||
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
|
require.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||||
|
|
||||||
// check the bond that should have been created as well
|
// check the bond that should have been created as well
|
||||||
checkDelegation(t, mApp, keeper, addr1, addr1, true, sdk.NewRat(10))
|
checkDelegation(t, mApp, keeper, addr1, addr1, true, sdk.NewDec(10))
|
||||||
|
|
||||||
// edit the validator
|
// edit the validator
|
||||||
description = NewDescription("bar_moniker", "", "", "")
|
description = NewDescription("bar_moniker", "", "", "")
|
||||||
|
@ -169,14 +169,14 @@ func TestStakeMsgs(t *testing.T) {
|
||||||
|
|
||||||
mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{delegateMsg}, []int64{1}, []int64{1}, true, priv2)
|
mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{delegateMsg}, []int64{1}, []int64{1}, true, priv2)
|
||||||
mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)})
|
mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)})
|
||||||
checkDelegation(t, mApp, keeper, addr2, addr1, true, sdk.NewRat(10))
|
checkDelegation(t, mApp, keeper, addr2, addr1, true, sdk.NewDec(10))
|
||||||
|
|
||||||
// begin unbonding
|
// begin unbonding
|
||||||
beginUnbondingMsg := NewMsgBeginUnbonding(addr2, addr1, sdk.NewRat(10))
|
beginUnbondingMsg := NewMsgBeginUnbonding(addr2, addr1, sdk.NewDec(10))
|
||||||
mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{beginUnbondingMsg}, []int64{1}, []int64{2}, true, priv2)
|
mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{beginUnbondingMsg}, []int64{1}, []int64{2}, true, priv2)
|
||||||
|
|
||||||
// delegation should exist anymore
|
// delegation should exist anymore
|
||||||
checkDelegation(t, mApp, keeper, addr2, addr1, false, sdk.Rat{})
|
checkDelegation(t, mApp, keeper, addr2, addr1, false, sdk.Dec{})
|
||||||
|
|
||||||
// balance should be the same because bonding not yet complete
|
// balance should be the same because bonding not yet complete
|
||||||
mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)})
|
mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)})
|
||||||
|
|
|
@ -239,27 +239,27 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command {
|
||||||
func getShares(
|
func getShares(
|
||||||
storeName string, cdc *wire.Codec, sharesAmountStr,
|
storeName string, cdc *wire.Codec, sharesAmountStr,
|
||||||
sharesPercentStr string, delegatorAddr, validatorAddr sdk.AccAddress,
|
sharesPercentStr string, delegatorAddr, validatorAddr sdk.AccAddress,
|
||||||
) (sharesAmount sdk.Rat, err error) {
|
) (sharesAmount sdk.Dec, err error) {
|
||||||
switch {
|
switch {
|
||||||
case sharesAmountStr != "" && sharesPercentStr != "":
|
case sharesAmountStr != "" && sharesPercentStr != "":
|
||||||
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
|
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
|
||||||
case sharesAmountStr == "" && sharesPercentStr == "":
|
case sharesAmountStr == "" && sharesPercentStr == "":
|
||||||
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
|
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
|
||||||
case sharesAmountStr != "":
|
case sharesAmountStr != "":
|
||||||
sharesAmount, err = sdk.NewRatFromDecimal(sharesAmountStr, types.MaxBondDenominatorPrecision)
|
sharesAmount, err = sdk.NewDecFromStr(sharesAmountStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sharesAmount, err
|
return sharesAmount, err
|
||||||
}
|
}
|
||||||
if !sharesAmount.GT(sdk.ZeroRat()) {
|
if !sharesAmount.GT(sdk.ZeroDec()) {
|
||||||
return sharesAmount, errors.Errorf("shares amount must be positive number (ex. 123, 1.23456789)")
|
return sharesAmount, errors.Errorf("shares amount must be positive number (ex. 123, 1.23456789)")
|
||||||
}
|
}
|
||||||
case sharesPercentStr != "":
|
case sharesPercentStr != "":
|
||||||
var sharesPercent sdk.Rat
|
var sharesPercent sdk.Dec
|
||||||
sharesPercent, err = sdk.NewRatFromDecimal(sharesPercentStr, types.MaxBondDenominatorPrecision)
|
sharesPercent, err = sdk.NewDecFromStr(sharesPercentStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sharesAmount, err
|
return sharesAmount, err
|
||||||
}
|
}
|
||||||
if !sharesPercent.GT(sdk.ZeroRat()) || !sharesPercent.LTE(sdk.OneRat()) {
|
if !sharesPercent.GT(sdk.ZeroDec()) || !sharesPercent.LTE(sdk.OneDec()) {
|
||||||
return sharesAmount, errors.Errorf("shares percent must be >0 and <=1 (ex. 0.01, 0.75, 1)")
|
return sharesAmount, errors.Errorf("shares percent must be >0 and <=1 (ex. 0.01, 0.75, 1)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -347,7 +347,7 @@ func delegationHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handle
|
||||||
DelegatorAddr: delegation.DelegatorAddr,
|
DelegatorAddr: delegation.DelegatorAddr,
|
||||||
ValidatorAddr: delegation.ValidatorAddr,
|
ValidatorAddr: delegation.ValidatorAddr,
|
||||||
Height: delegation.Height,
|
Height: delegation.Height,
|
||||||
Shares: delegation.Shares.FloatString(),
|
Shares: delegation.Shares.String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
output, err := cdc.MarshalJSON(outputDelegation)
|
output, err := cdc.MarshalJSON(outputDelegation)
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/wire"
|
"github.com/cosmos/cosmos-sdk/wire"
|
||||||
authcliCtx "github.com/cosmos/cosmos-sdk/x/auth/client/context"
|
authcliCtx "github.com/cosmos/cosmos-sdk/x/auth/client/context"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
|
@ -160,7 +159,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
shares, err := sdk.NewRatFromDecimal(msg.SharesAmount, types.MaxBondDenominatorPrecision)
|
shares, err := sdk.NewDecFromStr(msg.SharesAmount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error())))
|
w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error())))
|
||||||
|
@ -234,7 +233,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
shares, err := sdk.NewRatFromDecimal(msg.SharesAmount, types.MaxBondDenominatorPrecision)
|
shares, err := sdk.NewDecFromStr(msg.SharesAmount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error())))
|
w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error())))
|
||||||
|
|
|
@ -76,7 +76,7 @@ func getDelegatorDelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegat
|
||||||
DelegatorAddr: delegation.DelegatorAddr,
|
DelegatorAddr: delegation.DelegatorAddr,
|
||||||
ValidatorAddr: delegation.ValidatorAddr,
|
ValidatorAddr: delegation.ValidatorAddr,
|
||||||
Height: delegation.Height,
|
Height: delegation.Height,
|
||||||
Shares: delegation.Shares.FloatString(),
|
Shares: delegation.Shares.String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return outputDelegation, http.StatusOK, "", nil
|
return outputDelegation, http.StatusOK, "", nil
|
||||||
|
|
|
@ -17,7 +17,7 @@ func TestInitGenesis(t *testing.T) {
|
||||||
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
||||||
|
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
pool.BondedTokens = sdk.NewRat(2)
|
pool.BondedTokens = sdk.NewDec(2)
|
||||||
|
|
||||||
params := keeper.GetParams(ctx)
|
params := keeper.GetParams(ctx)
|
||||||
var delegations []Delegation
|
var delegations []Delegation
|
||||||
|
@ -32,11 +32,11 @@ func TestInitGenesis(t *testing.T) {
|
||||||
|
|
||||||
// initialize the validators
|
// initialize the validators
|
||||||
validators[0].Status = sdk.Bonded
|
validators[0].Status = sdk.Bonded
|
||||||
validators[0].Tokens = sdk.OneRat()
|
validators[0].Tokens = sdk.OneDec()
|
||||||
validators[0].DelegatorShares = sdk.OneRat()
|
validators[0].DelegatorShares = sdk.OneDec()
|
||||||
validators[1].Status = sdk.Bonded
|
validators[1].Status = sdk.Bonded
|
||||||
validators[1].Tokens = sdk.OneRat()
|
validators[1].Tokens = sdk.OneDec()
|
||||||
validators[1].DelegatorShares = sdk.OneRat()
|
validators[1].DelegatorShares = sdk.OneDec()
|
||||||
|
|
||||||
genesisState = types.NewGenesisState(pool, params, validators, delegations)
|
genesisState = types.NewGenesisState(pool, params, validators, delegations)
|
||||||
vals, err := InitGenesis(ctx, keeper, genesisState)
|
vals, err := InitGenesis(ctx, keeper, genesisState)
|
||||||
|
@ -69,7 +69,7 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) {
|
||||||
|
|
||||||
// Assigning 2 to the first 100 vals, 1 to the rest
|
// Assigning 2 to the first 100 vals, 1 to the rest
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
pool.BondedTokens = sdk.NewRat(int64(200 + (size - 100)))
|
pool.BondedTokens = sdk.NewDec(int64(200 + (size - 100)))
|
||||||
|
|
||||||
params := keeper.GetParams(ctx)
|
params := keeper.GetParams(ctx)
|
||||||
delegations := []Delegation{}
|
delegations := []Delegation{}
|
||||||
|
@ -80,11 +80,11 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) {
|
||||||
|
|
||||||
validators[i].Status = sdk.Bonded
|
validators[i].Status = sdk.Bonded
|
||||||
if i < 100 {
|
if i < 100 {
|
||||||
validators[i].Tokens = sdk.NewRat(2)
|
validators[i].Tokens = sdk.NewDec(2)
|
||||||
validators[i].DelegatorShares = sdk.NewRat(2)
|
validators[i].DelegatorShares = sdk.NewDec(2)
|
||||||
} else {
|
} else {
|
||||||
validators[i].Tokens = sdk.OneRat()
|
validators[i].Tokens = sdk.OneDec()
|
||||||
validators[i].DelegatorShares = sdk.OneRat()
|
validators[i].DelegatorShares = sdk.OneDec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ func TestValidatorByPowerIndex(t *testing.T) {
|
||||||
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
||||||
|
|
||||||
// slash and revoke the first validator
|
// slash and revoke the first validator
|
||||||
keeper.Slash(ctx, keep.PKs[0], 0, initBond, sdk.NewRat(1, 2))
|
keeper.Slash(ctx, keep.PKs[0], 0, initBond, sdk.NewDecWithPrec(5, 1))
|
||||||
keeper.Revoke(ctx, keep.PKs[0])
|
keeper.Revoke(ctx, keep.PKs[0])
|
||||||
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
|
@ -110,7 +110,7 @@ func TestValidatorByPowerIndex(t *testing.T) {
|
||||||
require.Equal(t, power2, power3)
|
require.Equal(t, power2, power3)
|
||||||
|
|
||||||
// unbond self-delegation
|
// unbond self-delegation
|
||||||
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(1000000))
|
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(1000000))
|
||||||
msgCompleteUnbonding := NewMsgCompleteUnbonding(validatorAddr, validatorAddr)
|
msgCompleteUnbonding := NewMsgCompleteUnbonding(validatorAddr, validatorAddr)
|
||||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||||
|
@ -138,8 +138,8 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) {
|
||||||
assert.Equal(t, sdk.Bonded, validator.Status)
|
assert.Equal(t, sdk.Bonded, validator.Status)
|
||||||
assert.Equal(t, addr1, validator.Owner)
|
assert.Equal(t, addr1, validator.Owner)
|
||||||
assert.Equal(t, pk1, validator.PubKey)
|
assert.Equal(t, pk1, validator.PubKey)
|
||||||
assert.Equal(t, sdk.NewRat(10), validator.BondedTokens())
|
assert.Equal(t, sdk.NewDec(10), validator.BondedTokens())
|
||||||
assert.Equal(t, sdk.NewRat(10), validator.DelegatorShares)
|
assert.Equal(t, sdk.NewDec(10), validator.DelegatorShares)
|
||||||
assert.Equal(t, Description{}, validator.Description)
|
assert.Equal(t, Description{}, validator.Description)
|
||||||
|
|
||||||
// two validators can't have the same owner address
|
// two validators can't have the same owner address
|
||||||
|
@ -162,8 +162,8 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) {
|
||||||
assert.Equal(t, sdk.Bonded, validator.Status)
|
assert.Equal(t, sdk.Bonded, validator.Status)
|
||||||
assert.Equal(t, addr2, validator.Owner)
|
assert.Equal(t, addr2, validator.Owner)
|
||||||
assert.Equal(t, pk2, validator.PubKey)
|
assert.Equal(t, pk2, validator.PubKey)
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
|
||||||
assert.Equal(t, Description{}, validator.Description)
|
assert.Equal(t, Description{}, validator.Description)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,8 +182,8 @@ func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) {
|
||||||
assert.Equal(t, sdk.Bonded, validator.Status)
|
assert.Equal(t, sdk.Bonded, validator.Status)
|
||||||
assert.Equal(t, validatorAddr, validator.Owner)
|
assert.Equal(t, validatorAddr, validator.Owner)
|
||||||
assert.Equal(t, pk, validator.PubKey)
|
assert.Equal(t, pk, validator.PubKey)
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
|
||||||
assert.Equal(t, Description{}, validator.Description)
|
assert.Equal(t, Description{}, validator.Description)
|
||||||
|
|
||||||
// one validator cannot be created twice even from different delegator
|
// one validator cannot be created twice even from different delegator
|
||||||
|
@ -221,7 +221,7 @@ func TestIncrementsMsgDelegate(t *testing.T) {
|
||||||
|
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
exRate := validator.DelegatorShareExRate()
|
exRate := validator.DelegatorShareExRate()
|
||||||
require.True(t, exRate.Equal(sdk.OneRat()), "expected exRate 1 got %v", exRate)
|
require.True(t, exRate.Equal(sdk.OneDec()), "expected exRate 1 got %v", exRate)
|
||||||
require.Equal(t, bondAmount, pool.BondedTokens.RoundInt64())
|
require.Equal(t, bondAmount, pool.BondedTokens.RoundInt64())
|
||||||
|
|
||||||
// just send the same msgbond multiple times
|
// just send the same msgbond multiple times
|
||||||
|
@ -240,7 +240,7 @@ func TestIncrementsMsgDelegate(t *testing.T) {
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
|
|
||||||
exRate := validator.DelegatorShareExRate()
|
exRate := validator.DelegatorShareExRate()
|
||||||
require.True(t, exRate.Equal(sdk.OneRat()), "expected exRate 1 got %v, i = %v", exRate, i)
|
require.True(t, exRate.Equal(sdk.OneDec()), "expected exRate 1 got %v, i = %v", exRate, i)
|
||||||
|
|
||||||
expBond := int64(i+1) * bondAmount
|
expBond := int64(i+1) * bondAmount
|
||||||
expDelegatorShares := int64(i+2) * bondAmount // (1 self delegation)
|
expDelegatorShares := int64(i+2) * bondAmount // (1 self delegation)
|
||||||
|
@ -295,7 +295,7 @@ func TestIncrementsMsgUnbond(t *testing.T) {
|
||||||
|
|
||||||
// just send the same msgUnbond multiple times
|
// just send the same msgUnbond multiple times
|
||||||
// TODO use decimals here
|
// TODO use decimals here
|
||||||
unbondShares := sdk.NewRat(10)
|
unbondShares := sdk.NewDec(10)
|
||||||
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
|
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
|
||||||
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
|
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
|
||||||
numUnbonds := 5
|
numUnbonds := 5
|
||||||
|
@ -339,7 +339,7 @@ func TestIncrementsMsgUnbond(t *testing.T) {
|
||||||
initBond,
|
initBond,
|
||||||
}
|
}
|
||||||
for _, c := range errorCases {
|
for _, c := range errorCases {
|
||||||
unbondShares := sdk.NewRat(int64(c))
|
unbondShares := sdk.NewDec(int64(c))
|
||||||
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
|
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
|
||||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||||
require.False(t, got.IsOK(), "expected unbond msg to fail")
|
require.False(t, got.IsOK(), "expected unbond msg to fail")
|
||||||
|
@ -348,14 +348,14 @@ func TestIncrementsMsgUnbond(t *testing.T) {
|
||||||
leftBonded := initBond - int64(numUnbonds)*unbondShares.RoundInt64()
|
leftBonded := initBond - int64(numUnbonds)*unbondShares.RoundInt64()
|
||||||
|
|
||||||
// should be unable to unbond one more than we have
|
// should be unable to unbond one more than we have
|
||||||
unbondShares = sdk.NewRat(leftBonded + 1)
|
unbondShares = sdk.NewDec(leftBonded + 1)
|
||||||
msgBeginUnbonding = NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
|
msgBeginUnbonding = NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
|
||||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||||
require.False(t, got.IsOK(),
|
require.False(t, got.IsOK(),
|
||||||
"got: %v\nmsgUnbond: %v\nshares: %v\nleftBonded: %v\n", got, msgBeginUnbonding, unbondShares.String(), leftBonded)
|
"got: %v\nmsgUnbond: %v\nshares: %v\nleftBonded: %v\n", got, msgBeginUnbonding, unbondShares.String(), leftBonded)
|
||||||
|
|
||||||
// should be able to unbond just what we have
|
// should be able to unbond just what we have
|
||||||
unbondShares = sdk.NewRat(leftBonded)
|
unbondShares = sdk.NewDec(leftBonded)
|
||||||
msgBeginUnbonding = NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
|
msgBeginUnbonding = NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
|
||||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||||
require.True(t, got.IsOK(),
|
require.True(t, got.IsOK(),
|
||||||
|
@ -391,7 +391,7 @@ func TestMultipleMsgCreateValidator(t *testing.T) {
|
||||||
for i, validatorAddr := range validatorAddrs {
|
for i, validatorAddr := range validatorAddrs {
|
||||||
_, found := keeper.GetValidator(ctx, validatorAddr)
|
_, found := keeper.GetValidator(ctx, validatorAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddrs[i], validatorAddr, sdk.NewRat(10)) // remove delegation
|
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddrs[i], validatorAddr, sdk.NewDec(10)) // remove delegation
|
||||||
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddrs[i], validatorAddr)
|
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddrs[i], validatorAddr)
|
||||||
got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||||
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
|
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
|
||||||
|
@ -436,7 +436,7 @@ func TestMultipleMsgDelegate(t *testing.T) {
|
||||||
|
|
||||||
// unbond them all
|
// unbond them all
|
||||||
for i, delegatorAddr := range delegatorAddrs {
|
for i, delegatorAddr := range delegatorAddrs {
|
||||||
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewRat(10))
|
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewDec(10))
|
||||||
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
|
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
|
||||||
got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||||
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
|
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
|
||||||
|
@ -467,7 +467,7 @@ func TestRevokeValidator(t *testing.T) {
|
||||||
validator, _ := keeper.GetValidator(ctx, validatorAddr)
|
validator, _ := keeper.GetValidator(ctx, validatorAddr)
|
||||||
|
|
||||||
// unbond the validators bond portion
|
// unbond the validators bond portion
|
||||||
msgBeginUnbondingValidator := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(10))
|
msgBeginUnbondingValidator := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(10))
|
||||||
msgCompleteUnbondingValidator := NewMsgCompleteUnbonding(validatorAddr, validatorAddr)
|
msgCompleteUnbondingValidator := NewMsgCompleteUnbonding(validatorAddr, validatorAddr)
|
||||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper)
|
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper)
|
||||||
require.True(t, got.IsOK(), "expected no error")
|
require.True(t, got.IsOK(), "expected no error")
|
||||||
|
@ -483,7 +483,7 @@ func TestRevokeValidator(t *testing.T) {
|
||||||
require.False(t, got.IsOK(), "expected error, got %v", got)
|
require.False(t, got.IsOK(), "expected error, got %v", got)
|
||||||
|
|
||||||
// test that the delegator can still withdraw their bonds
|
// test that the delegator can still withdraw their bonds
|
||||||
msgBeginUnbondingDelegator := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewRat(10))
|
msgBeginUnbondingDelegator := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewDec(10))
|
||||||
msgCompleteUnbondingDelegator := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
|
msgCompleteUnbondingDelegator := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
|
||||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingDelegator, keeper)
|
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingDelegator, keeper)
|
||||||
require.True(t, got.IsOK(), "expected no error")
|
require.True(t, got.IsOK(), "expected no error")
|
||||||
|
@ -510,7 +510,7 @@ func TestUnbondingPeriod(t *testing.T) {
|
||||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||||
|
|
||||||
// begin unbonding
|
// begin unbonding
|
||||||
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(10))
|
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(10))
|
||||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||||
require.True(t, got.IsOK(), "expected no error")
|
require.True(t, got.IsOK(), "expected no error")
|
||||||
|
|
||||||
|
@ -565,7 +565,7 @@ func TestRedelegationPeriod(t *testing.T) {
|
||||||
bal1 := AccMapper.GetAccount(ctx, validatorAddr).GetCoins()
|
bal1 := AccMapper.GetAccount(ctx, validatorAddr).GetCoins()
|
||||||
|
|
||||||
// begin redelegate
|
// begin redelegate
|
||||||
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewRat(10))
|
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewDec(10))
|
||||||
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
||||||
require.True(t, got.IsOK(), "expected no error, %v", got)
|
require.True(t, got.IsOK(), "expected no error, %v", got)
|
||||||
|
|
||||||
|
@ -617,12 +617,12 @@ func TestTransitiveRedelegation(t *testing.T) {
|
||||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||||
|
|
||||||
// begin redelegate
|
// begin redelegate
|
||||||
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewRat(10))
|
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewDec(10))
|
||||||
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
||||||
require.True(t, got.IsOK(), "expected no error, %v", got)
|
require.True(t, got.IsOK(), "expected no error, %v", got)
|
||||||
|
|
||||||
// cannot redelegation to next validator while first delegation exists
|
// cannot redelegation to next validator while first delegation exists
|
||||||
msgBeginRedelegate = NewMsgBeginRedelegate(validatorAddr, validatorAddr2, validatorAddr3, sdk.NewRat(10))
|
msgBeginRedelegate = NewMsgBeginRedelegate(validatorAddr, validatorAddr2, validatorAddr3, sdk.NewDec(10))
|
||||||
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
||||||
require.True(t, !got.IsOK(), "expected an error, msg: %v", msgBeginRedelegate)
|
require.True(t, !got.IsOK(), "expected an error, msg: %v", msgBeginRedelegate)
|
||||||
|
|
||||||
|
@ -663,7 +663,7 @@ func TestUnbondingWhenExcessValidators(t *testing.T) {
|
||||||
require.Equal(t, 2, len(keeper.GetValidatorsBonded(ctx)))
|
require.Equal(t, 2, len(keeper.GetValidatorsBonded(ctx)))
|
||||||
|
|
||||||
// unbond the valdator-2
|
// unbond the valdator-2
|
||||||
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewRat(30))
|
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewDec(30))
|
||||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||||
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
|
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
|
||||||
|
|
||||||
|
@ -785,7 +785,7 @@ func TestCliffValidator(t *testing.T) {
|
||||||
require.Equal(t, validatorAddr2.Bytes(), cliffVal)
|
require.Equal(t, validatorAddr2.Bytes(), cliffVal)
|
||||||
|
|
||||||
// unbond valdator-2
|
// unbond valdator-2
|
||||||
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewRat(30))
|
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewDec(30))
|
||||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||||
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
|
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
|
||||||
|
|
||||||
|
@ -798,7 +798,7 @@ func TestCliffValidator(t *testing.T) {
|
||||||
require.Equal(t, validatorAddr3.Bytes(), cliffVal)
|
require.Equal(t, validatorAddr3.Bytes(), cliffVal)
|
||||||
|
|
||||||
// unbond valdator-1
|
// unbond valdator-1
|
||||||
msgBeginUnbonding = NewMsgBeginUnbonding(validatorAddr1, validatorAddr1, sdk.NewRat(50))
|
msgBeginUnbonding = NewMsgBeginUnbonding(validatorAddr1, validatorAddr1, sdk.NewDec(50))
|
||||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||||
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
|
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
|
||||||
|
|
||||||
|
@ -832,22 +832,22 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
|
||||||
ctx = ctx.WithBlockHeight(1)
|
ctx = ctx.WithBlockHeight(1)
|
||||||
|
|
||||||
// begin unbonding 4 stake
|
// begin unbonding 4 stake
|
||||||
msgBeginUnbonding := NewMsgBeginUnbonding(del, valA, sdk.NewRat(4))
|
msgBeginUnbonding := NewMsgBeginUnbonding(del, valA, sdk.NewDec(4))
|
||||||
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
|
||||||
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
|
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
|
||||||
|
|
||||||
// begin redelegate 6 stake
|
// begin redelegate 6 stake
|
||||||
msgBeginRedelegate := NewMsgBeginRedelegate(del, valA, valB, sdk.NewRat(6))
|
msgBeginRedelegate := NewMsgBeginRedelegate(del, valA, valB, sdk.NewDec(6))
|
||||||
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
||||||
require.True(t, got.IsOK(), "expected no error on runMsgBeginRedelegate")
|
require.True(t, got.IsOK(), "expected no error on runMsgBeginRedelegate")
|
||||||
|
|
||||||
// destination delegation should have 6 shares
|
// destination delegation should have 6 shares
|
||||||
delegation, found := keeper.GetDelegation(ctx, del, valB)
|
delegation, found := keeper.GetDelegation(ctx, del, valB)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, sdk.NewRat(6), delegation.Shares)
|
require.Equal(t, sdk.NewDec(6), delegation.Shares)
|
||||||
|
|
||||||
// slash the validator by half
|
// slash the validator by half
|
||||||
keeper.Slash(ctx, keep.PKs[0], 0, 20, sdk.NewRat(1, 2))
|
keeper.Slash(ctx, keep.PKs[0], 0, 20, sdk.NewDecWithPrec(5, 1))
|
||||||
|
|
||||||
// unbonding delegation should have been slashed by half
|
// unbonding delegation should have been slashed by half
|
||||||
unbonding, found := keeper.GetUnbondingDelegation(ctx, del, valA)
|
unbonding, found := keeper.GetUnbondingDelegation(ctx, del, valA)
|
||||||
|
@ -862,16 +862,16 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
|
||||||
// destination delegation should have been slashed by half
|
// destination delegation should have been slashed by half
|
||||||
delegation, found = keeper.GetDelegation(ctx, del, valB)
|
delegation, found = keeper.GetDelegation(ctx, del, valB)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, sdk.NewRat(3), delegation.Shares)
|
require.Equal(t, sdk.NewDec(3), delegation.Shares)
|
||||||
|
|
||||||
// validator power should have been reduced by half
|
// validator power should have been reduced by half
|
||||||
validator, found := keeper.GetValidator(ctx, valA)
|
validator, found := keeper.GetValidator(ctx, valA)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, sdk.NewRat(5), validator.GetPower())
|
require.Equal(t, sdk.NewDec(5), validator.GetPower())
|
||||||
|
|
||||||
// slash the validator for an infraction committed after the unbonding and redelegation begin
|
// slash the validator for an infraction committed after the unbonding and redelegation begin
|
||||||
ctx = ctx.WithBlockHeight(3)
|
ctx = ctx.WithBlockHeight(3)
|
||||||
keeper.Slash(ctx, keep.PKs[0], 2, 10, sdk.NewRat(1, 2))
|
keeper.Slash(ctx, keep.PKs[0], 2, 10, sdk.NewDecWithPrec(5, 1))
|
||||||
|
|
||||||
// unbonding delegation should be unchanged
|
// unbonding delegation should be unchanged
|
||||||
unbonding, found = keeper.GetUnbondingDelegation(ctx, del, valA)
|
unbonding, found = keeper.GetUnbondingDelegation(ctx, del, valA)
|
||||||
|
@ -886,7 +886,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
|
||||||
// destination delegation should be unchanged
|
// destination delegation should be unchanged
|
||||||
delegation, found = keeper.GetDelegation(ctx, del, valB)
|
delegation, found = keeper.GetDelegation(ctx, del, valB)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, sdk.NewRat(3), delegation.Shares)
|
require.Equal(t, sdk.NewDec(3), delegation.Shares)
|
||||||
|
|
||||||
// validator power should have been reduced to zero
|
// validator power should have been reduced to zero
|
||||||
// ergo validator should have been removed from the store
|
// ergo validator should have been removed from the store
|
||||||
|
|
|
@ -218,7 +218,7 @@ func (k Keeper) RemoveRedelegation(ctx sdk.Context, red types.Redelegation) {
|
||||||
|
|
||||||
// Perform a delegation, set/update everything necessary within the store.
|
// Perform a delegation, set/update everything necessary within the store.
|
||||||
func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt sdk.Coin,
|
func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt sdk.Coin,
|
||||||
validator types.Validator, subtractAccount bool) (newShares sdk.Rat, err sdk.Error) {
|
validator types.Validator, subtractAccount bool) (newShares sdk.Dec, err sdk.Error) {
|
||||||
|
|
||||||
// Get or create the delegator delegation
|
// Get or create the delegator delegation
|
||||||
delegation, found := k.GetDelegation(ctx, delegatorAddr, validator.Owner)
|
delegation, found := k.GetDelegation(ctx, delegatorAddr, validator.Owner)
|
||||||
|
@ -226,7 +226,7 @@ func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt
|
||||||
delegation = types.Delegation{
|
delegation = types.Delegation{
|
||||||
DelegatorAddr: delegatorAddr,
|
DelegatorAddr: delegatorAddr,
|
||||||
ValidatorAddr: validator.Owner,
|
ValidatorAddr: validator.Owner,
|
||||||
Shares: sdk.ZeroRat(),
|
Shares: sdk.ZeroDec(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +254,7 @@ func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt
|
||||||
|
|
||||||
// unbond the the delegation return
|
// unbond the the delegation return
|
||||||
func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress,
|
func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress,
|
||||||
shares sdk.Rat) (amount sdk.Rat, err sdk.Error) {
|
shares sdk.Dec) (amount sdk.Dec, err sdk.Error) {
|
||||||
|
|
||||||
// check if delegation has any shares in it unbond
|
// check if delegation has any shares in it unbond
|
||||||
delegation, found := k.GetDelegation(ctx, delegatorAddr, validatorAddr)
|
delegation, found := k.GetDelegation(ctx, delegatorAddr, validatorAddr)
|
||||||
|
@ -312,7 +312,7 @@ func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddr
|
||||||
//______________________________________________________________________________________________________
|
//______________________________________________________________________________________________________
|
||||||
|
|
||||||
// complete unbonding an unbonding record
|
// complete unbonding an unbonding record
|
||||||
func (k Keeper) BeginUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Rat) sdk.Error {
|
func (k Keeper) BeginUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Dec) sdk.Error {
|
||||||
|
|
||||||
// TODO quick fix, instead we should use an index, see https://github.com/cosmos/cosmos-sdk/issues/1402
|
// TODO quick fix, instead we should use an index, see https://github.com/cosmos/cosmos-sdk/issues/1402
|
||||||
_, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr)
|
_, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr)
|
||||||
|
@ -365,7 +365,7 @@ func (k Keeper) CompleteUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr
|
||||||
|
|
||||||
// complete unbonding an unbonding record
|
// complete unbonding an unbonding record
|
||||||
func (k Keeper) BeginRedelegation(ctx sdk.Context, delegatorAddr, validatorSrcAddr,
|
func (k Keeper) BeginRedelegation(ctx sdk.Context, delegatorAddr, validatorSrcAddr,
|
||||||
validatorDstAddr sdk.AccAddress, sharesAmount sdk.Rat) sdk.Error {
|
validatorDstAddr sdk.AccAddress, sharesAmount sdk.Dec) sdk.Error {
|
||||||
|
|
||||||
// check if this is a transitive redelegation
|
// check if this is a transitive redelegation
|
||||||
if k.HasReceivingRedelegation(ctx, delegatorAddr, validatorSrcAddr) {
|
if k.HasReceivingRedelegation(ctx, delegatorAddr, validatorSrcAddr) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ func TestDelegation(t *testing.T) {
|
||||||
bond1to1 := types.Delegation{
|
bond1to1 := types.Delegation{
|
||||||
DelegatorAddr: addrDels[0],
|
DelegatorAddr: addrDels[0],
|
||||||
ValidatorAddr: addrVals[0],
|
ValidatorAddr: addrVals[0],
|
||||||
Shares: sdk.NewRat(9),
|
Shares: sdk.NewDec(9),
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the empty keeper first
|
// check the empty keeper first
|
||||||
|
@ -46,18 +46,18 @@ func TestDelegation(t *testing.T) {
|
||||||
require.True(t, bond1to1.Equal(resBond))
|
require.True(t, bond1to1.Equal(resBond))
|
||||||
|
|
||||||
// modify a records, save, and retrieve
|
// modify a records, save, and retrieve
|
||||||
bond1to1.Shares = sdk.NewRat(99)
|
bond1to1.Shares = sdk.NewDec(99)
|
||||||
keeper.SetDelegation(ctx, bond1to1)
|
keeper.SetDelegation(ctx, bond1to1)
|
||||||
resBond, found = keeper.GetDelegation(ctx, addrDels[0], addrVals[0])
|
resBond, found = keeper.GetDelegation(ctx, addrDels[0], addrVals[0])
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.True(t, bond1to1.Equal(resBond))
|
require.True(t, bond1to1.Equal(resBond))
|
||||||
|
|
||||||
// add some more records
|
// add some more records
|
||||||
bond1to2 := types.Delegation{addrDels[0], addrVals[1], sdk.NewRat(9), 0}
|
bond1to2 := types.Delegation{addrDels[0], addrVals[1], sdk.NewDec(9), 0}
|
||||||
bond1to3 := types.Delegation{addrDels[0], addrVals[2], sdk.NewRat(9), 1}
|
bond1to3 := types.Delegation{addrDels[0], addrVals[2], sdk.NewDec(9), 1}
|
||||||
bond2to1 := types.Delegation{addrDels[1], addrVals[0], sdk.NewRat(9), 2}
|
bond2to1 := types.Delegation{addrDels[1], addrVals[0], sdk.NewDec(9), 2}
|
||||||
bond2to2 := types.Delegation{addrDels[1], addrVals[1], sdk.NewRat(9), 3}
|
bond2to2 := types.Delegation{addrDels[1], addrVals[1], sdk.NewDec(9), 3}
|
||||||
bond2to3 := types.Delegation{addrDels[1], addrVals[2], sdk.NewRat(9), 4}
|
bond2to3 := types.Delegation{addrDels[1], addrVals[2], sdk.NewDec(9), 4}
|
||||||
keeper.SetDelegation(ctx, bond1to2)
|
keeper.SetDelegation(ctx, bond1to2)
|
||||||
keeper.SetDelegation(ctx, bond1to3)
|
keeper.SetDelegation(ctx, bond1to3)
|
||||||
keeper.SetDelegation(ctx, bond2to1)
|
keeper.SetDelegation(ctx, bond2to1)
|
||||||
|
@ -142,7 +142,7 @@ func TestUnbondingDelegation(t *testing.T) {
|
||||||
func TestUnbondDelegation(t *testing.T) {
|
func TestUnbondDelegation(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 0)
|
ctx, _, keeper := CreateTestInput(t, false, 0)
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
pool.LooseTokens = sdk.NewRat(10)
|
pool.LooseTokens = sdk.NewDec(10)
|
||||||
|
|
||||||
//create a validator and a delegator to that validator
|
//create a validator and a delegator to that validator
|
||||||
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
|
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
|
||||||
|
@ -163,8 +163,8 @@ func TestUnbondDelegation(t *testing.T) {
|
||||||
keeper.SetDelegation(ctx, delegation)
|
keeper.SetDelegation(ctx, delegation)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var amount sdk.Rat
|
var amount sdk.Dec
|
||||||
amount, err = keeper.unbond(ctx, addrDels[0], addrVals[0], sdk.NewRat(6))
|
amount, err = keeper.unbond(ctx, addrDels[0], addrVals[0], sdk.NewDec(6))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, int64(6), amount.RoundInt64()) // shares to be added to an unbonding delegation / redelegation
|
require.Equal(t, int64(6), amount.RoundInt64()) // shares to be added to an unbonding delegation / redelegation
|
||||||
|
|
||||||
|
@ -190,8 +190,8 @@ func TestGetRedelegationsFromValidator(t *testing.T) {
|
||||||
ValidatorDstAddr: addrVals[1],
|
ValidatorDstAddr: addrVals[1],
|
||||||
CreationHeight: 0,
|
CreationHeight: 0,
|
||||||
MinTime: time.Unix(0, 0),
|
MinTime: time.Unix(0, 0),
|
||||||
SharesSrc: sdk.NewRat(5),
|
SharesSrc: sdk.NewDec(5),
|
||||||
SharesDst: sdk.NewRat(5),
|
SharesDst: sdk.NewDec(5),
|
||||||
}
|
}
|
||||||
|
|
||||||
// set and retrieve a record
|
// set and retrieve a record
|
||||||
|
@ -220,8 +220,8 @@ func TestRedelegation(t *testing.T) {
|
||||||
ValidatorDstAddr: addrVals[1],
|
ValidatorDstAddr: addrVals[1],
|
||||||
CreationHeight: 0,
|
CreationHeight: 0,
|
||||||
MinTime: time.Unix(0, 0),
|
MinTime: time.Unix(0, 0),
|
||||||
SharesSrc: sdk.NewRat(5),
|
SharesSrc: sdk.NewDec(5),
|
||||||
SharesDst: sdk.NewRat(5),
|
SharesDst: sdk.NewDec(5),
|
||||||
}
|
}
|
||||||
|
|
||||||
// test shouldn't have and redelegations
|
// test shouldn't have and redelegations
|
||||||
|
@ -242,8 +242,8 @@ func TestRedelegation(t *testing.T) {
|
||||||
require.True(t, has)
|
require.True(t, has)
|
||||||
|
|
||||||
// modify a records, save, and retrieve
|
// modify a records, save, and retrieve
|
||||||
rd.SharesSrc = sdk.NewRat(21)
|
rd.SharesSrc = sdk.NewDec(21)
|
||||||
rd.SharesDst = sdk.NewRat(21)
|
rd.SharesDst = sdk.NewDec(21)
|
||||||
keeper.SetRedelegation(ctx, rd)
|
keeper.SetRedelegation(ctx, rd)
|
||||||
|
|
||||||
resBond, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
resBond, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||||
|
|
|
@ -33,7 +33,7 @@ func TestPool(t *testing.T) {
|
||||||
require.True(t, expPool.Equal(resPool))
|
require.True(t, expPool.Equal(resPool))
|
||||||
|
|
||||||
//modify a params, save, and retrieve
|
//modify a params, save, and retrieve
|
||||||
expPool.BondedTokens = sdk.NewRat(777)
|
expPool.BondedTokens = sdk.NewDec(777)
|
||||||
keeper.SetPool(ctx, expPool)
|
keeper.SetPool(ctx, expPool)
|
||||||
resPool = keeper.GetPool(ctx)
|
resPool = keeper.GetPool(ctx)
|
||||||
require.True(t, expPool.Equal(resPool))
|
require.True(t, expPool.Equal(resPool))
|
||||||
|
|
|
@ -69,7 +69,7 @@ func (k Keeper) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) sdk.Val
|
||||||
}
|
}
|
||||||
|
|
||||||
// total power from the bond
|
// total power from the bond
|
||||||
func (k Keeper) TotalPower(ctx sdk.Context) sdk.Rat {
|
func (k Keeper) TotalPower(ctx sdk.Context) sdk.Dec {
|
||||||
pool := k.GetPool(ctx)
|
pool := k.GetPool(ctx)
|
||||||
return pool.BondedTokens
|
return pool.BondedTokens
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,15 +20,15 @@ import (
|
||||||
// CONTRACT:
|
// CONTRACT:
|
||||||
// Infraction committed at the current height or at a past height,
|
// Infraction committed at the current height or at a past height,
|
||||||
// not at a height in the future
|
// not at a height in the future
|
||||||
func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, power int64, slashFactor sdk.Rat) {
|
func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, power int64, slashFactor sdk.Dec) {
|
||||||
logger := ctx.Logger().With("module", "x/stake")
|
logger := ctx.Logger().With("module", "x/stake")
|
||||||
|
|
||||||
if slashFactor.LT(sdk.ZeroRat()) {
|
if slashFactor.LT(sdk.ZeroDec()) {
|
||||||
panic(fmt.Errorf("attempted to slash with a negative slashFactor: %v", slashFactor))
|
panic(fmt.Errorf("attempted to slash with a negative slashFactor: %v", slashFactor))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Amount of slashing = slash slashFactor * power at time of infraction
|
// Amount of slashing = slash slashFactor * power at time of infraction
|
||||||
slashAmount := sdk.NewRat(power).Mul(slashFactor)
|
slashAmount := sdk.NewDec(power).Mul(slashFactor)
|
||||||
// ref https://github.com/cosmos/cosmos-sdk/issues/1348
|
// ref https://github.com/cosmos/cosmos-sdk/issues/1348
|
||||||
// ref https://github.com/cosmos/cosmos-sdk/issues/1471
|
// ref https://github.com/cosmos/cosmos-sdk/issues/1471
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot decrease balance below zero
|
// Cannot decrease balance below zero
|
||||||
tokensToBurn := sdk.MinRat(remainingSlashAmount, validator.Tokens)
|
tokensToBurn := sdk.MinDec(remainingSlashAmount, validator.Tokens)
|
||||||
|
|
||||||
// Get the current pool
|
// Get the current pool
|
||||||
pool := k.GetPool(ctx)
|
pool := k.GetPool(ctx)
|
||||||
|
@ -150,23 +150,23 @@ func (k Keeper) setRevoked(ctx sdk.Context, pubkey crypto.PubKey, revoked bool)
|
||||||
// (the amount actually slashed may be less if there's
|
// (the amount actually slashed may be less if there's
|
||||||
// insufficient stake remaining)
|
// insufficient stake remaining)
|
||||||
func (k Keeper) slashUnbondingDelegation(ctx sdk.Context, unbondingDelegation types.UnbondingDelegation,
|
func (k Keeper) slashUnbondingDelegation(ctx sdk.Context, unbondingDelegation types.UnbondingDelegation,
|
||||||
infractionHeight int64, slashFactor sdk.Rat) (slashAmount sdk.Rat) {
|
infractionHeight int64, slashFactor sdk.Dec) (slashAmount sdk.Dec) {
|
||||||
|
|
||||||
now := ctx.BlockHeader().Time
|
now := ctx.BlockHeader().Time
|
||||||
|
|
||||||
// If unbonding started before this height, stake didn't contribute to infraction
|
// If unbonding started before this height, stake didn't contribute to infraction
|
||||||
if unbondingDelegation.CreationHeight < infractionHeight {
|
if unbondingDelegation.CreationHeight < infractionHeight {
|
||||||
return sdk.ZeroRat()
|
return sdk.ZeroDec()
|
||||||
}
|
}
|
||||||
|
|
||||||
if unbondingDelegation.MinTime.Before(now) {
|
if unbondingDelegation.MinTime.Before(now) {
|
||||||
// Unbonding delegation no longer eligible for slashing, skip it
|
// Unbonding delegation no longer eligible for slashing, skip it
|
||||||
// TODO Settle and delete it automatically?
|
// TODO Settle and delete it automatically?
|
||||||
return sdk.ZeroRat()
|
return sdk.ZeroDec()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate slash amount proportional to stake contributing to infraction
|
// Calculate slash amount proportional to stake contributing to infraction
|
||||||
slashAmount = sdk.NewRatFromInt(unbondingDelegation.InitialBalance.Amount, sdk.OneInt()).Mul(slashFactor)
|
slashAmount = sdk.NewDecFromInt(unbondingDelegation.InitialBalance.Amount).Mul(slashFactor)
|
||||||
|
|
||||||
// Don't slash more tokens than held
|
// Don't slash more tokens than held
|
||||||
// Possible since the unbonding delegation may already
|
// Possible since the unbonding delegation may already
|
||||||
|
@ -194,23 +194,23 @@ func (k Keeper) slashUnbondingDelegation(ctx sdk.Context, unbondingDelegation ty
|
||||||
// (the amount actually slashed may be less if there's
|
// (the amount actually slashed may be less if there's
|
||||||
// insufficient stake remaining)
|
// insufficient stake remaining)
|
||||||
func (k Keeper) slashRedelegation(ctx sdk.Context, validator types.Validator, redelegation types.Redelegation,
|
func (k Keeper) slashRedelegation(ctx sdk.Context, validator types.Validator, redelegation types.Redelegation,
|
||||||
infractionHeight int64, slashFactor sdk.Rat) (slashAmount sdk.Rat) {
|
infractionHeight int64, slashFactor sdk.Dec) (slashAmount sdk.Dec) {
|
||||||
|
|
||||||
now := ctx.BlockHeader().Time
|
now := ctx.BlockHeader().Time
|
||||||
|
|
||||||
// If redelegation started before this height, stake didn't contribute to infraction
|
// If redelegation started before this height, stake didn't contribute to infraction
|
||||||
if redelegation.CreationHeight < infractionHeight {
|
if redelegation.CreationHeight < infractionHeight {
|
||||||
return sdk.ZeroRat()
|
return sdk.ZeroDec()
|
||||||
}
|
}
|
||||||
|
|
||||||
if redelegation.MinTime.Before(now) {
|
if redelegation.MinTime.Before(now) {
|
||||||
// Redelegation no longer eligible for slashing, skip it
|
// Redelegation no longer eligible for slashing, skip it
|
||||||
// TODO Delete it automatically?
|
// TODO Delete it automatically?
|
||||||
return sdk.ZeroRat()
|
return sdk.ZeroDec()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate slash amount proportional to stake contributing to infraction
|
// Calculate slash amount proportional to stake contributing to infraction
|
||||||
slashAmount = sdk.NewRatFromInt(redelegation.InitialBalance.Amount, sdk.OneInt()).Mul(slashFactor)
|
slashAmount = sdk.NewDecFromInt(redelegation.InitialBalance.Amount).Mul(slashFactor)
|
||||||
|
|
||||||
// Don't slash more tokens than held
|
// Don't slash more tokens than held
|
||||||
// Possible since the redelegation may already
|
// Possible since the redelegation may already
|
||||||
|
|
|
@ -19,7 +19,7 @@ func setupHelper(t *testing.T, amt int64) (sdk.Context, Keeper, types.Params) {
|
||||||
params := keeper.GetParams(ctx)
|
params := keeper.GetParams(ctx)
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
numVals := 3
|
numVals := 3
|
||||||
pool.LooseTokens = sdk.NewRat(amt * int64(numVals))
|
pool.LooseTokens = sdk.NewDec(amt * int64(numVals))
|
||||||
|
|
||||||
// add numVals validators
|
// add numVals validators
|
||||||
for i := 0; i < numVals; i++ {
|
for i := 0; i < numVals; i++ {
|
||||||
|
@ -63,7 +63,7 @@ func TestRevocation(t *testing.T) {
|
||||||
// tests slashUnbondingDelegation
|
// tests slashUnbondingDelegation
|
||||||
func TestSlashUnbondingDelegation(t *testing.T) {
|
func TestSlashUnbondingDelegation(t *testing.T) {
|
||||||
ctx, keeper, params := setupHelper(t, 10)
|
ctx, keeper, params := setupHelper(t, 10)
|
||||||
fraction := sdk.NewRat(1, 2)
|
fraction := sdk.NewDecWithPrec(5, 1)
|
||||||
|
|
||||||
// set an unbonding delegation
|
// set an unbonding delegation
|
||||||
ubd := types.UnbondingDelegation{
|
ubd := types.UnbondingDelegation{
|
||||||
|
@ -106,7 +106,7 @@ func TestSlashUnbondingDelegation(t *testing.T) {
|
||||||
// tests slashRedelegation
|
// tests slashRedelegation
|
||||||
func TestSlashRedelegation(t *testing.T) {
|
func TestSlashRedelegation(t *testing.T) {
|
||||||
ctx, keeper, params := setupHelper(t, 10)
|
ctx, keeper, params := setupHelper(t, 10)
|
||||||
fraction := sdk.NewRat(1, 2)
|
fraction := sdk.NewDecWithPrec(5, 1)
|
||||||
|
|
||||||
// set a redelegation
|
// set a redelegation
|
||||||
rd := types.Redelegation{
|
rd := types.Redelegation{
|
||||||
|
@ -116,8 +116,8 @@ func TestSlashRedelegation(t *testing.T) {
|
||||||
CreationHeight: 0,
|
CreationHeight: 0,
|
||||||
// expiration timestamp (beyond which the redelegation shouldn't be slashed)
|
// expiration timestamp (beyond which the redelegation shouldn't be slashed)
|
||||||
MinTime: time.Unix(0, 0),
|
MinTime: time.Unix(0, 0),
|
||||||
SharesSrc: sdk.NewRat(10),
|
SharesSrc: sdk.NewDec(10),
|
||||||
SharesDst: sdk.NewRat(10),
|
SharesDst: sdk.NewDec(10),
|
||||||
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 10),
|
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 10),
|
||||||
Balance: sdk.NewInt64Coin(params.BondDenom, 10),
|
Balance: sdk.NewInt64Coin(params.BondDenom, 10),
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ func TestSlashRedelegation(t *testing.T) {
|
||||||
del := types.Delegation{
|
del := types.Delegation{
|
||||||
DelegatorAddr: addrDels[0],
|
DelegatorAddr: addrDels[0],
|
||||||
ValidatorAddr: addrVals[1],
|
ValidatorAddr: addrVals[1],
|
||||||
Shares: sdk.NewRat(10),
|
Shares: sdk.NewDec(10),
|
||||||
}
|
}
|
||||||
keeper.SetDelegation(ctx, del)
|
keeper.SetDelegation(ctx, del)
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ func TestSlashRedelegation(t *testing.T) {
|
||||||
func TestSlashAtFutureHeight(t *testing.T) {
|
func TestSlashAtFutureHeight(t *testing.T) {
|
||||||
ctx, keeper, _ := setupHelper(t, 10)
|
ctx, keeper, _ := setupHelper(t, 10)
|
||||||
pk := PKs[0]
|
pk := PKs[0]
|
||||||
fraction := sdk.NewRat(1, 2)
|
fraction := sdk.NewDecWithPrec(5, 1)
|
||||||
require.Panics(t, func() { keeper.Slash(ctx, pk, 1, 10, fraction) })
|
require.Panics(t, func() { keeper.Slash(ctx, pk, 1, 10, fraction) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ func TestSlashAtFutureHeight(t *testing.T) {
|
||||||
func TestSlashAtCurrentHeight(t *testing.T) {
|
func TestSlashAtCurrentHeight(t *testing.T) {
|
||||||
ctx, keeper, _ := setupHelper(t, 10)
|
ctx, keeper, _ := setupHelper(t, 10)
|
||||||
pk := PKs[0]
|
pk := PKs[0]
|
||||||
fraction := sdk.NewRat(1, 2)
|
fraction := sdk.NewDecWithPrec(5, 1)
|
||||||
|
|
||||||
oldPool := keeper.GetPool(ctx)
|
oldPool := keeper.GetPool(ctx)
|
||||||
validator, found := keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found := keeper.GetValidatorByPubKey(ctx, pk)
|
||||||
|
@ -193,16 +193,16 @@ func TestSlashAtCurrentHeight(t *testing.T) {
|
||||||
newPool := keeper.GetPool(ctx)
|
newPool := keeper.GetPool(ctx)
|
||||||
|
|
||||||
// power decreased
|
// power decreased
|
||||||
require.Equal(t, sdk.NewRat(5), validator.GetPower())
|
require.Equal(t, sdk.NewDec(5), validator.GetPower())
|
||||||
// pool bonded shares decreased
|
// pool bonded shares decreased
|
||||||
require.Equal(t, sdk.NewRat(5).RoundInt64(), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
require.Equal(t, sdk.NewDec(5).RoundInt64(), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
||||||
}
|
}
|
||||||
|
|
||||||
// tests Slash at a previous height with an unbonding delegation
|
// tests Slash at a previous height with an unbonding delegation
|
||||||
func TestSlashWithUnbondingDelegation(t *testing.T) {
|
func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
ctx, keeper, params := setupHelper(t, 10)
|
ctx, keeper, params := setupHelper(t, 10)
|
||||||
pk := PKs[0]
|
pk := PKs[0]
|
||||||
fraction := sdk.NewRat(1, 2)
|
fraction := sdk.NewDecWithPrec(5, 1)
|
||||||
|
|
||||||
// set an unbonding delegation
|
// set an unbonding delegation
|
||||||
ubd := types.UnbondingDelegation{
|
ubd := types.UnbondingDelegation{
|
||||||
|
@ -239,7 +239,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
// was still bonded at the time of discovery and was slashed by half, 4 stake
|
// was still bonded at the time of discovery and was slashed by half, 4 stake
|
||||||
// bonded at the time of discovery hadn't been bonded at the time of infraction
|
// bonded at the time of discovery hadn't been bonded at the time of infraction
|
||||||
// and wasn't slashed
|
// and wasn't slashed
|
||||||
require.Equal(t, sdk.NewRat(7), validator.GetPower())
|
require.Equal(t, sdk.NewDec(7), validator.GetPower())
|
||||||
|
|
||||||
// slash validator again
|
// slash validator again
|
||||||
ctx = ctx.WithBlockHeight(13)
|
ctx = ctx.WithBlockHeight(13)
|
||||||
|
@ -256,7 +256,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
// power decreased by 3 again
|
// power decreased by 3 again
|
||||||
require.Equal(t, sdk.NewRat(4), validator.GetPower())
|
require.Equal(t, sdk.NewDec(4), validator.GetPower())
|
||||||
|
|
||||||
// slash validator again
|
// slash validator again
|
||||||
// all originally bonded stake has been slashed, so this will have no effect
|
// all originally bonded stake has been slashed, so this will have no effect
|
||||||
|
@ -276,7 +276,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
// power decreased by 3 again
|
// power decreased by 3 again
|
||||||
require.Equal(t, sdk.NewRat(1), validator.GetPower())
|
require.Equal(t, sdk.NewDec(1), validator.GetPower())
|
||||||
|
|
||||||
// slash validator again
|
// slash validator again
|
||||||
// all originally bonded stake has been slashed, so this will have no effect
|
// all originally bonded stake has been slashed, so this will have no effect
|
||||||
|
@ -303,7 +303,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
func TestSlashWithRedelegation(t *testing.T) {
|
func TestSlashWithRedelegation(t *testing.T) {
|
||||||
ctx, keeper, params := setupHelper(t, 10)
|
ctx, keeper, params := setupHelper(t, 10)
|
||||||
pk := PKs[0]
|
pk := PKs[0]
|
||||||
fraction := sdk.NewRat(1, 2)
|
fraction := sdk.NewDecWithPrec(5, 1)
|
||||||
|
|
||||||
// set a redelegation
|
// set a redelegation
|
||||||
rd := types.Redelegation{
|
rd := types.Redelegation{
|
||||||
|
@ -312,8 +312,8 @@ func TestSlashWithRedelegation(t *testing.T) {
|
||||||
ValidatorDstAddr: addrVals[1],
|
ValidatorDstAddr: addrVals[1],
|
||||||
CreationHeight: 11,
|
CreationHeight: 11,
|
||||||
MinTime: time.Unix(0, 0),
|
MinTime: time.Unix(0, 0),
|
||||||
SharesSrc: sdk.NewRat(6),
|
SharesSrc: sdk.NewDec(6),
|
||||||
SharesDst: sdk.NewRat(6),
|
SharesDst: sdk.NewDec(6),
|
||||||
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6),
|
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6),
|
||||||
Balance: sdk.NewInt64Coin(params.BondDenom, 6),
|
Balance: sdk.NewInt64Coin(params.BondDenom, 6),
|
||||||
}
|
}
|
||||||
|
@ -323,13 +323,13 @@ func TestSlashWithRedelegation(t *testing.T) {
|
||||||
del := types.Delegation{
|
del := types.Delegation{
|
||||||
DelegatorAddr: addrDels[0],
|
DelegatorAddr: addrDels[0],
|
||||||
ValidatorAddr: addrVals[1],
|
ValidatorAddr: addrVals[1],
|
||||||
Shares: sdk.NewRat(6),
|
Shares: sdk.NewDec(6),
|
||||||
}
|
}
|
||||||
keeper.SetDelegation(ctx, del)
|
keeper.SetDelegation(ctx, del)
|
||||||
|
|
||||||
// update bonded tokens
|
// update bonded tokens
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
pool.BondedTokens = pool.BondedTokens.Add(sdk.NewRat(6))
|
pool.BondedTokens = pool.BondedTokens.Add(sdk.NewDec(6))
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
|
|
||||||
// slash validator
|
// slash validator
|
||||||
|
@ -355,13 +355,13 @@ func TestSlashWithRedelegation(t *testing.T) {
|
||||||
// was still bonded at the time of discovery and was slashed by half, 4 stake
|
// was still bonded at the time of discovery and was slashed by half, 4 stake
|
||||||
// bonded at the time of discovery hadn't been bonded at the time of infraction
|
// bonded at the time of discovery hadn't been bonded at the time of infraction
|
||||||
// and wasn't slashed
|
// and wasn't slashed
|
||||||
require.Equal(t, sdk.NewRat(8), validator.GetPower())
|
require.Equal(t, sdk.NewDec(8), validator.GetPower())
|
||||||
|
|
||||||
// slash the validator again
|
// slash the validator again
|
||||||
ctx = ctx.WithBlockHeight(12)
|
ctx = ctx.WithBlockHeight(12)
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.NotPanics(t, func() { keeper.Slash(ctx, pk, 10, 10, sdk.OneRat()) })
|
require.NotPanics(t, func() { keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) })
|
||||||
|
|
||||||
// read updating redelegation
|
// read updating redelegation
|
||||||
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||||
|
@ -376,13 +376,13 @@ func TestSlashWithRedelegation(t *testing.T) {
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
// power decreased by 4
|
// power decreased by 4
|
||||||
require.Equal(t, sdk.NewRat(4), validator.GetPower())
|
require.Equal(t, sdk.NewDec(4), validator.GetPower())
|
||||||
|
|
||||||
// slash the validator again, by 100%
|
// slash the validator again, by 100%
|
||||||
ctx = ctx.WithBlockHeight(12)
|
ctx = ctx.WithBlockHeight(12)
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
keeper.Slash(ctx, pk, 10, 10, sdk.OneRat())
|
keeper.Slash(ctx, pk, 10, 10, sdk.OneDec())
|
||||||
|
|
||||||
// read updating redelegation
|
// read updating redelegation
|
||||||
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||||
|
@ -404,7 +404,7 @@ func TestSlashWithRedelegation(t *testing.T) {
|
||||||
// validator no longer in the store
|
// validator no longer in the store
|
||||||
_, found = keeper.GetValidatorByPubKey(ctx, pk)
|
_, found = keeper.GetValidatorByPubKey(ctx, pk)
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
keeper.Slash(ctx, pk, 10, 10, sdk.OneRat())
|
keeper.Slash(ctx, pk, 10, 10, sdk.OneDec())
|
||||||
|
|
||||||
// read updating redelegation
|
// read updating redelegation
|
||||||
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||||
|
@ -424,7 +424,7 @@ func TestSlashWithRedelegation(t *testing.T) {
|
||||||
// tests Slash at a previous height with both an unbonding delegation and a redelegation
|
// tests Slash at a previous height with both an unbonding delegation and a redelegation
|
||||||
func TestSlashBoth(t *testing.T) {
|
func TestSlashBoth(t *testing.T) {
|
||||||
ctx, keeper, params := setupHelper(t, 10)
|
ctx, keeper, params := setupHelper(t, 10)
|
||||||
fraction := sdk.NewRat(1, 2)
|
fraction := sdk.NewDecWithPrec(5, 1)
|
||||||
|
|
||||||
// set a redelegation
|
// set a redelegation
|
||||||
rdA := types.Redelegation{
|
rdA := types.Redelegation{
|
||||||
|
@ -434,8 +434,8 @@ func TestSlashBoth(t *testing.T) {
|
||||||
CreationHeight: 11,
|
CreationHeight: 11,
|
||||||
// expiration timestamp (beyond which the redelegation shouldn't be slashed)
|
// expiration timestamp (beyond which the redelegation shouldn't be slashed)
|
||||||
MinTime: time.Unix(0, 0),
|
MinTime: time.Unix(0, 0),
|
||||||
SharesSrc: sdk.NewRat(6),
|
SharesSrc: sdk.NewDec(6),
|
||||||
SharesDst: sdk.NewRat(6),
|
SharesDst: sdk.NewDec(6),
|
||||||
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6),
|
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6),
|
||||||
Balance: sdk.NewInt64Coin(params.BondDenom, 6),
|
Balance: sdk.NewInt64Coin(params.BondDenom, 6),
|
||||||
}
|
}
|
||||||
|
@ -445,7 +445,7 @@ func TestSlashBoth(t *testing.T) {
|
||||||
delA := types.Delegation{
|
delA := types.Delegation{
|
||||||
DelegatorAddr: addrDels[0],
|
DelegatorAddr: addrDels[0],
|
||||||
ValidatorAddr: addrVals[1],
|
ValidatorAddr: addrVals[1],
|
||||||
Shares: sdk.NewRat(6),
|
Shares: sdk.NewDec(6),
|
||||||
}
|
}
|
||||||
keeper.SetDelegation(ctx, delA)
|
keeper.SetDelegation(ctx, delA)
|
||||||
|
|
||||||
|
@ -483,5 +483,5 @@ func TestSlashBoth(t *testing.T) {
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, PKs[0])
|
validator, found = keeper.GetValidatorByPubKey(ctx, PKs[0])
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
// power not decreased, all stake was bonded since
|
// power not decreased, all stake was bonded since
|
||||||
require.Equal(t, sdk.NewRat(10), validator.GetPower())
|
require.Equal(t, sdk.NewDec(10), validator.GetPower())
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,10 +77,10 @@ func MakeTestCodec() *wire.Codec {
|
||||||
// default params without inflation
|
// default params without inflation
|
||||||
func ParamsNoInflation() types.Params {
|
func ParamsNoInflation() types.Params {
|
||||||
return types.Params{
|
return types.Params{
|
||||||
InflationRateChange: sdk.ZeroRat(),
|
InflationRateChange: sdk.ZeroDec(),
|
||||||
InflationMax: sdk.ZeroRat(),
|
InflationMax: sdk.ZeroDec(),
|
||||||
InflationMin: sdk.ZeroRat(),
|
InflationMin: sdk.ZeroDec(),
|
||||||
GoalBonded: sdk.NewRat(67, 100),
|
GoalBonded: sdk.NewDecWithPrec(67, 2),
|
||||||
MaxValidators: 100,
|
MaxValidators: 100,
|
||||||
BondDenom: "steak",
|
BondDenom: "steak",
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context
|
||||||
{keeper.GetParams(ctx).BondDenom, sdk.NewInt(initCoins)},
|
{keeper.GetParams(ctx).BondDenom, sdk.NewInt(initCoins)},
|
||||||
})
|
})
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewRat(initCoins))
|
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewDec(initCoins))
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ func TestSetValidator(t *testing.T) {
|
||||||
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
|
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
|
||||||
validator, pool, _ = validator.AddTokensFromDel(pool, 10)
|
validator, pool, _ = validator.AddTokensFromDel(pool, 10)
|
||||||
require.Equal(t, sdk.Unbonded, validator.Status)
|
require.Equal(t, sdk.Unbonded, validator.Status)
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
keeper.UpdateValidator(ctx, validator)
|
keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
@ -29,8 +29,8 @@ func TestSetValidator(t *testing.T) {
|
||||||
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, sdk.Bonded, validator.Status)
|
require.Equal(t, sdk.Bonded, validator.Status)
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
|
||||||
|
|
||||||
// Check each store for being saved
|
// Check each store for being saved
|
||||||
resVal, found := keeper.GetValidator(ctx, addrVals[0])
|
resVal, found := keeper.GetValidator(ctx, addrVals[0])
|
||||||
|
@ -56,8 +56,8 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) {
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
|
|
||||||
// create a random pool
|
// create a random pool
|
||||||
pool.LooseTokens = sdk.NewRat(10000)
|
pool.LooseTokens = sdk.NewDec(10000)
|
||||||
pool.BondedTokens = sdk.NewRat(1234)
|
pool.BondedTokens = sdk.NewDec(1234)
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
|
|
||||||
// add a validator
|
// add a validator
|
||||||
|
@ -76,7 +76,7 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) {
|
||||||
require.True(t, keeper.validatorByPowerIndexExists(ctx, power))
|
require.True(t, keeper.validatorByPowerIndexExists(ctx, power))
|
||||||
|
|
||||||
// burn half the delegator shares
|
// burn half the delegator shares
|
||||||
validator, pool, burned := validator.RemoveDelShares(pool, delSharesCreated.Quo(sdk.NewRat(2)))
|
validator, pool, burned := validator.RemoveDelShares(pool, delSharesCreated.Quo(sdk.NewDec(2)))
|
||||||
require.Equal(t, int64(50), burned.RoundInt64())
|
require.Equal(t, int64(50), burned.RoundInt64())
|
||||||
keeper.SetPool(ctx, pool) // update the pool
|
keeper.SetPool(ctx, pool) // update the pool
|
||||||
keeper.UpdateValidator(ctx, validator) // update the validator, possibly kicking it out
|
keeper.UpdateValidator(ctx, validator) // update the validator, possibly kicking it out
|
||||||
|
@ -103,8 +103,8 @@ func TestCliffValidatorChange(t *testing.T) {
|
||||||
keeper.SetParams(ctx, params)
|
keeper.SetParams(ctx, params)
|
||||||
|
|
||||||
// create a random pool
|
// create a random pool
|
||||||
pool.LooseTokens = sdk.NewRat(10000)
|
pool.LooseTokens = sdk.NewDec(10000)
|
||||||
pool.BondedTokens = sdk.NewRat(1234)
|
pool.BondedTokens = sdk.NewDec(1234)
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
|
|
||||||
validators := make([]types.Validator, numVals)
|
validators := make([]types.Validator, numVals)
|
||||||
|
@ -161,7 +161,7 @@ func TestSlashToZeroPowerRemoved(t *testing.T) {
|
||||||
require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool)
|
require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool)
|
||||||
|
|
||||||
// slash the validator by 100%
|
// slash the validator by 100%
|
||||||
keeper.Slash(ctx, PKs[0], 0, 100, sdk.OneRat())
|
keeper.Slash(ctx, PKs[0], 0, 100, sdk.OneDec())
|
||||||
// validator should have been deleted
|
// validator should have been deleted
|
||||||
_, found := keeper.GetValidator(ctx, addrVals[0])
|
_, found := keeper.GetValidator(ctx, addrVals[0])
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
|
@ -178,13 +178,13 @@ func TestValidatorBasics(t *testing.T) {
|
||||||
for i, amt := range amts {
|
for i, amt := range amts {
|
||||||
validators[i] = types.NewValidator(addrVals[i], PKs[i], types.Description{})
|
validators[i] = types.NewValidator(addrVals[i], PKs[i], types.Description{})
|
||||||
validators[i].Status = sdk.Unbonded
|
validators[i].Status = sdk.Unbonded
|
||||||
validators[i].Tokens = sdk.ZeroRat()
|
validators[i].Tokens = sdk.ZeroDec()
|
||||||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
}
|
}
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(9), validators[0].Tokens))
|
assert.True(sdk.DecEq(t, sdk.NewDec(9), validators[0].Tokens))
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(8), validators[1].Tokens))
|
assert.True(sdk.DecEq(t, sdk.NewDec(8), validators[1].Tokens))
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(7), validators[2].Tokens))
|
assert.True(sdk.DecEq(t, sdk.NewDec(7), validators[2].Tokens))
|
||||||
|
|
||||||
// check the empty keeper first
|
// check the empty keeper first
|
||||||
_, found := keeper.GetValidator(ctx, addrVals[0])
|
_, found := keeper.GetValidator(ctx, addrVals[0])
|
||||||
|
@ -193,7 +193,7 @@ func TestValidatorBasics(t *testing.T) {
|
||||||
assert.Zero(t, len(resVals))
|
assert.Zero(t, len(resVals))
|
||||||
|
|
||||||
pool = keeper.GetPool(ctx)
|
pool = keeper.GetPool(ctx)
|
||||||
assert.True(sdk.RatEq(t, sdk.ZeroRat(), pool.BondedTokens))
|
assert.True(sdk.DecEq(t, sdk.ZeroDec(), pool.BondedTokens))
|
||||||
|
|
||||||
// set and retrieve a record
|
// set and retrieve a record
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
|
@ -205,15 +205,15 @@ func TestValidatorBasics(t *testing.T) {
|
||||||
require.Equal(t, 1, len(resVals))
|
require.Equal(t, 1, len(resVals))
|
||||||
assert.True(ValEq(t, validators[0], resVals[0]))
|
assert.True(ValEq(t, validators[0], resVals[0]))
|
||||||
assert.Equal(t, sdk.Bonded, validators[0].Status)
|
assert.Equal(t, sdk.Bonded, validators[0].Status)
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(9), validators[0].BondedTokens()))
|
assert.True(sdk.DecEq(t, sdk.NewDec(9), validators[0].BondedTokens()))
|
||||||
|
|
||||||
pool = keeper.GetPool(ctx)
|
pool = keeper.GetPool(ctx)
|
||||||
assert.True(sdk.RatEq(t, pool.BondedTokens, validators[0].BondedTokens()))
|
assert.True(sdk.DecEq(t, pool.BondedTokens, validators[0].BondedTokens()))
|
||||||
|
|
||||||
// modify a records, save, and retrieve
|
// modify a records, save, and retrieve
|
||||||
validators[0].Status = sdk.Bonded
|
validators[0].Status = sdk.Bonded
|
||||||
validators[0].Tokens = sdk.NewRat(10)
|
validators[0].Tokens = sdk.NewDec(10)
|
||||||
validators[0].DelegatorShares = sdk.NewRat(10)
|
validators[0].DelegatorShares = sdk.NewDec(10)
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
resVal, found = keeper.GetValidator(ctx, addrVals[0])
|
resVal, found = keeper.GetValidator(ctx, addrVals[0])
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
|
@ -256,19 +256,19 @@ func GetValidatorSortingUnmixed(t *testing.T) {
|
||||||
for i, amt := range amts {
|
for i, amt := range amts {
|
||||||
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
||||||
validators[i].Status = sdk.Bonded
|
validators[i].Status = sdk.Bonded
|
||||||
validators[i].Tokens = sdk.NewRat(amt)
|
validators[i].Tokens = sdk.NewDec(amt)
|
||||||
validators[i].DelegatorShares = sdk.NewRat(amt)
|
validators[i].DelegatorShares = sdk.NewDec(amt)
|
||||||
keeper.UpdateValidator(ctx, validators[i])
|
keeper.UpdateValidator(ctx, validators[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
// first make sure everything made it in to the gotValidator group
|
// first make sure everything made it in to the gotValidator group
|
||||||
resValidators := keeper.GetValidatorsByPower(ctx)
|
resValidators := keeper.GetValidatorsByPower(ctx)
|
||||||
assert.Equal(t, n, len(resValidators))
|
assert.Equal(t, n, len(resValidators))
|
||||||
assert.Equal(t, sdk.NewRat(400), resValidators[0].BondedTokens(), "%v", resValidators)
|
assert.Equal(t, sdk.NewDec(400), resValidators[0].BondedTokens(), "%v", resValidators)
|
||||||
assert.Equal(t, sdk.NewRat(200), resValidators[1].BondedTokens(), "%v", resValidators)
|
assert.Equal(t, sdk.NewDec(200), resValidators[1].BondedTokens(), "%v", resValidators)
|
||||||
assert.Equal(t, sdk.NewRat(100), resValidators[2].BondedTokens(), "%v", resValidators)
|
assert.Equal(t, sdk.NewDec(100), resValidators[2].BondedTokens(), "%v", resValidators)
|
||||||
assert.Equal(t, sdk.NewRat(1), resValidators[3].BondedTokens(), "%v", resValidators)
|
assert.Equal(t, sdk.NewDec(1), resValidators[3].BondedTokens(), "%v", resValidators)
|
||||||
assert.Equal(t, sdk.NewRat(0), resValidators[4].BondedTokens(), "%v", resValidators)
|
assert.Equal(t, sdk.NewDec(0), resValidators[4].BondedTokens(), "%v", resValidators)
|
||||||
assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators)
|
assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators)
|
||||||
assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators)
|
assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators)
|
||||||
assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators)
|
assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators)
|
||||||
|
@ -276,14 +276,14 @@ func GetValidatorSortingUnmixed(t *testing.T) {
|
||||||
assert.Equal(t, validators[0].Owner, resValidators[4].Owner, "%v", resValidators)
|
assert.Equal(t, validators[0].Owner, resValidators[4].Owner, "%v", resValidators)
|
||||||
|
|
||||||
// test a basic increase in voting power
|
// test a basic increase in voting power
|
||||||
validators[3].Tokens = sdk.NewRat(500)
|
validators[3].Tokens = sdk.NewDec(500)
|
||||||
keeper.UpdateValidator(ctx, validators[3])
|
keeper.UpdateValidator(ctx, validators[3])
|
||||||
resValidators = keeper.GetValidatorsByPower(ctx)
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
||||||
require.Equal(t, len(resValidators), n)
|
require.Equal(t, len(resValidators), n)
|
||||||
assert.True(ValEq(t, validators[3], resValidators[0]))
|
assert.True(ValEq(t, validators[3], resValidators[0]))
|
||||||
|
|
||||||
// test a decrease in voting power
|
// test a decrease in voting power
|
||||||
validators[3].Tokens = sdk.NewRat(300)
|
validators[3].Tokens = sdk.NewDec(300)
|
||||||
keeper.UpdateValidator(ctx, validators[3])
|
keeper.UpdateValidator(ctx, validators[3])
|
||||||
resValidators = keeper.GetValidatorsByPower(ctx)
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
||||||
require.Equal(t, len(resValidators), n)
|
require.Equal(t, len(resValidators), n)
|
||||||
|
@ -291,7 +291,7 @@ func GetValidatorSortingUnmixed(t *testing.T) {
|
||||||
assert.True(ValEq(t, validators[4], resValidators[1]))
|
assert.True(ValEq(t, validators[4], resValidators[1]))
|
||||||
|
|
||||||
// test equal voting power, different age
|
// test equal voting power, different age
|
||||||
validators[3].Tokens = sdk.NewRat(200)
|
validators[3].Tokens = sdk.NewDec(200)
|
||||||
ctx = ctx.WithBlockHeight(10)
|
ctx = ctx.WithBlockHeight(10)
|
||||||
keeper.UpdateValidator(ctx, validators[3])
|
keeper.UpdateValidator(ctx, validators[3])
|
||||||
resValidators = keeper.GetValidatorsByPower(ctx)
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
||||||
|
@ -310,8 +310,8 @@ func GetValidatorSortingUnmixed(t *testing.T) {
|
||||||
assert.True(ValEq(t, validators[4], resValidators[1]))
|
assert.True(ValEq(t, validators[4], resValidators[1]))
|
||||||
|
|
||||||
// change in voting power of both validators, both still in v-set, no age change
|
// change in voting power of both validators, both still in v-set, no age change
|
||||||
validators[3].Tokens = sdk.NewRat(300)
|
validators[3].Tokens = sdk.NewDec(300)
|
||||||
validators[4].Tokens = sdk.NewRat(300)
|
validators[4].Tokens = sdk.NewDec(300)
|
||||||
keeper.UpdateValidator(ctx, validators[3])
|
keeper.UpdateValidator(ctx, validators[3])
|
||||||
resValidators = keeper.GetValidatorsByPower(ctx)
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
||||||
require.Equal(t, len(resValidators), n)
|
require.Equal(t, len(resValidators), n)
|
||||||
|
@ -338,20 +338,20 @@ func GetValidatorSortingMixed(t *testing.T) {
|
||||||
var validators [5]types.Validator
|
var validators [5]types.Validator
|
||||||
for i, amt := range amts {
|
for i, amt := range amts {
|
||||||
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
||||||
validators[i].DelegatorShares = sdk.NewRat(amt)
|
validators[i].DelegatorShares = sdk.NewDec(amt)
|
||||||
}
|
}
|
||||||
|
|
||||||
validators[0].Status = sdk.Bonded
|
validators[0].Status = sdk.Bonded
|
||||||
validators[1].Status = sdk.Bonded
|
validators[1].Status = sdk.Bonded
|
||||||
validators[2].Status = sdk.Bonded
|
validators[2].Status = sdk.Bonded
|
||||||
validators[0].Tokens = sdk.NewRat(amts[0])
|
validators[0].Tokens = sdk.NewDec(amts[0])
|
||||||
validators[1].Tokens = sdk.NewRat(amts[1])
|
validators[1].Tokens = sdk.NewDec(amts[1])
|
||||||
validators[2].Tokens = sdk.NewRat(amts[2])
|
validators[2].Tokens = sdk.NewDec(amts[2])
|
||||||
|
|
||||||
validators[3].Status = sdk.Bonded
|
validators[3].Status = sdk.Bonded
|
||||||
validators[4].Status = sdk.Bonded
|
validators[4].Status = sdk.Bonded
|
||||||
validators[3].Tokens = sdk.NewRat(amts[3])
|
validators[3].Tokens = sdk.NewDec(amts[3])
|
||||||
validators[4].Tokens = sdk.NewRat(amts[4])
|
validators[4].Tokens = sdk.NewDec(amts[4])
|
||||||
|
|
||||||
for i := range amts {
|
for i := range amts {
|
||||||
keeper.UpdateValidator(ctx, validators[i])
|
keeper.UpdateValidator(ctx, validators[i])
|
||||||
|
@ -375,11 +375,11 @@ func GetValidatorSortingMixed(t *testing.T) {
|
||||||
// first make sure everything made it in to the gotValidator group
|
// first make sure everything made it in to the gotValidator group
|
||||||
resValidators := keeper.GetValidatorsByPower(ctx)
|
resValidators := keeper.GetValidatorsByPower(ctx)
|
||||||
assert.Equal(t, n, len(resValidators))
|
assert.Equal(t, n, len(resValidators))
|
||||||
assert.Equal(t, sdk.NewRat(400), resValidators[0].BondedTokens(), "%v", resValidators)
|
assert.Equal(t, sdk.NewDec(400), resValidators[0].BondedTokens(), "%v", resValidators)
|
||||||
assert.Equal(t, sdk.NewRat(200), resValidators[1].BondedTokens(), "%v", resValidators)
|
assert.Equal(t, sdk.NewDec(200), resValidators[1].BondedTokens(), "%v", resValidators)
|
||||||
assert.Equal(t, sdk.NewRat(100), resValidators[2].BondedTokens(), "%v", resValidators)
|
assert.Equal(t, sdk.NewDec(100), resValidators[2].BondedTokens(), "%v", resValidators)
|
||||||
assert.Equal(t, sdk.NewRat(1), resValidators[3].BondedTokens(), "%v", resValidators)
|
assert.Equal(t, sdk.NewDec(1), resValidators[3].BondedTokens(), "%v", resValidators)
|
||||||
assert.Equal(t, sdk.NewRat(0), resValidators[4].BondedTokens(), "%v", resValidators)
|
assert.Equal(t, sdk.NewDec(0), resValidators[4].BondedTokens(), "%v", resValidators)
|
||||||
assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators)
|
assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators)
|
||||||
assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators)
|
assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators)
|
||||||
assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators)
|
assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators)
|
||||||
|
@ -444,7 +444,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
|
||||||
assert.True(ValEq(t, validators[3], resValidators[1]))
|
assert.True(ValEq(t, validators[3], resValidators[1]))
|
||||||
|
|
||||||
// validator 3 kicked out temporarily
|
// validator 3 kicked out temporarily
|
||||||
validators[3], pool, _ = validators[3].RemoveDelShares(pool, sdk.NewRat(201))
|
validators[3], pool, _ = validators[3].RemoveDelShares(pool, sdk.NewDec(201))
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
validators[3] = keeper.UpdateValidator(ctx, validators[3])
|
validators[3] = keeper.UpdateValidator(ctx, validators[3])
|
||||||
resValidators = keeper.GetValidatorsByPower(ctx)
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
||||||
|
@ -656,7 +656,7 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) {
|
||||||
// test single value change
|
// test single value change
|
||||||
// tendermintUpdate set: {} -> {c1'}
|
// tendermintUpdate set: {} -> {c1'}
|
||||||
validators[0].Status = sdk.Bonded
|
validators[0].Status = sdk.Bonded
|
||||||
validators[0].Tokens = sdk.NewRat(600)
|
validators[0].Tokens = sdk.NewDec(600)
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
|
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetTendermintUpdates(ctx)
|
||||||
|
@ -794,21 +794,21 @@ func TestGetTendermintUpdatesPowerDecrease(t *testing.T) {
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
||||||
|
|
||||||
// check initial power
|
// check initial power
|
||||||
require.Equal(t, sdk.NewRat(100).RoundInt64(), validators[0].GetPower().RoundInt64())
|
require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[0].GetPower().RoundInt64())
|
||||||
require.Equal(t, sdk.NewRat(100).RoundInt64(), validators[1].GetPower().RoundInt64())
|
require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[1].GetPower().RoundInt64())
|
||||||
|
|
||||||
// test multiple value change
|
// test multiple value change
|
||||||
// tendermintUpdate set: {c1, c3} -> {c1', c3'}
|
// tendermintUpdate set: {c1, c3} -> {c1', c3'}
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
validators[0], pool, _ = validators[0].RemoveDelShares(pool, sdk.NewRat(20))
|
validators[0], pool, _ = validators[0].RemoveDelShares(pool, sdk.NewDec(20))
|
||||||
validators[1], pool, _ = validators[1].RemoveDelShares(pool, sdk.NewRat(30))
|
validators[1], pool, _ = validators[1].RemoveDelShares(pool, sdk.NewDec(30))
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
|
|
||||||
// power has changed
|
// power has changed
|
||||||
require.Equal(t, sdk.NewRat(80).RoundInt64(), validators[0].GetPower().RoundInt64())
|
require.Equal(t, sdk.NewDec(80).RoundInt64(), validators[0].GetPower().RoundInt64())
|
||||||
require.Equal(t, sdk.NewRat(70).RoundInt64(), validators[1].GetPower().RoundInt64())
|
require.Equal(t, sdk.NewDec(70).RoundInt64(), validators[1].GetPower().RoundInt64())
|
||||||
|
|
||||||
// Tendermint updates should reflect power change
|
// Tendermint updates should reflect power change
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetTendermintUpdates(ctx)
|
||||||
|
|
|
@ -31,7 +31,7 @@ func SupplyInvariants(ck bank.Keeper, k stake.Keeper, am auth.AccountMapper) sim
|
||||||
pool := k.GetPool(ctx)
|
pool := k.GetPool(ctx)
|
||||||
|
|
||||||
loose := sdk.ZeroInt()
|
loose := sdk.ZeroInt()
|
||||||
bonded := sdk.ZeroRat()
|
bonded := sdk.ZeroDec()
|
||||||
am.IterateAccounts(ctx, func(acc auth.Account) bool {
|
am.IterateAccounts(ctx, func(acc auth.Account) bool {
|
||||||
loose = loose.Add(acc.GetCoins().AmountOf("steak"))
|
loose = loose.Add(acc.GetCoins().AmountOf("steak"))
|
||||||
return false
|
return false
|
||||||
|
@ -67,7 +67,7 @@ func PositivePowerInvariant(k stake.Keeper) simulation.Invariant {
|
||||||
return func(t *testing.T, app *baseapp.BaseApp, log string) {
|
return func(t *testing.T, app *baseapp.BaseApp, log string) {
|
||||||
ctx := app.NewContext(false, abci.Header{})
|
ctx := app.NewContext(false, abci.Header{})
|
||||||
k.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) bool {
|
k.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) bool {
|
||||||
require.True(t, validator.GetPower().GT(sdk.ZeroRat()), "validator with non-positive power stored")
|
require.True(t, validator.GetPower().GT(sdk.ZeroDec()), "validator with non-positive power stored")
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.
|
||||||
msg := stake.MsgBeginUnbonding{
|
msg := stake.MsgBeginUnbonding{
|
||||||
DelegatorAddr: delegatorAddress,
|
DelegatorAddr: delegatorAddress,
|
||||||
ValidatorAddr: validatorAddress,
|
ValidatorAddr: validatorAddress,
|
||||||
SharesAmount: sdk.NewRatFromInt(amount),
|
SharesAmount: sdk.NewDecFromInt(amount),
|
||||||
}
|
}
|
||||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||||
ctx, write := ctx.CacheContext()
|
ctx, write := ctx.CacheContext()
|
||||||
|
@ -191,7 +191,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation
|
||||||
DelegatorAddr: delegatorAddress,
|
DelegatorAddr: delegatorAddress,
|
||||||
ValidatorSrcAddr: sourceValidatorAddress,
|
ValidatorSrcAddr: sourceValidatorAddress,
|
||||||
ValidatorDstAddr: destValidatorAddress,
|
ValidatorDstAddr: destValidatorAddress,
|
||||||
SharesAmount: sdk.NewRatFromInt(amount),
|
SharesAmount: sdk.NewDecFromInt(amount),
|
||||||
}
|
}
|
||||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||||
ctx, write := ctx.CacheContext()
|
ctx, write := ctx.CacheContext()
|
||||||
|
@ -247,7 +247,7 @@ func Setup(mapp *mock.App, k stake.Keeper) simulation.RandSetup {
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
pool := k.GetPool(ctx)
|
pool := k.GetPool(ctx)
|
||||||
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewRat(loose.Int64(), 1))
|
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewDec(loose.Int64()))
|
||||||
k.SetPool(ctx, pool)
|
k.SetPool(ctx, pool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,12 @@ import (
|
||||||
type Delegation struct {
|
type Delegation struct {
|
||||||
DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
|
DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
|
||||||
ValidatorAddr sdk.AccAddress `json:"validator_addr"`
|
ValidatorAddr sdk.AccAddress `json:"validator_addr"`
|
||||||
Shares sdk.Rat `json:"shares"`
|
Shares sdk.Dec `json:"shares"`
|
||||||
Height int64 `json:"height"` // Last height bond updated
|
Height int64 `json:"height"` // Last height bond updated
|
||||||
}
|
}
|
||||||
|
|
||||||
type delegationValue struct {
|
type delegationValue struct {
|
||||||
Shares sdk.Rat
|
Shares sdk.Dec
|
||||||
Height int64
|
Height int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ var _ sdk.Delegation = Delegation{}
|
||||||
// nolint - for sdk.Delegation
|
// nolint - for sdk.Delegation
|
||||||
func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr }
|
func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr }
|
||||||
func (d Delegation) GetValidator() sdk.AccAddress { return d.ValidatorAddr }
|
func (d Delegation) GetValidator() sdk.AccAddress { return d.ValidatorAddr }
|
||||||
func (d Delegation) GetBondShares() sdk.Rat { return d.Shares }
|
func (d Delegation) GetBondShares() sdk.Dec { return d.Shares }
|
||||||
|
|
||||||
// HumanReadableString returns a human readable string representation of a
|
// HumanReadableString returns a human readable string representation of a
|
||||||
// Delegation. An error is returned if the Delegation's delegator or validator
|
// Delegation. An error is returned if the Delegation's delegator or validator
|
||||||
|
@ -190,8 +190,8 @@ type Redelegation struct {
|
||||||
MinTime time.Time `json:"min_time"` // unix time for redelegation completion
|
MinTime time.Time `json:"min_time"` // unix time for redelegation completion
|
||||||
InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started
|
InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started
|
||||||
Balance sdk.Coin `json:"balance"` // current balance
|
Balance sdk.Coin `json:"balance"` // current balance
|
||||||
SharesSrc sdk.Rat `json:"shares_src"` // amount of source shares redelegating
|
SharesSrc sdk.Dec `json:"shares_src"` // amount of source shares redelegating
|
||||||
SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating
|
SharesDst sdk.Dec `json:"shares_dst"` // amount of destination shares redelegating
|
||||||
}
|
}
|
||||||
|
|
||||||
type redValue struct {
|
type redValue struct {
|
||||||
|
@ -199,8 +199,8 @@ type redValue struct {
|
||||||
MinTime time.Time
|
MinTime time.Time
|
||||||
InitialBalance sdk.Coin
|
InitialBalance sdk.Coin
|
||||||
Balance sdk.Coin
|
Balance sdk.Coin
|
||||||
SharesSrc sdk.Rat
|
SharesSrc sdk.Dec
|
||||||
SharesDst sdk.Rat
|
SharesDst sdk.Dec
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the redelegation without fields contained within the key for the store
|
// return the redelegation without fields contained within the key for the store
|
||||||
|
|
|
@ -12,19 +12,19 @@ func TestDelegationEqual(t *testing.T) {
|
||||||
d1 := Delegation{
|
d1 := Delegation{
|
||||||
DelegatorAddr: addr1,
|
DelegatorAddr: addr1,
|
||||||
ValidatorAddr: addr2,
|
ValidatorAddr: addr2,
|
||||||
Shares: sdk.NewRat(100),
|
Shares: sdk.NewDec(100),
|
||||||
}
|
}
|
||||||
d2 := Delegation{
|
d2 := Delegation{
|
||||||
DelegatorAddr: addr1,
|
DelegatorAddr: addr1,
|
||||||
ValidatorAddr: addr2,
|
ValidatorAddr: addr2,
|
||||||
Shares: sdk.NewRat(100),
|
Shares: sdk.NewDec(100),
|
||||||
}
|
}
|
||||||
|
|
||||||
ok := d1.Equal(d2)
|
ok := d1.Equal(d2)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
d2.ValidatorAddr = addr3
|
d2.ValidatorAddr = addr3
|
||||||
d2.Shares = sdk.NewRat(200)
|
d2.Shares = sdk.NewDec(200)
|
||||||
|
|
||||||
ok = d1.Equal(d2)
|
ok = d1.Equal(d2)
|
||||||
require.False(t, ok)
|
require.False(t, ok)
|
||||||
|
@ -34,7 +34,7 @@ func TestDelegationHumanReadableString(t *testing.T) {
|
||||||
d := Delegation{
|
d := Delegation{
|
||||||
DelegatorAddr: addr1,
|
DelegatorAddr: addr1,
|
||||||
ValidatorAddr: addr2,
|
ValidatorAddr: addr2,
|
||||||
Shares: sdk.NewRat(100),
|
Shares: sdk.NewDec(100),
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Being that the validator's keypair is random, we cannot test the
|
// NOTE: Being that the validator's keypair is random, we cannot test the
|
||||||
|
@ -58,8 +58,8 @@ func TestUnbondingDelegationEqual(t *testing.T) {
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
ud2.ValidatorAddr = addr3
|
ud2.ValidatorAddr = addr3
|
||||||
ud2.MinTime = time.Unix(20*20*2, 0)
|
|
||||||
|
|
||||||
|
ud2.MinTime = time.Unix(20*20*2, 0)
|
||||||
ok = ud1.Equal(ud2)
|
ok = ud1.Equal(ud2)
|
||||||
require.False(t, ok)
|
require.False(t, ok)
|
||||||
}
|
}
|
||||||
|
@ -92,8 +92,8 @@ func TestRedelegationEqual(t *testing.T) {
|
||||||
ok := r1.Equal(r2)
|
ok := r1.Equal(r2)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
r2.SharesDst = sdk.NewRat(10)
|
r2.SharesDst = sdk.NewDec(10)
|
||||||
r2.SharesSrc = sdk.NewRat(20)
|
r2.SharesSrc = sdk.NewDec(20)
|
||||||
r2.MinTime = time.Unix(20*20*2, 0)
|
r2.MinTime = time.Unix(20*20*2, 0)
|
||||||
|
|
||||||
ok = r1.Equal(r2)
|
ok = r1.Equal(r2)
|
||||||
|
@ -105,8 +105,8 @@ func TestRedelegationHumanReadableString(t *testing.T) {
|
||||||
DelegatorAddr: addr1,
|
DelegatorAddr: addr1,
|
||||||
ValidatorSrcAddr: addr2,
|
ValidatorSrcAddr: addr2,
|
||||||
ValidatorDstAddr: addr3,
|
ValidatorDstAddr: addr3,
|
||||||
SharesDst: sdk.NewRat(10),
|
SharesDst: sdk.NewDec(10),
|
||||||
SharesSrc: sdk.NewRat(20),
|
SharesSrc: sdk.NewDec(20),
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Being that the validator's keypair is random, we cannot test the
|
// NOTE: Being that the validator's keypair is random, we cannot test the
|
||||||
|
|
|
@ -100,13 +100,6 @@ func ErrBadSharesAmount(codespace sdk.CodespaceType) sdk.Error {
|
||||||
return sdk.NewError(codespace, CodeInvalidDelegation, "shares must be > 0")
|
return sdk.NewError(codespace, CodeInvalidDelegation, "shares must be > 0")
|
||||||
}
|
}
|
||||||
|
|
||||||
func ErrBadSharesPrecision(codespace sdk.CodespaceType) sdk.Error {
|
|
||||||
return sdk.NewError(codespace, CodeInvalidDelegation,
|
|
||||||
fmt.Sprintf("shares denominator must be < %s, try reducing the number of decimal points",
|
|
||||||
maximumBondingRationalDenominator.String()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ErrBadSharesPercent(codespace sdk.CodespaceType) sdk.Error {
|
func ErrBadSharesPercent(codespace sdk.CodespaceType) sdk.Error {
|
||||||
return sdk.NewError(codespace, CodeInvalidDelegation, "shares percent must be >0 and <=1")
|
return sdk.NewError(codespace, CodeInvalidDelegation, "shares percent must be >0 and <=1")
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,30 +23,30 @@ func TestGetInflation(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
setBondedTokens, setLooseTokens,
|
setBondedTokens, setLooseTokens,
|
||||||
setInflation, expectedChange sdk.Rat
|
setInflation, expectedChange sdk.Dec
|
||||||
}{
|
}{
|
||||||
// with 0% bonded atom supply the inflation should increase by InflationRateChange
|
// with 0% bonded atom supply the inflation should increase by InflationRateChange
|
||||||
{"test 1", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(7, 100), params.InflationRateChange.Quo(hrsPerYrRat).Round(precision)},
|
{"test 1", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), params.InflationRateChange.Quo(hrsPerYrDec)},
|
||||||
|
|
||||||
// 100% bonded, starting at 20% inflation and being reduced
|
// 100% bonded, starting at 20% inflation and being reduced
|
||||||
// (1 - (1/0.67))*(0.13/8667)
|
// (1 - (1/0.67))*(0.13/8667)
|
||||||
{"test 2", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(20, 100),
|
{"test 2", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2),
|
||||||
sdk.OneRat().Sub(sdk.OneRat().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)},
|
sdk.OneDec().Sub(sdk.OneDec().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrDec)},
|
||||||
|
|
||||||
// 50% bonded, starting at 10% inflation and being increased
|
// 50% bonded, starting at 10% inflation and being increased
|
||||||
{"test 3", sdk.OneRat(), sdk.OneRat(), sdk.NewRat(10, 100),
|
{"test 3", sdk.OneDec(), sdk.OneDec(), sdk.NewDecWithPrec(10, 2),
|
||||||
sdk.OneRat().Sub(sdk.NewRat(1, 2).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)},
|
sdk.OneDec().Sub(sdk.NewDecWithPrec(5, 1).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrDec)},
|
||||||
|
|
||||||
// test 7% minimum stop (testing with 100% bonded)
|
// test 7% minimum stop (testing with 100% bonded)
|
||||||
{"test 4", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(7, 100), sdk.ZeroRat()},
|
{"test 4", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), sdk.ZeroDec()},
|
||||||
{"test 5", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(70001, 1000000), sdk.NewRat(-1, 1000000)},
|
{"test 5", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(70001, 6), sdk.NewDecWithPrec(-1, 6)},
|
||||||
|
|
||||||
// test 20% maximum stop (testing with 0% bonded)
|
// test 20% maximum stop (testing with 0% bonded)
|
||||||
{"test 6", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(20, 100), sdk.ZeroRat()},
|
{"test 6", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2), sdk.ZeroDec()},
|
||||||
{"test 7", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(199999, 1000000), sdk.NewRat(1, 1000000)},
|
{"test 7", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(199999, 6), sdk.NewDecWithPrec(1, 6)},
|
||||||
|
|
||||||
// perfect balance shouldn't change inflation
|
// perfect balance shouldn't change inflation
|
||||||
{"test 8", sdk.NewRat(67), sdk.NewRat(33), sdk.NewRat(15, 100), sdk.ZeroRat()},
|
{"test 8", sdk.NewDec(67), sdk.NewDec(33), sdk.NewDecWithPrec(15, 2), sdk.ZeroDec()},
|
||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
pool.BondedTokens, pool.LooseTokens = tc.setBondedTokens, tc.setLooseTokens
|
pool.BondedTokens, pool.LooseTokens = tc.setBondedTokens, tc.setLooseTokens
|
||||||
|
@ -67,77 +67,80 @@ func TestProcessProvisions(t *testing.T) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
initialTotalTokens int64 = 550000000
|
initialTotalTokens int64 = 550000000
|
||||||
cumulativeExpProvs = sdk.ZeroRat()
|
cumulativeExpProvs = sdk.ZeroDec()
|
||||||
)
|
)
|
||||||
pool.LooseTokens = sdk.NewRat(initialTotalTokens)
|
pool.LooseTokens = sdk.NewDec(initialTotalTokens)
|
||||||
|
|
||||||
// process the provisions for a year
|
// process the provisions for a year
|
||||||
for hr := 0; hr < 100; hr++ {
|
for hr := 0; hr < 100; hr++ {
|
||||||
var expProvisions sdk.Rat
|
var expProvisions sdk.Dec
|
||||||
_, expProvisions, pool = updateProvisions(t, pool, params, hr)
|
_, expProvisions, pool = updateProvisions(t, pool, params, hr)
|
||||||
cumulativeExpProvs = cumulativeExpProvs.Add(expProvisions)
|
cumulativeExpProvs = cumulativeExpProvs.Add(expProvisions)
|
||||||
}
|
}
|
||||||
|
|
||||||
//get the pool and do the final value checks from checkFinalPoolValues
|
//get the pool and do the final value checks from checkFinalPoolValues
|
||||||
checkFinalPoolValues(t, pool, sdk.NewRat(initialTotalTokens), cumulativeExpProvs)
|
checkFinalPoolValues(t, pool, sdk.NewDec(initialTotalTokens), cumulativeExpProvs)
|
||||||
}
|
}
|
||||||
|
|
||||||
//_________________________________________________________________________________________
|
//_________________________________________________________________________________________
|
||||||
////////////////////////////////HELPER FUNCTIONS BELOW/////////////////////////////////////
|
////////////////////////////////HELPER FUNCTIONS BELOW/////////////////////////////////////
|
||||||
|
|
||||||
// Final check on the global pool values for what the total tokens accumulated from each hour of provisions
|
// Final check on the global pool values for what the total tokens accumulated from each hour of provisions
|
||||||
func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, cumulativeExpProvs sdk.Rat) {
|
func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, cumulativeExpProvs sdk.Dec) {
|
||||||
calculatedTotalTokens := initialTotalTokens.Add(cumulativeExpProvs)
|
calculatedTotalTokens := initialTotalTokens.Add(cumulativeExpProvs)
|
||||||
require.True(sdk.RatEq(t, calculatedTotalTokens, pool.TokenSupply()))
|
require.True(sdk.DecEq(t, calculatedTotalTokens, pool.TokenSupply()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Processes provisions are added to the pool correctly every hour
|
// Processes provisions are added to the pool correctly every hour
|
||||||
// Returns expected Provisions, expected Inflation, and pool, to help with cumulative calculations back in main Tests
|
// Returns expected Provisions, expected Inflation, and pool, to help with cumulative calculations back in main Tests
|
||||||
func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Rat, sdk.Rat, Pool) {
|
func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Dec, sdk.Dec, Pool) {
|
||||||
|
|
||||||
expInflation := pool.NextInflation(params)
|
expInflation := pool.NextInflation(params)
|
||||||
expProvisions := expInflation.Mul(pool.TokenSupply().Round(precision)).Quo(hrsPerYrRat)
|
expProvisions := expInflation.Mul(pool.TokenSupply()).Quo(hrsPerYrDec)
|
||||||
startTotalSupply := pool.TokenSupply()
|
startTotalSupply := pool.TokenSupply()
|
||||||
pool = pool.ProcessProvisions(params)
|
pool = pool.ProcessProvisions(params)
|
||||||
|
|
||||||
//check provisions were added to pool
|
//check provisions were added to pool
|
||||||
require.True(sdk.RatEq(t, startTotalSupply.Add(expProvisions), pool.TokenSupply()))
|
require.True(sdk.DecEq(t, startTotalSupply.Add(expProvisions), pool.TokenSupply()))
|
||||||
|
|
||||||
return expInflation, expProvisions, pool
|
return expInflation, expProvisions, pool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks that The inflation will correctly increase or decrease after an update to the pool
|
// Checks that The inflation will correctly increase or decrease after an update to the pool
|
||||||
// nolint: gocyclo
|
// nolint: gocyclo
|
||||||
func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation sdk.Rat, msg string) {
|
func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation sdk.Dec, msg string) {
|
||||||
inflationChange := updatedInflation.Sub(previousInflation)
|
inflationChange := updatedInflation.Sub(previousInflation)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
//BELOW 67% - Rate of change positive and increasing, while we are between 7% <= and < 20% inflation
|
//BELOW 67% - Rate of change positive and increasing, while we are between 7% <= and < 20% inflation
|
||||||
case pool.BondedRatio().LT(sdk.NewRat(67, 100)) && updatedInflation.LT(sdk.NewRat(20, 100)):
|
case pool.BondedRatio().LT(sdk.NewDecWithPrec(67, 2)) && updatedInflation.LT(sdk.NewDecWithPrec(20, 2)):
|
||||||
require.Equal(t, true, inflationChange.GT(sdk.ZeroRat()), msg)
|
require.Equal(t, true, inflationChange.GT(sdk.ZeroDec()), msg)
|
||||||
|
|
||||||
//BELOW 67% - Rate of change should be 0 while inflation continually stays at 20% until we reach 67% bonded ratio
|
//BELOW 67% - Rate of change should be 0 while inflation continually stays at 20% until we reach 67% bonded ratio
|
||||||
case pool.BondedRatio().LT(sdk.NewRat(67, 100)) && updatedInflation.Equal(sdk.NewRat(20, 100)):
|
case pool.BondedRatio().LT(sdk.NewDecWithPrec(67, 2)) && updatedInflation.Equal(sdk.NewDecWithPrec(20, 2)):
|
||||||
if previousInflation.Equal(sdk.NewRat(20, 100)) {
|
if previousInflation.Equal(sdk.NewDecWithPrec(20, 2)) {
|
||||||
require.Equal(t, true, inflationChange.IsZero(), msg)
|
require.Equal(t, true, inflationChange.IsZero(), msg)
|
||||||
|
|
||||||
//This else statement covers the one off case where we first hit 20%, but we still needed a positive ROC to get to 67% bonded ratio (i.e. we went from 19.99999% to 20%)
|
//This else statement covers the one off case where we first hit 20%, but we still needed a positive ROC to get to 67% bonded ratio (i.e. we went from 19.99999% to 20%)
|
||||||
} else {
|
} else {
|
||||||
require.Equal(t, true, inflationChange.GT(sdk.ZeroRat()), msg)
|
require.Equal(t, true, inflationChange.GT(sdk.ZeroDec()), msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
//ABOVE 67% - Rate of change should be negative while the bond is above 67, and should stay negative until we reach inflation of 7%
|
//ABOVE 67% - Rate of change should be negative while the bond is above 67, and should stay negative until we reach inflation of 7%
|
||||||
case pool.BondedRatio().GT(sdk.NewRat(67, 100)) && updatedInflation.LT(sdk.NewRat(20, 100)) && updatedInflation.GT(sdk.NewRat(7, 100)):
|
case pool.BondedRatio().GT(sdk.NewDecWithPrec(67, 2)) &&
|
||||||
require.Equal(t, true, inflationChange.LT(sdk.ZeroRat()), msg)
|
updatedInflation.LT(sdk.NewDecWithPrec(20, 2)) && updatedInflation.GT(sdk.NewDecWithPrec(7, 2)):
|
||||||
|
require.Equal(t, true, inflationChange.LT(sdk.ZeroDec()), msg)
|
||||||
|
|
||||||
//ABOVE 67% - Rate of change should be 0 while inflation continually stays at 7%.
|
//ABOVE 67% - Rate of change should be 0 while inflation continually stays at 7%.
|
||||||
case pool.BondedRatio().GT(sdk.NewRat(67, 100)) && updatedInflation.Equal(sdk.NewRat(7, 100)):
|
case pool.BondedRatio().GT(sdk.NewDecWithPrec(67, 2)) &&
|
||||||
if previousInflation.Equal(sdk.NewRat(7, 100)) {
|
updatedInflation.Equal(sdk.NewDecWithPrec(7, 2)):
|
||||||
|
|
||||||
|
if previousInflation.Equal(sdk.NewDecWithPrec(7, 2)) {
|
||||||
require.Equal(t, true, inflationChange.IsZero(), msg)
|
require.Equal(t, true, inflationChange.IsZero(), msg)
|
||||||
|
|
||||||
//This else statement covers the one off case where we first hit 7%, but we still needed a negative ROC to continue to get down to 67%. (i.e. we went from 7.00001% to 7%)
|
//This else statement covers the one off case where we first hit 7%, but we still needed a negative ROC to continue to get down to 67%. (i.e. we went from 7.00001% to 7%)
|
||||||
} else {
|
} else {
|
||||||
require.Equal(t, true, inflationChange.LT(sdk.ZeroRat()), msg)
|
require.Equal(t, true, inflationChange.LT(sdk.ZeroDec()), msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
@ -11,18 +10,11 @@ import (
|
||||||
// name to idetify transaction types
|
// name to idetify transaction types
|
||||||
const MsgType = "stake"
|
const MsgType = "stake"
|
||||||
|
|
||||||
// Maximum amount of decimal points in the decimal representation of rationals
|
|
||||||
// used in MsgBeginUnbonding / MsgBeginRedelegate
|
|
||||||
const MaxBondDenominatorPrecision = 8
|
|
||||||
|
|
||||||
// Verify interface at compile time
|
// Verify interface at compile time
|
||||||
var _, _, _ sdk.Msg = &MsgCreateValidator{}, &MsgEditValidator{}, &MsgDelegate{}
|
var _, _, _ sdk.Msg = &MsgCreateValidator{}, &MsgEditValidator{}, &MsgDelegate{}
|
||||||
var _, _ sdk.Msg = &MsgBeginUnbonding{}, &MsgCompleteUnbonding{}
|
var _, _ sdk.Msg = &MsgBeginUnbonding{}, &MsgCompleteUnbonding{}
|
||||||
var _, _ sdk.Msg = &MsgBeginRedelegate{}, &MsgCompleteRedelegate{}
|
var _, _ sdk.Msg = &MsgBeginRedelegate{}, &MsgCompleteRedelegate{}
|
||||||
|
|
||||||
// Initialize Int for the denominator
|
|
||||||
var maximumBondingRationalDenominator = sdk.NewInt(int64(math.Pow10(MaxBondDenominatorPrecision)))
|
|
||||||
|
|
||||||
//______________________________________________________________________
|
//______________________________________________________________________
|
||||||
|
|
||||||
// MsgCreateValidator - struct for unbonding transactions
|
// MsgCreateValidator - struct for unbonding transactions
|
||||||
|
@ -211,11 +203,11 @@ type MsgBeginRedelegate struct {
|
||||||
DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
|
DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
|
||||||
ValidatorSrcAddr sdk.AccAddress `json:"validator_src_addr"`
|
ValidatorSrcAddr sdk.AccAddress `json:"validator_src_addr"`
|
||||||
ValidatorDstAddr sdk.AccAddress `json:"validator_dst_addr"`
|
ValidatorDstAddr sdk.AccAddress `json:"validator_dst_addr"`
|
||||||
SharesAmount sdk.Rat `json:"shares_amount"`
|
SharesAmount sdk.Dec `json:"shares_amount"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMsgBeginRedelegate(delegatorAddr, validatorSrcAddr,
|
func NewMsgBeginRedelegate(delegatorAddr, validatorSrcAddr,
|
||||||
validatorDstAddr sdk.AccAddress, sharesAmount sdk.Rat) MsgBeginRedelegate {
|
validatorDstAddr sdk.AccAddress, sharesAmount sdk.Dec) MsgBeginRedelegate {
|
||||||
|
|
||||||
return MsgBeginRedelegate{
|
return MsgBeginRedelegate{
|
||||||
DelegatorAddr: delegatorAddr,
|
DelegatorAddr: delegatorAddr,
|
||||||
|
@ -261,12 +253,9 @@ func (msg MsgBeginRedelegate) ValidateBasic() sdk.Error {
|
||||||
if msg.ValidatorDstAddr == nil {
|
if msg.ValidatorDstAddr == nil {
|
||||||
return ErrNilValidatorAddr(DefaultCodespace)
|
return ErrNilValidatorAddr(DefaultCodespace)
|
||||||
}
|
}
|
||||||
if msg.SharesAmount.LTE(sdk.ZeroRat()) {
|
if msg.SharesAmount.LTE(sdk.ZeroDec()) {
|
||||||
return ErrBadSharesAmount(DefaultCodespace)
|
return ErrBadSharesAmount(DefaultCodespace)
|
||||||
}
|
}
|
||||||
if msg.SharesAmount.Denom().GT(maximumBondingRationalDenominator) {
|
|
||||||
return ErrBadSharesPrecision(DefaultCodespace)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,10 +311,10 @@ func (msg MsgCompleteRedelegate) ValidateBasic() sdk.Error {
|
||||||
type MsgBeginUnbonding struct {
|
type MsgBeginUnbonding struct {
|
||||||
DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
|
DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
|
||||||
ValidatorAddr sdk.AccAddress `json:"validator_addr"`
|
ValidatorAddr sdk.AccAddress `json:"validator_addr"`
|
||||||
SharesAmount sdk.Rat `json:"shares_amount"`
|
SharesAmount sdk.Dec `json:"shares_amount"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMsgBeginUnbonding(delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Rat) MsgBeginUnbonding {
|
func NewMsgBeginUnbonding(delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Dec) MsgBeginUnbonding {
|
||||||
return MsgBeginUnbonding{
|
return MsgBeginUnbonding{
|
||||||
DelegatorAddr: delegatorAddr,
|
DelegatorAddr: delegatorAddr,
|
||||||
ValidatorAddr: validatorAddr,
|
ValidatorAddr: validatorAddr,
|
||||||
|
@ -362,12 +351,9 @@ func (msg MsgBeginUnbonding) ValidateBasic() sdk.Error {
|
||||||
if msg.ValidatorAddr == nil {
|
if msg.ValidatorAddr == nil {
|
||||||
return ErrNilValidatorAddr(DefaultCodespace)
|
return ErrNilValidatorAddr(DefaultCodespace)
|
||||||
}
|
}
|
||||||
if msg.SharesAmount.LTE(sdk.ZeroRat()) {
|
if msg.SharesAmount.LTE(sdk.ZeroDec()) {
|
||||||
return ErrBadSharesAmount(DefaultCodespace)
|
return ErrBadSharesAmount(DefaultCodespace)
|
||||||
}
|
}
|
||||||
if msg.SharesAmount.Denom().GT(maximumBondingRationalDenominator) {
|
|
||||||
return ErrBadSharesPrecision(DefaultCodespace)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,15 +143,15 @@ func TestMsgBeginRedelegate(t *testing.T) {
|
||||||
delegatorAddr sdk.AccAddress
|
delegatorAddr sdk.AccAddress
|
||||||
validatorSrcAddr sdk.AccAddress
|
validatorSrcAddr sdk.AccAddress
|
||||||
validatorDstAddr sdk.AccAddress
|
validatorDstAddr sdk.AccAddress
|
||||||
sharesAmount sdk.Rat
|
sharesAmount sdk.Dec
|
||||||
expectPass bool
|
expectPass bool
|
||||||
}{
|
}{
|
||||||
{"regular", addr1, addr2, addr3, sdk.NewRat(1, 10), true},
|
{"regular", addr1, addr2, addr3, sdk.NewDecWithPrec(1, 1), true},
|
||||||
{"negative decimal", addr1, addr2, addr3, sdk.NewRat(-1, 10), false},
|
{"negative decimal", addr1, addr2, addr3, sdk.NewDecWithPrec(-1, 1), false},
|
||||||
{"zero amount", addr1, addr2, addr3, sdk.ZeroRat(), false},
|
{"zero amount", addr1, addr2, addr3, sdk.ZeroDec(), false},
|
||||||
{"empty delegator", emptyAddr, addr1, addr3, sdk.NewRat(1, 10), false},
|
{"empty delegator", emptyAddr, addr1, addr3, sdk.NewDecWithPrec(1, 1), false},
|
||||||
{"empty source validator", addr1, emptyAddr, addr3, sdk.NewRat(1, 10), false},
|
{"empty source validator", addr1, emptyAddr, addr3, sdk.NewDecWithPrec(1, 1), false},
|
||||||
{"empty destination validator", addr1, addr2, emptyAddr, sdk.NewRat(1, 10), false},
|
{"empty destination validator", addr1, addr2, emptyAddr, sdk.NewDecWithPrec(1, 1), false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
|
@ -195,14 +195,14 @@ func TestMsgBeginUnbonding(t *testing.T) {
|
||||||
name string
|
name string
|
||||||
delegatorAddr sdk.AccAddress
|
delegatorAddr sdk.AccAddress
|
||||||
validatorAddr sdk.AccAddress
|
validatorAddr sdk.AccAddress
|
||||||
sharesAmount sdk.Rat
|
sharesAmount sdk.Dec
|
||||||
expectPass bool
|
expectPass bool
|
||||||
}{
|
}{
|
||||||
{"regular", addr1, addr2, sdk.NewRat(1, 10), true},
|
{"regular", addr1, addr2, sdk.NewDecWithPrec(1, 1), true},
|
||||||
{"negative decimal", addr1, addr2, sdk.NewRat(-1, 10), false},
|
{"negative decimal", addr1, addr2, sdk.NewDecWithPrec(-1, 1), false},
|
||||||
{"zero amount", addr1, addr2, sdk.ZeroRat(), false},
|
{"zero amount", addr1, addr2, sdk.ZeroDec(), false},
|
||||||
{"empty delegator", emptyAddr, addr1, sdk.NewRat(1, 10), false},
|
{"empty delegator", emptyAddr, addr1, sdk.NewDecWithPrec(1, 1), false},
|
||||||
{"empty validator", addr1, emptyAddr, sdk.NewRat(1, 10), false},
|
{"empty validator", addr1, emptyAddr, sdk.NewDecWithPrec(1, 1), false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
|
|
|
@ -13,10 +13,10 @@ const defaultUnbondingTime time.Duration = 60 * 60 * 24 * 3 * time.Second
|
||||||
|
|
||||||
// Params defines the high level settings for staking
|
// Params defines the high level settings for staking
|
||||||
type Params struct {
|
type Params struct {
|
||||||
InflationRateChange sdk.Rat `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
InflationRateChange sdk.Dec `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
||||||
InflationMax sdk.Rat `json:"inflation_max"` // maximum inflation rate
|
InflationMax sdk.Dec `json:"inflation_max"` // maximum inflation rate
|
||||||
InflationMin sdk.Rat `json:"inflation_min"` // minimum inflation rate
|
InflationMin sdk.Dec `json:"inflation_min"` // minimum inflation rate
|
||||||
GoalBonded sdk.Rat `json:"goal_bonded"` // Goal of percent bonded atoms
|
GoalBonded sdk.Dec `json:"goal_bonded"` // Goal of percent bonded atoms
|
||||||
|
|
||||||
UnbondingTime time.Duration `json:"unbonding_time"`
|
UnbondingTime time.Duration `json:"unbonding_time"`
|
||||||
|
|
||||||
|
@ -34,10 +34,10 @@ func (p Params) Equal(p2 Params) bool {
|
||||||
// DefaultParams returns a default set of parameters.
|
// DefaultParams returns a default set of parameters.
|
||||||
func DefaultParams() Params {
|
func DefaultParams() Params {
|
||||||
return Params{
|
return Params{
|
||||||
InflationRateChange: sdk.NewRat(13, 100),
|
InflationRateChange: sdk.NewDecWithPrec(13, 2),
|
||||||
InflationMax: sdk.NewRat(20, 100),
|
InflationMax: sdk.NewDecWithPrec(20, 2),
|
||||||
InflationMin: sdk.NewRat(7, 100),
|
InflationMin: sdk.NewDecWithPrec(7, 2),
|
||||||
GoalBonded: sdk.NewRat(67, 100),
|
GoalBonded: sdk.NewDecWithPrec(67, 2),
|
||||||
UnbondingTime: defaultUnbondingTime,
|
UnbondingTime: defaultUnbondingTime,
|
||||||
MaxValidators: 100,
|
MaxValidators: 100,
|
||||||
BondDenom: "steak",
|
BondDenom: "steak",
|
||||||
|
|
|
@ -10,15 +10,15 @@ import (
|
||||||
|
|
||||||
// Pool - dynamic parameters of the current state
|
// Pool - dynamic parameters of the current state
|
||||||
type Pool struct {
|
type Pool struct {
|
||||||
LooseTokens sdk.Rat `json:"loose_tokens"` // tokens which are not bonded in a validator
|
LooseTokens sdk.Dec `json:"loose_tokens"` // tokens which are not bonded in a validator
|
||||||
BondedTokens sdk.Rat `json:"bonded_tokens"` // reserve of bonded tokens
|
BondedTokens sdk.Dec `json:"bonded_tokens"` // reserve of bonded tokens
|
||||||
InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed
|
InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time
|
||||||
Inflation sdk.Rat `json:"inflation"` // current annual inflation rate
|
Inflation sdk.Dec `json:"inflation"` // current annual inflation rate
|
||||||
|
|
||||||
DateLastCommissionReset int64 `json:"date_last_commission_reset"` // unix timestamp for last commission accounting reset (daily)
|
DateLastCommissionReset int64 `json:"date_last_commission_reset"` // unix timestamp for last commission accounting reset (daily)
|
||||||
|
|
||||||
// Fee Related
|
// Fee Related
|
||||||
PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // last recorded bonded shares - for fee calculations
|
PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // last recorded bonded shares - for fee calculations
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint
|
// nolint
|
||||||
|
@ -31,48 +31,48 @@ func (p Pool) Equal(p2 Pool) bool {
|
||||||
// initial pool for testing
|
// initial pool for testing
|
||||||
func InitialPool() Pool {
|
func InitialPool() Pool {
|
||||||
return Pool{
|
return Pool{
|
||||||
LooseTokens: sdk.ZeroRat(),
|
LooseTokens: sdk.ZeroDec(),
|
||||||
BondedTokens: sdk.ZeroRat(),
|
BondedTokens: sdk.ZeroDec(),
|
||||||
InflationLastTime: time.Unix(0, 0),
|
InflationLastTime: time.Unix(0, 0),
|
||||||
Inflation: sdk.NewRat(7, 100),
|
Inflation: sdk.NewDecWithPrec(7, 2),
|
||||||
DateLastCommissionReset: 0,
|
DateLastCommissionReset: 0,
|
||||||
PrevBondedShares: sdk.ZeroRat(),
|
PrevBondedShares: sdk.ZeroDec(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//____________________________________________________________________
|
//____________________________________________________________________
|
||||||
|
|
||||||
// Sum total of all staking tokens in the pool
|
// Sum total of all staking tokens in the pool
|
||||||
func (p Pool) TokenSupply() sdk.Rat {
|
func (p Pool) TokenSupply() sdk.Dec {
|
||||||
return p.LooseTokens.Add(p.BondedTokens)
|
return p.LooseTokens.Add(p.BondedTokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
//____________________________________________________________________
|
//____________________________________________________________________
|
||||||
|
|
||||||
// get the bond ratio of the global state
|
// get the bond ratio of the global state
|
||||||
func (p Pool) BondedRatio() sdk.Rat {
|
func (p Pool) BondedRatio() sdk.Dec {
|
||||||
supply := p.TokenSupply()
|
supply := p.TokenSupply()
|
||||||
if supply.GT(sdk.ZeroRat()) {
|
if supply.GT(sdk.ZeroDec()) {
|
||||||
return p.BondedTokens.Quo(supply)
|
return p.BondedTokens.Quo(supply)
|
||||||
}
|
}
|
||||||
return sdk.ZeroRat()
|
return sdk.ZeroDec()
|
||||||
}
|
}
|
||||||
|
|
||||||
//_______________________________________________________________________
|
//_______________________________________________________________________
|
||||||
|
|
||||||
func (p Pool) looseTokensToBonded(bondedTokens sdk.Rat) Pool {
|
func (p Pool) looseTokensToBonded(bondedTokens sdk.Dec) Pool {
|
||||||
p.BondedTokens = p.BondedTokens.Add(bondedTokens)
|
p.BondedTokens = p.BondedTokens.Add(bondedTokens)
|
||||||
p.LooseTokens = p.LooseTokens.Sub(bondedTokens)
|
p.LooseTokens = p.LooseTokens.Sub(bondedTokens)
|
||||||
if p.LooseTokens.LT(sdk.ZeroRat()) {
|
if p.LooseTokens.LT(sdk.ZeroDec()) {
|
||||||
panic(fmt.Sprintf("sanity check: loose tokens negative, pool: %v", p))
|
panic(fmt.Sprintf("sanity check: loose tokens negative, pool: %v", p))
|
||||||
}
|
}
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Pool) bondedTokensToLoose(bondedTokens sdk.Rat) Pool {
|
func (p Pool) bondedTokensToLoose(bondedTokens sdk.Dec) Pool {
|
||||||
p.BondedTokens = p.BondedTokens.Sub(bondedTokens)
|
p.BondedTokens = p.BondedTokens.Sub(bondedTokens)
|
||||||
p.LooseTokens = p.LooseTokens.Add(bondedTokens)
|
p.LooseTokens = p.LooseTokens.Add(bondedTokens)
|
||||||
if p.BondedTokens.LT(sdk.ZeroRat()) {
|
if p.BondedTokens.LT(sdk.ZeroDec()) {
|
||||||
panic(fmt.Sprintf("sanity check: bonded tokens negative, pool: %v", p))
|
panic(fmt.Sprintf("sanity check: bonded tokens negative, pool: %v", p))
|
||||||
}
|
}
|
||||||
return p
|
return p
|
||||||
|
@ -82,14 +82,14 @@ func (p Pool) bondedTokensToLoose(bondedTokens sdk.Rat) Pool {
|
||||||
// Inflation
|
// Inflation
|
||||||
|
|
||||||
const precision = 10000 // increased to this precision for accuracy
|
const precision = 10000 // increased to this precision for accuracy
|
||||||
var hrsPerYrRat = sdk.NewRat(8766) // as defined by a julian year of 365.25 days
|
var hrsPerYrDec = sdk.NewDec(8766) // as defined by a julian year of 365.25 days
|
||||||
|
|
||||||
// process provisions for an hour period
|
// process provisions for an hour period
|
||||||
func (p Pool) ProcessProvisions(params Params) Pool {
|
func (p Pool) ProcessProvisions(params Params) Pool {
|
||||||
p.Inflation = p.NextInflation(params)
|
p.Inflation = p.NextInflation(params)
|
||||||
provisions := p.Inflation.
|
provisions := p.Inflation.
|
||||||
Mul(p.TokenSupply().Round(precision)).
|
Mul(p.TokenSupply()).
|
||||||
Quo(hrsPerYrRat)
|
Quo(hrsPerYrDec)
|
||||||
|
|
||||||
// TODO add to the fees provisions
|
// TODO add to the fees provisions
|
||||||
p.LooseTokens = p.LooseTokens.Add(provisions)
|
p.LooseTokens = p.LooseTokens.Add(provisions)
|
||||||
|
@ -97,7 +97,7 @@ func (p Pool) ProcessProvisions(params Params) Pool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the next inflation rate for the hour
|
// get the next inflation rate for the hour
|
||||||
func (p Pool) NextInflation(params Params) (inflation sdk.Rat) {
|
func (p Pool) NextInflation(params Params) (inflation sdk.Dec) {
|
||||||
|
|
||||||
// The target annual inflation rate is recalculated for each previsions cycle. The
|
// The target annual inflation rate is recalculated for each previsions cycle. The
|
||||||
// inflation is also subject to a rate change (positive or negative) depending on
|
// inflation is also subject to a rate change (positive or negative) depending on
|
||||||
|
@ -106,11 +106,11 @@ func (p Pool) NextInflation(params Params) (inflation sdk.Rat) {
|
||||||
// 7% and 20%.
|
// 7% and 20%.
|
||||||
|
|
||||||
// (1 - bondedRatio/GoalBonded) * InflationRateChange
|
// (1 - bondedRatio/GoalBonded) * InflationRateChange
|
||||||
inflationRateChangePerYear := sdk.OneRat().
|
inflationRateChangePerYear := sdk.OneDec().
|
||||||
Sub(p.BondedRatio().Round(precision).
|
Sub(p.BondedRatio().
|
||||||
Quo(params.GoalBonded)).
|
Quo(params.GoalBonded)).
|
||||||
Mul(params.InflationRateChange)
|
Mul(params.InflationRateChange)
|
||||||
inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrRat)
|
inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrDec)
|
||||||
|
|
||||||
// increase the new annual inflation for this next cycle
|
// increase the new annual inflation for this next cycle
|
||||||
inflation = p.Inflation.Add(inflationRateChange)
|
inflation = p.Inflation.Add(inflationRateChange)
|
||||||
|
@ -121,5 +121,5 @@ func (p Pool) NextInflation(params Params) (inflation sdk.Rat) {
|
||||||
inflation = params.InflationMin
|
inflation = params.InflationMin
|
||||||
}
|
}
|
||||||
|
|
||||||
return inflation.Round(precision)
|
return inflation
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,28 +11,28 @@ func TestPoolEqual(t *testing.T) {
|
||||||
p1 := InitialPool()
|
p1 := InitialPool()
|
||||||
p2 := InitialPool()
|
p2 := InitialPool()
|
||||||
require.True(t, p1.Equal(p2))
|
require.True(t, p1.Equal(p2))
|
||||||
p2.BondedTokens = sdk.NewRat(3)
|
p2.BondedTokens = sdk.NewDec(3)
|
||||||
require.False(t, p1.Equal(p2))
|
require.False(t, p1.Equal(p2))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddBondedTokens(t *testing.T) {
|
func TestAddBondedTokens(t *testing.T) {
|
||||||
pool := InitialPool()
|
pool := InitialPool()
|
||||||
pool.LooseTokens = sdk.NewRat(10)
|
pool.LooseTokens = sdk.NewDec(10)
|
||||||
pool.BondedTokens = sdk.NewRat(10)
|
pool.BondedTokens = sdk.NewDec(10)
|
||||||
|
|
||||||
pool = pool.looseTokensToBonded(sdk.NewRat(10))
|
pool = pool.looseTokensToBonded(sdk.NewDec(10))
|
||||||
|
|
||||||
require.True(sdk.RatEq(t, sdk.NewRat(20), pool.BondedTokens))
|
require.True(sdk.DecEq(t, sdk.NewDec(20), pool.BondedTokens))
|
||||||
require.True(sdk.RatEq(t, sdk.NewRat(0), pool.LooseTokens))
|
require.True(sdk.DecEq(t, sdk.NewDec(0), pool.LooseTokens))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveBondedTokens(t *testing.T) {
|
func TestRemoveBondedTokens(t *testing.T) {
|
||||||
pool := InitialPool()
|
pool := InitialPool()
|
||||||
pool.LooseTokens = sdk.NewRat(10)
|
pool.LooseTokens = sdk.NewDec(10)
|
||||||
pool.BondedTokens = sdk.NewRat(10)
|
pool.BondedTokens = sdk.NewDec(10)
|
||||||
|
|
||||||
pool = pool.bondedTokensToLoose(sdk.NewRat(5))
|
pool = pool.bondedTokensToLoose(sdk.NewDec(5))
|
||||||
|
|
||||||
require.True(sdk.RatEq(t, sdk.NewRat(5), pool.BondedTokens))
|
require.True(sdk.DecEq(t, sdk.NewDec(5), pool.BondedTokens))
|
||||||
require.True(sdk.RatEq(t, sdk.NewRat(15), pool.LooseTokens))
|
require.True(sdk.DecEq(t, sdk.NewDec(15), pool.LooseTokens))
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,21 +26,21 @@ type Validator struct {
|
||||||
Revoked bool `json:"revoked"` // has the validator been revoked from bonded status?
|
Revoked bool `json:"revoked"` // has the validator been revoked from bonded status?
|
||||||
|
|
||||||
Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded)
|
Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded)
|
||||||
Tokens sdk.Rat `json:"tokens"` // delegated tokens (incl. self-delegation)
|
Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation)
|
||||||
DelegatorShares sdk.Rat `json:"delegator_shares"` // total shares issued to a validator's delegators
|
DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators
|
||||||
|
|
||||||
Description Description `json:"description"` // description terms for the validator
|
Description Description `json:"description"` // description terms for the validator
|
||||||
BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator
|
BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator
|
||||||
BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change
|
BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change
|
||||||
ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer
|
ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer
|
||||||
|
|
||||||
Commission sdk.Rat `json:"commission"` // XXX the commission rate of fees charged to any delegators
|
Commission sdk.Dec `json:"commission"` // XXX the commission rate of fees charged to any delegators
|
||||||
CommissionMax sdk.Rat `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
|
CommissionMax sdk.Dec `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
|
||||||
CommissionChangeRate sdk.Rat `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
|
CommissionChangeRate sdk.Dec `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
|
||||||
CommissionChangeToday sdk.Rat `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
|
CommissionChangeToday sdk.Dec `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
|
||||||
|
|
||||||
// fee related
|
// fee related
|
||||||
LastBondedTokens sdk.Rat `json:"prev_bonded_tokens"` // Previous bonded tokens held
|
LastBondedTokens sdk.Dec `json:"prev_bonded_tokens"` // Previous bonded tokens held
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewValidator - initialize a new validator
|
// NewValidator - initialize a new validator
|
||||||
|
@ -50,17 +50,17 @@ func NewValidator(owner sdk.AccAddress, pubKey crypto.PubKey, description Descri
|
||||||
PubKey: pubKey,
|
PubKey: pubKey,
|
||||||
Revoked: false,
|
Revoked: false,
|
||||||
Status: sdk.Unbonded,
|
Status: sdk.Unbonded,
|
||||||
Tokens: sdk.ZeroRat(),
|
Tokens: sdk.ZeroDec(),
|
||||||
DelegatorShares: sdk.ZeroRat(),
|
DelegatorShares: sdk.ZeroDec(),
|
||||||
Description: description,
|
Description: description,
|
||||||
BondHeight: int64(0),
|
BondHeight: int64(0),
|
||||||
BondIntraTxCounter: int16(0),
|
BondIntraTxCounter: int16(0),
|
||||||
ProposerRewardPool: sdk.Coins{},
|
ProposerRewardPool: sdk.Coins{},
|
||||||
Commission: sdk.ZeroRat(),
|
Commission: sdk.ZeroDec(),
|
||||||
CommissionMax: sdk.ZeroRat(),
|
CommissionMax: sdk.ZeroDec(),
|
||||||
CommissionChangeRate: sdk.ZeroRat(),
|
CommissionChangeRate: sdk.ZeroDec(),
|
||||||
CommissionChangeToday: sdk.ZeroRat(),
|
CommissionChangeToday: sdk.ZeroDec(),
|
||||||
LastBondedTokens: sdk.ZeroRat(),
|
LastBondedTokens: sdk.ZeroDec(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,17 +69,17 @@ type validatorValue struct {
|
||||||
PubKey crypto.PubKey
|
PubKey crypto.PubKey
|
||||||
Revoked bool
|
Revoked bool
|
||||||
Status sdk.BondStatus
|
Status sdk.BondStatus
|
||||||
Tokens sdk.Rat
|
Tokens sdk.Dec
|
||||||
DelegatorShares sdk.Rat
|
DelegatorShares sdk.Dec
|
||||||
Description Description
|
Description Description
|
||||||
BondHeight int64
|
BondHeight int64
|
||||||
BondIntraTxCounter int16
|
BondIntraTxCounter int16
|
||||||
ProposerRewardPool sdk.Coins
|
ProposerRewardPool sdk.Coins
|
||||||
Commission sdk.Rat
|
Commission sdk.Dec
|
||||||
CommissionMax sdk.Rat
|
CommissionMax sdk.Dec
|
||||||
CommissionChangeRate sdk.Rat
|
CommissionChangeRate sdk.Dec
|
||||||
CommissionChangeToday sdk.Rat
|
CommissionChangeToday sdk.Dec
|
||||||
LastBondedTokens sdk.Rat
|
LastBondedTokens sdk.Dec
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the redelegation without fields contained within the key for the store
|
// return the redelegation without fields contained within the key for the store
|
||||||
|
@ -159,8 +159,8 @@ func (v Validator) HumanReadableString() (string, error) {
|
||||||
resp += fmt.Sprintf("Validator: %s\n", bechVal)
|
resp += fmt.Sprintf("Validator: %s\n", bechVal)
|
||||||
resp += fmt.Sprintf("Revoked: %v\n", v.Revoked)
|
resp += fmt.Sprintf("Revoked: %v\n", v.Revoked)
|
||||||
resp += fmt.Sprintf("Status: %s\n", sdk.BondStatusToString(v.Status))
|
resp += fmt.Sprintf("Status: %s\n", sdk.BondStatusToString(v.Status))
|
||||||
resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.FloatString())
|
resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.String())
|
||||||
resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares.FloatString())
|
resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares.String())
|
||||||
resp += fmt.Sprintf("Description: %s\n", v.Description)
|
resp += fmt.Sprintf("Description: %s\n", v.Description)
|
||||||
resp += fmt.Sprintf("Bond Height: %d\n", v.BondHeight)
|
resp += fmt.Sprintf("Bond Height: %d\n", v.BondHeight)
|
||||||
resp += fmt.Sprintf("Proposer Reward Pool: %s\n", v.ProposerRewardPool.String())
|
resp += fmt.Sprintf("Proposer Reward Pool: %s\n", v.ProposerRewardPool.String())
|
||||||
|
@ -182,21 +182,21 @@ type BechValidator struct {
|
||||||
Revoked bool `json:"revoked"` // has the validator been revoked from bonded status?
|
Revoked bool `json:"revoked"` // has the validator been revoked from bonded status?
|
||||||
|
|
||||||
Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded)
|
Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded)
|
||||||
Tokens sdk.Rat `json:"tokens"` // delegated tokens (incl. self-delegation)
|
Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation)
|
||||||
DelegatorShares sdk.Rat `json:"delegator_shares"` // total shares issued to a validator's delegators
|
DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators
|
||||||
|
|
||||||
Description Description `json:"description"` // description terms for the validator
|
Description Description `json:"description"` // description terms for the validator
|
||||||
BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator
|
BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator
|
||||||
BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change
|
BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change
|
||||||
ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer
|
ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer
|
||||||
|
|
||||||
Commission sdk.Rat `json:"commission"` // XXX the commission rate of fees charged to any delegators
|
Commission sdk.Dec `json:"commission"` // XXX the commission rate of fees charged to any delegators
|
||||||
CommissionMax sdk.Rat `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
|
CommissionMax sdk.Dec `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
|
||||||
CommissionChangeRate sdk.Rat `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
|
CommissionChangeRate sdk.Dec `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
|
||||||
CommissionChangeToday sdk.Rat `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
|
CommissionChangeToday sdk.Dec `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
|
||||||
|
|
||||||
// fee related
|
// fee related
|
||||||
LastBondedTokens sdk.Rat `json:"prev_bonded_shares"` // last bonded token amount
|
LastBondedTokens sdk.Dec `json:"prev_bonded_shares"` // last bonded token amount
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the bech validator from the the regular validator
|
// get the bech validator from the the regular validator
|
||||||
|
@ -364,7 +364,7 @@ func (v Validator) UpdateStatus(pool Pool, NewStatus sdk.BondStatus) (Validator,
|
||||||
}
|
}
|
||||||
|
|
||||||
// removes tokens from a validator
|
// removes tokens from a validator
|
||||||
func (v Validator) RemoveTokens(pool Pool, tokens sdk.Rat) (Validator, Pool) {
|
func (v Validator) RemoveTokens(pool Pool, tokens sdk.Dec) (Validator, Pool) {
|
||||||
if v.Status == sdk.Bonded {
|
if v.Status == sdk.Bonded {
|
||||||
pool = pool.bondedTokensToLoose(tokens)
|
pool = pool.bondedTokensToLoose(tokens)
|
||||||
}
|
}
|
||||||
|
@ -376,25 +376,25 @@ func (v Validator) RemoveTokens(pool Pool, tokens sdk.Rat) (Validator, Pool) {
|
||||||
//_________________________________________________________________________________________________________
|
//_________________________________________________________________________________________________________
|
||||||
|
|
||||||
// AddTokensFromDel adds tokens to a validator
|
// AddTokensFromDel adds tokens to a validator
|
||||||
func (v Validator) AddTokensFromDel(pool Pool, amount int64) (Validator, Pool, sdk.Rat) {
|
func (v Validator) AddTokensFromDel(pool Pool, amount int64) (Validator, Pool, sdk.Dec) {
|
||||||
|
|
||||||
// bondedShare/delegatedShare
|
// bondedShare/delegatedShare
|
||||||
exRate := v.DelegatorShareExRate()
|
exRate := v.DelegatorShareExRate()
|
||||||
amountRat := sdk.NewRat(amount)
|
amountDec := sdk.NewDec(amount)
|
||||||
|
|
||||||
if v.Status == sdk.Bonded {
|
if v.Status == sdk.Bonded {
|
||||||
pool = pool.looseTokensToBonded(amountRat)
|
pool = pool.looseTokensToBonded(amountDec)
|
||||||
}
|
}
|
||||||
|
|
||||||
v.Tokens = v.Tokens.Add(amountRat)
|
v.Tokens = v.Tokens.Add(amountDec)
|
||||||
issuedShares := amountRat.Quo(exRate)
|
issuedShares := amountDec.Quo(exRate)
|
||||||
v.DelegatorShares = v.DelegatorShares.Add(issuedShares)
|
v.DelegatorShares = v.DelegatorShares.Add(issuedShares)
|
||||||
|
|
||||||
return v, pool, issuedShares
|
return v, pool, issuedShares
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveDelShares removes delegator shares from a validator.
|
// RemoveDelShares removes delegator shares from a validator.
|
||||||
func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Rat) (Validator, Pool, sdk.Rat) {
|
func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Dec) (Validator, Pool, sdk.Dec) {
|
||||||
issuedTokens := v.DelegatorShareExRate().Mul(delShares)
|
issuedTokens := v.DelegatorShareExRate().Mul(delShares)
|
||||||
v.Tokens = v.Tokens.Sub(issuedTokens)
|
v.Tokens = v.Tokens.Sub(issuedTokens)
|
||||||
v.DelegatorShares = v.DelegatorShares.Sub(delShares)
|
v.DelegatorShares = v.DelegatorShares.Sub(delShares)
|
||||||
|
@ -408,19 +408,19 @@ func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Rat) (Validator, Poo
|
||||||
|
|
||||||
// DelegatorShareExRate gets the exchange rate of tokens over delegator shares.
|
// DelegatorShareExRate gets the exchange rate of tokens over delegator shares.
|
||||||
// UNITS: tokens/delegator-shares
|
// UNITS: tokens/delegator-shares
|
||||||
func (v Validator) DelegatorShareExRate() sdk.Rat {
|
func (v Validator) DelegatorShareExRate() sdk.Dec {
|
||||||
if v.DelegatorShares.IsZero() {
|
if v.DelegatorShares.IsZero() {
|
||||||
return sdk.OneRat()
|
return sdk.OneDec()
|
||||||
}
|
}
|
||||||
return v.Tokens.Quo(v.DelegatorShares)
|
return v.Tokens.Quo(v.DelegatorShares)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the bonded tokens which the validator holds
|
// Get the bonded tokens which the validator holds
|
||||||
func (v Validator) BondedTokens() sdk.Rat {
|
func (v Validator) BondedTokens() sdk.Dec {
|
||||||
if v.Status == sdk.Bonded {
|
if v.Status == sdk.Bonded {
|
||||||
return v.Tokens
|
return v.Tokens
|
||||||
}
|
}
|
||||||
return sdk.ZeroRat()
|
return sdk.ZeroDec()
|
||||||
}
|
}
|
||||||
|
|
||||||
//______________________________________________________________________
|
//______________________________________________________________________
|
||||||
|
@ -434,7 +434,7 @@ func (v Validator) GetMoniker() string { return v.Description.Moniker }
|
||||||
func (v Validator) GetStatus() sdk.BondStatus { return v.Status }
|
func (v Validator) GetStatus() sdk.BondStatus { return v.Status }
|
||||||
func (v Validator) GetOwner() sdk.AccAddress { return v.Owner }
|
func (v Validator) GetOwner() sdk.AccAddress { return v.Owner }
|
||||||
func (v Validator) GetPubKey() crypto.PubKey { return v.PubKey }
|
func (v Validator) GetPubKey() crypto.PubKey { return v.PubKey }
|
||||||
func (v Validator) GetPower() sdk.Rat { return v.BondedTokens() }
|
func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() }
|
||||||
func (v Validator) GetTokens() sdk.Rat { return v.Tokens }
|
func (v Validator) GetTokens() sdk.Dec { return v.Tokens }
|
||||||
func (v Validator) GetDelegatorShares() sdk.Rat { return v.DelegatorShares }
|
func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares }
|
||||||
func (v Validator) GetBondHeight() int64 { return v.BondHeight }
|
func (v Validator) GetBondHeight() int64 { return v.BondHeight }
|
||||||
|
|
|
@ -75,19 +75,19 @@ func TestRemoveTokens(t *testing.T) {
|
||||||
Owner: addr1,
|
Owner: addr1,
|
||||||
PubKey: pk1,
|
PubKey: pk1,
|
||||||
Status: sdk.Bonded,
|
Status: sdk.Bonded,
|
||||||
Tokens: sdk.NewRat(100),
|
Tokens: sdk.NewDec(100),
|
||||||
DelegatorShares: sdk.NewRat(100),
|
DelegatorShares: sdk.NewDec(100),
|
||||||
}
|
}
|
||||||
|
|
||||||
pool := InitialPool()
|
pool := InitialPool()
|
||||||
pool.LooseTokens = sdk.NewRat(10)
|
pool.LooseTokens = sdk.NewDec(10)
|
||||||
pool.BondedTokens = validator.BondedTokens()
|
pool.BondedTokens = validator.BondedTokens()
|
||||||
|
|
||||||
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
||||||
require.Equal(t, sdk.Bonded, validator.Status)
|
require.Equal(t, sdk.Bonded, validator.Status)
|
||||||
|
|
||||||
// remove tokens and test check everything
|
// remove tokens and test check everything
|
||||||
validator, pool = validator.RemoveTokens(pool, sdk.NewRat(10))
|
validator, pool = validator.RemoveTokens(pool, sdk.NewDec(10))
|
||||||
require.Equal(t, int64(90), validator.Tokens.RoundInt64())
|
require.Equal(t, int64(90), validator.Tokens.RoundInt64())
|
||||||
require.Equal(t, int64(90), pool.BondedTokens.RoundInt64())
|
require.Equal(t, int64(90), pool.BondedTokens.RoundInt64())
|
||||||
require.Equal(t, int64(20), pool.LooseTokens.RoundInt64())
|
require.Equal(t, int64(20), pool.LooseTokens.RoundInt64())
|
||||||
|
@ -98,7 +98,7 @@ func TestRemoveTokens(t *testing.T) {
|
||||||
require.Equal(t, int64(0), pool.BondedTokens.RoundInt64())
|
require.Equal(t, int64(0), pool.BondedTokens.RoundInt64())
|
||||||
require.Equal(t, int64(110), pool.LooseTokens.RoundInt64())
|
require.Equal(t, int64(110), pool.LooseTokens.RoundInt64())
|
||||||
|
|
||||||
validator, pool = validator.RemoveTokens(pool, sdk.NewRat(10))
|
validator, pool = validator.RemoveTokens(pool, sdk.NewDec(10))
|
||||||
require.Equal(t, int64(80), validator.Tokens.RoundInt64())
|
require.Equal(t, int64(80), validator.Tokens.RoundInt64())
|
||||||
require.Equal(t, int64(0), pool.BondedTokens.RoundInt64())
|
require.Equal(t, int64(0), pool.BondedTokens.RoundInt64())
|
||||||
require.Equal(t, int64(110), pool.LooseTokens.RoundInt64())
|
require.Equal(t, int64(110), pool.LooseTokens.RoundInt64())
|
||||||
|
@ -106,43 +106,43 @@ func TestRemoveTokens(t *testing.T) {
|
||||||
|
|
||||||
func TestAddTokensValidatorBonded(t *testing.T) {
|
func TestAddTokensValidatorBonded(t *testing.T) {
|
||||||
pool := InitialPool()
|
pool := InitialPool()
|
||||||
pool.LooseTokens = sdk.NewRat(10)
|
pool.LooseTokens = sdk.NewDec(10)
|
||||||
validator := NewValidator(addr1, pk1, Description{})
|
validator := NewValidator(addr1, pk1, Description{})
|
||||||
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
||||||
validator, pool, delShares := validator.AddTokensFromDel(pool, 10)
|
validator, pool, delShares := validator.AddTokensFromDel(pool, 10)
|
||||||
|
|
||||||
require.Equal(t, sdk.OneRat(), validator.DelegatorShareExRate())
|
require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate())
|
||||||
|
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), delShares))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), delShares))
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens()))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddTokensValidatorUnbonding(t *testing.T) {
|
func TestAddTokensValidatorUnbonding(t *testing.T) {
|
||||||
pool := InitialPool()
|
pool := InitialPool()
|
||||||
pool.LooseTokens = sdk.NewRat(10)
|
pool.LooseTokens = sdk.NewDec(10)
|
||||||
validator := NewValidator(addr1, pk1, Description{})
|
validator := NewValidator(addr1, pk1, Description{})
|
||||||
validator, pool = validator.UpdateStatus(pool, sdk.Unbonding)
|
validator, pool = validator.UpdateStatus(pool, sdk.Unbonding)
|
||||||
validator, pool, delShares := validator.AddTokensFromDel(pool, 10)
|
validator, pool, delShares := validator.AddTokensFromDel(pool, 10)
|
||||||
|
|
||||||
require.Equal(t, sdk.OneRat(), validator.DelegatorShareExRate())
|
require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate())
|
||||||
|
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), delShares))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), delShares))
|
||||||
assert.Equal(t, sdk.Unbonding, validator.Status)
|
assert.Equal(t, sdk.Unbonding, validator.Status)
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddTokensValidatorUnbonded(t *testing.T) {
|
func TestAddTokensValidatorUnbonded(t *testing.T) {
|
||||||
pool := InitialPool()
|
pool := InitialPool()
|
||||||
pool.LooseTokens = sdk.NewRat(10)
|
pool.LooseTokens = sdk.NewDec(10)
|
||||||
validator := NewValidator(addr1, pk1, Description{})
|
validator := NewValidator(addr1, pk1, Description{})
|
||||||
validator, pool = validator.UpdateStatus(pool, sdk.Unbonded)
|
validator, pool = validator.UpdateStatus(pool, sdk.Unbonded)
|
||||||
validator, pool, delShares := validator.AddTokensFromDel(pool, 10)
|
validator, pool, delShares := validator.AddTokensFromDel(pool, 10)
|
||||||
|
|
||||||
require.Equal(t, sdk.OneRat(), validator.DelegatorShareExRate())
|
require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate())
|
||||||
|
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), delShares))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), delShares))
|
||||||
assert.Equal(t, sdk.Unbonded, validator.Status)
|
assert.Equal(t, sdk.Unbonded, validator.Status)
|
||||||
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO refactor to make simpler like the AddToken tests above
|
// TODO refactor to make simpler like the AddToken tests above
|
||||||
|
@ -151,16 +151,16 @@ func TestRemoveDelShares(t *testing.T) {
|
||||||
Owner: addr1,
|
Owner: addr1,
|
||||||
PubKey: pk1,
|
PubKey: pk1,
|
||||||
Status: sdk.Bonded,
|
Status: sdk.Bonded,
|
||||||
Tokens: sdk.NewRat(100),
|
Tokens: sdk.NewDec(100),
|
||||||
DelegatorShares: sdk.NewRat(100),
|
DelegatorShares: sdk.NewDec(100),
|
||||||
}
|
}
|
||||||
poolA := InitialPool()
|
poolA := InitialPool()
|
||||||
poolA.LooseTokens = sdk.NewRat(10)
|
poolA.LooseTokens = sdk.NewDec(10)
|
||||||
poolA.BondedTokens = valA.BondedTokens()
|
poolA.BondedTokens = valA.BondedTokens()
|
||||||
require.Equal(t, valA.DelegatorShareExRate(), sdk.OneRat())
|
require.Equal(t, valA.DelegatorShareExRate(), sdk.OneDec())
|
||||||
|
|
||||||
// Remove delegator shares
|
// Remove delegator shares
|
||||||
valB, poolB, coinsB := valA.RemoveDelShares(poolA, sdk.NewRat(10))
|
valB, poolB, coinsB := valA.RemoveDelShares(poolA, sdk.NewDec(10))
|
||||||
assert.Equal(t, int64(10), coinsB.RoundInt64())
|
assert.Equal(t, int64(10), coinsB.RoundInt64())
|
||||||
assert.Equal(t, int64(90), valB.DelegatorShares.RoundInt64())
|
assert.Equal(t, int64(90), valB.DelegatorShares.RoundInt64())
|
||||||
assert.Equal(t, int64(90), valB.BondedTokens().RoundInt64())
|
assert.Equal(t, int64(90), valB.BondedTokens().RoundInt64())
|
||||||
|
@ -168,13 +168,13 @@ func TestRemoveDelShares(t *testing.T) {
|
||||||
assert.Equal(t, int64(20), poolB.LooseTokens.RoundInt64())
|
assert.Equal(t, int64(20), poolB.LooseTokens.RoundInt64())
|
||||||
|
|
||||||
// conservation of tokens
|
// conservation of tokens
|
||||||
require.True(sdk.RatEq(t,
|
require.True(sdk.DecEq(t,
|
||||||
poolB.LooseTokens.Add(poolB.BondedTokens),
|
poolB.LooseTokens.Add(poolB.BondedTokens),
|
||||||
poolA.LooseTokens.Add(poolA.BondedTokens)))
|
poolA.LooseTokens.Add(poolA.BondedTokens)))
|
||||||
|
|
||||||
// specific case from random tests
|
// specific case from random tests
|
||||||
poolTokens := sdk.NewRat(5102)
|
poolTokens := sdk.NewDec(5102)
|
||||||
delShares := sdk.NewRat(115)
|
delShares := sdk.NewDec(115)
|
||||||
validator := Validator{
|
validator := Validator{
|
||||||
Owner: addr1,
|
Owner: addr1,
|
||||||
PubKey: pk1,
|
PubKey: pk1,
|
||||||
|
@ -183,22 +183,27 @@ func TestRemoveDelShares(t *testing.T) {
|
||||||
DelegatorShares: delShares,
|
DelegatorShares: delShares,
|
||||||
}
|
}
|
||||||
pool := Pool{
|
pool := Pool{
|
||||||
BondedTokens: sdk.NewRat(248305),
|
BondedTokens: sdk.NewDec(248305),
|
||||||
LooseTokens: sdk.NewRat(232147),
|
LooseTokens: sdk.NewDec(232147),
|
||||||
InflationLastTime: time.Unix(0, 0),
|
InflationLastTime: time.Unix(0, 0),
|
||||||
Inflation: sdk.NewRat(7, 100),
|
Inflation: sdk.NewDecWithPrec(7, 2),
|
||||||
}
|
}
|
||||||
shares := sdk.NewRat(29)
|
shares := sdk.NewDec(29)
|
||||||
_, newPool, tokens := validator.RemoveDelShares(pool, shares)
|
_, newPool, tokens := validator.RemoveDelShares(pool, shares)
|
||||||
require.True(sdk.RatEq(t, sdk.NewRat(147958, 115), tokens))
|
|
||||||
require.True(sdk.RatEq(t,
|
exp, err := sdk.NewDecFromStr("1286.5913043477")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.True(sdk.DecEq(t, exp, tokens))
|
||||||
|
|
||||||
|
require.True(sdk.DecEq(t,
|
||||||
newPool.LooseTokens.Add(newPool.BondedTokens),
|
newPool.LooseTokens.Add(newPool.BondedTokens),
|
||||||
pool.LooseTokens.Add(pool.BondedTokens)))
|
pool.LooseTokens.Add(pool.BondedTokens)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateStatus(t *testing.T) {
|
func TestUpdateStatus(t *testing.T) {
|
||||||
pool := InitialPool()
|
pool := InitialPool()
|
||||||
pool.LooseTokens = sdk.NewRat(100)
|
pool.LooseTokens = sdk.NewDec(100)
|
||||||
|
|
||||||
validator := NewValidator(addr1, pk1, Description{})
|
validator := NewValidator(addr1, pk1, Description{})
|
||||||
validator, pool, _ = validator.AddTokensFromDel(pool, 100)
|
validator, pool, _ = validator.AddTokensFromDel(pool, 100)
|
||||||
|
@ -221,8 +226,8 @@ func TestUpdateStatus(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPossibleOverflow(t *testing.T) {
|
func TestPossibleOverflow(t *testing.T) {
|
||||||
poolTokens := sdk.NewRat(2159)
|
poolTokens := sdk.NewDec(2159)
|
||||||
delShares := sdk.NewRat(391432570689183511).Quo(sdk.NewRat(40113011844664))
|
delShares := sdk.NewDec(391432570689183511).Quo(sdk.NewDec(40113011844664))
|
||||||
validator := Validator{
|
validator := Validator{
|
||||||
Owner: addr1,
|
Owner: addr1,
|
||||||
PubKey: pk1,
|
PubKey: pk1,
|
||||||
|
@ -231,17 +236,17 @@ func TestPossibleOverflow(t *testing.T) {
|
||||||
DelegatorShares: delShares,
|
DelegatorShares: delShares,
|
||||||
}
|
}
|
||||||
pool := Pool{
|
pool := Pool{
|
||||||
LooseTokens: sdk.NewRat(100),
|
LooseTokens: sdk.NewDec(100),
|
||||||
BondedTokens: poolTokens,
|
BondedTokens: poolTokens,
|
||||||
InflationLastTime: time.Unix(0, 0),
|
InflationLastTime: time.Unix(0, 0),
|
||||||
Inflation: sdk.NewRat(7, 100),
|
Inflation: sdk.NewDecWithPrec(7, 2),
|
||||||
}
|
}
|
||||||
tokens := int64(71)
|
tokens := int64(71)
|
||||||
msg := fmt.Sprintf("validator %#v", validator)
|
msg := fmt.Sprintf("validator %#v", validator)
|
||||||
newValidator, _, _ := validator.AddTokensFromDel(pool, tokens)
|
newValidator, _, _ := validator.AddTokensFromDel(pool, tokens)
|
||||||
|
|
||||||
msg = fmt.Sprintf("Added %d tokens to %s", tokens, msg)
|
msg = fmt.Sprintf("Added %d tokens to %s", tokens, msg)
|
||||||
require.False(t, newValidator.DelegatorShareExRate().LT(sdk.ZeroRat()),
|
require.False(t, newValidator.DelegatorShareExRate().LT(sdk.ZeroDec()),
|
||||||
"Applying operation \"%s\" resulted in negative DelegatorShareExRate(): %v",
|
"Applying operation \"%s\" resulted in negative DelegatorShareExRate(): %v",
|
||||||
msg, newValidator.DelegatorShareExRate())
|
msg, newValidator.DelegatorShareExRate())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue