make `/status` RPC endpoint resistant to consensus halt

Refs #1772
This commit is contained in:
Anton Kaliaev 2018-07-19 11:26:50 +04:00
parent 40342bfa4a
commit 1bd5476854
No known key found for this signature in database
GPG Key ID: 7B6881D965918214
1 changed files with 28 additions and 2 deletions

View File

@ -4,10 +4,10 @@ import (
"bytes" "bytes"
"time" "time"
cmn "github.com/tendermint/tendermint/libs/common"
ctypes "github.com/tendermint/tendermint/rpc/core/types" ctypes "github.com/tendermint/tendermint/rpc/core/types"
sm "github.com/tendermint/tendermint/state" sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
cmn "github.com/tendermint/tendermint/libs/common"
) )
// Get Tendermint status including node info, pubkey, latest block // Get Tendermint status including node info, pubkey, latest block
@ -105,7 +105,11 @@ func Status() (*ctypes.ResultStatus, error) {
} }
func validatorAtHeight(h int64) *types.Validator { func validatorAtHeight(h int64) *types.Validator {
lastBlockHeight, vals := consensusState.GetValidators() lastBlockHeight, vals := getValidatorsWithTimeout(1 * time.Second)
if lastBlockHeight == -1 {
return nil
}
privValAddress := pubKey.Address() privValAddress := pubKey.Address()
@ -131,3 +135,25 @@ func validatorAtHeight(h int64) *types.Validator {
return nil 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{}
}
}