mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-14 22:01:20 +00:00
Fixed tests
This commit is contained in:
@ -252,6 +252,8 @@ func NewConsensusState(state *sm.State, blockStore *bc.BlockStore, mempoolReacto
|
||||
newStepCh: make(chan *RoundState, 10),
|
||||
}
|
||||
cs.updateToState(state, true)
|
||||
// Don't call scheduleRound0 yet.
|
||||
// We do that upon Start().
|
||||
cs.maybeRebond()
|
||||
cs.reconstructLastCommit(state)
|
||||
return cs
|
||||
@ -268,7 +270,7 @@ func (cs *ConsensusState) reconstructLastCommit(state *sm.State) {
|
||||
for idx, precommit := range seenValidation.Precommits {
|
||||
precommitVote := &types.Vote{
|
||||
Height: state.LastBlockHeight,
|
||||
Round: seenValidation.Round,
|
||||
Round: seenValidation.Round(),
|
||||
Type: types.VoteTypePrecommit,
|
||||
BlockHash: state.LastBlockHash,
|
||||
BlockParts: state.LastBlockParts,
|
||||
@ -309,11 +311,12 @@ func (cs *ConsensusState) NewStepCh() chan *RoundState {
|
||||
func (cs *ConsensusState) Start() {
|
||||
if atomic.CompareAndSwapUint32(&cs.started, 0, 1) {
|
||||
log.Info("Starting ConsensusState")
|
||||
cs.scheduleRound0()
|
||||
cs.scheduleRound0(cs.Height)
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) scheduleRound0(height uint) {
|
||||
log.Debug("scheduleRound0", "now", time.Now(), "startTime", cs.StartTime)
|
||||
sleepDuration := cs.StartTime.Sub(time.Now())
|
||||
go func() {
|
||||
if sleepDuration > 0 {
|
||||
@ -423,7 +426,7 @@ func (cs *ConsensusState) SetPrivValidator(priv *sm.PrivValidator) {
|
||||
func (cs *ConsensusState) EnterNewRound(height uint, round uint) {
|
||||
cs.mtx.Lock()
|
||||
defer cs.mtx.Unlock()
|
||||
if cs.Height != height || cs.Round >= round {
|
||||
if cs.Height != height || round < cs.Round || (cs.Round == round && cs.Step != RoundStepNewHeight) {
|
||||
log.Debug(Fmt("EnterNewRound(%v/%v): Invalid args. Current step: %v/%v/%v", height, round, cs.Height, cs.Round, cs.Step))
|
||||
return
|
||||
}
|
||||
@ -432,8 +435,9 @@ func (cs *ConsensusState) EnterNewRound(height uint, round uint) {
|
||||
}
|
||||
|
||||
// Increment validators if necessary
|
||||
validators := cs.Validators
|
||||
if cs.Round < round {
|
||||
validators := cs.Validators.Copy()
|
||||
validators = validators.Copy()
|
||||
validators.IncrementAccum(round - cs.Round)
|
||||
}
|
||||
|
||||
@ -517,18 +521,23 @@ func (cs *ConsensusState) EnterPropose(height uint, round uint) {
|
||||
} else {
|
||||
log.Warn("EnterPropose: Error signing proposal", "height", cs.Height, "round", cs.Round, "error", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) isProposalComplete() bool {
|
||||
if cs.Proposal == nil || cs.ProposalBlock == nil {
|
||||
return false
|
||||
}
|
||||
return cs.Votes.Prevote(cs.Proposal.POLRound).HasTwoThirdsMajority()
|
||||
if cs.Proposal.POLRound < 0 {
|
||||
return true
|
||||
} else {
|
||||
return cs.Votes.Prevotes(uint(cs.Proposal.POLRound)).HasTwoThirdsMajority()
|
||||
}
|
||||
}
|
||||
|
||||
// Create the next block to propose and return it.
|
||||
// NOTE: make it side-effect free for clarity.
|
||||
func (cs *ConsensusState) createProposalBlock() (*types.Block, *types.PartSet) {
|
||||
func (cs *ConsensusState) createProposalBlock() (block *types.Block, blockParts *types.PartSet) {
|
||||
var validation *types.Validation
|
||||
if cs.Height == 1 {
|
||||
// We're creating a proposal for the first block.
|
||||
@ -554,7 +563,7 @@ func (cs *ConsensusState) createProposalBlock() (*types.Block, *types.PartSet) {
|
||||
LastBlockParts: cs.state.LastBlockParts,
|
||||
StateHash: nil, // Will set afterwards.
|
||||
},
|
||||
Validation: validation,
|
||||
LastValidation: validation,
|
||||
Data: &types.Data{
|
||||
Txs: txs,
|
||||
},
|
||||
@ -645,9 +654,9 @@ func (cs *ConsensusState) EnterPrevoteWait(height uint, round uint) {
|
||||
cs.Step = RoundStepPrevoteWait
|
||||
cs.newStepCh <- cs.getRoundState()
|
||||
|
||||
// After `timeoutPrevote`, EnterPrecommit()
|
||||
// After `timeoutPrevote0+timeoutPrevoteDelta*round`, EnterPrecommit()
|
||||
go func() {
|
||||
time.Sleep(timeoutPrevote)
|
||||
time.Sleep(timeoutPrevote0 + timeoutPrevote0*time.Duration(round))
|
||||
cs.EnterPrecommit(height, round)
|
||||
}()
|
||||
}
|
||||
@ -734,7 +743,7 @@ func (cs *ConsensusState) EnterPrecommit(height uint, round uint) {
|
||||
cs.ProposalBlock = nil
|
||||
cs.ProposalBlockParts = types.NewPartSetFromHeader(partsHeader)
|
||||
}
|
||||
cs.signAddVote(types.VoteTypePrecommit, nil, PartSetHeader{})
|
||||
cs.signAddVote(types.VoteTypePrecommit, nil, types.PartSetHeader{})
|
||||
return
|
||||
}
|
||||
|
||||
@ -755,9 +764,9 @@ func (cs *ConsensusState) EnterPrecommitWait(height uint, round uint) {
|
||||
cs.Step = RoundStepPrecommitWait
|
||||
cs.newStepCh <- cs.getRoundState()
|
||||
|
||||
// After `timeoutPrecommit`, EnterNewRound()
|
||||
// After `timeoutPrecommit0+timeoutPrecommitDelta*round`, EnterNewRound()
|
||||
go func() {
|
||||
time.Sleep(timeoutPrecommit)
|
||||
time.Sleep(timeoutPrecommit0 + timeoutPrecommitDelta*time.Duration(round))
|
||||
// If we have +2/3 of precommits for a particular block (or nil),
|
||||
// we already entered commit (or the next round).
|
||||
// So just try to transition to the next round,
|
||||
@ -782,11 +791,11 @@ func (cs *ConsensusState) EnterCommit(height uint) {
|
||||
cs.newStepCh <- cs.getRoundState()
|
||||
|
||||
// Maybe finalize immediately.
|
||||
cs.TryFinalizeCommit(height)
|
||||
cs.tryFinalizeCommit(height)
|
||||
}()
|
||||
|
||||
// SANITY CHECK
|
||||
hash, partsHeader, ok := cs.Precommits.TwoThirdsMajority()
|
||||
hash, partsHeader, ok := cs.Votes.Precommits(cs.Round).TwoThirdsMajority()
|
||||
if !ok {
|
||||
panic("RunActionCommit() expects +2/3 precommits")
|
||||
}
|
||||
@ -815,17 +824,25 @@ func (cs *ConsensusState) EnterCommit(height uint) {
|
||||
} else {
|
||||
// We just need to keep waiting.
|
||||
}
|
||||
} else {
|
||||
// We have the block, so sign a Commit-vote.
|
||||
cs.commitVoteBlock(cs.ProposalBlock, cs.ProposalBlockParts)
|
||||
}
|
||||
}
|
||||
|
||||
// If we have the block AND +2/3 commits for it, finalize.
|
||||
func (cs *ConsensusState) TryFinalizeCommit(height uint) {
|
||||
if cs.ProposalBlock.HashesTo(hash) && cs.Commits.HasTwoThirdsMajority() {
|
||||
go cs.FinalizeCommit(height)
|
||||
func (cs *ConsensusState) tryFinalizeCommit(height uint) {
|
||||
// SANITY CHECK
|
||||
if cs.Height != height {
|
||||
panic(Fmt("tryFinalizeCommit() cs.Height: %v vs height: %v", cs.Height, height))
|
||||
}
|
||||
// END SANITY CHECK
|
||||
|
||||
hash, _, ok := cs.Votes.Precommits(cs.Round).TwoThirdsMajority()
|
||||
if !ok || len(hash) == 0 {
|
||||
return
|
||||
}
|
||||
if !cs.ProposalBlock.HashesTo(hash) {
|
||||
return
|
||||
}
|
||||
go cs.FinalizeCommit(height)
|
||||
}
|
||||
|
||||
// Increment height and goto RoundStepNewHeight
|
||||
@ -838,7 +855,7 @@ func (cs *ConsensusState) FinalizeCommit(height uint) {
|
||||
return
|
||||
}
|
||||
|
||||
hash, header, ok := cs.Commits.TwoThirdsMajority()
|
||||
hash, header, ok := cs.Votes.Precommits(cs.Round).TwoThirdsMajority()
|
||||
|
||||
// SANITY CHECK
|
||||
if !ok {
|
||||
@ -857,26 +874,19 @@ func (cs *ConsensusState) FinalizeCommit(height uint) {
|
||||
|
||||
log.Debug(Fmt("Finalizing commit of block: %v", cs.ProposalBlock))
|
||||
// We have the block, so stage/save/commit-vote.
|
||||
cs.saveBlock(cs.ProposalBlock, cs.ProposalBlockParts, cs.Commits)
|
||||
cs.commitVoteBlock(cs.ProposalBlock, cs.ProposalBlockParts, cs.Commits)
|
||||
// Fire off event
|
||||
go func() {
|
||||
cs.evsw.FireEvent(types.EventStringNewBlock(), cs.ProposalBlock)
|
||||
cs.evc.Flush()
|
||||
}(cs.ProposalBlock)
|
||||
|
||||
cs.saveBlock(cs.ProposalBlock, cs.ProposalBlockParts, cs.Votes.Precommits(cs.Round))
|
||||
// Increment height.
|
||||
cs.updateToState(cs.stagedState, true)
|
||||
|
||||
// cs.StartTime is already set.
|
||||
// Schedule Round0 to start soon.
|
||||
go cs.scheduleRound0(height + 1)
|
||||
// If we're unbonded, broadcast RebondTx.
|
||||
cs.maybeRebond()
|
||||
|
||||
// By here,
|
||||
// * cs.Height has been increment to height+1
|
||||
// * cs.Step is now RoundStepNewHeight
|
||||
// * cs.StartTime is set to when we should start round0.
|
||||
// Start round 0 when cs.StartTime.
|
||||
go cs.scheduleRound0(height)
|
||||
// * cs.StartTime is set to when we will start round0.
|
||||
return
|
||||
}
|
||||
|
||||
@ -903,7 +913,7 @@ func (cs *ConsensusState) SetProposal(proposal *Proposal) error {
|
||||
|
||||
// Verify POLRound, which must be -1 or between 0 and proposal.Round exclusive.
|
||||
if proposal.POLRound != -1 &&
|
||||
(proposal.POLRound < 0 || proposal.Round <= proposal.POLRound) {
|
||||
(proposal.POLRound < 0 || proposal.Round <= uint(proposal.POLRound)) {
|
||||
return ErrInvalidProposalPOLRound
|
||||
}
|
||||
|
||||
@ -913,7 +923,7 @@ func (cs *ConsensusState) SetProposal(proposal *Proposal) error {
|
||||
}
|
||||
|
||||
cs.Proposal = proposal
|
||||
cs.ProposalBlockParts = types.NewPartSetFromHeader(proposal.BlockParts)
|
||||
cs.ProposalBlockParts = types.NewPartSetFromHeader(proposal.BlockPartsHeader)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -944,23 +954,23 @@ func (cs *ConsensusState) AddProposalBlockPart(height uint, round uint, part *ty
|
||||
if cs.Step == RoundStepPropose && cs.isProposalComplete() {
|
||||
go cs.EnterPrevote(height, round)
|
||||
} else if cs.Step == RoundStepCommit {
|
||||
cs.TryFinalizeCommit(height)
|
||||
cs.tryFinalizeCommit(height)
|
||||
}
|
||||
return true, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) AddVote(address []byte, vote *types.Vote) (added bool, index uint, err error) {
|
||||
func (cs *ConsensusState) AddVote(address []byte, vote *types.Vote, peerKey string) (added bool, index uint, err error) {
|
||||
cs.mtx.Lock()
|
||||
defer cs.mtx.Unlock()
|
||||
|
||||
return cs.addVote(address, vote)
|
||||
return cs.addVote(address, vote, peerKey)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
func (cs *ConsensusState) addVote(address []byte, vote *types.Vote) (added bool, index uint, err error) {
|
||||
func (cs *ConsensusState) addVote(address []byte, vote *types.Vote, peerKey string) (added bool, index uint, err error) {
|
||||
// A precommit for the previous height?
|
||||
if vote.Height+1 == cs.Height && vote.Type == types.VoteTypePrecommit {
|
||||
added, index, err = cs.LastCommit.AddByAddress(address, vote)
|
||||
@ -972,7 +982,8 @@ func (cs *ConsensusState) addVote(address []byte, vote *types.Vote) (added bool,
|
||||
|
||||
// A prevote/precommit for this height?
|
||||
if vote.Height == cs.Height {
|
||||
added, index, err = cs.Votes.AddByAddress(address, vote)
|
||||
height := cs.Height
|
||||
added, index, err = cs.Votes.AddByAddress(address, vote, peerKey)
|
||||
if added {
|
||||
switch vote.Type {
|
||||
case types.VoteTypePrevote:
|
||||
@ -995,7 +1006,7 @@ func (cs *ConsensusState) addVote(address []byte, vote *types.Vote) (added bool,
|
||||
cs.EnterPrevoteWait(height, cs.Round)
|
||||
}()
|
||||
}
|
||||
} else if cs.Proposal != nil && cs.Proposal.POLRound == vote.Round {
|
||||
} else if cs.Proposal != nil && cs.Proposal.POLRound >= 0 && uint(cs.Proposal.POLRound) == vote.Round {
|
||||
if cs.isProposalComplete() {
|
||||
go cs.EnterPrevote(height, cs.Round)
|
||||
}
|
||||
@ -1017,7 +1028,7 @@ func (cs *ConsensusState) addVote(address []byte, vote *types.Vote) (added bool,
|
||||
// If hash is block, goto Commit
|
||||
go func() {
|
||||
cs.EnterNewRound(height, vote.Round)
|
||||
cs.EnterCommit(height, vote.Round)
|
||||
cs.EnterCommit(height)
|
||||
}()
|
||||
}
|
||||
} else if cs.Votes.Precommits(vote.Round).HasTwoThirdsAny() {
|
||||
@ -1035,7 +1046,7 @@ func (cs *ConsensusState) addVote(address []byte, vote *types.Vote) (added bool,
|
||||
go cs.EnterNewRound(height, cs.Round+1)
|
||||
} else {
|
||||
// If hash is block, goto Commit
|
||||
go cs.EnterCommit(height, cs.Round)
|
||||
go cs.EnterCommit(height)
|
||||
}
|
||||
} else if cs.Votes.Precommits(cs.Round).HasTwoThirdsAny() {
|
||||
// Goto PrecommitWait
|
||||
@ -1098,8 +1109,8 @@ func (cs *ConsensusState) signAddVote(type_ byte, hash []byte, header types.Part
|
||||
}
|
||||
err := cs.privValidator.SignVote(cs.state.ChainID, vote)
|
||||
if err == nil {
|
||||
log.Info("Signed and added vote", "height", cs.Height, "round", cs.Round, "vote", vote)
|
||||
cs.addVote(cs.privValidator.Address, vote)
|
||||
_, _, err := cs.addVote(cs.privValidator.Address, vote, "")
|
||||
log.Info("Signed and added vote", "height", cs.Height, "round", cs.Round, "vote", vote, "error", err)
|
||||
return vote
|
||||
} else {
|
||||
log.Warn("Error signing vote", "height", cs.Height, "round", cs.Round, "vote", vote, "error", err)
|
||||
@ -1127,6 +1138,12 @@ func (cs *ConsensusState) saveBlock(block *types.Block, blockParts *types.PartSe
|
||||
// Update mempool.
|
||||
cs.mempoolReactor.Mempool.ResetForBlockAndState(block, cs.stagedState)
|
||||
|
||||
// Fire off event
|
||||
go func(block *types.Block) {
|
||||
cs.evsw.FireEvent(types.EventStringNewBlock(), block)
|
||||
cs.evc.Flush()
|
||||
}(block)
|
||||
|
||||
}
|
||||
|
||||
// implements events.Eventable
|
||||
|
Reference in New Issue
Block a user