Browse Source

rpc: add pagination to /validators (#3993)

* Add pagination to /validators

- closes #3472

Signed-off-by: Marko Baricevic <marbar3778@yahoo.com>

* add swagger params, default returns all

* address pr comments

* golint fix

* swagger default change, change to default in comment

* swagger.yaml: replace x-example with example

https://swagger.io/docs/specification/adding-examples/

* Revert "swagger.yaml: replace x-example with example"

This reverts commit 9df1b006de.

* update changelog and remove extra body close
pull/4149/head
Marko 5 years ago
committed by Anton Kaliaev
parent
commit
1ddc43d029
13 changed files with 50 additions and 16 deletions
  1. +2
    -0
      CHANGELOG_PENDING.md
  2. +1
    -1
      lite/client/provider.go
  3. +1
    -1
      lite/proxy/proxy.go
  4. +3
    -2
      p2p/switch_test.go
  5. +6
    -2
      rpc/client/httpclient.go
  6. +1
    -1
      rpc/client/interface.go
  7. +2
    -2
      rpc/client/localclient.go
  8. +2
    -2
      rpc/client/mock/client.go
  9. +1
    -1
      rpc/client/rpc_test.go
  10. +15
    -2
      rpc/core/consensus.go
  11. +1
    -1
      rpc/core/routes.go
  12. +1
    -1
      rpc/lib/server/handlers_test.go
  13. +14
    -0
      rpc/swagger/swagger.yaml

+ 2
- 0
CHANGELOG_PENDING.md View File

@ -11,6 +11,7 @@ program](https://hackerone.com/tendermint).
### BREAKING CHANGES:
- CLI/RPC/Config
- [rpc] \#3471 Paginate `/validators` response (default: 30 vals per page)
- [rpc] \#3188 Remove `BlockMeta` in `ResultBlock` in favor of `BlockId` for `/block`
- [rpc] `/block_results` response format updated (see RPC docs for details)
```
@ -32,6 +33,7 @@ program](https://hackerone.com/tendermint).
- Go API
- [libs/pubsub] [\#4070](https://github.com/tendermint/tendermint/pull/4070) `Query#(Matches|Conditions)` returns an error.
- [rpc/client] \#3471 `Validators` now requires two more args: `page` and `perPage`
- Blockchain Protocol
- [abci] \#2521 Remove `TotalTxs` and `NumTxs` from `Header`


+ 1
- 1
lite/client/provider.go View File

@ -106,7 +106,7 @@ func (p *provider) getValidatorSet(chainID string, height int64) (valset *types.
err = fmt.Errorf("expected height >= 1, got height %v", height)
return
}
res, err := p.client.Validators(&height)
res, err := p.client.Validators(&height, 0, 0)
if err != nil {
// TODO pass through other types of errors.
return nil, lerr.ErrUnknownValidators(chainID, height)


+ 1
- 1
lite/proxy/proxy.go View File

@ -134,7 +134,7 @@ func makeValidatorsFunc(c rpcclient.Client) func(
height *int64,
) (*ctypes.ResultValidators, error) {
return func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultValidators, error) {
return c.Validators(height)
return c.Validators(height, 0, 0)
}
}


+ 3
- 2
p2p/switch_test.go View File

@ -368,9 +368,10 @@ func TestSwitchStopPeerForError(t *testing.T) {
defer s.Close()
scrapeMetrics := func() string {
resp, _ := http.Get(s.URL)
resp, err := http.Get(s.URL)
assert.NoError(t, err)
defer resp.Body.Close()
buf, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
return string(buf)
}


+ 6
- 2
rpc/client/httpclient.go View File

@ -339,9 +339,13 @@ func (c *baseRPCClient) TxSearch(query string, prove bool, page, perPage int) (*
return result, nil
}
func (c *baseRPCClient) Validators(height *int64) (*ctypes.ResultValidators, error) {
func (c *baseRPCClient) Validators(height *int64, page, perPage int) (*ctypes.ResultValidators, error) {
result := new(ctypes.ResultValidators)
_, err := c.caller.Call("validators", map[string]interface{}{"height": height}, result)
_, err := c.caller.Call("validators", map[string]interface{}{
"height": height,
"page": page,
"per_page": perPage,
}, result)
if err != nil {
return nil, errors.Wrap(err, "Validators")
}


+ 1
- 1
rpc/client/interface.go View File

@ -66,7 +66,7 @@ type SignClient interface {
Block(height *int64) (*ctypes.ResultBlock, error)
BlockResults(height *int64) (*ctypes.ResultBlockResults, error)
Commit(height *int64) (*ctypes.ResultCommit, error)
Validators(height *int64) (*ctypes.ResultValidators, error)
Validators(height *int64, page, perPage int) (*ctypes.ResultValidators, error)
Tx(hash []byte, prove bool) (*ctypes.ResultTx, error)
TxSearch(query string, prove bool, page, perPage int) (*ctypes.ResultTxSearch, error)
}


+ 2
- 2
rpc/client/localclient.go View File

@ -148,8 +148,8 @@ func (c *Local) Commit(height *int64) (*ctypes.ResultCommit, error) {
return core.Commit(c.ctx, height)
}
func (c *Local) Validators(height *int64) (*ctypes.ResultValidators, error) {
return core.Validators(c.ctx, height)
func (c *Local) Validators(height *int64, page, perPage int) (*ctypes.ResultValidators, error) {
return core.Validators(c.ctx, height, page, perPage)
}
func (c *Local) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) {


+ 2
- 2
rpc/client/mock/client.go View File

@ -149,8 +149,8 @@ func (c Client) Commit(height *int64) (*ctypes.ResultCommit, error) {
return core.Commit(&rpctypes.Context{}, height)
}
func (c Client) Validators(height *int64) (*ctypes.ResultValidators, error) {
return core.Validators(&rpctypes.Context{}, height)
func (c Client) Validators(height *int64, page, perPage int) (*ctypes.ResultValidators, error) {
return core.Validators(&rpctypes.Context{}, height, page, perPage)
}
func (c Client) BroadcastEvidence(ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) {


+ 1
- 1
rpc/client/rpc_test.go View File

@ -152,7 +152,7 @@ func TestGenesisAndValidators(t *testing.T) {
gval := gen.Genesis.Validators[0]
// get the current validators
vals, err := c.Validators(nil)
vals, err := c.Validators(nil, 0, 0)
require.Nil(t, err, "%d: %+v", i, err)
require.Equal(t, 1, len(vals.Validators))
val := vals.Validators[0]


+ 15
- 2
rpc/core/consensus.go View File

@ -2,6 +2,7 @@ package core
import (
cm "github.com/tendermint/tendermint/consensus"
cmn "github.com/tendermint/tendermint/libs/common"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
rpctypes "github.com/tendermint/tendermint/rpc/lib/types"
sm "github.com/tendermint/tendermint/state"
@ -13,7 +14,7 @@ import (
// Note the validators are sorted by their address - this is the canonical
// order for the validators in the set as used in computing their Merkle root.
// More: https://tendermint.com/rpc/#/Info/validators
func Validators(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultValidators, error) {
func Validators(ctx *rpctypes.Context, heightPtr *int64, page, perPage int) (*ctypes.ResultValidators, error) {
// The latest validator that we know is the
// NextValidator of the last block.
height := consensusState.GetState().LastBlockHeight + 1
@ -26,9 +27,21 @@ func Validators(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultValidato
if err != nil {
return nil, err
}
totalCount := len(validators.Validators)
perPage = validatePerPage(perPage)
page, err = validatePage(page, perPage, totalCount)
if err != nil {
return nil, err
}
skipCount := validateSkipCount(page, perPage)
v := validators.Validators[skipCount : skipCount+cmn.MinInt(perPage, totalCount-skipCount)]
return &ctypes.ResultValidators{
BlockHeight: height,
Validators: validators.Validators}, nil
Validators: v}, nil
}
// DumpConsensusState dumps consensus state.


+ 1
- 1
rpc/core/routes.go View File

@ -23,7 +23,7 @@ var Routes = map[string]*rpc.RPCFunc{
"commit": rpc.NewRPCFunc(Commit, "height"),
"tx": rpc.NewRPCFunc(Tx, "hash,prove"),
"tx_search": rpc.NewRPCFunc(TxSearch, "query,prove,page,per_page"),
"validators": rpc.NewRPCFunc(Validators, "height"),
"validators": rpc.NewRPCFunc(Validators, "height,page,per_page"),
"dump_consensus_state": rpc.NewRPCFunc(DumpConsensusState, ""),
"consensus_state": rpc.NewRPCFunc(ConsensusState, ""),
"consensus_params": rpc.NewRPCFunc(ConsensusParams, "height"),


+ 1
- 1
rpc/lib/server/handlers_test.go View File

@ -71,6 +71,7 @@ func TestRPCParams(t *testing.T) {
rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req)
res := rec.Result()
defer res.Body.Close()
// Always expecting back a JSONRPCResponse
assert.True(t, statusOK(res.StatusCode), "#%d: should always return 2XX", i)
blob, err := ioutil.ReadAll(res.Body)
@ -78,7 +79,6 @@ func TestRPCParams(t *testing.T) {
t.Errorf("#%d: err reading body: %v", i, err)
continue
}
res.Body.Close()
recv := new(types.RPCResponse)
assert.Nil(t, json.Unmarshal(blob, recv), "#%d: expecting successful parsing of an RPCResponse:\nblob: %s", i, blob)


+ 14
- 0
rpc/swagger/swagger.yaml View File

@ -584,6 +584,20 @@ paths:
description: height to return. If no height is provided, it will fetch validato set at the latest block. 0 means latest
default: 0
x-example: 1
- in: query
name: page
type: number
description: "Page number (1-based)"
required: false
x-example: 1
default: 0
- in: query
name: per_page
type: number
description: "Number of entries per page (max: 100)"
required: false
x-example: 30
default: 30
tags:
- Info
description: |


Loading…
Cancel
Save