Merge PR #2537: Staking REST utils refactor and querier tests (pt 1 redelegation PR)

This commit is contained in:
Federico Kunze 2018-10-20 00:49:10 +02:00 committed by Christopher Goes
parent b48d0d5623
commit 57277d1143
8 changed files with 173 additions and 216 deletions

View File

@ -7,7 +7,7 @@
BUG FIXES
* Tendermint
- Fix unbounded consensus WAL growth
- Fix unbounded consensus WAL growth
## 0.24.1

View File

@ -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

View File

@ -112,4 +112,4 @@ much as possible with its [counterpart in the Tendermint Core repo](https://gith
4. Compile gaiacli
```
make install
```
```

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}

View File

@ -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