mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-26 15:22:15 +00:00
parent
c4157549ab
commit
c20fbed2f7
@ -94,7 +94,6 @@ type ConsensusState struct {
|
|||||||
// internal state
|
// internal state
|
||||||
mtx sync.RWMutex
|
mtx sync.RWMutex
|
||||||
cstypes.RoundState
|
cstypes.RoundState
|
||||||
triggeredTimeoutPrecommit bool
|
|
||||||
state sm.State // State until height-1.
|
state sm.State // State until height-1.
|
||||||
|
|
||||||
// state changes may be triggered by: msgs from peers,
|
// state changes may be triggered by: msgs from peers,
|
||||||
@ -732,6 +731,7 @@ func (cs *ConsensusState) handleTxsAvailable() {
|
|||||||
cs.mtx.Lock()
|
cs.mtx.Lock()
|
||||||
defer cs.mtx.Unlock()
|
defer cs.mtx.Unlock()
|
||||||
// we only need to do this for round 0
|
// we only need to do this for round 0
|
||||||
|
cs.enterNewRound(cs.Height, 0)
|
||||||
cs.enterPropose(cs.Height, 0)
|
cs.enterPropose(cs.Height, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -782,7 +782,7 @@ func (cs *ConsensusState) enterNewRound(height int64, round int) {
|
|||||||
cs.ProposalBlockParts = nil
|
cs.ProposalBlockParts = nil
|
||||||
}
|
}
|
||||||
cs.Votes.SetRound(round + 1) // also track next round (round+1) to allow round-skipping
|
cs.Votes.SetRound(round + 1) // also track next round (round+1) to allow round-skipping
|
||||||
cs.triggeredTimeoutPrecommit = false
|
cs.TriggeredTimeoutPrecommit = false
|
||||||
|
|
||||||
cs.eventBus.PublishEventNewRound(cs.NewRoundEvent())
|
cs.eventBus.PublishEventNewRound(cs.NewRoundEvent())
|
||||||
cs.metrics.Rounds.Set(float64(round))
|
cs.metrics.Rounds.Set(float64(round))
|
||||||
@ -1128,12 +1128,12 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) {
|
|||||||
func (cs *ConsensusState) enterPrecommitWait(height int64, round int) {
|
func (cs *ConsensusState) enterPrecommitWait(height int64, round int) {
|
||||||
logger := cs.Logger.With("height", height, "round", round)
|
logger := cs.Logger.With("height", height, "round", round)
|
||||||
|
|
||||||
if cs.Height != height || round < cs.Round || (cs.Round == round && cs.triggeredTimeoutPrecommit) {
|
if cs.Height != height || round < cs.Round || (cs.Round == round && cs.TriggeredTimeoutPrecommit) {
|
||||||
logger.Debug(
|
logger.Debug(
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
"enterPrecommitWait(%v/%v): Invalid args. "+
|
"enterPrecommitWait(%v/%v): Invalid args. "+
|
||||||
"Current state is Height/Round: %v/%v/, triggeredTimeoutPrecommit:%v",
|
"Current state is Height/Round: %v/%v/, TriggeredTimeoutPrecommit:%v",
|
||||||
height, round, cs.Height, cs.Round, cs.triggeredTimeoutPrecommit))
|
height, round, cs.Height, cs.Round, cs.TriggeredTimeoutPrecommit))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !cs.Votes.Precommits(round).HasTwoThirdsAny() {
|
if !cs.Votes.Precommits(round).HasTwoThirdsAny() {
|
||||||
@ -1143,7 +1143,7 @@ func (cs *ConsensusState) enterPrecommitWait(height int64, round int) {
|
|||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
// Done enterPrecommitWait:
|
// Done enterPrecommitWait:
|
||||||
cs.triggeredTimeoutPrecommit = true
|
cs.TriggeredTimeoutPrecommit = true
|
||||||
cs.newStep()
|
cs.newStep()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -1279,6 +1279,71 @@ func TestCommitFromPreviousRound(t *testing.T) {
|
|||||||
ensureNewRound(newRoundCh, height+1, 0)
|
ensureNewRound(newRoundCh, height+1, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type fakeTxNotifier struct {
|
||||||
|
ch chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *fakeTxNotifier) TxsAvailable() <-chan struct{} {
|
||||||
|
return n.ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *fakeTxNotifier) Notify() {
|
||||||
|
n.ch <- struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStartNextHeightCorrectly(t *testing.T) {
|
||||||
|
cs1, vss := randConsensusState(4)
|
||||||
|
cs1.config.SkipTimeoutCommit = false
|
||||||
|
cs1.txNotifier = &fakeTxNotifier{ch: make(chan struct{})}
|
||||||
|
|
||||||
|
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
|
||||||
|
height, round := cs1.Height, cs1.Round
|
||||||
|
|
||||||
|
proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal)
|
||||||
|
timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose)
|
||||||
|
|
||||||
|
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
|
||||||
|
newBlockHeader := subscribe(cs1.eventBus, types.EventQueryNewBlockHeader)
|
||||||
|
addr := cs1.privValidator.GetPubKey().Address()
|
||||||
|
voteCh := subscribeToVoter(cs1, addr)
|
||||||
|
|
||||||
|
// start round and wait for propose and prevote
|
||||||
|
startTestRound(cs1, height, round)
|
||||||
|
ensureNewRound(newRoundCh, height, round)
|
||||||
|
|
||||||
|
ensureNewProposal(proposalCh, height, round)
|
||||||
|
rs := cs1.GetRoundState()
|
||||||
|
theBlockHash := rs.ProposalBlock.Hash()
|
||||||
|
theBlockParts := rs.ProposalBlockParts.Header()
|
||||||
|
|
||||||
|
ensurePrevote(voteCh, height, round)
|
||||||
|
validatePrevote(t, cs1, round, vss[0], theBlockHash)
|
||||||
|
|
||||||
|
signAddVotes(cs1, types.PrevoteType, theBlockHash, theBlockParts, vs2, vs3, vs4)
|
||||||
|
|
||||||
|
ensurePrecommit(voteCh, height, round)
|
||||||
|
// the proposed block should now be locked and our precommit added
|
||||||
|
validatePrecommit(t, cs1, round, round, vss[0], theBlockHash, theBlockHash)
|
||||||
|
|
||||||
|
rs = cs1.GetRoundState()
|
||||||
|
|
||||||
|
// add precommits
|
||||||
|
signAddVotes(cs1, types.PrecommitType, nil, types.PartSetHeader{}, vs2)
|
||||||
|
signAddVotes(cs1, types.PrecommitType, theBlockHash, theBlockParts, vs3)
|
||||||
|
signAddVotes(cs1, types.PrecommitType, theBlockHash, theBlockParts, vs4)
|
||||||
|
|
||||||
|
ensureNewBlockHeader(newBlockHeader, height, theBlockHash)
|
||||||
|
|
||||||
|
rs = cs1.GetRoundState()
|
||||||
|
assert.True(t, rs.TriggeredTimeoutPrecommit)
|
||||||
|
|
||||||
|
cs1.txNotifier.(*fakeTxNotifier).Notify()
|
||||||
|
|
||||||
|
ensureNewTimeout(timeoutProposeCh, height+1, round, cs1.config.TimeoutPropose.Nanoseconds())
|
||||||
|
rs = cs1.GetRoundState()
|
||||||
|
assert.False(t, rs.TriggeredTimeoutPrecommit, "triggeredTimeoutPrecommit should be false at the beginning of each round")
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
// SlashingSuite
|
// SlashingSuite
|
||||||
// TODO: Slashing
|
// TODO: Slashing
|
||||||
|
@ -84,6 +84,7 @@ type RoundState struct {
|
|||||||
CommitRound int `json:"commit_round"` //
|
CommitRound int `json:"commit_round"` //
|
||||||
LastCommit *types.VoteSet `json:"last_commit"` // Last precommits at Height-1
|
LastCommit *types.VoteSet `json:"last_commit"` // Last precommits at Height-1
|
||||||
LastValidators *types.ValidatorSet `json:"last_validators"`
|
LastValidators *types.ValidatorSet `json:"last_validators"`
|
||||||
|
TriggeredTimeoutPrecommit bool `json:"triggered_timeout_precommit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compressed version of the RoundState for use in RPC
|
// Compressed version of the RoundState for use in RPC
|
||||||
|
Loading…
x
Reference in New Issue
Block a user