Merge PR #4183: Cherry pick 4181 into v0.34.2
* Support pagination and status query params for /staking/validators * Rename BondStatusToString to String * Cherry pick 4181 * Remove pending log
This commit is contained in:
parent
66a913c205
commit
94bc55ef4f
|
@ -16,6 +16,8 @@ to generate only usage.
|
|||
* [\#4135](https://github.com/cosmos/cosmos-sdk/pull/4135) Fix `NewResponseFormatBroadcastTxCommit`
|
||||
* [\#4053](https://github.com/cosmos/cosmos-sdk/issues/4053) Add `--inv-check-period`
|
||||
flag to gaiad to set period at which invariants checks will run.
|
||||
* [\#4099](https://github.com/cosmos/cosmos-sdk/issues/4099) Update the /staking/validators endpoint to support
|
||||
status and pagination query flags.
|
||||
|
||||
## 0.34.1
|
||||
|
||||
|
|
|
@ -763,7 +763,23 @@ paths:
|
|||
description: Internal Server Error
|
||||
/staking/validators:
|
||||
get:
|
||||
summary: Get all validator candidates
|
||||
summary: Get all validator candidates. By default it returns only the bonded validators.
|
||||
parameters:
|
||||
- in: query
|
||||
name: status
|
||||
type: string
|
||||
description: The validator bond status. Must be either 'bonded', 'unbonded', or 'unbonding'.
|
||||
x-example: bonded
|
||||
- in: query
|
||||
name: page
|
||||
description: The gage number.
|
||||
type: integer
|
||||
x-example: 1
|
||||
- in: query
|
||||
name: limit
|
||||
description: The maximum number of items per page.
|
||||
type: integer
|
||||
x-example: 1
|
||||
tags:
|
||||
- ICS21
|
||||
produces:
|
||||
|
|
|
@ -162,7 +162,6 @@ func QueryTxsByTagsRequestHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec)
|
|||
}
|
||||
|
||||
tags, page, limit, err = rest.ParseHTTPArgs(r)
|
||||
|
||||
if err != nil {
|
||||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
|
|
|
@ -25,19 +25,23 @@ const (
|
|||
// Constant as this should not change without a hard fork.
|
||||
// TODO: Link to some Tendermint docs, this is very unobvious.
|
||||
ValidatorUpdateDelay int64 = 1
|
||||
|
||||
BondStatusUnbonded = "Unbonded"
|
||||
BondStatusUnbonding = "Unbonding"
|
||||
BondStatusBonded = "Bonded"
|
||||
)
|
||||
|
||||
//BondStatusToString for pretty prints of Bond Status
|
||||
func BondStatusToString(b BondStatus) string {
|
||||
// String implements the Stringer interface for BondStatus.
|
||||
func (b BondStatus) String() string {
|
||||
switch b {
|
||||
case 0x00:
|
||||
return "Unbonded"
|
||||
return BondStatusUnbonded
|
||||
case 0x01:
|
||||
return "Unbonding"
|
||||
return BondStatusUnbonding
|
||||
case 0x02:
|
||||
return "Bonded"
|
||||
return BondStatusBonded
|
||||
default:
|
||||
panic("improper use of BondStatusToString")
|
||||
panic("invalid bond status")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ type (
|
|||
QueryValidatorParams = querier.QueryValidatorParams
|
||||
QueryBondsParams = querier.QueryBondsParams
|
||||
QueryRedelegationParams = querier.QueryRedelegationParams
|
||||
QueryValidatorsParams = querier.QueryValidatorsParams
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -97,10 +98,11 @@ var (
|
|||
NewMsgUndelegate = types.NewMsgUndelegate
|
||||
NewMsgBeginRedelegate = types.NewMsgBeginRedelegate
|
||||
|
||||
NewQuerier = querier.NewQuerier
|
||||
NewQueryDelegatorParams = querier.NewQueryDelegatorParams
|
||||
NewQueryValidatorParams = querier.NewQueryValidatorParams
|
||||
NewQueryBondsParams = querier.NewQueryBondsParams
|
||||
NewQuerier = querier.NewQuerier
|
||||
NewQueryDelegatorParams = querier.NewQueryDelegatorParams
|
||||
NewQueryValidatorParams = querier.NewQueryValidatorParams
|
||||
NewQueryBondsParams = querier.NewQueryBondsParams
|
||||
NewQueryValidatorsParams = querier.NewQueryValidatorsParams
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
|
@ -15,7 +16,6 @@ import (
|
|||
)
|
||||
|
||||
func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec) {
|
||||
|
||||
// Get all delegations from a delegator
|
||||
r.HandleFunc(
|
||||
"/staking/delegators/{delegatorAddr}/delegations",
|
||||
|
@ -249,7 +249,31 @@ func delegatorValidatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) ht
|
|||
// HTTP request handler to query list of validators
|
||||
func validatorsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
res, err := cliCtx.QueryWithData("custom/staking/validators", nil)
|
||||
_, page, limit, err := rest.ParseHTTPArgs(r)
|
||||
if err != nil {
|
||||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// override default limit if it wasn't provided
|
||||
if l := r.FormValue("limit"); l == "" {
|
||||
limit = 0
|
||||
}
|
||||
|
||||
status := r.FormValue("status")
|
||||
if status == "" {
|
||||
status = sdk.BondStatusBonded
|
||||
}
|
||||
|
||||
params := staking.NewQueryValidatorsParams(page, limit, status)
|
||||
bz, err := cdc.MarshalJSON(params)
|
||||
if err != nil {
|
||||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
route := fmt.Sprintf("custom/%s/%s", staking.QuerierRoute, staking.QueryValidators)
|
||||
res, err := cliCtx.QueryWithData(route, bz)
|
||||
if err != nil {
|
||||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
|
|
|
@ -162,9 +162,8 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) {
|
|||
|
||||
assert.Equal(
|
||||
t, status, val.GetStatus(),
|
||||
fmt.Sprintf("expected validator at index %v to have status: %s",
|
||||
valIdx,
|
||||
sdk.BondStatusToString(status)))
|
||||
fmt.Sprintf("expected validator at index %v to have status: %s", valIdx, status),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package querier
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
|
@ -35,7 +36,7 @@ func NewQuerier(k keep.Keeper, cdc *codec.Codec) sdk.Querier {
|
|||
return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) {
|
||||
switch path[0] {
|
||||
case QueryValidators:
|
||||
return queryValidators(ctx, cdc, k)
|
||||
return queryValidators(ctx, cdc, req, k)
|
||||
case QueryValidator:
|
||||
return queryValidator(ctx, cdc, req, k)
|
||||
case QueryValidatorDelegations:
|
||||
|
@ -128,14 +129,47 @@ func NewQueryRedelegationParams(delegatorAddr sdk.AccAddress, srcValidatorAddr s
|
|||
}
|
||||
}
|
||||
|
||||
func queryValidators(ctx sdk.Context, cdc *codec.Codec, k keep.Keeper) (res []byte, err sdk.Error) {
|
||||
stakingParams := k.GetParams(ctx)
|
||||
validators := k.GetValidators(ctx, stakingParams.MaxValidators)
|
||||
func queryValidators(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) ([]byte, sdk.Error) {
|
||||
var params QueryValidatorsParams
|
||||
|
||||
res, errRes := codec.MarshalJSONIndent(cdc, validators)
|
||||
err := cdc.UnmarshalJSON(req.Data, ¶ms)
|
||||
if err != nil {
|
||||
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error()))
|
||||
return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err))
|
||||
}
|
||||
|
||||
stakingParams := k.GetParams(ctx)
|
||||
if params.Limit == 0 {
|
||||
params.Limit = int(stakingParams.MaxValidators)
|
||||
}
|
||||
|
||||
validators := k.GetAllValidators(ctx)
|
||||
filteredVals := make([]types.Validator, 0, len(validators))
|
||||
|
||||
for _, val := range validators {
|
||||
if strings.ToLower(val.GetStatus().String()) == strings.ToLower(params.Status) {
|
||||
filteredVals = append(filteredVals, val)
|
||||
}
|
||||
}
|
||||
|
||||
// get pagination bounds
|
||||
start := (params.Page - 1) * params.Limit
|
||||
end := params.Limit + start
|
||||
if end >= len(filteredVals) {
|
||||
end = len(filteredVals)
|
||||
}
|
||||
|
||||
if start >= len(filteredVals) {
|
||||
// page is out of bounds
|
||||
filteredVals = []types.Validator{}
|
||||
} else {
|
||||
filteredVals = filteredVals[start:end]
|
||||
}
|
||||
|
||||
res, err := codec.MarshalJSONIndent(cdc, filteredVals)
|
||||
if err != nil {
|
||||
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to JSON marshal result: %s", err.Error()))
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
|
@ -354,3 +388,14 @@ func queryParameters(ctx sdk.Context, cdc *codec.Codec, k keep.Keeper) (res []by
|
|||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// QueryValidatorsParams defines the params for the following queries:
|
||||
// - 'custom/staking/validators'
|
||||
type QueryValidatorsParams struct {
|
||||
Page, Limit int
|
||||
Status string
|
||||
}
|
||||
|
||||
func NewQueryValidatorsParams(page, limit int, status string) QueryValidatorsParams {
|
||||
return QueryValidatorsParams{page, limit, status}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package querier
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -44,9 +45,6 @@ func TestNewQuerier(t *testing.T) {
|
|||
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)
|
||||
|
||||
|
@ -121,28 +119,44 @@ func TestQueryValidators(t *testing.T) {
|
|||
params := keeper.GetParams(ctx)
|
||||
|
||||
// Create Validators
|
||||
amts := []sdk.Int{sdk.NewInt(9), sdk.NewInt(8)}
|
||||
var validators [2]types.Validator
|
||||
amts := []sdk.Int{sdk.NewInt(9), sdk.NewInt(8), sdk.NewInt(7)}
|
||||
status := []sdk.BondStatus{sdk.Bonded, sdk.Unbonded, sdk.Unbonding}
|
||||
var validators [3]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], pool = validators[i].UpdateStatus(pool, status[i])
|
||||
}
|
||||
|
||||
keeper.SetPool(ctx, pool)
|
||||
keeper.SetValidator(ctx, validators[0])
|
||||
keeper.SetValidator(ctx, validators[1])
|
||||
keeper.SetValidator(ctx, validators[2])
|
||||
|
||||
// Query Validators
|
||||
queriedValidators := keeper.GetValidators(ctx, params.MaxValidators)
|
||||
|
||||
res, err := queryValidators(ctx, cdc, keeper)
|
||||
require.Nil(t, err)
|
||||
for i, s := range status {
|
||||
queryValsParams := NewQueryValidatorsParams(1, int(params.MaxValidators), s.String())
|
||||
bz, errRes := cdc.MarshalJSON(queryValsParams)
|
||||
require.Nil(t, errRes)
|
||||
|
||||
var validatorsResp []types.Validator
|
||||
errRes := cdc.UnmarshalJSON(res, &validatorsResp)
|
||||
require.Nil(t, errRes)
|
||||
req := abci.RequestQuery{
|
||||
Path: fmt.Sprintf("/custom/%s/%s", types.QuerierRoute, QueryValidators),
|
||||
Data: bz,
|
||||
}
|
||||
|
||||
require.Equal(t, len(queriedValidators), len(validatorsResp))
|
||||
require.ElementsMatch(t, queriedValidators, validatorsResp)
|
||||
res, err := queryValidators(ctx, cdc, req, keeper)
|
||||
require.Nil(t, err)
|
||||
|
||||
var validatorsResp []types.Validator
|
||||
errRes = cdc.UnmarshalJSON(res, &validatorsResp)
|
||||
require.Nil(t, errRes)
|
||||
|
||||
require.Equal(t, 1, len(validatorsResp))
|
||||
require.ElementsMatch(t, validators[i].OperatorAddress, validatorsResp[0].OperatorAddress)
|
||||
|
||||
}
|
||||
|
||||
// Query each validator
|
||||
queryParams := NewQueryValidatorParams(addrVal1)
|
||||
|
@ -153,7 +167,7 @@ func TestQueryValidators(t *testing.T) {
|
|||
Path: "/custom/staking/validator",
|
||||
Data: bz,
|
||||
}
|
||||
res, err = queryValidator(ctx, cdc, query, keeper)
|
||||
res, err := queryValidator(ctx, cdc, query, keeper)
|
||||
require.Nil(t, err)
|
||||
|
||||
var validator types.Validator
|
||||
|
|
|
@ -117,7 +117,7 @@ func (v Validator) String() string {
|
|||
Unbonding Completion Time: %v
|
||||
Minimum Self Delegation: %v
|
||||
Commission: %s`, v.OperatorAddress, bechConsPubKey,
|
||||
v.Jailed, sdk.BondStatusToString(v.Status), v.Tokens,
|
||||
v.Jailed, v.Status, v.Tokens,
|
||||
v.DelegatorShares, v.Description,
|
||||
v.UnbondingHeight, v.UnbondingCompletionTime, v.MinSelfDelegation, v.Commission)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue