github.com/cosmos/cosmos-sdk@v0.50.10/x/staking/keeper/validator.go (about) 1 package keeper 2 3 import ( 4 "bytes" 5 "context" 6 "errors" 7 "fmt" 8 "time" 9 10 cmtprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto" 11 gogotypes "github.com/cosmos/gogoproto/types" 12 13 corestore "cosmossdk.io/core/store" 14 errorsmod "cosmossdk.io/errors" 15 "cosmossdk.io/math" 16 storetypes "cosmossdk.io/store/types" 17 18 sdk "github.com/cosmos/cosmos-sdk/types" 19 "github.com/cosmos/cosmos-sdk/x/staking/types" 20 ) 21 22 // GetValidator gets a single validator 23 func (k Keeper) GetValidator(ctx context.Context, addr sdk.ValAddress) (validator types.Validator, err error) { 24 store := k.storeService.OpenKVStore(ctx) 25 value, err := store.Get(types.GetValidatorKey(addr)) 26 if err != nil { 27 return validator, err 28 } 29 30 if value == nil { 31 return validator, types.ErrNoValidatorFound 32 } 33 34 return types.UnmarshalValidator(k.cdc, value) 35 } 36 37 func (k Keeper) mustGetValidator(ctx context.Context, addr sdk.ValAddress) types.Validator { 38 validator, err := k.GetValidator(ctx, addr) 39 if err != nil { 40 panic(fmt.Sprintf("validator record not found for address: %X\n", addr)) 41 } 42 43 return validator 44 } 45 46 // GetValidatorByConsAddr gets a single validator by consensus address 47 func (k Keeper) GetValidatorByConsAddr(ctx context.Context, consAddr sdk.ConsAddress) (validator types.Validator, err error) { 48 store := k.storeService.OpenKVStore(ctx) 49 opAddr, err := store.Get(types.GetValidatorByConsAddrKey(consAddr)) 50 if err != nil { 51 return validator, err 52 } 53 54 if opAddr == nil { 55 return validator, types.ErrNoValidatorFound 56 } 57 58 return k.GetValidator(ctx, opAddr) 59 } 60 61 func (k Keeper) mustGetValidatorByConsAddr(ctx context.Context, consAddr sdk.ConsAddress) types.Validator { 62 validator, err := k.GetValidatorByConsAddr(ctx, consAddr) 63 if err != nil { 64 panic(fmt.Errorf("validator with consensus-Address %s not found", consAddr)) 65 } 66 67 return validator 68 } 69 70 // SetValidator sets the main record holding validator details 71 func (k Keeper) SetValidator(ctx context.Context, validator types.Validator) error { 72 store := k.storeService.OpenKVStore(ctx) 73 bz := types.MustMarshalValidator(k.cdc, &validator) 74 str, err := k.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) 75 if err != nil { 76 return err 77 } 78 return store.Set(types.GetValidatorKey(str), bz) 79 } 80 81 // SetValidatorByConsAddr sets a validator by conesensus address 82 func (k Keeper) SetValidatorByConsAddr(ctx context.Context, validator types.Validator) error { 83 consPk, err := validator.GetConsAddr() 84 if err != nil { 85 return err 86 } 87 store := k.storeService.OpenKVStore(ctx) 88 89 bz, err := k.validatorAddressCodec.StringToBytes(validator.GetOperator()) 90 if err != nil { 91 return err 92 } 93 94 return store.Set(types.GetValidatorByConsAddrKey(consPk), bz) 95 } 96 97 // SetValidatorByPowerIndex sets a validator by power index 98 func (k Keeper) SetValidatorByPowerIndex(ctx context.Context, validator types.Validator) error { 99 // jailed validators are not kept in the power index 100 if validator.Jailed { 101 return nil 102 } 103 104 store := k.storeService.OpenKVStore(ctx) 105 str, err := k.validatorAddressCodec.StringToBytes(validator.GetOperator()) 106 if err != nil { 107 return err 108 } 109 return store.Set(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx), k.validatorAddressCodec), str) 110 } 111 112 // DeleteValidatorByPowerIndex deletes a record by power index 113 func (k Keeper) DeleteValidatorByPowerIndex(ctx context.Context, validator types.Validator) error { 114 store := k.storeService.OpenKVStore(ctx) 115 return store.Delete(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx), k.validatorAddressCodec)) 116 } 117 118 // SetNewValidatorByPowerIndex adds new entry by power index 119 func (k Keeper) SetNewValidatorByPowerIndex(ctx context.Context, validator types.Validator) error { 120 store := k.storeService.OpenKVStore(ctx) 121 str, err := k.validatorAddressCodec.StringToBytes(validator.GetOperator()) 122 if err != nil { 123 return err 124 } 125 return store.Set(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx), k.validatorAddressCodec), str) 126 } 127 128 // AddValidatorTokensAndShares updates the tokens of an existing validator, updates the validators power index key 129 func (k Keeper) AddValidatorTokensAndShares(ctx context.Context, validator types.Validator, 130 tokensToAdd math.Int, 131 ) (valOut types.Validator, addedShares math.LegacyDec, err error) { 132 err = k.DeleteValidatorByPowerIndex(ctx, validator) 133 if err != nil { 134 return valOut, addedShares, err 135 } 136 137 validator, addedShares = validator.AddTokensFromDel(tokensToAdd) 138 err = k.SetValidator(ctx, validator) 139 if err != nil { 140 return validator, addedShares, err 141 } 142 143 err = k.SetValidatorByPowerIndex(ctx, validator) 144 return validator, addedShares, err 145 } 146 147 // RemoveValidatorTokensAndShares updates the tokens of an existing validator, updates the validators power index key 148 func (k Keeper) RemoveValidatorTokensAndShares(ctx context.Context, validator types.Validator, 149 sharesToRemove math.LegacyDec, 150 ) (valOut types.Validator, removedTokens math.Int, err error) { 151 err = k.DeleteValidatorByPowerIndex(ctx, validator) 152 if err != nil { 153 return valOut, removedTokens, err 154 } 155 validator, removedTokens = validator.RemoveDelShares(sharesToRemove) 156 err = k.SetValidator(ctx, validator) 157 if err != nil { 158 return validator, removedTokens, err 159 } 160 161 err = k.SetValidatorByPowerIndex(ctx, validator) 162 return validator, removedTokens, err 163 } 164 165 // RemoveValidatorTokens updates the tokens of an existing validator, updates the validators power index key 166 func (k Keeper) RemoveValidatorTokens(ctx context.Context, 167 validator types.Validator, tokensToRemove math.Int, 168 ) (types.Validator, error) { 169 if err := k.DeleteValidatorByPowerIndex(ctx, validator); err != nil { 170 return validator, err 171 } 172 173 validator = validator.RemoveTokens(tokensToRemove) 174 if err := k.SetValidator(ctx, validator); err != nil { 175 return validator, err 176 } 177 178 if err := k.SetValidatorByPowerIndex(ctx, validator); err != nil { 179 return validator, err 180 } 181 182 return validator, nil 183 } 184 185 // UpdateValidatorCommission attempts to update a validator's commission rate. 186 // An error is returned if the new commission rate is invalid. 187 func (k Keeper) UpdateValidatorCommission(ctx context.Context, 188 validator types.Validator, newRate math.LegacyDec, 189 ) (types.Commission, error) { 190 commission := validator.Commission 191 sdkCtx := sdk.UnwrapSDKContext(ctx) 192 blockTime := sdkCtx.BlockHeader().Time 193 194 if err := commission.ValidateNewRate(newRate, blockTime); err != nil { 195 return commission, err 196 } 197 198 minCommissionRate, err := k.MinCommissionRate(ctx) 199 if err != nil { 200 return commission, err 201 } 202 203 if newRate.LT(minCommissionRate) { 204 return commission, fmt.Errorf("cannot set validator commission to less than minimum rate of %s", minCommissionRate) 205 } 206 207 commission.Rate = newRate 208 commission.UpdateTime = blockTime 209 210 return commission, nil 211 } 212 213 // RemoveValidator removes the validator record and associated indexes 214 // except for the bonded validator index which is only handled in ApplyAndReturnTendermintUpdates 215 func (k Keeper) RemoveValidator(ctx context.Context, address sdk.ValAddress) error { 216 // first retrieve the old validator record 217 validator, err := k.GetValidator(ctx, address) 218 if errors.Is(err, types.ErrNoValidatorFound) { 219 return nil 220 } 221 222 if !validator.IsUnbonded() { 223 return types.ErrBadRemoveValidator.Wrap("cannot call RemoveValidator on bonded or unbonding validators") 224 } 225 226 if validator.Tokens.IsPositive() { 227 return types.ErrBadRemoveValidator.Wrap("attempting to remove a validator which still contains tokens") 228 } 229 230 valConsAddr, err := validator.GetConsAddr() 231 if err != nil { 232 return err 233 } 234 235 // delete the old validator record 236 store := k.storeService.OpenKVStore(ctx) 237 if err = store.Delete(types.GetValidatorKey(address)); err != nil { 238 return err 239 } 240 241 if err = store.Delete(types.GetValidatorByConsAddrKey(valConsAddr)); err != nil { 242 return err 243 } 244 245 if err = store.Delete(types.GetValidatorsByPowerIndexKey(validator, k.PowerReduction(ctx), k.validatorAddressCodec)); err != nil { 246 return err 247 } 248 249 str, err := k.validatorAddressCodec.StringToBytes(validator.GetOperator()) 250 if err != nil { 251 return err 252 } 253 254 if err := k.Hooks().AfterValidatorRemoved(ctx, valConsAddr, str); err != nil { 255 k.Logger(ctx).Error("error in after validator removed hook", "error", err) 256 } 257 258 return nil 259 } 260 261 // get groups of validators 262 263 // GetAllValidators gets the set of all validators with no limits, used during genesis dump 264 func (k Keeper) GetAllValidators(ctx context.Context) (validators []types.Validator, err error) { 265 store := k.storeService.OpenKVStore(ctx) 266 267 iterator, err := store.Iterator(types.ValidatorsKey, storetypes.PrefixEndBytes(types.ValidatorsKey)) 268 if err != nil { 269 return nil, err 270 } 271 defer iterator.Close() 272 273 for ; iterator.Valid(); iterator.Next() { 274 validator, err := types.UnmarshalValidator(k.cdc, iterator.Value()) 275 if err != nil { 276 return nil, err 277 } 278 validators = append(validators, validator) 279 } 280 281 return validators, nil 282 } 283 284 // GetValidators returns a given amount of all the validators 285 func (k Keeper) GetValidators(ctx context.Context, maxRetrieve uint32) (validators []types.Validator, err error) { 286 store := k.storeService.OpenKVStore(ctx) 287 validators = make([]types.Validator, maxRetrieve) 288 289 iterator, err := store.Iterator(types.ValidatorsKey, storetypes.PrefixEndBytes(types.ValidatorsKey)) 290 if err != nil { 291 return nil, err 292 } 293 294 i := 0 295 for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() { 296 validator, err := types.UnmarshalValidator(k.cdc, iterator.Value()) 297 if err != nil { 298 return nil, err 299 } 300 validators[i] = validator 301 i++ 302 } 303 304 return validators[:i], nil // trim if the array length < maxRetrieve 305 } 306 307 // GetBondedValidatorsByPower gets the current group of bonded validators sorted by power-rank 308 func (k Keeper) GetBondedValidatorsByPower(ctx context.Context) ([]types.Validator, error) { 309 maxValidators, err := k.MaxValidators(ctx) 310 if err != nil { 311 return nil, err 312 } 313 validators := make([]types.Validator, maxValidators) 314 315 iterator, err := k.ValidatorsPowerStoreIterator(ctx) 316 if err != nil { 317 return nil, err 318 } 319 defer iterator.Close() 320 321 i := 0 322 for ; iterator.Valid() && i < int(maxValidators); iterator.Next() { 323 address := iterator.Value() 324 validator := k.mustGetValidator(ctx, address) 325 326 if validator.IsBonded() { 327 validators[i] = validator 328 i++ 329 } 330 } 331 332 return validators[:i], nil // trim 333 } 334 335 // ValidatorsPowerStoreIterator returns an iterator for the current validator power store 336 func (k Keeper) ValidatorsPowerStoreIterator(ctx context.Context) (corestore.Iterator, error) { 337 store := k.storeService.OpenKVStore(ctx) 338 return store.ReverseIterator(types.ValidatorsByPowerIndexKey, storetypes.PrefixEndBytes(types.ValidatorsByPowerIndexKey)) 339 } 340 341 // Last Validator Index 342 343 // GetLastValidatorPower loads the last validator power. 344 // Returns zero if the operator was not a validator last block. 345 func (k Keeper) GetLastValidatorPower(ctx context.Context, operator sdk.ValAddress) (power int64, err error) { 346 store := k.storeService.OpenKVStore(ctx) 347 bz, err := store.Get(types.GetLastValidatorPowerKey(operator)) 348 if err != nil { 349 return 0, err 350 } 351 352 if bz == nil { 353 return 0, nil 354 } 355 356 intV := gogotypes.Int64Value{} 357 err = k.cdc.Unmarshal(bz, &intV) 358 if err != nil { 359 return 0, err 360 } 361 362 return intV.GetValue(), nil 363 } 364 365 // SetLastValidatorPower sets the last validator power. 366 func (k Keeper) SetLastValidatorPower(ctx context.Context, operator sdk.ValAddress, power int64) error { 367 store := k.storeService.OpenKVStore(ctx) 368 bz, err := k.cdc.Marshal(&gogotypes.Int64Value{Value: power}) 369 if err != nil { 370 return err 371 } 372 return store.Set(types.GetLastValidatorPowerKey(operator), bz) 373 } 374 375 // DeleteLastValidatorPower deletes the last validator power. 376 func (k Keeper) DeleteLastValidatorPower(ctx context.Context, operator sdk.ValAddress) error { 377 store := k.storeService.OpenKVStore(ctx) 378 return store.Delete(types.GetLastValidatorPowerKey(operator)) 379 } 380 381 // lastValidatorsIterator returns an iterator for the consensus validators in the last block 382 func (k Keeper) LastValidatorsIterator(ctx context.Context) (corestore.Iterator, error) { 383 store := k.storeService.OpenKVStore(ctx) 384 return store.Iterator(types.LastValidatorPowerKey, storetypes.PrefixEndBytes(types.LastValidatorPowerKey)) 385 } 386 387 // IterateLastValidatorPowers iterates over last validator powers. 388 func (k Keeper) IterateLastValidatorPowers(ctx context.Context, handler func(operator sdk.ValAddress, power int64) (stop bool)) error { 389 iter, err := k.LastValidatorsIterator(ctx) 390 if err != nil { 391 return err 392 } 393 394 for ; iter.Valid(); iter.Next() { 395 addr := sdk.ValAddress(types.AddressFromLastValidatorPowerKey(iter.Key())) 396 intV := &gogotypes.Int64Value{} 397 398 if err = k.cdc.Unmarshal(iter.Value(), intV); err != nil { 399 return err 400 } 401 402 if handler(addr, intV.GetValue()) { 403 break 404 } 405 } 406 407 return nil 408 } 409 410 // GetLastValidators gets the group of the bonded validators 411 func (k Keeper) GetLastValidators(ctx context.Context) (validators []types.Validator, err error) { 412 store := k.storeService.OpenKVStore(ctx) 413 414 // add the actual validator power sorted store 415 maxValidators, err := k.MaxValidators(ctx) 416 if err != nil { 417 return nil, err 418 } 419 validators = make([]types.Validator, maxValidators) 420 421 iterator, err := store.Iterator(types.LastValidatorPowerKey, storetypes.PrefixEndBytes(types.LastValidatorPowerKey)) 422 if err != nil { 423 return nil, err 424 } 425 defer iterator.Close() 426 427 i := 0 428 for ; iterator.Valid(); iterator.Next() { 429 // sanity check 430 if i >= int(maxValidators) { 431 panic("more validators than maxValidators found") 432 } 433 434 address := types.AddressFromLastValidatorPowerKey(iterator.Key()) 435 validator, err := k.GetValidator(ctx, address) 436 if err != nil { 437 return nil, err 438 } 439 440 validators[i] = validator 441 i++ 442 } 443 444 return validators[:i], nil // trim 445 } 446 447 // GetUnbondingValidators returns a slice of mature validator addresses that 448 // complete their unbonding at a given time and height. 449 func (k Keeper) GetUnbondingValidators(ctx context.Context, endTime time.Time, endHeight int64) ([]string, error) { 450 store := k.storeService.OpenKVStore(ctx) 451 452 bz, err := store.Get(types.GetValidatorQueueKey(endTime, endHeight)) 453 if err != nil { 454 return nil, err 455 } 456 457 if bz == nil { 458 return []string{}, nil 459 } 460 461 addrs := types.ValAddresses{} 462 if err = k.cdc.Unmarshal(bz, &addrs); err != nil { 463 return nil, err 464 } 465 466 return addrs.Addresses, nil 467 } 468 469 // SetUnbondingValidatorsQueue sets a given slice of validator addresses into 470 // the unbonding validator queue by a given height and time. 471 func (k Keeper) SetUnbondingValidatorsQueue(ctx context.Context, endTime time.Time, endHeight int64, addrs []string) error { 472 store := k.storeService.OpenKVStore(ctx) 473 bz, err := k.cdc.Marshal(&types.ValAddresses{Addresses: addrs}) 474 if err != nil { 475 return err 476 } 477 return store.Set(types.GetValidatorQueueKey(endTime, endHeight), bz) 478 } 479 480 // InsertUnbondingValidatorQueue inserts a given unbonding validator address into 481 // the unbonding validator queue for a given height and time. 482 func (k Keeper) InsertUnbondingValidatorQueue(ctx context.Context, val types.Validator) error { 483 addrs, err := k.GetUnbondingValidators(ctx, val.UnbondingTime, val.UnbondingHeight) 484 if err != nil { 485 return err 486 } 487 addrs = append(addrs, val.OperatorAddress) 488 return k.SetUnbondingValidatorsQueue(ctx, val.UnbondingTime, val.UnbondingHeight, addrs) 489 } 490 491 // DeleteValidatorQueueTimeSlice deletes all entries in the queue indexed by a 492 // given height and time. 493 func (k Keeper) DeleteValidatorQueueTimeSlice(ctx context.Context, endTime time.Time, endHeight int64) error { 494 store := k.storeService.OpenKVStore(ctx) 495 return store.Delete(types.GetValidatorQueueKey(endTime, endHeight)) 496 } 497 498 // DeleteValidatorQueue removes a validator by address from the unbonding queue 499 // indexed by a given height and time. 500 func (k Keeper) DeleteValidatorQueue(ctx context.Context, val types.Validator) error { 501 addrs, err := k.GetUnbondingValidators(ctx, val.UnbondingTime, val.UnbondingHeight) 502 if err != nil { 503 return err 504 } 505 newAddrs := []string{} 506 507 // since address string may change due to Bech32 prefix change, we parse the addresses into bytes 508 // format for normalization 509 deletingAddr, err := k.validatorAddressCodec.StringToBytes(val.OperatorAddress) 510 if err != nil { 511 return err 512 } 513 514 for _, addr := range addrs { 515 storedAddr, err := k.validatorAddressCodec.StringToBytes(addr) 516 if err != nil { 517 // even if we don't error here, it will error in UnbondAllMatureValidators at unbond time 518 return err 519 } 520 if !bytes.Equal(storedAddr, deletingAddr) { 521 newAddrs = append(newAddrs, addr) 522 } 523 } 524 525 if len(newAddrs) == 0 { 526 return k.DeleteValidatorQueueTimeSlice(ctx, val.UnbondingTime, val.UnbondingHeight) 527 } 528 529 return k.SetUnbondingValidatorsQueue(ctx, val.UnbondingTime, val.UnbondingHeight, newAddrs) 530 } 531 532 // ValidatorQueueIterator returns an interator ranging over validators that are 533 // unbonding whose unbonding completion occurs at the given height and time. 534 func (k Keeper) ValidatorQueueIterator(ctx context.Context, endTime time.Time, endHeight int64) (corestore.Iterator, error) { 535 store := k.storeService.OpenKVStore(ctx) 536 return store.Iterator(types.ValidatorQueueKey, storetypes.InclusiveEndBytes(types.GetValidatorQueueKey(endTime, endHeight))) 537 } 538 539 // UnbondAllMatureValidators unbonds all the mature unbonding validators that 540 // have finished their unbonding period. 541 func (k Keeper) UnbondAllMatureValidators(ctx context.Context) error { 542 sdkCtx := sdk.UnwrapSDKContext(ctx) 543 blockTime := sdkCtx.BlockTime() 544 blockHeight := sdkCtx.BlockHeight() 545 546 // unbondingValIterator will contains all validator addresses indexed under 547 // the ValidatorQueueKey prefix. Note, the entire index key is composed as 548 // ValidatorQueueKey | timeBzLen (8-byte big endian) | timeBz | heightBz (8-byte big endian), 549 // so it may be possible that certain validator addresses that are iterated 550 // over are not ready to unbond, so an explicit check is required. 551 unbondingValIterator, err := k.ValidatorQueueIterator(ctx, blockTime, blockHeight) 552 if err != nil { 553 return err 554 } 555 defer unbondingValIterator.Close() 556 557 for ; unbondingValIterator.Valid(); unbondingValIterator.Next() { 558 key := unbondingValIterator.Key() 559 keyTime, keyHeight, err := types.ParseValidatorQueueKey(key) 560 if err != nil { 561 return fmt.Errorf("failed to parse unbonding key: %w", err) 562 } 563 564 // All addresses for the given key have the same unbonding height and time. 565 // We only unbond if the height and time are less than the current height 566 // and time. 567 if keyHeight <= blockHeight && (keyTime.Before(blockTime) || keyTime.Equal(blockTime)) { 568 addrs := types.ValAddresses{} 569 if err = k.cdc.Unmarshal(unbondingValIterator.Value(), &addrs); err != nil { 570 return err 571 } 572 573 for _, valAddr := range addrs.Addresses { 574 addr, err := k.validatorAddressCodec.StringToBytes(valAddr) 575 if err != nil { 576 return err 577 } 578 val, err := k.GetValidator(ctx, addr) 579 if err != nil { 580 return errorsmod.Wrap(err, "validator in the unbonding queue was not found") 581 } 582 583 if !val.IsUnbonding() { 584 return fmt.Errorf("unexpected validator in unbonding queue; status was not unbonding") 585 } 586 587 if val.UnbondingOnHoldRefCount == 0 { 588 for _, id := range val.UnbondingIds { 589 if err = k.DeleteUnbondingIndex(ctx, id); err != nil { 590 return err 591 } 592 } 593 594 val, err = k.UnbondingToUnbonded(ctx, val) 595 if err != nil { 596 return err 597 } 598 599 if val.GetDelegatorShares().IsZero() { 600 str, err := k.validatorAddressCodec.StringToBytes(val.GetOperator()) 601 if err != nil { 602 return err 603 } 604 if err = k.RemoveValidator(ctx, str); err != nil { 605 return err 606 } 607 } else { 608 // remove unbonding ids 609 val.UnbondingIds = []uint64{} 610 } 611 612 // remove validator from queue 613 if err = k.DeleteValidatorQueue(ctx, val); err != nil { 614 return err 615 } 616 } 617 } 618 } 619 } 620 return nil 621 } 622 623 // IsValidatorJailed checks and returns boolean of a validator status jailed or not. 624 func (k Keeper) IsValidatorJailed(ctx context.Context, addr sdk.ConsAddress) (bool, error) { 625 v, err := k.GetValidatorByConsAddr(ctx, addr) 626 if err != nil { 627 return false, err 628 } 629 630 return v.Jailed, nil 631 } 632 633 // GetPubKeyByConsAddr returns the consensus public key by consensus address. 634 func (k Keeper) GetPubKeyByConsAddr(ctx context.Context, addr sdk.ConsAddress) (cmtprotocrypto.PublicKey, error) { 635 v, err := k.GetValidatorByConsAddr(ctx, addr) 636 if err != nil { 637 return cmtprotocrypto.PublicKey{}, err 638 } 639 640 pubkey, err := v.CmtConsPublicKey() 641 if err != nil { 642 return cmtprotocrypto.PublicKey{}, err 643 } 644 645 return pubkey, nil 646 }