From 74a02b1d2be418505e9d20be4ee5657ba2587998 Mon Sep 17 00:00:00 2001 From: Marko Baricevic Date: Tue, 17 Sep 2019 15:11:04 +0200 Subject: [PATCH] Add pagination to /validators - closes #3472 Signed-off-by: Marko Baricevic --- lite/client/provider.go | 2 +- lite/proxy/proxy.go | 2 +- rpc/client/httpclient.go | 8 ++++++-- rpc/client/interface.go | 2 +- rpc/client/localclient.go | 4 ++-- rpc/core/consensus.go | 24 ++++++++++++++++++++++-- 6 files changed, 33 insertions(+), 9 deletions(-) diff --git a/lite/client/provider.go b/lite/client/provider.go index e0c0a331b..475763d6c 100644 --- a/lite/client/provider.go +++ b/lite/client/provider.go @@ -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) // page & perPage are hard coded to 0 to get the entire validator set in one request if err != nil { // TODO pass through other types of errors. return nil, lerr.ErrUnknownValidators(chainID, height) diff --git a/lite/proxy/proxy.go b/lite/proxy/proxy.go index 80343a531..401d128d9 100644 --- a/lite/proxy/proxy.go +++ b/lite/proxy/proxy.go @@ -126,7 +126,7 @@ func makeTxFunc(c rpcclient.Client) func(ctx *rpctypes.Context, hash []byte, pro func makeValidatorsFunc(c rpcclient.Client) func(ctx *rpctypes.Context, 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) } } diff --git a/rpc/client/httpclient.go b/rpc/client/httpclient.go index d1981e1ce..12fe994d4 100644 --- a/rpc/client/httpclient.go +++ b/rpc/client/httpclient.go @@ -336,9 +336,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") } diff --git a/rpc/client/interface.go b/rpc/client/interface.go index c4a7b023d..861aaf3ee 100644 --- a/rpc/client/interface.go +++ b/rpc/client/interface.go @@ -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) } diff --git a/rpc/client/localclient.go b/rpc/client/localclient.go index 3c3a1dcc6..7f74c6014 100644 --- a/rpc/client/localclient.go +++ b/rpc/client/localclient.go @@ -145,8 +145,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) { diff --git a/rpc/core/consensus.go b/rpc/core/consensus.go index ad23a461c..9bdfe89b8 100644 --- a/rpc/core/consensus.go +++ b/rpc/core/consensus.go @@ -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" @@ -50,7 +51,7 @@ import ( // "jsonrpc": "2.0" // } // ``` -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 @@ -63,9 +64,28 @@ 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) + apiResults := make([]*types.Validator, cmn.MinInt(perPage, totalCount-skipCount)) + + for i := 0; i < len(apiResults); i++ { + v := validators.Validators[skipCount+1] + apiResults[i] = &types.Validator{ + Address: v.Address, + PubKey: v.PubKey, + VotingPower: v.VotingPower, + ProposerPriority: v.ProposerPriority, + } + } + return &ctypes.ResultValidators{ BlockHeight: height, - Validators: validators.Validators}, nil + Validators: apiResults}, nil } // DumpConsensusState dumps consensus state.