From 658060150c127fbbd5eaa4629ba6e7db745506ae Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 13 May 2018 19:17:25 -0400 Subject: [PATCH] rpc: add voting power totals to vote bitarrays --- consensus/state.go | 1 + consensus/types/height_vote_set.go | 23 +++++++----- rpc/core/types/responses.go | 3 +- types/vote_set.go | 58 +++++++++++++++++++++++++----- 4 files changed, 66 insertions(+), 19 deletions(-) diff --git a/consensus/state.go b/consensus/state.go index 40b8f16d5..10bbb15f7 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1279,6 +1279,7 @@ func (cs *ConsensusState) defaultSetProposal(proposal *types.Proposal) error { cs.Proposal = proposal cs.ProposalBlockParts = types.NewPartSetFromHeader(proposal.BlockPartsHeader) + cs.Logger.Info("Received proposal", "proposal", proposal) return nil } diff --git a/consensus/types/height_vote_set.go b/consensus/types/height_vote_set.go index f65f365b8..a861571e0 100644 --- a/consensus/types/height_vote_set.go +++ b/consensus/types/height_vote_set.go @@ -207,23 +207,28 @@ func (hvs *HeightVoteSet) StringIndented(indent string) string { indent) } -type roundVoteBitArrays struct { - Round int `json:"round"` - Prevotes *cmn.BitArray `json:"prevotes"` - Precommits *cmn.BitArray `json:"precommits"` +// `"__xx_xx____x:46/100:0.46"` +type roundVotes struct { + Round int `json:"round"` + Prevotes []string `json:"prevotes"` + PrevotesBitArray string `json:"prevotes_bit_array"` + Precommits []string `json:"precommits"` + PrecommitsBitArray string `json:"precommits_bit_array"` } func (hvs *HeightVoteSet) MarshalJSON() ([]byte, error) { hvs.mtx.Lock() defer hvs.mtx.Unlock() totalRounds := hvs.round + 1 - roundsVotes := make([]roundVoteBitArrays, totalRounds) + roundsVotes := make([]roundVotes, totalRounds) // rounds 0 ~ hvs.round inclusive for round := 0; round < totalRounds; round++ { - roundsVotes[round] = roundVoteBitArrays{ - Round: round, - Prevotes: hvs.roundVoteSets[round].Prevotes.BitArray(), - Precommits: hvs.roundVoteSets[round].Precommits.BitArray(), + roundsVotes[round] = roundVotes{ + Round: round, + Prevotes: hvs.roundVoteSets[round].Prevotes.VoteStrings(), + PrevotesBitArray: hvs.roundVoteSets[round].Prevotes.BitArrayString(), + Precommits: hvs.roundVoteSets[round].Precommits.VoteStrings(), + PrecommitsBitArray: hvs.roundVoteSets[round].Precommits.BitArrayString(), } } // TODO: all other peer catchup rounds diff --git a/rpc/core/types/responses.go b/rpc/core/types/responses.go index eb0f46f97..41d765bf9 100644 --- a/rpc/core/types/responses.go +++ b/rpc/core/types/responses.go @@ -128,12 +128,13 @@ type ResultValidators struct { } // Info about the consensus state. -// Unstable +// UNSTABLE type ResultDumpConsensusState struct { RoundState json.RawMessage `json:"round_state"` Peers []PeerStateInfo `json:"peers"` } +// UNSTABLE type PeerStateInfo struct { NodeAddress string `json:"node_address"` PeerState json.RawMessage `json:"peer_state"` diff --git a/types/vote_set.go b/types/vote_set.go index c5c72d435..cde15e19b 100644 --- a/types/vote_set.go +++ b/types/vote_set.go @@ -454,6 +454,44 @@ func (voteSet *VoteSet) StringIndented(indent string) string { func (voteSet *VoteSet) MarshalJSON() ([]byte, error) { voteSet.mtx.Lock() defer voteSet.mtx.Unlock() + return cdc.MarshalJSON(VoteSetJSON{ + voteSet.voteStrings(), + voteSet.bitArrayString(), + voteSet.peerMaj23s, + }) +} + +// More human readable JSON of the vote set +// NOTE: insufficient for unmarshalling from (compressed votes) +// TODO: make the peerMaj23s nicer to read (eg just the block hash) +type VoteSetJSON struct { + Votes []string `json:"votes"` + VotesBitArray string `json:"votes_bit_array"` + PeerMaj23s map[P2PID]BlockID `json:"peer_maj_23s"` +} + +// Return the bit-array of votes including the fraction of power +// that has voted eg. "__x_xxx_:6/20 = 0.3". +func (voteSet *VoteSet) BitArrayString() string { + voteSet.mtx.Lock() + defer voteSet.mtx.Unlock() + return voteSet.bitArrayString() +} + +func (voteSet *VoteSet) bitArrayString() string { + bAString := voteSet.votesBitArray.String() + voted, total, fracVoted := voteSet.sumTotalFrac() + return fmt.Sprintf("%s %d/%d = %.2f", bAString, voted, total, fracVoted) +} + +// Returns a list of votes compressed to more readable strings. +func (voteSet *VoteSet) VoteStrings() []string { + voteSet.mtx.Lock() + defer voteSet.mtx.Unlock() + return voteSet.voteStrings() +} + +func (voteSet *VoteSet) voteStrings() []string { voteStrings := make([]string, len(voteSet.votes)) for i, vote := range voteSet.votes { if vote == nil { @@ -462,13 +500,7 @@ func (voteSet *VoteSet) MarshalJSON() ([]byte, error) { voteStrings[i] = vote.String() } } - return cdc.MarshalJSON(struct { - Votes []string `json:"votes"` - VotesBitArray *cmn.BitArray `json:"votes_bit_array"` - PeerMaj23s map[P2PID]BlockID `json:"peer_maj_23s"` - }{ - voteStrings, voteSet.votesBitArray, voteSet.peerMaj23s, - }) + return voteStrings } func (voteSet *VoteSet) StringShort() string { @@ -477,8 +509,16 @@ func (voteSet *VoteSet) StringShort() string { } voteSet.mtx.Lock() defer voteSet.mtx.Unlock() - return fmt.Sprintf(`VoteSet{H:%v R:%v T:%v +2/3:%v %v %v}`, - voteSet.height, voteSet.round, voteSet.type_, voteSet.maj23, voteSet.votesBitArray, voteSet.peerMaj23s) + _, _, frac := voteSet.sumTotalFrac() + return fmt.Sprintf(`VoteSet{H:%v R:%v T:%v +2/3:%v(%v) %v %v}`, + voteSet.height, voteSet.round, voteSet.type_, voteSet.maj23, frac, voteSet.votesBitArray, voteSet.peerMaj23s) +} + +// return the power voted, the total, and the fraction +func (voteSet *VoteSet) sumTotalFrac() (int64, int64, float64) { + voted, total := voteSet.sum, voteSet.valSet.TotalVotingPower() + fracVoted := float64(voted) / float64(total) + return voted, total, fracVoted } //--------------------------------------------------------------------------------