diff --git a/consensus/reactor.go b/consensus/reactor.go index 6c8a7544..3e12a314 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -1318,7 +1318,7 @@ func (m *VoteSetBitsMessage) String() string { //------------------------------------- -// ProposalHeartbeatMessage is sent to signal that the proposer is alive and waiting for transactions +// ProposalHeartbeatMessage is sent to signal that a node is alive and waiting for transactions for a proposal. type ProposalHeartbeatMessage struct { Heartbeat *types.Heartbeat } diff --git a/consensus/state.go b/consensus/state.go index 2d0a9a21..e6fd665a 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -788,7 +788,7 @@ func (cs *ConsensusState) enterNewRound(height int, round int) { // we may need an empty "proof" block, and enterPropose immediately. waitForTxs := cs.config.NoEmptyBlocks && round == 0 && !cs.needProofBlock(height) if waitForTxs { - go cs.proposalHeartbeat() + go cs.proposalHeartbeat(height, round) } else { cs.enterPropose(height, round) } @@ -808,7 +808,7 @@ func (cs *ConsensusState) needProofBlock(height int) bool { return false } -func (cs *ConsensusState) proposalHeartbeat() { +func (cs *ConsensusState) proposalHeartbeat(height, round int) { counter := 0 addr := cs.privValidator.GetAddress() valIndex, v := cs.Validators.GetByAddress(addr) @@ -817,24 +817,23 @@ func (cs *ConsensusState) proposalHeartbeat() { valIndex = -1 } for { - select { - default: - if cs.evsw != nil { - rs := cs.GetRoundState().RoundStateEvent() - heartbeat := &types.Heartbeat{ - Height: rs.Height, - Round: rs.Round, - Sequence: counter, - ValidatorAddress: addr, - ValidatorIndex: valIndex, - } - cs.privValidator.SignHeartbeat(cs.state.ChainID, heartbeat) - heartbeatEvent := types.EventDataProposalHeartbeat{heartbeat} - types.FireEventProposalHeartbeat(cs.evsw, heartbeatEvent) - counter += 1 - } - time.Sleep(time.Second) + rs := cs.GetRoundState() + // if we've already moved on, no need to send more heartbeats + if rs.Step > RoundStepNewRound || rs.Round > round || rs.Height > height { + return } + heartbeat := &types.Heartbeat{ + Height: rs.Height, + Round: rs.Round, + Sequence: counter, + ValidatorAddress: addr, + ValidatorIndex: valIndex, + } + cs.privValidator.SignHeartbeat(cs.state.ChainID, heartbeat) + heartbeatEvent := types.EventDataProposalHeartbeat{heartbeat} + types.FireEventProposalHeartbeat(cs.evsw, heartbeatEvent) + counter += 1 + time.Sleep(time.Second) } }