From 26c192b047f304591078fd23e1b11855794aa94f Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 26 Jun 2015 17:48:24 -0700 Subject: [PATCH] Fix consensus: * Use LastValidators when a Vote is received for the last height. * Fix Validation.Height/Round to use FirstPrecommit. --- consensus/reactor.go | 8 +++++--- consensus/state.go | 4 ++++ types/block.go | 25 +++++++++++++++++++++---- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/consensus/reactor.go b/consensus/reactor.go index 236f8e8f6..971a677bb 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -177,18 +177,20 @@ func (conR *ConsensusReactor) Receive(chId byte, peer *p2p.Peer, msgBytes []byte switch msg := msg_.(type) { case *VoteMessage: vote := msg.Vote - var validators *ValidatorSet + var validators *sm.ValidatorSet if rs.Height == vote.Height { validators = rs.Validators } else if rs.Height == vote.Height+1 { - validators = rs.LastBondedValidators if !(rs.Step == RoundStepNewHeight && vote.Type == types.VoteTypePrecommit) { return // Wrong height, not a LastCommit straggler commit. } + validators = rs.LastValidators } else { return // Wrong height. Not necessarily a bad peer. } - VOTE_PASS: + + // We have vote/validators. Height may not be rs.Height + address, _ := validators.GetByIndex(msg.ValidatorIndex) added, index, err := conR.conS.AddVote(address, vote, peer.Key) if err != nil { diff --git a/consensus/state.go b/consensus/state.go index b74e9a0d8..1c6820f31 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -215,6 +215,7 @@ type RoundState struct { LockedBlockParts *types.PartSet Votes *HeightVoteSet LastCommit *VoteSet // Last precommits at Height-1 + LastValidators *sm.ValidatorSet } func (rs *RoundState) String() string { @@ -233,6 +234,7 @@ func (rs *RoundState) StringIndented(indent string) string { %s LockedBlock: %v %v %s Votes: %v %s LastCommit: %v +%s LastValidators: %v %s}`, indent, rs.Height, rs.Round, rs.Step, indent, rs.StartTime, @@ -244,6 +246,7 @@ func (rs *RoundState) StringIndented(indent string) string { indent, rs.LockedBlockParts.StringShort(), rs.LockedBlock.StringShort(), indent, rs.Votes.StringIndented(indent+" "), indent, rs.LastCommit.StringShort(), + indent, rs.LastValidators.StringIndented(indent+" "), indent) } @@ -406,6 +409,7 @@ func (cs *ConsensusState) updateToState(state *sm.State, contiguous bool) { cs.LockedBlockParts = nil cs.Votes = NewHeightVoteSet(height, validators) cs.LastCommit = lastPrecommits + cs.LastValidators = state.LastBondedValidators cs.state = state cs.stagedBlock = nil diff --git a/types/block.go b/types/block.go index 2fdf9f1df..6f004a935 100644 --- a/types/block.go +++ b/types/block.go @@ -184,22 +184,39 @@ type Validation struct { Precommits []*Vote `json:"precommits"` // Volatile - hash []byte - bitArray *BitArray + firstPrecommit *Vote + hash []byte + bitArray *BitArray +} + +func (v *Validation) FirstPrecommit() *Vote { + if len(v.Precommits) == 0 { + return nil + } + if v.firstPrecommit != nil { + return v.firstPrecommit + } + for _, precommit := range v.Precommits { + if precommit != nil { + v.firstPrecommit = precommit + return precommit + } + } + return nil } func (v *Validation) Height() int { if len(v.Precommits) == 0 { return 0 } - return v.Precommits[0].Height + return v.FirstPrecommit().Height } func (v *Validation) Round() int { if len(v.Precommits) == 0 { return 0 } - return v.Precommits[0].Round + return v.FirstPrecommit().Round } func (v *Validation) ValidateBasic() error {