From 1bd547685448c9367b431acb4a207c7c0e5f46a5 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 19 Jul 2018 11:26:50 +0400 Subject: [PATCH] make `/status` RPC endpoint resistant to consensus halt Refs #1772 --- rpc/core/status.go | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/rpc/core/status.go b/rpc/core/status.go index 63e62b2c7..de3ddb7f7 100644 --- a/rpc/core/status.go +++ b/rpc/core/status.go @@ -4,10 +4,10 @@ import ( "bytes" "time" + cmn "github.com/tendermint/tendermint/libs/common" ctypes "github.com/tendermint/tendermint/rpc/core/types" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" - cmn "github.com/tendermint/tendermint/libs/common" ) // Get Tendermint status including node info, pubkey, latest block @@ -105,7 +105,11 @@ func Status() (*ctypes.ResultStatus, error) { } func validatorAtHeight(h int64) *types.Validator { - lastBlockHeight, vals := consensusState.GetValidators() + lastBlockHeight, vals := getValidatorsWithTimeout(1 * time.Second) + + if lastBlockHeight == -1 { + return nil + } privValAddress := pubKey.Address() @@ -131,3 +135,25 @@ func validatorAtHeight(h int64) *types.Validator { return nil } + +// NOTE: Consensus might halt, but we still need to process RPC requests (at +// least for endpoints whole output does not depend on consensus state). +func getValidatorsWithTimeout(t time.Duration) (int64, []*types.Validator) { + resultCh := make(chan struct { + lastBlockHeight int64 + vals []*types.Validator + }) + go func() { + h, v := consensusState.GetValidators() + resultCh <- struct { + lastBlockHeight int64 + vals []*types.Validator + }{h, v} + }() + select { + case res := <-resultCh: + return res.lastBlockHeight, res.vals + case <-time.After(t): + return -1, []*types.Validator{} + } +}