Merge PR #1233: Inflation now unbonded
working debug fix add broken test fix testnet bug updated provision test changelog cwgoes comments
This commit is contained in:
parent
ef2e7a5129
commit
83c1183e25
@ -12,8 +12,10 @@ IMPROVEMENTS
|
||||
* [tests] Application module tests now use a mock application
|
||||
* [gaiacli] Fix error message when account isn't found when running gaiacli account
|
||||
* [lcd] refactored to eliminate use of global variables, and interdependent tests
|
||||
* [x/stake] More stake tests added to test ByPower index
|
||||
|
||||
FIXES
|
||||
* [x/stake] bonded inflation removed, non-bonded inflation partially implemented
|
||||
* [lcd] Switch to bech32 for addresses on all human readable inputs and outputs
|
||||
* [lcd] fixed tx indexing/querying
|
||||
* [cli] Added `--gas` flag to specify transaction gas limit
|
||||
|
||||
@ -33,6 +33,78 @@ func newTestMsgDelegate(delegatorAddr, validatorAddr sdk.Address, amt int64) Msg
|
||||
|
||||
//______________________________________________________________________
|
||||
|
||||
func TestValidatorByPowerIndex(t *testing.T) {
|
||||
validatorAddr, validatorAddr3 := addrs[0], addrs[1]
|
||||
|
||||
initBond := int64(1000000)
|
||||
initBondStr := "1000"
|
||||
ctx, _, keeper := createTestInput(t, false, initBond)
|
||||
|
||||
// create validator
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, pks[0], initBond)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
assert.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
||||
|
||||
// verify the self-delegation exists
|
||||
bond, found := keeper.GetDelegation(ctx, validatorAddr, validatorAddr)
|
||||
require.True(t, found)
|
||||
gotBond := bond.Shares.Evaluate()
|
||||
require.Equal(t, initBond, gotBond,
|
||||
"initBond: %v\ngotBond: %v\nbond: %v\n",
|
||||
initBond, gotBond, bond)
|
||||
|
||||
// verify that the by power index exists
|
||||
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
||||
require.True(t, found)
|
||||
pool := keeper.GetPool(ctx)
|
||||
power := GetValidatorsByPowerKey(validator, pool)
|
||||
require.True(t, keeper.validatorByPowerIndexExists(ctx, power))
|
||||
|
||||
// create a second validator keep it bonded
|
||||
msgCreateValidator = newTestMsgCreateValidator(validatorAddr3, pks[2], int64(1000000))
|
||||
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
assert.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
||||
|
||||
// slash and revoke the first validator
|
||||
keeper.Slash(ctx, pks[0], 0, sdk.NewRat(1, 2))
|
||||
keeper.Revoke(ctx, pks[0])
|
||||
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
||||
require.True(t, found)
|
||||
require.Equal(t, sdk.Unbonded, validator.PoolShares.Status) // ensure is unbonded
|
||||
require.Equal(t, int64(500000), validator.PoolShares.Amount.Evaluate()) // ensure is unbonded
|
||||
|
||||
// the old power record should have been deleted as the power changed
|
||||
assert.False(t, keeper.validatorByPowerIndexExists(ctx, power))
|
||||
|
||||
// but the new power record should have been created
|
||||
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
||||
require.True(t, found)
|
||||
pool = keeper.GetPool(ctx)
|
||||
power2 := GetValidatorsByPowerKey(validator, pool)
|
||||
require.True(t, keeper.validatorByPowerIndexExists(ctx, power2))
|
||||
|
||||
// inflate a bunch
|
||||
for i := 0; i < 20000; i++ {
|
||||
pool = keeper.processProvisions(ctx)
|
||||
keeper.setPool(ctx, pool)
|
||||
}
|
||||
|
||||
// now the new record power index should be the same as the original record
|
||||
power3 := GetValidatorsByPowerKey(validator, pool)
|
||||
assert.Equal(t, power2, power3)
|
||||
|
||||
// unbond self-delegation
|
||||
msgUnbond := NewMsgUnbond(validatorAddr, validatorAddr, "MAX")
|
||||
got = handleMsgUnbond(ctx, msgUnbond, keeper)
|
||||
assert.True(t, got.IsOK(),
|
||||
"got: %v\nmsgUnbond: %v\ninitBondStr: %v\n", got, msgUnbond, initBondStr)
|
||||
|
||||
// verify that by power key nolonger exists
|
||||
_, found = keeper.GetValidator(ctx, validatorAddr)
|
||||
require.False(t, found)
|
||||
assert.False(t, keeper.validatorByPowerIndexExists(ctx, power3))
|
||||
}
|
||||
|
||||
func TestDuplicatesMsgCreateValidator(t *testing.T) {
|
||||
ctx, _, keeper := createTestInput(t, false, 1000)
|
||||
|
||||
@ -42,6 +114,7 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) {
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
assert.True(t, got.IsOK(), "%v", got)
|
||||
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
||||
|
||||
require.True(t, found)
|
||||
assert.Equal(t, sdk.Bonded, validator.Status())
|
||||
assert.Equal(t, validatorAddr, validator.Owner)
|
||||
|
||||
@ -22,7 +22,9 @@ func (k Keeper) processProvisions(ctx sdk.Context) Pool {
|
||||
// which needs to be updated is the `BondedPool`. So for each previsions cycle:
|
||||
|
||||
provisions := pool.Inflation.Mul(sdk.NewRat(pool.TokenSupply())).Quo(hrsPerYrRat).Evaluate()
|
||||
pool.BondedTokens += provisions
|
||||
|
||||
// TODO add to the fees provisions
|
||||
pool.LooseUnbondedTokens += provisions
|
||||
return pool
|
||||
}
|
||||
|
||||
|
||||
@ -74,8 +74,6 @@ func TestProcessProvisions(t *testing.T) {
|
||||
initialBondedTokens int64 = 250000000
|
||||
initialUnbondedTokens int64 = 300000000
|
||||
cumulativeExpProvs int64
|
||||
initialBondedShares = sdk.NewRat(250000000, 1)
|
||||
initialUnbondedShares = sdk.NewRat(300000000, 1)
|
||||
validatorTokens = []int64{150000000, 100000000, 100000000, 100000000, 100000000}
|
||||
bondedValidators uint16 = 2
|
||||
)
|
||||
@ -93,9 +91,7 @@ func TestProcessProvisions(t *testing.T) {
|
||||
|
||||
//get the pool and do the final value checks from checkFinalPoolValues
|
||||
pool = keeper.GetPool(ctx)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens,
|
||||
initialUnbondedTokens, cumulativeExpProvs,
|
||||
0, 0, initialBondedShares, initialUnbondedShares)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens, cumulativeExpProvs)
|
||||
}
|
||||
|
||||
// Tests that the hourly rate of change of inflation will be positive, negative, or zero, depending on bonded ratio and inflation rate
|
||||
@ -109,8 +105,6 @@ func TestHourlyInflationRateOfChange(t *testing.T) {
|
||||
initialBondedTokens int64 = 150000000
|
||||
initialUnbondedTokens int64 = 400000000
|
||||
cumulativeExpProvs int64
|
||||
bondedShares = sdk.NewRat(150000000, 1)
|
||||
unbondedShares = sdk.NewRat(400000000, 1)
|
||||
validatorTokens = []int64{150000000, 100000000, 100000000, 100000000, 100000000}
|
||||
bondedValidators uint16 = 1
|
||||
)
|
||||
@ -131,9 +125,7 @@ func TestHourlyInflationRateOfChange(t *testing.T) {
|
||||
|
||||
// Final check that the pool equals initial values + cumulative provisions and adjustments we recorded
|
||||
pool = keeper.GetPool(ctx)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens,
|
||||
initialUnbondedTokens, cumulativeExpProvs,
|
||||
0, 0, bondedShares, unbondedShares)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens, cumulativeExpProvs)
|
||||
}
|
||||
|
||||
//Test that a large unbonding will significantly lower the bonded ratio
|
||||
@ -181,9 +173,7 @@ func TestLargeUnbond(t *testing.T) {
|
||||
|
||||
// Final check that the pool equals initial values + provisions and adjustments we recorded
|
||||
pool = keeper.GetPool(ctx)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens,
|
||||
initialUnbondedTokens, expProvisionsAfter,
|
||||
-val0UnbondedTokens, val0UnbondedTokens, bondedShares, unbondedShares)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens, expProvisionsAfter)
|
||||
}
|
||||
|
||||
//Test that a large bonding will significantly increase the bonded ratio
|
||||
@ -192,12 +182,9 @@ func TestLargeBond(t *testing.T) {
|
||||
pool := keeper.GetPool(ctx)
|
||||
|
||||
var (
|
||||
initialTotalTokens int64 = 1600000000
|
||||
initialBondedTokens int64 = 400000000
|
||||
initialUnbondedTokens int64 = 1200000000
|
||||
val9UnbondedTokens int64 = 400000000
|
||||
val9BondedTokens int64
|
||||
bondedShares = sdk.NewRat(400000000, 1)
|
||||
initialTotalTokens int64 = 1600000000
|
||||
initialBondedTokens int64 = 400000000
|
||||
initialUnbondedTokens int64 = 1200000000
|
||||
unbondedShares = sdk.NewRat(1200000000, 1)
|
||||
unbondedSharesVal9 = sdk.NewRat(400000000, 1)
|
||||
validatorTokens = []int64{400000000, 100000000, 100000000, 100000000, 100000000, 100000000, 100000000, 100000000, 100000000, 400000000}
|
||||
@ -225,10 +212,6 @@ func TestLargeBond(t *testing.T) {
|
||||
// process provisions after the bonding, to compare the difference in expProvisions and expInflation
|
||||
_, expProvisionsAfter, pool := updateProvisions(t, keeper, pool, ctx, 0)
|
||||
unbondedShares = unbondedShares.Sub(unbondedSharesVal9)
|
||||
val9BondedTokens = val9UnbondedTokens
|
||||
val9UnbondedTokens = 0
|
||||
bondedTokens := initialBondedTokens + val9BondedTokens + expProvisionsAfter
|
||||
bondedShares = sdk.NewRat(bondedTokens, 1).Quo(pool.bondedShareExRate())
|
||||
|
||||
// unbonded shares should decrease
|
||||
assert.True(t, unbondedShares.LT(sdk.NewRat(1200000000, 1)))
|
||||
@ -237,9 +220,7 @@ func TestLargeBond(t *testing.T) {
|
||||
// Final check that the pool equals initial values + provisions and adjustments we recorded
|
||||
pool = keeper.GetPool(ctx)
|
||||
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens,
|
||||
initialUnbondedTokens, expProvisionsAfter,
|
||||
val9BondedTokens, -val9BondedTokens, bondedShares, unbondedShares)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens, expProvisionsAfter)
|
||||
}
|
||||
|
||||
// Tests that inflation increases or decreases as expected when we do a random operation on 20 different validators
|
||||
@ -296,30 +277,13 @@ func TestInflationWithRandomOperations(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
//_________________________________________________________________________________________
|
||||
////////////////////////////////HELPER FUNCTIONS BELOW/////////////////////////////////////
|
||||
|
||||
// Final check on the global pool values for what the total tokens accumulated from each hour of provisions and other functions
|
||||
// bondedAdjustment and unbondedAdjustment are the accumulated changes for the operations of the test
|
||||
// (i.e. if three unbond operations happened, their total value would be passed as unbondedAdjustment)
|
||||
func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, initialUnbondedTokens,
|
||||
cumulativeExpProvs, bondedAdjustment, unbondedAdjustment int64, bondedShares, unbondedShares sdk.Rat) {
|
||||
|
||||
initialBonded := initialTotalTokens - initialUnbondedTokens
|
||||
// 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 int64) {
|
||||
calculatedTotalTokens := initialTotalTokens + cumulativeExpProvs
|
||||
calculatedBondedTokens := initialBonded + cumulativeExpProvs + bondedAdjustment
|
||||
calculatedUnbondedTokens := initialUnbondedTokens + unbondedAdjustment
|
||||
|
||||
// test that the bonded ratio the pool has is equal to what we calculated for tokens
|
||||
assert.True(t, pool.bondedRatio().Equal(sdk.NewRat(calculatedBondedTokens, calculatedTotalTokens)), "%v", pool.bondedRatio())
|
||||
|
||||
// test global supply
|
||||
assert.Equal(t, calculatedTotalTokens, pool.TokenSupply())
|
||||
assert.Equal(t, calculatedBondedTokens, pool.BondedTokens)
|
||||
assert.Equal(t, calculatedUnbondedTokens, pool.UnbondedTokens)
|
||||
|
||||
// test the value of validator shares
|
||||
assert.True(t, pool.bondedShareExRate().Mul(bondedShares).Equal(sdk.NewRat(calculatedBondedTokens)), "%v", pool.bondedShareExRate())
|
||||
assert.True(t, pool.unbondedShareExRate().Mul(unbondedShares).Equal(sdk.NewRat(calculatedUnbondedTokens)), "%v", pool.unbondedShareExRate())
|
||||
}
|
||||
|
||||
// Processes provisions are added to the pool correctly every hour
|
||||
@ -327,13 +291,11 @@ func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, initialUn
|
||||
func updateProvisions(t *testing.T, keeper Keeper, pool Pool, ctx sdk.Context, hr int) (sdk.Rat, int64, Pool) {
|
||||
expInflation := keeper.nextInflation(ctx)
|
||||
expProvisions := (expInflation.Mul(sdk.NewRat(pool.TokenSupply())).Quo(hrsPerYrRat)).Evaluate()
|
||||
startBondedPool := pool.BondedTokens
|
||||
startTotalSupply := pool.TokenSupply()
|
||||
pool = keeper.processProvisions(ctx)
|
||||
keeper.setPool(ctx, pool)
|
||||
|
||||
//check provisions were added to pool
|
||||
require.Equal(t, startBondedPool+expProvisions, pool.BondedTokens, "hr %v", hr)
|
||||
require.Equal(t, startTotalSupply+expProvisions, pool.TokenSupply())
|
||||
|
||||
return expInflation, expProvisions, pool
|
||||
@ -405,5 +367,4 @@ func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation
|
||||
assert.Equal(t, true, inflationChange.LT(sdk.ZeroRat()), msg)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -78,6 +78,12 @@ func (k Keeper) setValidatorByPowerIndex(ctx sdk.Context, validator Validator, p
|
||||
store.Set(GetValidatorsByPowerKey(validator, pool), validator.Owner)
|
||||
}
|
||||
|
||||
// used in testing
|
||||
func (k Keeper) validatorByPowerIndexExists(ctx sdk.Context, power []byte) bool {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
return store.Get(power) != nil
|
||||
}
|
||||
|
||||
// Get the set of all validators with no limits, used during genesis dump
|
||||
func (k Keeper) getAllValidators(ctx sdk.Context) (validators Validators) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
@ -24,6 +24,47 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func TestUpdateValidatorByPowerIndex(t *testing.T) {
|
||||
ctx, _, keeper := createTestInput(t, false, 0)
|
||||
pool := keeper.GetPool(ctx)
|
||||
|
||||
// create a random pool
|
||||
pool.BondedTokens = 1234
|
||||
pool.BondedShares = sdk.NewRat(124)
|
||||
pool.UnbondingTokens = 13934
|
||||
pool.UnbondingShares = sdk.NewRat(145)
|
||||
pool.UnbondedTokens = 154
|
||||
pool.UnbondedShares = sdk.NewRat(1333)
|
||||
keeper.setPool(ctx, pool)
|
||||
|
||||
// add a validator
|
||||
validator := NewValidator(addrVals[0], pks[0], Description{})
|
||||
validator, pool, delSharesCreated := validator.addTokensFromDel(pool, 100)
|
||||
require.Equal(t, sdk.Unbonded, validator.Status())
|
||||
assert.Equal(t, int64(100), validator.PoolShares.Tokens(pool).Evaluate())
|
||||
keeper.setPool(ctx, pool)
|
||||
keeper.updateValidator(ctx, validator)
|
||||
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
assert.Equal(t, int64(100), validator.PoolShares.Tokens(pool).Evaluate(), "\nvalidator %v\npool %v", validator, pool)
|
||||
|
||||
pool = keeper.GetPool(ctx)
|
||||
power := GetValidatorsByPowerKey(validator, pool)
|
||||
assert.True(t, keeper.validatorByPowerIndexExists(ctx, power))
|
||||
|
||||
// burn half the delegator shares
|
||||
validator, pool, burned := validator.removeDelShares(pool, delSharesCreated.Quo(sdk.NewRat(2)))
|
||||
assert.Equal(t, int64(50), burned)
|
||||
keeper.setPool(ctx, pool) // update the pool
|
||||
keeper.updateValidator(ctx, validator) // update the validator, possibly kicking it out
|
||||
assert.False(t, keeper.validatorByPowerIndexExists(ctx, power))
|
||||
|
||||
pool = keeper.GetPool(ctx)
|
||||
validator, found = keeper.GetValidator(ctx, addrVals[0])
|
||||
power = GetValidatorsByPowerKey(validator, pool)
|
||||
assert.True(t, keeper.validatorByPowerIndexExists(ctx, power))
|
||||
}
|
||||
|
||||
func TestSetValidator(t *testing.T) {
|
||||
ctx, _, keeper := createTestInput(t, false, 0)
|
||||
pool := keeper.GetPool(ctx)
|
||||
|
||||
@ -118,13 +118,14 @@ func (s PoolShares) ToBonded(p Pool) PoolShares {
|
||||
|
||||
//_________________________________________________________________________________________________________
|
||||
|
||||
// TODO better tests
|
||||
// get the equivalent amount of tokens contained by the shares
|
||||
func (s PoolShares) Tokens(p Pool) sdk.Rat {
|
||||
switch s.Status {
|
||||
case sdk.Bonded:
|
||||
return p.unbondedShareExRate().Mul(s.Amount) // (tokens/shares) * shares
|
||||
return p.bondedShareExRate().Mul(s.Amount) // (tokens/shares) * shares
|
||||
case sdk.Unbonding:
|
||||
return p.unbondedShareExRate().Mul(s.Amount)
|
||||
return p.unbondingShareExRate().Mul(s.Amount)
|
||||
case sdk.Unbonded:
|
||||
return p.unbondedShareExRate().Mul(s.Amount)
|
||||
default:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user