diff --git a/CHANGELOG.md b/CHANGELOG.md index a08c1aa86e..ec8a5a423f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Improvements + +* (x/group, x/gov) [#17109](https://github.com/cosmos/cosmos-sdk/pull/17109) Let proposal summary be 40x longer than metadata limit. + ## [v0.50.0-beta.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.50.0-beta.0) - 2023-07-19 ### Features diff --git a/client/flags/flags.go b/client/flags/flags.go index a2d918edde..c397b89be8 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -76,6 +76,7 @@ const ( FlagOffset = "offset" FlagCountTotal = "count-total" FlagTimeoutHeight = "timeout-height" + FlagKeyAlgorithm = "algo" FlagKeyType = "key-type" FlagFeePayer = "fee-payer" FlagFeeGranter = "fee-granter" diff --git a/client/keys/add.go b/client/keys/add.go index 4392f90bf2..6d6d08e7da 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -82,7 +82,7 @@ Example: // support old flags name for backwards compatibility f.SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName { - if name == "algo" { + if name == flags.FlagKeyAlgorithm { name = flags.FlagKeyType } diff --git a/simapp/simd/cmd/testnet.go b/simapp/simd/cmd/testnet.go index cd539255b1..fdb0474a06 100644 --- a/simapp/simd/cmd/testnet.go +++ b/simapp/simd/cmd/testnet.go @@ -83,7 +83,7 @@ func addTestnetFlagsToCmd(cmd *cobra.Command) { // support old flags name for backwards compatibility cmd.Flags().SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName { - if name == "algo" { + if name == flags.FlagKeyAlgorithm { name = flags.FlagKeyType } diff --git a/x/gov/README.md b/x/gov/README.md index 683e8bbbac..a508327497 100644 --- a/x/gov/README.md +++ b/x/gov/README.md @@ -1183,6 +1183,10 @@ where `proposal.json` contains: By default the metadata, summary and title are both limited by 255 characters, this can be overridden by the application developer. ::: +:::tip +When metadata is not specified, the title is limited to 255 characters and the summary 40x the title length. +::: + ##### submit-legacy-proposal The `submit-legacy-proposal` command allows users to submit a governance legacy proposal along with an initial deposit. diff --git a/x/gov/keeper/keeper.go b/x/gov/keeper/keeper.go index 3396997124..63ff7c2527 100644 --- a/x/gov/keeper/keeper.go +++ b/x/gov/keeper/keeper.go @@ -183,3 +183,12 @@ func (k Keeper) assertMetadataLength(metadata string) error { } return nil } + +// assertSummaryLength returns an error if given summary length +// is greater than a pre-defined 40*MaxMetadataLen. +func (k Keeper) assertSummaryLength(summary string) error { + if summary != "" && uint64(len(summary)) > 40*k.config.MaxMetadataLen { + return types.ErrSummaryTooLong.Wrapf("got summary with length %d", len(summary)) + } + return nil +} diff --git a/x/gov/keeper/msg_server_test.go b/x/gov/keeper/msg_server_test.go index 8ffb611432..a72aad9070 100644 --- a/x/gov/keeper/msg_server_test.go +++ b/x/gov/keeper/msg_server_test.go @@ -147,6 +147,21 @@ func (suite *KeeperTestSuite) TestSubmitProposalReq() { expErr: true, expErrMsg: "metadata too long", }, + "summary too long": { + preRun: func() (*v1.MsgSubmitProposal, error) { + return v1.NewMsgSubmitProposal( + []sdk.Msg{bankMsg}, + initialDeposit, + proposer.String(), + "", + "Proposal", + strings.Repeat("1", 300*40), + false, + ) + }, + expErr: true, + expErrMsg: "summary too long", + }, "many signers": { preRun: func() (*v1.MsgSubmitProposal, error) { return v1.NewMsgSubmitProposal( diff --git a/x/gov/keeper/proposal.go b/x/gov/keeper/proposal.go index 094b792a19..35080aaea0 100644 --- a/x/gov/keeper/proposal.go +++ b/x/gov/keeper/proposal.go @@ -24,7 +24,7 @@ func (keeper Keeper) SubmitProposal(ctx context.Context, messages []sdk.Msg, met } // assert summary is no longer than predefined max length of metadata - err = keeper.assertMetadataLength(summary) + err = keeper.assertSummaryLength(summary) if err != nil { return v1.Proposal{}, err } diff --git a/x/gov/types/errors.go b/x/gov/types/errors.go index fa584da934..87e9b68546 100644 --- a/x/gov/types/errors.go +++ b/x/gov/types/errors.go @@ -23,4 +23,5 @@ var ( ErrInvalidProposer = errors.Register(ModuleName, 18, "invalid proposer") ErrVotingPeriodEnded = errors.Register(ModuleName, 20, "voting period already ended") ErrInvalidProposal = errors.Register(ModuleName, 21, "invalid proposal") + ErrSummaryTooLong = errors.Register(ModuleName, 22, "summary too long") ) diff --git a/x/group/keeper/msg_server.go b/x/group/keeper/msg_server.go index e27f78be02..048b82a356 100644 --- a/x/group/keeper/msg_server.go +++ b/x/group/keeper/msg_server.go @@ -521,7 +521,7 @@ func (k Keeper) SubmitProposal(goCtx context.Context, msg *group.MsgSubmitPropos return nil, err } - if err := k.assertMetadataLength(msg.Summary, "proposal summary"); err != nil { + if err := k.assertSummaryLength(msg.Summary); err != nil { return nil, err } @@ -1062,6 +1062,15 @@ func (k Keeper) assertMetadataLength(metadata, description string) error { return nil } +// assertSummaryLength returns an error if given summary length +// is greater than a pre-defined 40*MaxMetadataLen. +func (k Keeper) assertSummaryLength(summary string) error { + if summary != "" && uint64(len(summary)) > 40*k.config.MaxMetadataLen { + return errorsmod.Wrapf(errors.ErrMaxLimit, "proposal summary is too long") + } + return nil +} + // validateDecisionPolicies loops through all decision policies from the group, // and calls each of their Validate() method. func (k Keeper) validateDecisionPolicies(ctx sdk.Context, g group.GroupInfo) error { diff --git a/x/group/keeper/msg_server_test.go b/x/group/keeper/msg_server_test.go index c0f2462661..493b8167e8 100644 --- a/x/group/keeper/msg_server_test.go +++ b/x/group/keeper/msg_server_test.go @@ -1742,6 +1742,17 @@ func (s *TestSuite) TestSubmitProposal() { expErrMsg: "limit exceeded", postRun: func(sdkCtx sdk.Context) {}, }, + "summary too long": { + req: &group.MsgSubmitProposal{ + GroupPolicyAddress: accountAddr.String(), + Proposers: []string{addr2.String()}, + Metadata: "{\"title\":\"title\",\"summary\":\"description\"}", + Summary: strings.Repeat("a", 256*40), + }, + expErr: true, + expErrMsg: "limit exceeded", + postRun: func(sdkCtx sdk.Context) {}, + }, "group policy required": { req: &group.MsgSubmitProposal{ Proposers: []string{addr2.String()}, diff --git a/x/staking/keeper/msg_server.go b/x/staking/keeper/msg_server.go index 22321a4095..ae385b7cf7 100644 --- a/x/staking/keeper/msg_server.go +++ b/x/staking/keeper/msg_server.go @@ -178,6 +178,15 @@ func (k msgServer) EditValidator(ctx context.Context, msg *types.MsgEditValidato if msg.CommissionRate.GT(math.LegacyOneDec()) || msg.CommissionRate.IsNegative() { return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "commission rate must be between 0 and 1 (inclusive)") } + + minCommissionRate, err := k.MinCommissionRate(ctx) + if err != nil { + return nil, errorsmod.Wrap(sdkerrors.ErrLogic, err.Error()) + } + + if msg.CommissionRate.LT(minCommissionRate) { + return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "commission rate cannot be less than the min commission rate %s", minCommissionRate.String()) + } } // validator must already be registered