Skip to content

Commit

Permalink
refactor(x/gov): move ValidateBasic to msg server (#15832)
Browse files Browse the repository at this point in the history
Co-authored-by: Marko <[email protected]>
  • Loading branch information
atheeshp and tac0turtle authored Apr 17, 2023
1 parent 64d09e3 commit debf1fa
Show file tree
Hide file tree
Showing 6 changed files with 634 additions and 553 deletions.
142 changes: 129 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 := validateDeposit(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,43 @@ 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 validateDeposit(deposit sdk.Coins) error {
if !deposit.IsValid() {
return errors.Wrap(sdkerrors.ErrInvalidCoins, deposit.String())
}

if deposit.IsAnyNegative() {
return errors.Wrap(sdkerrors.ErrInvalidCoins, deposit.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

0 comments on commit debf1fa

Please sign in to comment.