Skip to content

Commit

Permalink
Refactor x/distribution according to ADR 031 (#7524)
Browse files Browse the repository at this point in the history
* Refactor x/distribution according to ADR 31

* lint

* removed unused

* Apply suggestions from code review

Co-authored-by: Marie Gauthier <[email protected]>

Co-authored-by: Aaron Craelius <[email protected]>
Co-authored-by: Marie Gauthier <[email protected]>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
4 people authored Oct 15, 2020
1 parent 1279da5 commit bf71654
Show file tree
Hide file tree
Showing 4 changed files with 1,009 additions and 153 deletions.
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

0 comments on commit bf71654

Please sign in to comment.