github.com/cosmos/cosmos-sdk@v0.50.10/x/staking/keeper/val_state_change.go (about)

     1  package keeper
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"sort"
     8  
     9  	abci "github.com/cometbft/cometbft/abci/types"
    10  	gogotypes "github.com/cosmos/gogoproto/types"
    11  
    12  	"cosmossdk.io/core/address"
    13  	"cosmossdk.io/math"
    14  
    15  	sdk "github.com/cosmos/cosmos-sdk/types"
    16  	"github.com/cosmos/cosmos-sdk/x/staking/types"
    17  )
    18  
    19  // BlockValidatorUpdates calculates the ValidatorUpdates for the current block
    20  // Called in each EndBlock
    21  func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]abci.ValidatorUpdate, error) {
    22  	// Calculate validator set changes.
    23  	//
    24  	// NOTE: ApplyAndReturnValidatorSetUpdates has to come before
    25  	// UnbondAllMatureValidatorQueue.
    26  	// This fixes a bug when the unbonding period is instant (is the case in
    27  	// some of the tests). The test expected the validator to be completely
    28  	// unbonded after the Endblocker (go from Bonded -> Unbonding during
    29  	// ApplyAndReturnValidatorSetUpdates and then Unbonding -> Unbonded during
    30  	// UnbondAllMatureValidatorQueue).
    31  	validatorUpdates, err := k.ApplyAndReturnValidatorSetUpdates(ctx)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  
    36  	// unbond all mature validators from the unbonding queue
    37  	err = k.UnbondAllMatureValidators(ctx)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  
    42  	sdkCtx := sdk.UnwrapSDKContext(ctx)
    43  	// Remove all mature unbonding delegations from the ubd queue.
    44  	matureUnbonds, err := k.DequeueAllMatureUBDQueue(ctx, sdkCtx.BlockHeader().Time)
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  
    49  	for _, dvPair := range matureUnbonds {
    50  		addr, err := k.validatorAddressCodec.StringToBytes(dvPair.ValidatorAddress)
    51  		if err != nil {
    52  			return nil, err
    53  		}
    54  		delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(dvPair.DelegatorAddress)
    55  		if err != nil {
    56  			return nil, err
    57  		}
    58  
    59  		balances, err := k.CompleteUnbonding(ctx, delegatorAddress, addr)
    60  		if err != nil {
    61  			continue
    62  		}
    63  
    64  		sdkCtx.EventManager().EmitEvent(
    65  			sdk.NewEvent(
    66  				types.EventTypeCompleteUnbonding,
    67  				sdk.NewAttribute(sdk.AttributeKeyAmount, balances.String()),
    68  				sdk.NewAttribute(types.AttributeKeyValidator, dvPair.ValidatorAddress),
    69  				sdk.NewAttribute(types.AttributeKeyDelegator, dvPair.DelegatorAddress),
    70  			),
    71  		)
    72  	}
    73  
    74  	// Remove all mature redelegations from the red queue.
    75  	matureRedelegations, err := k.DequeueAllMatureRedelegationQueue(ctx, sdkCtx.BlockHeader().Time)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	for _, dvvTriplet := range matureRedelegations {
    81  		valSrcAddr, err := k.validatorAddressCodec.StringToBytes(dvvTriplet.ValidatorSrcAddress)
    82  		if err != nil {
    83  			return nil, err
    84  		}
    85  		valDstAddr, err := k.validatorAddressCodec.StringToBytes(dvvTriplet.ValidatorDstAddress)
    86  		if err != nil {
    87  			return nil, err
    88  		}
    89  		delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(dvvTriplet.DelegatorAddress)
    90  		if err != nil {
    91  			return nil, err
    92  		}
    93  
    94  		balances, err := k.CompleteRedelegation(
    95  			ctx,
    96  			delegatorAddress,
    97  			valSrcAddr,
    98  			valDstAddr,
    99  		)
   100  		if err != nil {
   101  			continue
   102  		}
   103  
   104  		sdkCtx.EventManager().EmitEvent(
   105  			sdk.NewEvent(
   106  				types.EventTypeCompleteRedelegation,
   107  				sdk.NewAttribute(sdk.AttributeKeyAmount, balances.String()),
   108  				sdk.NewAttribute(types.AttributeKeyDelegator, dvvTriplet.DelegatorAddress),
   109  				sdk.NewAttribute(types.AttributeKeySrcValidator, dvvTriplet.ValidatorSrcAddress),
   110  				sdk.NewAttribute(types.AttributeKeyDstValidator, dvvTriplet.ValidatorDstAddress),
   111  			),
   112  		)
   113  	}
   114  
   115  	return validatorUpdates, nil
   116  }
   117  
   118  // ApplyAndReturnValidatorSetUpdates applies and return accumulated updates to the bonded validator set. Also,
   119  // * Updates the active valset as keyed by LastValidatorPowerKey.
   120  // * Updates the total power as keyed by LastTotalPowerKey.
   121  // * Updates validator status' according to updated powers.
   122  // * Updates the fee pool bonded vs not-bonded tokens.
   123  // * Updates relevant indices.
   124  // It gets called once after genesis, another time maybe after genesis transactions,
   125  // then once at every EndBlock.
   126  //
   127  // CONTRACT: Only validators with non-zero power or zero-power that were bonded
   128  // at the previous block height or were removed from the validator set entirely
   129  // are returned to CometBFT.
   130  func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx context.Context) (updates []abci.ValidatorUpdate, err error) {
   131  	params, err := k.GetParams(ctx)
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  	maxValidators := params.MaxValidators
   136  	powerReduction := k.PowerReduction(ctx)
   137  	totalPower := math.ZeroInt()
   138  	amtFromBondedToNotBonded, amtFromNotBondedToBonded := math.ZeroInt(), math.ZeroInt()
   139  
   140  	// Retrieve the last validator set.
   141  	// The persistent set is updated later in this function.
   142  	// (see LastValidatorPowerKey).
   143  	last, err := k.getLastValidatorsByAddr(ctx)
   144  	if err != nil {
   145  		return nil, err
   146  	}
   147  
   148  	// Iterate over validators, highest power to lowest.
   149  	iterator, err := k.ValidatorsPowerStoreIterator(ctx)
   150  	if err != nil {
   151  		return nil, err
   152  	}
   153  	defer iterator.Close()
   154  
   155  	for count := 0; iterator.Valid() && count < int(maxValidators); iterator.Next() {
   156  		// everything that is iterated in this loop is becoming or already a
   157  		// part of the bonded validator set
   158  		valAddr := sdk.ValAddress(iterator.Value())
   159  		validator := k.mustGetValidator(ctx, valAddr)
   160  
   161  		if validator.Jailed {
   162  			panic("should never retrieve a jailed validator from the power store")
   163  		}
   164  
   165  		// if we get to a zero-power validator (which we don't bond),
   166  		// there are no more possible bonded validators
   167  		if validator.PotentialConsensusPower(k.PowerReduction(ctx)) == 0 {
   168  			break
   169  		}
   170  
   171  		// apply the appropriate state change if necessary
   172  		switch {
   173  		case validator.IsUnbonded():
   174  			validator, err = k.unbondedToBonded(ctx, validator)
   175  			if err != nil {
   176  				return
   177  			}
   178  			amtFromNotBondedToBonded = amtFromNotBondedToBonded.Add(validator.GetTokens())
   179  		case validator.IsUnbonding():
   180  			validator, err = k.unbondingToBonded(ctx, validator)
   181  			if err != nil {
   182  				return
   183  			}
   184  			amtFromNotBondedToBonded = amtFromNotBondedToBonded.Add(validator.GetTokens())
   185  		case validator.IsBonded():
   186  			// no state change
   187  		default:
   188  			panic("unexpected validator status")
   189  		}
   190  
   191  		// fetch the old power bytes
   192  		valAddrStr, err := k.validatorAddressCodec.BytesToString(valAddr)
   193  		if err != nil {
   194  			return nil, err
   195  		}
   196  		oldPowerBytes, found := last[valAddrStr]
   197  		newPower := validator.ConsensusPower(powerReduction)
   198  		newPowerBytes := k.cdc.MustMarshal(&gogotypes.Int64Value{Value: newPower})
   199  
   200  		// update the validator set if power has changed
   201  		if !found || !bytes.Equal(oldPowerBytes, newPowerBytes) {
   202  			updates = append(updates, validator.ABCIValidatorUpdate(powerReduction))
   203  
   204  			if err = k.SetLastValidatorPower(ctx, valAddr, newPower); err != nil {
   205  				return nil, err
   206  			}
   207  		}
   208  
   209  		delete(last, valAddrStr)
   210  		count++
   211  
   212  		totalPower = totalPower.Add(math.NewInt(newPower))
   213  	}
   214  
   215  	noLongerBonded, err := sortNoLongerBonded(last, k.validatorAddressCodec)
   216  	if err != nil {
   217  		return nil, err
   218  	}
   219  
   220  	for _, valAddrBytes := range noLongerBonded {
   221  		validator := k.mustGetValidator(ctx, sdk.ValAddress(valAddrBytes))
   222  		validator, err = k.bondedToUnbonding(ctx, validator)
   223  		if err != nil {
   224  			return nil, err
   225  		}
   226  		str, err := k.validatorAddressCodec.StringToBytes(validator.GetOperator())
   227  		if err != nil {
   228  			return nil, err
   229  		}
   230  		amtFromBondedToNotBonded = amtFromBondedToNotBonded.Add(validator.GetTokens())
   231  		if err = k.DeleteLastValidatorPower(ctx, str); err != nil {
   232  			return nil, err
   233  		}
   234  
   235  		updates = append(updates, validator.ABCIValidatorUpdateZero())
   236  	}
   237  
   238  	// Update the pools based on the recent updates in the validator set:
   239  	// - The tokens from the non-bonded candidates that enter the new validator set need to be transferred
   240  	// to the Bonded pool.
   241  	// - The tokens from the bonded validators that are being kicked out from the validator set
   242  	// need to be transferred to the NotBonded pool.
   243  	switch {
   244  	// Compare and subtract the respective amounts to only perform one transfer.
   245  	// This is done in order to avoid doing multiple updates inside each iterator/loop.
   246  	case amtFromNotBondedToBonded.GT(amtFromBondedToNotBonded):
   247  		if err = k.notBondedTokensToBonded(ctx, amtFromNotBondedToBonded.Sub(amtFromBondedToNotBonded)); err != nil {
   248  			return nil, err
   249  		}
   250  	case amtFromNotBondedToBonded.LT(amtFromBondedToNotBonded):
   251  		if err = k.bondedTokensToNotBonded(ctx, amtFromBondedToNotBonded.Sub(amtFromNotBondedToBonded)); err != nil {
   252  			return nil, err
   253  		}
   254  	default: // equal amounts of tokens; no update required
   255  	}
   256  
   257  	// set total power on lookup index if there are any updates
   258  	if len(updates) > 0 {
   259  		if err = k.SetLastTotalPower(ctx, totalPower); err != nil {
   260  			return nil, err
   261  		}
   262  	}
   263  
   264  	// set the list of validator updates
   265  	if err = k.SetValidatorUpdates(ctx, updates); err != nil {
   266  		return nil, err
   267  	}
   268  
   269  	return updates, err
   270  }
   271  
   272  // Validator state transitions
   273  
   274  func (k Keeper) bondedToUnbonding(ctx context.Context, validator types.Validator) (types.Validator, error) {
   275  	if !validator.IsBonded() {
   276  		panic(fmt.Sprintf("bad state transition bondedToUnbonding, validator: %v\n", validator))
   277  	}
   278  
   279  	return k.BeginUnbondingValidator(ctx, validator)
   280  }
   281  
   282  func (k Keeper) unbondingToBonded(ctx context.Context, validator types.Validator) (types.Validator, error) {
   283  	if !validator.IsUnbonding() {
   284  		panic(fmt.Sprintf("bad state transition unbondingToBonded, validator: %v\n", validator))
   285  	}
   286  
   287  	return k.bondValidator(ctx, validator)
   288  }
   289  
   290  func (k Keeper) unbondedToBonded(ctx context.Context, validator types.Validator) (types.Validator, error) {
   291  	if !validator.IsUnbonded() {
   292  		panic(fmt.Sprintf("bad state transition unbondedToBonded, validator: %v\n", validator))
   293  	}
   294  
   295  	return k.bondValidator(ctx, validator)
   296  }
   297  
   298  // UnbondingToUnbonded switches a validator from unbonding state to unbonded state
   299  func (k Keeper) UnbondingToUnbonded(ctx context.Context, validator types.Validator) (types.Validator, error) {
   300  	if !validator.IsUnbonding() {
   301  		return types.Validator{}, fmt.Errorf("bad state transition unbondingToUnbonded, validator: %v", validator)
   302  	}
   303  
   304  	return k.completeUnbondingValidator(ctx, validator)
   305  }
   306  
   307  // send a validator to jail
   308  func (k Keeper) jailValidator(ctx context.Context, validator types.Validator) error {
   309  	if validator.Jailed {
   310  		return types.ErrValidatorJailed.Wrapf("cannot jail already jailed validator, validator: %v", validator)
   311  	}
   312  
   313  	validator.Jailed = true
   314  	if err := k.SetValidator(ctx, validator); err != nil {
   315  		return err
   316  	}
   317  
   318  	return k.DeleteValidatorByPowerIndex(ctx, validator)
   319  }
   320  
   321  // remove a validator from jail
   322  func (k Keeper) unjailValidator(ctx context.Context, validator types.Validator) error {
   323  	if !validator.Jailed {
   324  		return fmt.Errorf("cannot unjail already unjailed validator, validator: %v", validator)
   325  	}
   326  
   327  	validator.Jailed = false
   328  	if err := k.SetValidator(ctx, validator); err != nil {
   329  		return err
   330  	}
   331  
   332  	return k.SetValidatorByPowerIndex(ctx, validator)
   333  }
   334  
   335  // perform all the store operations for when a validator status becomes bonded
   336  func (k Keeper) bondValidator(ctx context.Context, validator types.Validator) (types.Validator, error) {
   337  	// delete the validator by power index, as the key will change
   338  	if err := k.DeleteValidatorByPowerIndex(ctx, validator); err != nil {
   339  		return validator, err
   340  	}
   341  
   342  	validator = validator.UpdateStatus(types.Bonded)
   343  
   344  	// save the now bonded validator record to the two referenced stores
   345  	if err := k.SetValidator(ctx, validator); err != nil {
   346  		return validator, err
   347  	}
   348  
   349  	if err := k.SetValidatorByPowerIndex(ctx, validator); err != nil {
   350  		return validator, err
   351  	}
   352  
   353  	// delete from queue if present
   354  	if err := k.DeleteValidatorQueue(ctx, validator); err != nil {
   355  		return validator, err
   356  	}
   357  
   358  	// trigger hook
   359  	consAddr, err := validator.GetConsAddr()
   360  	if err != nil {
   361  		return validator, err
   362  	}
   363  
   364  	str, err := k.validatorAddressCodec.StringToBytes(validator.GetOperator())
   365  	if err != nil {
   366  		return validator, err
   367  	}
   368  
   369  	if err := k.Hooks().AfterValidatorBonded(ctx, consAddr, str); err != nil {
   370  		return validator, err
   371  	}
   372  
   373  	return validator, err
   374  }
   375  
   376  // BeginUnbondingValidator performs all the store operations for when a validator begins unbonding
   377  func (k Keeper) BeginUnbondingValidator(ctx context.Context, validator types.Validator) (types.Validator, error) {
   378  	params, err := k.GetParams(ctx)
   379  	if err != nil {
   380  		return validator, err
   381  	}
   382  
   383  	// delete the validator by power index, as the key will change
   384  	if err = k.DeleteValidatorByPowerIndex(ctx, validator); err != nil {
   385  		return validator, err
   386  	}
   387  
   388  	// sanity check
   389  	if validator.Status != types.Bonded {
   390  		panic(fmt.Sprintf("should not already be unbonded or unbonding, validator: %v\n", validator))
   391  	}
   392  
   393  	id, err := k.IncrementUnbondingID(ctx)
   394  	if err != nil {
   395  		return validator, err
   396  	}
   397  
   398  	validator = validator.UpdateStatus(types.Unbonding)
   399  
   400  	sdkCtx := sdk.UnwrapSDKContext(ctx)
   401  	// set the unbonding completion time and completion height appropriately
   402  	validator.UnbondingTime = sdkCtx.BlockHeader().Time.Add(params.UnbondingTime)
   403  	validator.UnbondingHeight = sdkCtx.BlockHeader().Height
   404  
   405  	validator.UnbondingIds = append(validator.UnbondingIds, id)
   406  
   407  	// save the now unbonded validator record and power index
   408  	if err = k.SetValidator(ctx, validator); err != nil {
   409  		return validator, err
   410  	}
   411  
   412  	if err = k.SetValidatorByPowerIndex(ctx, validator); err != nil {
   413  		return validator, err
   414  	}
   415  
   416  	// Adds to unbonding validator queue
   417  	if err = k.InsertUnbondingValidatorQueue(ctx, validator); err != nil {
   418  		return validator, err
   419  	}
   420  
   421  	// trigger hook
   422  	consAddr, err := validator.GetConsAddr()
   423  	if err != nil {
   424  		return validator, err
   425  	}
   426  
   427  	str, err := k.validatorAddressCodec.StringToBytes(validator.GetOperator())
   428  	if err != nil {
   429  		return validator, err
   430  	}
   431  
   432  	if err := k.Hooks().AfterValidatorBeginUnbonding(ctx, consAddr, str); err != nil {
   433  		return validator, err
   434  	}
   435  
   436  	if err := k.SetValidatorByUnbondingID(ctx, validator, id); err != nil {
   437  		return validator, err
   438  	}
   439  
   440  	if err := k.Hooks().AfterUnbondingInitiated(ctx, id); err != nil {
   441  		return validator, err
   442  	}
   443  
   444  	return validator, nil
   445  }
   446  
   447  // perform all the store operations for when a validator status becomes unbonded
   448  func (k Keeper) completeUnbondingValidator(ctx context.Context, validator types.Validator) (types.Validator, error) {
   449  	validator = validator.UpdateStatus(types.Unbonded)
   450  	if err := k.SetValidator(ctx, validator); err != nil {
   451  		return validator, err
   452  	}
   453  
   454  	return validator, nil
   455  }
   456  
   457  // map of operator bech32-addresses to serialized power
   458  // We use bech32 strings here, because we can't have slices as keys: map[[]byte][]byte
   459  type validatorsByAddr map[string][]byte
   460  
   461  // get the last validator set
   462  func (k Keeper) getLastValidatorsByAddr(ctx context.Context) (validatorsByAddr, error) {
   463  	last := make(validatorsByAddr)
   464  
   465  	iterator, err := k.LastValidatorsIterator(ctx)
   466  	if err != nil {
   467  		return nil, err
   468  	}
   469  	defer iterator.Close()
   470  
   471  	for ; iterator.Valid(); iterator.Next() {
   472  		// extract the validator address from the key (prefix is 1-byte, addrLen is 1-byte)
   473  		valAddr := types.AddressFromLastValidatorPowerKey(iterator.Key())
   474  		valAddrStr, err := k.validatorAddressCodec.BytesToString(valAddr)
   475  		if err != nil {
   476  			return nil, err
   477  		}
   478  
   479  		powerBytes := iterator.Value()
   480  		last[valAddrStr] = make([]byte, len(powerBytes))
   481  		copy(last[valAddrStr], powerBytes)
   482  	}
   483  
   484  	return last, nil
   485  }
   486  
   487  // given a map of remaining validators to previous bonded power
   488  // returns the list of validators to be unbonded, sorted by operator address
   489  func sortNoLongerBonded(last validatorsByAddr, ac address.Codec) ([][]byte, error) {
   490  	// sort the map keys for determinism
   491  	noLongerBonded := make([][]byte, len(last))
   492  	index := 0
   493  
   494  	for valAddrStr := range last {
   495  		valAddrBytes, err := ac.StringToBytes(valAddrStr)
   496  		if err != nil {
   497  			return nil, err
   498  		}
   499  		noLongerBonded[index] = valAddrBytes
   500  		index++
   501  	}
   502  	// sorted by address - order doesn't matter
   503  	sort.SliceStable(noLongerBonded, func(i, j int) bool {
   504  		// -1 means strictly less than
   505  		return bytes.Compare(noLongerBonded[i], noLongerBonded[j]) == -1
   506  	})
   507  
   508  	return noLongerBonded, nil
   509  }