feat(x/staking): implement RotateConsPubKey method (#18188)
This commit is contained in:
@@ -2,6 +2,7 @@ package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"cosmossdk.io/math"
|
||||
"cosmossdk.io/x/staking/types"
|
||||
@@ -605,6 +607,76 @@ func (k msgServer) UpdateParams(ctx context.Context, msg *types.MsgUpdateParams)
|
||||
return &types.MsgUpdateParamsResponse{}, nil
|
||||
}
|
||||
|
||||
func (k msgServer) RotateConsPubKey(_ context.Context, _ *types.MsgRotateConsPubKey) (*types.MsgRotateConsPubKeyResponse, error) {
|
||||
return nil, nil
|
||||
func (k msgServer) RotateConsPubKey(ctx context.Context, msg *types.MsgRotateConsPubKey) (res *types.MsgRotateConsPubKeyResponse, err error) {
|
||||
cv := msg.NewPubkey.GetCachedValue()
|
||||
pk, ok := cv.(cryptotypes.PubKey)
|
||||
if !ok {
|
||||
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidType, "expecting cryptotypes.PubKey, got %T", cv)
|
||||
}
|
||||
|
||||
// check cons key is already present in the key rotation history.
|
||||
rotatedTo, err := k.RotatedConsKeyMapIndex.Get(ctx, pk.Address())
|
||||
if err != nil && !errors.Is(err, collections.ErrNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if rotatedTo != nil {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidAddress,
|
||||
"the new public key is already present in rotation history, please try with a different one")
|
||||
}
|
||||
|
||||
newConsAddr := sdk.ConsAddress(pk.Address())
|
||||
|
||||
// checks if NewPubKey is not duplicated on ValidatorsByConsAddr
|
||||
validator1, _ := k.Keeper.ValidatorByConsAddr(ctx, newConsAddr)
|
||||
if validator1 != nil {
|
||||
return nil, types.ErrConsensusPubKeyAlreadyUsedForValidator
|
||||
}
|
||||
|
||||
valAddr, err := k.validatorAddressCodec.StringToBytes(msg.ValidatorAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
validator2, err := k.Keeper.GetValidator(ctx, valAddr)
|
||||
if err != nil {
|
||||
return nil, types.ErrNoValidatorFound
|
||||
}
|
||||
|
||||
if status := validator2.GetStatus(); status != types.Bonded {
|
||||
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidType, "validator status is not bonded, got %s", status.String())
|
||||
}
|
||||
|
||||
// Check if the validator is exceeding parameter MaxConsPubKeyRotations within the
|
||||
// unbonding period by iterating ConsPubKeyRotationHistory.
|
||||
err = k.exceedsMaxRotations(ctx, valAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check if the signing account has enough balance to pay KeyRotationFee
|
||||
// KeyRotationFees are sent to the community fund.
|
||||
params, err := k.Params.Get(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = k.Keeper.bankKeeper.SendCoinsFromAccountToModule(ctx, sdk.AccAddress(valAddr), types.DistributionModuleName, sdk.NewCoins(params.KeyRotationFee))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Add ConsPubKeyRotationHistory for tracking rotation
|
||||
err = k.setConsPubKeyRotationHistory(
|
||||
ctx,
|
||||
valAddr,
|
||||
validator2.ConsensusPubkey,
|
||||
msg.NewPubkey,
|
||||
params.KeyRotationFee,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user