github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/staking/keeper/validator.go (about)

     1  package keeper
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"time"
     7  
     8  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     9  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/staking/types"
    10  )
    11  
    12  // Cache the amino decoding of validators, as it can be the case that repeated slashing calls
    13  // cause many calls to GetValidator, which were shown to throttle the state machine in our
    14  // simulation. Note this is quite biased though, as the simulator does more slashes than a
    15  // live chain should, however we require the slashing to be fast as noone pays gas for it.
    16  type cachedValidator struct {
    17  	val        types.Validator
    18  	marshalled string // marshalled amino bytes for the validator object (not operator address)
    19  }
    20  
    21  func newCachedValidator(val types.Validator, marshalled string) cachedValidator {
    22  	return cachedValidator{
    23  		val:        val,
    24  		marshalled: marshalled,
    25  	}
    26  }
    27  
    28  // get a single validator
    29  func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator types.Validator, found bool) {
    30  	store := ctx.KVStore(k.storeKey)
    31  	value := store.Get(types.GetValidatorKey(addr))
    32  	if value == nil {
    33  		return validator, false
    34  	}
    35  
    36  	// If these amino encoded bytes are in the cache, return the cached validator
    37  	strValue := string(value)
    38  	if val, ok := k.validatorCache[strValue]; ok {
    39  		valToReturn := val.val
    40  		// Doesn't mutate the cache's value
    41  		valToReturn.OperatorAddress = addr
    42  		return valToReturn, true
    43  	}
    44  
    45  	// amino bytes weren't found in cache, so amino unmarshal and add it to the cache
    46  	validator = types.MustUnmarshalValidator(k.cdc, value)
    47  	cachedVal := newCachedValidator(validator, strValue)
    48  	k.validatorCache[strValue] = newCachedValidator(validator, strValue)
    49  	k.validatorCacheList.PushBack(cachedVal)
    50  
    51  	// if the cache is too big, pop off the last element from it
    52  	if k.validatorCacheList.Len() > aminoCacheSize {
    53  		valToRemove := k.validatorCacheList.Remove(k.validatorCacheList.Front()).(cachedValidator)
    54  		delete(k.validatorCache, valToRemove.marshalled)
    55  	}
    56  
    57  	validator = types.MustUnmarshalValidator(k.cdc, value)
    58  	return validator, true
    59  }
    60  
    61  func (k Keeper) mustGetValidator(ctx sdk.Context, addr sdk.ValAddress) types.Validator {
    62  	validator, found := k.GetValidator(ctx, addr)
    63  	if !found {
    64  		panic(fmt.Sprintf("validator record not found for address: %X\n", addr))
    65  	}
    66  	return validator
    67  }
    68  
    69  // get a single validator by consensus address
    70  func (k Keeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator types.Validator, found bool) {
    71  	store := ctx.KVStore(k.storeKey)
    72  	opAddr := store.Get(types.GetValidatorByConsAddrKey(consAddr))
    73  	if opAddr == nil {
    74  		return validator, false
    75  	}
    76  	return k.GetValidator(ctx, opAddr)
    77  }
    78  
    79  func (k Keeper) mustGetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) types.Validator {
    80  	validator, found := k.GetValidatorByConsAddr(ctx, consAddr)
    81  	if !found {
    82  		panic(fmt.Errorf("validator with consensus-Address %s not found", consAddr))
    83  	}
    84  	return validator
    85  }
    86  
    87  // set the main record holding validator details
    88  func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) {
    89  	store := ctx.KVStore(k.storeKey)
    90  	bz := types.MustMarshalValidator(k.cdc, validator)
    91  	store.Set(types.GetValidatorKey(validator.OperatorAddress), bz)
    92  }
    93  
    94  // validator index
    95  func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) {
    96  	store := ctx.KVStore(k.storeKey)
    97  	consAddr := sdk.ConsAddress(validator.ConsPubKey.Address())
    98  	store.Set(types.GetValidatorByConsAddrKey(consAddr), validator.OperatorAddress)
    99  }
   100  
   101  // validator index
   102  func (k Keeper) SetValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
   103  	// jailed validators are not kept in the power index
   104  	if validator.Jailed {
   105  		return
   106  	}
   107  	store := ctx.KVStore(k.storeKey)
   108  	store.Set(types.GetValidatorsByPowerIndexKey(validator), validator.OperatorAddress)
   109  }
   110  
   111  // validator index
   112  func (k Keeper) DeleteValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
   113  	store := ctx.KVStore(k.storeKey)
   114  	store.Delete(types.GetValidatorsByPowerIndexKey(validator))
   115  }
   116  
   117  // validator index
   118  func (k Keeper) SetNewValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
   119  	store := ctx.KVStore(k.storeKey)
   120  	store.Set(types.GetValidatorsByPowerIndexKey(validator), validator.OperatorAddress)
   121  }
   122  
   123  // Update the tokens of an existing validator, update the validators power index key
   124  func (k Keeper) AddValidatorTokensAndShares(ctx sdk.Context, validator types.Validator,
   125  	tokensToAdd sdk.Int) (valOut types.Validator, addedShares sdk.Dec) {
   126  
   127  	k.DeleteValidatorByPowerIndex(ctx, validator)
   128  	validator, addedShares = validator.AddTokensFromDel(tokensToAdd)
   129  	k.SetValidator(ctx, validator)
   130  	k.SetValidatorByPowerIndex(ctx, validator)
   131  	return validator, addedShares
   132  }
   133  
   134  // Update the tokens of an existing validator, update the validators power index key
   135  func (k Keeper) RemoveValidatorTokensAndShares(ctx sdk.Context, validator types.Validator,
   136  	sharesToRemove sdk.Dec) (valOut types.Validator, removedTokens sdk.Int) {
   137  
   138  	k.DeleteValidatorByPowerIndex(ctx, validator)
   139  	validator, removedTokens = validator.RemoveDelShares(sharesToRemove)
   140  	k.SetValidator(ctx, validator)
   141  	k.SetValidatorByPowerIndex(ctx, validator)
   142  	return validator, removedTokens
   143  }
   144  
   145  // Update the tokens of an existing validator, update the validators power index key
   146  func (k Keeper) RemoveValidatorTokens(ctx sdk.Context,
   147  	validator types.Validator, tokensToRemove sdk.Int) types.Validator {
   148  
   149  	k.DeleteValidatorByPowerIndex(ctx, validator)
   150  	validator = validator.RemoveTokens(tokensToRemove)
   151  	k.SetValidator(ctx, validator)
   152  	k.SetValidatorByPowerIndex(ctx, validator)
   153  	return validator
   154  }
   155  
   156  // UpdateValidatorCommission attempts to update a validator's commission rate.
   157  // An error is returned if the new commission rate is invalid.
   158  func (k Keeper) UpdateValidatorCommission(ctx sdk.Context,
   159  	validator types.Validator, newRate sdk.Dec) (types.Commission, error) {
   160  
   161  	commission := validator.Commission
   162  	blockTime := ctx.BlockHeader().Time
   163  
   164  	if err := commission.ValidateNewRate(newRate, blockTime); err != nil {
   165  		return commission, err
   166  	}
   167  
   168  	commission.Rate = newRate
   169  	commission.UpdateTime = blockTime
   170  
   171  	return commission, nil
   172  }
   173  
   174  // remove the validator record and associated indexes
   175  // except for the bonded validator index which is only handled in ApplyAndReturnTendermintUpdates
   176  func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
   177  
   178  	// first retrieve the old validator record
   179  	validator, found := k.GetValidator(ctx, address)
   180  	if !found {
   181  		return
   182  	}
   183  
   184  	if !validator.IsUnbonded() {
   185  		panic("cannot call RemoveValidator on bonded or unbonding validators")
   186  	}
   187  	if validator.Tokens.IsPositive() {
   188  		panic("attempting to remove a validator which still contains tokens")
   189  	}
   190  	if validator.Tokens.IsPositive() {
   191  		panic("validator being removed should never have positive tokens")
   192  	}
   193  
   194  	// delete the old validator record
   195  	store := ctx.KVStore(k.storeKey)
   196  	store.Delete(types.GetValidatorKey(address))
   197  	store.Delete(types.GetValidatorByConsAddrKey(sdk.ConsAddress(validator.ConsPubKey.Address())))
   198  	store.Delete(types.GetValidatorsByPowerIndexKey(validator))
   199  
   200  	// call hooks
   201  	k.AfterValidatorRemoved(ctx, validator.ConsAddress(), validator.OperatorAddress)
   202  }
   203  
   204  // get groups of validators
   205  
   206  // get the set of all validators with no limits, used during genesis dump
   207  func (k Keeper) GetAllValidators(ctx sdk.Context) (validators []types.Validator) {
   208  	store := ctx.KVStore(k.storeKey)
   209  	iterator := sdk.KVStorePrefixIterator(store, types.ValidatorsKey)
   210  	defer iterator.Close()
   211  
   212  	for ; iterator.Valid(); iterator.Next() {
   213  		validator := types.MustUnmarshalValidator(k.cdc, iterator.Value())
   214  		validators = append(validators, validator)
   215  	}
   216  	return validators
   217  }
   218  
   219  // return a given amount of all the validators
   220  func (k Keeper) GetValidators(ctx sdk.Context, maxRetrieve uint16) (validators []types.Validator) {
   221  	store := ctx.KVStore(k.storeKey)
   222  	validators = make([]types.Validator, maxRetrieve)
   223  
   224  	iterator := sdk.KVStorePrefixIterator(store, types.ValidatorsKey)
   225  	defer iterator.Close()
   226  
   227  	i := 0
   228  	for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
   229  		validator := types.MustUnmarshalValidator(k.cdc, iterator.Value())
   230  		validators[i] = validator
   231  		i++
   232  	}
   233  	return validators[:i] // trim if the array length < maxRetrieve
   234  }
   235  
   236  // get the current group of bonded validators sorted by power-rank
   237  func (k Keeper) GetBondedValidatorsByPower(ctx sdk.Context) []types.Validator {
   238  	maxValidators := k.MaxValidators(ctx)
   239  	validators := make([]types.Validator, maxValidators)
   240  
   241  	iterator := k.ValidatorsPowerStoreIterator(ctx)
   242  	defer iterator.Close()
   243  
   244  	i := 0
   245  	for ; iterator.Valid() && i < int(maxValidators); iterator.Next() {
   246  		address := iterator.Value()
   247  		validator := k.mustGetValidator(ctx, address)
   248  
   249  		if validator.IsBonded() {
   250  			validators[i] = validator
   251  			i++
   252  		}
   253  	}
   254  	return validators[:i] // trim
   255  }
   256  
   257  // returns an iterator for the current validator power store
   258  func (k Keeper) ValidatorsPowerStoreIterator(ctx sdk.Context) sdk.Iterator {
   259  	store := ctx.KVStore(k.storeKey)
   260  	return sdk.KVStoreReversePrefixIterator(store, types.ValidatorsByPowerIndexKey)
   261  }
   262  
   263  //_______________________________________________________________________
   264  // Last Validator Index
   265  
   266  // Load the last validator power.
   267  // Returns zero if the operator was not a validator last block.
   268  func (k Keeper) GetLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress) (power int64) {
   269  	store := ctx.KVStore(k.storeKey)
   270  	bz := store.Get(types.GetLastValidatorPowerKey(operator))
   271  	if bz == nil {
   272  		return 0
   273  	}
   274  	k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &power)
   275  	return
   276  }
   277  
   278  // Set the last validator power.
   279  func (k Keeper) SetLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress, power int64) {
   280  	store := ctx.KVStore(k.storeKey)
   281  	bz := k.cdc.MustMarshalBinaryLengthPrefixed(power)
   282  	store.Set(types.GetLastValidatorPowerKey(operator), bz)
   283  }
   284  
   285  // Delete the last validator power.
   286  func (k Keeper) DeleteLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress) {
   287  	store := ctx.KVStore(k.storeKey)
   288  	store.Delete(types.GetLastValidatorPowerKey(operator))
   289  }
   290  
   291  // returns an iterator for the consensus validators in the last block
   292  func (k Keeper) LastValidatorsIterator(ctx sdk.Context) (iterator sdk.Iterator) {
   293  	store := ctx.KVStore(k.storeKey)
   294  	iterator = sdk.KVStorePrefixIterator(store, types.LastValidatorPowerKey)
   295  	return iterator
   296  }
   297  
   298  // Iterate over last validator powers.
   299  func (k Keeper) IterateLastValidatorPowers(ctx sdk.Context, handler func(operator sdk.ValAddress, power int64) (stop bool)) {
   300  	store := ctx.KVStore(k.storeKey)
   301  	iter := sdk.KVStorePrefixIterator(store, types.LastValidatorPowerKey)
   302  	defer iter.Close()
   303  	for ; iter.Valid(); iter.Next() {
   304  		addr := sdk.ValAddress(iter.Key()[len(types.LastValidatorPowerKey):])
   305  		var power int64
   306  		k.cdc.MustUnmarshalBinaryLengthPrefixed(iter.Value(), &power)
   307  		if handler(addr, power) {
   308  			break
   309  		}
   310  	}
   311  }
   312  
   313  // get the group of the bonded validators
   314  func (k Keeper) GetLastValidators(ctx sdk.Context) (validators []types.Validator) {
   315  	store := ctx.KVStore(k.storeKey)
   316  
   317  	// add the actual validator power sorted store
   318  	maxValidators := k.MaxValidators(ctx)
   319  	validators = make([]types.Validator, maxValidators)
   320  
   321  	iterator := sdk.KVStorePrefixIterator(store, types.LastValidatorPowerKey)
   322  	defer iterator.Close()
   323  
   324  	i := 0
   325  	for ; iterator.Valid(); iterator.Next() {
   326  
   327  		// sanity check
   328  		if i >= int(maxValidators) {
   329  			panic("more validators than maxValidators found")
   330  		}
   331  		address := types.AddressFromLastValidatorPowerKey(iterator.Key())
   332  		validator := k.mustGetValidator(ctx, address)
   333  
   334  		validators[i] = validator
   335  		i++
   336  	}
   337  	return validators[:i] // trim
   338  }
   339  
   340  //_______________________________________________________________________
   341  // Validator Queue
   342  
   343  // gets a specific validator queue timeslice. A timeslice is a slice of ValAddresses corresponding to unbonding validators
   344  // that expire at a certain time.
   345  func (k Keeper) GetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time) (valAddrs []sdk.ValAddress) {
   346  	store := ctx.KVStore(k.storeKey)
   347  	bz := store.Get(types.GetValidatorQueueTimeKey(timestamp))
   348  	if bz == nil {
   349  		return []sdk.ValAddress{}
   350  	}
   351  	k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &valAddrs)
   352  	return valAddrs
   353  }
   354  
   355  // Sets a specific validator queue timeslice.
   356  func (k Keeper) SetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []sdk.ValAddress) {
   357  	store := ctx.KVStore(k.storeKey)
   358  	bz := k.cdc.MustMarshalBinaryLengthPrefixed(keys)
   359  	store.Set(types.GetValidatorQueueTimeKey(timestamp), bz)
   360  }
   361  
   362  // Deletes a specific validator queue timeslice.
   363  func (k Keeper) DeleteValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time) {
   364  	store := ctx.KVStore(k.storeKey)
   365  	store.Delete(types.GetValidatorQueueTimeKey(timestamp))
   366  }
   367  
   368  // Insert an validator address to the appropriate timeslice in the validator queue
   369  func (k Keeper) InsertValidatorQueue(ctx sdk.Context, val types.Validator) {
   370  	timeSlice := k.GetValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime)
   371  	timeSlice = append(timeSlice, val.OperatorAddress)
   372  	k.SetValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime, timeSlice)
   373  }
   374  
   375  // Delete a validator address from the validator queue
   376  func (k Keeper) DeleteValidatorQueue(ctx sdk.Context, val types.Validator) {
   377  	timeSlice := k.GetValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime)
   378  	newTimeSlice := []sdk.ValAddress{}
   379  	for _, addr := range timeSlice {
   380  		if !bytes.Equal(addr, val.OperatorAddress) {
   381  			newTimeSlice = append(newTimeSlice, addr)
   382  		}
   383  	}
   384  	if len(newTimeSlice) == 0 {
   385  		k.DeleteValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime)
   386  	} else {
   387  		k.SetValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime, newTimeSlice)
   388  	}
   389  }
   390  
   391  // Returns all the validator queue timeslices from time 0 until endTime
   392  func (k Keeper) ValidatorQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
   393  	store := ctx.KVStore(k.storeKey)
   394  	return store.Iterator(types.ValidatorQueueKey, sdk.InclusiveEndBytes(types.GetValidatorQueueTimeKey(endTime)))
   395  }
   396  
   397  // Returns a concatenated list of all the timeslices before currTime, and deletes the timeslices from the queue
   398  func (k Keeper) GetAllMatureValidatorQueue(ctx sdk.Context, currTime time.Time) (matureValsAddrs []sdk.ValAddress) {
   399  	// gets an iterator for all timeslices from time 0 until the current Blockheader time
   400  	validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time)
   401  	defer validatorTimesliceIterator.Close()
   402  
   403  	for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() {
   404  		timeslice := []sdk.ValAddress{}
   405  		k.cdc.MustUnmarshalBinaryLengthPrefixed(validatorTimesliceIterator.Value(), &timeslice)
   406  		matureValsAddrs = append(matureValsAddrs, timeslice...)
   407  	}
   408  
   409  	return matureValsAddrs
   410  }
   411  
   412  // Unbonds all the unbonding validators that have finished their unbonding period
   413  func (k Keeper) UnbondAllMatureValidatorQueue(ctx sdk.Context) {
   414  	store := ctx.KVStore(k.storeKey)
   415  	validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time)
   416  	defer validatorTimesliceIterator.Close()
   417  
   418  	for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() {
   419  		timeslice := []sdk.ValAddress{}
   420  		k.cdc.MustUnmarshalBinaryLengthPrefixed(validatorTimesliceIterator.Value(), &timeslice)
   421  
   422  		for _, valAddr := range timeslice {
   423  			val, found := k.GetValidator(ctx, valAddr)
   424  			if !found {
   425  				panic("validator in the unbonding queue was not found")
   426  			}
   427  
   428  			if !val.IsUnbonding() {
   429  				panic("unexpected validator in unbonding queue; status was not unbonding")
   430  			}
   431  			val = k.unbondingToUnbonded(ctx, val)
   432  			if val.GetDelegatorShares().IsZero() {
   433  				k.RemoveValidator(ctx, val.OperatorAddress)
   434  			}
   435  		}
   436  
   437  		store.Delete(validatorTimesliceIterator.Key())
   438  	}
   439  }