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/gov): move ValidateBasic to msg server #15832

Merged
merged 15 commits into from
Apr 17, 2023
Merged
130 changes: 117 additions & 13 deletions x/gov/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import (
"strconv"

"cosmossdk.io/errors"
"cosmossdk.io/math"
"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"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
Expand All @@ -29,24 +31,43 @@ var _ v1.MsgServer = msgServer{}

// SubmitProposal implements the MsgServer.SubmitProposal method.
func (k msgServer) SubmitProposal(goCtx context.Context, msg *v1.MsgSubmitProposal) (*v1.MsgSubmitProposalResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

initialDeposit := msg.GetInitialDeposit()

if err := k.validateInitialDeposit(ctx, initialDeposit, msg.Expedited); err != nil {
return nil, err
if msg.Title == "" {
return nil, errors.Wrap(sdkerrors.ErrInvalidRequest, "proposal title cannot be empty")
}
if msg.Summary == "" {
return nil, errors.Wrap(sdkerrors.ErrInvalidRequest, "proposal summary cannot be empty")
}

proposer, err := k.authKeeper.StringToBytes(msg.GetProposer())
if err != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid proposer address: %s", err)
}

if err := validateAmount(sdk.NewCoins(msg.InitialDeposit...)); err != nil {
return nil, err
}

// Check that either metadata or Msgs length is non nil.
if len(msg.Messages) == 0 && len(msg.Metadata) == 0 {
return nil, errors.Wrap(govtypes.ErrNoProposalMsgs, "either metadata or Msgs length must be non-nil")
}

proposalMsgs, err := msg.GetMsgs()
if err != nil {
return nil, err
}

if err := validateMsgs(proposalMsgs); err != nil {
return nil, err
}

ctx := sdk.UnwrapSDKContext(goCtx)
initialDeposit := msg.GetInitialDeposit()

if err := k.validateInitialDeposit(ctx, initialDeposit, msg.Expedited); err != nil {
return nil, err
}

proposal, err := k.Keeper.SubmitProposal(ctx, proposalMsgs, msg.Metadata, msg.Title, msg.Summary, proposer, msg.Expedited)
if err != nil {
return nil, err
Expand Down Expand Up @@ -85,12 +106,12 @@ func (k msgServer) SubmitProposal(goCtx context.Context, msg *v1.MsgSubmitPropos

// CancelProposals implements the MsgServer.CancelProposal method.
func (k msgServer) CancelProposal(goCtx context.Context, msg *v1.MsgCancelProposal) (*v1.MsgCancelProposalResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
_, err := k.authKeeper.StringToBytes(msg.Proposer)
if err != nil {
return nil, err
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid proposer address: %s", err)
}

ctx := sdk.UnwrapSDKContext(goCtx)
if err := k.Keeper.CancelProposal(ctx, msg.ProposalId, msg.Proposer); err != nil {
return nil, err
}
Expand Down Expand Up @@ -139,11 +160,16 @@ func (k msgServer) ExecLegacyContent(goCtx context.Context, msg *v1.MsgExecLegac

// Vote implements the MsgServer.Vote method.
func (k msgServer) Vote(goCtx context.Context, msg *v1.MsgVote) (*v1.MsgVoteResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
accAddr, err := k.authKeeper.StringToBytes(msg.Voter)
if err != nil {
return nil, err
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid voter address: %s", err)
}

if !v1.ValidVoteOption(msg.Option) {
return nil, errors.Wrap(govtypes.ErrInvalidVote, msg.Option.String())
}

ctx := sdk.UnwrapSDKContext(goCtx)
err = k.Keeper.AddVote(ctx, msg.ProposalId, accAddr, v1.NewNonSplitVoteOption(msg.Option), msg.Metadata)
if err != nil {
return nil, err
Expand All @@ -162,11 +188,41 @@ func (k msgServer) Vote(goCtx context.Context, msg *v1.MsgVote) (*v1.MsgVoteResp

// VoteWeighted implements the MsgServer.VoteWeighted method.
func (k msgServer) VoteWeighted(goCtx context.Context, msg *v1.MsgVoteWeighted) (*v1.MsgVoteWeightedResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
accAddr, accErr := k.authKeeper.StringToBytes(msg.Voter)
if accErr != nil {
return nil, accErr
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid voter address: %s", accErr)
}

if len(msg.Options) == 0 {
return nil, errors.Wrap(sdkerrors.ErrInvalidRequest, v1.WeightedVoteOptions(msg.Options).String())
}

totalWeight := math.LegacyNewDec(0)
usedOptions := make(map[v1.VoteOption]bool)
for _, option := range msg.Options {
if !option.IsValid() {
return nil, errors.Wrap(govtypes.ErrInvalidVote, option.String())
}
weight, err := sdk.NewDecFromStr(option.Weight)
if err != nil {
return nil, errors.Wrapf(govtypes.ErrInvalidVote, "invalid weight: %s", err)
}
totalWeight = totalWeight.Add(weight)
if usedOptions[option.Option] {
return nil, errors.Wrap(govtypes.ErrInvalidVote, "duplicated vote option")
}
usedOptions[option.Option] = true
}

if totalWeight.GT(math.LegacyNewDec(1)) {
return nil, errors.Wrap(govtypes.ErrInvalidVote, "total weight overflow 1.00")
}

if totalWeight.LT(math.LegacyNewDec(1)) {
return nil, errors.Wrap(govtypes.ErrInvalidVote, "total weight lower than 1.00")
}

ctx := sdk.UnwrapSDKContext(goCtx)
err := k.Keeper.AddVote(ctx, msg.ProposalId, accAddr, msg.Options, msg.Metadata)
if err != nil {
return nil, err
Expand All @@ -185,11 +241,16 @@ func (k msgServer) VoteWeighted(goCtx context.Context, msg *v1.MsgVoteWeighted)

// Deposit implements the MsgServer.Deposit method.
func (k msgServer) Deposit(goCtx context.Context, msg *v1.MsgDeposit) (*v1.MsgDepositResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
accAddr, err := k.authKeeper.StringToBytes(msg.Depositor)
if err != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid depositor address: %s", err)
}

if err := validateAmount(sdk.NewCoins(msg.Amount...)); err != nil {
return nil, err
}

ctx := sdk.UnwrapSDKContext(goCtx)
votingStarted, err := k.Keeper.AddDeposit(ctx, msg.ProposalId, accAddr, msg.Amount)
if err != nil {
return nil, err
Expand Down Expand Up @@ -221,6 +282,10 @@ func (k msgServer) UpdateParams(goCtx context.Context, msg *v1.MsgUpdateParams)
return nil, errors.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, msg.Authority)
}

if err := msg.Params.ValidateBasic(); err != nil {
return nil, err
}

ctx := sdk.UnwrapSDKContext(goCtx)
if err := k.SetParams(ctx, msg.Params); err != nil {
return nil, err
Expand All @@ -243,6 +308,17 @@ func NewLegacyMsgServerImpl(govAcct string, v1Server v1.MsgServer) v1beta1.MsgSe
var _ v1beta1.MsgServer = legacyMsgServer{}

func (k legacyMsgServer) SubmitProposal(goCtx context.Context, msg *v1beta1.MsgSubmitProposal) (*v1beta1.MsgSubmitProposalResponse, error) {
content := msg.GetContent()
if content == nil {
return nil, errors.Wrap(govtypes.ErrInvalidProposalContent, "missing content")
}
if !v1beta1.IsValidProposalType(content.ProposalType()) {
return nil, errors.Wrap(govtypes.ErrInvalidProposalType, content.ProposalType())
}
if err := content.ValidateBasic(); err != nil {
return nil, err
}

contentMsg, err := v1.NewLegacyContent(msg.GetContent(), k.govAcct)
if err != nil {
return nil, fmt.Errorf("error converting legacy content into proposal message: %w", err)
Expand Down Expand Up @@ -312,3 +388,31 @@ func (k legacyMsgServer) Deposit(goCtx context.Context, msg *v1beta1.MsgDeposit)
}
return &v1beta1.MsgDepositResponse{}, nil
}

func validateAmount(amount sdk.Coins) error {
if !amount.IsValid() {
return sdkerrors.ErrInvalidCoins.Wrap(amount.String())
}

if !amount.IsAllPositive() {
return sdkerrors.ErrInvalidCoins.Wrap(amount.String())
}

return nil
}

func validateMsgs(msgs []sdk.Msg) error {
for idx, msg := range msgs {
m, ok := msg.(sdk.HasValidateBasic)
if !ok {
continue
}

if err := m.ValidateBasic(); err != nil {
return errors.Wrap(govtypes.ErrInvalidProposalMsg,
fmt.Sprintf("msg: %d, err: %s", idx, err.Error()))
}
}

return nil
}
Loading