From 85ded710f5da8637d2a44da5539e494dbf06f5ea Mon Sep 17 00:00:00 2001 From: William Banfield Date: Tue, 22 Nov 2022 20:44:14 -0500 Subject: [PATCH] put duplicate vote metric in place --- consensus/reactor.go | 62 +++++++++++++++++++++++++++++ consensus/types/peer_round_state.go | 4 ++ 2 files changed, 66 insertions(+) diff --git a/consensus/reactor.go b/consensus/reactor.go index e052f197a..623ca8e3a 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -349,6 +349,11 @@ func (conR *Reactor) ReceiveEnvelope(e p2p.Envelope) { ps.EnsureVoteBitArrays(height-1, lastCommitSize) ps.SetHasVote(msg.Vote) + duplicate := ps.SetReceivedVote(msg.Vote) + if duplicate { + conR.Metrics.DuplicateVoteReceive.With("peer_id", string(e.Src.ID())).Add(1) + } + cs.peerMsgQueue <- msgInfo{msg, e.Src.ID()} default: @@ -1239,6 +1244,41 @@ func (ps *PeerState) getVoteBitArray(height int64, round int32, votesType tmprot return nil } +func (ps *PeerState) getVoteReceivedBitArray(height int64, round int32, votesType tmproto.SignedMsgType) *bits.BitArray { + if !types.IsVoteTypeValid(votesType) { + return nil + } + + if ps.PRS.Height == height { + if ps.PRS.Round == round { + switch votesType { + case tmproto.PrevoteType: + return ps.PRS.PrevotesReceived + case tmproto.PrecommitType: + return ps.PRS.PrecommitsReceived + } + } + if ps.PRS.CatchupCommitRound == round { + switch votesType { + case tmproto.PrevoteType: + return nil + case tmproto.PrecommitType: + return ps.PRS.CatchupCommit + } + } + if ps.PRS.ProposalPOLRound == round { + switch votesType { + case tmproto.PrevoteType: + return ps.PRS.ProposalPOL + case tmproto.PrecommitType: + return nil + } + } + return nil + } + return nil +} + // 'round': A round for which we have a +2/3 commit. func (ps *PeerState) ensureCatchupCommitRound(height int64, round int32, numValidators int) { if ps.PRS.Height != height { @@ -1286,6 +1326,12 @@ func (ps *PeerState) ensureVoteBitArrays(height int64, numValidators int) { if ps.PRS.Precommits == nil { ps.PRS.Precommits = bits.NewBitArray(numValidators) } + if ps.PRS.PrevotesReceived == nil { + ps.PRS.PrevotesReceived = bits.NewBitArray(numValidators) + } + if ps.PRS.PrecommitsReceived == nil { + ps.PRS.PrecommitsReceived = bits.NewBitArray(numValidators) + } if ps.PRS.CatchupCommit == nil { ps.PRS.CatchupCommit = bits.NewBitArray(numValidators) } @@ -1345,6 +1391,13 @@ func (ps *PeerState) SetHasVote(vote *types.Vote) { ps.setHasVote(vote.Height, vote.Round, vote.Type, vote.ValidatorIndex) } +func (ps *PeerState) SetReceivedVote(vote *types.Vote) bool { + ps.mtx.Lock() + defer ps.mtx.Unlock() + + return ps.setReceivedVote(vote.Height, vote.Round, vote.Type, vote.ValidatorIndex) +} + func (ps *PeerState) setHasVote(height int64, round int32, voteType tmproto.SignedMsgType, index int32) { ps.logger.Debug("setHasVote", "peerH/R", @@ -1359,6 +1412,15 @@ func (ps *PeerState) setHasVote(height int64, round int32, voteType tmproto.Sign psVotes.SetIndex(int(index), true) } } +func (ps *PeerState) setReceivedVote(height int64, round int32, voteType tmproto.SignedMsgType, index int32) bool { + psVotes := ps.getVoteReceivedBitArray(height, round, voteType) + var alreadySet bool + if psVotes != nil { + alreadySet = psVotes.GetIndex(int(index)) + psVotes.SetIndex(int(index), true) + } + return alreadySet +} // ApplyNewRoundStepMessage updates the peer state for the new round. func (ps *PeerState) ApplyNewRoundStepMessage(msg *NewRoundStepMessage) { diff --git a/consensus/types/peer_round_state.go b/consensus/types/peer_round_state.go index 07283c5b4..1e9cd10cc 100644 --- a/consensus/types/peer_round_state.go +++ b/consensus/types/peer_round_state.go @@ -34,6 +34,10 @@ type PeerRoundState struct { LastCommitRound int32 `json:"last_commit_round"` // Round of commit for last height. -1 if none. LastCommit *bits.BitArray `json:"last_commit"` // All commit precommits of commit for last height. + // FOR TESTING PURPOSES + PrevotesReceived *bits.BitArray `json:"prevotes_received"` // All votes peer has for this round + PrecommitsReceived *bits.BitArray `json:"precommits_received"` // All precommits peer has for this round + // Round that we have commit for. Not necessarily unique. -1 if none. CatchupCommitRound int32 `json:"catchup_commit_round"`