From 57277d11431a7cd1de313ef9325446dfcd5a057c Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Sat, 20 Oct 2018 00:49:10 +0200 Subject: [PATCH] Merge PR #2537: Staking REST utils refactor and querier tests (pt 1 redelegation PR) --- CHANGELOG.md | 2 +- PENDING.md | 1 + docs/DOCS_README.md | 2 +- x/stake/client/rest/query.go | 231 +++--------------------------- x/stake/client/rest/tx.go | 4 +- x/stake/client/rest/utils.go | 68 +++++++++ x/stake/querier/queryable_test.go | 77 ++++++++++ x/stake/types/delegation.go | 4 +- 8 files changed, 173 insertions(+), 216 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb5d1e639..d72440bae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ BUG FIXES * Tendermint - - Fix unbounded consensus WAL growth + - Fix unbounded consensus WAL growth ## 0.24.1 diff --git a/PENDING.md b/PENDING.md index 76c575368..3a92041c3 100644 --- a/PENDING.md +++ b/PENDING.md @@ -154,6 +154,7 @@ IMPROVEMENTS * [x/stake] [\#2000](https://github.com/cosmos/cosmos-sdk/issues/2000) Added tests for new staking endpoints * [gaia-lite] [\#2445](https://github.com/cosmos/cosmos-sdk/issues/2445) Standarized REST error responses * [gaia-lite] Added example to Swagger specification for /keys/seed. + * [x/stake] Refactor REST utils * Gaia CLI (`gaiacli`) * [cli] #2060 removed `--select` from `block` command diff --git a/docs/DOCS_README.md b/docs/DOCS_README.md index 59a1c9b6d..48a31c2ea 100644 --- a/docs/DOCS_README.md +++ b/docs/DOCS_README.md @@ -112,4 +112,4 @@ much as possible with its [counterpart in the Tendermint Core repo](https://gith 4. Compile gaiacli ``` make install - ``` \ No newline at end of file + ``` diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index 1995efcf6..0398119d8 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -58,74 +58,41 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Co // Get all validators r.HandleFunc( "/stake/validators", - validatorsHandlerFn(cliCtx), + validatorsHandlerFn(cliCtx, cdc), ).Methods("GET") // Get a single validator info r.HandleFunc( - "/stake/validators/{addr}", + "/stake/validators/{validatorAddr}", validatorHandlerFn(cliCtx, cdc), ).Methods("GET") // Get the current state of the staking pool r.HandleFunc( "/stake/pool", - poolHandlerFn(cliCtx), + poolHandlerFn(cliCtx, cdc), ).Methods("GET") // Get the current staking parameter values r.HandleFunc( "/stake/parameters", - paramsHandlerFn(cliCtx), + paramsHandlerFn(cliCtx, cdc), ).Methods("GET") } // HTTP request handler to query a delegator delegations func delegatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - - vars := mux.Vars(r) - bech32delegator := vars["delegatorAddr"] - - w.Header().Set("Content-Type", "application/json") - - delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) - if err != nil { - utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } - - params := stake.QueryDelegatorParams{ - DelegatorAddr: delegatorAddr, - } - - bz, err := cdc.MarshalJSON(params) - if err != nil { - utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } - - res, err := cliCtx.QueryWithData("custom/stake/delegator", bz) - if err != nil { - utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) - return - } - - w.Write(res) - } + return queryDelegator(cliCtx, cdc, "custom/stake/delegator") } // HTTP request handler to query all staking txs (msgs) from a delegator func delegatorTxsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var output []byte var typesQuerySlice []string vars := mux.Vars(r) delegatorAddr := vars["delegatorAddr"] - w.Header().Set("Content-Type", "application/json") - _, err := sdk.AccAddressFromBech32(delegatorAddr) if err != nil { utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) @@ -134,8 +101,7 @@ func delegatorTxsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Han node, err := cliCtx.GetNode() if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } @@ -182,198 +148,52 @@ func delegatorTxsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Han txs = append(txs, foundTxs...) } - output, err = cdc.MarshalJSON(txs) + res, err := cdc.MarshalJSON(txs) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - w.Write(output) + utils.PostProcessResponse(w, cdc, res, cliCtx.Indent) } } // HTTP request handler to query an unbonding-delegation func unbondingDelegationHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - bech32delegator := vars["delegatorAddr"] - bech32validator := vars["validatorAddr"] - - w.Header().Set("Content-Type", "application/json") - - delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) - if err != nil { - utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } - - validatorAddr, err := sdk.ValAddressFromBech32(bech32validator) - if err != nil { - utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } - - params := stake.QueryBondsParams{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, - } - - bz, err := cdc.MarshalJSON(params) - if err != nil { - utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } - - res, err := cliCtx.QueryWithData("custom/stake/unbondingDelegation", bz) - if err != nil { - utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) - return - } - - w.Write(res) - } + return queryBonds(cliCtx, cdc, "custom/stake/unbondingDelegation") } -// HTTP request handler to query a bonded validator +// HTTP request handler to query a delegation func delegationHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - // read parameters - vars := mux.Vars(r) - bech32delegator := vars["delegatorAddr"] - bech32validator := vars["validatorAddr"] - - w.Header().Set("Content-Type", "application/json") - - delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) - if err != nil { - utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } - - validatorAddr, err := sdk.ValAddressFromBech32(bech32validator) - if err != nil { - utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } - - params := stake.QueryBondsParams{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, - } - - bz, err := cdc.MarshalJSON(params) - if err != nil { - utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } - - res, err := cliCtx.QueryWithData("custom/stake/delegation", bz) - if err != nil { - utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) - return - } - - w.Write(res) - } + return queryBonds(cliCtx, cdc, "custom/stake/delegation") } // HTTP request handler to query all delegator bonded validators func delegatorValidatorsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - // read parameters - vars := mux.Vars(r) - bech32delegator := vars["delegatorAddr"] - - w.Header().Set("Content-Type", "application/json") - - delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) - if err != nil { - utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } - - params := stake.QueryDelegatorParams{ - DelegatorAddr: delegatorAddr, - } - - bz, err := cdc.MarshalJSON(params) - if err != nil { - utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } - - res, err := cliCtx.QueryWithData("custom/stake/delegatorValidators", bz) - if err != nil { - utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) - return - } - - w.Write(res) - } + return queryDelegator(cliCtx, cdc, "custom/stake/delegatorValidators") } // HTTP request handler to get information from a currently bonded validator func delegatorValidatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - - vars := mux.Vars(r) - bech32delegator := vars["delegatorAddr"] - bech32validator := vars["validatorAddr"] - - w.Header().Set("Content-Type", "application/json") - - delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) - validatorAddr, err := sdk.ValAddressFromBech32(bech32validator) - if err != nil { - utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } - - params := stake.QueryBondsParams{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, - } - - bz, err := cdc.MarshalJSON(params) - if err != nil { - utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return - } - - res, err := cliCtx.QueryWithData("custom/stake/delegatorValidator", bz) - if err != nil { - utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) - return - } - - w.Write(res) - } + return queryBonds(cliCtx, cdc, "custom/stake/delegatorValidator") } // HTTP request handler to query list of validators -func validatorsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { +func validatorsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - - w.Header().Set("Content-Type", "application/json") - res, err := cliCtx.QueryWithData("custom/stake/validators", nil) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - - w.Header().Set("Content-Type", "application/json") - w.Write(res) + utils.PostProcessResponse(w, cdc, res, cliCtx.Indent) } } // HTTP request handler to query the validator information from a given validator address func validatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - bech32validatorAddr := vars["addr"] - - w.Header().Set("Content-Type", "application/json") + bech32validatorAddr := vars["validatorAddr"] validatorAddr, err := sdk.ValAddressFromBech32(bech32validatorAddr) if err != nil { @@ -396,39 +216,30 @@ func validatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Handle utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - - w.Write(res) + utils.PostProcessResponse(w, cdc, res, cliCtx.Indent) } } // HTTP request handler to query the pool information -func poolHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { +func poolHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - - w.Header().Set("Content-Type", "application/json") - res, err := cliCtx.QueryWithData("custom/stake/pool", nil) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - - w.Write(res) + utils.PostProcessResponse(w, cdc, res, cliCtx.Indent) } } // HTTP request handler to query the staking params values -func paramsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { +func paramsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - - w.Header().Set("Content-Type", "application/json") - res, err := cliCtx.QueryWithData("custom/stake/parameters", nil) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - - w.Write(res) + utils.PostProcessResponse(w, cdc, res, cliCtx.Indent) } } diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index ae991dd4b..e4fd6a1a3 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -262,12 +262,12 @@ func delegationsRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx conte results[i] = res } - output, err := codec.MarshalJSONIndent(cdc, results[:]) + res, err := codec.MarshalJSONIndent(cdc, results[:]) if err != nil { utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - w.Write(output) + utils.PostProcessResponse(w, cdc, res, cliCtx.Indent) } } diff --git a/x/stake/client/rest/utils.go b/x/stake/client/rest/utils.go index e7b8891ea..477432032 100644 --- a/x/stake/client/rest/utils.go +++ b/x/stake/client/rest/utils.go @@ -2,11 +2,16 @@ package rest import ( "fmt" + "net/http" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/client/utils" "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/x/stake/tags" + "github.com/gorilla/mux" rpcclient "github.com/tendermint/tendermint/rpc/client" ) @@ -43,3 +48,66 @@ func queryTxs(node rpcclient.Client, cliCtx context.CLIContext, cdc *codec.Codec return tx.FormatTxResults(cdc, res.Txs) } + +func queryBonds(cliCtx context.CLIContext, cdc *codec.Codec, endpoint string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + bech32delegator := vars["delegatorAddr"] + bech32validator := vars["validatorAddr"] + + delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) + validatorAddr, err := sdk.ValAddressFromBech32(bech32validator) + if err != nil { + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + params := stake.QueryBondsParams{ + DelegatorAddr: delegatorAddr, + ValidatorAddr: validatorAddr, + } + + bz, err := cdc.MarshalJSON(params) + if err != nil { + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + res, err := cliCtx.QueryWithData(endpoint, bz) + if err != nil { + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + utils.PostProcessResponse(w, cdc, res, cliCtx.Indent) + } +} + +func queryDelegator(cliCtx context.CLIContext, cdc *codec.Codec, endpoint string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + bech32delegator := vars["delegatorAddr"] + + delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) + if err != nil { + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + params := stake.QueryDelegatorParams{ + DelegatorAddr: delegatorAddr, + } + + bz, err := cdc.MarshalJSON(params) + if err != nil { + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + res, err := cliCtx.QueryWithData(endpoint, bz) + if err != nil { + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + utils.PostProcessResponse(w, cdc, res, cliCtx.Indent) + } +} diff --git a/x/stake/querier/queryable_test.go b/x/stake/querier/queryable_test.go index d950f90bf..1d76da90d 100644 --- a/x/stake/querier/queryable_test.go +++ b/x/stake/querier/queryable_test.go @@ -36,6 +36,53 @@ func newTestBondQuery(delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress } } +func TestNewQuerier(t *testing.T) { + cdc := codec.New() + ctx, _, keeper := keep.CreateTestInput(t, false, 1000) + pool := keeper.GetPool(ctx) + // Create Validators + amts := []sdk.Int{sdk.NewInt(9), sdk.NewInt(8)} + var validators [2]types.Validator + for i, amt := range amts { + validators[i] = types.NewValidator(sdk.ValAddress(keep.Addrs[i]), keep.PKs[i], types.Description{}) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + validators[i].BondIntraTxCounter = int16(i) + keeper.SetValidator(ctx, validators[i]) + keeper.SetValidatorByPowerIndex(ctx, validators[i], pool) + } + keeper.SetPool(ctx, pool) + + query := abci.RequestQuery{ + Path: "", + Data: []byte{}, + } + + querier := NewQuerier(keeper, cdc) + + bz, err := querier(ctx, []string{"other"}, query) + require.NotNil(t, err) + require.Nil(t, bz) + + _, err = querier(ctx, []string{"validators"}, query) + require.Nil(t, err) + + _, err = querier(ctx, []string{"pool"}, query) + require.Nil(t, err) + + _, err = querier(ctx, []string{"parameters"}, query) + require.Nil(t, err) + + queryParams := newTestValidatorQuery(addrVal1) + bz, errRes := cdc.MarshalJSON(queryParams) + require.Nil(t, errRes) + + query.Path = "/custom/stake/validator" + query.Data = bz + + _, err = querier(ctx, []string{"validator"}, query) + require.Nil(t, err) +} + func TestQueryParametersPool(t *testing.T) { cdc := codec.New() ctx, _, keeper := keep.CreateTestInput(t, false, 1000) @@ -144,6 +191,12 @@ func TestQueryDelegation(t *testing.T) { require.Equal(t, len(delValidators), len(validatorsResp)) require.ElementsMatch(t, delValidators, validatorsResp) + // error unknown request + query.Data = bz[:len(bz)-1] + + _, err = queryDelegatorValidators(ctx, cdc, query, keeper) + require.NotNil(t, err) + // Query bonded validator queryBondParams := newTestBondQuery(addrAcc2, addrVal1) bz, errRes = cdc.MarshalJSON(queryBondParams) @@ -163,6 +216,12 @@ func TestQueryDelegation(t *testing.T) { require.Equal(t, delValidators[0], validator) + // error unknown request + query.Data = bz[:len(bz)-1] + + _, err = queryDelegatorValidator(ctx, cdc, query, keeper) + require.NotNil(t, err) + // Query delegation query = abci.RequestQuery{ @@ -182,6 +241,12 @@ func TestQueryDelegation(t *testing.T) { require.Equal(t, delegation, delegationRes) + // error unknown request + query.Data = bz[:len(bz)-1] + + _, err = queryDelegation(ctx, cdc, query, keeper) + require.NotNil(t, err) + // Query unbonging delegation keeper.BeginUnbonding(ctx, addrAcc2, val1.OperatorAddr, sdk.NewDec(10)) @@ -202,6 +267,12 @@ func TestQueryDelegation(t *testing.T) { require.Equal(t, unbond, unbondRes) + // error unknown request + query.Data = bz[:len(bz)-1] + + _, err = queryUnbondingDelegation(ctx, cdc, query, keeper) + require.NotNil(t, err) + // Query Delegator Summary query = abci.RequestQuery{ @@ -217,4 +288,10 @@ func TestQueryDelegation(t *testing.T) { require.Nil(t, errRes) require.Equal(t, unbond, summary.UnbondingDelegations[0]) + + // error unknown request + query.Data = bz[:len(bz)-1] + + _, err = queryDelegator(ctx, cdc, query, keeper) + require.NotNil(t, err) } diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index d38911521..1b51e00ac 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -115,7 +115,7 @@ func (d Delegation) HumanReadableString() (string, error) { resp := "Delegation \n" resp += fmt.Sprintf("Delegator: %s\n", d.DelegatorAddr) resp += fmt.Sprintf("Validator: %s\n", d.ValidatorAddr) - resp += fmt.Sprintf("Shares: %s", d.Shares.String()) + resp += fmt.Sprintf("Shares: %s\n", d.Shares.String()) resp += fmt.Sprintf("Height: %d", d.Height) return resp, nil @@ -297,7 +297,7 @@ func (d Redelegation) HumanReadableString() (string, error) { resp += fmt.Sprintf("Destination Validator: %s\n", d.ValidatorDstAddr) resp += fmt.Sprintf("Creation height: %v\n", d.CreationHeight) resp += fmt.Sprintf("Min time to unbond (unix): %v\n", d.MinTime) - resp += fmt.Sprintf("Source shares: %s", d.SharesSrc.String()) + resp += fmt.Sprintf("Source shares: %s\n", d.SharesSrc.String()) resp += fmt.Sprintf("Destination shares: %s", d.SharesDst.String()) return resp, nil