From e2e87460444ba0c8097c416da9b91734f74af498 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 21 Aug 2017 18:11:16 -0400 Subject: [PATCH] rpc: historical validators --- rpc/client/httpclient.go | 6 ++++-- rpc/client/interface.go | 2 +- rpc/client/localclient.go | 4 ++-- rpc/client/mock/client.go | 4 ++-- rpc/client/rpc_test.go | 2 +- rpc/core/blocks.go | 4 +++- rpc/core/consensus.go | 17 +++++++++++++---- rpc/core/pipe.go | 5 ++++- rpc/core/routes.go | 2 +- 9 files changed, 31 insertions(+), 15 deletions(-) diff --git a/rpc/client/httpclient.go b/rpc/client/httpclient.go index 9623229e6..4e54cbf7d 100644 --- a/rpc/client/httpclient.go +++ b/rpc/client/httpclient.go @@ -174,9 +174,11 @@ func (c *HTTP) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { return result, nil } -func (c *HTTP) Validators() (*ctypes.ResultValidators, error) { +func (c *HTTP) Validators(height *int) (*ctypes.ResultValidators, error) { result := new(ctypes.ResultValidators) - _, err := c.rpc.Call("validators", map[string]interface{}{}, result) + _, err := c.rpc.Call("validators", map[string]interface{}{ + "height": height, + }, result) if err != nil { return nil, errors.Wrap(err, "Validators") } diff --git a/rpc/client/interface.go b/rpc/client/interface.go index 0cd0f29bb..8845e5e5a 100644 --- a/rpc/client/interface.go +++ b/rpc/client/interface.go @@ -44,7 +44,7 @@ type ABCIClient interface { type SignClient interface { Block(height int) (*ctypes.ResultBlock, error) Commit(height int) (*ctypes.ResultCommit, error) - Validators() (*ctypes.ResultValidators, error) + Validators(height *int) (*ctypes.ResultValidators, error) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) } diff --git a/rpc/client/localclient.go b/rpc/client/localclient.go index f4eb00d78..0d8500e1e 100644 --- a/rpc/client/localclient.go +++ b/rpc/client/localclient.go @@ -101,8 +101,8 @@ func (c Local) Commit(height int) (*ctypes.ResultCommit, error) { return core.Commit(height) } -func (c Local) Validators() (*ctypes.ResultValidators, error) { - return core.Validators() +func (c Local) Validators(height *int) (*ctypes.ResultValidators, error) { + return core.Validators(height) } func (c Local) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { diff --git a/rpc/client/mock/client.go b/rpc/client/mock/client.go index bf8d78dce..be61b7af3 100644 --- a/rpc/client/mock/client.go +++ b/rpc/client/mock/client.go @@ -124,6 +124,6 @@ func (c Client) Commit(height int) (*ctypes.ResultCommit, error) { return core.Commit(height) } -func (c Client) Validators() (*ctypes.ResultValidators, error) { - return core.Validators() +func (c Client) Validators(height *int) (*ctypes.ResultValidators, error) { + return core.Validators(height) } diff --git a/rpc/client/rpc_test.go b/rpc/client/rpc_test.go index e82f8df42..304d2b906 100644 --- a/rpc/client/rpc_test.go +++ b/rpc/client/rpc_test.go @@ -87,7 +87,7 @@ func TestGenesisAndValidators(t *testing.T) { gval := gen.Genesis.Validators[0] // get the current validators - vals, err := c.Validators() + vals, err := c.Validators(nil) require.Nil(t, err, "%d: %+v", i, err) require.Equal(t, 1, len(vals.Validators)) val := vals.Validators[0] diff --git a/rpc/core/blocks.go b/rpc/core/blocks.go index 1f9e85422..5603cdd22 100644 --- a/rpc/core/blocks.go +++ b/rpc/core/blocks.go @@ -85,6 +85,7 @@ func BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResultBlockchainInfo, err } // Get block at a given height. +// If no height is provided, it will fetch the latest block. // // ```shell // curl 'localhost:46657/block?height=10' @@ -196,7 +197,8 @@ func Block(height int) (*ctypes.ResultBlock, error) { return &ctypes.ResultBlock{blockMeta, block}, nil } -// Get block commit at a given height. +// Get block commit at a given height. If the height is left out, it +// If no height is provided, it will fetch the commit for the latest block. // // ```shell // curl 'localhost:46657/commit?height=11' diff --git a/rpc/core/consensus.go b/rpc/core/consensus.go index fdce29e48..55596ec26 100644 --- a/rpc/core/consensus.go +++ b/rpc/core/consensus.go @@ -7,7 +7,8 @@ import ( "github.com/tendermint/tendermint/types" ) -// Get current validators set along with a block height. +// Get the validator set at a give block height. +// If no height is provided, it will fetch the current validator set. // // ```shell // curl 'localhost:46657/validators' @@ -41,9 +42,17 @@ import ( // "jsonrpc": "2.0" // } // ``` -func Validators() (*ctypes.ResultValidators, error) { - blockHeight, validators := consensusState.GetValidators() - return &ctypes.ResultValidators{blockHeight, validators}, nil +func Validators(height *int) (*ctypes.ResultValidators, error) { + if height == nil { + blockHeight, validators := consensusState.GetValidators() + return &ctypes.ResultValidators{blockHeight, validators}, nil + } + state := consensusState.GetState() + validators, err := state.LoadValidators(*height) + if err != nil { + return nil, err + } + return &ctypes.ResultValidators{*height, validators.Validators}, nil } // Dump consensus state. diff --git a/rpc/core/pipe.go b/rpc/core/pipe.go index 92e5746a6..86c6c65e1 100644 --- a/rpc/core/pipe.go +++ b/rpc/core/pipe.go @@ -2,18 +2,21 @@ package core import ( crypto "github.com/tendermint/go-crypto" + "github.com/tendermint/tmlibs/log" + "github.com/tendermint/tendermint/consensus" p2p "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/proxy" + sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/state/txindex" "github.com/tendermint/tendermint/types" - "github.com/tendermint/tmlibs/log" ) //---------------------------------------------- // These interfaces are used by RPC and must be thread safe type Consensus interface { + GetState() *sm.State GetValidators() (int, []*types.Validator) GetRoundState() *consensus.RoundState } diff --git a/rpc/core/routes.go b/rpc/core/routes.go index 795acde9b..485f7a00f 100644 --- a/rpc/core/routes.go +++ b/rpc/core/routes.go @@ -18,7 +18,7 @@ var Routes = map[string]*rpc.RPCFunc{ "block": rpc.NewRPCFunc(Block, "height"), "commit": rpc.NewRPCFunc(Commit, "height"), "tx": rpc.NewRPCFunc(Tx, "hash,prove"), - "validators": rpc.NewRPCFunc(Validators, ""), + "validators": rpc.NewRPCFunc(Validators, "height"), "dump_consensus_state": rpc.NewRPCFunc(DumpConsensusState, ""), "unconfirmed_txs": rpc.NewRPCFunc(UnconfirmedTxs, ""), "num_unconfirmed_txs": rpc.NewRPCFunc(NumUnconfirmedTxs, ""),