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(), ×lice) 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 }