Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor x/distribution according to ADR 031 #7524

Merged
merged 9 commits into from
Oct 15, 2020
33 changes: 32 additions & 1 deletion proto/cosmos/distribution/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,25 @@ option (gogoproto.equal_all) = true;
import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";

// Msg defines the distribution Msg service.
service Msg {
// SetWithdrawAddress defines a method to change the withdraw address
// for a delegator (or validator self-delegation).
rpc SetWithdrawAddress(MsgSetWithdrawAddress) returns (MsgSetWithdrawAddressResponse);

// WithdrawDelegatorReward defines a method to withdraw rewards of delegator
// from a single validator.
rpc WithdrawDelegatorReward(MsgWithdrawDelegatorReward) returns (MsgWithdrawDelegatorRewardResponse);

// WithdrawValidatorCommission defines a method to withdraw the
// full commission to the validator address.
rpc WithdrawValidatorCommission(MsgWithdrawValidatorCommission) returns (MsgWithdrawValidatorCommissionResponse);

// FundCommunityPool defines a method to allow an account to directly
// fund the community pool.
rpc FundCommunityPool(MsgFundCommunityPool) returns (MsgFundCommunityPoolResponse);
}

// MsgSetWithdrawAddress sets the withdraw address for
// a delegator (or validator self-delegation).
message MsgSetWithdrawAddress {
Expand All @@ -17,6 +36,9 @@ message MsgSetWithdrawAddress {
string withdraw_address = 2 [(gogoproto.moretags) = "yaml:\"withdraw_address\""];
}

// MsgSetWithdrawAddressResponse defines the Msg/SetWithdrawAddress response type.
message MsgSetWithdrawAddressResponse { }

// MsgWithdrawDelegatorReward represents delegation withdrawal to a delegator
// from a single validator.
message MsgWithdrawDelegatorReward {
Expand All @@ -27,6 +49,9 @@ message MsgWithdrawDelegatorReward {
string validator_address = 2 [(gogoproto.moretags) = "yaml:\"validator_address\""];
}

// MsgWithdrawDelegatorRewardResponse defines the Msg/WithdrawDelegatorReward response type.
message MsgWithdrawDelegatorRewardResponse { }

// MsgWithdrawValidatorCommission withdraws the full commission to the validator
// address.
message MsgWithdrawValidatorCommission {
Expand All @@ -36,6 +61,9 @@ message MsgWithdrawValidatorCommission {
string validator_address = 1 [(gogoproto.moretags) = "yaml:\"validator_address\""];
}

// MsgWithdrawValidatorCommissionResponse defines the Msg/WithdrawValidatorCommission response type.
message MsgWithdrawValidatorCommissionResponse { }

// MsgFundCommunityPool allows an account to directly
// fund the community pool.
message MsgFundCommunityPool {
Expand All @@ -45,4 +73,7 @@ message MsgFundCommunityPool {
repeated cosmos.base.v1beta1.Coin amount = 1
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
string depositor = 2;
}
}

// MsgFundCommunityPoolResponse defines the Msg/FundCommunityPool response type.
message MsgFundCommunityPoolResponse { }
130 changes: 10 additions & 120 deletions x/distribution/handler.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package distribution

import (
metrics "github.com/armon/go-metrics"

"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
Expand All @@ -15,138 +12,31 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
ctx = ctx.WithEventManager(sdk.NewEventManager())

msgServer := keeper.NewMsgServerImpl(k)

switch msg := msg.(type) {
case *types.MsgSetWithdrawAddress:
return handleMsgModifyWithdrawAddress(ctx, msg, k)
res, err := msgServer.SetWithdrawAddress(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)

case *types.MsgWithdrawDelegatorReward:
return handleMsgWithdrawDelegatorReward(ctx, msg, k)
res, err := msgServer.WithdrawDelegatorReward(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)

case *types.MsgWithdrawValidatorCommission:
return handleMsgWithdrawValidatorCommission(ctx, msg, k)
res, err := msgServer.WithdrawValidatorCommission(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)

case *types.MsgFundCommunityPool:
return handleMsgFundCommunityPool(ctx, msg, k)
res, err := msgServer.FundCommunityPool(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)

default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized distribution message type: %T", msg)
}
}
}

// These functions assume everything has been authenticated (ValidateBasic passed, and signatures checked)

func handleMsgModifyWithdrawAddress(ctx sdk.Context, msg *types.MsgSetWithdrawAddress, k keeper.Keeper) (*sdk.Result, error) {
delegatorAddress, err := sdk.AccAddressFromBech32(msg.DelegatorAddress)
if err != nil {
return nil, err
}
withdrawAddress, err := sdk.AccAddressFromBech32(msg.DelegatorAddress)
if err != nil {
return nil, err
}
err = k.SetWithdrawAddr(ctx, delegatorAddress, withdrawAddress)
if err != nil {
return nil, err
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.DelegatorAddress),
),
)

return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil
}

func handleMsgWithdrawDelegatorReward(ctx sdk.Context, msg *types.MsgWithdrawDelegatorReward, k keeper.Keeper) (*sdk.Result, error) {
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, err
}
delegatorAddress, err := sdk.AccAddressFromBech32(msg.DelegatorAddress)
if err != nil {
return nil, err
}
amount, err := k.WithdrawDelegationRewards(ctx, delegatorAddress, valAddr)
if err != nil {
return nil, err
}

defer func() {
for _, a := range amount {
telemetry.SetGaugeWithLabels(
[]string{"tx", "msg", "withdraw_reward"},
float32(a.Amount.Int64()),
[]metrics.Label{telemetry.NewLabel("denom", a.Denom)},
)
}
}()

ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.DelegatorAddress),
),
)

return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil
}

func handleMsgWithdrawValidatorCommission(ctx sdk.Context, msg *types.MsgWithdrawValidatorCommission, k keeper.Keeper) (*sdk.Result, error) {
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, err
}
amount, err := k.WithdrawValidatorCommission(ctx, valAddr)
if err != nil {
return nil, err
}

defer func() {
for _, a := range amount {
telemetry.SetGaugeWithLabels(
[]string{"tx", "msg", "withdraw_commission"},
float32(a.Amount.Int64()),
[]metrics.Label{telemetry.NewLabel("denom", a.Denom)},
)
}
}()

ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.ValidatorAddress),
),
)

return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil
}

func handleMsgFundCommunityPool(ctx sdk.Context, msg *types.MsgFundCommunityPool, k keeper.Keeper) (*sdk.Result, error) {
depositer, err := sdk.AccAddressFromBech32(msg.Depositor)
if err != nil {
return nil, err
}
if err := k.FundCommunityPool(ctx, msg.Amount, depositer); err != nil {
return nil, err
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.Depositor),
),
)

return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil
}

func NewCommunityPoolSpendProposalHandler(k keeper.Keeper) govtypes.Handler {
return func(ctx sdk.Context, content govtypes.Content) error {
switch c := content.(type) {
Expand Down
140 changes: 140 additions & 0 deletions x/distribution/keeper/msg_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package keeper

import (
"context"

"github.com/armon/go-metrics"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
)

type msgServer struct {
Keeper
}

// NewMsgServerImpl returns an implementation of the bank MsgServer interface
// for the provided Keeper.
func NewMsgServerImpl(keeper Keeper) types.MsgServer {
return &msgServer{Keeper: keeper}
}

var _ types.MsgServer = msgServer{}

func (k msgServer) SetWithdrawAddress(goCtx context.Context, msg *types.MsgSetWithdrawAddress) (*types.MsgSetWithdrawAddressResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

delegatorAddress, err := sdk.AccAddressFromBech32(msg.DelegatorAddress)
if err != nil {
return nil, err
}
withdrawAddress, err := sdk.AccAddressFromBech32(msg.DelegatorAddress)
if err != nil {
return nil, err
}
err = k.SetWithdrawAddr(ctx, delegatorAddress, withdrawAddress)
if err != nil {
return nil, err
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.DelegatorAddress),
),
)

return &types.MsgSetWithdrawAddressResponse{}, nil
}

func (k msgServer) WithdrawDelegatorReward(goCtx context.Context, msg *types.MsgWithdrawDelegatorReward) (*types.MsgWithdrawDelegatorRewardResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, err
}
delegatorAddress, err := sdk.AccAddressFromBech32(msg.DelegatorAddress)
if err != nil {
return nil, err
}
amount, err := k.WithdrawDelegationRewards(ctx, delegatorAddress, valAddr)
if err != nil {
return nil, err
}

defer func() {
for _, a := range amount {
telemetry.SetGaugeWithLabels(
[]string{"tx", "msg", "withdraw_reward"},
float32(a.Amount.Int64()),
[]metrics.Label{telemetry.NewLabel("denom", a.Denom)},
)
}
}()

ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.DelegatorAddress),
),
)
return &types.MsgWithdrawDelegatorRewardResponse{}, nil
}

func (k msgServer) WithdrawValidatorCommission(goCtx context.Context, msg *types.MsgWithdrawValidatorCommission) (*types.MsgWithdrawValidatorCommissionResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, err
}
amount, err := k.Keeper.WithdrawValidatorCommission(ctx, valAddr)
if err != nil {
return nil, err
}

defer func() {
for _, a := range amount {
telemetry.SetGaugeWithLabels(
[]string{"tx", "msg", "withdraw_commission"},
float32(a.Amount.Int64()),
[]metrics.Label{telemetry.NewLabel("denom", a.Denom)},
)
}
}()

ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.ValidatorAddress),
),
)

return &types.MsgWithdrawValidatorCommissionResponse{}, nil
}

func (k msgServer) FundCommunityPool(goCtx context.Context, msg *types.MsgFundCommunityPool) (*types.MsgFundCommunityPoolResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

depositer, err := sdk.AccAddressFromBech32(msg.Depositor)
if err != nil {
return nil, err
}
if err := k.Keeper.FundCommunityPool(ctx, msg.Amount, depositer); err != nil {
return nil, err
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.Depositor),
),
)

return &types.MsgFundCommunityPoolResponse{}, nil
}
Loading