Merge PR #3033: Fix negative stake & invariance bug
* Fix negative stake & invariance bug * Merge PR #3037: Updates to negative stake fix * Update invariant; fix lint * Fix linter * Add comment & TODO
This commit is contained in:
parent
2473b74d86
commit
1ba93ea1c1
|
@ -18,7 +18,7 @@ func (app *GaiaApp) runtimeInvariants() []simulation.Invariant {
|
|||
distrsim.ValAccumInvariants(app.distrKeeper, app.stakeKeeper),
|
||||
stakesim.SupplyInvariants(app.bankKeeper, app.stakeKeeper,
|
||||
app.feeCollectionKeeper, app.distrKeeper, app.accountKeeper),
|
||||
stakesim.PositivePowerInvariant(app.stakeKeeper),
|
||||
stakesim.NonNegativePowerInvariant(app.stakeKeeper),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,9 @@ func run(rootDir string) {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer proxyApp.Stop()
|
||||
defer func() {
|
||||
_ = proxyApp.Stop()
|
||||
}()
|
||||
|
||||
var state tmsm.State = tmsm.LoadState(tmDB)
|
||||
if state.LastBlockHeight == 0 {
|
||||
|
|
|
@ -272,6 +272,10 @@ func (d Dec) Format(s fmt.State, verb rune) {
|
|||
}
|
||||
|
||||
func (d Dec) String() string {
|
||||
isNeg := d.IsNegative()
|
||||
if d.IsNegative() {
|
||||
d = d.Neg()
|
||||
}
|
||||
bz, err := d.Int.MarshalText()
|
||||
if err != nil {
|
||||
return ""
|
||||
|
@ -298,6 +302,9 @@ func (d Dec) String() string {
|
|||
bzWDec[inputSize-10] = byte('.')
|
||||
copy(bzWDec[inputSize-9:], bz[inputSize-10:])
|
||||
}
|
||||
if isNeg {
|
||||
return "-" + string(bzWDec)
|
||||
}
|
||||
return string(bzWDec)
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [
|
|||
|
||||
// Manually set indices for the first time
|
||||
keeper.SetValidatorByConsAddr(ctx, validator)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validator)
|
||||
keeper.OnValidatorCreated(ctx, validator.OperatorAddr)
|
||||
|
||||
// Set timeslice if necessary
|
||||
|
|
|
@ -55,8 +55,7 @@ func TestValidatorByPowerIndex(t *testing.T) {
|
|||
// verify that the by power index exists
|
||||
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
||||
require.True(t, found)
|
||||
pool := keeper.GetPool(ctx)
|
||||
power := keep.GetValidatorsByPowerIndexKey(validator, pool)
|
||||
power := keep.GetValidatorsByPowerIndexKey(validator)
|
||||
require.True(t, keep.ValidatorByPowerIndexExists(ctx, keeper, power))
|
||||
|
||||
// create a second validator keep it bonded
|
||||
|
@ -85,12 +84,11 @@ func TestValidatorByPowerIndex(t *testing.T) {
|
|||
// but the new power record should have been created
|
||||
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
||||
require.True(t, found)
|
||||
pool = keeper.GetPool(ctx)
|
||||
power2 := GetValidatorsByPowerIndexKey(validator, pool)
|
||||
power2 := GetValidatorsByPowerIndexKey(validator)
|
||||
require.True(t, keep.ValidatorByPowerIndexExists(ctx, keeper, power2))
|
||||
|
||||
// now the new record power index should be the same as the original record
|
||||
power3 := GetValidatorsByPowerIndexKey(validator, pool)
|
||||
power3 := GetValidatorsByPowerIndexKey(validator)
|
||||
require.Equal(t, power2, power3)
|
||||
|
||||
// unbond self-delegation
|
||||
|
|
|
@ -240,7 +240,7 @@ func TestUndelegateSelfDelegation(t *testing.T) {
|
|||
keeper.SetDelegation(ctx, selfDelegation)
|
||||
|
||||
// create a second delegation to this validator
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator, pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator)
|
||||
validator, pool, issuedShares = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
|
@ -288,7 +288,7 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) {
|
|||
keeper.SetDelegation(ctx, selfDelegation)
|
||||
|
||||
// create a second delegation to this validator
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator, pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator)
|
||||
validator, pool, issuedShares = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
|
@ -365,7 +365,7 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) {
|
|||
keeper.SetDelegation(ctx, selfDelegation)
|
||||
|
||||
// create a second delegation to this validator
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator, pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator)
|
||||
validator, pool, issuedShares = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
|
@ -444,7 +444,7 @@ func TestUnbondingAllDelegationFromValidator(t *testing.T) {
|
|||
keeper.SetDelegation(ctx, selfDelegation)
|
||||
|
||||
// create a second delegation to this validator
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator, pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator)
|
||||
validator, pool, issuedShares = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
|
@ -689,7 +689,7 @@ func TestRedelegateFromUnbondingValidator(t *testing.T) {
|
|||
keeper.SetDelegation(ctx, selfDelegation)
|
||||
|
||||
// create a second delegation to this validator
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator, pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator)
|
||||
validator, pool, issuedShares = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
|
@ -773,7 +773,7 @@ func TestRedelegateFromUnbondedValidator(t *testing.T) {
|
|||
keeper.SetDelegation(ctx, selfDelegation)
|
||||
|
||||
// create a second delegation to this validator
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator, pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator)
|
||||
validator, pool, issuedShares = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
validator.BondIntraTxCounter = 1
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
|
|
|
@ -61,7 +61,7 @@ func AddressFromLastValidatorPowerKey(key []byte) []byte {
|
|||
// Power index is the key used in the power-store, and represents the relative
|
||||
// power ranking of the validator.
|
||||
// VALUE: validator operator address ([]byte)
|
||||
func GetValidatorsByPowerIndexKey(validator types.Validator, pool types.Pool) []byte {
|
||||
func GetValidatorsByPowerIndexKey(validator types.Validator) []byte {
|
||||
// NOTE the address doesn't need to be stored because counter bytes must always be different
|
||||
return getValidatorPowerRank(validator)
|
||||
}
|
||||
|
|
|
@ -202,9 +202,8 @@ func ValidatorByPowerIndexExists(ctx sdk.Context, keeper Keeper, power []byte) b
|
|||
|
||||
// update validator for testing
|
||||
func TestingUpdateValidator(keeper Keeper, ctx sdk.Context, validator types.Validator) types.Validator {
|
||||
pool := keeper.GetPool(ctx)
|
||||
keeper.SetValidator(ctx, validator)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validator)
|
||||
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
validator, found := keeper.GetValidator(ctx, validator.OperatorAddr)
|
||||
if !found {
|
||||
|
|
|
@ -160,10 +160,9 @@ func (k Keeper) jailValidator(ctx sdk.Context, validator types.Validator) {
|
|||
panic(fmt.Sprintf("cannot jail already jailed validator, validator: %v\n", validator))
|
||||
}
|
||||
|
||||
pool := k.GetPool(ctx)
|
||||
validator.Jailed = true
|
||||
k.SetValidator(ctx, validator)
|
||||
k.DeleteValidatorByPowerIndex(ctx, validator, pool)
|
||||
k.DeleteValidatorByPowerIndex(ctx, validator)
|
||||
}
|
||||
|
||||
// remove a validator from jail
|
||||
|
@ -172,28 +171,26 @@ func (k Keeper) unjailValidator(ctx sdk.Context, validator types.Validator) {
|
|||
panic(fmt.Sprintf("cannot unjail already unjailed validator, validator: %v\n", validator))
|
||||
}
|
||||
|
||||
pool := k.GetPool(ctx)
|
||||
validator.Jailed = false
|
||||
k.SetValidator(ctx, validator)
|
||||
k.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||
k.SetValidatorByPowerIndex(ctx, validator)
|
||||
}
|
||||
|
||||
// perform all the store operations for when a validator status becomes bonded
|
||||
func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.Validator {
|
||||
|
||||
pool := k.GetPool(ctx)
|
||||
|
||||
k.DeleteValidatorByPowerIndex(ctx, validator, pool)
|
||||
k.DeleteValidatorByPowerIndex(ctx, validator)
|
||||
|
||||
validator.BondHeight = ctx.BlockHeight()
|
||||
|
||||
// set the status
|
||||
pool := k.GetPool(ctx)
|
||||
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
||||
k.SetPool(ctx, pool)
|
||||
|
||||
// save the now bonded validator record to the two referenced stores
|
||||
k.SetValidator(ctx, validator)
|
||||
k.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||
k.SetValidatorByPowerIndex(ctx, validator)
|
||||
|
||||
// delete from queue if present
|
||||
k.DeleteValidatorQueue(ctx, validator)
|
||||
|
@ -209,10 +206,9 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.
|
|||
// perform all the store operations for when a validator status begins unbonding
|
||||
func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validator) types.Validator {
|
||||
|
||||
pool := k.GetPool(ctx)
|
||||
params := k.GetParams(ctx)
|
||||
|
||||
k.DeleteValidatorByPowerIndex(ctx, validator, pool)
|
||||
k.DeleteValidatorByPowerIndex(ctx, validator)
|
||||
|
||||
// sanity check
|
||||
if validator.Status != sdk.Bonded {
|
||||
|
@ -220,6 +216,7 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat
|
|||
}
|
||||
|
||||
// set the status
|
||||
pool := k.GetPool(ctx)
|
||||
validator, pool = validator.UpdateStatus(pool, sdk.Unbonding)
|
||||
k.SetPool(ctx, pool)
|
||||
|
||||
|
@ -228,7 +225,7 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat
|
|||
|
||||
// save the now unbonded validator record and power index
|
||||
k.SetValidator(ctx, validator)
|
||||
k.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||
k.SetValidatorByPowerIndex(ctx, validator)
|
||||
|
||||
// Adds to unbonding validator queue
|
||||
k.InsertValidatorQueue(ctx, validator)
|
||||
|
|
|
@ -99,26 +99,25 @@ func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validato
|
|||
}
|
||||
|
||||
// validator index
|
||||
func (k Keeper) SetValidatorByPowerIndex(ctx sdk.Context, validator types.Validator, pool types.Pool) {
|
||||
func (k Keeper) SetValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
|
||||
// jailed validators are not kept in the power index
|
||||
if validator.Jailed {
|
||||
return
|
||||
}
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
store.Set(GetValidatorsByPowerIndexKey(validator, pool), validator.OperatorAddr)
|
||||
store.Set(GetValidatorsByPowerIndexKey(validator), validator.OperatorAddr)
|
||||
}
|
||||
|
||||
// validator index
|
||||
func (k Keeper) DeleteValidatorByPowerIndex(ctx sdk.Context, validator types.Validator, pool types.Pool) {
|
||||
func (k Keeper) DeleteValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
store.Delete(GetValidatorsByPowerIndexKey(validator, pool))
|
||||
store.Delete(GetValidatorsByPowerIndexKey(validator))
|
||||
}
|
||||
|
||||
// validator index
|
||||
func (k Keeper) SetNewValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
pool := k.GetPool(ctx)
|
||||
store.Set(GetValidatorsByPowerIndexKey(validator, pool), validator.OperatorAddr)
|
||||
store.Set(GetValidatorsByPowerIndexKey(validator), validator.OperatorAddr)
|
||||
}
|
||||
|
||||
//___________________________________________________________________________
|
||||
|
@ -127,8 +126,8 @@ func (k Keeper) SetNewValidatorByPowerIndex(ctx sdk.Context, validator types.Val
|
|||
func (k Keeper) AddValidatorTokensAndShares(ctx sdk.Context, validator types.Validator,
|
||||
tokensToAdd sdk.Int) (valOut types.Validator, addedShares sdk.Dec) {
|
||||
|
||||
k.DeleteValidatorByPowerIndex(ctx, validator)
|
||||
pool := k.GetPool(ctx)
|
||||
k.DeleteValidatorByPowerIndex(ctx, validator, pool)
|
||||
validator, pool, addedShares = validator.AddTokensFromDel(pool, tokensToAdd)
|
||||
// increment the intra-tx counter
|
||||
// in case of a conflict, the validator which least recently changed power takes precedence
|
||||
|
@ -137,7 +136,7 @@ func (k Keeper) AddValidatorTokensAndShares(ctx sdk.Context, validator types.Val
|
|||
k.SetIntraTxCounter(ctx, counter+1)
|
||||
k.SetValidator(ctx, validator)
|
||||
k.SetPool(ctx, pool)
|
||||
k.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||
k.SetValidatorByPowerIndex(ctx, validator)
|
||||
return validator, addedShares
|
||||
}
|
||||
|
||||
|
@ -145,24 +144,24 @@ func (k Keeper) AddValidatorTokensAndShares(ctx sdk.Context, validator types.Val
|
|||
func (k Keeper) RemoveValidatorTokensAndShares(ctx sdk.Context, validator types.Validator,
|
||||
sharesToRemove sdk.Dec) (valOut types.Validator, removedTokens sdk.Dec) {
|
||||
|
||||
k.DeleteValidatorByPowerIndex(ctx, validator)
|
||||
pool := k.GetPool(ctx)
|
||||
k.DeleteValidatorByPowerIndex(ctx, validator, pool)
|
||||
validator, pool, removedTokens = validator.RemoveDelShares(pool, sharesToRemove)
|
||||
k.SetValidator(ctx, validator)
|
||||
k.SetPool(ctx, pool)
|
||||
k.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||
k.SetValidatorByPowerIndex(ctx, validator)
|
||||
return validator, removedTokens
|
||||
}
|
||||
|
||||
// Update the tokens of an existing validator, update the validators power index key
|
||||
func (k Keeper) RemoveValidatorTokens(ctx sdk.Context, validator types.Validator, tokensToRemove sdk.Dec) types.Validator {
|
||||
|
||||
k.DeleteValidatorByPowerIndex(ctx, validator)
|
||||
pool := k.GetPool(ctx)
|
||||
k.DeleteValidatorByPowerIndex(ctx, validator, pool)
|
||||
validator, pool = validator.RemoveTokens(pool, tokensToRemove)
|
||||
k.SetValidator(ctx, validator)
|
||||
k.SetPool(ctx, pool)
|
||||
k.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||
k.SetValidatorByPowerIndex(ctx, validator)
|
||||
return validator
|
||||
}
|
||||
|
||||
|
@ -195,12 +194,18 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
|
|||
panic("Cannot call RemoveValidator on bonded or unbonding validators")
|
||||
}
|
||||
|
||||
// if any tokens remain, remove from pool (burning the tokens).
|
||||
// this happens if shares are zero but tokens are not.
|
||||
// TODO: Remove once https://github.com/cosmos/cosmos-sdk/pull/2958 is merged
|
||||
pool := k.GetPool(ctx)
|
||||
pool.LooseTokens = pool.LooseTokens.Sub(validator.Tokens)
|
||||
k.SetPool(ctx, pool)
|
||||
|
||||
// delete the old validator record
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
pool := k.GetPool(ctx)
|
||||
store.Delete(GetValidatorKey(address))
|
||||
store.Delete(GetValidatorByConsAddrKey(sdk.ConsAddress(validator.ConsPubKey.Address())))
|
||||
store.Delete(GetValidatorsByPowerIndexKey(validator, pool))
|
||||
store.Delete(GetValidatorsByPowerIndexKey(validator))
|
||||
|
||||
// call hook if present
|
||||
if k.hooks != nil {
|
||||
|
|
|
@ -30,7 +30,7 @@ func TestSetValidator(t *testing.T) {
|
|||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
|
||||
keeper.SetPool(ctx, pool)
|
||||
keeper.SetValidator(ctx, validator)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validator)
|
||||
|
||||
// ensure update
|
||||
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
@ -90,11 +90,11 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) {
|
|||
require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool)
|
||||
|
||||
pool = keeper.GetPool(ctx)
|
||||
power := GetValidatorsByPowerIndexKey(validator, pool)
|
||||
power := GetValidatorsByPowerIndexKey(validator)
|
||||
require.True(t, validatorByPowerIndexExists(keeper, ctx, power))
|
||||
|
||||
// burn half the delegator shares
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator, pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validator)
|
||||
validator, pool, burned := validator.RemoveDelShares(pool, delSharesCreated.Quo(sdk.NewDec(2)))
|
||||
require.Equal(t, int64(50), burned.RoundInt64())
|
||||
keeper.SetPool(ctx, pool) // update the pool
|
||||
|
@ -104,7 +104,7 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) {
|
|||
pool = keeper.GetPool(ctx)
|
||||
validator, found = keeper.GetValidator(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
power = GetValidatorsByPowerIndexKey(validator, pool)
|
||||
power = GetValidatorsByPowerIndexKey(validator)
|
||||
require.True(t, validatorByPowerIndexExists(keeper, ctx, power))
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) {
|
|||
|
||||
// remove enough tokens to kick out the validator below the current cliff
|
||||
// validator and next in line cliff validator
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, nextCliffVal, pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, nextCliffVal)
|
||||
nextCliffVal, pool, _ = nextCliffVal.RemoveDelShares(pool, sdk.NewDec(21))
|
||||
keeper.SetPool(ctx, pool)
|
||||
nextCliffVal = TestingUpdateValidator(keeper, ctx, nextCliffVal)
|
||||
|
@ -459,7 +459,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
|
|||
assert.True(ValEq(t, validators[3], resValidators[1]))
|
||||
|
||||
pool := keeper.GetPool(ctx)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[0], pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[0])
|
||||
validators[0], pool, _ = validators[0].AddTokensFromDel(pool, sdk.NewInt(500))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
|
@ -477,7 +477,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
|
|||
|
||||
validators[3], found = keeper.GetValidator(ctx, validators[3].OperatorAddr)
|
||||
require.True(t, found)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[3], pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[3])
|
||||
validators[3], pool, _ = validators[3].AddTokensFromDel(pool, sdk.NewInt(1))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[3] = TestingUpdateValidator(keeper, ctx, validators[3])
|
||||
|
@ -487,7 +487,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
|
|||
assert.True(ValEq(t, validators[3], resValidators[1]))
|
||||
|
||||
// validator 3 kicked out temporarily
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[3], pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[3])
|
||||
validators[3], pool, _ = validators[3].RemoveDelShares(pool, sdk.NewDec(201))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[3] = TestingUpdateValidator(keeper, ctx, validators[3])
|
||||
|
@ -497,7 +497,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
|
|||
assert.True(ValEq(t, validators[2], resValidators[1]))
|
||||
|
||||
// validator 4 does not get spot back
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[3], pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[3])
|
||||
validators[3], pool, _ = validators[3].AddTokensFromDel(pool, sdk.NewInt(200))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[3] = TestingUpdateValidator(keeper, ctx, validators[3])
|
||||
|
@ -548,8 +548,8 @@ func TestValidatorBondHeight(t *testing.T) {
|
|||
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[1], resValidators[1]))
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[1], pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[2], pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[1])
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[2])
|
||||
validators[1], pool, _ = validators[1].AddTokensFromDel(pool, sdk.NewInt(50))
|
||||
validators[2], pool, _ = validators[2].AddTokensFromDel(pool, sdk.NewInt(50))
|
||||
keeper.SetPool(ctx, pool)
|
||||
|
@ -624,11 +624,10 @@ func TestApplyAndReturnValidatorSetUpdatesAllNone(t *testing.T) {
|
|||
// test from nothing to something
|
||||
// tendermintUpdate set: {} -> {c1, c3}
|
||||
require.Equal(t, 0, len(keeper.ApplyAndReturnValidatorSetUpdates(ctx)))
|
||||
pool := keeper.GetPool(ctx)
|
||||
keeper.SetValidator(ctx, validators[0])
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[0], pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[0])
|
||||
keeper.SetValidator(ctx, validators[1])
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[1], pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[1])
|
||||
|
||||
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
assert.Equal(t, 2, len(updates))
|
||||
|
@ -734,9 +733,8 @@ func TestApplyAndReturnValidatorSetUpdatesInserted(t *testing.T) {
|
|||
|
||||
// test validtor added at the beginning
|
||||
// tendermintUpdate set: {} -> {c0}
|
||||
pool := keeper.GetPool(ctx)
|
||||
keeper.SetValidator(ctx, validators[2])
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[2], pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[2])
|
||||
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
validators[2], _ = keeper.GetValidator(ctx, validators[2].OperatorAddr)
|
||||
require.Equal(t, 1, len(updates))
|
||||
|
@ -744,9 +742,8 @@ func TestApplyAndReturnValidatorSetUpdatesInserted(t *testing.T) {
|
|||
|
||||
// test validtor added at the beginning
|
||||
// tendermintUpdate set: {} -> {c0}
|
||||
pool = keeper.GetPool(ctx)
|
||||
keeper.SetValidator(ctx, validators[3])
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[3], pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[3])
|
||||
updates = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
validators[3], _ = keeper.GetValidator(ctx, validators[3].OperatorAddr)
|
||||
require.Equal(t, 1, len(updates))
|
||||
|
@ -754,9 +751,8 @@ func TestApplyAndReturnValidatorSetUpdatesInserted(t *testing.T) {
|
|||
|
||||
// test validtor added at the end
|
||||
// tendermintUpdate set: {} -> {c0}
|
||||
pool = keeper.GetPool(ctx)
|
||||
keeper.SetValidator(ctx, validators[4])
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[4], pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[4])
|
||||
updates = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
validators[4], _ = keeper.GetValidator(ctx, validators[4].OperatorAddr)
|
||||
require.Equal(t, 1, len(updates))
|
||||
|
@ -795,7 +791,7 @@ func TestApplyAndReturnValidatorSetUpdatesWithCliffValidator(t *testing.T) {
|
|||
validators[2], pool, _ = validators[2].AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
keeper.SetPool(ctx, pool)
|
||||
keeper.SetValidator(ctx, validators[2])
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[2], pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[2])
|
||||
updates = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
validators[2], _ = keeper.GetValidator(ctx, validators[2].OperatorAddr)
|
||||
require.Equal(t, 2, len(updates), "%v", updates)
|
||||
|
@ -865,7 +861,7 @@ func TestApplyAndReturnValidatorSetUpdatesNewValidator(t *testing.T) {
|
|||
|
||||
keeper.SetPool(ctx, pool)
|
||||
keeper.SetValidator(ctx, validators[i])
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[i], pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[i])
|
||||
}
|
||||
|
||||
// verify initial Tendermint updates are correct
|
||||
|
@ -881,12 +877,12 @@ func TestApplyAndReturnValidatorSetUpdatesNewValidator(t *testing.T) {
|
|||
// update initial validator set
|
||||
for i, amt := range amts {
|
||||
pool := keeper.GetPool(ctx)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[i], pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[i])
|
||||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||
|
||||
keeper.SetPool(ctx, pool)
|
||||
keeper.SetValidator(ctx, validators[i])
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[i], pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[i])
|
||||
}
|
||||
|
||||
// add a new validator that goes from zero power, to non-zero power, back to
|
||||
|
@ -904,7 +900,7 @@ func TestApplyAndReturnValidatorSetUpdatesNewValidator(t *testing.T) {
|
|||
|
||||
validator, pool, _ = validator.RemoveDelShares(pool, sdk.NewDecFromInt(amt))
|
||||
keeper.SetValidator(ctx, validator)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validator)
|
||||
|
||||
// add a new validator that increases in power
|
||||
valPubKey = PKs[len(validators)+2]
|
||||
|
@ -913,7 +909,7 @@ func TestApplyAndReturnValidatorSetUpdatesNewValidator(t *testing.T) {
|
|||
validator = types.NewValidator(valAddr, valPubKey, types.Description{})
|
||||
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(500))
|
||||
keeper.SetValidator(ctx, validator)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validator)
|
||||
keeper.SetPool(ctx, pool)
|
||||
|
||||
// verify initial Tendermint updates are correct
|
||||
|
@ -949,7 +945,7 @@ func TestApplyAndReturnValidatorSetUpdatesBondTransition(t *testing.T) {
|
|||
validators[i].BondIntraTxCounter = int16(i)
|
||||
keeper.SetPool(ctx, pool)
|
||||
keeper.SetValidator(ctx, validators[i])
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[i], pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[i])
|
||||
}
|
||||
|
||||
// verify initial Tendermint updates are correct
|
||||
|
@ -970,11 +966,11 @@ func TestApplyAndReturnValidatorSetUpdatesBondTransition(t *testing.T) {
|
|||
validators[0], found = keeper.GetValidator(ctx, validators[0].OperatorAddr)
|
||||
require.True(t, found)
|
||||
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[0], pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[0])
|
||||
validators[0], pool, _ = validators[0].AddTokensFromDel(pool, sdk.NewInt(1))
|
||||
keeper.SetPool(ctx, pool)
|
||||
keeper.SetValidator(ctx, validators[0])
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[0], pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[0])
|
||||
|
||||
// verify initial Tendermint updates are correct
|
||||
require.Equal(t, 0, len(keeper.ApplyAndReturnValidatorSetUpdates(ctx)))
|
||||
|
@ -987,19 +983,19 @@ func TestApplyAndReturnValidatorSetUpdatesBondTransition(t *testing.T) {
|
|||
validators[1], found = keeper.GetValidator(ctx, validators[1].OperatorAddr)
|
||||
require.True(t, found)
|
||||
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[0], pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[0])
|
||||
validators[0], pool, _ = validators[0].RemoveDelShares(pool, validators[0].DelegatorShares)
|
||||
keeper.SetPool(ctx, pool)
|
||||
keeper.SetValidator(ctx, validators[0])
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[0], pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[0])
|
||||
updates = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
require.Equal(t, 0, len(updates))
|
||||
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[1], pool)
|
||||
keeper.DeleteValidatorByPowerIndex(ctx, validators[1])
|
||||
validators[1], pool, _ = validators[1].AddTokensFromDel(pool, sdk.NewInt(250))
|
||||
keeper.SetPool(ctx, pool)
|
||||
keeper.SetValidator(ctx, validators[1])
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[1], pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[1])
|
||||
|
||||
// verify initial Tendermint updates are correct
|
||||
updates = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
|
|
@ -29,7 +29,7 @@ func TestNewQuerier(t *testing.T) {
|
|||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
|
||||
validators[i].BondIntraTxCounter = int16(i)
|
||||
keeper.SetValidator(ctx, validators[i])
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[i], pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validators[i])
|
||||
}
|
||||
keeper.SetPool(ctx, pool)
|
||||
|
||||
|
@ -170,13 +170,11 @@ func TestQueryDelegation(t *testing.T) {
|
|||
// Create Validators and Delegation
|
||||
val1 := types.NewValidator(addrVal1, pk1, types.Description{})
|
||||
keeper.SetValidator(ctx, val1)
|
||||
pool := keeper.GetPool(ctx)
|
||||
keeper.SetValidatorByPowerIndex(ctx, val1, pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, val1)
|
||||
|
||||
val2 := types.NewValidator(addrVal2, pk2, types.Description{})
|
||||
keeper.SetValidator(ctx, val2)
|
||||
pool = keeper.GetPool(ctx)
|
||||
keeper.SetValidatorByPowerIndex(ctx, val2, pool)
|
||||
keeper.SetValidatorByPowerIndex(ctx, val2)
|
||||
|
||||
keeper.Delegate(ctx, addrAcc2, sdk.NewCoin(types.DefaultBondDenom, sdk.NewInt(20)), val1, true)
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ func AllInvariants(ck bank.Keeper, k stake.Keeper,
|
|||
return err
|
||||
}
|
||||
|
||||
err = PositivePowerInvariant(k)(ctx)
|
||||
err = NonNegativePowerInvariant(k)(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -111,11 +111,10 @@ func SupplyInvariants(ck bank.Keeper, k stake.Keeper,
|
|||
}
|
||||
}
|
||||
|
||||
// PositivePowerInvariant checks that all stored validators have > 0 power.
|
||||
func PositivePowerInvariant(k stake.Keeper) simulation.Invariant {
|
||||
// NonNegativePowerInvariant checks that all stored validators have >= 0 power.
|
||||
func NonNegativePowerInvariant(k stake.Keeper) simulation.Invariant {
|
||||
return func(ctx sdk.Context) error {
|
||||
iterator := k.ValidatorsPowerStoreIterator(ctx)
|
||||
pool := k.GetPool(ctx)
|
||||
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
validator, found := k.GetValidator(ctx, iterator.Value())
|
||||
|
@ -123,12 +122,16 @@ func PositivePowerInvariant(k stake.Keeper) simulation.Invariant {
|
|||
panic(fmt.Sprintf("validator record not found for address: %X\n", iterator.Value()))
|
||||
}
|
||||
|
||||
powerKey := keeper.GetValidatorsByPowerIndexKey(validator, pool)
|
||||
powerKey := keeper.GetValidatorsByPowerIndexKey(validator)
|
||||
|
||||
if !bytes.Equal(iterator.Key(), powerKey) {
|
||||
return fmt.Errorf("power store invariance:\n\tvalidator.Power: %v"+
|
||||
"\n\tkey should be: %v\n\tkey in store: %v", validator.GetPower(), powerKey, iterator.Key())
|
||||
}
|
||||
|
||||
if validator.Tokens.LT(sdk.ZeroDec()) {
|
||||
return fmt.Errorf("negative tokens for validator: %v", validator)
|
||||
}
|
||||
}
|
||||
iterator.Close()
|
||||
return nil
|
||||
|
|
|
@ -360,11 +360,16 @@ func (v Validator) UpdateStatus(pool Pool, NewStatus sdk.BondStatus) (Validator,
|
|||
|
||||
// removes tokens from a validator
|
||||
func (v Validator) RemoveTokens(pool Pool, tokens sdk.Dec) (Validator, Pool) {
|
||||
if tokens.IsNegative() {
|
||||
panic(fmt.Sprintf("should not happen: trying to remove negative tokens %v", tokens))
|
||||
}
|
||||
if v.Tokens.LT(tokens) {
|
||||
panic(fmt.Sprintf("should not happen: only have %v tokens, trying to remove %v", v.Tokens, tokens))
|
||||
}
|
||||
v.Tokens = v.Tokens.Sub(tokens)
|
||||
if v.Status == sdk.Bonded {
|
||||
pool = pool.bondedTokensToLoose(tokens)
|
||||
}
|
||||
|
||||
v.Tokens = v.Tokens.Sub(tokens)
|
||||
return v, pool
|
||||
}
|
||||
|
||||
|
@ -404,15 +409,11 @@ func (v Validator) AddTokensFromDel(pool Pool, amount sdk.Int) (Validator, Pool,
|
|||
|
||||
// RemoveDelShares removes delegator shares from a validator.
|
||||
func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Dec) (Validator, Pool, sdk.Dec) {
|
||||
issuedTokens := v.DelegatorShareExRate().Mul(delShares)
|
||||
v.Tokens = v.Tokens.Sub(issuedTokens)
|
||||
delTokens := v.DelegatorShareExRate().Mul(delShares)
|
||||
delTokens = sdk.MinDec(delTokens, v.Tokens)
|
||||
v, pool = v.RemoveTokens(pool, delTokens)
|
||||
v.DelegatorShares = v.DelegatorShares.Sub(delShares)
|
||||
|
||||
if v.Status == sdk.Bonded {
|
||||
pool = pool.bondedTokensToLoose(issuedTokens)
|
||||
}
|
||||
|
||||
return v, pool, issuedTokens
|
||||
return v, pool, delTokens
|
||||
}
|
||||
|
||||
// DelegatorShareExRate gets the exchange rate of tokens over delegator shares.
|
||||
|
|
Loading…
Reference in New Issue