mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 14:52:17 +00:00
Merge pull request #1560 from tendermint/jae/hotfix-update-validBlockRule
Suggested changes to consensus/reactor.go
This commit is contained in:
commit
7bde50ca1c
@ -696,10 +696,8 @@ func (conR *ConsensusReactor) gossipVotesForHeight(logger log.Logger, rs *cstype
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If there are POL prevotes to send...
|
||||||
if prs.Step <= cstypes.RoundStepCommit && prs.Round != -1 && prs.Round <= rs.Round {
|
if prs.Step <= cstypes.RoundStepPropose && prs.Round != -1 && prs.Round <= rs.Round && prs.ProposalPOLRound != -1 {
|
||||||
// If there are POLPrevotes to send...
|
|
||||||
if prs.ProposalPOLRound != -1 {
|
|
||||||
if polPrevotes := rs.Votes.Prevotes(prs.ProposalPOLRound); polPrevotes != nil {
|
if polPrevotes := rs.Votes.Prevotes(prs.ProposalPOLRound); polPrevotes != nil {
|
||||||
if ps.PickSendVote(polPrevotes) {
|
if ps.PickSendVote(polPrevotes) {
|
||||||
logger.Debug("Picked rs.Prevotes(prs.ProposalPOLRound) to send",
|
logger.Debug("Picked rs.Prevotes(prs.ProposalPOLRound) to send",
|
||||||
@ -708,19 +706,37 @@ func (conR *ConsensusReactor) gossipVotesForHeight(logger log.Logger, rs *cstype
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are prevotes to send...
|
// If there are prevotes to send...
|
||||||
|
if prs.Step <= cstypes.RoundStepPrevoteWait && prs.Round != -1 && prs.Round <= rs.Round {
|
||||||
if ps.PickSendVote(rs.Votes.Prevotes(prs.Round)) {
|
if ps.PickSendVote(rs.Votes.Prevotes(prs.Round)) {
|
||||||
logger.Debug("Picked rs.Prevotes(prs.Round) to send", "round", prs.Round)
|
logger.Debug("Picked rs.Prevotes(prs.Round) to send", "round", prs.Round)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// If there are precommits to send...
|
// If there are precommits to send...
|
||||||
|
if prs.Step <= cstypes.RoundStepPrecommitWait && prs.Round != -1 && prs.Round <= rs.Round {
|
||||||
if ps.PickSendVote(rs.Votes.Precommits(prs.Round)) {
|
if ps.PickSendVote(rs.Votes.Precommits(prs.Round)) {
|
||||||
logger.Debug("Picked rs.Precommits(prs.Round) to send", "round", prs.Round)
|
logger.Debug("Picked rs.Precommits(prs.Round) to send", "round", prs.Round)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If there are prevotes to send...Needed because of validBlock mechanism
|
||||||
|
if prs.Round != -1 && prs.Round <= rs.Round {
|
||||||
|
if ps.PickSendVote(rs.Votes.Prevotes(prs.Round)) {
|
||||||
|
logger.Debug("Picked rs.Prevotes(prs.Round) to send", "round", prs.Round)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If there are POLPrevotes to send...
|
||||||
|
if prs.ProposalPOLRound != -1 {
|
||||||
|
if polPrevotes := rs.Votes.Prevotes(prs.ProposalPOLRound); polPrevotes != nil {
|
||||||
|
if ps.PickSendVote(polPrevotes) {
|
||||||
|
logger.Debug("Picked rs.Prevotes(prs.ProposalPOLRound) to send",
|
||||||
|
"round", prs.ProposalPOLRound)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -992,7 +992,7 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) {
|
|||||||
|
|
||||||
blockID, ok := cs.Votes.Prevotes(round).TwoThirdsMajority()
|
blockID, ok := cs.Votes.Prevotes(round).TwoThirdsMajority()
|
||||||
|
|
||||||
// If we don't have a polka, we must precommit nil
|
// If we don't have a polka, we must precommit nil.
|
||||||
if !ok {
|
if !ok {
|
||||||
if cs.LockedBlock != nil {
|
if cs.LockedBlock != nil {
|
||||||
cs.Logger.Info("enterPrecommit: No +2/3 prevotes during enterPrecommit while we're locked. Precommitting nil")
|
cs.Logger.Info("enterPrecommit: No +2/3 prevotes during enterPrecommit while we're locked. Precommitting nil")
|
||||||
@ -1003,10 +1003,10 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point +2/3 prevoted for a particular block or nil
|
// At this point +2/3 prevoted for a particular block or nil.
|
||||||
cs.eventBus.PublishEventPolka(cs.RoundStateEvent())
|
cs.eventBus.PublishEventPolka(cs.RoundStateEvent())
|
||||||
|
|
||||||
// the latest POLRound should be this round
|
// the latest POLRound should be this round.
|
||||||
polRound, _ := cs.Votes.POLInfo()
|
polRound, _ := cs.Votes.POLInfo()
|
||||||
if polRound < round {
|
if polRound < round {
|
||||||
cmn.PanicSanity(cmn.Fmt("This POLRound should be %v but got %", round, polRound))
|
cmn.PanicSanity(cmn.Fmt("This POLRound should be %v but got %", round, polRound))
|
||||||
@ -1307,19 +1307,20 @@ func (cs *ConsensusState) addProposalBlockPart(height int64, part *types.Part, v
|
|||||||
// NOTE: it's possible to receive complete proposal blocks for future rounds without having the proposal
|
// NOTE: it's possible to receive complete proposal blocks for future rounds without having the proposal
|
||||||
cs.Logger.Info("Received complete proposal block", "height", cs.ProposalBlock.Height, "hash", cs.ProposalBlock.Hash())
|
cs.Logger.Info("Received complete proposal block", "height", cs.ProposalBlock.Height, "hash", cs.ProposalBlock.Hash())
|
||||||
|
|
||||||
// Update ValidBlock
|
// Update Valid* if we can.
|
||||||
prevotes := cs.Votes.Prevotes(cs.Round)
|
prevotes := cs.Votes.Prevotes(cs.Round)
|
||||||
blockID, ok := prevotes.TwoThirdsMajority()
|
blockID, hasTwoThirds := prevotes.TwoThirdsMajority()
|
||||||
if ok && !blockID.IsZero() && (cs.ValidRound < cs.Round) {
|
if hasTwoThirds && !blockID.IsZero() && (cs.ValidRound < cs.Round) {
|
||||||
// update valid value
|
|
||||||
if cs.ProposalBlock.HashesTo(blockID.Hash) {
|
if cs.ProposalBlock.HashesTo(blockID.Hash) {
|
||||||
cs.ValidRound = cs.Round
|
cs.ValidRound = cs.Round
|
||||||
cs.ValidBlock = cs.ProposalBlock
|
cs.ValidBlock = cs.ProposalBlock
|
||||||
cs.ValidBlockParts = cs.ProposalBlockParts
|
cs.ValidBlockParts = cs.ProposalBlockParts
|
||||||
}
|
}
|
||||||
//TODO: In case there is +2/3 majority in Prevotes set for some block and cs.ProposalBlock contains different block,
|
// TODO: In case there is +2/3 majority in Prevotes set for some
|
||||||
//either proposer is faulty or voting power of faulty processes is more than 1/3. We should
|
// block and cs.ProposalBlock contains different block, either
|
||||||
//trigger in the future accountability procedure at this point.
|
// proposer is faulty or voting power of faulty processes is more
|
||||||
|
// than 1/3. We should trigger in the future accountability
|
||||||
|
// procedure at this point.
|
||||||
}
|
}
|
||||||
|
|
||||||
if cs.Step == cstypes.RoundStepPropose && cs.isProposalComplete() {
|
if cs.Step == cstypes.RoundStepPropose && cs.isProposalComplete() {
|
||||||
@ -1412,33 +1413,43 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool,
|
|||||||
case types.VoteTypePrevote:
|
case types.VoteTypePrevote:
|
||||||
prevotes := cs.Votes.Prevotes(vote.Round)
|
prevotes := cs.Votes.Prevotes(vote.Round)
|
||||||
cs.Logger.Info("Added to prevote", "vote", vote, "prevotes", prevotes.StringShort())
|
cs.Logger.Info("Added to prevote", "vote", vote, "prevotes", prevotes.StringShort())
|
||||||
blockID, ok := prevotes.TwoThirdsMajority()
|
|
||||||
|
// If +2/3 prevotes for a block or nil for *any* round:
|
||||||
|
if blockID, ok := prevotes.TwoThirdsMajority(); ok {
|
||||||
|
|
||||||
// First, unlock if prevotes is a valid POL.
|
// First, unlock if prevotes is a valid POL.
|
||||||
// >> lockRound < POLRound <= unlockOrChangeLockRound (see spec)
|
// `lockRound < POLRound <= unlockOrChangeLockRound (see spec)`
|
||||||
// NOTE: If (lockRound < POLRound) but !(POLRound <= unlockOrChangeLockRound),
|
// NOTE: If `lockRound < POLRound` but `!(POLRound <=
|
||||||
// we'll still enterNewRound(H,vote.R) and enterPrecommit(H,vote.R) to process it
|
// unlockOrChangeLockRound)`, we'll still enterNewRound(H,vote.R)
|
||||||
// there.
|
// and enterPrecommit(H,vote.R) to process it there.
|
||||||
if (cs.LockedBlock != nil) && (cs.LockedRound < vote.Round) && (vote.Round <= cs.Round) {
|
if (cs.LockedBlock != nil) &&
|
||||||
if ok && !cs.LockedBlock.HashesTo(blockID.Hash) {
|
(cs.LockedRound < vote.Round) &&
|
||||||
|
(vote.Round <= cs.Round) &&
|
||||||
|
!cs.LockedBlock.HashesTo(blockID.Hash) {
|
||||||
|
|
||||||
cs.Logger.Info("Unlocking because of POL.", "lockedRound", cs.LockedRound, "POLRound", vote.Round)
|
cs.Logger.Info("Unlocking because of POL.", "lockedRound", cs.LockedRound, "POLRound", vote.Round)
|
||||||
cs.LockedRound = 0
|
cs.LockedRound = 0
|
||||||
cs.LockedBlock = nil
|
cs.LockedBlock = nil
|
||||||
cs.LockedBlockParts = nil
|
cs.LockedBlockParts = nil
|
||||||
cs.eventBus.PublishEventUnlock(cs.RoundStateEvent())
|
cs.eventBus.PublishEventUnlock(cs.RoundStateEvent())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Update ValidBlock
|
// Update Valid* if we can.
|
||||||
if ok && !blockID.IsZero() && (cs.ValidRound < vote.Round) && (vote.Round <= cs.Round) {
|
if !blockID.IsZero() &&
|
||||||
// update valid value
|
(cs.ValidRound < vote.Round) &&
|
||||||
if cs.ProposalBlock.HashesTo(blockID.Hash) {
|
(vote.Round <= cs.Round) &&
|
||||||
|
cs.ProposalBlock.HashesTo(blockID.Hash) {
|
||||||
|
|
||||||
cs.ValidRound = vote.Round
|
cs.ValidRound = vote.Round
|
||||||
cs.ValidBlock = cs.ProposalBlock
|
cs.ValidBlock = cs.ProposalBlock
|
||||||
cs.ValidBlockParts = cs.ProposalBlockParts
|
cs.ValidBlockParts = cs.ProposalBlockParts
|
||||||
|
// TODO: We might want to update ValidBlock also in case we
|
||||||
|
// don't have that block yet, and obtain the required block
|
||||||
|
// using gossiping
|
||||||
}
|
}
|
||||||
//TODO: We might want to update ValidBlock also in case we don't have that block yet,
|
|
||||||
// and obtain the required block using gossiping
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If +2/3 prevotes for *anything* for this or future round:
|
||||||
if cs.Round <= vote.Round && prevotes.HasTwoThirdsAny() {
|
if cs.Round <= vote.Round && prevotes.HasTwoThirdsAny() {
|
||||||
// Round-skip over to PrevoteWait or goto Precommit.
|
// Round-skip over to PrevoteWait or goto Precommit.
|
||||||
cs.enterNewRound(height, vote.Round) // if the vote is ahead of us
|
cs.enterNewRound(height, vote.Round) // if the vote is ahead of us
|
||||||
@ -1454,6 +1465,7 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool,
|
|||||||
cs.enterPrevote(height, cs.Round)
|
cs.enterPrevote(height, cs.Round)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case types.VoteTypePrecommit:
|
case types.VoteTypePrecommit:
|
||||||
precommits := cs.Votes.Precommits(vote.Round)
|
precommits := cs.Votes.Precommits(vote.Round)
|
||||||
cs.Logger.Info("Added to precommit", "vote", vote, "precommits", precommits.StringShort())
|
cs.Logger.Info("Added to precommit", "vote", vote, "precommits", precommits.StringShort())
|
||||||
|
@ -67,9 +67,9 @@ type RoundState struct {
|
|||||||
LockedRound int
|
LockedRound int
|
||||||
LockedBlock *types.Block
|
LockedBlock *types.Block
|
||||||
LockedBlockParts *types.PartSet
|
LockedBlockParts *types.PartSet
|
||||||
ValidRound int
|
ValidRound int // Last known round with POL for non-nil valid block.
|
||||||
ValidBlock *types.Block
|
ValidBlock *types.Block // Last known block of POL mentioned above.
|
||||||
ValidBlockParts *types.PartSet
|
ValidBlockParts *types.PartSet // Last known block parts of POL metnioned above.
|
||||||
Votes *HeightVoteSet
|
Votes *HeightVoteSet
|
||||||
CommitRound int //
|
CommitRound int //
|
||||||
LastCommit *types.VoteSet // Last precommits at Height-1
|
LastCommit *types.VoteSet // Last precommits at Height-1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user