From 44934e3b68133ada71117a4dadbe9fafce9b6599 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Wed, 11 Oct 2023 08:10:10 +0200 Subject: [PATCH] feat(x/distribution): add autocli options for tx (#17963) --- CHANGELOG.md | 2 + tests/e2e/bank/suite.go | 3 +- tests/e2e/distribution/cli_test.go | 8 +- tests/e2e/distribution/suite.go | 330 ----------------- tests/e2e/distribution/withdraw_all_suite.go | 5 +- x/bank/client/cli/tx.go | 9 +- x/bank/client/cli/tx_test.go | 2 +- x/bank/module.go | 6 +- x/distribution/autocli.go | 75 +++- x/distribution/client/cli/tx.go | 206 ++--------- x/distribution/client/cli/tx_test.go | 125 +------ x/distribution/client/cli/util_test.go | 59 --- x/distribution/keeper/grpc_query_test.go | 179 ++++++++++ x/distribution/keeper/keeper_test.go | 93 ++--- x/distribution/keeper/msg_server.go | 5 +- x/distribution/keeper/msg_server_test.go | 358 +++++++++++++++++++ x/distribution/module.go | 6 +- x/protocolpool/autocli.go | 2 +- x/staking/client/cli/tx.go | 18 +- x/staking/client/cli/tx_test.go | 4 +- x/staking/module.go | 5 +- 21 files changed, 684 insertions(+), 816 deletions(-) delete mode 100644 tests/e2e/distribution/suite.go delete mode 100644 x/distribution/client/cli/util_test.go create mode 100644 x/distribution/keeper/grpc_query_test.go create mode 100644 x/distribution/keeper/msg_server_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 38fb0bb52264..a1eabfb22895 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -164,6 +164,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### CLI Breaking Changes +* (x/distribution) [#17963](https://github.com/cosmos/cosmos-sdk/pull/17963) `appd tx distribution withdraw-rewards` now only withdraws rewards for the delegator's own delegations. For withdrawing validators commission, use `appd tx distribution withdraw-validator-commission`. + ### State Machine Breaking * (x/distribution) [#17657](https://github.com/cosmos/cosmos-sdk/pull/17657) Migrate community pool funds from x/distribution to x/protocolpool. diff --git a/tests/e2e/bank/suite.go b/tests/e2e/bank/suite.go index 0cb3d837fe24..635c512251ac 100644 --- a/tests/e2e/bank/suite.go +++ b/tests/e2e/bank/suite.go @@ -10,7 +10,6 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" - addresscodec "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/testutil" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" "github.com/cosmos/cosmos-sdk/testutil/network" @@ -387,5 +386,5 @@ func MsgMultiSendExec(clientCtx client.Context, from sdk.AccAddress, to []sdk.Ac args = append(args, amount.String()) args = append(args, extraArgs...) - return clitestutil.ExecTestCLICmd(clientCtx, cli.NewMultiSendTxCmd(addresscodec.NewBech32Codec("cosmos")), args) + return clitestutil.ExecTestCLICmd(clientCtx, cli.NewMultiSendTxCmd(), args) } diff --git a/tests/e2e/distribution/cli_test.go b/tests/e2e/distribution/cli_test.go index 34d8cb0e0591..ad8e877d9611 100644 --- a/tests/e2e/distribution/cli_test.go +++ b/tests/e2e/distribution/cli_test.go @@ -9,14 +9,10 @@ import ( "github.com/stretchr/testify/suite" ) -func TestE2ETestSuite(t *testing.T) { - suite.Run(t, new(E2ETestSuite)) +func TestWithdrawAllSuite(t *testing.T) { + suite.Run(t, new(WithdrawAllTestSuite)) } func TestGRPCQueryTestSuite(t *testing.T) { suite.Run(t, new(GRPCQueryTestSuite)) } - -func TestWithdrawAllSuite(t *testing.T) { - suite.Run(t, new(WithdrawAllTestSuite)) -} diff --git a/tests/e2e/distribution/suite.go b/tests/e2e/distribution/suite.go deleted file mode 100644 index a133c0fc6672..000000000000 --- a/tests/e2e/distribution/suite.go +++ /dev/null @@ -1,330 +0,0 @@ -package distribution - -import ( - "context" - "encoding/hex" - "fmt" - "time" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/math" - "cosmossdk.io/simapp" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/codec/address" - svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - "github.com/cosmos/cosmos-sdk/testutil/network" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/distribution/client/cli" - distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" -) - -type E2ETestSuite struct { - suite.Suite - - cfg network.Config - network *network.Network -} - -func NewE2ETestSuite(cfg network.Config) *E2ETestSuite { - return &E2ETestSuite{cfg: cfg} -} - -// SetupSuite creates a new network for _each_ e2e test. We create a new -// network for each test because there are some state modifications that are -// needed to be made in order to make useful queries. However, we don't want -// these state changes to be present in other tests. -func (s *E2ETestSuite) SetupSuite() { - s.T().Log("setting up e2e test suite") - - cfg := network.DefaultConfig(simapp.NewTestNetworkFixture) - cfg.NumValidators = 1 - s.cfg = cfg - - genesisState := s.cfg.GenesisState - var mintData minttypes.GenesisState - s.Require().NoError(s.cfg.Codec.UnmarshalJSON(genesisState[minttypes.ModuleName], &mintData)) - - inflation := math.LegacyMustNewDecFromStr("1.0") - mintData.Minter.Inflation = inflation - mintData.Params.InflationMin = inflation - mintData.Params.InflationMax = inflation - - mintDataBz, err := s.cfg.Codec.MarshalJSON(&mintData) - s.Require().NoError(err) - genesisState[minttypes.ModuleName] = mintDataBz - s.cfg.GenesisState = genesisState - - s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) - s.Require().NoError(err) - - s.Require().NoError(s.network.WaitForNextBlock()) -} - -// TearDownSuite cleans up the curret test network after _each_ test. -func (s *E2ETestSuite) TearDownSuite() { - s.T().Log("tearing down e2e test suite1") - s.network.Cleanup() -} - -func (s *E2ETestSuite) TestNewWithdrawRewardsCmd() { - val := s.network.Validators[0] - - testCases := []struct { - name string - valAddr fmt.Stringer - args []string - expectErr bool - expectedCode uint32 - respType proto.Message - expectedResponseType []string - }{ - { - "invalid validator address", - val.Address, - []string{ - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - true, 0, nil, - []string{}, - }, - { - "valid transaction", - sdk.ValAddress(val.Address), - []string{ - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, &sdk.TxResponse{}, - []string{ - "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse", - }, - }, - { - "valid transaction (with commission)", - sdk.ValAddress(val.Address), - []string{ - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=true", cli.FlagCommission), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, &sdk.TxResponse{}, - []string{ - "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse", - "/cosmos.distribution.v1beta1.MsgWithdrawValidatorCommissionResponse", - }, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - clientCtx := val.ClientCtx - - args := append([]string{tc.valAddr.String()}, tc.args...) - - _, _ = s.network.WaitForHeightWithTimeout(10, time.Minute) - - ctx := svrcmd.CreateExecuteContext(context.Background()) - cmd := cli.NewWithdrawRewardsCmd(address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - cmd.SetContext(ctx) - cmd.SetArgs(args) - s.Require().NoError(client.SetCmdClientContextHandler(clientCtx, cmd)) - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - s.Require().NoError(s.network.WaitForNextBlock()) - - txResp, err := clitestutil.GetTxResponse(s.network, clientCtx, tc.respType.(*sdk.TxResponse).TxHash) - s.Require().NoError(err) - s.Require().Equal(tc.expectedCode, txResp.Code) - - data, err := hex.DecodeString(txResp.Data) - s.Require().NoError(err) - - txMsgData := sdk.TxMsgData{} - err = s.cfg.Codec.Unmarshal(data, &txMsgData) - s.Require().NoError(err) - for responseIdx, msgResponse := range txMsgData.MsgResponses { - s.Require().Equal(tc.expectedResponseType[responseIdx], msgResponse.TypeUrl) - switch msgResponse.TypeUrl { - case "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse": - var resp distrtypes.MsgWithdrawDelegatorRewardResponse - // can't use unpackAny as response types are not registered. - err = s.cfg.Codec.Unmarshal(msgResponse.Value, &resp) - s.Require().NoError(err) - s.Require().True(resp.Amount.IsAllGT(sdk.NewCoins(sdk.NewCoin("stake", math.OneInt()))), - fmt.Sprintf("expected a positive coin value, got %v", resp.Amount)) - case "/cosmos.distribution.v1beta1.MsgWithdrawValidatorCommissionResponse": - var resp distrtypes.MsgWithdrawValidatorCommissionResponse - // can't use unpackAny as response types are not registered. - err = s.cfg.Codec.Unmarshal(msgResponse.Value, &resp) - s.Require().NoError(err) - s.Require().True(resp.Amount.IsAllGT(sdk.NewCoins(sdk.NewCoin("stake", math.OneInt()))), - fmt.Sprintf("expected a positive coin value, got %v", resp.Amount)) - } - } - } - }) - } -} - -func (s *E2ETestSuite) TestNewWithdrawAllRewardsCmd() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - expectedCode uint32 - respType proto.Message - expectedResponseType []string - }{ - { - "valid transaction (offline)", - []string{ - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), - fmt.Sprintf("--%s=true", flags.FlagOffline), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - true, 0, nil, - []string{}, - }, - { - "valid transaction", - []string{ - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, &sdk.TxResponse{}, - []string{ - "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse", - }, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewWithdrawAllRewardsCmd(address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - clientCtx := val.ClientCtx - - _, _ = s.network.WaitForHeightWithTimeout(10, time.Minute) - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - s.Require().NoError(s.network.WaitForNextBlock()) - - txResp, err := clitestutil.GetTxResponse(s.network, clientCtx, tc.respType.(*sdk.TxResponse).TxHash) - s.Require().NoError(err) - s.Require().Equal(tc.expectedCode, txResp.Code) - - data, err := hex.DecodeString(txResp.Data) - s.Require().NoError(err) - - txMsgData := sdk.TxMsgData{} - err = s.cfg.Codec.Unmarshal(data, &txMsgData) - s.Require().NoError(err) - for responseIdx, msgResponse := range txMsgData.MsgResponses { - s.Require().Equal(tc.expectedResponseType[responseIdx], msgResponse.TypeUrl) - switch msgResponse.TypeUrl { - case "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse": - var resp distrtypes.MsgWithdrawDelegatorRewardResponse - // can't use unpackAny as response types are not registered. - err = s.cfg.Codec.Unmarshal(msgResponse.Value, &resp) - s.Require().NoError(err) - s.Require().True(resp.Amount.IsAllGT(sdk.NewCoins(sdk.NewCoin("stake", math.OneInt()))), - fmt.Sprintf("expected a positive coin value, got %v", resp.Amount)) - case "/cosmos.distribution.v1beta1.MsgWithdrawValidatorCommissionResponse": - var resp distrtypes.MsgWithdrawValidatorCommissionResponse - // can't use unpackAny as response types are not registered. - err = s.cfg.Codec.Unmarshal(msgResponse.Value, &resp) - s.Require().NoError(err) - s.Require().True(resp.Amount.IsAllGT(sdk.NewCoins(sdk.NewCoin("stake", math.OneInt()))), - fmt.Sprintf("expected a positive coin value, got %v", resp.Amount)) - } - } - } - }) - } -} - -func (s *E2ETestSuite) TestNewSetWithdrawAddrCmd() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - expectedCode uint32 - respType proto.Message - }{ - { - "invalid withdraw address", - []string{ - "foo", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - true, 0, nil, - }, - { - "valid transaction", - []string{ - val.Address.String(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, &sdk.TxResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewSetWithdrawAddrCmd(address.NewBech32Codec("cosmos")) - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - - txResp := tc.respType.(*sdk.TxResponse) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, txResp.TxHash, tc.expectedCode)) - } - }) - } -} diff --git a/tests/e2e/distribution/withdraw_all_suite.go b/tests/e2e/distribution/withdraw_all_suite.go index 300b54f18559..17caf9ba88b1 100644 --- a/tests/e2e/distribution/withdraw_all_suite.go +++ b/tests/e2e/distribution/withdraw_all_suite.go @@ -10,7 +10,6 @@ import ( "cosmossdk.io/simapp" "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" @@ -109,7 +108,7 @@ func (s *WithdrawAllTestSuite) TestNewWithdrawAllRewardsGenerateOnly() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), } - cmd := cli.NewWithdrawAllRewardsCmd(address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) + cmd := cli.NewWithdrawAllRewardsCmd() out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args) if err != nil { return err @@ -132,7 +131,7 @@ func (s *WithdrawAllTestSuite) TestNewWithdrawAllRewardsGenerateOnly() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), } - cmd := cli.NewWithdrawAllRewardsCmd(address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) + cmd := cli.NewWithdrawAllRewardsCmd() out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args) require.NoError(err) // expect 1 transaction in the generated file when --max-msgs in a tx set 2, since there are only delegations. diff --git a/x/bank/client/cli/tx.go b/x/bank/client/cli/tx.go index d45db2b248f1..f39ef8398810 100644 --- a/x/bank/client/cli/tx.go +++ b/x/bank/client/cli/tx.go @@ -5,7 +5,6 @@ import ( "github.com/spf13/cobra" - "cosmossdk.io/core/address" sdkmath "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/client" @@ -19,7 +18,7 @@ import ( var FlagSplit = "split" // NewTxCmd returns a root CLI command handler for all x/bank transaction commands. -func NewTxCmd(ac address.Codec) *cobra.Command { +func NewTxCmd() *cobra.Command { txCmd := &cobra.Command{ Use: types.ModuleName, Short: "Bank transaction subcommands", @@ -29,7 +28,7 @@ func NewTxCmd(ac address.Codec) *cobra.Command { } txCmd.AddCommand( - NewMultiSendTxCmd(ac), + NewMultiSendTxCmd(), ) return txCmd @@ -37,7 +36,7 @@ func NewTxCmd(ac address.Codec) *cobra.Command { // NewMultiSendTxCmd returns a CLI command handler for creating a MsgMultiSend transaction. // For a better UX this command is limited to send funds from one account to two or more accounts. -func NewMultiSendTxCmd(ac address.Codec) *cobra.Command { +func NewMultiSendTxCmd() *cobra.Command { cmd := &cobra.Command{ Use: "multi-send [from_key_or_address] [to_address_1 to_address_2 ...] [amount]", Short: "Send funds from one account to two or more accounts.", @@ -82,7 +81,7 @@ When using '--dry-run' a key name cannot be used, only a bech32 address.`, var output []types.Output for _, arg := range args[1 : len(args)-1] { - toAddr, err := ac.StringToBytes(arg) + toAddr, err := clientCtx.AddressCodec.StringToBytes(arg) if err != nil { return err } diff --git a/x/bank/client/cli/tx_test.go b/x/bank/client/cli/tx_test.go index e3f4e418ea01..e3b6378c535c 100644 --- a/x/bank/client/cli/tx_test.go +++ b/x/bank/client/cli/tx_test.go @@ -54,7 +54,7 @@ func (s *CLITestSuite) SetupSuite() { func (s *CLITestSuite) TestMultiSendTxCmd() { accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 3) - cmd := cli.NewMultiSendTxCmd(addresscodec.NewBech32Codec("cosmos")) + cmd := cli.NewMultiSendTxCmd() cmd.SetOutput(io.Discard) extraArgs := []string{ diff --git a/x/bank/module.go b/x/bank/module.go index 071897763279..e65b04dfd93b 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -10,7 +10,6 @@ import ( "github.com/spf13/cobra" modulev1 "cosmossdk.io/api/cosmos/bank/module/v1" - "cosmossdk.io/core/address" "cosmossdk.io/core/appmodule" corestore "cosmossdk.io/core/store" "cosmossdk.io/depinject" @@ -46,7 +45,6 @@ var ( // AppModuleBasic defines the basic application module used by the bank module. type AppModuleBasic struct { cdc codec.Codec - ac address.Codec } // Name returns the bank module's name. @@ -82,7 +80,7 @@ func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *g // GetTxCmd returns the root tx command for the bank module. func (ab AppModuleBasic) GetTxCmd() *cobra.Command { - return cli.NewTxCmd(ab.ac) + return cli.NewTxCmd() } // RegisterInterfaces registers interfaces and implementations of the bank module. @@ -127,7 +125,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { // NewAppModule creates a new AppModule object func NewAppModule(cdc codec.Codec, keeper keeper.Keeper, accountKeeper types.AccountKeeper) AppModule { return AppModule{ - AppModuleBasic: AppModuleBasic{cdc: cdc, ac: accountKeeper.AddressCodec()}, + AppModuleBasic: AppModuleBasic{cdc: cdc}, keeper: keeper, accountKeeper: accountKeeper, } diff --git a/x/distribution/autocli.go b/x/distribution/autocli.go index 8df238c8c203..8984a58fdf01 100644 --- a/x/distribution/autocli.go +++ b/x/distribution/autocli.go @@ -2,7 +2,6 @@ package distribution import ( "fmt" - "strings" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" distirbuitonv1beta1 "cosmossdk.io/api/cosmos/distribution/v1beta1" @@ -17,11 +16,6 @@ var ( // AutoCLIOptions implements the autocli.HasAutoCLIConfig interface. func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { - exAccAddress, err := am.ac.BytesToString([]byte("A58856F0FD53BF058B4909A21AEC019107BA6A58856F0FD53BF058B4909A21AEC019107BA6")) - if err != nil { - panic(err) - } - return &autocliv1.ModuleOptions{ Query: &autocliv1.ServiceCommandDescriptor{ Service: distirbuitonv1beta1.Query_ServiceDesc.ServiceName, @@ -35,9 +29,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { RpcMethod: "ValidatorDistributionInfo", Use: "validator-distribution-info [validator]", Short: "Query validator distribution info", - Example: fmt.Sprintf(`Example: $ %s query distribution validator-distribution-info %s`, - version.AppName, exAccAddress, - ), + Example: fmt.Sprintf(`Example: $ %s query distribution validator-distribution-info [validator-address]`, version.AppName), PositionalArgs: []*autocliv1.PositionalArgDescriptor{ {ProtoField: "validator_address"}, @@ -77,14 +69,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { Use: "rewards [delegator-addr] [validator-addr]", Short: "Query all distribution delegator rewards or rewards from a particular validator", Long: "Query all rewards earned by a delegator, optionally restrict to rewards from a single validator.", - Example: strings.TrimSpace( - fmt.Sprintf(` -$ %s query distribution rewards %s -$ %s query distribution rewards %s [validator-address] -`, - version.AppName, exAccAddress, version.AppName, exAccAddress, - ), - ), + Example: fmt.Sprintf("$ %s query distribution rewards [delegator-address] [validator-address]", version.AppName), PositionalArgs: []*autocliv1.PositionalArgDescriptor{ {ProtoField: "delegator_address"}, {ProtoField: "validator_address"}, @@ -100,6 +85,62 @@ $ %s query distribution rewards %s [validator-address] }, Tx: &autocliv1.ServiceCommandDescriptor{ Service: distirbuitonv1beta1.Msg_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "SetWithdrawAddress", + Use: "set-withdraw-addr [withdraw-addr]", + Short: "Change the default withdraw address for rewards associated with an address", + Example: fmt.Sprintf("%s tx distribution set-withdraw-addr cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p --from mykey", version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "withdraw_address"}, + }, + }, + { + RpcMethod: "WithdrawDelegatorReward", + Use: "withdraw-rewards [validator-addr]", + Short: "Withdraw rewards from a given delegation address", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "validator_address"}, + }, + }, + { + RpcMethod: "WithdrawValidatorCommission", + Use: "withdraw-validator-commission [validator-addr]", + Short: "Withdraw commissions from a validator address (must be a validator operator)", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "validator_address"}, + }, + }, + { + RpcMethod: "DepositValidatorRewardsPool", + Use: "fund-validator-rewards-pool [validator-addr] [amount]", + Short: "Fund the validator rewards pool with the specified amount", + Example: fmt.Sprintf("%s tx distribution fund-validator-rewards-pool cosmosvaloper1x20lytyf6zkcrv5edpkfkn8sz578qg5sqfyqnp 100uatom --from mykey", version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "validator_address"}, + {ProtoField: "amount", Varargs: true}, + }, + }, + { + RpcMethod: "FundCommunityPool", + Deprecated: fmt.Sprintf("Use %s tx protocolpool fund-community-pool", version.AppName), + Use: "fund-community-pool [amount]", + Short: "Funds the community pool with the specified amount", + Example: fmt.Sprintf(`$ %s tx distribution fund-community-pool 100uatom --from mykey`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "amount", Varargs: true}, + }, + }, + { + RpcMethod: "UpdateParams", + Skip: true, // skipped because authority gated + }, + { + RpcMethod: "CommunityPoolSpend", + Skip: true, // skipped because authority gated + }, + }, + EnhanceCustomCommand: true, }, } } diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index 80c137dd24ab..b9fac8b60daa 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -2,12 +2,8 @@ package cli import ( "fmt" - "strings" "github.com/spf13/cobra" - "github.com/spf13/pflag" - - "cosmossdk.io/core/address" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" @@ -28,7 +24,7 @@ const ( ) // NewTxCmd returns a root CLI command handler for all x/distribution transaction commands. -func NewTxCmd(valAc, ac address.Codec) *cobra.Command { +func NewTxCmd() *cobra.Command { distTxCmd := &cobra.Command{ Use: types.ModuleName, Short: "Distribution transactions subcommands", @@ -38,115 +34,26 @@ func NewTxCmd(valAc, ac address.Codec) *cobra.Command { } distTxCmd.AddCommand( - NewWithdrawRewardsCmd(valAc, ac), - NewWithdrawAllRewardsCmd(valAc, ac), - NewSetWithdrawAddrCmd(ac), - NewDepositValidatorRewardsPoolCmd(valAc, ac), + NewWithdrawAllRewardsCmd(), ) return distTxCmd } -type newGenerateOrBroadcastFunc func(client.Context, *pflag.FlagSet, ...sdk.Msg) error - -func newSplitAndApply( - genOrBroadcastFn newGenerateOrBroadcastFunc, clientCtx client.Context, - fs *pflag.FlagSet, msgs []sdk.Msg, chunkSize int, -) error { - if chunkSize == 0 { - return genOrBroadcastFn(clientCtx, fs, msgs...) - } - - // split messages into slices of length chunkSize - totalMessages := len(msgs) - for i := 0; i < len(msgs); i += chunkSize { - - sliceEnd := i + chunkSize - if sliceEnd > totalMessages { - sliceEnd = totalMessages - } - - msgChunk := msgs[i:sliceEnd] - if err := genOrBroadcastFn(clientCtx, fs, msgChunk...); err != nil { - return err - } - } - - return nil -} - -// NewWithdrawRewardsCmd returns a CLI command handler for creating a MsgWithdrawDelegatorReward transaction. -func NewWithdrawRewardsCmd(valCodec, ac address.Codec) *cobra.Command { - bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() - - cmd := &cobra.Command{ - Use: "withdraw-rewards [validator-addr]", - Short: "Withdraw rewards from a given delegation address, and optionally withdraw validator commission if the delegation address given is a validator operator", - Long: strings.TrimSpace( - fmt.Sprintf(`Withdraw rewards from a given delegation address, -and optionally withdraw validator commission if the delegation address given is a validator operator. - -Example: -$ %s tx distribution withdraw-rewards %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj --from mykey -$ %s tx distribution withdraw-rewards %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj --from mykey --commission -`, - version.AppName, bech32PrefixValAddr, version.AppName, bech32PrefixValAddr, - ), - ), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - delAddr, err := ac.BytesToString(clientCtx.GetFromAddress()) - if err != nil { - return err - } - - _, err = valCodec.StringToBytes(args[0]) - if err != nil { - return err - } - - msgs := []sdk.Msg{types.NewMsgWithdrawDelegatorReward(delAddr, args[0])} - - if commission, _ := cmd.Flags().GetBool(FlagCommission); commission { - msgs = append(msgs, types.NewMsgWithdrawValidatorCommission(args[0])) - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msgs...) - }, - } - - cmd.Flags().Bool(FlagCommission, false, "Withdraw the validator's commission in addition to the rewards") - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - // NewWithdrawAllRewardsCmd returns a CLI command handler for creating a MsgWithdrawDelegatorReward transaction. -func NewWithdrawAllRewardsCmd(valCodec, ac address.Codec) *cobra.Command { +// This command is more powerful than AutoCLI generated command as it allows sending batch of messages. +func NewWithdrawAllRewardsCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "withdraw-all-rewards", - Short: "withdraw all delegations rewards for a delegator", - Long: strings.TrimSpace( - fmt.Sprintf(`Withdraw all rewards for a single delegator. -Note that if you use this command with --%[2]s=%[3]s or --%[2]s=%[4]s, the %[5]s flag will automatically be set to 0. - -Example: -$ %[1]s tx distribution withdraw-all-rewards --from mykey -`, - version.AppName, flags.FlagBroadcastMode, flags.BroadcastSync, flags.BroadcastAsync, FlagMaxMessagesPerTx, - ), - ), - Args: cobra.NoArgs, + Use: "withdraw-all-rewards", + Short: "Withdraw all delegations rewards for a delegator", + Example: fmt.Sprintf("%s tx distribution withdraw-all-rewards --from mykey", version.AppName), + Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err } - delAddr, err := ac.BytesToString(clientCtx.GetFromAddress()) + delAddr, err := clientCtx.AddressCodec.BytesToString(clientCtx.GetFromAddress()) if err != nil { return err } @@ -167,7 +74,7 @@ $ %[1]s tx distribution withdraw-all-rewards --from mykey // build multi-message transaction msgs := make([]sdk.Msg, 0, len(validators)) for _, valAddr := range validators { - _, err := valCodec.StringToBytes(valAddr) + _, err := clientCtx.ValidatorAddressCodec.StringToBytes(valAddr) if err != nil { return err } @@ -177,93 +84,30 @@ $ %[1]s tx distribution withdraw-all-rewards --from mykey } chunkSize, _ := cmd.Flags().GetInt(FlagMaxMessagesPerTx) - - return newSplitAndApply(tx.GenerateOrBroadcastTxCLI, clientCtx, cmd.Flags(), msgs, chunkSize) - }, - } - - cmd.Flags().Int(FlagMaxMessagesPerTx, MaxMessagesPerTxDefault, "Limit the number of messages per tx (0 for unlimited)") - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewSetWithdrawAddrCmd returns a CLI command handler for creating a MsgSetWithdrawAddress transaction. -func NewSetWithdrawAddrCmd(ac address.Codec) *cobra.Command { - bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() - - cmd := &cobra.Command{ - Use: "set-withdraw-addr [withdraw-addr]", - Short: "change the default withdraw address for rewards associated with an address", - Long: strings.TrimSpace( - fmt.Sprintf(`Set the withdraw address for rewards associated with a delegator address. - -Example: -$ %s tx distribution set-withdraw-addr %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p --from mykey -`, - version.AppName, bech32PrefixAccAddr, - ), - ), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err + if chunkSize == 0 { + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msgs...) } - delAddr := clientCtx.GetFromAddress() - withdrawAddr, err := ac.StringToBytes(args[0]) - if err != nil { - return err - } - - msg := types.NewMsgSetWithdrawAddress(delAddr, withdrawAddr) - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - flags.AddTxFlagsToCmd(cmd) + // split messages into slices of length chunkSize + totalMessages := len(msgs) + for i := 0; i < len(msgs); i += chunkSize { - return cmd -} - -// NewDepositValidatorRewardsPoolCmd returns a CLI command handler for creating -// a MsgDepositValidatorRewardsPool transaction. -func NewDepositValidatorRewardsPoolCmd(valCodec, ac address.Codec) *cobra.Command { - cmd := &cobra.Command{ - Use: "fund-validator-rewards-pool [val_addr] [amount]", - Args: cobra.ExactArgs(2), - Short: "Fund the validator rewards pool with the specified amount", - Example: fmt.Sprintf( - "%s tx distribution fund-validator-rewards-pool cosmosvaloper1x20lytyf6zkcrv5edpkfkn8sz578qg5sqfyqnp 100uatom --from mykey", - version.AppName, - ), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - - depositorAddr, err := ac.BytesToString(clientCtx.GetFromAddress()) - if err != nil { - return err - } - - _, err = valCodec.StringToBytes(args[0]) - if err != nil { - return err - } + sliceEnd := i + chunkSize + if sliceEnd > totalMessages { + sliceEnd = totalMessages + } - amount, err := sdk.ParseCoinsNormalized(args[1]) - if err != nil { - return err + msgChunk := msgs[i:sliceEnd] + if err := tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msgChunk...); err != nil { + return err + } } - msg := types.NewMsgDepositValidatorRewardsPool(depositorAddr, args[0], amount) - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return nil }, } + cmd.Flags().Int(FlagMaxMessagesPerTx, MaxMessagesPerTxDefault, "Limit the number of messages per tx (0 for unlimited)") flags.AddTxFlagsToCmd(cmd) return cmd diff --git a/x/distribution/client/cli/tx_test.go b/x/distribution/client/cli/tx_test.go index c0b7071700ae..2a4c1b331b66 100644 --- a/x/distribution/client/cli/tx_test.go +++ b/x/distribution/client/cli/tx_test.go @@ -1,14 +1,12 @@ package cli_test import ( - "context" "fmt" "io" "testing" abci "github.com/cometbft/cometbft/abci/types" rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock" - "github.com/cosmos/gogoproto/proto" "github.com/stretchr/testify/suite" sdkmath "cosmossdk.io/math" @@ -17,7 +15,6 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" addresscodec "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/crypto/keyring" - svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" "github.com/cosmos/cosmos-sdk/testutil" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" "github.com/cosmos/cosmos-sdk/testutil/network" @@ -84,76 +81,6 @@ func (s *CLITestSuite) SetupSuite() { cfg.GenesisState = genesisState } -func (s *CLITestSuite) TestTxWithdrawRewardsCmd() { - val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) - - testCases := []struct { - name string - valAddr fmt.Stringer - args []string - expectErrMsg string - }{ - { - "invalid validator address", - val[0].Address, - []string{ - fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), - }, - "hrp does not match bech32 prefix", - }, - { - "valid transaction", - sdk.ValAddress(val[0].Address), - []string{ - fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), - }, - "", - }, - { - "valid transaction (with commission)", - sdk.ValAddress(val[0].Address), - []string{ - fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=true", cli.FlagCommission), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), - }, - "", - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - args := append([]string{tc.valAddr.String()}, tc.args...) - - ctx := svrcmd.CreateExecuteContext(context.Background()) - cmd := cli.NewWithdrawRewardsCmd(addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos")) - cmd.SetContext(ctx) - cmd.SetArgs(args) - s.Require().NoError(client.SetCmdClientContextHandler(s.clientCtx, cmd)) - - out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, args) - if tc.expectErrMsg != "" { - s.Require().Error(err) - s.Require().Contains(err.Error(), tc.expectErrMsg) - } else { - s.Require().NoError(err) - msg := &sdk.TxResponse{} - s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) - } - }) - } -} - func (s *CLITestSuite) TestTxWithdrawAllRewardsCmd() { val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) @@ -188,7 +115,7 @@ func (s *CLITestSuite) TestTxWithdrawAllRewardsCmd() { tc := tc s.Run(tc.name, func() { - cmd := cli.NewWithdrawAllRewardsCmd(addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos")) + cmd := cli.NewWithdrawAllRewardsCmd() out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) if tc.expectErrMsg != "" { @@ -202,53 +129,3 @@ func (s *CLITestSuite) TestTxWithdrawAllRewardsCmd() { }) } } - -func (s *CLITestSuite) TestTxSetWithdrawAddrCmd() { - val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - }{ - { - "invalid withdraw address", - []string{ - "foo", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), - }, - true, nil, - }, - { - "valid transaction", - []string{ - val[0].Address.String(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), - }, - false, &sdk.TxResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewSetWithdrawAddrCmd(addresscodec.NewBech32Codec("cosmos")) - - out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) - } -} diff --git a/x/distribution/client/cli/util_test.go b/x/distribution/client/cli/util_test.go deleted file mode 100644 index 0c1ea11ff5f7..000000000000 --- a/x/distribution/client/cli/util_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package cli - -import ( - "testing" - - "github.com/spf13/pflag" - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/cosmos-sdk/testutil/testdata" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func Test_splitAndCall_NoMessages(t *testing.T) { - clientCtx := client.Context{} - - err := newSplitAndApply(nil, clientCtx, nil, nil, 10) - require.NoError(t, err, "") -} - -func Test_splitAndCall_Splitting(t *testing.T) { - clientCtx := client.Context{} - - addr := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()) - - // Add five messages - msgs := []sdk.Msg{ - testdata.NewTestMsg(addr), - testdata.NewTestMsg(addr), - testdata.NewTestMsg(addr), - testdata.NewTestMsg(addr), - testdata.NewTestMsg(addr), - } - - // Keep track of number of calls - const chunkSize = 2 - - callCount := 0 - err := newSplitAndApply( - func(clientCtx client.Context, fs *pflag.FlagSet, msgs ...sdk.Msg) error { - callCount++ - - require.NotNil(t, clientCtx) - require.NotNil(t, msgs) - - if callCount < 3 { - require.Equal(t, len(msgs), 2) - } else { - require.Equal(t, len(msgs), 1) - } - - return nil - }, - clientCtx, nil, msgs, chunkSize) - - require.NoError(t, err, "") - require.Equal(t, 3, callCount) -} diff --git a/x/distribution/keeper/grpc_query_test.go b/x/distribution/keeper/grpc_query_test.go new file mode 100644 index 000000000000..b4860ba114b6 --- /dev/null +++ b/x/distribution/keeper/grpc_query_test.go @@ -0,0 +1,179 @@ +package keeper_test + +import ( + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + distrtestutil "github.com/cosmos/cosmos-sdk/x/distribution/testutil" + "github.com/cosmos/cosmos-sdk/x/distribution/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +func TestQueryParams(t *testing.T) { + ctx, _, distrKeeper, _ := initFixture(t) + queryServer := keeper.NewQuerier(distrKeeper) + + cases := []struct { + name string + req *types.QueryParamsRequest + resp *types.QueryParamsResponse + errMsg string + }{ + { + name: "success", + req: &types.QueryParamsRequest{}, + resp: &types.QueryParamsResponse{ + Params: types.DefaultParams(), + }, + errMsg: "", + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + out, err := queryServer.Params(ctx, tc.req) + if tc.errMsg == "" { + require.NoError(t, err) + require.Equal(t, tc.resp, out) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + require.Nil(t, out) + } + }) + } +} + +func TestQueryValidatorDistributionInfo(t *testing.T) { + ctx, addrs, distrKeeper, dep := initFixture(t) + queryServer := keeper.NewQuerier(distrKeeper) + + val, err := distrtestutil.CreateValidator(valConsPk0, math.NewInt(100)) + require.NoError(t, err) + + del := stakingtypes.NewDelegation(addrs[0].String(), val.OperatorAddress, val.DelegatorShares) + + dep.stakingKeeper.EXPECT().Validator(gomock.Any(), gomock.Any()).Return(val, nil).AnyTimes() + dep.stakingKeeper.EXPECT().Delegation(gomock.Any(), gomock.Any(), gomock.Any()).Return(del, nil).AnyTimes() + + cases := []struct { + name string + req *types.QueryValidatorDistributionInfoRequest + resp *types.QueryValidatorDistributionInfoResponse + errMsg string + }{ + { + name: "invalid validator address", + req: &types.QueryValidatorDistributionInfoRequest{ + ValidatorAddress: "invalid address", + }, + resp: &types.QueryValidatorDistributionInfoResponse{}, + errMsg: "decoding bech32 failed", + }, + { + name: "not a validator", + req: &types.QueryValidatorDistributionInfoRequest{ + ValidatorAddress: addrs[0].String(), + }, + resp: &types.QueryValidatorDistributionInfoResponse{}, + errMsg: `expected 'cosmosvaloper' got 'cosmos'`, + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + out, err := queryServer.ValidatorDistributionInfo(ctx, tc.req) + if tc.errMsg == "" { + require.NoError(t, err) + require.Equal(t, tc.resp, out) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + require.Nil(t, out) + } + }) + } +} + +func TestQueryValidatorOutstandingRewards(t *testing.T) { + // TODO https://github.com/cosmos/cosmos-sdk/issues/16757 + // currently tested in tests/e2e/distribution/grpc_query_suite.go +} + +func TestQueryValidatorCommission(t *testing.T) { + // TODO https://github.com/cosmos/cosmos-sdk/issues/16757 + // currently tested in tests/e2e/distribution/grpc_query_suite.go +} + +func TestQueryValidatorSlashes(t *testing.T) { + // TODO https://github.com/cosmos/cosmos-sdk/issues/16757 + // currently tested in tests/e2e/distribution/grpc_query_suite.go +} + +func TestQueryDelegationRewards(t *testing.T) { + // TODO https://github.com/cosmos/cosmos-sdk/issues/16757 + // currently tested in tests/e2e/distribution/grpc_query_suite.go +} + +func TestQueryDelegationTotalRewards(t *testing.T) { + // TODO https://github.com/cosmos/cosmos-sdk/issues/16757 + // currently tested in tests/e2e/distribution/grpc_query_suite.go +} + +func TestQueryDelegatorValidators(t *testing.T) { + // TODO https://github.com/cosmos/cosmos-sdk/issues/16757 + // currently tested in tests/e2e/distribution/grpc_query_suite.go +} + +func TestQueryDelegatorWithdrawAddress(t *testing.T) { + // TODO https://github.com/cosmos/cosmos-sdk/issues/16757 + // currently tested in tests/e2e/distribution/grpc_query_suite.go +} + +func TestQueryCommunityPool(t *testing.T) { + ctx, _, distrKeeper, dep := initFixture(t) + queryServer := keeper.NewQuerier(distrKeeper) + + coins := sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(100))) + decCoins := sdk.NewDecCoinsFromCoins(coins...) + dep.poolKeeper.EXPECT().GetCommunityPool(gomock.Any()).Return(coins, nil).AnyTimes() + + cases := []struct { + name string + req *types.QueryCommunityPoolRequest //nolint:staticcheck // Testing deprecated method + resp *types.QueryCommunityPoolResponse //nolint:staticcheck // Testing deprecated method + errMsg string + }{ + { + name: "success", + req: &types.QueryCommunityPoolRequest{}, //nolint:staticcheck // Testing deprecated method + resp: &types.QueryCommunityPoolResponse{ //nolint:staticcheck // Testing deprecated method + Pool: decCoins, + }, + errMsg: "", + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + out, err := queryServer.CommunityPool(ctx, tc.req) + if tc.errMsg == "" { + require.NoError(t, err) + require.Equal(t, tc.resp, out) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + require.Nil(t, out) + } + }) + } +} diff --git a/x/distribution/keeper/keeper_test.go b/x/distribution/keeper/keeper_test.go index 089e8f626341..69359ab91d28 100644 --- a/x/distribution/keeper/keeper_test.go +++ b/x/distribution/keeper/keeper_test.go @@ -11,6 +11,7 @@ import ( "cosmossdk.io/math" storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/testutil" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" @@ -23,7 +24,16 @@ import ( "github.com/cosmos/cosmos-sdk/x/distribution/types" ) -func TestSetWithdrawAddr(t *testing.T) { +type dep struct { + bankKeeper *distrtestutil.MockBankKeeper + stakingKeeper *distrtestutil.MockStakingKeeper + accountKeeper *distrtestutil.MockAccountKeeper + poolKeeper *distrtestutil.MockPoolKeeper +} + +func initFixture(t *testing.T) (sdk.Context, []sdk.AccAddress, keeper.Keeper, dep) { + t.Helper() + ctrl := gomock.NewController(t) key := storetypes.NewKVStoreKey(types.StoreKey) storeService := runtime.NewKVStoreService(key) @@ -32,16 +42,17 @@ func TestSetWithdrawAddr(t *testing.T) { ctx := testCtx.Ctx.WithBlockHeader(cmtproto.Header{Time: time.Now()}) addrs := simtestutil.CreateIncrementalAccounts(2) - delegatorAddr := addrs[0] - withdrawAddr := addrs[1] - bankKeeper := distrtestutil.NewMockBankKeeper(ctrl) stakingKeeper := distrtestutil.NewMockStakingKeeper(ctrl) accountKeeper := distrtestutil.NewMockAccountKeeper(ctrl) poolKeeper := distrtestutil.NewMockPoolKeeper(ctrl) accountKeeper.EXPECT().GetModuleAddress("distribution").Return(distrAcc.GetAddress()) + accountKeeper.EXPECT().AddressCodec().Return(address.NewBech32Codec("cosmos")).AnyTimes() + stakingKeeper.EXPECT().ValidatorAddressCodec().Return(address.NewBech32Codec("cosmosvaloper")).AnyTimes() + + withdrawAddr := addrs[1] bankKeeper.EXPECT().BlockedAddr(withdrawAddr).Return(false).AnyTimes() bankKeeper.EXPECT().BlockedAddr(distrAcc.GetAddress()).Return(true).AnyTimes() @@ -56,10 +67,22 @@ func TestSetWithdrawAddr(t *testing.T) { authtypes.NewModuleAddress("gov").String(), ) + params := types.DefaultParams() + require.NoError(t, distrKeeper.Params.Set(ctx, params)) + + return ctx, addrs, distrKeeper, dep{bankKeeper, stakingKeeper, accountKeeper, poolKeeper} +} + +func TestSetWithdrawAddr(t *testing.T) { + ctx, addrs, distrKeeper, _ := initFixture(t) + params := types.DefaultParams() params.WithdrawAddrEnabled = false require.NoError(t, distrKeeper.Params.Set(ctx, params)) + delegatorAddr := addrs[0] + withdrawAddr := addrs[1] + err := distrKeeper.SetWithdrawAddr(ctx, delegatorAddr, withdrawAddr) require.NotNil(t, err) @@ -76,39 +99,14 @@ func TestSetWithdrawAddr(t *testing.T) { } func TestWithdrawValidatorCommission(t *testing.T) { - ctrl := gomock.NewController(t) - key := storetypes.NewKVStoreKey(types.StoreKey) - storeService := runtime.NewKVStoreService(key) - testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) - encCfg := moduletestutil.MakeTestEncodingConfig(distribution.AppModuleBasic{}) - ctx := testCtx.Ctx.WithBlockHeader(cmtproto.Header{Time: time.Now()}) - addrs := simtestutil.CreateIncrementalAccounts(1) + ctx, addrs, distrKeeper, dep := initFixture(t) valAddr := sdk.ValAddress(addrs[0]) - - bankKeeper := distrtestutil.NewMockBankKeeper(ctrl) - stakingKeeper := distrtestutil.NewMockStakingKeeper(ctrl) - accountKeeper := distrtestutil.NewMockAccountKeeper(ctrl) - poolKeeper := distrtestutil.NewMockPoolKeeper(ctrl) - - accountKeeper.EXPECT().GetModuleAddress("distribution").Return(distrAcc.GetAddress()) - valCommission := sdk.DecCoins{ sdk.NewDecCoinFromDec("mytoken", math.LegacyNewDec(5).Quo(math.LegacyNewDec(4))), sdk.NewDecCoinFromDec("stake", math.LegacyNewDec(3).Quo(math.LegacyNewDec(2))), } - distrKeeper := keeper.NewKeeper( - encCfg.Codec, - storeService, - accountKeeper, - bankKeeper, - stakingKeeper, - poolKeeper, - "fee_collector", - authtypes.NewModuleAddress("gov").String(), - ) - // set outstanding rewards require.NoError(t, distrKeeper.ValidatorOutstandingRewards.Set(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})) @@ -118,7 +116,7 @@ func TestWithdrawValidatorCommission(t *testing.T) { // withdraw commission coins := sdk.NewCoins(sdk.NewCoin("mytoken", math.NewInt(1)), sdk.NewCoin("stake", math.NewInt(1))) // if SendCoinsFromModuleToAccount is called, we know that the withdraw was successful - bankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), "distribution", addrs[0], coins).Return(nil) + dep.bankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), "distribution", addrs[0], coins).Return(nil) _, err := distrKeeper.WithdrawValidatorCommission(ctx, valAddr) require.NoError(t, err) @@ -134,42 +132,15 @@ func TestWithdrawValidatorCommission(t *testing.T) { } func TestGetTotalRewards(t *testing.T) { - ctrl := gomock.NewController(t) - key := storetypes.NewKVStoreKey(types.StoreKey) - storeService := runtime.NewKVStoreService(key) - testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) - encCfg := moduletestutil.MakeTestEncodingConfig(distribution.AppModuleBasic{}) - ctx := testCtx.Ctx.WithBlockHeader(cmtproto.Header{Time: time.Now()}) - addrs := simtestutil.CreateIncrementalAccounts(2) - - valAddr0 := sdk.ValAddress(addrs[0]) - valAddr1 := sdk.ValAddress(addrs[1]) - - bankKeeper := distrtestutil.NewMockBankKeeper(ctrl) - stakingKeeper := distrtestutil.NewMockStakingKeeper(ctrl) - accountKeeper := distrtestutil.NewMockAccountKeeper(ctrl) - poolKeeper := distrtestutil.NewMockPoolKeeper(ctrl) - - accountKeeper.EXPECT().GetModuleAddress("distribution").Return(distrAcc.GetAddress()) - - distrKeeper := keeper.NewKeeper( - encCfg.Codec, - storeService, - accountKeeper, - bankKeeper, - stakingKeeper, - poolKeeper, - "fee_collector", - authtypes.NewModuleAddress("gov").String(), - ) + ctx, addrs, distrKeeper, _ := initFixture(t) valCommission := sdk.DecCoins{ sdk.NewDecCoinFromDec("mytoken", math.LegacyNewDec(5).Quo(math.LegacyNewDec(4))), sdk.NewDecCoinFromDec("stake", math.LegacyNewDec(3).Quo(math.LegacyNewDec(2))), } - require.NoError(t, distrKeeper.ValidatorOutstandingRewards.Set(ctx, valAddr0, types.ValidatorOutstandingRewards{Rewards: valCommission})) - require.NoError(t, distrKeeper.ValidatorOutstandingRewards.Set(ctx, valAddr1, types.ValidatorOutstandingRewards{Rewards: valCommission})) + require.NoError(t, distrKeeper.ValidatorOutstandingRewards.Set(ctx, sdk.ValAddress(addrs[0]), types.ValidatorOutstandingRewards{Rewards: valCommission})) + require.NoError(t, distrKeeper.ValidatorOutstandingRewards.Set(ctx, sdk.ValAddress(addrs[1]), types.ValidatorOutstandingRewards{Rewards: valCommission})) expectedRewards := valCommission.MulDec(math.LegacyNewDec(2)) totalRewards := distrKeeper.GetTotalRewards(ctx) diff --git a/x/distribution/keeper/msg_server.go b/x/distribution/keeper/msg_server.go index 3feb052fbc34..77ec9db0db31 100644 --- a/x/distribution/keeper/msg_server.go +++ b/x/distribution/keeper/msg_server.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "fmt" "github.com/hashicorp/go-metrics" @@ -154,7 +155,7 @@ func (k msgServer) CommunityPoolSpend(ctx context.Context, msg *types.MsgCommuni recipient, err := k.authKeeper.AddressCodec().StringToBytes(msg.Recipient) if err != nil { - return nil, err + return nil, fmt.Errorf("invalid recipient address: %w", err) } if err := k.poolKeeper.DistributeFromFeePool(ctx, msg.Amount, recipient); err != nil { @@ -170,7 +171,7 @@ func (k msgServer) CommunityPoolSpend(ctx context.Context, msg *types.MsgCommuni func (k msgServer) DepositValidatorRewardsPool(ctx context.Context, msg *types.MsgDepositValidatorRewardsPool) (*types.MsgDepositValidatorRewardsPoolResponse, error) { depositor, err := k.authKeeper.AddressCodec().StringToBytes(msg.Depositor) if err != nil { - return nil, err + return nil, fmt.Errorf("invalid depositor address: %w", err) } // deposit coins from depositor's account to the distribution module diff --git a/x/distribution/keeper/msg_server_test.go b/x/distribution/keeper/msg_server_test.go new file mode 100644 index 000000000000..1f136cd525d8 --- /dev/null +++ b/x/distribution/keeper/msg_server_test.go @@ -0,0 +1,358 @@ +package keeper_test + +import ( + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + "github.com/cosmos/cosmos-sdk/x/distribution/types" +) + +func TestMsgSetWithdrawAddress(t *testing.T) { + ctx, addrs, distrKeeper, _ := initFixture(t) + msgServer := keeper.NewMsgServerImpl(distrKeeper) + + cases := []struct { + name string + msg *types.MsgSetWithdrawAddress + errMsg string + }{ + { + name: "success", + msg: &types.MsgSetWithdrawAddress{ + DelegatorAddress: addrs[0].String(), + WithdrawAddress: addrs[1].String(), + }, + errMsg: "", + }, + { + name: "invalid delegator address", + msg: &types.MsgSetWithdrawAddress{ + DelegatorAddress: "invalid", + WithdrawAddress: addrs[1].String(), + }, + errMsg: "invalid address", + }, + { + name: "invalid withdraw address", + msg: &types.MsgSetWithdrawAddress{ + DelegatorAddress: addrs[0].String(), + WithdrawAddress: "invalid", + }, + errMsg: "invalid address", + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + _, err := msgServer.SetWithdrawAddress(ctx, tc.msg) + if tc.errMsg == "" { + require.NoError(t, err) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + } + }) + } +} + +func TestMsgWithdrawDelegatorReward(t *testing.T) { + ctx, addrs, distrKeeper, dep := initFixture(t) + dep.stakingKeeper.EXPECT().Validator(gomock.Any(), gomock.Any()).AnyTimes() + msgServer := keeper.NewMsgServerImpl(distrKeeper) + + cases := []struct { + name string + preRun func() + msg *types.MsgWithdrawDelegatorReward + errMsg string + }{ + { + name: "invalid delegator address", + msg: &types.MsgWithdrawDelegatorReward{ + DelegatorAddress: "invalid", + ValidatorAddress: sdk.ValAddress(addrs[1]).String(), + }, + errMsg: "invalid delegator address", + }, + { + name: "invalid validator address", + msg: &types.MsgWithdrawDelegatorReward{ + DelegatorAddress: addrs[0].String(), + ValidatorAddress: "invalid", + }, + errMsg: "invalid validator address", + }, + { + name: "no validator", + msg: &types.MsgWithdrawDelegatorReward{ + DelegatorAddress: addrs[0].String(), + ValidatorAddress: sdk.ValAddress(addrs[1]).String(), + }, + errMsg: "no validator distribution info", + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + if tc.preRun != nil { + tc.preRun() + } + _, err := msgServer.WithdrawDelegatorReward(ctx, tc.msg) + if tc.errMsg == "" { + require.NoError(t, err) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + } + }) + } +} + +func TestMsgWithdrawValidatorCommission(t *testing.T) { + ctx, addrs, distrKeeper, _ := initFixture(t) + msgServer := keeper.NewMsgServerImpl(distrKeeper) + + cases := []struct { + name string + preRun func() + msg *types.MsgWithdrawValidatorCommission + errMsg string + }{ + { + name: "invalid validator address", + msg: &types.MsgWithdrawValidatorCommission{ + ValidatorAddress: "invalid", + }, + errMsg: "invalid validator address", + }, + { + name: "no validator commission to withdraw", + msg: &types.MsgWithdrawValidatorCommission{ + ValidatorAddress: sdk.ValAddress(addrs[1]).String(), + }, + errMsg: "no validator commission to withdraw", + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + if tc.preRun != nil { + tc.preRun() + } + _, err := msgServer.WithdrawValidatorCommission(ctx, tc.msg) + if tc.errMsg == "" { + require.NoError(t, err) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + } + }) + } +} + +func TestMsgFundCommunityPool(t *testing.T) { + ctx, addrs, distrKeeper, dep := initFixture(t) + dep.poolKeeper.EXPECT().FundCommunityPool(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + msgServer := keeper.NewMsgServerImpl(distrKeeper) + + cases := []struct { + name string + msg *types.MsgFundCommunityPool //nolint:staticcheck // Testing deprecated method + errMsg string + }{ + { + name: "invalid depositor address", + msg: &types.MsgFundCommunityPool{ //nolint:staticcheck // Testing deprecated method + Depositor: "invalid", + Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(100))), + }, + errMsg: "invalid depositor address", + }, + { + name: "success", + msg: &types.MsgFundCommunityPool{ //nolint:staticcheck // Testing deprecated method + Depositor: addrs[0].String(), + Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), + }, + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + _, err := msgServer.FundCommunityPool(ctx, tc.msg) //nolint:staticcheck // Testing deprecated method + if tc.errMsg == "" { + require.NoError(t, err) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + } + }) + } +} + +func TestMsgUpdateParams(t *testing.T) { + ctx, addrs, distrKeeper, _ := initFixture(t) + msgServer := keeper.NewMsgServerImpl(distrKeeper) + + cases := []struct { + name string + msg *types.MsgUpdateParams + errMsg string + }{ + { + name: "invalid authority", + msg: &types.MsgUpdateParams{ + Authority: "invalid", + Params: types.DefaultParams(), + }, + errMsg: "invalid address", + }, + { + name: "incorrect authority", + msg: &types.MsgUpdateParams{ + Authority: addrs[0].String(), + Params: types.DefaultParams(), + }, + errMsg: "expected authority account as only signer for proposal message", + }, + { + name: "invalid params", + msg: &types.MsgUpdateParams{ + Authority: authtypes.NewModuleAddress("gov").String(), + Params: types.Params{CommunityTax: math.LegacyNewDec(-1)}, + }, + errMsg: "community tax must be positive", + }, + { + name: "success", + msg: &types.MsgUpdateParams{ + Authority: authtypes.NewModuleAddress("gov").String(), + Params: types.DefaultParams(), + }, + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + _, err := msgServer.UpdateParams(ctx, tc.msg) + if tc.errMsg == "" { + require.NoError(t, err) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + } + }) + } +} + +func TestMsgCommunityPoolSpend(t *testing.T) { + ctx, addrs, distrKeeper, dep := initFixture(t) + dep.poolKeeper.EXPECT().DistributeFromFeePool(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + msgServer := keeper.NewMsgServerImpl(distrKeeper) + + cases := []struct { + name string + msg *types.MsgCommunityPoolSpend //nolint:staticcheck // Testing deprecated method + errMsg string + }{ + { + name: "invalid authority", + msg: &types.MsgCommunityPoolSpend{ //nolint:staticcheck // Testing deprecated method + Authority: "invalid", + Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(100))), + }, + errMsg: "invalid address", + }, + { + name: "incorrect authority", + msg: &types.MsgCommunityPoolSpend{ //nolint:staticcheck // Testing deprecated method + Authority: addrs[0].String(), + Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(100))), + }, + errMsg: "expected authority account as only signer for proposal message", + }, + { + name: "invalid recipient address", + msg: &types.MsgCommunityPoolSpend{ //nolint:staticcheck // Testing deprecated method + Authority: authtypes.NewModuleAddress("gov").String(), + Recipient: "invalid", + Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(100))), + }, + errMsg: "invalid recipient address", + }, + { + name: "invalid amount", + msg: &types.MsgCommunityPoolSpend{ //nolint:staticcheck // Testing deprecated method + Authority: authtypes.NewModuleAddress("gov").String(), + Recipient: addrs[0].String(), + }, + errMsg: "invalid coins", + }, + { + name: "success", + msg: &types.MsgCommunityPoolSpend{ //nolint:staticcheck // Testing deprecated method + Authority: authtypes.NewModuleAddress("gov").String(), + Recipient: addrs[0].String(), + Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), + }, + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + _, err := msgServer.CommunityPoolSpend(ctx, tc.msg) //nolint:staticcheck // Testing deprecated method + if tc.errMsg == "" { + require.NoError(t, err) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + } + }) + } +} + +func TestMsgDepositValidatorRewardsPool(t *testing.T) { + ctx, _, distrKeeper, _ := initFixture(t) + msgServer := keeper.NewMsgServerImpl(distrKeeper) + + cases := []struct { + name string + msg *types.MsgDepositValidatorRewardsPool + errMsg string + }{ + { + name: "invalid depositor address", + msg: &types.MsgDepositValidatorRewardsPool{ + Depositor: "invalid", + Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(100))), + }, + errMsg: "invalid depositor address", + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + _, err := msgServer.DepositValidatorRewardsPool(ctx, tc.msg) + if tc.errMsg == "" { + require.NoError(t, err) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + } + }) + } +} diff --git a/x/distribution/module.go b/x/distribution/module.go index 6c179c537d83..b57b1925ebb2 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -9,7 +9,6 @@ import ( "github.com/spf13/cobra" modulev1 "cosmossdk.io/api/cosmos/distribution/module/v1" - "cosmossdk.io/core/address" "cosmossdk.io/core/appmodule" "cosmossdk.io/core/store" "cosmossdk.io/depinject" @@ -45,7 +44,6 @@ var ( // AppModuleBasic defines the basic application module used by the distribution module. type AppModuleBasic struct { cdc codec.Codec - ac address.Codec } // Name returns the distribution module's name. @@ -83,7 +81,7 @@ func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx sdkclient.Context, mux // GetTxCmd returns the root tx command for the distribution module. func (ab AppModuleBasic) GetTxCmd() *cobra.Command { - return cli.NewTxCmd(ab.cdc.InterfaceRegistry().SigningContext().ValidatorAddressCodec(), ab.cdc.InterfaceRegistry().SigningContext().AddressCodec()) + return cli.NewTxCmd() } // RegisterInterfaces implements InterfaceModule @@ -108,7 +106,7 @@ func NewAppModule( bankKeeper types.BankKeeper, stakingKeeper types.StakingKeeper, poolKeeper types.PoolKeeper, ) AppModule { return AppModule{ - AppModuleBasic: AppModuleBasic{cdc: cdc, ac: accountKeeper.AddressCodec()}, + AppModuleBasic: AppModuleBasic{cdc: cdc}, keeper: keeper, accountKeeper: accountKeeper, bankKeeper: bankKeeper, diff --git a/x/protocolpool/autocli.go b/x/protocolpool/autocli.go index 39d4087afaea..f8fbaa4c6139 100644 --- a/x/protocolpool/autocli.go +++ b/x/protocolpool/autocli.go @@ -30,7 +30,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { RpcMethod: "FundCommunityPool", Use: "fund-community-pool [amount]", Short: "Funds the community pool with the specified amount", - Example: fmt.Sprintf(`$ %s tx pool fund-community-pool 100uatom --from mykey`, version.AppName), + Example: fmt.Sprintf(`$ %s tx protocolpool fund-community-pool 100uatom --from mykey`, version.AppName), PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "amount"}}, }, }, diff --git a/x/staking/client/cli/tx.go b/x/staking/client/cli/tx.go index 45db874da52c..70cab08f7c73 100644 --- a/x/staking/client/cli/tx.go +++ b/x/staking/client/cli/tx.go @@ -33,7 +33,7 @@ var ( ) // NewTxCmd returns a root CLI command handler for all x/staking transaction commands. -func NewTxCmd(valAddrCodec, ac address.Codec) *cobra.Command { +func NewTxCmd() *cobra.Command { stakingTxCmd := &cobra.Command{ Use: types.ModuleName, Short: "Staking transaction subcommands", @@ -43,17 +43,15 @@ func NewTxCmd(valAddrCodec, ac address.Codec) *cobra.Command { } stakingTxCmd.AddCommand( - NewCreateValidatorCmd(valAddrCodec), - NewEditValidatorCmd(valAddrCodec), + NewCreateValidatorCmd(), + NewEditValidatorCmd(), ) return stakingTxCmd } // NewCreateValidatorCmd returns a CLI command handler for creating a MsgCreateValidator transaction. -// -// cannot give autocli support, can be CLI breaking -func NewCreateValidatorCmd(ac address.Codec) *cobra.Command { +func NewCreateValidatorCmd() *cobra.Command { cmd := &cobra.Command{ Use: "create-validator [path/to/validator.json]", Short: "create new validator initialized with a self-delegation to it", @@ -97,7 +95,7 @@ where we can get the pubkey using "%s tendermint show-validator" return err } - txf, msg, err := newBuildCreateValidatorMsg(clientCtx, txf, cmd.Flags(), validator, ac) + txf, msg, err := newBuildCreateValidatorMsg(clientCtx, txf, cmd.Flags(), validator, clientCtx.ValidatorAddressCodec) if err != nil { return err } @@ -116,9 +114,7 @@ where we can get the pubkey using "%s tendermint show-validator" } // NewEditValidatorCmd returns a CLI command handler for creating a MsgEditValidator transaction. -// -// cannot give autocli support, can be CLI breaking -func NewEditValidatorCmd(ac address.Codec) *cobra.Command { +func NewEditValidatorCmd() *cobra.Command { cmd := &cobra.Command{ Use: "edit-validator", Short: "edit an existing validator account", @@ -159,7 +155,7 @@ func NewEditValidatorCmd(ac address.Codec) *cobra.Command { newMinSelfDelegation = &msb } - valAddr, err := ac.BytesToString(clientCtx.GetFromAddress()) + valAddr, err := clientCtx.AddressCodec.BytesToString(clientCtx.GetFromAddress()) if err != nil { return err } diff --git a/x/staking/client/cli/tx_test.go b/x/staking/client/cli/tx_test.go index 05ad38a1271a..eaf8e91ba4b9 100644 --- a/x/staking/client/cli/tx_test.go +++ b/x/staking/client/cli/tx_test.go @@ -169,7 +169,7 @@ func (s *CLITestSuite) TestPrepareConfigForTxCreateValidator() { func (s *CLITestSuite) TestNewCreateValidatorCmd() { require := s.Require() - cmd := cli.NewCreateValidatorCmd(addresscodec.NewBech32Codec("cosmosvaloper")) + cmd := cli.NewCreateValidatorCmd() validJSON := fmt.Sprintf(` { @@ -316,7 +316,7 @@ func (s *CLITestSuite) TestNewCreateValidatorCmd() { } func (s *CLITestSuite) TestNewEditValidatorCmd() { - cmd := cli.NewEditValidatorCmd(addresscodec.NewBech32Codec("cosmos")) + cmd := cli.NewEditValidatorCmd() moniker := "testing" details := "bio" diff --git a/x/staking/module.go b/x/staking/module.go index 8c1cea7f69d2..b56294785711 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -49,7 +49,6 @@ var ( // AppModuleBasic defines the basic application module used by the staking module. type AppModuleBasic struct { cdc codec.Codec - ak types.AccountKeeper } // Name returns the staking module's name. @@ -92,7 +91,7 @@ func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *g // GetTxCmd returns the root tx command for the staking module. func (amb AppModuleBasic) GetTxCmd() *cobra.Command { - return cli.NewTxCmd(amb.cdc.InterfaceRegistry().SigningContext().ValidatorAddressCodec(), amb.cdc.InterfaceRegistry().SigningContext().AddressCodec()) + return cli.NewTxCmd() } // AppModule implements an application module for the staking module. @@ -112,7 +111,7 @@ func NewAppModule( bk types.BankKeeper, ) AppModule { return AppModule{ - AppModuleBasic: AppModuleBasic{cdc: cdc, ak: ak}, + AppModuleBasic: AppModuleBasic{cdc: cdc}, keeper: keeper, accountKeeper: ak, bankKeeper: bk,