diff --git a/CHANGELOG.md b/CHANGELOG.md index 11601034c9..53af158ebc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -161,6 +161,7 @@ be used to retrieve the actual proposal `Content`. Also the `NewMsgSubmitProposa ### Features +* (vesting) [\#7209](https://github.com/cosmos/cosmos-sdk/pull/7209) Create new `MsgCreateVestingAccount` message type along with CLI handler that allows for the creation of delayed and continuous vesting types. * (events) [\#7121](https://github.com/cosmos/cosmos-sdk/pull/7121) The application now drives what events are indexed by Tendermint via the `index-events` configuration in `app.toml`, which is a list of events taking the form `{eventType}.{attributeKey}`. * [\#6089](https://github.com/cosmos/cosmos-sdk/pull/6089) Transactions can now have a `TimeoutHeight` set which allows the transaction to be rejected if it's committed at a height greater than the timeout. * (tests) [\#6489](https://github.com/cosmos/cosmos-sdk/pull/6489) Introduce package `testutil`, new in-process testing network framework for use in integration and unit tests. diff --git a/proto/cosmos/vesting/v1beta1/tx.proto b/proto/cosmos/vesting/v1beta1/tx.proto new file mode 100644 index 0000000000..4219c01c24 --- /dev/null +++ b/proto/cosmos/vesting/v1beta1/tx.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; +package cosmos.vesting.v1beta1; + +import "gogoproto/gogo.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"; + +// MsgCreateVestingAccount defines a message that enables creating a vesting +// account. +message MsgCreateVestingAccount { + option (gogoproto.equal) = true; + + bytes from_address = 1 [ + (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress", + (gogoproto.moretags) = "yaml:\"from_address\"" + ]; + bytes to_address = 2 [ + (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress", + (gogoproto.moretags) = "yaml:\"to_address\"" + ]; + repeated cosmos.base.v1beta1.Coin amount = 3 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + + int64 end_time = 4 [(gogoproto.moretags) = "yaml:\"end_time\""]; + bool delayed = 5; +} diff --git a/simapp/app.go b/simapp/app.go index a26d08bd07..5f225ccc65 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -27,6 +27,7 @@ import ( authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/vesting" "github.com/cosmos/cosmos-sdk/x/bank" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -301,6 +302,7 @@ func NewSimApp( encodingConfig.TxConfig, ), auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), + vesting.NewAppModule(app.AccountKeeper, app.BankKeeper), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), capability.NewAppModule(appCodec, *app.CapabilityKeeper), crisis.NewAppModule(&app.CrisisKeeper), @@ -332,7 +334,7 @@ func NewSimApp( // so that other modules that want to create or claim capabilities afterwards in InitChain // can do so safely. app.mm.SetOrderInitGenesis( - capabilitytypes.ModuleName, authtypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, banktypes.ModuleName, + capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName, ibchost.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, ibctransfertypes.ModuleName, ) diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index a3bae53a60..55d2359410 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -30,6 +30,7 @@ import ( authclient "github.com/cosmos/cosmos-sdk/x/auth/client" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" "github.com/cosmos/cosmos-sdk/x/auth/types" + vestingcli "github.com/cosmos/cosmos-sdk/x/auth/vesting/client/cli" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" ) @@ -150,6 +151,7 @@ func txCommand() *cobra.Command { authcmd.GetEncodeCommand(), authcmd.GetDecodeCommand(), flags.LineBreak, + vestingcli.GetTxCmd(), ) simapp.ModuleBasics.AddTxCommands(cmd) diff --git a/types/module/module.go b/types/module/module.go index 6934ce89f1..d02b9b2568 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -166,10 +166,13 @@ type AppModule interface { // routes Route() sdk.Route + // Deprecated: use RegisterQueryService QuerierRoute() string + // Deprecated: use RegisterQueryService LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier + // RegisterQueryService allows a module to register a gRPC query service RegisterQueryService(grpc.Server) diff --git a/x/auth/vesting/client/cli/cli_test.go b/x/auth/vesting/client/cli/cli_test.go new file mode 100644 index 0000000000..ce2e13e8f2 --- /dev/null +++ b/x/auth/vesting/client/cli/cli_test.go @@ -0,0 +1,137 @@ +package cli_test + +import ( + "fmt" + "testing" + + "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/client/flags" + 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/auth/vesting/client/cli" +) + +type IntegrationTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + + s.cfg = cfg + s.network = network.New(s.T(), cfg) + + _, err := s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *IntegrationTestSuite) TestNewMsgCreateVestingAccountCmd() { + val := s.network.Validators[0] + + testCases := map[string]struct { + args []string + expectErr bool + respType proto.Message + expectedCode uint32 + }{ + "create a continuous vesting account": { + args: []string{ + sdk.AccAddress("addr2_______________").String(), + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String(), + "4070908800", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + expectErr: false, + respType: &sdk.TxResponse{}, + expectedCode: 0, + }, + "create a delayed vesting account": { + args: []string{ + sdk.AccAddress("addr3_______________").String(), + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String(), + "4070908800", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), + fmt.Sprintf("--%s=true", cli.FlagDelayed), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + expectErr: false, + respType: &sdk.TxResponse{}, + expectedCode: 0, + }, + "invalid address": { + args: []string{ + sdk.AccAddress("addr4").String(), + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String(), + "4070908800", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), + }, + expectErr: true, + respType: &sdk.TxResponse{}, + expectedCode: 0, + }, + "invalid coins": { + args: []string{ + sdk.AccAddress("addr4_______________").String(), + "fooo", + "4070908800", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), + }, + expectErr: true, + respType: &sdk.TxResponse{}, + expectedCode: 0, + }, + "invalid end time": { + args: []string{ + sdk.AccAddress("addr4_______________").String(), + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String(), + "-4070908800", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), + }, + expectErr: true, + respType: &sdk.TxResponse{}, + expectedCode: 0, + }, + } + + for name, tc := range testCases { + tc := tc + + s.Run(name, func() { + clientCtx := val.ClientCtx + + bw, err := clitestutil.ExecTestCLICmd(clientCtx, cli.NewMsgCreateVestingAccountCmd(), tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(bw.Bytes(), tc.respType), bw.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code) + } + }) + } +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/auth/vesting/client/cli/tx.go b/x/auth/vesting/client/cli/tx.go new file mode 100644 index 0000000000..33668fadde --- /dev/null +++ b/x/auth/vesting/client/cli/tx.go @@ -0,0 +1,86 @@ +package cli + +import ( + "strconv" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" +) + +// Transaction command flags +const ( + FlagDelayed = "delayed" +) + +// GetTxCmd returns vesting module's transaction commands. +func GetTxCmd() *cobra.Command { + txCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Vesting transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand( + NewMsgCreateVestingAccountCmd(), + ) + + return txCmd +} + +// NewMsgCreateVestingAccountCmd returns a CLI command handler for creating a +// MsgCreateVestingAccount transaction. +func NewMsgCreateVestingAccountCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-vesting-account [to_address] [amount] [end_time]", + Short: "Create a new vesting account funded with an allocation of tokens.", + Long: `Create a new vesting account funded with an allocation of tokens. The +account can either be a delayed or continuous vesting account, which is determined +by the '--delayed' flag. All vesting accouts created will have their start time +set by the committed block's time. The end_time must be provided as a UNIX epoch +timestamp.`, + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags()) + if err != nil { + return err + } + + toAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + amount, err := sdk.ParseCoins(args[1]) + if err != nil { + return err + } + + endTime, err := strconv.ParseInt(args[2], 10, 64) + if err != nil { + return err + } + + delayed, _ := cmd.Flags().GetBool(FlagDelayed) + + msg := types.NewMsgCreateVestingAccount(clientCtx.GetFromAddress(), toAddr, amount, endTime, delayed) + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().Bool(FlagDelayed, false, "Create a delayed vesting account if true") + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/auth/vesting/handler.go b/x/auth/vesting/handler.go new file mode 100644 index 0000000000..963f66eb80 --- /dev/null +++ b/x/auth/vesting/handler.go @@ -0,0 +1,86 @@ +package vesting + +import ( + "github.com/armon/go-metrics" + + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" +) + +// NewHandler returns a handler for x/auth message types. +func NewHandler(ak keeper.AccountKeeper, bk types.BankKeeper) sdk.Handler { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { + ctx = ctx.WithEventManager(sdk.NewEventManager()) + + switch msg := msg.(type) { + case *types.MsgCreateVestingAccount: + return handleMsgCreateVestingAccount(ctx, ak, bk, msg) + + default: + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg) + } + } +} + +func handleMsgCreateVestingAccount(ctx sdk.Context, ak keeper.AccountKeeper, bk types.BankKeeper, msg *types.MsgCreateVestingAccount) (*sdk.Result, error) { + if err := bk.SendEnabledCoins(ctx, msg.Amount...); err != nil { + return nil, err + } + + if bk.BlockedAddr(msg.ToAddress) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress) + } + + if acc := ak.GetAccount(ctx, msg.ToAddress); acc != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress) + } + + baseAccount := ak.NewAccountWithAddress(ctx, msg.ToAddress) + if _, ok := baseAccount.(*authtypes.BaseAccount); !ok { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid account type; expected: BaseAccount, got: %T", baseAccount) + } + + baseVestingAccount := types.NewBaseVestingAccount(baseAccount.(*authtypes.BaseAccount), msg.Amount.Sort(), msg.EndTime) + + var acc authtypes.AccountI + + if msg.Delayed { + acc = types.NewDelayedVestingAccountRaw(baseVestingAccount) + } else { + acc = types.NewContinuousVestingAccountRaw(baseVestingAccount, ctx.BlockTime().Unix()) + } + + ak.SetAccount(ctx, acc) + + defer func() { + telemetry.IncrCounter(1, "new", "account") + + for _, a := range msg.Amount { + if a.Amount.IsInt64() { + telemetry.SetGaugeWithLabels( + []string{"tx", "msg", "create_vesting_account"}, + float32(a.Amount.Int64()), + []metrics.Label{telemetry.NewLabel("denom", a.Denom)}, + ) + } + } + }() + + err := bk.SendCoins(ctx, msg.FromAddress, msg.ToAddress, msg.Amount) + if err != nil { + return nil, err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + ), + ) + + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil +} diff --git a/x/auth/vesting/handler_test.go b/x/auth/vesting/handler_test.go new file mode 100644 index 0000000000..05bb1edb0f --- /dev/null +++ b/x/auth/vesting/handler_test.go @@ -0,0 +1,90 @@ +package vesting_test + +import ( + "testing" + + "github.com/stretchr/testify/suite" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/vesting" + "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" +) + +type HandlerTestSuite struct { + suite.Suite + + handler sdk.Handler + app *simapp.SimApp +} + +func (suite *HandlerTestSuite) SetupTest() { + checkTx := false + app := simapp.Setup(checkTx) + + suite.handler = vesting.NewHandler(app.AccountKeeper, app.BankKeeper) + suite.app = app +} + +func (suite *HandlerTestSuite) TestMsgCreateVestingAccount() { + ctx := suite.app.BaseApp.NewContext(false, tmproto.Header{Height: suite.app.LastBlockHeight() + 1}) + + balances := sdk.NewCoins(sdk.NewInt64Coin("test", 1000)) + addr1 := sdk.AccAddress([]byte("addr1")) + addr2 := sdk.AccAddress([]byte("addr2")) + addr3 := sdk.AccAddress([]byte("addr3")) + + acc1 := suite.app.AccountKeeper.NewAccountWithAddress(ctx, addr1) + suite.app.AccountKeeper.SetAccount(ctx, acc1) + suite.Require().NoError(suite.app.BankKeeper.SetBalances(ctx, addr1, balances)) + + testCases := map[string]struct { + msg *types.MsgCreateVestingAccount + expectErr bool + }{ + "create delayed vesting account": { + msg: types.NewMsgCreateVestingAccount(addr1, addr2, sdk.NewCoins(sdk.NewInt64Coin("test", 100)), ctx.BlockTime().Unix()+10000, true), + expectErr: false, + }, + "create continuous vesting account": { + msg: types.NewMsgCreateVestingAccount(addr1, addr3, sdk.NewCoins(sdk.NewInt64Coin("test", 100)), ctx.BlockTime().Unix()+10000, false), + expectErr: false, + }, + "continuous vesting account already exists": { + msg: types.NewMsgCreateVestingAccount(addr1, addr3, sdk.NewCoins(sdk.NewInt64Coin("test", 100)), ctx.BlockTime().Unix()+10000, false), + expectErr: true, + }, + } + + for name, tc := range testCases { + tc := tc + + suite.Run(name, func() { + res, err := suite.handler(ctx, tc.msg) + if tc.expectErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().NotNil(res) + + accI := suite.app.AccountKeeper.GetAccount(ctx, tc.msg.ToAddress) + suite.Require().NotNil(accI) + + if tc.msg.Delayed { + acc, ok := accI.(*types.DelayedVestingAccount) + suite.Require().True(ok) + suite.Require().Equal(tc.msg.Amount, acc.GetVestingCoins(ctx.BlockTime())) + } else { + acc, ok := accI.(*types.ContinuousVestingAccount) + suite.Require().True(ok) + suite.Require().Equal(tc.msg.Amount, acc.GetVestingCoins(ctx.BlockTime())) + } + } + }) + } +} + +func TestHandlerTestSuite(t *testing.T) { + suite.Run(t, new(HandlerTestSuite)) +} diff --git a/x/auth/vesting/module.go b/x/auth/vesting/module.go new file mode 100644 index 0000000000..026b9858bb --- /dev/null +++ b/x/auth/vesting/module.go @@ -0,0 +1,128 @@ +package vesting + +import ( + "encoding/json" + + "github.com/gogo/protobuf/grpc" + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/auth/keeper" + "github.com/cosmos/cosmos-sdk/x/auth/vesting/client/cli" + "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// AppModuleBasic defines the basic application module used by the sub-vesting +// module. The module itself contain no special logic or state other than message +// handling. +type AppModuleBasic struct{} + +// Name returns the module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterCodec registers the module's types with the given codec. +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// RegisterInterfaces registers the module's interfaces and implementations with +// the given interface registry. +func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// DefaultGenesis returns the module's default genesis state as raw bytes. +func (AppModuleBasic) DefaultGenesis(_ codec.JSONMarshaler) json.RawMessage { + return []byte("{}") +} + +// ValidateGenesis performs genesis state validation. Currently, this is a no-op. +func (AppModuleBasic) ValidateGenesis(_ codec.JSONMarshaler, _ client.TxEncodingConfig, bz json.RawMessage) error { + return nil +} + +// RegisterRESTRoutes registers module's REST handlers. Currently, this is a no-op. +func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {} + +// RegisterGRPCRoutes registers the module's gRPC Gateway routes. Currently, this +// is a no-op. +func (a AppModuleBasic) RegisterGRPCRoutes(_ client.Context, _ *runtime.ServeMux) {} + +// GetTxCmd returns the root tx command for the auth module. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +// GetQueryCmd returns the module's root query command. Currently, this is a no-op. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return nil +} + +// AppModule extends the AppModuleBasic implementation by implementing the +// AppModule interface. +type AppModule struct { + AppModuleBasic + + accountKeeper keeper.AccountKeeper + bankKeeper types.BankKeeper +} + +func NewAppModule(ak keeper.AccountKeeper, bk types.BankKeeper) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{}, + accountKeeper: ak, + bankKeeper: bk, + } +} + +// RegisterInvariants performs a no-op; there are no invariants to enforce. +func (AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// Route returns the module's message router and handler. +func (am AppModule) Route() sdk.Route { + return sdk.NewRoute(types.RouterKey, NewHandler(am.accountKeeper, am.bankKeeper)) +} + +// QuerierRoute returns an empty string as the module contains no query +// functionality. +func (AppModule) QuerierRoute() string { return "" } + +// RegisterQueryService performs a no-op. +func (am AppModule) RegisterQueryService(_ grpc.Server) {} + +// LegacyQuerierHandler performs a no-op. +func (am AppModule) LegacyQuerierHandler(_ *codec.LegacyAmino) sdk.Querier { + return nil +} + +// InitGenesis performs a no-op. +func (am AppModule) InitGenesis(_ sdk.Context, _ codec.JSONMarshaler, _ json.RawMessage) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// BeginBlock performs a no-op. +func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} + +// EndBlock performs a no-op. +func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// ExportGenesis is always empty, as InitGenesis does nothing either. +func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { + return am.DefaultGenesis(cdc) +} diff --git a/x/auth/vesting/types/codec.go b/x/auth/vesting/types/codec.go index 177942c83f..8abf56cd6b 100644 --- a/x/auth/vesting/types/codec.go +++ b/x/auth/vesting/types/codec.go @@ -3,6 +3,7 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported" ) @@ -41,6 +42,11 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { &ContinuousVestingAccount{}, &PeriodicVestingAccount{}, ) + + registry.RegisterImplementations( + (*sdk.Msg)(nil), + &MsgCreateVestingAccount{}, + ) } var amino = codec.NewLegacyAmino() diff --git a/x/auth/vesting/types/constants.go b/x/auth/vesting/types/constants.go new file mode 100644 index 0000000000..1d0b0ebbb3 --- /dev/null +++ b/x/auth/vesting/types/constants.go @@ -0,0 +1,12 @@ +package types + +const ( + // ModuleName defines the module's name. + ModuleName = "vesting" + + // AttributeValueCategory is an alias for the message event value. + AttributeValueCategory = ModuleName + + // RouterKey defines the module's message routing key + RouterKey = ModuleName +) diff --git a/x/auth/vesting/types/expected_keepers.go b/x/auth/vesting/types/expected_keepers.go new file mode 100644 index 0000000000..8212f6e375 --- /dev/null +++ b/x/auth/vesting/types/expected_keepers.go @@ -0,0 +1,13 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// BankKeeper defines the expected interface contract the vesting module requires +// for creating vesting accounts with funds. +type BankKeeper interface { + SendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error + SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error + BlockedAddr(addr sdk.AccAddress) bool +} diff --git a/x/auth/vesting/types/msgs.go b/x/auth/vesting/types/msgs.go new file mode 100644 index 0000000000..01e8d95e1a --- /dev/null +++ b/x/auth/vesting/types/msgs.go @@ -0,0 +1,64 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// TypeMsgCreateVestingAccount defines the type value for a MsgCreateVestingAccount. +const TypeMsgCreateVestingAccount = "msg_create_vesting_account" + +var _ sdk.Msg = &MsgCreateVestingAccount{} + +// NewMsgCreateVestingAccount returns a reference to a new MsgCreateVestingAccount. +func NewMsgCreateVestingAccount(fromAddr, toAddr sdk.AccAddress, amount sdk.Coins, endTime int64, delayed bool) *MsgCreateVestingAccount { + return &MsgCreateVestingAccount{ + FromAddress: fromAddr, + ToAddress: toAddr, + Amount: amount, + EndTime: endTime, + Delayed: delayed, + } +} + +// Route returns the message route for a MsgCreateVestingAccount. +func (msg MsgCreateVestingAccount) Route() string { return RouterKey } + +// Type returns the message type for a MsgCreateVestingAccount. +func (msg MsgCreateVestingAccount) Type() string { return TypeMsgCreateVestingAccount } + +// ValidateBasic Implements Msg. +func (msg MsgCreateVestingAccount) ValidateBasic() error { + if err := sdk.VerifyAddressFormat(msg.FromAddress); err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid sender address: %s", err) + } + + if err := sdk.VerifyAddressFormat(msg.ToAddress); err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid recipient address: %s", err) + } + + if !msg.Amount.IsValid() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) + } + + if !msg.Amount.IsAllPositive() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) + } + + if msg.EndTime <= 0 { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid end time") + } + + return nil +} + +// GetSignBytes returns the bytes all expected signers must sign over for a +// MsgCreateVestingAccount. +func (msg MsgCreateVestingAccount) GetSignBytes() []byte { + return sdk.MustSortJSON(amino.MustMarshalJSON(&msg)) +} + +// GetSigners returns the expected signers for a MsgCreateVestingAccount. +func (msg MsgCreateVestingAccount) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.FromAddress} +} diff --git a/x/auth/vesting/types/tx.pb.go b/x/auth/vesting/types/tx.pb.go new file mode 100644 index 0000000000..d9b283d33a --- /dev/null +++ b/x/auth/vesting/types/tx.pb.go @@ -0,0 +1,572 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/vesting/v1beta1/tx.proto + +package types + +import ( + bytes "bytes" + fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgCreateVestingAccount defines a message that enables creating a vesting +// account. +type MsgCreateVestingAccount struct { + FromAddress github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,1,opt,name=from_address,json=fromAddress,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"from_address,omitempty" yaml:"from_address"` + ToAddress github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,2,opt,name=to_address,json=toAddress,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"to_address,omitempty" yaml:"to_address"` + Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` + EndTime int64 `protobuf:"varint,4,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty" yaml:"end_time"` + Delayed bool `protobuf:"varint,5,opt,name=delayed,proto3" json:"delayed,omitempty"` +} + +func (m *MsgCreateVestingAccount) Reset() { *m = MsgCreateVestingAccount{} } +func (m *MsgCreateVestingAccount) String() string { return proto.CompactTextString(m) } +func (*MsgCreateVestingAccount) ProtoMessage() {} +func (*MsgCreateVestingAccount) Descriptor() ([]byte, []int) { + return fileDescriptor_5338ca97811f9792, []int{0} +} +func (m *MsgCreateVestingAccount) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateVestingAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateVestingAccount.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgCreateVestingAccount) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateVestingAccount.Merge(m, src) +} +func (m *MsgCreateVestingAccount) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateVestingAccount) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateVestingAccount.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateVestingAccount proto.InternalMessageInfo + +func (m *MsgCreateVestingAccount) GetFromAddress() github_com_cosmos_cosmos_sdk_types.AccAddress { + if m != nil { + return m.FromAddress + } + return nil +} + +func (m *MsgCreateVestingAccount) GetToAddress() github_com_cosmos_cosmos_sdk_types.AccAddress { + if m != nil { + return m.ToAddress + } + return nil +} + +func (m *MsgCreateVestingAccount) GetAmount() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.Amount + } + return nil +} + +func (m *MsgCreateVestingAccount) GetEndTime() int64 { + if m != nil { + return m.EndTime + } + return 0 +} + +func (m *MsgCreateVestingAccount) GetDelayed() bool { + if m != nil { + return m.Delayed + } + return false +} + +func init() { + proto.RegisterType((*MsgCreateVestingAccount)(nil), "cosmos.vesting.v1beta1.MsgCreateVestingAccount") +} + +func init() { proto.RegisterFile("cosmos/vesting/v1beta1/tx.proto", fileDescriptor_5338ca97811f9792) } + +var fileDescriptor_5338ca97811f9792 = []byte{ + // 385 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0x31, 0xcf, 0xd2, 0x40, + 0x18, 0xc7, 0x7b, 0x16, 0x01, 0x0f, 0x12, 0x63, 0x31, 0x5a, 0x19, 0x7a, 0x4d, 0xa7, 0x2e, 0x5c, + 0x45, 0x37, 0x36, 0x4a, 0x62, 0x4c, 0x8c, 0x4b, 0x63, 0x1c, 0x5c, 0xc8, 0xf5, 0x7a, 0x96, 0x06, + 0xda, 0x23, 0xbd, 0x83, 0xc0, 0xb7, 0xf0, 0x23, 0x18, 0x47, 0x3f, 0x09, 0x23, 0xa3, 0x53, 0x35, + 0xb0, 0x38, 0x33, 0x3a, 0x99, 0xf6, 0x5a, 0xde, 0x77, 0x7a, 0xf3, 0xe6, 0x9d, 0xda, 0x27, 0xff, + 0xff, 0xf3, 0xff, 0x3d, 0xcf, 0xd3, 0x42, 0x44, 0xb9, 0x48, 0xb9, 0xf0, 0xb6, 0x4c, 0xc8, 0x24, + 0x8b, 0xbd, 0xed, 0x38, 0x64, 0x92, 0x8c, 0x3d, 0xb9, 0xc3, 0xeb, 0x9c, 0x4b, 0x6e, 0xbc, 0x50, + 0x06, 0x5c, 0x1b, 0x70, 0x6d, 0x18, 0x3e, 0x8f, 0x79, 0xcc, 0x2b, 0x8b, 0x57, 0xbe, 0x29, 0xf7, + 0xd0, 0xaa, 0xe3, 0x42, 0x22, 0xd8, 0x35, 0x8b, 0xf2, 0x24, 0x53, 0xba, 0xf3, 0x43, 0x87, 0x2f, + 0x3f, 0x8a, 0x78, 0x96, 0x33, 0x22, 0xd9, 0x67, 0x15, 0x39, 0xa5, 0x94, 0x6f, 0x32, 0x69, 0x2c, + 0x61, 0xff, 0x6b, 0xce, 0xd3, 0x39, 0x89, 0xa2, 0x9c, 0x09, 0x61, 0x02, 0x1b, 0xb8, 0x7d, 0xff, + 0xfd, 0xa5, 0x40, 0x83, 0x3d, 0x49, 0x57, 0x13, 0xe7, 0xb6, 0xea, 0xfc, 0x2b, 0xd0, 0x28, 0x4e, + 0xe4, 0x62, 0x13, 0x62, 0xca, 0x53, 0xaf, 0xe6, 0xaa, 0xc7, 0x48, 0x44, 0x4b, 0x4f, 0xee, 0xd7, + 0x4c, 0xe0, 0x29, 0xa5, 0x53, 0xd5, 0x11, 0xf4, 0xca, 0xfe, 0xba, 0x30, 0x18, 0x84, 0x92, 0x5f, + 0x51, 0x8f, 0x2a, 0xd4, 0xbb, 0x4b, 0x81, 0x9e, 0x29, 0xd4, 0x8d, 0xf6, 0x00, 0xd0, 0x13, 0xc9, + 0x1b, 0x0c, 0x85, 0x6d, 0x92, 0x96, 0xdb, 0x99, 0xba, 0xad, 0xbb, 0xbd, 0x37, 0xaf, 0x70, 0x7d, + 0xce, 0xf2, 0x40, 0xcd, 0x2d, 0xf1, 0x8c, 0x27, 0x99, 0xff, 0xfa, 0x50, 0x20, 0xed, 0xe7, 0x6f, + 0xe4, 0xde, 0x03, 0x56, 0x36, 0x88, 0xa0, 0x8e, 0x36, 0x30, 0xec, 0xb2, 0x2c, 0x9a, 0xcb, 0x24, + 0x65, 0x66, 0xcb, 0x06, 0xae, 0xee, 0x0f, 0x2e, 0x05, 0x7a, 0xaa, 0x36, 0x69, 0x14, 0x27, 0xe8, + 0xb0, 0x2c, 0xfa, 0x94, 0xa4, 0xcc, 0x30, 0x61, 0x27, 0x62, 0x2b, 0xb2, 0x67, 0x91, 0xf9, 0xd8, + 0x06, 0x6e, 0x37, 0x68, 0xca, 0x49, 0xeb, 0xef, 0x77, 0x04, 0xfc, 0x0f, 0x87, 0x93, 0x05, 0x8e, + 0x27, 0x0b, 0xfc, 0x39, 0x59, 0xe0, 0xdb, 0xd9, 0xd2, 0x8e, 0x67, 0x4b, 0xfb, 0x75, 0xb6, 0xb4, + 0x2f, 0xe3, 0x3b, 0x67, 0xdb, 0x79, 0x64, 0x23, 0x17, 0xd7, 0x5f, 0xa9, 0x1a, 0x35, 0x6c, 0x57, + 0x1f, 0xfe, 0xed, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0b, 0x00, 0x09, 0x49, 0x69, 0x02, 0x00, + 0x00, +} + +func (this *MsgCreateVestingAccount) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*MsgCreateVestingAccount) + if !ok { + that2, ok := that.(MsgCreateVestingAccount) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.FromAddress, that1.FromAddress) { + return false + } + if !bytes.Equal(this.ToAddress, that1.ToAddress) { + return false + } + if len(this.Amount) != len(that1.Amount) { + return false + } + for i := range this.Amount { + if !this.Amount[i].Equal(&that1.Amount[i]) { + return false + } + } + if this.EndTime != that1.EndTime { + return false + } + if this.Delayed != that1.Delayed { + return false + } + return true +} +func (m *MsgCreateVestingAccount) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgCreateVestingAccount) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateVestingAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Delayed { + i-- + if m.Delayed { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } + if m.EndTime != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.EndTime)) + i-- + dAtA[i] = 0x20 + } + if len(m.Amount) > 0 { + for iNdEx := len(m.Amount) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Amount[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.ToAddress) > 0 { + i -= len(m.ToAddress) + copy(dAtA[i:], m.ToAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.ToAddress))) + i-- + dAtA[i] = 0x12 + } + if len(m.FromAddress) > 0 { + i -= len(m.FromAddress) + copy(dAtA[i:], m.FromAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.FromAddress))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgCreateVestingAccount) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.FromAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ToAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Amount) > 0 { + for _, e := range m.Amount { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + if m.EndTime != 0 { + n += 1 + sovTx(uint64(m.EndTime)) + } + if m.Delayed { + n += 2 + } + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgCreateVestingAccount) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCreateVestingAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateVestingAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FromAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FromAddress = append(m.FromAddress[:0], dAtA[iNdEx:postIndex]...) + if m.FromAddress == nil { + m.FromAddress = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ToAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ToAddress = append(m.ToAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ToAddress == nil { + m.ToAddress = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Amount = append(m.Amount, types.Coin{}) + if err := m.Amount[len(m.Amount)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EndTime", wireType) + } + m.EndTime = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.EndTime |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Delayed", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Delayed = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/bank/client/cli/cli_test.go b/x/bank/client/cli/cli_test.go index a1f129653a..67f967b44a 100644 --- a/x/bank/client/cli/cli_test.go +++ b/x/bank/client/cli/cli_test.go @@ -5,13 +5,11 @@ import ( "fmt" "testing" - "github.com/cosmos/cosmos-sdk/client" - "github.com/gogo/protobuf/proto" - "github.com/stretchr/testify/suite" tmcli "github.com/tendermint/tendermint/libs/cli" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" "github.com/cosmos/cosmos-sdk/testutil/network" diff --git a/x/bank/client/testutil/cli_helpers.go b/x/bank/client/testutil/cli_helpers.go index f6da9e8d31..a1a33c4f67 100644 --- a/x/bank/client/testutil/cli_helpers.go +++ b/x/bank/client/testutil/cli_helpers.go @@ -5,11 +5,9 @@ import ( "github.com/tendermint/tendermint/libs/cli" - "github.com/cosmos/cosmos-sdk/testutil" - - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/testutil" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/cli" ) diff --git a/x/bank/handler.go b/x/bank/handler.go index 5d4b7fe970..7371412e2d 100644 --- a/x/bank/handler.go +++ b/x/bank/handler.go @@ -35,7 +35,7 @@ func handleMsgSend(ctx sdk.Context, k keeper.Keeper, msg *types.MsgSend) (*sdk.R } if k.BlockedAddr(msg.ToAddress) { - return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive transactions", msg.ToAddress) + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress) } err := k.SendCoins(ctx, msg.FromAddress, msg.ToAddress, msg.Amount) diff --git a/x/upgrade/module.go b/x/upgrade/module.go index 940ee9460c..bc44a49742 100644 --- a/x/upgrade/module.go +++ b/x/upgrade/module.go @@ -5,11 +5,9 @@ import ( "encoding/json" "github.com/gogo/protobuf/grpc" - "github.com/grpc-ecosystem/grpc-gateway/runtime" - "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/spf13/cobra" - abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/client"