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 }