2018-06-26 19:00:12 -07:00
|
|
|
package keeper
|
|
|
|
|
|
|
|
import (
|
2018-11-08 16:28:28 -08:00
|
|
|
"bytes"
|
2018-06-26 19:00:12 -07:00
|
|
|
"fmt"
|
2018-10-14 17:37:06 -07:00
|
|
|
"time"
|
2018-06-26 19:00:12 -07:00
|
|
|
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2019-01-11 12:08:01 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
2018-06-26 19:00:12 -07:00
|
|
|
)
|
|
|
|
|
2018-09-01 13:21:42 -07:00
|
|
|
// Cache the amino decoding of validators, as it can be the case that repeated slashing calls
|
|
|
|
// cause many calls to GetValidator, which were shown to throttle the state machine in our
|
|
|
|
// simulation. Note this is quite biased though, as the simulator does more slashes than a
|
|
|
|
// live chain should, however we require the slashing to be fast as noone pays gas for it.
|
2018-08-31 00:37:25 -07:00
|
|
|
type cachedValidator struct {
|
|
|
|
val types.Validator
|
2018-09-02 12:42:25 -07:00
|
|
|
marshalled string // marshalled amino bytes for the validator object (not operator address)
|
2018-08-31 00:37:25 -07:00
|
|
|
}
|
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
// get a single validator
|
2018-08-30 21:06:44 -07:00
|
|
|
func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator types.Validator, found bool) {
|
2018-06-26 19:00:12 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-07-03 22:32:49 -07:00
|
|
|
value := store.Get(GetValidatorKey(addr))
|
|
|
|
if value == nil {
|
2018-06-26 19:00:12 -07:00
|
|
|
return validator, false
|
|
|
|
}
|
2018-09-02 12:42:25 -07:00
|
|
|
|
2018-09-01 13:21:42 -07:00
|
|
|
// If these amino encoded bytes are in the cache, return the cached validator
|
2018-08-31 00:37:25 -07:00
|
|
|
strValue := string(value)
|
2018-12-10 14:14:52 -08:00
|
|
|
if val, ok := k.validatorCache[strValue]; ok {
|
2018-08-31 00:37:25 -07:00
|
|
|
valToReturn := val.val
|
|
|
|
// Doesn't mutate the cache's value
|
2018-09-08 01:44:58 -07:00
|
|
|
valToReturn.OperatorAddr = addr
|
2018-08-31 00:37:25 -07:00
|
|
|
return valToReturn, true
|
|
|
|
}
|
2018-09-02 12:42:25 -07:00
|
|
|
|
2018-09-01 13:21:42 -07:00
|
|
|
// amino bytes weren't found in cache, so amino unmarshal and add it to the cache
|
2019-01-07 12:42:52 -08:00
|
|
|
validator = types.MustUnmarshalValidator(k.cdc, value)
|
2018-08-31 08:29:32 -07:00
|
|
|
cachedVal := cachedValidator{validator, strValue}
|
2018-12-10 14:14:52 -08:00
|
|
|
k.validatorCache[strValue] = cachedValidator{validator, strValue}
|
|
|
|
k.validatorCacheList.PushBack(cachedVal)
|
2018-09-02 12:42:25 -07:00
|
|
|
|
2018-09-01 13:21:42 -07:00
|
|
|
// if the cache is too big, pop off the last element from it
|
2018-12-11 13:10:42 -08:00
|
|
|
if k.validatorCacheList.Len() > aminoCacheSize {
|
2018-12-10 14:14:52 -08:00
|
|
|
valToRemove := k.validatorCacheList.Remove(k.validatorCacheList.Front()).(cachedValidator)
|
|
|
|
delete(k.validatorCache, valToRemove.marshalled)
|
2018-08-31 08:29:32 -07:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:42:52 -08:00
|
|
|
validator = types.MustUnmarshalValidator(k.cdc, value)
|
2018-06-26 19:00:12 -07:00
|
|
|
return validator, true
|
|
|
|
}
|
|
|
|
|
2018-10-03 09:37:06 -07:00
|
|
|
func (k Keeper) mustGetValidator(ctx sdk.Context, addr sdk.ValAddress) types.Validator {
|
|
|
|
validator, found := k.GetValidator(ctx, addr)
|
|
|
|
if !found {
|
|
|
|
panic(fmt.Sprintf("validator record not found for address: %X\n", addr))
|
|
|
|
}
|
|
|
|
return validator
|
|
|
|
}
|
|
|
|
|
2018-09-24 21:09:31 -07:00
|
|
|
// get a single validator by consensus address
|
|
|
|
func (k Keeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator types.Validator, found bool) {
|
2018-06-26 19:00:12 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-09-24 21:09:31 -07:00
|
|
|
opAddr := store.Get(GetValidatorByConsAddrKey(consAddr))
|
|
|
|
if opAddr == nil {
|
2018-06-26 19:00:12 -07:00
|
|
|
return validator, false
|
|
|
|
}
|
2018-09-24 21:09:31 -07:00
|
|
|
return k.GetValidator(ctx, opAddr)
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
|
|
|
|
2018-10-03 09:37:06 -07:00
|
|
|
func (k Keeper) mustGetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) types.Validator {
|
|
|
|
validator, found := k.GetValidatorByConsAddr(ctx, consAddr)
|
|
|
|
if !found {
|
|
|
|
panic(fmt.Errorf("validator with consensus-Address %s not found", consAddr))
|
|
|
|
}
|
|
|
|
return validator
|
|
|
|
}
|
|
|
|
|
|
|
|
//___________________________________________________________________________
|
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
// set the main record holding validator details
|
|
|
|
func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-07-04 14:07:06 -07:00
|
|
|
bz := types.MustMarshalValidator(k.cdc, validator)
|
2018-09-08 01:44:58 -07:00
|
|
|
store.Set(GetValidatorKey(validator.OperatorAddr), bz)
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// validator index
|
2018-09-24 21:09:31 -07:00
|
|
|
func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) {
|
2018-06-26 19:00:12 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-09-24 21:09:31 -07:00
|
|
|
consAddr := sdk.ConsAddress(validator.ConsPubKey.Address())
|
|
|
|
store.Set(GetValidatorByConsAddrKey(consAddr), validator.OperatorAddr)
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// validator index
|
2018-12-07 16:04:52 -08:00
|
|
|
func (k Keeper) SetValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
|
2018-10-03 09:37:06 -07:00
|
|
|
// jailed validators are not kept in the power index
|
|
|
|
if validator.Jailed {
|
|
|
|
return
|
|
|
|
}
|
2018-06-26 19:00:12 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-12-07 16:04:52 -08:00
|
|
|
store.Set(GetValidatorsByPowerIndexKey(validator), validator.OperatorAddr)
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// validator index
|
2018-12-07 16:04:52 -08:00
|
|
|
func (k Keeper) DeleteValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
|
2018-06-26 19:00:12 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-12-07 16:04:52 -08:00
|
|
|
store.Delete(GetValidatorsByPowerIndexKey(validator))
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
|
|
|
|
2018-10-03 09:37:06 -07:00
|
|
|
// validator index
|
|
|
|
func (k Keeper) SetNewValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
|
2018-06-26 19:00:12 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-12-07 16:04:52 -08:00
|
|
|
store.Set(GetValidatorsByPowerIndexKey(validator), validator.OperatorAddr)
|
2018-10-03 09:37:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//___________________________________________________________________________
|
|
|
|
|
|
|
|
// Update the tokens of an existing validator, update the validators power index key
|
|
|
|
func (k Keeper) AddValidatorTokensAndShares(ctx sdk.Context, validator types.Validator,
|
|
|
|
tokensToAdd sdk.Int) (valOut types.Validator, addedShares sdk.Dec) {
|
|
|
|
|
2018-12-07 16:04:52 -08:00
|
|
|
k.DeleteValidatorByPowerIndex(ctx, validator)
|
2018-10-03 09:37:06 -07:00
|
|
|
pool := k.GetPool(ctx)
|
|
|
|
validator, pool, addedShares = validator.AddTokensFromDel(pool, tokensToAdd)
|
|
|
|
k.SetValidator(ctx, validator)
|
|
|
|
k.SetPool(ctx, pool)
|
2018-12-07 16:04:52 -08:00
|
|
|
k.SetValidatorByPowerIndex(ctx, validator)
|
2018-10-03 09:37:06 -07:00
|
|
|
return validator, addedShares
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the tokens of an existing validator, update the validators power index key
|
|
|
|
func (k Keeper) RemoveValidatorTokensAndShares(ctx sdk.Context, validator types.Validator,
|
2019-01-02 12:29:47 -08:00
|
|
|
sharesToRemove sdk.Dec) (valOut types.Validator, removedTokens sdk.Int) {
|
2018-10-03 09:37:06 -07:00
|
|
|
|
2018-12-07 16:04:52 -08:00
|
|
|
k.DeleteValidatorByPowerIndex(ctx, validator)
|
2018-10-03 09:37:06 -07:00
|
|
|
pool := k.GetPool(ctx)
|
|
|
|
validator, pool, removedTokens = validator.RemoveDelShares(pool, sharesToRemove)
|
|
|
|
k.SetValidator(ctx, validator)
|
|
|
|
k.SetPool(ctx, pool)
|
2018-12-07 16:04:52 -08:00
|
|
|
k.SetValidatorByPowerIndex(ctx, validator)
|
2018-10-03 09:37:06 -07:00
|
|
|
return validator, removedTokens
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the tokens of an existing validator, update the validators power index key
|
2019-01-02 12:29:47 -08:00
|
|
|
func (k Keeper) RemoveValidatorTokens(ctx sdk.Context,
|
|
|
|
validator types.Validator, tokensToRemove sdk.Int) types.Validator {
|
2018-11-04 22:11:03 -08:00
|
|
|
|
2018-12-07 16:04:52 -08:00
|
|
|
k.DeleteValidatorByPowerIndex(ctx, validator)
|
2018-10-03 09:37:06 -07:00
|
|
|
pool := k.GetPool(ctx)
|
|
|
|
validator, pool = validator.RemoveTokens(pool, tokensToRemove)
|
|
|
|
k.SetValidator(ctx, validator)
|
|
|
|
k.SetPool(ctx, pool)
|
2018-12-07 16:04:52 -08:00
|
|
|
k.SetValidatorByPowerIndex(ctx, validator)
|
2018-10-03 09:37:06 -07:00
|
|
|
return validator
|
|
|
|
}
|
|
|
|
|
|
|
|
// UpdateValidatorCommission attempts to update a validator's commission rate.
|
|
|
|
// An error is returned if the new commission rate is invalid.
|
2019-01-02 12:29:47 -08:00
|
|
|
func (k Keeper) UpdateValidatorCommission(ctx sdk.Context,
|
|
|
|
validator types.Validator, newRate sdk.Dec) (types.Commission, sdk.Error) {
|
|
|
|
|
2018-10-03 09:37:06 -07:00
|
|
|
commission := validator.Commission
|
|
|
|
blockTime := ctx.BlockHeader().Time
|
|
|
|
|
|
|
|
if err := commission.ValidateNewRate(newRate, blockTime); err != nil {
|
|
|
|
return commission, err
|
|
|
|
}
|
|
|
|
|
|
|
|
commission.Rate = newRate
|
|
|
|
commission.UpdateTime = blockTime
|
|
|
|
|
|
|
|
return commission, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove the validator record and associated indexes
|
|
|
|
// except for the bonded validator index which is only handled in ApplyAndReturnTendermintUpdates
|
|
|
|
func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
|
|
|
|
|
|
|
|
// first retrieve the old validator record
|
|
|
|
validator, found := k.GetValidator(ctx, address)
|
|
|
|
if !found {
|
|
|
|
return
|
|
|
|
}
|
2018-11-04 22:11:03 -08:00
|
|
|
if validator.Status != sdk.Unbonded {
|
|
|
|
panic("Cannot call RemoveValidator on bonded or unbonding validators")
|
|
|
|
}
|
2018-10-03 09:37:06 -07:00
|
|
|
|
2018-12-07 16:04:52 -08:00
|
|
|
// 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)
|
2019-01-21 16:52:03 -08:00
|
|
|
pool.NotBondedTokens = pool.NotBondedTokens.Sub(validator.Tokens)
|
2018-12-07 16:04:52 -08:00
|
|
|
k.SetPool(ctx, pool)
|
|
|
|
|
2018-10-03 09:37:06 -07:00
|
|
|
// delete the old validator record
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
store.Delete(GetValidatorKey(address))
|
|
|
|
store.Delete(GetValidatorByConsAddrKey(sdk.ConsAddress(validator.ConsPubKey.Address())))
|
2018-12-07 16:04:52 -08:00
|
|
|
store.Delete(GetValidatorsByPowerIndexKey(validator))
|
2018-10-03 09:37:06 -07:00
|
|
|
|
2018-11-08 16:28:28 -08:00
|
|
|
// call hook if present
|
|
|
|
if k.hooks != nil {
|
2019-01-08 21:28:46 -08:00
|
|
|
k.hooks.AfterValidatorRemoved(ctx, validator.ConsAddress(), validator.OperatorAddr)
|
2018-11-08 16:28:28 -08:00
|
|
|
}
|
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
|
|
|
|
2018-10-03 09:37:06 -07:00
|
|
|
//___________________________________________________________________________
|
|
|
|
// get groups of validators
|
|
|
|
|
|
|
|
// get the set of all validators with no limits, used during genesis dump
|
2018-06-26 19:00:12 -07:00
|
|
|
func (k Keeper) GetAllValidators(ctx sdk.Context) (validators []types.Validator) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
iterator := sdk.KVStorePrefixIterator(store, ValidatorsKey)
|
2018-09-13 14:23:44 -07:00
|
|
|
defer iterator.Close()
|
2018-06-26 19:00:12 -07:00
|
|
|
|
2018-09-13 14:23:44 -07:00
|
|
|
for ; iterator.Valid(); iterator.Next() {
|
2019-01-07 12:42:52 -08:00
|
|
|
validator := types.MustUnmarshalValidator(k.cdc, iterator.Value())
|
2018-06-26 19:00:12 -07:00
|
|
|
validators = append(validators, validator)
|
|
|
|
}
|
|
|
|
return validators
|
|
|
|
}
|
|
|
|
|
2018-09-13 14:23:44 -07:00
|
|
|
// return a given amount of all the validators
|
|
|
|
func (k Keeper) GetValidators(ctx sdk.Context, maxRetrieve uint16) (validators []types.Validator) {
|
2018-06-26 19:00:12 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-09-13 14:23:44 -07:00
|
|
|
validators = make([]types.Validator, maxRetrieve)
|
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
iterator := sdk.KVStorePrefixIterator(store, ValidatorsKey)
|
2018-09-13 14:23:44 -07:00
|
|
|
defer iterator.Close()
|
2018-06-26 19:00:12 -07:00
|
|
|
|
|
|
|
i := 0
|
2018-09-13 14:23:44 -07:00
|
|
|
for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
|
2019-01-07 12:42:52 -08:00
|
|
|
validator := types.MustUnmarshalValidator(k.cdc, iterator.Value())
|
2018-06-26 19:00:12 -07:00
|
|
|
validators[i] = validator
|
2018-09-13 14:23:44 -07:00
|
|
|
i++
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
2018-09-13 14:23:44 -07:00
|
|
|
return validators[:i] // trim if the array length < maxRetrieve
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// get the group of the bonded validators
|
2018-10-21 15:26:58 -07:00
|
|
|
func (k Keeper) GetLastValidators(ctx sdk.Context) (validators []types.Validator) {
|
2018-06-26 19:00:12 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
|
|
|
|
// add the actual validator power sorted store
|
2018-08-31 02:03:43 -07:00
|
|
|
maxValidators := k.MaxValidators(ctx)
|
2018-06-26 19:00:12 -07:00
|
|
|
validators = make([]types.Validator, maxValidators)
|
|
|
|
|
2018-10-22 01:18:10 -07:00
|
|
|
iterator := sdk.KVStorePrefixIterator(store, LastValidatorPowerKey)
|
2018-09-13 14:23:44 -07:00
|
|
|
defer iterator.Close()
|
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
i := 0
|
|
|
|
for ; iterator.Valid(); iterator.Next() {
|
|
|
|
|
|
|
|
// sanity check
|
2018-10-21 15:26:58 -07:00
|
|
|
if i >= int(maxValidators) {
|
|
|
|
panic("more validators than maxValidators found")
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
2018-10-22 01:18:10 -07:00
|
|
|
address := AddressFromLastValidatorPowerKey(iterator.Key())
|
2018-10-03 09:37:06 -07:00
|
|
|
validator := k.mustGetValidator(ctx, address)
|
2018-06-26 19:00:12 -07:00
|
|
|
|
|
|
|
validators[i] = validator
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
return validators[:i] // trim
|
|
|
|
}
|
|
|
|
|
2018-11-04 20:44:43 -08:00
|
|
|
// returns an iterator for the consensus validators in the last block
|
|
|
|
func (k Keeper) LastValidatorsIterator(ctx sdk.Context) (iterator sdk.Iterator) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
iterator = sdk.KVStorePrefixIterator(store, LastValidatorPowerKey)
|
|
|
|
return iterator
|
|
|
|
}
|
|
|
|
|
2018-10-21 15:26:58 -07:00
|
|
|
// get the current group of bonded validators sorted by power-rank
|
2018-10-03 09:37:06 -07:00
|
|
|
func (k Keeper) GetBondedValidatorsByPower(ctx sdk.Context) []types.Validator {
|
2018-06-26 19:00:12 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-08-31 02:03:43 -07:00
|
|
|
maxValidators := k.MaxValidators(ctx)
|
2018-06-26 19:00:12 -07:00
|
|
|
validators := make([]types.Validator, maxValidators)
|
2018-09-13 14:23:44 -07:00
|
|
|
|
|
|
|
iterator := sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey)
|
|
|
|
defer iterator.Close()
|
|
|
|
|
2018-06-26 19:00:12 -07:00
|
|
|
i := 0
|
2018-09-13 14:23:44 -07:00
|
|
|
for ; iterator.Valid() && i < int(maxValidators); iterator.Next() {
|
2018-06-26 19:00:12 -07:00
|
|
|
address := iterator.Value()
|
2018-10-03 09:37:06 -07:00
|
|
|
validator := k.mustGetValidator(ctx, address)
|
2018-09-11 02:12:35 -07:00
|
|
|
|
2018-07-13 13:46:14 -07:00
|
|
|
if validator.Status == sdk.Bonded {
|
2018-06-26 19:00:12 -07:00
|
|
|
validators[i] = validator
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return validators[:i] // trim
|
|
|
|
}
|
2018-10-14 17:37:06 -07:00
|
|
|
|
2018-11-04 20:44:43 -08:00
|
|
|
// returns an iterator for the current validator power store
|
|
|
|
func (k Keeper) ValidatorsPowerStoreIterator(ctx sdk.Context) (iterator sdk.Iterator) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
iterator = sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey)
|
|
|
|
return iterator
|
|
|
|
}
|
|
|
|
|
2018-10-14 17:37:06 -07:00
|
|
|
// gets a specific validator queue timeslice. A timeslice is a slice of ValAddresses corresponding to unbonding validators
|
|
|
|
// that expire at a certain time.
|
|
|
|
func (k Keeper) GetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time) (valAddrs []sdk.ValAddress) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
bz := store.Get(GetValidatorQueueTimeKey(timestamp))
|
|
|
|
if bz == nil {
|
|
|
|
return []sdk.ValAddress{}
|
|
|
|
}
|
2018-11-04 18:28:38 -08:00
|
|
|
k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &valAddrs)
|
2018-10-14 17:37:06 -07:00
|
|
|
return valAddrs
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sets a specific validator queue timeslice.
|
|
|
|
func (k Keeper) SetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []sdk.ValAddress) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-11-04 18:28:38 -08:00
|
|
|
bz := k.cdc.MustMarshalBinaryLengthPrefixed(keys)
|
2018-10-14 17:37:06 -07:00
|
|
|
store.Set(GetValidatorQueueTimeKey(timestamp), bz)
|
|
|
|
}
|
|
|
|
|
2018-11-08 16:28:28 -08:00
|
|
|
// Deletes a specific validator queue timeslice.
|
|
|
|
func (k Keeper) DeleteValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
store.Delete(GetValidatorQueueTimeKey(timestamp))
|
|
|
|
}
|
|
|
|
|
2018-10-14 17:37:06 -07:00
|
|
|
// Insert an validator address to the appropriate timeslice in the validator queue
|
|
|
|
func (k Keeper) InsertValidatorQueue(ctx sdk.Context, val types.Validator) {
|
2019-01-17 09:53:22 -08:00
|
|
|
timeSlice := k.GetValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime)
|
2019-01-02 12:29:47 -08:00
|
|
|
var keys []sdk.ValAddress
|
2018-10-14 17:37:06 -07:00
|
|
|
if len(timeSlice) == 0 {
|
2019-01-02 12:29:47 -08:00
|
|
|
keys = []sdk.ValAddress{val.OperatorAddr}
|
2018-10-14 17:37:06 -07:00
|
|
|
} else {
|
2019-01-02 12:29:47 -08:00
|
|
|
keys = append(timeSlice, val.OperatorAddr)
|
2018-10-14 17:37:06 -07:00
|
|
|
}
|
2019-01-17 09:53:22 -08:00
|
|
|
k.SetValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime, keys)
|
2018-10-14 17:37:06 -07:00
|
|
|
}
|
|
|
|
|
2018-11-08 16:28:28 -08:00
|
|
|
// Delete a validator address from the validator queue
|
|
|
|
func (k Keeper) DeleteValidatorQueue(ctx sdk.Context, val types.Validator) {
|
2019-01-17 09:53:22 -08:00
|
|
|
timeSlice := k.GetValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime)
|
2018-11-08 16:28:28 -08:00
|
|
|
newTimeSlice := []sdk.ValAddress{}
|
|
|
|
for _, addr := range timeSlice {
|
|
|
|
if !bytes.Equal(addr, val.OperatorAddr) {
|
|
|
|
newTimeSlice = append(newTimeSlice, addr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(newTimeSlice) == 0 {
|
2019-01-17 09:53:22 -08:00
|
|
|
k.DeleteValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime)
|
2018-11-08 16:28:28 -08:00
|
|
|
} else {
|
2019-01-17 09:53:22 -08:00
|
|
|
k.SetValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime, newTimeSlice)
|
2018-11-08 16:28:28 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-14 17:37:06 -07:00
|
|
|
// Returns all the validator queue timeslices from time 0 until endTime
|
|
|
|
func (k Keeper) ValidatorQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
2019-01-02 12:29:47 -08:00
|
|
|
return store.Iterator(ValidatorQueueKey,
|
|
|
|
sdk.InclusiveEndBytes(GetValidatorQueueTimeKey(endTime)))
|
2018-10-14 17:37:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a concatenated list of all the timeslices before currTime, and deletes the timeslices from the queue
|
|
|
|
func (k Keeper) GetAllMatureValidatorQueue(ctx sdk.Context, currTime time.Time) (matureValsAddrs []sdk.ValAddress) {
|
|
|
|
// gets an iterator for all timeslices from time 0 until the current Blockheader time
|
|
|
|
validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time)
|
|
|
|
for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() {
|
|
|
|
timeslice := []sdk.ValAddress{}
|
2018-11-04 18:28:38 -08:00
|
|
|
k.cdc.MustUnmarshalBinaryLengthPrefixed(validatorTimesliceIterator.Value(), ×lice)
|
2018-10-14 17:37:06 -07:00
|
|
|
matureValsAddrs = append(matureValsAddrs, timeslice...)
|
|
|
|
}
|
|
|
|
return matureValsAddrs
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unbonds all the unbonding validators that have finished their unbonding period
|
|
|
|
func (k Keeper) UnbondAllMatureValidatorQueue(ctx sdk.Context) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time)
|
|
|
|
for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() {
|
|
|
|
timeslice := []sdk.ValAddress{}
|
2018-11-04 18:28:38 -08:00
|
|
|
k.cdc.MustUnmarshalBinaryLengthPrefixed(validatorTimesliceIterator.Value(), ×lice)
|
2018-10-14 17:37:06 -07:00
|
|
|
for _, valAddr := range timeslice {
|
|
|
|
val, found := k.GetValidator(ctx, valAddr)
|
2018-11-08 16:28:28 -08:00
|
|
|
if !found {
|
2018-10-14 17:37:06 -07:00
|
|
|
continue
|
|
|
|
}
|
2018-11-08 16:28:28 -08:00
|
|
|
if val.GetStatus() != sdk.Unbonding {
|
|
|
|
panic("unexpected validator in unbonding queue, status was not unbonding")
|
|
|
|
}
|
2018-11-04 22:11:03 -08:00
|
|
|
k.unbondingToUnbonded(ctx, val)
|
2018-10-18 12:58:18 -07:00
|
|
|
if val.GetDelegatorShares().IsZero() {
|
|
|
|
k.RemoveValidator(ctx, val.OperatorAddr)
|
|
|
|
}
|
2018-10-14 17:37:06 -07:00
|
|
|
}
|
|
|
|
store.Delete(validatorTimesliceIterator.Key())
|
|
|
|
}
|
|
|
|
}
|