From 985efc2fe10b2201f8a3400fdbeead3408f19e75 Mon Sep 17 00:00:00 2001 From: sahith-narahari Date: Mon, 6 Apr 2020 01:00:31 +0530 Subject: [PATCH 1/5] Added proto compatible tx cli for distribution --- x/distribution/client/cli/tx.go | 213 +++++++++++++++++++++++++++++++- 1 file changed, 212 insertions(+), 1 deletion(-) diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index 892058f6b38b..565f586ccadd 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -4,6 +4,7 @@ package cli import ( "bufio" "fmt" + "github.com/cosmos/cosmos-sdk/client/tx" "strings" "github.com/spf13/cobra" @@ -34,7 +35,218 @@ const ( MaxMessagesPerTxDefault = 5 ) +// NewTxCmd returns a root CLI command handler for all x/distribution transaction commands. +func NewTxCmd(storeKey string, m codec.Marshaler, txg tx.Generator, ar tx.AccountRetriever) *cobra.Command { + distTxCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Distribution transactions subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + distTxCmd.AddCommand(flags.PostCommands( + NewWithdrawRewardsCmd(m, txg, ar), + NewWithdrawAllRewardsCmd(m, txg, ar, storeKey), + NewSetWithdrawAddrCmd(m, txg, ar), + NewFundCommunityPoolCmd(m, txg, ar), + )...) + + return distTxCmd +} + +type newGenerateOrBroadcastFunc func(ctx context.CLIContext, txf tx.Factory, msgs ...sdk.Msg) error + +func newSplitAndApply( + newGenerateOrBroadcast newGenerateOrBroadcastFunc, + cliCtx context.CLIContext, + txBldr tx.Factory, + msgs []sdk.Msg, + chunkSize int, +) error { + return nil +} + +func NewWithdrawRewardsCmd(m codec.Marshaler, txg tx.Generator, ar tx.AccountRetriever) *cobra.Command { + 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 cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj --from mykey +$ %s tx distribution withdraw-rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj --from mykey --commission +`, + version.ClientName, version.ClientName, + ), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + inBuf := bufio.NewReader(cmd.InOrStdin()) + txf := tx.NewFactoryFromCLI(inBuf). + WithTxGenerator(txg). + WithAccountRetriever(ar) + + cliCtx := context.NewCLIContextWithInputAndFrom(inBuf, args[0]).WithMarshaler(m) + delAddr := cliCtx.GetFromAddress() + valAddr, err := sdk.ValAddressFromBech32(args[0]) + if err != nil { + return err + } + + msg := []sdk.Msg{types.NewMsgWithdrawDelegatorReward(delAddr, valAddr)} + if viper.GetBool(flagCommission) { + msgs = append(msgs, types.NewMsgWithdrawValidatorCommission(valAddr)) + } + + return tx.GenerateOrBroadcastTx(cliCtx, txf, msgs) + }, + } + cmd.Flags().Bool(flagCommission, false, "also withdraw validator's commission") + return flags.PostCommands(cmd)[0] +} + +func NewWithdrawAllRewardsCmd(m codec.Marshaler, txg tx.Generator, ar tx.AccountRetriever, queryRoute string) *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. + +Example: +$ %s tx distribution withdraw-all-rewards --from mykey +`, + version.ClientName, + ), + ), + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + inBuf := bufio.NewReader(cmd.InOrStdin()) + txf := tx.NewFactoryFromCLI(inBuf). + WithTxGenerator(txg). + WithAccountRetriever(ar) + + cliCtx := context.NewCLIContextWithInputAndFrom(inBuf, args[0]).WithMarshaler(m) + + delAddr := cliCtx.GetFromAddress() + + // The transaction cannot be generated offline since it requires a query + // to get all the validators. + if cliCtx.Offline { + return fmt.Errorf("cannot generate tx in offline mode") + } + + msgs, err := common.WithdrawAllDelegatorRewards(cliCtx, queryRoute, delAddr) + if err != nil { + return err + } + + chunkSize := viper.GetInt(flagMaxMessagesPerTx) + return newSplitAndApply(tx.GenerateOrBroadcastTx, cliCtx, txf, msgs, chunkSize) + + }, + } + return flags.PostCommands(cmd)[0] +} + +func NewSetWithdrawAddrCmd(m codec.Marshaler, txg tx.Generator, ar tx.AccountRetriever) *cobra.Command { + 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 cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p --from mykey +`, + version.ClientName, + ), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + inBuf := bufio.NewReader(cmd.InOrStdin()) + txf := tx.NewFactoryFromCLI(inBuf). + WithTxGenerator(txg). + WithAccountRetriever(ar) + + cliCtx := context.NewCLIContextWithInputAndFrom(inBuf, args[0]).WithMarshaler(m) + + delAddr := cliCtx.GetFromAddress() + withdrawAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + msg := types.NewMsgSetWithdrawAddress(delAddr, withdrawAddr) + return tx.GenerateOrBroadcastTx(cliCtx, txf, msg) + }, + } + return flags.PostCommands(cmd)[0] +} + +func NewFundCommunityPoolCmd(m codec.Marshaler, txg tx.Generator, ar tx.AccountRetriever) *cobra.Command { + cmd := &cobra.Command{ + Use: "community-pool-spend [proposal-file]", + Args: cobra.ExactArgs(1), + Short: "Submit a community pool spend proposal", + Long: strings.TrimSpace( + fmt.Sprintf(`Submit a community pool spend proposal along with an initial deposit. +The proposal details must be supplied via a JSON file. + +Example: +$ %s tx gov submit-proposal community-pool-spend --from= + +Where proposal.json contains: + +{ + "title": "Community Pool Spend", + "description": "Pay me some Atoms!", + "recipient": "cosmos1s5afhd6gxevu37mkqcvvsj8qeylhn0rz46zdlq", + "amount": "1000stake", + "deposit": "1000stake" +} +`, + version.ClientName, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + inBuf := bufio.NewReader(cmd.InOrStdin()) + txf := tx.NewFactoryFromCLI(inBuf). + WithTxGenerator(txg). + WithAccountRetriever(ar) + + cliCtx := context.NewCLIContextWithInputAndFrom(inBuf, args[0]).WithMarshaler(m) + + depositorAddr := cliCtx.GetFromAddress() + amount, err := sdk.ParseCoins(args[0]) + if err != nil { + return err + } + + msg := types.NewMsgFundCommunityPool(amount, depositorAddr) + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTx(cliCtx, txf, msg) + }, + } + return flags.PostCommands(cmd)[0] +} + +// --------------------------------------------------------------------------- +// Deprecated +// +// TODO: Remove once client-side Protobuf migration has been completed. +// --------------------------------------------------------------------------- // GetTxCmd returns the transaction commands for this module +// --------------------------------------------------------------------------- +// Deprecated +// +// TODO: Remove once client-side Protobuf migration has been completed. +// --------------------------------------------------------------------------- func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { distTxCmd := &cobra.Command{ Use: types.ModuleName, @@ -184,7 +396,6 @@ $ %s tx distribution set-withdraw-addr cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75 ), Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - inBuf := bufio.NewReader(cmd.InOrStdin()) txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(authclient.GetTxEncoder(cdc)) cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc) From 00f8f0efff57d0fce178c3e1fa18a8c866e1cdbd Mon Sep 17 00:00:00 2001 From: sahith-narahari Date: Mon, 6 Apr 2020 23:58:32 +0530 Subject: [PATCH 2/5] Added proto compatible rest tx in x/distr --- x/distribution/client/cli/tx.go | 23 ++- x/distribution/client/rest/rest.go | 8 ++ x/distribution/client/rest/tx.go | 224 ++++++++++++++++++++++++++--- 3 files changed, 237 insertions(+), 18 deletions(-) diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index 565f586ccadd..b22f79d0f547 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -64,6 +64,25 @@ func newSplitAndApply( msgs []sdk.Msg, chunkSize int, ) error { + if chunkSize == 0 { + return newGenerateOrBroadcast(cliCtx, txBldr, 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 := newGenerateOrBroadcast(cliCtx, txBldr, msgChunk...); err != nil { + return err + } + } + return nil } @@ -96,12 +115,12 @@ $ %s tx distribution withdraw-rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fx return err } - msg := []sdk.Msg{types.NewMsgWithdrawDelegatorReward(delAddr, valAddr)} + msgs := []sdk.Msg{types.NewMsgWithdrawDelegatorReward(delAddr, valAddr)} if viper.GetBool(flagCommission) { msgs = append(msgs, types.NewMsgWithdrawValidatorCommission(valAddr)) } - return tx.GenerateOrBroadcastTx(cliCtx, txf, msgs) + return tx.GenerateOrBroadcastTx(cliCtx, txf, msgs...) }, } cmd.Flags().Bool(flagCommission, false, "also withdraw validator's commission") diff --git a/x/distribution/client/rest/rest.go b/x/distribution/client/rest/rest.go index ee26ce9544f5..f067a84bd9ee 100644 --- a/x/distribution/client/rest/rest.go +++ b/x/distribution/client/rest/rest.go @@ -1,6 +1,8 @@ package rest import ( + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec" "net/http" "github.com/gorilla/mux" @@ -14,12 +16,18 @@ import ( govrest "github.com/cosmos/cosmos-sdk/x/gov/client/rest" ) +func RegisterHandlers(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator, r *mux.Router, queryRoute string) { + registerQueryRoutes(cliCtx, r, queryRoute) + registerTxHandlers(cliCtx, m, txg, r, queryRoute) +} + // RegisterRoutes register distribution REST routes. func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, queryRoute string) { registerQueryRoutes(cliCtx, r, queryRoute) registerTxRoutes(cliCtx, r, queryRoute) } +// TODO add proto compatible Handler after x/gov migration // ProposalRESTHandler returns a ProposalRESTHandler that exposes the community pool spend REST handler with a given sub-route. func ProposalRESTHandler(cliCtx context.CLIContext) govrest.ProposalRESTHandler { return govrest.ProposalRESTHandler{ diff --git a/x/distribution/client/rest/tx.go b/x/distribution/client/rest/tx.go index 233c92832c78..fa1e53effbc1 100644 --- a/x/distribution/client/rest/tx.go +++ b/x/distribution/client/rest/tx.go @@ -1,6 +1,8 @@ package rest import ( + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec" "net/http" "github.com/gorilla/mux" @@ -14,54 +16,244 @@ import ( "github.com/cosmos/cosmos-sdk/types/rest" ) -func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router, queryRoute string) { +type ( + withdrawRewardsReq struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + } + + setWithdrawalAddrReq struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + WithdrawAddress sdk.AccAddress `json:"withdraw_address" yaml:"withdraw_address"` + } + + fundCommunityPoolReq struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + Amount sdk.Coins `json:"amount" yaml:"amount"` + } +) + +func registerTxHandlers(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator, r *mux.Router, queryRoute string) { // Withdraw all delegator rewards r.HandleFunc( "/distribution/delegators/{delegatorAddr}/rewards", - withdrawDelegatorRewardsHandlerFn(cliCtx, queryRoute), + newWithdrawDelegatorRewardsHandlerFn(cliCtx, m, txg, queryRoute), ).Methods("POST") // Withdraw delegation rewards r.HandleFunc( "/distribution/delegators/{delegatorAddr}/rewards/{validatorAddr}", - withdrawDelegationRewardsHandlerFn(cliCtx), + newWithdrawDelegationRewardsHandlerFn(cliCtx, m, txg), ).Methods("POST") // Replace the rewards withdrawal address r.HandleFunc( "/distribution/delegators/{delegatorAddr}/withdraw_address", - setDelegatorWithdrawalAddrHandlerFn(cliCtx), + newSetDelegatorWithdrawalAddrHandlerFn(cliCtx, m, txg), ).Methods("POST") // Withdraw validator rewards and commission r.HandleFunc( "/distribution/validators/{validatorAddr}/rewards", - withdrawValidatorRewardsHandlerFn(cliCtx), + newWithdrawValidatorRewardsHandlerFn(cliCtx, m, txg), ).Methods("POST") // Fund the community pool r.HandleFunc( "/distribution/community_pool", - fundCommunityPoolHandlerFn(cliCtx), + newFundCommunityPoolHandlerFn(cliCtx, m, txg), ).Methods("POST") +} + +func newWithdrawDelegatorRewardsHandlerFn(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator, queryRoute string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx = cliCtx.WithMarshaler(m) + var req withdrawRewardsReq + if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + // read and validate URL's variables + delAddr, ok := checkDelegatorAddressVar(w, r) + if !ok { + return + } + + msgs, err := common.WithdrawAllDelegatorRewards(cliCtx, queryRoute, delAddr) + if rest.CheckInternalServerError(w, err) { + return + } + + tx.WriteGeneratedTxResponse(cliCtx, w, txg, req.BaseReq, msgs...) + } } -type ( - withdrawRewardsReq struct { - BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` +func newWithdrawDelegationRewardsHandlerFn(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx = cliCtx.WithMarshaler(m) + + var req withdrawRewardsReq + + if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + // read and validate URL's variables + delAddr, ok := checkDelegatorAddressVar(w, r) + if !ok { + return + } + + valAddr, ok := checkValidatorAddressVar(w, r) + if !ok { + return + } + + msg := types.NewMsgWithdrawDelegatorReward(delAddr, valAddr) + if rest.CheckBadRequestError(w, msg.ValidateBasic()) { + return + } + + tx.WriteGeneratedTxResponse(cliCtx, w, txg, req.BaseReq, msg) } +} - setWithdrawalAddrReq struct { - BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` - WithdrawAddress sdk.AccAddress `json:"withdraw_address" yaml:"withdraw_address"` +func newSetDelegatorWithdrawalAddrHandlerFn(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx = cliCtx.WithMarshaler(m) + + var req setWithdrawalAddrReq + + if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + // read and validate URL's variables + delAddr, ok := checkDelegatorAddressVar(w, r) + if !ok { + return + } + + msg := types.NewMsgSetWithdrawAddress(delAddr, req.WithdrawAddress) + if rest.CheckBadRequestError(w, msg.ValidateBasic()) { + return + } + + tx.WriteGeneratedTxResponse(cliCtx, w, txg, req.BaseReq, msg) } +} - fundCommunityPoolReq struct { - BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` - Amount sdk.Coins `json:"amount" yaml:"amount"` +func newWithdrawValidatorRewardsHandlerFn(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx = cliCtx.WithMarshaler(m) + + var req withdrawRewardsReq + + if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + // read and validate URL's variable + valAddr, ok := checkValidatorAddressVar(w, r) + if !ok { + return + } + + // prepare multi-message transaction + msgs, err := common.WithdrawValidatorRewardsAndCommission(valAddr) + if rest.CheckBadRequestError(w, err) { + return + } + + tx.WriteGeneratedTxResponse(cliCtx, w, txg, req.BaseReq, msgs...) } -) +} + +func newFundCommunityPoolHandlerFn(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx = cliCtx.WithMarshaler(m) + + var req fundCommunityPoolReq + if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + fromAddr, err := sdk.AccAddressFromBech32(req.BaseReq.From) + if rest.CheckBadRequestError(w, err) { + return + } + + msg := types.NewMsgFundCommunityPool(req.Amount, fromAddr) + if rest.CheckBadRequestError(w, msg.ValidateBasic()) { + return + } + + tx.WriteGeneratedTxResponse(cliCtx, w, txg, req.BaseReq, msg) + } +} + +// --------------------------------------------------------------------------- +// Deprecated +// +// TODO: Remove once client-side Protobuf migration has been completed. +// --------------------------------------------------------------------------- +func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router, queryRoute string) { + // Withdraw all delegator rewards + r.HandleFunc( + "/distribution/delegators/{delegatorAddr}/rewards", + withdrawDelegatorRewardsHandlerFn(cliCtx, queryRoute), + ).Methods("POST") + + // Withdraw delegation rewards + r.HandleFunc( + "/distribution/delegators/{delegatorAddr}/rewards/{validatorAddr}", + withdrawDelegationRewardsHandlerFn(cliCtx), + ).Methods("POST") + + // Replace the rewards withdrawal address + r.HandleFunc( + "/distribution/delegators/{delegatorAddr}/withdraw_address", + setDelegatorWithdrawalAddrHandlerFn(cliCtx), + ).Methods("POST") + + // Withdraw validator rewards and commission + r.HandleFunc( + "/distribution/validators/{validatorAddr}/rewards", + withdrawValidatorRewardsHandlerFn(cliCtx), + ).Methods("POST") + + // Fund the community pool + r.HandleFunc( + "/distribution/community_pool", + fundCommunityPoolHandlerFn(cliCtx), + ).Methods("POST") + +} // Withdraw delegator rewards func withdrawDelegatorRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc { From 4194f5015a2aa965f5b03332426da295ceb91197 Mon Sep 17 00:00:00 2001 From: sahith-narahari Date: Wed, 8 Apr 2020 01:22:13 +0530 Subject: [PATCH 3/5] Fixed style issues --- x/distribution/client/cli/tx.go | 6 +----- x/distribution/client/rest/tx.go | 8 -------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index b22f79d0f547..8c9963a5811d 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -107,8 +107,8 @@ $ %s tx distribution withdraw-rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fx txf := tx.NewFactoryFromCLI(inBuf). WithTxGenerator(txg). WithAccountRetriever(ar) - cliCtx := context.NewCLIContextWithInputAndFrom(inBuf, args[0]).WithMarshaler(m) + delAddr := cliCtx.GetFromAddress() valAddr, err := sdk.ValAddressFromBech32(args[0]) if err != nil { @@ -146,7 +146,6 @@ $ %s tx distribution withdraw-all-rewards --from mykey txf := tx.NewFactoryFromCLI(inBuf). WithTxGenerator(txg). WithAccountRetriever(ar) - cliCtx := context.NewCLIContextWithInputAndFrom(inBuf, args[0]).WithMarshaler(m) delAddr := cliCtx.GetFromAddress() @@ -164,7 +163,6 @@ $ %s tx distribution withdraw-all-rewards --from mykey chunkSize := viper.GetInt(flagMaxMessagesPerTx) return newSplitAndApply(tx.GenerateOrBroadcastTx, cliCtx, txf, msgs, chunkSize) - }, } return flags.PostCommands(cmd)[0] @@ -189,7 +187,6 @@ $ %s tx distribution set-withdraw-addr cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75 txf := tx.NewFactoryFromCLI(inBuf). WithTxGenerator(txg). WithAccountRetriever(ar) - cliCtx := context.NewCLIContextWithInputAndFrom(inBuf, args[0]).WithMarshaler(m) delAddr := cliCtx.GetFromAddress() @@ -235,7 +232,6 @@ Where proposal.json contains: txf := tx.NewFactoryFromCLI(inBuf). WithTxGenerator(txg). WithAccountRetriever(ar) - cliCtx := context.NewCLIContextWithInputAndFrom(inBuf, args[0]).WithMarshaler(m) depositorAddr := cliCtx.GetFromAddress() diff --git a/x/distribution/client/rest/tx.go b/x/distribution/client/rest/tx.go index fa1e53effbc1..a3f59cf75615 100644 --- a/x/distribution/client/rest/tx.go +++ b/x/distribution/client/rest/tx.go @@ -67,7 +67,6 @@ func registerTxHandlers(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Gen func newWithdrawDelegatorRewardsHandlerFn(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator, queryRoute string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { cliCtx = cliCtx.WithMarshaler(m) - var req withdrawRewardsReq if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { return @@ -96,9 +95,7 @@ func newWithdrawDelegatorRewardsHandlerFn(cliCtx context.CLIContext, m codec.Mar func newWithdrawDelegationRewardsHandlerFn(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { cliCtx = cliCtx.WithMarshaler(m) - var req withdrawRewardsReq - if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { return } @@ -131,9 +128,7 @@ func newWithdrawDelegationRewardsHandlerFn(cliCtx context.CLIContext, m codec.Ma func newSetDelegatorWithdrawalAddrHandlerFn(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { cliCtx = cliCtx.WithMarshaler(m) - var req setWithdrawalAddrReq - if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { return } @@ -161,9 +156,7 @@ func newSetDelegatorWithdrawalAddrHandlerFn(cliCtx context.CLIContext, m codec.M func newWithdrawValidatorRewardsHandlerFn(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { cliCtx = cliCtx.WithMarshaler(m) - var req withdrawRewardsReq - if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { return } @@ -192,7 +185,6 @@ func newWithdrawValidatorRewardsHandlerFn(cliCtx context.CLIContext, m codec.Mar func newFundCommunityPoolHandlerFn(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { cliCtx = cliCtx.WithMarshaler(m) - var req fundCommunityPoolReq if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { return From bc4721234dc2d052b86b1b04f41cd8135a392fda Mon Sep 17 00:00:00 2001 From: sahith-narahari Date: Wed, 8 Apr 2020 16:45:58 +0530 Subject: [PATCH 4/5] Added validation to messages --- x/distribution/client/cli/tx.go | 23 +++++++------ x/distribution/client/rest/query.go | 50 ++++++++++++++--------------- x/distribution/client/rest/rest.go | 8 ++--- x/distribution/client/rest/tx.go | 8 ++--- 4 files changed, 47 insertions(+), 42 deletions(-) diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index 8c9963a5811d..5856119e4a02 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -36,7 +36,7 @@ const ( ) // NewTxCmd returns a root CLI command handler for all x/distribution transaction commands. -func NewTxCmd(storeKey string, m codec.Marshaler, txg tx.Generator, ar tx.AccountRetriever) *cobra.Command { +func NewTxCmd(m codec.Marshaler, txg tx.Generator, ar tx.AccountRetriever) *cobra.Command { distTxCmd := &cobra.Command{ Use: types.ModuleName, Short: "Distribution transactions subcommands", @@ -47,7 +47,7 @@ func NewTxCmd(storeKey string, m codec.Marshaler, txg tx.Generator, ar tx.Accoun distTxCmd.AddCommand(flags.PostCommands( NewWithdrawRewardsCmd(m, txg, ar), - NewWithdrawAllRewardsCmd(m, txg, ar, storeKey), + NewWithdrawAllRewardsCmd(m, txg, ar), NewSetWithdrawAddrCmd(m, txg, ar), NewFundCommunityPoolCmd(m, txg, ar), )...) @@ -116,6 +116,12 @@ $ %s tx distribution withdraw-rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fx } msgs := []sdk.Msg{types.NewMsgWithdrawDelegatorReward(delAddr, valAddr)} + for _, msg := range msgs { + if err := msg.ValidateBasic(); err != nil { + return err + } + } + if viper.GetBool(flagCommission) { msgs = append(msgs, types.NewMsgWithdrawValidatorCommission(valAddr)) } @@ -127,7 +133,7 @@ $ %s tx distribution withdraw-rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fx return flags.PostCommands(cmd)[0] } -func NewWithdrawAllRewardsCmd(m codec.Marshaler, txg tx.Generator, ar tx.AccountRetriever, queryRoute string) *cobra.Command { +func NewWithdrawAllRewardsCmd(m codec.Marshaler, txg tx.Generator, ar tx.AccountRetriever) *cobra.Command { cmd := &cobra.Command{ Use: "withdraw-all-rewards", Short: "withdraw all delegations rewards for a delegator", @@ -156,7 +162,7 @@ $ %s tx distribution withdraw-all-rewards --from mykey return fmt.Errorf("cannot generate tx in offline mode") } - msgs, err := common.WithdrawAllDelegatorRewards(cliCtx, queryRoute, delAddr) + msgs, err := common.WithdrawAllDelegatorRewards(cliCtx, types.QuerierRoute, delAddr) if err != nil { return err } @@ -196,6 +202,10 @@ $ %s tx distribution set-withdraw-addr cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75 } msg := types.NewMsgSetWithdrawAddress(delAddr, withdrawAddr) + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTx(cliCtx, txf, msg) }, } @@ -257,11 +267,6 @@ Where proposal.json contains: // TODO: Remove once client-side Protobuf migration has been completed. // --------------------------------------------------------------------------- // GetTxCmd returns the transaction commands for this module -// --------------------------------------------------------------------------- -// Deprecated -// -// TODO: Remove once client-side Protobuf migration has been completed. -// --------------------------------------------------------------------------- func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { distTxCmd := &cobra.Command{ Use: types.ModuleName, diff --git a/x/distribution/client/rest/query.go b/x/distribution/client/rest/query.go index 1d614c17fe6a..4f0c203ee721 100644 --- a/x/distribution/client/rest/query.go +++ b/x/distribution/client/rest/query.go @@ -14,59 +14,59 @@ import ( "github.com/cosmos/cosmos-sdk/types/rest" ) -func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, queryRoute string) { +func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) { // Get the total rewards balance from all delegations r.HandleFunc( "/distribution/delegators/{delegatorAddr}/rewards", - delegatorRewardsHandlerFn(cliCtx, queryRoute), + delegatorRewardsHandlerFn(cliCtx), ).Methods("GET") // Query a delegation reward r.HandleFunc( "/distribution/delegators/{delegatorAddr}/rewards/{validatorAddr}", - delegationRewardsHandlerFn(cliCtx, queryRoute), + delegationRewardsHandlerFn(cliCtx), ).Methods("GET") // Get the rewards withdrawal address r.HandleFunc( "/distribution/delegators/{delegatorAddr}/withdraw_address", - delegatorWithdrawalAddrHandlerFn(cliCtx, queryRoute), + delegatorWithdrawalAddrHandlerFn(cliCtx), ).Methods("GET") // Validator distribution information r.HandleFunc( "/distribution/validators/{validatorAddr}", - validatorInfoHandlerFn(cliCtx, queryRoute), + validatorInfoHandlerFn(cliCtx), ).Methods("GET") // Commission and self-delegation rewards of a single a validator r.HandleFunc( "/distribution/validators/{validatorAddr}/rewards", - validatorRewardsHandlerFn(cliCtx, queryRoute), + validatorRewardsHandlerFn(cliCtx), ).Methods("GET") // Outstanding rewards of a single validator r.HandleFunc( "/distribution/validators/{validatorAddr}/outstanding_rewards", - outstandingRewardsHandlerFn(cliCtx, queryRoute), + outstandingRewardsHandlerFn(cliCtx), ).Methods("GET") // Get the current distribution parameter values r.HandleFunc( "/distribution/parameters", - paramsHandlerFn(cliCtx, queryRoute), + paramsHandlerFn(cliCtx), ).Methods("GET") // Get the amount held in the community pool r.HandleFunc( "/distribution/community_pool", - communityPoolHandler(cliCtx, queryRoute), + communityPoolHandler(cliCtx), ).Methods("GET") } // HTTP request handler to query the total rewards balance from all delegations -func delegatorRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc { +func delegatorRewardsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) if !ok { @@ -85,7 +85,7 @@ func delegatorRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) htt return } - route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryDelegatorTotalRewards) + route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryDelegatorTotalRewards) res, height, err := cliCtx.QueryWithData(route, bz) if rest.CheckInternalServerError(w, err) { return @@ -97,7 +97,7 @@ func delegatorRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) htt } // HTTP request handler to query a delegation rewards -func delegationRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc { +func delegationRewardsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) if !ok { @@ -108,7 +108,7 @@ func delegationRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) ht valAddr := mux.Vars(r)["validatorAddr"] // query for rewards from a particular delegation - res, height, ok := checkResponseQueryDelegationRewards(w, cliCtx, queryRoute, delAddr, valAddr) + res, height, ok := checkResponseQueryDelegationRewards(w, cliCtx, types.QuerierRoute, delAddr, valAddr) if !ok { return } @@ -119,7 +119,7 @@ func delegationRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) ht } // HTTP request handler to query a delegation rewards -func delegatorWithdrawalAddrHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc { +func delegatorWithdrawalAddrHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { delegatorAddr, ok := checkDelegatorAddressVar(w, r) if !ok { @@ -132,7 +132,7 @@ func delegatorWithdrawalAddrHandlerFn(cliCtx context.CLIContext, queryRoute stri } bz := cliCtx.Codec.MustMarshalJSON(types.NewQueryDelegatorWithdrawAddrParams(delegatorAddr)) - res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/withdraw_addr", queryRoute), bz) + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/withdraw_addr", types.QuerierRoute), bz) if rest.CheckInternalServerError(w, err) { return } @@ -161,7 +161,7 @@ func NewValidatorDistInfo(operatorAddr sdk.AccAddress, rewards sdk.DecCoins, } // HTTP request handler to query validator's distribution information -func validatorInfoHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc { +func validatorInfoHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { valAddr, ok := checkValidatorAddressVar(w, r) if !ok { @@ -174,7 +174,7 @@ func validatorInfoHandlerFn(cliCtx context.CLIContext, queryRoute string) http.H } // query commission - bz, err := common.QueryValidatorCommission(cliCtx, queryRoute, valAddr) + bz, err := common.QueryValidatorCommission(cliCtx, types.QuerierRoute, valAddr) if rest.CheckInternalServerError(w, err) { return } @@ -186,7 +186,7 @@ func validatorInfoHandlerFn(cliCtx context.CLIContext, queryRoute string) http.H // self bond rewards delAddr := sdk.AccAddress(valAddr) - bz, height, ok := checkResponseQueryDelegationRewards(w, cliCtx, queryRoute, delAddr.String(), valAddr.String()) + bz, height, ok := checkResponseQueryDelegationRewards(w, cliCtx, types.QuerierRoute, delAddr.String(), valAddr.String()) if !ok { return } @@ -207,7 +207,7 @@ func validatorInfoHandlerFn(cliCtx context.CLIContext, queryRoute string) http.H } // HTTP request handler to query validator's commission and self-delegation rewards -func validatorRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc { +func validatorRewardsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { valAddr := mux.Vars(r)["validatorAddr"] validatorAddr, ok := checkValidatorAddressVar(w, r) @@ -221,7 +221,7 @@ func validatorRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) htt } delAddr := sdk.AccAddress(validatorAddr).String() - bz, height, ok := checkResponseQueryDelegationRewards(w, cliCtx, queryRoute, delAddr, valAddr) + bz, height, ok := checkResponseQueryDelegationRewards(w, cliCtx, types.QuerierRoute, delAddr, valAddr) if !ok { return } @@ -232,7 +232,7 @@ func validatorRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) htt } // HTTP request handler to query the distribution params values -func paramsHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc { +func paramsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) if !ok { @@ -250,14 +250,14 @@ func paramsHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerF } } -func communityPoolHandler(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc { +func communityPoolHandler(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) if !ok { return } - res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/community_pool", queryRoute), nil) + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/community_pool", types.QuerierRoute), nil) if rest.CheckInternalServerError(w, err) { return } @@ -273,7 +273,7 @@ func communityPoolHandler(cliCtx context.CLIContext, queryRoute string) http.Han } // HTTP request handler to query the outstanding rewards -func outstandingRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc { +func outstandingRewardsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { validatorAddr, ok := checkValidatorAddressVar(w, r) if !ok { @@ -286,7 +286,7 @@ func outstandingRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) h } bin := cliCtx.Codec.MustMarshalJSON(types.NewQueryValidatorOutstandingRewardsParams(validatorAddr)) - res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/validator_outstanding_rewards", queryRoute), bin) + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/validator_outstanding_rewards", types.QuerierRoute), bin) if rest.CheckInternalServerError(w, err) { return } diff --git a/x/distribution/client/rest/rest.go b/x/distribution/client/rest/rest.go index f067a84bd9ee..02fe286f9f65 100644 --- a/x/distribution/client/rest/rest.go +++ b/x/distribution/client/rest/rest.go @@ -16,14 +16,14 @@ import ( govrest "github.com/cosmos/cosmos-sdk/x/gov/client/rest" ) -func RegisterHandlers(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator, r *mux.Router, queryRoute string) { - registerQueryRoutes(cliCtx, r, queryRoute) - registerTxHandlers(cliCtx, m, txg, r, queryRoute) +func RegisterHandlers(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator, r *mux.Router) { + registerQueryRoutes(cliCtx, r) + registerTxHandlers(cliCtx, m, txg, r) } // RegisterRoutes register distribution REST routes. func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, queryRoute string) { - registerQueryRoutes(cliCtx, r, queryRoute) + registerQueryRoutes(cliCtx, r) registerTxRoutes(cliCtx, r, queryRoute) } diff --git a/x/distribution/client/rest/tx.go b/x/distribution/client/rest/tx.go index a3f59cf75615..28be05d77f52 100644 --- a/x/distribution/client/rest/tx.go +++ b/x/distribution/client/rest/tx.go @@ -32,11 +32,11 @@ type ( } ) -func registerTxHandlers(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator, r *mux.Router, queryRoute string) { +func registerTxHandlers(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator, r *mux.Router) { // Withdraw all delegator rewards r.HandleFunc( "/distribution/delegators/{delegatorAddr}/rewards", - newWithdrawDelegatorRewardsHandlerFn(cliCtx, m, txg, queryRoute), + newWithdrawDelegatorRewardsHandlerFn(cliCtx, m, txg), ).Methods("POST") // Withdraw delegation rewards @@ -64,7 +64,7 @@ func registerTxHandlers(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Gen ).Methods("POST") } -func newWithdrawDelegatorRewardsHandlerFn(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator, queryRoute string) http.HandlerFunc { +func newWithdrawDelegatorRewardsHandlerFn(cliCtx context.CLIContext, m codec.Marshaler, txg tx.Generator) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { cliCtx = cliCtx.WithMarshaler(m) var req withdrawRewardsReq @@ -83,7 +83,7 @@ func newWithdrawDelegatorRewardsHandlerFn(cliCtx context.CLIContext, m codec.Mar return } - msgs, err := common.WithdrawAllDelegatorRewards(cliCtx, queryRoute, delAddr) + msgs, err := common.WithdrawAllDelegatorRewards(cliCtx, types.QuerierRoute, delAddr) if rest.CheckInternalServerError(w, err) { return } From a13e41d2dee23ac5452881db38e07dd07db48e75 Mon Sep 17 00:00:00 2001 From: sahith-narahari Date: Wed, 8 Apr 2020 17:04:59 +0530 Subject: [PATCH 5/5] Fixed message validation --- x/distribution/client/cli/tx.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index 5856119e4a02..4c2a055ac9e2 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -116,16 +116,16 @@ $ %s tx distribution withdraw-rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fx } msgs := []sdk.Msg{types.NewMsgWithdrawDelegatorReward(delAddr, valAddr)} + if viper.GetBool(flagCommission) { + msgs = append(msgs, types.NewMsgWithdrawValidatorCommission(valAddr)) + } + for _, msg := range msgs { if err := msg.ValidateBasic(); err != nil { return err } } - if viper.GetBool(flagCommission) { - msgs = append(msgs, types.NewMsgWithdrawValidatorCommission(valAddr)) - } - return tx.GenerateOrBroadcastTx(cliCtx, txf, msgs...) }, }