Merge pull request #1391 from tendermint/581-include-validator-power

Include validator power in /status
This commit is contained in:
Ethan Buchman 2018-04-05 11:18:45 +03:00 committed by GitHub
commit c23d907f12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 85 additions and 23 deletions

View File

@ -32,6 +32,7 @@ BUG FIXES:
IMPROVEMENTS:
- [rpc] `/tx` and `/tx_search` responses now include the transaction hash
- [rpc] include validator power in `/status`
## 0.17.1 (March 27th, 2018)

View File

@ -720,11 +720,7 @@ func (cs *ConsensusState) needProofBlock(height int64) bool {
func (cs *ConsensusState) proposalHeartbeat(height int64, round int) {
counter := 0
addr := cs.privValidator.GetAddress()
valIndex, v := cs.Validators.GetByAddress(addr)
if v == nil {
// not a validator
valIndex = -1
}
valIndex, _ := cs.Validators.GetByAddress(addr)
chainID := cs.state.ChainID
for {
rs := cs.GetRoundState()

View File

@ -1,9 +1,11 @@
package core
import (
"bytes"
"time"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
cmn "github.com/tendermint/tmlibs/common"
)
@ -48,7 +50,10 @@ import (
// "remote_addr": "",
// "network": "test-chain-qhVCa2",
// "moniker": "vagrant-ubuntu-trusty-64",
// "pub_key": "844981FE99ABB19F7816F2D5E94E8A74276AB1153760A7799E925C75401856C6"
// "pub_key": "844981FE99ABB19F7816F2D5E94E8A74276AB1153760A7799E925C75401856C6",
// "validator_status": {
// "voting_power": 10
// }
// }
// },
// "id": "",
@ -72,12 +77,50 @@ func Status() (*ctypes.ResultStatus, error) {
latestBlockTime := time.Unix(0, latestBlockTimeNano)
return &ctypes.ResultStatus{
result := &ctypes.ResultStatus{
NodeInfo: p2pSwitch.NodeInfo(),
PubKey: pubKey,
LatestBlockHash: latestBlockHash,
LatestAppHash: latestAppHash,
LatestBlockHeight: latestHeight,
LatestBlockTime: latestBlockTime,
Syncing: consensusReactor.FastSync()}, nil
Syncing: consensusReactor.FastSync(),
}
// add ValidatorStatus if node is a validator
if val := validatorAtHeight(latestHeight); val != nil {
result.ValidatorStatus = ctypes.ValidatorStatus{
VotingPower: val.VotingPower,
}
}
return result, nil
}
func validatorAtHeight(h int64) *types.Validator {
lastBlockHeight, vals := consensusState.GetValidators()
privValAddress := pubKey.Address()
// if we're still at height h, search in the current validator set
if lastBlockHeight == h {
for _, val := range vals {
if bytes.Equal(val.Address, privValAddress) {
return val
}
}
}
// if we've moved to the next height, retrieve the validator set from DB
if lastBlockHeight > h {
vals, err := sm.LoadValidators(stateDB, h)
if err != nil {
// should not happen
return nil
}
_, val := vals.GetByAddress(privValAddress)
return val
}
return nil
}

View File

@ -54,14 +54,19 @@ func NewResultCommit(header *types.Header, commit *types.Commit,
}
}
type ValidatorStatus struct {
VotingPower int64 `json:"voting_power"`
}
type ResultStatus struct {
NodeInfo p2p.NodeInfo `json:"node_info"`
PubKey crypto.PubKey `json:"pub_key"`
LatestBlockHash cmn.HexBytes `json:"latest_block_hash"`
LatestAppHash cmn.HexBytes `json:"latest_app_hash"`
LatestBlockHeight int64 `json:"latest_block_height"`
LatestBlockTime time.Time `json:"latest_block_time"`
Syncing bool `json:"syncing"`
NodeInfo p2p.NodeInfo `json:"node_info"`
PubKey crypto.PubKey `json:"pub_key"`
LatestBlockHash cmn.HexBytes `json:"latest_block_hash"`
LatestAppHash cmn.HexBytes `json:"latest_app_hash"`
LatestBlockHeight int64 `json:"latest_block_height"`
LatestBlockTime time.Time `json:"latest_block_time"`
Syncing bool `json:"syncing"`
ValidatorStatus ValidatorStatus `json:"validator_status,omitempty"`
}
func (s *ResultStatus) TxIndexEnabled() bool {

View File

@ -83,26 +83,30 @@ func (valSet *ValidatorSet) Copy() *ValidatorSet {
}
}
// HasAddress returns true if address given is in the validator set, false -
// otherwise.
func (valSet *ValidatorSet) HasAddress(address []byte) bool {
idx := sort.Search(len(valSet.Validators), func(i int) bool {
return bytes.Compare(address, valSet.Validators[i].Address) <= 0
})
return idx != len(valSet.Validators) && bytes.Equal(valSet.Validators[idx].Address, address)
return idx < len(valSet.Validators) && bytes.Equal(valSet.Validators[idx].Address, address)
}
// GetByAddress returns an index of the validator with address and validator
// itself if found. Otherwise, -1 and nil are returned.
func (valSet *ValidatorSet) GetByAddress(address []byte) (index int, val *Validator) {
idx := sort.Search(len(valSet.Validators), func(i int) bool {
return bytes.Compare(address, valSet.Validators[i].Address) <= 0
})
if idx != len(valSet.Validators) && bytes.Equal(valSet.Validators[idx].Address, address) {
if idx < len(valSet.Validators) && bytes.Equal(valSet.Validators[idx].Address, address) {
return idx, valSet.Validators[idx].Copy()
}
return 0, nil
return -1, nil
}
// GetByIndex returns the validator by index.
// It returns nil values if index < 0 or
// index >= len(ValidatorSet.Validators)
// GetByIndex returns the validator's address and validator itself by index.
// It returns nil values if index is less than 0 or greater or equal to
// len(ValidatorSet.Validators).
func (valSet *ValidatorSet) GetByIndex(index int) (address []byte, val *Validator) {
if index < 0 || index >= len(valSet.Validators) {
return nil, nil
@ -111,10 +115,12 @@ func (valSet *ValidatorSet) GetByIndex(index int) (address []byte, val *Validato
return val.Address, val.Copy()
}
// Size returns the length of the validator set.
func (valSet *ValidatorSet) Size() int {
return len(valSet.Validators)
}
// TotalVotingPower returns the sum of the voting powers of all validators.
func (valSet *ValidatorSet) TotalVotingPower() int64 {
if valSet.totalVotingPower == 0 {
for _, val := range valSet.Validators {
@ -125,6 +131,8 @@ func (valSet *ValidatorSet) TotalVotingPower() int64 {
return valSet.totalVotingPower
}
// GetProposer returns the current proposer. If the validator set is empty, nil
// is returned.
func (valSet *ValidatorSet) GetProposer() (proposer *Validator) {
if len(valSet.Validators) == 0 {
return nil
@ -145,6 +153,8 @@ func (valSet *ValidatorSet) findProposer() *Validator {
return proposer
}
// Hash returns the Merkle root hash build using validators (as leaves) in the
// set.
func (valSet *ValidatorSet) Hash() []byte {
if len(valSet.Validators) == 0 {
return nil
@ -156,12 +166,14 @@ func (valSet *ValidatorSet) Hash() []byte {
return merkle.SimpleHashFromHashers(hashers)
}
// Add adds val to the validator set and returns true. It returns false if val
// is already in the set.
func (valSet *ValidatorSet) Add(val *Validator) (added bool) {
val = val.Copy()
idx := sort.Search(len(valSet.Validators), func(i int) bool {
return bytes.Compare(val.Address, valSet.Validators[i].Address) <= 0
})
if idx == len(valSet.Validators) {
if idx >= len(valSet.Validators) {
valSet.Validators = append(valSet.Validators, val)
// Invalidate cache
valSet.Proposer = nil
@ -182,6 +194,8 @@ func (valSet *ValidatorSet) Add(val *Validator) (added bool) {
}
}
// Update updates val and returns true. It returns false if val is not present
// in the set.
func (valSet *ValidatorSet) Update(val *Validator) (updated bool) {
index, sameVal := valSet.GetByAddress(val.Address)
if sameVal == nil {
@ -194,11 +208,13 @@ func (valSet *ValidatorSet) Update(val *Validator) (updated bool) {
return true
}
// Remove deletes the validator with address. It returns the validator removed
// and true. If returns nil and false if validator is not present in the set.
func (valSet *ValidatorSet) Remove(address []byte) (val *Validator, removed bool) {
idx := sort.Search(len(valSet.Validators), func(i int) bool {
return bytes.Compare(address, valSet.Validators[i].Address) <= 0
})
if idx == len(valSet.Validators) || !bytes.Equal(valSet.Validators[idx].Address, address) {
if idx >= len(valSet.Validators) || !bytes.Equal(valSet.Validators[idx].Address, address) {
return nil, false
}
removedVal := valSet.Validators[idx]
@ -213,6 +229,7 @@ func (valSet *ValidatorSet) Remove(address []byte) (val *Validator, removed bool
return removedVal, true
}
// Iterate will run the given function over the set.
func (valSet *ValidatorSet) Iterate(fn func(index int, val *Validator) bool) {
for i, val := range valSet.Validators {
stop := fn(i, val.Copy())