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