add pagination (#6163)

* add pagination

* make test pass with validators

* add pagination option

* unbonding delegations test added

* test unbondedvalidators pagination

* clean test

* remove comment

* remove comment

* add page and limit to unbonding delegations

* add flag limit and page for delegations-to command

* refactor hardcoded string values

* udpate page and limit for validator

* update changelog

* add pagination option

* add defaults

* Update CHANGELOG.md

Co-authored-by: Alexander Bezobchuk <alexanderbez@users.noreply.github.com>

Co-authored-by: Alexander Bezobchuk <alexanderbez@users.noreply.github.com>
Co-authored-by: Alessio Treglia <alessio@tendermint.com>
This commit is contained in:
Jonathan Gimeno 2020-06-06 19:32:15 +02:00 committed by GitHub
parent 71374d0eca
commit 626f9b62c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 167 additions and 26 deletions

View File

@ -271,6 +271,9 @@ functionality that requires an online connection.
* (simulation) [\#6002](https://github.com/cosmos/cosmos-sdk/pull/6002) Add randomized consensus params into simulation.
* (x/staking) [\#6059](https://github.com/cosmos/cosmos-sdk/pull/6059) Updated `HistoricalEntries` parameter default to 100.
* (x/ibc) [\#5948](https://github.com/cosmos/cosmos-sdk/issues/5948) Add `InitGenesis` and `ExportGenesis` functions for `ibc` module.
* (types) [\#6128](https://github.com/cosmos/cosmos-sdk/pull/6137) Add String() method to GasMeter
* (x/staking) [\#6163](https://github.com/cosmos/cosmos-sdk/pull/6163) CLI and REST call to unbonding delegations and delegations now accept
pagination.
* (types) [\#6128](https://github.com/cosmos/cosmos-sdk/pull/6137) Add `String()` method to `GasMeter`.
* (types) [\#6195](https://github.com/cosmos/cosmos-sdk/pull/6195) Add codespace to broadcast(sync/async) response.
* (baseapp) [\#6053](https://github.com/cosmos/cosmos-sdk/pull/6053) Customizable panic recovery handling added for `app.runTx()` method (as proposed in the [ADR 22](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-022-custom-panic-handling.md)). Adds ability for developers to register custom panic handlers extending standard ones.

View File

@ -6,6 +6,7 @@ import (
"strings"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
@ -125,7 +126,7 @@ $ %s query staking validators
// GetCmdQueryValidatorUnbondingDelegations implements the query all unbonding delegatations from a validator command.
func GetCmdQueryValidatorUnbondingDelegations(queryRoute string, cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
cmd := &cobra.Command{
Use: "unbonding-delegations-from [validator-addr]",
Short: "Query all unbonding delegatations from a validator",
Long: strings.TrimSpace(
@ -146,7 +147,7 @@ $ %s query staking unbonding-delegations-from cosmosvaloper1gghjut3ccd8ay0zduzj6
return err
}
bz, err := cdc.MarshalJSON(types.NewQueryValidatorParams(valAddr))
bz, err := cdc.MarshalJSON(types.NewQueryValidatorParams(valAddr, viper.GetInt(flags.FlagPage), viper.GetInt(flags.FlagLimit)))
if err != nil {
return err
}
@ -162,6 +163,11 @@ $ %s query staking unbonding-delegations-from cosmosvaloper1gghjut3ccd8ay0zduzj6
return clientCtx.PrintOutput(ubds)
},
}
cmd.Flags().Int(flags.FlagPage, 1, "pagination page of unbonding delegations to query for")
cmd.Flags().Int(flags.FlagLimit, 100, "pagination limit of unbonding delegations to query for")
return cmd
}
// GetCmdQueryValidatorRedelegations implements the query all redelegatations
@ -306,7 +312,7 @@ $ %s query staking delegations cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p
// GetCmdQueryValidatorDelegations implements the command to query all the
// delegations to a specific validator.
func GetCmdQueryValidatorDelegations(queryRoute string, cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
cmd := &cobra.Command{
Use: "delegations-to [validator-addr]",
Short: "Query all delegations made to one validator",
Long: strings.TrimSpace(
@ -327,7 +333,7 @@ $ %s query staking delegations-to cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ld
return err
}
bz, err := cdc.MarshalJSON(types.NewQueryValidatorParams(valAddr))
bz, err := cdc.MarshalJSON(types.NewQueryValidatorParams(valAddr, viper.GetInt(flags.FlagPage), viper.GetInt(flags.FlagLimit)))
if err != nil {
return err
}
@ -346,6 +352,11 @@ $ %s query staking delegations-to cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ld
return clientCtx.PrintOutput(resp)
},
}
cmd.Flags().Int(flags.FlagPage, 1, "pagination page of delegations to query for")
cmd.Flags().Int(flags.FlagLimit, 100, "pagination limit of delegations to query for")
return cmd
}
// GetCmdQueryUnbondingDelegation implements the command to query a single

View File

@ -112,8 +112,8 @@ func delegatorDelegationsHandlerFn(clientCtx client.Context) http.HandlerFunc {
}
// HTTP request handler to query a delegator unbonding delegations
func delegatorUnbondingDelegationsHandlerFn(clientCtx client.Context) http.HandlerFunc {
return queryDelegator(clientCtx, "custom/staking/delegatorUnbondingDelegations")
func delegatorUnbondingDelegationsHandlerFn(cliCtx client.Context) http.HandlerFunc {
return queryDelegator(cliCtx, fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryDelegatorUnbondingDelegations))
}
// HTTP request handler to query all staking txs (msgs) from a delegator
@ -189,8 +189,8 @@ func delegatorTxsHandlerFn(clientCtx client.Context) http.HandlerFunc {
}
// HTTP request handler to query an unbonding-delegation
func unbondingDelegationHandlerFn(clientCtx client.Context) http.HandlerFunc {
return queryBonds(clientCtx, "custom/staking/unbondingDelegation")
func unbondingDelegationHandlerFn(cliCtx client.Context) http.HandlerFunc {
return queryBonds(cliCtx, fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryUnbondingDelegation))
}
// HTTP request handler to query redelegations
@ -239,7 +239,7 @@ func redelegationsHandlerFn(clientCtx client.Context) http.HandlerFunc {
return
}
res, height, err := clientCtx.QueryWithData("custom/staking/redelegations", bz)
res, height, err := clientCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryRedelegations), bz)
if rest.CheckInternalServerError(w, err) {
return
}
@ -255,13 +255,13 @@ func delegationHandlerFn(clientCtx client.Context) http.HandlerFunc {
}
// HTTP request handler to query all delegator bonded validators
func delegatorValidatorsHandlerFn(clientCtx client.Context) http.HandlerFunc {
return queryDelegator(clientCtx, "custom/staking/delegatorValidators")
func delegatorValidatorsHandlerFn(cliCtx client.Context) http.HandlerFunc {
return queryDelegator(cliCtx, fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryDelegatorValidators))
}
// HTTP request handler to get information from a currently bonded validator
func delegatorValidatorHandlerFn(clientCtx client.Context) http.HandlerFunc {
return queryBonds(clientCtx, "custom/staking/delegatorValidator")
func delegatorValidatorHandlerFn(cliCtx client.Context) http.HandlerFunc {
return queryBonds(cliCtx, fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryDelegatorValidator))
}
// HTTP request handler to query list of validators
@ -302,8 +302,8 @@ func validatorsHandlerFn(clientCtx client.Context) http.HandlerFunc {
}
// HTTP request handler to query the validator information from a given validator address
func validatorHandlerFn(clientCtx client.Context) http.HandlerFunc {
return queryValidator(clientCtx, "custom/staking/validator")
func validatorHandlerFn(cliCtx client.Context) http.HandlerFunc {
return queryValidator(cliCtx, fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryValidator))
}
// HTTP request handler to query all unbonding delegations from a validator
@ -312,8 +312,8 @@ func validatorDelegationsHandlerFn(clientCtx client.Context) http.HandlerFunc {
}
// HTTP request handler to query all unbonding delegations from a validator
func validatorUnbondingDelegationsHandlerFn(clientCtx client.Context) http.HandlerFunc {
return queryValidator(clientCtx, "custom/staking/validatorUnbondingDelegations")
func validatorUnbondingDelegationsHandlerFn(cliCtx client.Context) http.HandlerFunc {
return queryValidator(cliCtx, fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryValidatorUnbondingDelegations))
}
// HTTP request handler to query historical info at a given height
@ -353,7 +353,7 @@ func poolHandlerFn(clientCtx client.Context) http.HandlerFunc {
return
}
res, height, err := clientCtx.QueryWithData("custom/staking/pool", nil)
res, height, err := clientCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryPool), nil)
if rest.CheckInternalServerError(w, err) {
return
}
@ -371,7 +371,7 @@ func paramsHandlerFn(clientCtx client.Context) http.HandlerFunc {
return
}
res, height, err := clientCtx.QueryWithData("custom/staking/parameters", nil)
res, height, err := clientCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryParameters), nil)
if rest.CheckInternalServerError(w, err) {
return
}

View File

@ -111,6 +111,11 @@ func queryValidator(clientCtx client.Context, endpoint string) http.HandlerFunc
vars := mux.Vars(r)
bech32validatorAddr := vars["validatorAddr"]
_, page, limit, err := rest.ParseHTTPArgsWithLimit(r, 0)
if rest.CheckBadRequestError(w, err) {
return
}
validatorAddr, err := sdk.ValAddressFromBech32(bech32validatorAddr)
if rest.CheckBadRequestError(w, err) {
return
@ -121,7 +126,7 @@ func queryValidator(clientCtx client.Context, endpoint string) http.HandlerFunc
return
}
params := types.NewQueryValidatorParams(validatorAddr)
params := types.NewQueryValidatorParams(validatorAddr, page, limit)
bz, err := clientCtx.Codec.MarshalJSON(params)
if rest.CheckBadRequestError(w, err) {

View File

@ -128,6 +128,13 @@ func queryValidatorDelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper)
delegations := k.GetValidatorDelegations(ctx, params.ValidatorAddr)
start, end := client.Paginate(len(delegations), params.Page, params.Limit, int(k.GetParams(ctx).MaxValidators))
if start < 0 || end < 0 {
delegations = []types.Delegation{}
} else {
delegations = delegations[start:end]
}
delegationResps, err := delegationsToDelegationResponses(ctx, k, delegations)
if err != nil {
return nil, err
@ -158,6 +165,13 @@ func queryValidatorUnbondingDelegations(ctx sdk.Context, req abci.RequestQuery,
unbonds = types.UnbondingDelegations{}
}
start, end := client.Paginate(len(unbonds), params.Page, params.Limit, int(k.GetParams(ctx).MaxValidators))
if start < 0 || end < 0 {
unbonds = types.UnbondingDelegations{}
} else {
unbonds = unbonds[start:end]
}
res, err := codec.MarshalJSONIndent(types.ModuleCdc, unbonds)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())

View File

@ -55,7 +55,7 @@ func TestNewQuerier(t *testing.T) {
_, err = querier(ctx, []string{"parameters"}, query)
require.NoError(t, err)
queryValParams := types.NewQueryValidatorParams(addrVal1)
queryValParams := types.NewQueryValidatorParams(addrVal1, 0, 0)
bz, errRes := cdc.MarshalJSON(queryValParams)
require.NoError(t, errRes)
@ -178,7 +178,7 @@ func TestQueryValidators(t *testing.T) {
// Query each validator
for _, validator := range validators {
queryParams := types.NewQueryValidatorParams(validator.OperatorAddress)
queryParams := types.NewQueryValidatorParams(validator.OperatorAddress, 0, 0)
bz, err := cdc.MarshalJSON(queryParams)
require.NoError(t, err)
@ -323,7 +323,7 @@ func TestQueryDelegation(t *testing.T) {
require.Error(t, err)
// Query validator delegations
bz, errRes = cdc.MarshalJSON(types.NewQueryValidatorParams(addrVal1))
bz, errRes = cdc.MarshalJSON(types.NewQueryValidatorParams(addrVal1, 1, 100))
require.NoError(t, errRes)
query = abci.RequestQuery{
@ -424,6 +424,112 @@ func TestQueryDelegation(t *testing.T) {
require.Len(t, redel.Entries, len(redelRes[0].Entries))
}
func TestQueryValidatorDelegations_Pagination(t *testing.T) {
cases := []struct {
page int
limit int
expectedResults int
}{
{
page: 1,
limit: 75,
expectedResults: 75,
},
{
page: 2,
limit: 75,
expectedResults: 25,
},
{
page: 1,
limit: 100,
expectedResults: 100,
},
}
cdc, app, ctx := createTestInput()
querier := staking.NewQuerier(app.StakingKeeper)
addrs := simapp.AddTestAddrs(app, ctx, 100, sdk.TokensFromConsensusPower(10000))
pubKeys := simapp.CreateTestPubKeys(1)
valAddress := sdk.ValAddress(addrs[0])
val1 := types.NewValidator(valAddress, pubKeys[0], types.Description{})
app.StakingKeeper.SetValidator(ctx, val1)
app.StakingKeeper.SetValidatorByPowerIndex(ctx, val1)
// Create Validators and Delegation
for _, addr := range addrs {
validator, found := app.StakingKeeper.GetValidator(ctx, valAddress)
if !found {
t.Error("expected validator not found")
}
delTokens := sdk.TokensFromConsensusPower(20)
_, err := app.StakingKeeper.Delegate(ctx, addr, delTokens, sdk.Unbonded, validator, true)
require.NoError(t, err)
}
// apply TM updates
app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
for _, c := range cases {
// Query Delegator bonded validators
queryParams := types.NewQueryDelegatorParams(addrs[0])
bz, errRes := cdc.MarshalJSON(queryParams)
require.NoError(t, errRes)
// Query valAddress delegations
bz, errRes = cdc.MarshalJSON(types.NewQueryValidatorParams(valAddress, c.page, c.limit))
require.NoError(t, errRes)
query := abci.RequestQuery{
Path: "custom/staking/validatorDelegations",
Data: bz,
}
res, err := querier(ctx, []string{types.QueryValidatorDelegations}, query)
require.NoError(t, err)
var delegationsRes types.DelegationResponses
errRes = cdc.UnmarshalJSON(res, &delegationsRes)
require.NoError(t, errRes)
require.Len(t, delegationsRes, c.expectedResults)
}
// Undelegate
for _, addr := range addrs {
delTokens := sdk.TokensFromConsensusPower(20)
_, err := app.StakingKeeper.Undelegate(ctx, addr, val1.GetOperator(), delTokens.ToDec())
require.NoError(t, err)
}
// apply TM updates
app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
for _, c := range cases {
// Query Unbonding delegations with pagination.
queryParams := types.NewQueryDelegatorParams(addrs[0])
bz, errRes := cdc.MarshalJSON(queryParams)
require.NoError(t, errRes)
bz, errRes = cdc.MarshalJSON(types.NewQueryValidatorParams(valAddress, c.page, c.limit))
require.NoError(t, errRes)
query := abci.RequestQuery{
Data: bz,
}
unbondingDelegations := types.UnbondingDelegations{}
res, err := querier(ctx, []string{types.QueryValidatorUnbondingDelegations}, query)
require.NoError(t, err)
errRes = cdc.UnmarshalJSON(res, &unbondingDelegations)
require.NoError(t, errRes)
require.Len(t, unbondingDelegations, c.expectedResults)
}
}
func TestQueryRedelegations(t *testing.T) {
cdc, app, ctx := createTestInput()
querier := staking.NewQuerier(app.StakingKeeper)
@ -474,7 +580,7 @@ func TestQueryRedelegations(t *testing.T) {
require.Len(t, redel.Entries, len(redelRes[0].Entries))
// validator redelegations
queryValidatorParams := types.NewQueryValidatorParams(val1.GetOperator())
queryValidatorParams := types.NewQueryValidatorParams(val1.GetOperator(), 0, 0)
bz, errRes = cdc.MarshalJSON(queryValidatorParams)
require.NoError(t, errRes)

View File

@ -26,7 +26,6 @@ const (
// defines the params for the following queries:
// - 'custom/staking/delegatorDelegations'
// - 'custom/staking/delegatorUnbondingDelegations'
// - 'custom/staking/delegatorRedelegations'
// - 'custom/staking/delegatorValidators'
type QueryDelegatorParams struct {
DelegatorAddr sdk.AccAddress
@ -45,11 +44,14 @@ func NewQueryDelegatorParams(delegatorAddr sdk.AccAddress) QueryDelegatorParams
// - 'custom/staking/validatorRedelegations'
type QueryValidatorParams struct {
ValidatorAddr sdk.ValAddress
Page, Limit int
}
func NewQueryValidatorParams(validatorAddr sdk.ValAddress) QueryValidatorParams {
func NewQueryValidatorParams(validatorAddr sdk.ValAddress, page, limit int) QueryValidatorParams {
return QueryValidatorParams{
ValidatorAddr: validatorAddr,
Page: page,
Limit: limit,
}
}