github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/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/x/staking/types"
    10  )
    11  
    12  // GetValidator gets a single validator
    13  func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator types.Validator, found bool) {
    14  	store := ctx.KVStore(k.storeKey)
    15  	value := store.Get(types.GetValidatorKey(addr))
    16  	if value == nil {
    17  		return validator, false
    18  	}
    19  	validator = types.MustUnmarshalValidator(k.cdcMarshl.GetCdc(), value)
    20  	return validator, true
    21  }
    22  
    23  func (k Keeper) mustGetValidator(ctx sdk.Context, addr sdk.ValAddress) types.Validator {
    24  	validator, found := k.GetValidator(ctx, addr)
    25  	if !found {
    26  		panic(fmt.Sprintf("validator record not found for address: %X\n", addr))
    27  	}
    28  	return validator
    29  }
    30  
    31  // GetValidatorByConsAddr gets a single validator by consensus address
    32  func (k Keeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator types.Validator,
    33  	found bool) {
    34  	store := ctx.KVStore(k.storeKey)
    35  	opAddr := store.Get(types.GetValidatorByConsAddrKey(consAddr))
    36  	if opAddr == nil {
    37  		return validator, false
    38  	}
    39  	return k.GetValidator(ctx, opAddr)
    40  }
    41  
    42  func (k Keeper) mustGetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) types.Validator {
    43  	validator, found := k.GetValidatorByConsAddr(ctx, consAddr)
    44  	if !found {
    45  		panic(fmt.Errorf("validator with consensus-Address %s not found", consAddr))
    46  	}
    47  	return validator
    48  }
    49  
    50  // SetValidator sets the main record holding validator details
    51  func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) {
    52  	store := ctx.KVStore(k.storeKey)
    53  	bz := types.MustMarshalValidator(k.cdcMarshl.GetCdc(), validator)
    54  	store.Set(types.GetValidatorKey(validator.OperatorAddress), bz)
    55  }
    56  
    57  // SetValidatorByConsAddr sets the operator address with the key of validator consensus pubkey
    58  func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) {
    59  	store := ctx.KVStore(k.storeKey)
    60  	consAddr := sdk.ConsAddress(validator.ConsPubKey.Address())
    61  	store.Set(types.GetValidatorByConsAddrKey(consAddr), validator.OperatorAddress)
    62  }
    63  
    64  // SetValidatorByPowerIndex sets the power index key of an unjailed validator
    65  func (k Keeper) SetValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
    66  	// jailed validators are not kept in the power index
    67  	if validator.Jailed {
    68  		return
    69  	}
    70  	store := ctx.KVStore(k.storeKey)
    71  	store.Set(types.GetValidatorsByPowerIndexKey(validator), validator.OperatorAddress)
    72  }
    73  
    74  // DeleteValidatorByPowerIndex deletes the power index key
    75  func (k Keeper) DeleteValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
    76  	store := ctx.KVStore(k.storeKey)
    77  	store.Delete(types.GetValidatorsByPowerIndexKey(validator))
    78  }
    79  
    80  // SetNewValidatorByPowerIndex sets the power index key of a validator
    81  func (k Keeper) SetNewValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
    82  	store := ctx.KVStore(k.storeKey)
    83  	store.Set(types.GetValidatorsByPowerIndexKey(validator), validator.OperatorAddress)
    84  }
    85  
    86  // RemoveValidator removes the validator record and associated indexes
    87  // except for the bonded validator index which is only handled in ApplyAndReturnTendermintUpdates
    88  func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
    89  	k.Logger(ctx).Debug("Remove Validator", "ValAddr", address.String())
    90  
    91  	// first retrieve the old validator record
    92  	validator, found := k.GetValidator(ctx, address)
    93  	if !found {
    94  		return
    95  	}
    96  
    97  	if !validator.IsUnbonded() {
    98  		panic("cannot call RemoveValidator on bonded or unbonding validators")
    99  	}
   100  	if validator.Tokens.IsPositive() {
   101  		panic("attempting to remove a validator which still contains tokens")
   102  	}
   103  	if validator.Tokens.GT(sdk.ZeroInt()) {
   104  		panic("validator being removed should never have positive tokens")
   105  	}
   106  
   107  	// delete the old validator record
   108  	store := ctx.KVStore(k.storeKey)
   109  	store.Delete(types.GetValidatorKey(address))
   110  	store.Delete(types.GetValidatorByConsAddrKey(sdk.ConsAddress(validator.ConsPubKey.Address())))
   111  	store.Delete(types.GetValidatorsByPowerIndexKey(validator))
   112  
   113  	// call hooks
   114  	k.AfterValidatorRemoved(ctx, validator.ConsAddress(), validator.OperatorAddress)
   115  }
   116  
   117  // get groups of validators
   118  
   119  // GetAllValidators gets the set of all validators with no limits, used during genesis dump
   120  func (k Keeper) GetAllValidators(ctx sdk.Context) (validators types.Validators) {
   121  	store := ctx.KVStore(k.storeKey)
   122  	iterator := sdk.KVStorePrefixIterator(store, types.ValidatorsKey)
   123  	defer iterator.Close()
   124  
   125  	for ; iterator.Valid(); iterator.Next() {
   126  		validator := types.MustUnmarshalValidator(k.cdcMarshl.GetCdc(), iterator.Value())
   127  		validators = append(validators, validator)
   128  	}
   129  	return validators
   130  }
   131  
   132  // ValidatorsPowerStoreIterator returns an iterator for the current validator power store
   133  func (k Keeper) ValidatorsPowerStoreIterator(ctx sdk.Context) (iterator sdk.Iterator) {
   134  	store := ctx.KVStore(k.storeKey)
   135  	iterator = sdk.KVStoreReversePrefixIterator(store, types.ValidatorsByPowerIndexKey)
   136  	return iterator
   137  }
   138  
   139  //_______________________________________________________________________
   140  // Last Validator Index
   141  
   142  // GetLastValidatorPower loads the last validator power and returns zero if the operator was not a validator last block
   143  func (k Keeper) GetLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress) (power int64) {
   144  	store := ctx.KVStore(k.storeKey)
   145  	bz := store.Get(types.GetLastValidatorPowerKey(operator))
   146  	if bz == nil {
   147  		return 0
   148  	}
   149  	k.cdcMarshl.GetCdc().MustUnmarshalBinaryLengthPrefixed(bz, &power)
   150  	return
   151  }
   152  
   153  // SetLastValidatorPower sets the last validator power
   154  func (k Keeper) SetLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress, power int64) {
   155  	store := ctx.KVStore(k.storeKey)
   156  	bz := k.cdcMarshl.GetCdc().MustMarshalBinaryLengthPrefixed(power)
   157  	store.Set(types.GetLastValidatorPowerKey(operator), bz)
   158  }
   159  
   160  // DeleteLastValidatorPower deletes the last validator power
   161  func (k Keeper) DeleteLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress) {
   162  	store := ctx.KVStore(k.storeKey)
   163  	store.Delete(types.GetLastValidatorPowerKey(operator))
   164  }
   165  
   166  // LastValidatorsIterator returns an iterator for the consensus validators in the last block
   167  func (k Keeper) LastValidatorsIterator(ctx sdk.Context) (iterator sdk.Iterator) {
   168  	store := ctx.KVStore(k.storeKey)
   169  	iterator = sdk.KVStorePrefixIterator(store, types.LastValidatorPowerKey)
   170  	return iterator
   171  }
   172  
   173  // IterateLastValidatorPowers iterates over last validator powers
   174  func (k Keeper) IterateLastValidatorPowers(ctx sdk.Context,
   175  	handler func(operator sdk.ValAddress, power int64) (stop bool)) {
   176  	store := ctx.KVStore(k.storeKey)
   177  	iter := sdk.KVStorePrefixIterator(store, types.LastValidatorPowerKey)
   178  	defer iter.Close()
   179  	for ; iter.Valid(); iter.Next() {
   180  		addr := sdk.ValAddress(iter.Key()[len(types.LastValidatorPowerKey):])
   181  		var power int64
   182  		k.cdcMarshl.GetCdc().MustUnmarshalBinaryLengthPrefixed(iter.Value(), &power)
   183  		if handler(addr, power) {
   184  			break
   185  		}
   186  	}
   187  }
   188  
   189  //_______________________________________________________________________
   190  // Validator Queue
   191  
   192  // GetValidatorQueueTimeSlice gets a specific validator queue timeslice
   193  // A timeslice is a slice of ValAddresses corresponding to unbonding validators that expire at a certain time
   194  func (k Keeper) GetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time) (valAddrs []sdk.ValAddress) {
   195  	store := ctx.KVStore(k.storeKey)
   196  	bz := store.Get(types.GetValidatorQueueTimeKey(timestamp))
   197  	if bz == nil {
   198  		return []sdk.ValAddress{}
   199  	}
   200  	k.cdcMarshl.GetCdc().MustUnmarshalBinaryLengthPrefixed(bz, &valAddrs)
   201  	return valAddrs
   202  }
   203  
   204  // SetValidatorQueueTimeSlice sets a specific validator queue timeslice
   205  func (k Keeper) SetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []sdk.ValAddress) {
   206  	store := ctx.KVStore(k.storeKey)
   207  	bz := k.cdcMarshl.GetCdc().MustMarshalBinaryLengthPrefixed(keys)
   208  	store.Set(types.GetValidatorQueueTimeKey(timestamp), bz)
   209  }
   210  
   211  // DeleteValidatorQueueTimeSlice deletes a specific validator queue timeslice
   212  func (k Keeper) DeleteValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time) {
   213  	store := ctx.KVStore(k.storeKey)
   214  	store.Delete(types.GetValidatorQueueTimeKey(timestamp))
   215  }
   216  
   217  // InsertValidatorQueue inserts an validator address to the appropriate timeslice in the validator queue
   218  func (k Keeper) InsertValidatorQueue(ctx sdk.Context, val types.Validator) {
   219  	timeSlice := k.GetValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime)
   220  	var keys []sdk.ValAddress
   221  	if len(timeSlice) == 0 {
   222  		keys = []sdk.ValAddress{val.OperatorAddress}
   223  	} else {
   224  		keys = append(timeSlice, val.OperatorAddress)
   225  	}
   226  	k.SetValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime, keys)
   227  }
   228  
   229  // DeleteValidatorQueue deletes a validator address from the validator queue
   230  func (k Keeper) DeleteValidatorQueue(ctx sdk.Context, val types.Validator) {
   231  	timeSlice := k.GetValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime)
   232  	newTimeSlice := []sdk.ValAddress{}
   233  	for _, addr := range timeSlice {
   234  		if !bytes.Equal(addr, val.OperatorAddress) {
   235  			newTimeSlice = append(newTimeSlice, addr)
   236  		}
   237  	}
   238  	if len(newTimeSlice) == 0 {
   239  		k.DeleteValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime)
   240  	} else {
   241  		k.SetValidatorQueueTimeSlice(ctx, val.UnbondingCompletionTime, newTimeSlice)
   242  	}
   243  }
   244  
   245  // ValidatorQueueIterator returns all the validator queue timeslices from time 0 until endTime
   246  func (k Keeper) ValidatorQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
   247  	store := ctx.KVStore(k.storeKey)
   248  	return store.Iterator(types.ValidatorQueueKey, sdk.InclusiveEndBytes(types.GetValidatorQueueTimeKey(endTime)))
   249  }
   250  
   251  // UnbondAllMatureValidatorQueue unbonds all the unbonding validators that have finished their unbonding period
   252  func (k Keeper) UnbondAllMatureValidatorQueue(ctx sdk.Context) {
   253  	store := ctx.KVStore(k.storeKey)
   254  	validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time)
   255  	defer validatorTimesliceIterator.Close()
   256  
   257  	for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() {
   258  		timeslice := []sdk.ValAddress{}
   259  		k.cdcMarshl.GetCdc().MustUnmarshalBinaryLengthPrefixed(validatorTimesliceIterator.Value(), &timeslice)
   260  
   261  		for _, valAddr := range timeslice {
   262  			val, found := k.GetValidator(ctx, valAddr)
   263  			if !found {
   264  				panic("validator in the unbonding queue was not found")
   265  			}
   266  
   267  			if !val.IsUnbonding() {
   268  				panic("unexpected validator in unbonding queue; status was not unbonding")
   269  			}
   270  			val = k.unbondingToUnbonded(ctx, val)
   271  			// required by fbchain
   272  			//if val.GetDelegatorShares().IsZero() {
   273  			//	k.RemoveValidator(ctx, val.OperatorAddress)
   274  			//}
   275  			if val.GetDelegatorShares().IsZero() && val.GetMinSelfDelegation().IsZero() {
   276  				k.RemoveValidator(ctx, val.OperatorAddress)
   277  			}
   278  		}
   279  
   280  		store.Delete(validatorTimesliceIterator.Key())
   281  	}
   282  }