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

     1  package keeper
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/hashicorp/go-metrics"
     7  
     8  	"cosmossdk.io/errors"
     9  
    10  	"github.com/cosmos/cosmos-sdk/telemetry"
    11  	sdk "github.com/cosmos/cosmos-sdk/types"
    12  	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
    13  	"github.com/cosmos/cosmos-sdk/x/distribution/types"
    14  	govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
    15  )
    16  
    17  type msgServer struct {
    18  	Keeper
    19  }
    20  
    21  var _ types.MsgServer = msgServer{}
    22  
    23  // NewMsgServerImpl returns an implementation of the distribution MsgServer interface
    24  // for the provided Keeper.
    25  func NewMsgServerImpl(keeper Keeper) types.MsgServer {
    26  	return &msgServer{Keeper: keeper}
    27  }
    28  
    29  func (k msgServer) SetWithdrawAddress(ctx context.Context, msg *types.MsgSetWithdrawAddress) (*types.MsgSetWithdrawAddressResponse, error) {
    30  	delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(msg.DelegatorAddress)
    31  	if err != nil {
    32  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
    33  	}
    34  
    35  	withdrawAddress, err := k.authKeeper.AddressCodec().StringToBytes(msg.WithdrawAddress)
    36  	if err != nil {
    37  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid withdraw address: %s", err)
    38  	}
    39  
    40  	err = k.SetWithdrawAddr(ctx, delegatorAddress, withdrawAddress)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	return &types.MsgSetWithdrawAddressResponse{}, nil
    46  }
    47  
    48  func (k msgServer) WithdrawDelegatorReward(ctx context.Context, msg *types.MsgWithdrawDelegatorReward) (*types.MsgWithdrawDelegatorRewardResponse, error) {
    49  	valAddr, err := k.stakingKeeper.ValidatorAddressCodec().StringToBytes(msg.ValidatorAddress)
    50  	if err != nil {
    51  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
    52  	}
    53  
    54  	delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(msg.DelegatorAddress)
    55  	if err != nil {
    56  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
    57  	}
    58  
    59  	amount, err := k.WithdrawDelegationRewards(ctx, delegatorAddress, valAddr)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	defer func() {
    65  		for _, a := range amount {
    66  			if a.Amount.IsInt64() {
    67  				telemetry.SetGaugeWithLabels(
    68  					[]string{"tx", "msg", "withdraw_reward"},
    69  					float32(a.Amount.Int64()),
    70  					[]metrics.Label{telemetry.NewLabel("denom", a.Denom)},
    71  				)
    72  			}
    73  		}
    74  	}()
    75  
    76  	return &types.MsgWithdrawDelegatorRewardResponse{Amount: amount}, nil
    77  }
    78  
    79  func (k msgServer) WithdrawValidatorCommission(ctx context.Context, msg *types.MsgWithdrawValidatorCommission) (*types.MsgWithdrawValidatorCommissionResponse, error) {
    80  	valAddr, err := k.stakingKeeper.ValidatorAddressCodec().StringToBytes(msg.ValidatorAddress)
    81  	if err != nil {
    82  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
    83  	}
    84  
    85  	amount, err := k.Keeper.WithdrawValidatorCommission(ctx, valAddr)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	defer func() {
    91  		for _, a := range amount {
    92  			if a.Amount.IsInt64() {
    93  				telemetry.SetGaugeWithLabels(
    94  					[]string{"tx", "msg", "withdraw_commission"},
    95  					float32(a.Amount.Int64()),
    96  					[]metrics.Label{telemetry.NewLabel("denom", a.Denom)},
    97  				)
    98  			}
    99  		}
   100  	}()
   101  
   102  	return &types.MsgWithdrawValidatorCommissionResponse{Amount: amount}, nil
   103  }
   104  
   105  func (k msgServer) FundCommunityPool(ctx context.Context, msg *types.MsgFundCommunityPool) (*types.MsgFundCommunityPoolResponse, error) {
   106  	depositor, err := k.authKeeper.AddressCodec().StringToBytes(msg.Depositor)
   107  	if err != nil {
   108  		return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid depositor address: %s", err)
   109  	}
   110  
   111  	if err := validateAmount(msg.Amount); err != nil {
   112  		return nil, err
   113  	}
   114  
   115  	if err := k.Keeper.FundCommunityPool(ctx, msg.Amount, depositor); err != nil {
   116  		return nil, err
   117  	}
   118  
   119  	return &types.MsgFundCommunityPoolResponse{}, nil
   120  }
   121  
   122  func (k msgServer) UpdateParams(ctx context.Context, msg *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {
   123  	if err := k.validateAuthority(msg.Authority); err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	if (!msg.Params.BaseProposerReward.IsNil() && !msg.Params.BaseProposerReward.IsZero()) || //nolint:staticcheck // deprecated but kept for backwards compatibility
   128  		(!msg.Params.BonusProposerReward.IsNil() && !msg.Params.BonusProposerReward.IsZero()) { //nolint:staticcheck // deprecated but kept for backwards compatibility
   129  		return nil, errors.Wrapf(sdkerrors.ErrInvalidRequest, "cannot update base or bonus proposer reward because these are deprecated fields")
   130  	}
   131  
   132  	if err := msg.Params.ValidateBasic(); err != nil {
   133  		return nil, err
   134  	}
   135  
   136  	if err := k.Params.Set(ctx, msg.Params); err != nil {
   137  		return nil, err
   138  	}
   139  
   140  	return &types.MsgUpdateParamsResponse{}, nil
   141  }
   142  
   143  func (k msgServer) CommunityPoolSpend(ctx context.Context, msg *types.MsgCommunityPoolSpend) (*types.MsgCommunityPoolSpendResponse, error) {
   144  	if err := k.validateAuthority(msg.Authority); err != nil {
   145  		return nil, err
   146  	}
   147  
   148  	if err := validateAmount(msg.Amount); err != nil {
   149  		return nil, err
   150  	}
   151  
   152  	recipient, err := k.authKeeper.AddressCodec().StringToBytes(msg.Recipient)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  
   157  	if k.bankKeeper.BlockedAddr(recipient) {
   158  		return nil, errors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive external funds", msg.Recipient)
   159  	}
   160  
   161  	if err := k.DistributeFromFeePool(ctx, msg.Amount, recipient); err != nil {
   162  		return nil, err
   163  	}
   164  
   165  	logger := k.Logger(ctx)
   166  	logger.Info("transferred from the community pool to recipient", "amount", msg.Amount.String(), "recipient", msg.Recipient)
   167  
   168  	return &types.MsgCommunityPoolSpendResponse{}, nil
   169  }
   170  
   171  func (k msgServer) DepositValidatorRewardsPool(ctx context.Context, msg *types.MsgDepositValidatorRewardsPool) (*types.MsgDepositValidatorRewardsPoolResponse, error) {
   172  	depositor, err := k.authKeeper.AddressCodec().StringToBytes(msg.Depositor)
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  
   177  	// deposit coins from depositor's account to the distribution module
   178  	if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, depositor, types.ModuleName, msg.Amount); err != nil {
   179  		return nil, err
   180  	}
   181  
   182  	valAddr, err := k.stakingKeeper.ValidatorAddressCodec().StringToBytes(msg.ValidatorAddress)
   183  	if err != nil {
   184  		return nil, err
   185  	}
   186  
   187  	validator, err := k.stakingKeeper.Validator(ctx, valAddr)
   188  	if err != nil {
   189  		return nil, err
   190  	}
   191  
   192  	if validator == nil {
   193  		return nil, errors.Wrapf(types.ErrNoValidatorExists, msg.ValidatorAddress)
   194  	}
   195  
   196  	// Allocate tokens from the distribution module to the validator, which are
   197  	// then distributed to the validator's delegators.
   198  	reward := sdk.NewDecCoinsFromCoins(msg.Amount...)
   199  	if err = k.AllocateTokensToValidator(ctx, validator, reward); err != nil {
   200  		return nil, err
   201  	}
   202  
   203  	logger := k.Logger(ctx)
   204  	logger.Info(
   205  		"transferred from rewards to validator rewards pool",
   206  		"depositor", msg.Depositor,
   207  		"amount", msg.Amount.String(),
   208  		"validator", msg.ValidatorAddress,
   209  	)
   210  
   211  	return &types.MsgDepositValidatorRewardsPoolResponse{}, nil
   212  }
   213  
   214  func (k *Keeper) validateAuthority(authority string) error {
   215  	if _, err := k.authKeeper.AddressCodec().StringToBytes(authority); err != nil {
   216  		return sdkerrors.ErrInvalidAddress.Wrapf("invalid authority address: %s", err)
   217  	}
   218  
   219  	if k.authority != authority {
   220  		return errors.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, authority)
   221  	}
   222  
   223  	return nil
   224  }
   225  
   226  func validateAmount(amount sdk.Coins) error {
   227  	if amount == nil {
   228  		return errors.Wrap(sdkerrors.ErrInvalidCoins, "amount cannot be nil")
   229  	}
   230  
   231  	if err := amount.Validate(); err != nil {
   232  		return errors.Wrap(sdkerrors.ErrInvalidCoins, amount.String())
   233  	}
   234  
   235  	return nil
   236  }