github.com/Finschia/finschia-sdk@v0.48.1/x/staking/keeper/validator.go (about)

     1  package keeper
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	gogotypes "github.com/gogo/protobuf/types"
     8  
     9  	sdk "github.com/Finschia/finschia-sdk/types"
    10  	"github.com/Finschia/finschia-sdk/x/staking/types"
    11  )
    12  
    13  // get a single validator
    14  func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator types.Validator, found bool) {
    15  	store := ctx.KVStore(k.storeKey)
    16  
    17  	value := store.Get(types.GetValidatorKey(addr))
    18  	if value == nil {
    19  		return validator, false
    20  	}
    21  
    22  	validator = types.MustUnmarshalValidator(k.cdc, value)
    23  	return validator, true
    24  }
    25  
    26  func (k Keeper) mustGetValidator(ctx sdk.Context, addr sdk.ValAddress) types.Validator {
    27  	validator, found := k.GetValidator(ctx, addr)
    28  	if !found {
    29  		panic(fmt.Sprintf("validator record not found for address: %X\n", addr))
    30  	}
    31  
    32  	return validator
    33  }
    34  
    35  // get a single validator by consensus address
    36  func (k Keeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator types.Validator, found bool) {
    37  	store := ctx.KVStore(k.storeKey)
    38  
    39  	opAddr := store.Get(types.GetValidatorByConsAddrKey(consAddr))
    40  	if opAddr == nil {
    41  		return validator, false
    42  	}
    43  
    44  	return k.GetValidator(ctx, opAddr)
    45  }
    46  
    47  func (k Keeper) mustGetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) types.Validator {
    48  	validator, found := k.GetValidatorByConsAddr(ctx, consAddr)
    49  	if !found {
    50  		panic(fmt.Errorf("validator with consensus-Address %s not found", consAddr))
    51  	}
    52  
    53  	return validator
    54  }
    55  
    56  // set the main record holding validator details
    57  func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) {
    58  	store := ctx.KVStore(k.storeKey)
    59  	bz := types.MustMarshalValidator(k.cdc, &validator)
    60  	store.Set(types.GetValidatorKey(validator.GetOperator()), bz)
    61  }
    62  
    63  // validator index
    64  func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) error {
    65  	consPk, err := validator.GetConsAddr()
    66  	if err != nil {
    67  		return err
    68  	}
    69  	store := ctx.KVStore(k.storeKey)
    70  	store.Set(types.GetValidatorByConsAddrKey(consPk), validator.GetOperator())
    71  	return nil
    72  }
    73  
    74  // validator index
    75  func (k Keeper) SetValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
    76  	// jailed validators are not kept in the power index
    77  	if validator.Jailed {
    78  		return
    79  	}
    80  
    81  	store := ctx.KVStore(k.storeKey)
    82  	store.Set(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx)), validator.GetOperator())
    83  }
    84  
    85  // validator index
    86  func (k Keeper) DeleteValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
    87  	store := ctx.KVStore(k.storeKey)
    88  	store.Delete(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx)))
    89  }
    90  
    91  // validator index
    92  func (k Keeper) SetNewValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
    93  	store := ctx.KVStore(k.storeKey)
    94  	store.Set(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx)), validator.GetOperator())
    95  }
    96  
    97  // Update the tokens of an existing validator, update the validators power index key
    98  func (k Keeper) AddValidatorTokensAndShares(ctx sdk.Context, validator types.Validator,
    99  	tokensToAdd sdk.Int,
   100  ) (valOut types.Validator, addedShares sdk.Dec) {
   101  	k.DeleteValidatorByPowerIndex(ctx, validator)
   102  	validator, addedShares = validator.AddTokensFromDel(tokensToAdd)
   103  	k.SetValidator(ctx, validator)
   104  	k.SetValidatorByPowerIndex(ctx, validator)
   105  
   106  	return validator, addedShares
   107  }
   108  
   109  // Update the tokens of an existing validator, update the validators power index key
   110  func (k Keeper) RemoveValidatorTokensAndShares(ctx sdk.Context, validator types.Validator,
   111  	sharesToRemove sdk.Dec,
   112  ) (valOut types.Validator, removedTokens sdk.Int) {
   113  	k.DeleteValidatorByPowerIndex(ctx, validator)
   114  	validator, removedTokens = validator.RemoveDelShares(sharesToRemove)
   115  	k.SetValidator(ctx, validator)
   116  	k.SetValidatorByPowerIndex(ctx, validator)
   117  
   118  	return validator, removedTokens
   119  }
   120  
   121  // Update the tokens of an existing validator, update the validators power index key
   122  func (k Keeper) RemoveValidatorTokens(ctx sdk.Context,
   123  	validator types.Validator, tokensToRemove sdk.Int,
   124  ) types.Validator {
   125  	k.DeleteValidatorByPowerIndex(ctx, validator)
   126  	validator = validator.RemoveTokens(tokensToRemove)
   127  	k.SetValidator(ctx, validator)
   128  	k.SetValidatorByPowerIndex(ctx, validator)
   129  
   130  	return validator
   131  }
   132  
   133  // UpdateValidatorCommission attempts to update a validator's commission rate.
   134  // An error is returned if the new commission rate is invalid.
   135  func (k Keeper) UpdateValidatorCommission(ctx sdk.Context,
   136  	validator types.Validator, newRate sdk.Dec,
   137  ) (types.Commission, error) {
   138  	commission := validator.Commission
   139  	blockTime := ctx.BlockHeader().Time
   140  
   141  	if err := commission.ValidateNewRate(newRate, blockTime); err != nil {
   142  		return commission, err
   143  	}
   144  
   145  	commission.Rate = newRate
   146  	commission.UpdateTime = blockTime
   147  
   148  	return commission, nil
   149  }
   150  
   151  // remove the validator record and associated indexes
   152  // except for the bonded validator index which is only handled in ApplyAndReturnTendermintUpdates
   153  // TODO, this function panics, and it's not good.
   154  func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
   155  	// first retrieve the old validator record
   156  	validator, found := k.GetValidator(ctx, address)
   157  	if !found {
   158  		return
   159  	}
   160  
   161  	if !validator.IsUnbonded() {
   162  		panic("cannot call RemoveValidator on bonded or unbonding validators")
   163  	}
   164  
   165  	if validator.Tokens.IsPositive() {
   166  		panic("attempting to remove a validator which still contains tokens")
   167  	}
   168  
   169  	valConsAddr, err := validator.GetConsAddr()
   170  	if err != nil {
   171  		panic(err)
   172  	}
   173  
   174  	// delete the old validator record
   175  	store := ctx.KVStore(k.storeKey)
   176  	store.Delete(types.GetValidatorKey(address))
   177  	store.Delete(types.GetValidatorByConsAddrKey(valConsAddr))
   178  	store.Delete(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx)))
   179  
   180  	// call hooks
   181  	k.AfterValidatorRemoved(ctx, valConsAddr, validator.GetOperator())
   182  }
   183  
   184  // get groups of validators
   185  
   186  // get the set of all validators with no limits, used during genesis dump
   187  func (k Keeper) GetAllValidators(ctx sdk.Context) (validators []types.Validator) {
   188  	store := ctx.KVStore(k.storeKey)
   189  
   190  	iterator := sdk.KVStorePrefixIterator(store, types.ValidatorsKey)
   191  	defer iterator.Close()
   192  
   193  	for ; iterator.Valid(); iterator.Next() {
   194  		validator := types.MustUnmarshalValidator(k.cdc, iterator.Value())
   195  		validators = append(validators, validator)
   196  	}
   197  
   198  	return validators
   199  }
   200  
   201  // return a given amount of all the validators
   202  func (k Keeper) GetValidators(ctx sdk.Context, maxRetrieve uint32) (validators []types.Validator) {
   203  	store := ctx.KVStore(k.storeKey)
   204  	validators = make([]types.Validator, maxRetrieve)
   205  
   206  	iterator := sdk.KVStorePrefixIterator(store, types.ValidatorsKey)
   207  	defer iterator.Close()
   208  
   209  	i := 0
   210  	for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
   211  		validator := types.MustUnmarshalValidator(k.cdc, iterator.Value())
   212  		validators[i] = validator
   213  		i++
   214  	}
   215  
   216  	return validators[:i] // trim if the array length < maxRetrieve
   217  }
   218  
   219  // get the current group of bonded validators sorted by power-rank
   220  func (k Keeper) GetBondedValidatorsByPower(ctx sdk.Context) []types.Validator {
   221  	maxValidators := k.MaxValidators(ctx)
   222  	validators := make([]types.Validator, maxValidators)
   223  
   224  	iterator := k.ValidatorsPowerStoreIterator(ctx)
   225  	defer iterator.Close()
   226  
   227  	i := 0
   228  	for ; iterator.Valid() && i < int(maxValidators); iterator.Next() {
   229  		address := iterator.Value()
   230  		validator := k.mustGetValidator(ctx, address)
   231  
   232  		if validator.IsBonded() {
   233  			validators[i] = validator
   234  			i++
   235  		}
   236  	}
   237  
   238  	return validators[:i] // trim
   239  }
   240  
   241  // returns an iterator for the current validator power store
   242  func (k Keeper) ValidatorsPowerStoreIterator(ctx sdk.Context) sdk.Iterator {
   243  	store := ctx.KVStore(k.storeKey)
   244  	return sdk.KVStoreReversePrefixIterator(store, types.ValidatorsByPowerIndexKey)
   245  }
   246  
   247  // Last Validator Index
   248  
   249  // Load the last validator power.
   250  // Returns zero if the operator was not a validator last block.
   251  func (k Keeper) GetLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress) (power int64) {
   252  	store := ctx.KVStore(k.storeKey)
   253  
   254  	bz := store.Get(types.GetLastValidatorPowerKey(operator))
   255  	if bz == nil {
   256  		return 0
   257  	}
   258  
   259  	intV := gogotypes.Int64Value{}
   260  	k.cdc.MustUnmarshal(bz, &intV)
   261  
   262  	return intV.GetValue()
   263  }
   264  
   265  // Set the last validator power.
   266  func (k Keeper) SetLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress, power int64) {
   267  	store := ctx.KVStore(k.storeKey)
   268  	bz := k.cdc.MustMarshal(&gogotypes.Int64Value{Value: power})
   269  	store.Set(types.GetLastValidatorPowerKey(operator), bz)
   270  }
   271  
   272  // Delete the last validator power.
   273  func (k Keeper) DeleteLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress) {
   274  	store := ctx.KVStore(k.storeKey)
   275  	store.Delete(types.GetLastValidatorPowerKey(operator))
   276  }
   277  
   278  // returns an iterator for the consensus validators in the last block
   279  func (k Keeper) LastValidatorsIterator(ctx sdk.Context) (iterator sdk.Iterator) {
   280  	store := ctx.KVStore(k.storeKey)
   281  	iterator = sdk.KVStorePrefixIterator(store, types.LastValidatorPowerKey)
   282  
   283  	return iterator
   284  }
   285  
   286  // Iterate over last validator powers.
   287  func (k Keeper) IterateLastValidatorPowers(ctx sdk.Context, handler func(operator sdk.ValAddress, power int64) (stop bool)) {
   288  	store := ctx.KVStore(k.storeKey)
   289  
   290  	iter := sdk.KVStorePrefixIterator(store, types.LastValidatorPowerKey)
   291  	defer iter.Close()
   292  
   293  	for ; iter.Valid(); iter.Next() {
   294  		addr := sdk.ValAddress(types.AddressFromLastValidatorPowerKey(iter.Key()))
   295  		intV := &gogotypes.Int64Value{}
   296  
   297  		k.cdc.MustUnmarshal(iter.Value(), intV)
   298  
   299  		if handler(addr, intV.GetValue()) {
   300  			break
   301  		}
   302  	}
   303  }
   304  
   305  // get the group of the bonded validators
   306  func (k Keeper) GetLastValidators(ctx sdk.Context) (validators []types.Validator) {
   307  	store := ctx.KVStore(k.storeKey)
   308  
   309  	// add the actual validator power sorted store
   310  	maxValidators := k.MaxValidators(ctx)
   311  	validators = make([]types.Validator, maxValidators)
   312  
   313  	iterator := sdk.KVStorePrefixIterator(store, types.LastValidatorPowerKey)
   314  	defer iterator.Close()
   315  
   316  	i := 0
   317  	for ; iterator.Valid(); iterator.Next() {
   318  		// sanity check
   319  		if i >= int(maxValidators) {
   320  			panic("more validators than maxValidators found")
   321  		}
   322  
   323  		address := types.AddressFromLastValidatorPowerKey(iterator.Key())
   324  		validator := k.mustGetValidator(ctx, address)
   325  
   326  		validators[i] = validator
   327  		i++
   328  	}
   329  
   330  	return validators[:i] // trim
   331  }
   332  
   333  // GetUnbondingValidators returns a slice of mature validator addresses that
   334  // complete their unbonding at a given time and height.
   335  func (k Keeper) GetUnbondingValidators(ctx sdk.Context, endTime time.Time, endHeight int64) []string {
   336  	store := ctx.KVStore(k.storeKey)
   337  
   338  	bz := store.Get(types.GetValidatorQueueKey(endTime, endHeight))
   339  	if bz == nil {
   340  		return []string{}
   341  	}
   342  
   343  	addrs := types.ValAddresses{}
   344  	k.cdc.MustUnmarshal(bz, &addrs)
   345  
   346  	return addrs.Addresses
   347  }
   348  
   349  // SetUnbondingValidatorsQueue sets a given slice of validator addresses into
   350  // the unbonding validator queue by a given height and time.
   351  func (k Keeper) SetUnbondingValidatorsQueue(ctx sdk.Context, endTime time.Time, endHeight int64, addrs []string) {
   352  	store := ctx.KVStore(k.storeKey)
   353  	bz := k.cdc.MustMarshal(&types.ValAddresses{Addresses: addrs})
   354  	store.Set(types.GetValidatorQueueKey(endTime, endHeight), bz)
   355  }
   356  
   357  // InsertUnbondingValidatorQueue inserts a given unbonding validator address into
   358  // the unbonding validator queue for a given height and time.
   359  func (k Keeper) InsertUnbondingValidatorQueue(ctx sdk.Context, val types.Validator) {
   360  	addrs := k.GetUnbondingValidators(ctx, val.UnbondingTime, val.UnbondingHeight)
   361  	addrs = append(addrs, val.OperatorAddress)
   362  	k.SetUnbondingValidatorsQueue(ctx, val.UnbondingTime, val.UnbondingHeight, addrs)
   363  }
   364  
   365  // DeleteValidatorQueueTimeSlice deletes all entries in the queue indexed by a
   366  // given height and time.
   367  func (k Keeper) DeleteValidatorQueueTimeSlice(ctx sdk.Context, endTime time.Time, endHeight int64) {
   368  	store := ctx.KVStore(k.storeKey)
   369  	store.Delete(types.GetValidatorQueueKey(endTime, endHeight))
   370  }
   371  
   372  // DeleteValidatorQueue removes a validator by address from the unbonding queue
   373  // indexed by a given height and time.
   374  func (k Keeper) DeleteValidatorQueue(ctx sdk.Context, val types.Validator) {
   375  	addrs := k.GetUnbondingValidators(ctx, val.UnbondingTime, val.UnbondingHeight)
   376  	newAddrs := []string{}
   377  
   378  	for _, addr := range addrs {
   379  		if addr != val.OperatorAddress {
   380  			newAddrs = append(newAddrs, addr)
   381  		}
   382  	}
   383  
   384  	if len(newAddrs) == 0 {
   385  		k.DeleteValidatorQueueTimeSlice(ctx, val.UnbondingTime, val.UnbondingHeight)
   386  	} else {
   387  		k.SetUnbondingValidatorsQueue(ctx, val.UnbondingTime, val.UnbondingHeight, newAddrs)
   388  	}
   389  }
   390  
   391  // ValidatorQueueIterator returns an interator ranging over validators that are
   392  // unbonding whose unbonding completion occurs at the given height and time.
   393  func (k Keeper) ValidatorQueueIterator(ctx sdk.Context, endTime time.Time, endHeight int64) sdk.Iterator {
   394  	store := ctx.KVStore(k.storeKey)
   395  	return store.Iterator(types.ValidatorQueueKey, sdk.InclusiveEndBytes(types.GetValidatorQueueKey(endTime, endHeight)))
   396  }
   397  
   398  // UnbondAllMatureValidators unbonds all the mature unbonding validators that
   399  // have finished their unbonding period.
   400  func (k Keeper) UnbondAllMatureValidators(ctx sdk.Context) {
   401  	store := ctx.KVStore(k.storeKey)
   402  
   403  	blockTime := ctx.BlockTime()
   404  	blockHeight := ctx.BlockHeight()
   405  
   406  	// unbondingValIterator will contains all validator addresses indexed under
   407  	// the ValidatorQueueKey prefix. Note, the entire index key is composed as
   408  	// ValidatorQueueKey | timeBzLen (8-byte big endian) | timeBz | heightBz (8-byte big endian),
   409  	// so it may be possible that certain validator addresses that are iterated
   410  	// over are not ready to unbond, so an explicit check is required.
   411  	unbondingValIterator := k.ValidatorQueueIterator(ctx, blockTime, blockHeight)
   412  	defer unbondingValIterator.Close()
   413  
   414  	for ; unbondingValIterator.Valid(); unbondingValIterator.Next() {
   415  		key := unbondingValIterator.Key()
   416  		keyTime, keyHeight, err := types.ParseValidatorQueueKey(key)
   417  		if err != nil {
   418  			panic(fmt.Errorf("failed to parse unbonding key: %w", err))
   419  		}
   420  
   421  		// All addresses for the given key have the same unbonding height and time.
   422  		// We only unbond if the height and time are less than the current height
   423  		// and time.
   424  		if keyHeight <= blockHeight && (keyTime.Before(blockTime) || keyTime.Equal(blockTime)) {
   425  			addrs := types.ValAddresses{}
   426  			k.cdc.MustUnmarshal(unbondingValIterator.Value(), &addrs)
   427  
   428  			for _, valAddr := range addrs.Addresses {
   429  				addr, err := sdk.ValAddressFromBech32(valAddr)
   430  				if err != nil {
   431  					panic(err)
   432  				}
   433  				val, found := k.GetValidator(ctx, addr)
   434  				if !found {
   435  					panic("validator in the unbonding queue was not found")
   436  				}
   437  
   438  				if !val.IsUnbonding() {
   439  					panic("unexpected validator in unbonding queue; status was not unbonding")
   440  				}
   441  
   442  				val = k.UnbondingToUnbonded(ctx, val)
   443  				if val.GetDelegatorShares().IsZero() {
   444  					k.RemoveValidator(ctx, val.GetOperator())
   445  				}
   446  			}
   447  
   448  			store.Delete(key)
   449  		}
   450  	}
   451  }