github.com/cosmos/cosmos-sdk@v0.50.10/x/staking/keeper/validator.go (about)

     1  package keeper
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"errors"
     7  	"fmt"
     8  	"time"
     9  
    10  	cmtprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto"
    11  	gogotypes "github.com/cosmos/gogoproto/types"
    12  
    13  	corestore "cosmossdk.io/core/store"
    14  	errorsmod "cosmossdk.io/errors"
    15  	"cosmossdk.io/math"
    16  	storetypes "cosmossdk.io/store/types"
    17  
    18  	sdk "github.com/cosmos/cosmos-sdk/types"
    19  	"github.com/cosmos/cosmos-sdk/x/staking/types"
    20  )
    21  
    22  // GetValidator gets a single validator
    23  func (k Keeper) GetValidator(ctx context.Context, addr sdk.ValAddress) (validator types.Validator, err error) {
    24  	store := k.storeService.OpenKVStore(ctx)
    25  	value, err := store.Get(types.GetValidatorKey(addr))
    26  	if err != nil {
    27  		return validator, err
    28  	}
    29  
    30  	if value == nil {
    31  		return validator, types.ErrNoValidatorFound
    32  	}
    33  
    34  	return types.UnmarshalValidator(k.cdc, value)
    35  }
    36  
    37  func (k Keeper) mustGetValidator(ctx context.Context, addr sdk.ValAddress) types.Validator {
    38  	validator, err := k.GetValidator(ctx, addr)
    39  	if err != nil {
    40  		panic(fmt.Sprintf("validator record not found for address: %X\n", addr))
    41  	}
    42  
    43  	return validator
    44  }
    45  
    46  // GetValidatorByConsAddr gets a single validator by consensus address
    47  func (k Keeper) GetValidatorByConsAddr(ctx context.Context, consAddr sdk.ConsAddress) (validator types.Validator, err error) {
    48  	store := k.storeService.OpenKVStore(ctx)
    49  	opAddr, err := store.Get(types.GetValidatorByConsAddrKey(consAddr))
    50  	if err != nil {
    51  		return validator, err
    52  	}
    53  
    54  	if opAddr == nil {
    55  		return validator, types.ErrNoValidatorFound
    56  	}
    57  
    58  	return k.GetValidator(ctx, opAddr)
    59  }
    60  
    61  func (k Keeper) mustGetValidatorByConsAddr(ctx context.Context, consAddr sdk.ConsAddress) types.Validator {
    62  	validator, err := k.GetValidatorByConsAddr(ctx, consAddr)
    63  	if err != nil {
    64  		panic(fmt.Errorf("validator with consensus-Address %s not found", consAddr))
    65  	}
    66  
    67  	return validator
    68  }
    69  
    70  // SetValidator sets the main record holding validator details
    71  func (k Keeper) SetValidator(ctx context.Context, validator types.Validator) error {
    72  	store := k.storeService.OpenKVStore(ctx)
    73  	bz := types.MustMarshalValidator(k.cdc, &validator)
    74  	str, err := k.ValidatorAddressCodec().StringToBytes(validator.GetOperator())
    75  	if err != nil {
    76  		return err
    77  	}
    78  	return store.Set(types.GetValidatorKey(str), bz)
    79  }
    80  
    81  // SetValidatorByConsAddr sets a validator by conesensus address
    82  func (k Keeper) SetValidatorByConsAddr(ctx context.Context, validator types.Validator) error {
    83  	consPk, err := validator.GetConsAddr()
    84  	if err != nil {
    85  		return err
    86  	}
    87  	store := k.storeService.OpenKVStore(ctx)
    88  
    89  	bz, err := k.validatorAddressCodec.StringToBytes(validator.GetOperator())
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	return store.Set(types.GetValidatorByConsAddrKey(consPk), bz)
    95  }
    96  
    97  // SetValidatorByPowerIndex sets a validator by power index
    98  func (k Keeper) SetValidatorByPowerIndex(ctx context.Context, validator types.Validator) error {
    99  	// jailed validators are not kept in the power index
   100  	if validator.Jailed {
   101  		return nil
   102  	}
   103  
   104  	store := k.storeService.OpenKVStore(ctx)
   105  	str, err := k.validatorAddressCodec.StringToBytes(validator.GetOperator())
   106  	if err != nil {
   107  		return err
   108  	}
   109  	return store.Set(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx), k.validatorAddressCodec), str)
   110  }
   111  
   112  // DeleteValidatorByPowerIndex deletes a record by power index
   113  func (k Keeper) DeleteValidatorByPowerIndex(ctx context.Context, validator types.Validator) error {
   114  	store := k.storeService.OpenKVStore(ctx)
   115  	return store.Delete(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx), k.validatorAddressCodec))
   116  }
   117  
   118  // SetNewValidatorByPowerIndex adds new entry by power index
   119  func (k Keeper) SetNewValidatorByPowerIndex(ctx context.Context, validator types.Validator) error {
   120  	store := k.storeService.OpenKVStore(ctx)
   121  	str, err := k.validatorAddressCodec.StringToBytes(validator.GetOperator())
   122  	if err != nil {
   123  		return err
   124  	}
   125  	return store.Set(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx), k.validatorAddressCodec), str)
   126  }
   127  
   128  // AddValidatorTokensAndShares updates the tokens of an existing validator, updates the validators power index key
   129  func (k Keeper) AddValidatorTokensAndShares(ctx context.Context, validator types.Validator,
   130  	tokensToAdd math.Int,
   131  ) (valOut types.Validator, addedShares math.LegacyDec, err error) {
   132  	err = k.DeleteValidatorByPowerIndex(ctx, validator)
   133  	if err != nil {
   134  		return valOut, addedShares, err
   135  	}
   136  
   137  	validator, addedShares = validator.AddTokensFromDel(tokensToAdd)
   138  	err = k.SetValidator(ctx, validator)
   139  	if err != nil {
   140  		return validator, addedShares, err
   141  	}
   142  
   143  	err = k.SetValidatorByPowerIndex(ctx, validator)
   144  	return validator, addedShares, err
   145  }
   146  
   147  // RemoveValidatorTokensAndShares updates the tokens of an existing validator, updates the validators power index key
   148  func (k Keeper) RemoveValidatorTokensAndShares(ctx context.Context, validator types.Validator,
   149  	sharesToRemove math.LegacyDec,
   150  ) (valOut types.Validator, removedTokens math.Int, err error) {
   151  	err = k.DeleteValidatorByPowerIndex(ctx, validator)
   152  	if err != nil {
   153  		return valOut, removedTokens, err
   154  	}
   155  	validator, removedTokens = validator.RemoveDelShares(sharesToRemove)
   156  	err = k.SetValidator(ctx, validator)
   157  	if err != nil {
   158  		return validator, removedTokens, err
   159  	}
   160  
   161  	err = k.SetValidatorByPowerIndex(ctx, validator)
   162  	return validator, removedTokens, err
   163  }
   164  
   165  // RemoveValidatorTokens updates the tokens of an existing validator, updates the validators power index key
   166  func (k Keeper) RemoveValidatorTokens(ctx context.Context,
   167  	validator types.Validator, tokensToRemove math.Int,
   168  ) (types.Validator, error) {
   169  	if err := k.DeleteValidatorByPowerIndex(ctx, validator); err != nil {
   170  		return validator, err
   171  	}
   172  
   173  	validator = validator.RemoveTokens(tokensToRemove)
   174  	if err := k.SetValidator(ctx, validator); err != nil {
   175  		return validator, err
   176  	}
   177  
   178  	if err := k.SetValidatorByPowerIndex(ctx, validator); err != nil {
   179  		return validator, err
   180  	}
   181  
   182  	return validator, nil
   183  }
   184  
   185  // UpdateValidatorCommission attempts to update a validator's commission rate.
   186  // An error is returned if the new commission rate is invalid.
   187  func (k Keeper) UpdateValidatorCommission(ctx context.Context,
   188  	validator types.Validator, newRate math.LegacyDec,
   189  ) (types.Commission, error) {
   190  	commission := validator.Commission
   191  	sdkCtx := sdk.UnwrapSDKContext(ctx)
   192  	blockTime := sdkCtx.BlockHeader().Time
   193  
   194  	if err := commission.ValidateNewRate(newRate, blockTime); err != nil {
   195  		return commission, err
   196  	}
   197  
   198  	minCommissionRate, err := k.MinCommissionRate(ctx)
   199  	if err != nil {
   200  		return commission, err
   201  	}
   202  
   203  	if newRate.LT(minCommissionRate) {
   204  		return commission, fmt.Errorf("cannot set validator commission to less than minimum rate of %s", minCommissionRate)
   205  	}
   206  
   207  	commission.Rate = newRate
   208  	commission.UpdateTime = blockTime
   209  
   210  	return commission, nil
   211  }
   212  
   213  // RemoveValidator removes the validator record and associated indexes
   214  // except for the bonded validator index which is only handled in ApplyAndReturnTendermintUpdates
   215  func (k Keeper) RemoveValidator(ctx context.Context, address sdk.ValAddress) error {
   216  	// first retrieve the old validator record
   217  	validator, err := k.GetValidator(ctx, address)
   218  	if errors.Is(err, types.ErrNoValidatorFound) {
   219  		return nil
   220  	}
   221  
   222  	if !validator.IsUnbonded() {
   223  		return types.ErrBadRemoveValidator.Wrap("cannot call RemoveValidator on bonded or unbonding validators")
   224  	}
   225  
   226  	if validator.Tokens.IsPositive() {
   227  		return types.ErrBadRemoveValidator.Wrap("attempting to remove a validator which still contains tokens")
   228  	}
   229  
   230  	valConsAddr, err := validator.GetConsAddr()
   231  	if err != nil {
   232  		return err
   233  	}
   234  
   235  	// delete the old validator record
   236  	store := k.storeService.OpenKVStore(ctx)
   237  	if err = store.Delete(types.GetValidatorKey(address)); err != nil {
   238  		return err
   239  	}
   240  
   241  	if err = store.Delete(types.GetValidatorByConsAddrKey(valConsAddr)); err != nil {
   242  		return err
   243  	}
   244  
   245  	if err = store.Delete(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx), k.validatorAddressCodec)); err != nil {
   246  		return err
   247  	}
   248  
   249  	str, err := k.validatorAddressCodec.StringToBytes(validator.GetOperator())
   250  	if err != nil {
   251  		return err
   252  	}
   253  
   254  	if err := k.Hooks().AfterValidatorRemoved(ctx, valConsAddr, str); err != nil {
   255  		k.Logger(ctx).Error("error in after validator removed hook", "error", err)
   256  	}
   257  
   258  	return nil
   259  }
   260  
   261  // get groups of validators
   262  
   263  // GetAllValidators gets the set of all validators with no limits, used during genesis dump
   264  func (k Keeper) GetAllValidators(ctx context.Context) (validators []types.Validator, err error) {
   265  	store := k.storeService.OpenKVStore(ctx)
   266  
   267  	iterator, err := store.Iterator(types.ValidatorsKey, storetypes.PrefixEndBytes(types.ValidatorsKey))
   268  	if err != nil {
   269  		return nil, err
   270  	}
   271  	defer iterator.Close()
   272  
   273  	for ; iterator.Valid(); iterator.Next() {
   274  		validator, err := types.UnmarshalValidator(k.cdc, iterator.Value())
   275  		if err != nil {
   276  			return nil, err
   277  		}
   278  		validators = append(validators, validator)
   279  	}
   280  
   281  	return validators, nil
   282  }
   283  
   284  // GetValidators returns a given amount of all the validators
   285  func (k Keeper) GetValidators(ctx context.Context, maxRetrieve uint32) (validators []types.Validator, err error) {
   286  	store := k.storeService.OpenKVStore(ctx)
   287  	validators = make([]types.Validator, maxRetrieve)
   288  
   289  	iterator, err := store.Iterator(types.ValidatorsKey, storetypes.PrefixEndBytes(types.ValidatorsKey))
   290  	if err != nil {
   291  		return nil, err
   292  	}
   293  
   294  	i := 0
   295  	for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
   296  		validator, err := types.UnmarshalValidator(k.cdc, iterator.Value())
   297  		if err != nil {
   298  			return nil, err
   299  		}
   300  		validators[i] = validator
   301  		i++
   302  	}
   303  
   304  	return validators[:i], nil // trim if the array length < maxRetrieve
   305  }
   306  
   307  // GetBondedValidatorsByPower gets the current group of bonded validators sorted by power-rank
   308  func (k Keeper) GetBondedValidatorsByPower(ctx context.Context) ([]types.Validator, error) {
   309  	maxValidators, err := k.MaxValidators(ctx)
   310  	if err != nil {
   311  		return nil, err
   312  	}
   313  	validators := make([]types.Validator, maxValidators)
   314  
   315  	iterator, err := k.ValidatorsPowerStoreIterator(ctx)
   316  	if err != nil {
   317  		return nil, err
   318  	}
   319  	defer iterator.Close()
   320  
   321  	i := 0
   322  	for ; iterator.Valid() && i < int(maxValidators); iterator.Next() {
   323  		address := iterator.Value()
   324  		validator := k.mustGetValidator(ctx, address)
   325  
   326  		if validator.IsBonded() {
   327  			validators[i] = validator
   328  			i++
   329  		}
   330  	}
   331  
   332  	return validators[:i], nil // trim
   333  }
   334  
   335  // ValidatorsPowerStoreIterator returns an iterator for the current validator power store
   336  func (k Keeper) ValidatorsPowerStoreIterator(ctx context.Context) (corestore.Iterator, error) {
   337  	store := k.storeService.OpenKVStore(ctx)
   338  	return store.ReverseIterator(types.ValidatorsByPowerIndexKey, storetypes.PrefixEndBytes(types.ValidatorsByPowerIndexKey))
   339  }
   340  
   341  // Last Validator Index
   342  
   343  // GetLastValidatorPower loads the last validator power.
   344  // Returns zero if the operator was not a validator last block.
   345  func (k Keeper) GetLastValidatorPower(ctx context.Context, operator sdk.ValAddress) (power int64, err error) {
   346  	store := k.storeService.OpenKVStore(ctx)
   347  	bz, err := store.Get(types.GetLastValidatorPowerKey(operator))
   348  	if err != nil {
   349  		return 0, err
   350  	}
   351  
   352  	if bz == nil {
   353  		return 0, nil
   354  	}
   355  
   356  	intV := gogotypes.Int64Value{}
   357  	err = k.cdc.Unmarshal(bz, &intV)
   358  	if err != nil {
   359  		return 0, err
   360  	}
   361  
   362  	return intV.GetValue(), nil
   363  }
   364  
   365  // SetLastValidatorPower sets the last validator power.
   366  func (k Keeper) SetLastValidatorPower(ctx context.Context, operator sdk.ValAddress, power int64) error {
   367  	store := k.storeService.OpenKVStore(ctx)
   368  	bz, err := k.cdc.Marshal(&gogotypes.Int64Value{Value: power})
   369  	if err != nil {
   370  		return err
   371  	}
   372  	return store.Set(types.GetLastValidatorPowerKey(operator), bz)
   373  }
   374  
   375  // DeleteLastValidatorPower deletes the last validator power.
   376  func (k Keeper) DeleteLastValidatorPower(ctx context.Context, operator sdk.ValAddress) error {
   377  	store := k.storeService.OpenKVStore(ctx)
   378  	return store.Delete(types.GetLastValidatorPowerKey(operator))
   379  }
   380  
   381  // lastValidatorsIterator returns an iterator for the consensus validators in the last block
   382  func (k Keeper) LastValidatorsIterator(ctx context.Context) (corestore.Iterator, error) {
   383  	store := k.storeService.OpenKVStore(ctx)
   384  	return store.Iterator(types.LastValidatorPowerKey, storetypes.PrefixEndBytes(types.LastValidatorPowerKey))
   385  }
   386  
   387  // IterateLastValidatorPowers iterates over last validator powers.
   388  func (k Keeper) IterateLastValidatorPowers(ctx context.Context, handler func(operator sdk.ValAddress, power int64) (stop bool)) error {
   389  	iter, err := k.LastValidatorsIterator(ctx)
   390  	if err != nil {
   391  		return err
   392  	}
   393  
   394  	for ; iter.Valid(); iter.Next() {
   395  		addr := sdk.ValAddress(types.AddressFromLastValidatorPowerKey(iter.Key()))
   396  		intV := &gogotypes.Int64Value{}
   397  
   398  		if err = k.cdc.Unmarshal(iter.Value(), intV); err != nil {
   399  			return err
   400  		}
   401  
   402  		if handler(addr, intV.GetValue()) {
   403  			break
   404  		}
   405  	}
   406  
   407  	return nil
   408  }
   409  
   410  // GetLastValidators gets the group of the bonded validators
   411  func (k Keeper) GetLastValidators(ctx context.Context) (validators []types.Validator, err error) {
   412  	store := k.storeService.OpenKVStore(ctx)
   413  
   414  	// add the actual validator power sorted store
   415  	maxValidators, err := k.MaxValidators(ctx)
   416  	if err != nil {
   417  		return nil, err
   418  	}
   419  	validators = make([]types.Validator, maxValidators)
   420  
   421  	iterator, err := store.Iterator(types.LastValidatorPowerKey, storetypes.PrefixEndBytes(types.LastValidatorPowerKey))
   422  	if err != nil {
   423  		return nil, err
   424  	}
   425  	defer iterator.Close()
   426  
   427  	i := 0
   428  	for ; iterator.Valid(); iterator.Next() {
   429  		// sanity check
   430  		if i >= int(maxValidators) {
   431  			panic("more validators than maxValidators found")
   432  		}
   433  
   434  		address := types.AddressFromLastValidatorPowerKey(iterator.Key())
   435  		validator, err := k.GetValidator(ctx, address)
   436  		if err != nil {
   437  			return nil, err
   438  		}
   439  
   440  		validators[i] = validator
   441  		i++
   442  	}
   443  
   444  	return validators[:i], nil // trim
   445  }
   446  
   447  // GetUnbondingValidators returns a slice of mature validator addresses that
   448  // complete their unbonding at a given time and height.
   449  func (k Keeper) GetUnbondingValidators(ctx context.Context, endTime time.Time, endHeight int64) ([]string, error) {
   450  	store := k.storeService.OpenKVStore(ctx)
   451  
   452  	bz, err := store.Get(types.GetValidatorQueueKey(endTime, endHeight))
   453  	if err != nil {
   454  		return nil, err
   455  	}
   456  
   457  	if bz == nil {
   458  		return []string{}, nil
   459  	}
   460  
   461  	addrs := types.ValAddresses{}
   462  	if err = k.cdc.Unmarshal(bz, &addrs); err != nil {
   463  		return nil, err
   464  	}
   465  
   466  	return addrs.Addresses, nil
   467  }
   468  
   469  // SetUnbondingValidatorsQueue sets a given slice of validator addresses into
   470  // the unbonding validator queue by a given height and time.
   471  func (k Keeper) SetUnbondingValidatorsQueue(ctx context.Context, endTime time.Time, endHeight int64, addrs []string) error {
   472  	store := k.storeService.OpenKVStore(ctx)
   473  	bz, err := k.cdc.Marshal(&types.ValAddresses{Addresses: addrs})
   474  	if err != nil {
   475  		return err
   476  	}
   477  	return store.Set(types.GetValidatorQueueKey(endTime, endHeight), bz)
   478  }
   479  
   480  // InsertUnbondingValidatorQueue inserts a given unbonding validator address into
   481  // the unbonding validator queue for a given height and time.
   482  func (k Keeper) InsertUnbondingValidatorQueue(ctx context.Context, val types.Validator) error {
   483  	addrs, err := k.GetUnbondingValidators(ctx, val.UnbondingTime, val.UnbondingHeight)
   484  	if err != nil {
   485  		return err
   486  	}
   487  	addrs = append(addrs, val.OperatorAddress)
   488  	return k.SetUnbondingValidatorsQueue(ctx, val.UnbondingTime, val.UnbondingHeight, addrs)
   489  }
   490  
   491  // DeleteValidatorQueueTimeSlice deletes all entries in the queue indexed by a
   492  // given height and time.
   493  func (k Keeper) DeleteValidatorQueueTimeSlice(ctx context.Context, endTime time.Time, endHeight int64) error {
   494  	store := k.storeService.OpenKVStore(ctx)
   495  	return store.Delete(types.GetValidatorQueueKey(endTime, endHeight))
   496  }
   497  
   498  // DeleteValidatorQueue removes a validator by address from the unbonding queue
   499  // indexed by a given height and time.
   500  func (k Keeper) DeleteValidatorQueue(ctx context.Context, val types.Validator) error {
   501  	addrs, err := k.GetUnbondingValidators(ctx, val.UnbondingTime, val.UnbondingHeight)
   502  	if err != nil {
   503  		return err
   504  	}
   505  	newAddrs := []string{}
   506  
   507  	// since address string may change due to Bech32 prefix change, we parse the addresses into bytes
   508  	// format for normalization
   509  	deletingAddr, err := k.validatorAddressCodec.StringToBytes(val.OperatorAddress)
   510  	if err != nil {
   511  		return err
   512  	}
   513  
   514  	for _, addr := range addrs {
   515  		storedAddr, err := k.validatorAddressCodec.StringToBytes(addr)
   516  		if err != nil {
   517  			// even if we don't error here, it will error in UnbondAllMatureValidators at unbond time
   518  			return err
   519  		}
   520  		if !bytes.Equal(storedAddr, deletingAddr) {
   521  			newAddrs = append(newAddrs, addr)
   522  		}
   523  	}
   524  
   525  	if len(newAddrs) == 0 {
   526  		return k.DeleteValidatorQueueTimeSlice(ctx, val.UnbondingTime, val.UnbondingHeight)
   527  	}
   528  
   529  	return k.SetUnbondingValidatorsQueue(ctx, val.UnbondingTime, val.UnbondingHeight, newAddrs)
   530  }
   531  
   532  // ValidatorQueueIterator returns an interator ranging over validators that are
   533  // unbonding whose unbonding completion occurs at the given height and time.
   534  func (k Keeper) ValidatorQueueIterator(ctx context.Context, endTime time.Time, endHeight int64) (corestore.Iterator, error) {
   535  	store := k.storeService.OpenKVStore(ctx)
   536  	return store.Iterator(types.ValidatorQueueKey, storetypes.InclusiveEndBytes(types.GetValidatorQueueKey(endTime, endHeight)))
   537  }
   538  
   539  // UnbondAllMatureValidators unbonds all the mature unbonding validators that
   540  // have finished their unbonding period.
   541  func (k Keeper) UnbondAllMatureValidators(ctx context.Context) error {
   542  	sdkCtx := sdk.UnwrapSDKContext(ctx)
   543  	blockTime := sdkCtx.BlockTime()
   544  	blockHeight := sdkCtx.BlockHeight()
   545  
   546  	// unbondingValIterator will contains all validator addresses indexed under
   547  	// the ValidatorQueueKey prefix. Note, the entire index key is composed as
   548  	// ValidatorQueueKey | timeBzLen (8-byte big endian) | timeBz | heightBz (8-byte big endian),
   549  	// so it may be possible that certain validator addresses that are iterated
   550  	// over are not ready to unbond, so an explicit check is required.
   551  	unbondingValIterator, err := k.ValidatorQueueIterator(ctx, blockTime, blockHeight)
   552  	if err != nil {
   553  		return err
   554  	}
   555  	defer unbondingValIterator.Close()
   556  
   557  	for ; unbondingValIterator.Valid(); unbondingValIterator.Next() {
   558  		key := unbondingValIterator.Key()
   559  		keyTime, keyHeight, err := types.ParseValidatorQueueKey(key)
   560  		if err != nil {
   561  			return fmt.Errorf("failed to parse unbonding key: %w", err)
   562  		}
   563  
   564  		// All addresses for the given key have the same unbonding height and time.
   565  		// We only unbond if the height and time are less than the current height
   566  		// and time.
   567  		if keyHeight <= blockHeight && (keyTime.Before(blockTime) || keyTime.Equal(blockTime)) {
   568  			addrs := types.ValAddresses{}
   569  			if err = k.cdc.Unmarshal(unbondingValIterator.Value(), &addrs); err != nil {
   570  				return err
   571  			}
   572  
   573  			for _, valAddr := range addrs.Addresses {
   574  				addr, err := k.validatorAddressCodec.StringToBytes(valAddr)
   575  				if err != nil {
   576  					return err
   577  				}
   578  				val, err := k.GetValidator(ctx, addr)
   579  				if err != nil {
   580  					return errorsmod.Wrap(err, "validator in the unbonding queue was not found")
   581  				}
   582  
   583  				if !val.IsUnbonding() {
   584  					return fmt.Errorf("unexpected validator in unbonding queue; status was not unbonding")
   585  				}
   586  
   587  				if val.UnbondingOnHoldRefCount == 0 {
   588  					for _, id := range val.UnbondingIds {
   589  						if err = k.DeleteUnbondingIndex(ctx, id); err != nil {
   590  							return err
   591  						}
   592  					}
   593  
   594  					val, err = k.UnbondingToUnbonded(ctx, val)
   595  					if err != nil {
   596  						return err
   597  					}
   598  
   599  					if val.GetDelegatorShares().IsZero() {
   600  						str, err := k.validatorAddressCodec.StringToBytes(val.GetOperator())
   601  						if err != nil {
   602  							return err
   603  						}
   604  						if err = k.RemoveValidator(ctx, str); err != nil {
   605  							return err
   606  						}
   607  					} else {
   608  						// remove unbonding ids
   609  						val.UnbondingIds = []uint64{}
   610  					}
   611  
   612  					// remove validator from queue
   613  					if err = k.DeleteValidatorQueue(ctx, val); err != nil {
   614  						return err
   615  					}
   616  				}
   617  			}
   618  		}
   619  	}
   620  	return nil
   621  }
   622  
   623  // IsValidatorJailed checks and returns boolean of a validator status jailed or not.
   624  func (k Keeper) IsValidatorJailed(ctx context.Context, addr sdk.ConsAddress) (bool, error) {
   625  	v, err := k.GetValidatorByConsAddr(ctx, addr)
   626  	if err != nil {
   627  		return false, err
   628  	}
   629  
   630  	return v.Jailed, nil
   631  }
   632  
   633  // GetPubKeyByConsAddr returns the consensus public key by consensus address.
   634  func (k Keeper) GetPubKeyByConsAddr(ctx context.Context, addr sdk.ConsAddress) (cmtprotocrypto.PublicKey, error) {
   635  	v, err := k.GetValidatorByConsAddr(ctx, addr)
   636  	if err != nil {
   637  		return cmtprotocrypto.PublicKey{}, err
   638  	}
   639  
   640  	pubkey, err := v.CmtConsPublicKey()
   641  	if err != nil {
   642  		return cmtprotocrypto.PublicKey{}, err
   643  	}
   644  
   645  	return pubkey, nil
   646  }