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

     1  package keeper
     2  
     3  import (
     4  	"context"
     5  	"strconv"
     6  	"time"
     7  
     8  	"github.com/hashicorp/go-metrics"
     9  	"google.golang.org/grpc/codes"
    10  	"google.golang.org/grpc/status"
    11  
    12  	errorsmod "cosmossdk.io/errors"
    13  	"cosmossdk.io/math"
    14  
    15  	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
    16  	"github.com/cosmos/cosmos-sdk/telemetry"
    17  	sdk "github.com/cosmos/cosmos-sdk/types"
    18  	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
    19  	govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
    20  	"github.com/cosmos/cosmos-sdk/x/staking/types"
    21  )
    22  
    23  type msgServer struct {
    24  	*Keeper
    25  }
    26  
    27  // NewMsgServerImpl returns an implementation of the staking MsgServer interface
    28  // for the provided Keeper.
    29  func NewMsgServerImpl(keeper *Keeper) types.MsgServer {
    30  	return &msgServer{Keeper: keeper}
    31  }
    32  
    33  var _ types.MsgServer = msgServer{}
    34  
    35  // CreateValidator defines a method for creating a new validator
    36  func (k msgServer) CreateValidator(ctx context.Context, msg *types.MsgCreateValidator) (*types.MsgCreateValidatorResponse, error) {
    37  	valAddr, err := k.validatorAddressCodec.StringToBytes(msg.ValidatorAddress)
    38  	if err != nil {
    39  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
    40  	}
    41  
    42  	if err := msg.Validate(k.validatorAddressCodec); err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	minCommRate, err := k.MinCommissionRate(ctx)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	if msg.Commission.Rate.LT(minCommRate) {
    52  		return nil, errorsmod.Wrapf(types.ErrCommissionLTMinRate, "cannot set validator commission to less than minimum rate of %s", minCommRate)
    53  	}
    54  
    55  	// check to see if the pubkey or sender has been registered before
    56  	if _, err := k.GetValidator(ctx, valAddr); err == nil {
    57  		return nil, types.ErrValidatorOwnerExists
    58  	}
    59  
    60  	pk, ok := msg.Pubkey.GetCachedValue().(cryptotypes.PubKey)
    61  	if !ok {
    62  		return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidType, "Expecting cryptotypes.PubKey, got %T", pk)
    63  	}
    64  
    65  	if _, err := k.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk)); err == nil {
    66  		return nil, types.ErrValidatorPubKeyExists
    67  	}
    68  
    69  	bondDenom, err := k.BondDenom(ctx)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	if msg.Value.Denom != bondDenom {
    75  		return nil, errorsmod.Wrapf(
    76  			sdkerrors.ErrInvalidRequest, "invalid coin denomination: got %s, expected %s", msg.Value.Denom, bondDenom,
    77  		)
    78  	}
    79  
    80  	if _, err := msg.Description.EnsureLength(); err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	sdkCtx := sdk.UnwrapSDKContext(ctx)
    85  	cp := sdkCtx.ConsensusParams()
    86  	if cp.Validator != nil {
    87  		pkType := pk.Type()
    88  		hasKeyType := false
    89  		for _, keyType := range cp.Validator.PubKeyTypes {
    90  			if pkType == keyType {
    91  				hasKeyType = true
    92  				break
    93  			}
    94  		}
    95  		if !hasKeyType {
    96  			return nil, errorsmod.Wrapf(
    97  				types.ErrValidatorPubKeyTypeNotSupported,
    98  				"got: %s, expected: %s", pk.Type(), cp.Validator.PubKeyTypes,
    99  			)
   100  		}
   101  	}
   102  
   103  	validator, err := types.NewValidator(msg.ValidatorAddress, pk, msg.Description)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	commission := types.NewCommissionWithTime(
   109  		msg.Commission.Rate, msg.Commission.MaxRate,
   110  		msg.Commission.MaxChangeRate, sdkCtx.BlockHeader().Time,
   111  	)
   112  
   113  	validator, err = validator.SetInitialCommission(commission)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	validator.MinSelfDelegation = msg.MinSelfDelegation
   119  
   120  	err = k.SetValidator(ctx, validator)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  
   125  	err = k.SetValidatorByConsAddr(ctx, validator)
   126  	if err != nil {
   127  		return nil, err
   128  	}
   129  
   130  	err = k.SetNewValidatorByPowerIndex(ctx, validator)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	// call the after-creation hook
   136  	if err := k.Hooks().AfterValidatorCreated(ctx, valAddr); err != nil {
   137  		return nil, err
   138  	}
   139  
   140  	// move coins from the msg.Address account to a (self-delegation) delegator account
   141  	// the validator account and global shares are updated within here
   142  	// NOTE source will always be from a wallet which are unbonded
   143  	_, err = k.Keeper.Delegate(ctx, sdk.AccAddress(valAddr), msg.Value.Amount, types.Unbonded, validator, true)
   144  	if err != nil {
   145  		return nil, err
   146  	}
   147  
   148  	sdkCtx.EventManager().EmitEvents(sdk.Events{
   149  		sdk.NewEvent(
   150  			types.EventTypeCreateValidator,
   151  			sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress),
   152  			sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Value.String()),
   153  		),
   154  	})
   155  
   156  	return &types.MsgCreateValidatorResponse{}, nil
   157  }
   158  
   159  // EditValidator defines a method for editing an existing validator
   160  func (k msgServer) EditValidator(ctx context.Context, msg *types.MsgEditValidator) (*types.MsgEditValidatorResponse, error) {
   161  	valAddr, err := k.validatorAddressCodec.StringToBytes(msg.ValidatorAddress)
   162  	if err != nil {
   163  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
   164  	}
   165  
   166  	if msg.Description == (types.Description{}) {
   167  		return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "empty description")
   168  	}
   169  
   170  	if msg.MinSelfDelegation != nil && !msg.MinSelfDelegation.IsPositive() {
   171  		return nil, errorsmod.Wrap(
   172  			sdkerrors.ErrInvalidRequest,
   173  			"minimum self delegation must be a positive integer",
   174  		)
   175  	}
   176  
   177  	if msg.CommissionRate != nil {
   178  		if msg.CommissionRate.GT(math.LegacyOneDec()) || msg.CommissionRate.IsNegative() {
   179  			return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "commission rate must be between 0 and 1 (inclusive)")
   180  		}
   181  
   182  		minCommissionRate, err := k.MinCommissionRate(ctx)
   183  		if err != nil {
   184  			return nil, errorsmod.Wrap(sdkerrors.ErrLogic, err.Error())
   185  		}
   186  
   187  		if msg.CommissionRate.LT(minCommissionRate) {
   188  			return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "commission rate cannot be less than the min commission rate %s", minCommissionRate.String())
   189  		}
   190  	}
   191  
   192  	// validator must already be registered
   193  	validator, err := k.GetValidator(ctx, valAddr)
   194  	if err != nil {
   195  		return nil, err
   196  	}
   197  
   198  	// replace all editable fields (clients should autofill existing values)
   199  	description, err := validator.Description.UpdateDescription(msg.Description)
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  
   204  	validator.Description = description
   205  
   206  	if msg.CommissionRate != nil {
   207  		commission, err := k.UpdateValidatorCommission(ctx, validator, *msg.CommissionRate)
   208  		if err != nil {
   209  			return nil, err
   210  		}
   211  
   212  		// call the before-modification hook since we're about to update the commission
   213  		if err := k.Hooks().BeforeValidatorModified(ctx, valAddr); err != nil {
   214  			return nil, err
   215  		}
   216  
   217  		validator.Commission = commission
   218  	}
   219  
   220  	if msg.MinSelfDelegation != nil {
   221  		if !msg.MinSelfDelegation.GT(validator.MinSelfDelegation) {
   222  			return nil, types.ErrMinSelfDelegationDecreased
   223  		}
   224  
   225  		if msg.MinSelfDelegation.GT(validator.Tokens) {
   226  			return nil, types.ErrSelfDelegationBelowMinimum
   227  		}
   228  
   229  		validator.MinSelfDelegation = *msg.MinSelfDelegation
   230  	}
   231  
   232  	err = k.SetValidator(ctx, validator)
   233  	if err != nil {
   234  		return nil, err
   235  	}
   236  
   237  	sdkCtx := sdk.UnwrapSDKContext(ctx)
   238  	sdkCtx.EventManager().EmitEvents(sdk.Events{
   239  		sdk.NewEvent(
   240  			types.EventTypeEditValidator,
   241  			sdk.NewAttribute(types.AttributeKeyCommissionRate, validator.Commission.String()),
   242  			sdk.NewAttribute(types.AttributeKeyMinSelfDelegation, validator.MinSelfDelegation.String()),
   243  		),
   244  	})
   245  
   246  	return &types.MsgEditValidatorResponse{}, nil
   247  }
   248  
   249  // Delegate defines a method for performing a delegation of coins from a delegator to a validator
   250  func (k msgServer) Delegate(ctx context.Context, msg *types.MsgDelegate) (*types.MsgDelegateResponse, error) {
   251  	valAddr, valErr := k.validatorAddressCodec.StringToBytes(msg.ValidatorAddress)
   252  	if valErr != nil {
   253  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", valErr)
   254  	}
   255  
   256  	delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(msg.DelegatorAddress)
   257  	if err != nil {
   258  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
   259  	}
   260  
   261  	if !msg.Amount.IsValid() || !msg.Amount.Amount.IsPositive() {
   262  		return nil, errorsmod.Wrap(
   263  			sdkerrors.ErrInvalidRequest,
   264  			"invalid delegation amount",
   265  		)
   266  	}
   267  
   268  	validator, err := k.GetValidator(ctx, valAddr)
   269  	if err != nil {
   270  		return nil, err
   271  	}
   272  
   273  	bondDenom, err := k.BondDenom(ctx)
   274  	if err != nil {
   275  		return nil, err
   276  	}
   277  
   278  	if msg.Amount.Denom != bondDenom {
   279  		return nil, errorsmod.Wrapf(
   280  			sdkerrors.ErrInvalidRequest, "invalid coin denomination: got %s, expected %s", msg.Amount.Denom, bondDenom,
   281  		)
   282  	}
   283  
   284  	// NOTE: source funds are always unbonded
   285  	newShares, err := k.Keeper.Delegate(ctx, delegatorAddress, msg.Amount.Amount, types.Unbonded, validator, true)
   286  	if err != nil {
   287  		return nil, err
   288  	}
   289  
   290  	if msg.Amount.Amount.IsInt64() {
   291  		defer func() {
   292  			telemetry.IncrCounter(1, types.ModuleName, "delegate")
   293  			telemetry.SetGaugeWithLabels(
   294  				[]string{"tx", "msg", sdk.MsgTypeURL(msg)},
   295  				float32(msg.Amount.Amount.Int64()),
   296  				[]metrics.Label{telemetry.NewLabel("denom", msg.Amount.Denom)},
   297  			)
   298  		}()
   299  	}
   300  
   301  	sdkCtx := sdk.UnwrapSDKContext(ctx)
   302  	sdkCtx.EventManager().EmitEvents(sdk.Events{
   303  		sdk.NewEvent(
   304  			types.EventTypeDelegate,
   305  			sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress),
   306  			sdk.NewAttribute(types.AttributeKeyDelegator, msg.DelegatorAddress),
   307  			sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()),
   308  			sdk.NewAttribute(types.AttributeKeyNewShares, newShares.String()),
   309  		),
   310  	})
   311  
   312  	return &types.MsgDelegateResponse{}, nil
   313  }
   314  
   315  // BeginRedelegate defines a method for performing a redelegation of coins from a source validator to a destination validator of given delegator
   316  func (k msgServer) BeginRedelegate(ctx context.Context, msg *types.MsgBeginRedelegate) (*types.MsgBeginRedelegateResponse, error) {
   317  	valSrcAddr, err := k.validatorAddressCodec.StringToBytes(msg.ValidatorSrcAddress)
   318  	if err != nil {
   319  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid source validator address: %s", err)
   320  	}
   321  
   322  	valDstAddr, err := k.validatorAddressCodec.StringToBytes(msg.ValidatorDstAddress)
   323  	if err != nil {
   324  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid destination validator address: %s", err)
   325  	}
   326  
   327  	delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(msg.DelegatorAddress)
   328  	if err != nil {
   329  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
   330  	}
   331  
   332  	if !msg.Amount.IsValid() || !msg.Amount.Amount.IsPositive() {
   333  		return nil, errorsmod.Wrap(
   334  			sdkerrors.ErrInvalidRequest,
   335  			"invalid shares amount",
   336  		)
   337  	}
   338  
   339  	shares, err := k.ValidateUnbondAmount(
   340  		ctx, delegatorAddress, valSrcAddr, msg.Amount.Amount,
   341  	)
   342  	if err != nil {
   343  		return nil, err
   344  	}
   345  
   346  	bondDenom, err := k.BondDenom(ctx)
   347  	if err != nil {
   348  		return nil, err
   349  	}
   350  
   351  	if msg.Amount.Denom != bondDenom {
   352  		return nil, errorsmod.Wrapf(
   353  			sdkerrors.ErrInvalidRequest, "invalid coin denomination: got %s, expected %s", msg.Amount.Denom, bondDenom,
   354  		)
   355  	}
   356  
   357  	completionTime, err := k.BeginRedelegation(
   358  		ctx, delegatorAddress, valSrcAddr, valDstAddr, shares,
   359  	)
   360  	if err != nil {
   361  		return nil, err
   362  	}
   363  
   364  	if msg.Amount.Amount.IsInt64() {
   365  		defer func() {
   366  			telemetry.IncrCounter(1, types.ModuleName, "redelegate")
   367  			telemetry.SetGaugeWithLabels(
   368  				[]string{"tx", "msg", sdk.MsgTypeURL(msg)},
   369  				float32(msg.Amount.Amount.Int64()),
   370  				[]metrics.Label{telemetry.NewLabel("denom", msg.Amount.Denom)},
   371  			)
   372  		}()
   373  	}
   374  
   375  	sdkCtx := sdk.UnwrapSDKContext(ctx)
   376  	sdkCtx.EventManager().EmitEvents(sdk.Events{
   377  		sdk.NewEvent(
   378  			types.EventTypeRedelegate,
   379  			sdk.NewAttribute(types.AttributeKeySrcValidator, msg.ValidatorSrcAddress),
   380  			sdk.NewAttribute(types.AttributeKeyDstValidator, msg.ValidatorDstAddress),
   381  			sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()),
   382  			sdk.NewAttribute(types.AttributeKeyCompletionTime, completionTime.Format(time.RFC3339)),
   383  		),
   384  	})
   385  
   386  	return &types.MsgBeginRedelegateResponse{
   387  		CompletionTime: completionTime,
   388  	}, nil
   389  }
   390  
   391  // Undelegate defines a method for performing an undelegation from a delegate and a validator
   392  func (k msgServer) Undelegate(ctx context.Context, msg *types.MsgUndelegate) (*types.MsgUndelegateResponse, error) {
   393  	addr, err := k.validatorAddressCodec.StringToBytes(msg.ValidatorAddress)
   394  	if err != nil {
   395  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
   396  	}
   397  
   398  	delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(msg.DelegatorAddress)
   399  	if err != nil {
   400  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
   401  	}
   402  
   403  	if !msg.Amount.IsValid() || !msg.Amount.Amount.IsPositive() {
   404  		return nil, errorsmod.Wrap(
   405  			sdkerrors.ErrInvalidRequest,
   406  			"invalid shares amount",
   407  		)
   408  	}
   409  
   410  	shares, err := k.ValidateUnbondAmount(
   411  		ctx, delegatorAddress, addr, msg.Amount.Amount,
   412  	)
   413  	if err != nil {
   414  		return nil, err
   415  	}
   416  
   417  	bondDenom, err := k.BondDenom(ctx)
   418  	if err != nil {
   419  		return nil, err
   420  	}
   421  
   422  	if msg.Amount.Denom != bondDenom {
   423  		return nil, errorsmod.Wrapf(
   424  			sdkerrors.ErrInvalidRequest, "invalid coin denomination: got %s, expected %s", msg.Amount.Denom, bondDenom,
   425  		)
   426  	}
   427  
   428  	completionTime, undelegatedAmt, err := k.Keeper.Undelegate(ctx, delegatorAddress, addr, shares)
   429  	if err != nil {
   430  		return nil, err
   431  	}
   432  
   433  	undelegatedCoin := sdk.NewCoin(msg.Amount.Denom, undelegatedAmt)
   434  
   435  	if msg.Amount.Amount.IsInt64() {
   436  		defer func() {
   437  			telemetry.IncrCounter(1, types.ModuleName, "undelegate")
   438  			telemetry.SetGaugeWithLabels(
   439  				[]string{"tx", "msg", sdk.MsgTypeURL(msg)},
   440  				float32(msg.Amount.Amount.Int64()),
   441  				[]metrics.Label{telemetry.NewLabel("denom", msg.Amount.Denom)},
   442  			)
   443  		}()
   444  	}
   445  
   446  	sdkCtx := sdk.UnwrapSDKContext(ctx)
   447  	sdkCtx.EventManager().EmitEvents(sdk.Events{
   448  		sdk.NewEvent(
   449  			types.EventTypeUnbond,
   450  			sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress),
   451  			sdk.NewAttribute(types.AttributeKeyDelegator, msg.DelegatorAddress),
   452  			sdk.NewAttribute(sdk.AttributeKeyAmount, undelegatedCoin.String()),
   453  			sdk.NewAttribute(types.AttributeKeyCompletionTime, completionTime.Format(time.RFC3339)),
   454  		),
   455  	})
   456  
   457  	return &types.MsgUndelegateResponse{
   458  		CompletionTime: completionTime,
   459  		Amount:         undelegatedCoin,
   460  	}, nil
   461  }
   462  
   463  // CancelUnbondingDelegation defines a method for canceling the unbonding delegation
   464  // and delegate back to the validator.
   465  func (k msgServer) CancelUnbondingDelegation(ctx context.Context, msg *types.MsgCancelUnbondingDelegation) (*types.MsgCancelUnbondingDelegationResponse, error) {
   466  	valAddr, err := k.validatorAddressCodec.StringToBytes(msg.ValidatorAddress)
   467  	if err != nil {
   468  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
   469  	}
   470  
   471  	delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(msg.DelegatorAddress)
   472  	if err != nil {
   473  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
   474  	}
   475  
   476  	if !msg.Amount.IsValid() || !msg.Amount.Amount.IsPositive() {
   477  		return nil, errorsmod.Wrap(
   478  			sdkerrors.ErrInvalidRequest,
   479  			"invalid amount",
   480  		)
   481  	}
   482  
   483  	if msg.CreationHeight <= 0 {
   484  		return nil, errorsmod.Wrap(
   485  			sdkerrors.ErrInvalidRequest,
   486  			"invalid height",
   487  		)
   488  	}
   489  
   490  	bondDenom, err := k.BondDenom(ctx)
   491  	if err != nil {
   492  		return nil, err
   493  	}
   494  
   495  	if msg.Amount.Denom != bondDenom {
   496  		return nil, errorsmod.Wrapf(
   497  			sdkerrors.ErrInvalidRequest, "invalid coin denomination: got %s, expected %s", msg.Amount.Denom, bondDenom,
   498  		)
   499  	}
   500  
   501  	validator, err := k.GetValidator(ctx, valAddr)
   502  	if err != nil {
   503  		return nil, err
   504  	}
   505  
   506  	// In some situations, the exchange rate becomes invalid, e.g. if
   507  	// Validator loses all tokens due to slashing. In this case,
   508  	// make all future delegations invalid.
   509  	if validator.InvalidExRate() {
   510  		return nil, types.ErrDelegatorShareExRateInvalid
   511  	}
   512  
   513  	if validator.IsJailed() {
   514  		return nil, types.ErrValidatorJailed
   515  	}
   516  
   517  	ubd, err := k.GetUnbondingDelegation(ctx, delegatorAddress, valAddr)
   518  	if err != nil {
   519  		return nil, status.Errorf(
   520  			codes.NotFound,
   521  			"unbonding delegation with delegator %s not found for validator %s",
   522  			msg.DelegatorAddress, msg.ValidatorAddress,
   523  		)
   524  	}
   525  
   526  	var (
   527  		unbondEntry      types.UnbondingDelegationEntry
   528  		unbondEntryIndex int64 = -1
   529  	)
   530  
   531  	for i, entry := range ubd.Entries {
   532  		if entry.CreationHeight == msg.CreationHeight {
   533  			unbondEntry = entry
   534  			unbondEntryIndex = int64(i)
   535  			break
   536  		}
   537  	}
   538  	if unbondEntryIndex == -1 {
   539  		return nil, sdkerrors.ErrNotFound.Wrapf("unbonding delegation entry is not found at block height %d", msg.CreationHeight)
   540  	}
   541  
   542  	if unbondEntry.Balance.LT(msg.Amount.Amount) {
   543  		return nil, sdkerrors.ErrInvalidRequest.Wrap("amount is greater than the unbonding delegation entry balance")
   544  	}
   545  
   546  	sdkCtx := sdk.UnwrapSDKContext(ctx)
   547  	if unbondEntry.CompletionTime.Before(sdkCtx.BlockTime()) {
   548  		return nil, sdkerrors.ErrInvalidRequest.Wrap("unbonding delegation is already processed")
   549  	}
   550  
   551  	// delegate back the unbonding delegation amount to the validator
   552  	_, err = k.Keeper.Delegate(ctx, delegatorAddress, msg.Amount.Amount, types.Unbonding, validator, false)
   553  	if err != nil {
   554  		return nil, err
   555  	}
   556  
   557  	amount := unbondEntry.Balance.Sub(msg.Amount.Amount)
   558  	if amount.IsZero() {
   559  		ubd.RemoveEntry(unbondEntryIndex)
   560  	} else {
   561  		// update the unbondingDelegationEntryBalance and InitialBalance for ubd entry
   562  		unbondEntry.Balance = amount
   563  		unbondEntry.InitialBalance = unbondEntry.InitialBalance.Sub(msg.Amount.Amount)
   564  		ubd.Entries[unbondEntryIndex] = unbondEntry
   565  	}
   566  
   567  	// set the unbonding delegation or remove it if there are no more entries
   568  	if len(ubd.Entries) == 0 {
   569  		err = k.RemoveUnbondingDelegation(ctx, ubd)
   570  	} else {
   571  		err = k.SetUnbondingDelegation(ctx, ubd)
   572  	}
   573  
   574  	if err != nil {
   575  		return nil, err
   576  	}
   577  
   578  	sdkCtx.EventManager().EmitEvent(
   579  		sdk.NewEvent(
   580  			types.EventTypeCancelUnbondingDelegation,
   581  			sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()),
   582  			sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress),
   583  			sdk.NewAttribute(types.AttributeKeyDelegator, msg.DelegatorAddress),
   584  			sdk.NewAttribute(types.AttributeKeyCreationHeight, strconv.FormatInt(msg.CreationHeight, 10)),
   585  		),
   586  	)
   587  
   588  	return &types.MsgCancelUnbondingDelegationResponse{}, nil
   589  }
   590  
   591  // UpdateParams defines a method to perform updation of params exist in x/staking module.
   592  func (k msgServer) UpdateParams(ctx context.Context, msg *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {
   593  	if k.authority != msg.Authority {
   594  		return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, msg.Authority)
   595  	}
   596  
   597  	if err := msg.Params.Validate(); err != nil {
   598  		return nil, err
   599  	}
   600  
   601  	// store params
   602  	if err := k.SetParams(ctx, msg.Params); err != nil {
   603  		return nil, err
   604  	}
   605  
   606  	return &types.MsgUpdateParamsResponse{}, nil
   607  }