github.com/okex/exchain@v1.8.0/libs/tendermint/consensus/reactor.go (about)

     1  package consensus
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"github.com/okex/exchain/libs/tendermint/crypto"
     7  	"github.com/okex/exchain/libs/tendermint/libs/automation"
     8  	"reflect"
     9  	"sync"
    10  	"time"
    11  
    12  	"github.com/pkg/errors"
    13  
    14  	amino "github.com/tendermint/go-amino"
    15  
    16  	cstypes "github.com/okex/exchain/libs/tendermint/consensus/types"
    17  	"github.com/okex/exchain/libs/tendermint/libs/bits"
    18  	tmevents "github.com/okex/exchain/libs/tendermint/libs/events"
    19  	"github.com/okex/exchain/libs/tendermint/libs/log"
    20  	"github.com/okex/exchain/libs/tendermint/p2p"
    21  	sm "github.com/okex/exchain/libs/tendermint/state"
    22  	"github.com/okex/exchain/libs/tendermint/types"
    23  	tmtime "github.com/okex/exchain/libs/tendermint/types/time"
    24  )
    25  
    26  type bpType int
    27  
    28  const (
    29  	StateChannel       = byte(0x20)
    30  	DataChannel        = byte(0x21)
    31  	VoteChannel        = byte(0x22)
    32  	VoteSetBitsChannel = byte(0x23)
    33  	ViewChangeChannel  = byte(0x24)
    34  
    35  	maxPartSize = 1048576 // 1MB; NOTE/TODO: keep in sync with types.PartSet sizes.
    36  	maxMsgSize  = maxPartSize
    37  
    38  	blocksToContributeToBecomeGoodPeer = 10000
    39  	votesToContributeToBecomeGoodPeer  = 10000
    40  
    41  	BP_SEND bpType = iota
    42  	BP_RECV
    43  	BP_ACK
    44  	BP_CATCHUP
    45  )
    46  
    47  //-----------------------------------------------------------------------------
    48  
    49  type blockchainReactor interface {
    50  	// CheckFastSyncCondition called when we're hanging in a height for some time during consensus
    51  	CheckFastSyncCondition()
    52  }
    53  
    54  // Reactor defines a reactor for the consensus service.
    55  type Reactor struct {
    56  	p2p.BaseReactor // BaseService + p2p.Switch
    57  
    58  	conS *State
    59  
    60  	mtx                   sync.RWMutex
    61  	fastSync              bool
    62  	autoFastSync          bool
    63  	eventBus              *types.EventBus
    64  	switchToFastSyncTimer *time.Timer
    65  	conHeight             int64
    66  
    67  	metrics *Metrics
    68  
    69  	rs *cstypes.RoundState
    70  
    71  	hasViewChanged int64
    72  }
    73  
    74  type ReactorOption func(*Reactor)
    75  
    76  // NewReactor returns a new Reactor with the given
    77  // consensusState.
    78  func NewReactor(consensusState *State, fastSync bool, autoFastSync bool, options ...ReactorOption) *Reactor {
    79  	conR := &Reactor{
    80  		conS:                  consensusState,
    81  		fastSync:              fastSync,
    82  		autoFastSync:          autoFastSync,
    83  		switchToFastSyncTimer: time.NewTimer(0),
    84  		conHeight:             consensusState.Height,
    85  		rs:                    consensusState.GetRoundState(),
    86  		metrics:               NopMetrics(),
    87  	}
    88  	conR.updateFastSyncingMetric()
    89  	conR.BaseReactor = *p2p.NewBaseReactor("Consensus", conR)
    90  
    91  	conR.stopSwitchToFastSyncTimer()
    92  
    93  	for _, option := range options {
    94  		option(conR)
    95  	}
    96  
    97  	return conR
    98  }
    99  
   100  // OnStart implements BaseService by subscribing to events, which later will be
   101  // broadcasted to other peers and starting state if we're not in fast sync.
   102  func (conR *Reactor) OnStart() error {
   103  	conR.Logger.Info("Reactor ", "fastSync", conR.FastSync())
   104  
   105  	// start routine that computes peer statistics for evaluating peer quality
   106  	go conR.peerStatsRoutine()
   107  
   108  	conR.subscribeToBroadcastEvents()
   109  
   110  	if !conR.FastSync() {
   111  		err := conR.conS.Start()
   112  		if err != nil {
   113  			return err
   114  		}
   115  	}
   116  
   117  	go conR.updateRoundStateRoutine()
   118  
   119  	return nil
   120  }
   121  
   122  func (conR *Reactor) updateRoundStateRoutine() {
   123  	t := time.NewTicker(100 * time.Microsecond)
   124  	defer t.Stop()
   125  
   126  	for _ = range t.C {
   127  		rs := conR.conS.GetRoundState()
   128  		conR.mtx.Lock()
   129  		conR.rs = rs
   130  		conR.mtx.Unlock()
   131  	}
   132  
   133  }
   134  
   135  func (conR *Reactor) getRoundState() *cstypes.RoundState {
   136  	conR.mtx.RLock()
   137  	defer conR.mtx.RUnlock()
   138  	return conR.rs
   139  }
   140  
   141  // OnStop implements BaseService by unsubscribing from events and stopping
   142  // state.
   143  func (conR *Reactor) OnStop() {
   144  	conR.unsubscribeFromBroadcastEvents()
   145  	conR.conS.Stop()
   146  	if !conR.FastSync() {
   147  		conR.conS.Wait()
   148  	}
   149  	conR.stopSwitchToFastSyncTimer()
   150  }
   151  
   152  // SwitchToConsensus switches from fast_sync mode to consensus mode.
   153  // It resets the state, turns off fast_sync, and starts the consensus state-machine
   154  func (conR *Reactor) SwitchToConsensus(state sm.State, blocksSynced uint64) bool {
   155  	if conR.conS.IsRunning() {
   156  		return false
   157  	}
   158  
   159  	defer func() {
   160  		conR.setFastSyncFlag(false, 0)
   161  	}()
   162  
   163  	conR.Logger.Info("SwitchToConsensus")
   164  	if state.LastBlockHeight > types.GetStartBlockHeight() {
   165  		conR.conS.reconstructLastCommit(state)
   166  	}
   167  	// NOTE: The line below causes broadcastNewRoundStepRoutine() to
   168  	// broadcast a NewRoundStepMessage.
   169  	conR.conS.updateToState(state)
   170  
   171  	if blocksSynced > 0 {
   172  		// dont bother with the WAL if we fast synced
   173  		conR.conS.doWALCatchup = false
   174  	}
   175  	conR.conS.Stop()
   176  	//if !conR.FastSync() {
   177  	//	conR.conS.Wait()
   178  	//}
   179  	conR.conS.Reset()
   180  	conR.conS.Start()
   181  
   182  	go conR.peerStatsRoutine()
   183  	conR.subscribeToBroadcastEvents()
   184  
   185  	return true
   186  }
   187  
   188  func (conR *Reactor) SwitchToFastSync() (sm.State, error) {
   189  	conR.Logger.Info("SwitchToFastSync")
   190  
   191  	defer func() {
   192  		conR.setFastSyncFlag(true, 1)
   193  	}()
   194  
   195  	if !conR.conS.IsRunning() {
   196  		return conR.conS.GetState(), errors.New("state is not running")
   197  	}
   198  
   199  	err := conR.conS.Stop()
   200  	if err != nil {
   201  		panic(fmt.Sprintf(`Failed to stop consensus state: %v
   202  
   203  conS:
   204  %+v
   205  
   206  conR:
   207  %+v`, err, conR.conS, conR))
   208  	}
   209  
   210  	conR.stopSwitchToFastSyncTimer()
   211  	conR.conS.Wait()
   212  
   213  	cState := conR.conS.GetState()
   214  	return cState, nil
   215  }
   216  
   217  func (conR *Reactor) setFastSyncFlag(f bool, v float64) {
   218  	conR.mtx.Lock()
   219  	defer conR.mtx.Unlock()
   220  
   221  	conR.fastSync = f
   222  	conR.metrics.FastSyncing.Set(v)
   223  	conR.conS.blockExec.SetIsFastSyncing(f)
   224  }
   225  
   226  // Attempt to schedule a timer for checking whether consensus machine is hanged.
   227  func (conR *Reactor) resetSwitchToFastSyncTimer() {
   228  	if conR.autoFastSync {
   229  		conR.Logger.Info("Reset SwitchToFastSyncTimeout.")
   230  		conR.stopSwitchToFastSyncTimer()
   231  		conR.switchToFastSyncTimer.Reset(conR.conS.config.TimeoutToFastSync)
   232  	}
   233  }
   234  
   235  func (conR *Reactor) stopSwitchToFastSyncTimer() {
   236  	if !conR.switchToFastSyncTimer.Stop() { // Stop() returns false if it was already fired or was stopped
   237  		select {
   238  		case <-conR.switchToFastSyncTimer.C:
   239  		default:
   240  			conR.Logger.Debug("Timer already stopped")
   241  		}
   242  	}
   243  }
   244  
   245  // GetChannels implements Reactor
   246  func (conR *Reactor) GetChannels() []*p2p.ChannelDescriptor {
   247  	// TODO optimize
   248  	return []*p2p.ChannelDescriptor{
   249  		{
   250  			ID:                  StateChannel,
   251  			Priority:            5,
   252  			SendQueueCapacity:   100,
   253  			RecvMessageCapacity: maxMsgSize,
   254  		},
   255  		{
   256  			ID: DataChannel, // maybe split between gossiping current block and catchup stuff
   257  			// once we gossip the whole block there's nothing left to send until next height or round
   258  			Priority:            10,
   259  			SendQueueCapacity:   100,
   260  			RecvBufferCapacity:  50 * 4096,
   261  			RecvMessageCapacity: maxMsgSize,
   262  		},
   263  		{
   264  			ID:                  VoteChannel,
   265  			Priority:            5,
   266  			SendQueueCapacity:   100,
   267  			RecvBufferCapacity:  100 * 100,
   268  			RecvMessageCapacity: maxMsgSize,
   269  		},
   270  		{
   271  			ID:                  VoteSetBitsChannel,
   272  			Priority:            1,
   273  			SendQueueCapacity:   2,
   274  			RecvBufferCapacity:  1024,
   275  			RecvMessageCapacity: maxMsgSize,
   276  		},
   277  		{
   278  			ID:                  ViewChangeChannel,
   279  			Priority:            5,
   280  			SendQueueCapacity:   100,
   281  			RecvMessageCapacity: maxMsgSize,
   282  		},
   283  	}
   284  }
   285  
   286  // InitPeer implements Reactor by creating a state for the peer.
   287  func (conR *Reactor) InitPeer(peer p2p.Peer) p2p.Peer {
   288  	peerState := NewPeerState(peer).SetLogger(conR.Logger)
   289  	peer.Set(types.PeerStateKey, peerState)
   290  	return peer
   291  }
   292  
   293  // AddPeer implements Reactor by spawning multiple gossiping goroutines for the
   294  // peer.
   295  func (conR *Reactor) AddPeer(peer p2p.Peer) {
   296  	if !conR.IsRunning() {
   297  		return
   298  	}
   299  
   300  	peerState, ok := peer.Get(types.PeerStateKey).(*PeerState)
   301  	if !ok {
   302  		panic(fmt.Sprintf("peer %v has no state", peer))
   303  	}
   304  	// Begin routines for this peer.
   305  	go conR.gossipDataRoutine(peer, peerState)
   306  	go conR.gossipVotesRoutine(peer, peerState)
   307  	//	go conR.gossipVCRoutine(peer, peerState)
   308  	go conR.queryMaj23Routine(peer, peerState)
   309  
   310  	// Send our state to peer.
   311  	// If we're fast_syncing, broadcast a RoundStepMessage later upon SwitchToConsensus().
   312  	if !conR.FastSync() {
   313  		conR.sendNewRoundStepMessage(peer)
   314  	}
   315  }
   316  
   317  // RemovePeer is a noop.
   318  func (conR *Reactor) RemovePeer(peer p2p.Peer, reason interface{}) {
   319  	if !conR.IsRunning() {
   320  		return
   321  	}
   322  	// TODO
   323  	// ps, ok := peer.Get(PeerStateKey).(*PeerState)
   324  	// if !ok {
   325  	// 	panic(fmt.Sprintf("Peer %v has no state", peer))
   326  	// }
   327  	// ps.Disconnect()
   328  }
   329  
   330  // Receive implements Reactor
   331  // NOTE: We process these messages even when we're fast_syncing.
   332  // Messages affect either a peer state or the consensus state.
   333  // Peer state updates can happen in parallel, but processing of
   334  // proposals, block parts, and votes are ordered by the receiveRoutine
   335  // NOTE: blocks on consensus state for proposals, block parts, and votes
   336  func (conR *Reactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) {
   337  	if automation.NetworkDisconnect(conR.conS.Height, conR.conS.Round) {
   338  		return
   339  	}
   340  
   341  	if !conR.IsRunning() {
   342  		conR.Logger.Debug("Receive", "src", src, "chId", chID, "bytes", msgBytes)
   343  		return
   344  	}
   345  
   346  	msg, err := decodeMsg(msgBytes)
   347  	if err != nil {
   348  		conR.Logger.Error("Error decoding message", "src", src, "chId", chID, "msg", msg, "err", err, "bytes", msgBytes)
   349  		conR.Switch.StopPeerForError(src, err)
   350  		return
   351  	}
   352  
   353  	if err = msg.ValidateBasic(); err != nil {
   354  		conR.Logger.Error("Peer sent us invalid msg", "peer", src, "msg", msg, "err", err)
   355  		conR.Switch.StopPeerForError(src, err)
   356  		return
   357  	}
   358  
   359  	conR.Logger.Debug("Receive", "src", src, "chId", chID, "msg", msg)
   360  
   361  	// Get peer states
   362  	ps, ok := src.Get(types.PeerStateKey).(*PeerState)
   363  	if !ok {
   364  		panic(fmt.Sprintf("Peer %v has no state", src))
   365  	}
   366  
   367  	switch chID {
   368  	case ViewChangeChannel:
   369  		if !GetActiveVC() {
   370  			return
   371  		}
   372  		switch msg := msg.(type) {
   373  		case *ViewChangeMessage:
   374  			// verify the signature of vcMsg
   375  			_, val := conR.conS.Validators.GetByAddress(msg.CurrentProposer)
   376  			if err := msg.Verify(val.PubKey); err != nil {
   377  				conR.Logger.Error("reactor Verify Signature of ViewChangeMessage", "err", err)
   378  				return
   379  			}
   380  			conR.conS.peerMsgQueue <- msgInfo{msg, ""}
   381  		case *ProposeResponseMessage:
   382  			conR.conS.peerMsgQueue <- msgInfo{msg, ""}
   383  		case *ProposeRequestMessage:
   384  			conR.conS.stateMtx.Lock()
   385  			defer conR.conS.stateMtx.Unlock()
   386  			height := conR.conS.Height
   387  			// this peer has received a prMsg before
   388  			// or this peer is not proposer
   389  			// or only then proposer ApplyBlock(height) has finished, do not handle prMsg
   390  			// or prMsg.height != prMsg.proposal.Height
   391  			if msg.Height <= conR.hasViewChanged ||
   392  				!bytes.Equal(conR.conS.privValidatorPubKey.Address(), msg.CurrentProposer) ||
   393  				msg.Height < height || (msg.Height == height && conR.conS.Step != cstypes.RoundStepNewHeight) ||
   394  				msg.Height != msg.Proposal.Height {
   395  				return
   396  			}
   397  
   398  			// verify the signature of prMsg
   399  			_, val := conR.conS.Validators.GetByAddress(msg.NewProposer)
   400  			if val == nil {
   401  				return
   402  			}
   403  			if err := msg.Verify(val.PubKey); err != nil {
   404  				conR.Logger.Error("reactor Verify Signature of ProposeRequestMessage", "err", err)
   405  				return
   406  			}
   407  
   408  			// sign proposal
   409  			proposal := msg.Proposal
   410  			signBytes := proposal.SignBytes(conR.conS.state.ChainID)
   411  			sig, err := conR.conS.privValidator.SignBytes(signBytes)
   412  			if err != nil {
   413  				return
   414  			}
   415  			proposal.Signature = sig
   416  			// tell newProposer
   417  			prspMsg := &ProposeResponseMessage{Height: proposal.Height, Proposal: proposal}
   418  			ps.peer.Send(ViewChangeChannel, cdc.MustMarshalBinaryBare(prspMsg))
   419  			// broadcast the proposal
   420  			conR.Switch.Broadcast(DataChannel, cdc.MustMarshalBinaryBare(&ProposalMessage{Proposal: proposal}))
   421  
   422  			conR.hasViewChanged = msg.Height
   423  
   424  			// mark the height no need to be proposer in msg.Height
   425  			conR.conS.vcHeight[msg.Height] = msg.NewProposer.String()
   426  			conR.Logger.Info("receive prMsg", "height", height, "prMsg", msg, "vcMsg", conR.conS.vcMsg)
   427  		}
   428  	case StateChannel:
   429  		switch msg := msg.(type) {
   430  		case *NewRoundStepMessage:
   431  			ps.ApplyNewRoundStepMessage(msg)
   432  		case *NewValidBlockMessage:
   433  			ps.ApplyNewValidBlockMessage(msg)
   434  		case *HasBlockPartMessage:
   435  			ps.SetHasProposalBlockPart(msg.Height, msg.Round, msg.Index, BP_ACK, conR.conS.bt)
   436  		case *HasVoteMessage:
   437  			ps.ApplyHasVoteMessage(msg)
   438  		case *VoteSetMaj23Message:
   439  			cs := conR.conS
   440  			cs.stateMtx.RLock()
   441  			height, votes := cs.Height, cs.Votes
   442  			cs.stateMtx.RUnlock()
   443  			if height != msg.Height {
   444  				return
   445  			}
   446  			// Peer claims to have a maj23 for some BlockID at H,R,S,
   447  			err := votes.SetPeerMaj23(msg.Round, msg.Type, ps.peer.ID(), msg.BlockID)
   448  			if err != nil {
   449  				conR.Switch.StopPeerForError(src, err)
   450  				return
   451  			}
   452  			// Respond with a VoteSetBitsMessage showing which votes we have.
   453  			// (and consequently shows which we don't have)
   454  			var ourVotes *bits.BitArray
   455  			switch msg.Type {
   456  			case types.PrevoteType:
   457  				ourVotes = votes.Prevotes(msg.Round).BitArrayByBlockID(msg.BlockID)
   458  			case types.PrecommitType:
   459  				ourVotes = votes.Precommits(msg.Round).BitArrayByBlockID(msg.BlockID)
   460  			default:
   461  				panic("Bad VoteSetBitsMessage field Type. Forgot to add a check in ValidateBasic?")
   462  			}
   463  			src.TrySend(VoteSetBitsChannel, cdc.MustMarshalBinaryBare(&VoteSetBitsMessage{
   464  				Height:  msg.Height,
   465  				Round:   msg.Round,
   466  				Type:    msg.Type,
   467  				BlockID: msg.BlockID,
   468  				Votes:   ourVotes,
   469  			}))
   470  		default:
   471  			conR.Logger.Error(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg)))
   472  		}
   473  
   474  	case DataChannel:
   475  		if conR.FastSync() {
   476  			conR.Logger.Info("Ignoring message received during fastSync", "msg", msg)
   477  			return
   478  		}
   479  		switch msg := msg.(type) {
   480  		case *ProposalMessage:
   481  			ps.SetHasProposal(msg.Proposal)
   482  			conR.conS.peerMsgQueue <- msgInfo{msg, src.ID()}
   483  		case *ProposalPOLMessage:
   484  			ps.ApplyProposalPOLMessage(msg)
   485  		case *BlockPartMessage:
   486  			ps.SetHasProposalBlockPart(msg.Height, msg.Round, msg.Part.Index, BP_RECV, conR.conS.bt)
   487  			conR.metrics.BlockParts.With("peer_id", string(src.ID())).Add(1)
   488  			conR.conS.peerMsgQueue <- msgInfo{msg, src.ID()}
   489  		default:
   490  			conR.Logger.Error(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg)))
   491  		}
   492  
   493  	case VoteChannel:
   494  		if conR.FastSync() {
   495  			conR.Logger.Info("Ignoring message received during fastSync", "msg", msg)
   496  			return
   497  		}
   498  		switch msg := msg.(type) {
   499  		case *VoteMessage:
   500  			cs := conR.conS
   501  			cs.stateMtx.RLock()
   502  			height, valSize, lastCommitSize := cs.Height, cs.Validators.Size(), cs.LastCommit.Size()
   503  			cs.stateMtx.RUnlock()
   504  			ps.EnsureVoteBitArrays(height, valSize)
   505  			ps.EnsureVoteBitArrays(height-1, lastCommitSize)
   506  			ps.SetHasVote(msg.Vote)
   507  
   508  			cs.peerMsgQueue <- msgInfo{msg, src.ID()}
   509  
   510  		default:
   511  			// don't punish (leave room for soft upgrades)
   512  			conR.Logger.Error(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg)))
   513  		}
   514  
   515  	case VoteSetBitsChannel:
   516  		if conR.FastSync() {
   517  			conR.Logger.Info("Ignoring message received during fastSync", "msg", msg)
   518  			return
   519  		}
   520  		switch msg := msg.(type) {
   521  		case *VoteSetBitsMessage:
   522  			cs := conR.conS
   523  			cs.stateMtx.RLock()
   524  			height, votes := cs.Height, cs.Votes
   525  			cs.stateMtx.RUnlock()
   526  
   527  			if height == msg.Height {
   528  				var ourVotes *bits.BitArray
   529  				switch msg.Type {
   530  				case types.PrevoteType:
   531  					ourVotes = votes.Prevotes(msg.Round).BitArrayByBlockID(msg.BlockID)
   532  				case types.PrecommitType:
   533  					ourVotes = votes.Precommits(msg.Round).BitArrayByBlockID(msg.BlockID)
   534  				default:
   535  					panic("Bad VoteSetBitsMessage field Type. Forgot to add a check in ValidateBasic?")
   536  				}
   537  				ps.ApplyVoteSetBitsMessage(msg, ourVotes)
   538  			} else {
   539  				ps.ApplyVoteSetBitsMessage(msg, nil)
   540  			}
   541  		default:
   542  			// don't punish (leave room for soft upgrades)
   543  			conR.Logger.Error(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg)))
   544  		}
   545  
   546  	default:
   547  		conR.Logger.Error(fmt.Sprintf("Unknown chId %X", chID))
   548  	}
   549  }
   550  
   551  // SetEventBus sets event bus.
   552  func (conR *Reactor) SetEventBus(b *types.EventBus) {
   553  	conR.eventBus = b
   554  	conR.conS.SetEventBus(b)
   555  }
   556  
   557  // FastSync returns whether the consensus reactor is in fast-sync mode.
   558  func (conR *Reactor) FastSync() bool {
   559  	conR.mtx.RLock()
   560  	defer conR.mtx.RUnlock()
   561  	return conR.fastSync
   562  }
   563  
   564  //--------------------------------------
   565  
   566  // subscribeToBroadcastEvents subscribes for new round steps and votes
   567  // using internal pubsub defined on state to broadcast
   568  // them to peers upon receiving.
   569  func (conR *Reactor) subscribeToBroadcastEvents() {
   570  	const subscriber = "consensus-reactor"
   571  	conR.conS.evsw.AddListenerForEvent(subscriber, types.EventNewRoundStep,
   572  		func(data tmevents.EventData) {
   573  			conR.broadcastNewRoundStepMessage(data.(*cstypes.RoundState))
   574  
   575  		})
   576  
   577  	conR.conS.evsw.AddListenerForEvent(subscriber, types.EventValidBlock,
   578  		func(data tmevents.EventData) {
   579  			conR.broadcastNewValidBlockMessage(data.(*cstypes.RoundState))
   580  		})
   581  
   582  	conR.conS.evsw.AddListenerForEvent(subscriber, types.EventVote,
   583  		func(data tmevents.EventData) {
   584  			conR.broadcastHasVoteMessage(data.(*types.Vote))
   585  		})
   586  
   587  	conR.conS.evsw.AddListenerForEvent(subscriber, types.EventSignVote,
   588  		func(data tmevents.EventData) {
   589  			conR.broadcastSignVoteMessage(data.(*types.Vote))
   590  		})
   591  
   592  	conR.conS.evsw.AddListenerForEvent(subscriber, types.EventBlockPart,
   593  		func(data tmevents.EventData) {
   594  			conR.broadcastHasBlockPartMessage(data.(*HasBlockPartMessage))
   595  		})
   596  	conR.conS.evsw.AddListenerForEvent(subscriber, types.EventProposeRequest,
   597  		func(data tmevents.EventData) {
   598  			conR.broadcastProposeRequestMessage(data.(*ProposeRequestMessage))
   599  		})
   600  }
   601  
   602  func (conR *Reactor) unsubscribeFromBroadcastEvents() {
   603  	const subscriber = "consensus-reactor"
   604  	conR.conS.evsw.RemoveListener(subscriber)
   605  }
   606  
   607  func (conR *Reactor) broadcastProposeRequestMessage(prMsg *ProposeRequestMessage) {
   608  	conR.Switch.Broadcast(ViewChangeChannel, cdc.MustMarshalBinaryBare(prMsg))
   609  }
   610  
   611  func (conR *Reactor) broadcastViewChangeMessage(prMsg *ProposeRequestMessage) *ViewChangeMessage {
   612  	vcMsg := ViewChangeMessage{Height: prMsg.Height, CurrentProposer: prMsg.CurrentProposer, NewProposer: prMsg.NewProposer}
   613  	signature, err := conR.conS.privValidator.SignBytes(vcMsg.SignBytes())
   614  	if err != nil {
   615  		conR.Logger.Error("broadcastViewChangeMessage", "err", err)
   616  		return nil
   617  	}
   618  	vcMsg.Signature = signature
   619  	conR.Switch.Broadcast(ViewChangeChannel, cdc.MustMarshalBinaryBare(vcMsg))
   620  	return &vcMsg
   621  }
   622  
   623  func (conR *Reactor) broadcastNewRoundStepMessage(rs *cstypes.RoundState) {
   624  	nrsMsg := makeRoundStepMessage(rs)
   625  	conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(nrsMsg))
   626  }
   627  
   628  func (conR *Reactor) broadcastNewValidBlockMessage(rs *cstypes.RoundState) {
   629  	csMsg := &NewValidBlockMessage{
   630  		Height:           rs.Height,
   631  		Round:            rs.Round,
   632  		BlockPartsHeader: rs.ProposalBlockParts.Header(),
   633  		BlockParts:       rs.ProposalBlockParts.BitArray(),
   634  		IsCommit:         rs.Step == cstypes.RoundStepCommit,
   635  	}
   636  	conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(csMsg))
   637  }
   638  
   639  // Broadcasts HasBlockPartMessage to peers that care.
   640  func (conR *Reactor) broadcastHasBlockPartMessage(msg *HasBlockPartMessage) {
   641  	conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(msg))
   642  }
   643  
   644  // Broadcasts HasVoteMessage to peers that care.
   645  func (conR *Reactor) broadcastHasVoteMessage(vote *types.Vote) {
   646  	msg := &HasVoteMessage{
   647  		Height: vote.Height,
   648  		Round:  vote.Round,
   649  		Type:   vote.Type,
   650  		Index:  vote.ValidatorIndex,
   651  	}
   652  	conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(msg))
   653  	/*
   654  		// TODO: Make this broadcast more selective.
   655  		for _, peer := range conR.Switch.Peers().List() {
   656  			ps, ok := peer.Get(PeerStateKey).(*PeerState)
   657  			if !ok {
   658  				panic(fmt.Sprintf("Peer %v has no state", peer))
   659  			}
   660  			prs := ps.GetRoundState()
   661  			if prs.Height == vote.Height {
   662  				// TODO: Also filter on round?
   663  				peer.TrySend(StateChannel, struct{ ConsensusMessage }{msg})
   664  			} else {
   665  				// Height doesn't match
   666  				// TODO: check a field, maybe CatchupCommitRound?
   667  				// TODO: But that requires changing the struct field comment.
   668  			}
   669  		}
   670  	*/
   671  }
   672  func (conR *Reactor) broadcastSignVoteMessage(vote *types.Vote) {
   673  	msg := &VoteMessage{vote}
   674  	conR.Switch.Broadcast(VoteChannel, cdc.MustMarshalBinaryBare(msg))
   675  }
   676  func makeRoundStepMessage(rs *cstypes.RoundState) (nrsMsg *NewRoundStepMessage) {
   677  	nrsMsg = &NewRoundStepMessage{
   678  		Height:                rs.Height,
   679  		Round:                 rs.Round,
   680  		Step:                  rs.Step,
   681  		SecondsSinceStartTime: int(time.Since(rs.StartTime).Seconds()),
   682  		LastCommitRound:       rs.LastCommit.GetRound(),
   683  		HasVC:                 rs.HasVC,
   684  	}
   685  	return
   686  }
   687  
   688  func (conR *Reactor) sendNewRoundStepMessage(peer p2p.Peer) {
   689  	rs := conR.getRoundState()
   690  	nrsMsg := makeRoundStepMessage(rs)
   691  	peer.Send(StateChannel, cdc.MustMarshalBinaryBare(nrsMsg))
   692  }
   693  
   694  func (conR *Reactor) gossipDataRoutine(peer p2p.Peer, ps *PeerState) {
   695  	logger := conR.Logger.With("peer", peer)
   696  
   697  OUTER_LOOP:
   698  	for {
   699  		// Manage disconnects from self or peer.
   700  		if !peer.IsRunning() || !conR.IsRunning() {
   701  			logger.Info("Stopping gossipDataRoutine for peer")
   702  			return
   703  		}
   704  		rs := conR.getRoundState()
   705  		prs := ps.GetRoundState()
   706  
   707  		// Send proposal Block parts?
   708  		if rs.ProposalBlockParts.HasHeader(prs.ProposalBlockPartsHeader) {
   709  			if index, ok := rs.ProposalBlockParts.BitArray().Sub(prs.ProposalBlockParts.Copy()).PickRandom(); ok {
   710  				part := rs.ProposalBlockParts.GetPart(index)
   711  				msg := &BlockPartMessage{
   712  					Height: rs.Height, // This tells peer that this part applies to us.
   713  					Round:  rs.Round,  // This tells peer that this part applies to us.
   714  					Part:   part,
   715  				}
   716  				logger.Debug("Sending block part", "height", prs.Height, "round", prs.Round)
   717  				if peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg)) {
   718  					ps.SetHasProposalBlockPart(prs.Height, prs.Round, index, BP_SEND, conR.conS.bt)
   719  				}
   720  				continue OUTER_LOOP
   721  			}
   722  		}
   723  
   724  		// If the peer is on a previous height that we have, help catch up.
   725  		if (0 < prs.Height) && (prs.Height < rs.Height) && (prs.Height >= conR.conS.blockStore.Base()) {
   726  			heightLogger := logger.With("height", prs.Height)
   727  
   728  			// if we never received the commit message from the peer, the block parts wont be initialized
   729  			if prs.ProposalBlockParts == nil {
   730  				blockMeta := conR.conS.blockStore.LoadBlockMeta(prs.Height)
   731  				if blockMeta == nil {
   732  					heightLogger.Error("Failed to load block meta",
   733  						"blockstoreBase", conR.conS.blockStore.Base(), "blockstoreHeight", conR.conS.blockStore.Height())
   734  					time.Sleep(conR.conS.config.PeerGossipSleepDuration)
   735  				} else {
   736  					ps.InitProposalBlockParts(blockMeta.BlockID.PartsHeader)
   737  				}
   738  				// continue the loop since prs is a copy and not effected by this initialization
   739  				continue OUTER_LOOP
   740  			}
   741  			conR.gossipDataForCatchup(heightLogger, rs, prs, ps, peer)
   742  			continue OUTER_LOOP
   743  		}
   744  
   745  		// If height and round don't match, sleep.
   746  		if (rs.Height != prs.Height) || (rs.Round != prs.Round) {
   747  			//logger.Info("Peer Height|Round mismatch, sleeping", "peerHeight", prs.Height, "peerRound", prs.Round, "peer", peer)
   748  			time.Sleep(conR.conS.config.PeerGossipSleepDuration)
   749  			continue OUTER_LOOP
   750  		}
   751  
   752  		// By here, height and round match.
   753  		// Proposal block parts were already matched and sent if any were wanted.
   754  		// (These can match on hash so the round doesn't matter)
   755  		// Now consider sending other things, like the Proposal itself.
   756  
   757  		// Send Proposal && ProposalPOL BitArray?
   758  		if rs.Proposal != nil && !prs.Proposal {
   759  			// Proposal: share the proposal metadata with peer.
   760  			{
   761  				msg := &ProposalMessage{Proposal: rs.Proposal}
   762  				logger.Debug("Sending proposal", "height", prs.Height, "round", prs.Round)
   763  				if peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg)) {
   764  					// NOTE[ZM]: A peer might have received different proposal msg so this Proposal msg will be rejected!
   765  					ps.SetHasProposal(rs.Proposal)
   766  				}
   767  			}
   768  			// ProposalPOL: lets peer know which POL votes we have so far.
   769  			// Peer must receive ProposalMessage first.
   770  			// rs.Proposal was validated, so rs.Proposal.POLRound <= rs.Round,
   771  			// so we definitely have rs.Votes.Prevotes(rs.Proposal.POLRound).
   772  			if 0 <= rs.Proposal.POLRound {
   773  				msg := &ProposalPOLMessage{
   774  					Height:           rs.Height,
   775  					ProposalPOLRound: rs.Proposal.POLRound,
   776  					ProposalPOL:      rs.Votes.Prevotes(rs.Proposal.POLRound).BitArray(),
   777  				}
   778  				logger.Debug("Sending POL", "height", prs.Height, "round", prs.Round)
   779  				peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg))
   780  			}
   781  			continue OUTER_LOOP
   782  		}
   783  
   784  		// Nothing to do. Sleep.
   785  		time.Sleep(conR.conS.config.PeerGossipSleepDuration)
   786  		continue OUTER_LOOP
   787  	}
   788  }
   789  
   790  func (conR *Reactor) gossipDataForCatchup(logger log.Logger, rs *cstypes.RoundState,
   791  	prs *cstypes.PeerRoundState, ps *PeerState, peer p2p.Peer) {
   792  
   793  	if index, ok := prs.ProposalBlockParts.Not().PickRandom(); ok {
   794  		// Ensure that the peer's PartSetHeader is correct
   795  		blockMeta := conR.conS.blockStore.LoadBlockMeta(prs.Height)
   796  		if blockMeta == nil {
   797  			logger.Error("Failed to load block meta", "ourHeight", rs.Height,
   798  				"blockstoreBase", conR.conS.blockStore.Base(), "blockstoreHeight", conR.conS.blockStore.Height())
   799  			time.Sleep(conR.conS.config.PeerGossipSleepDuration)
   800  			return
   801  		} else if !blockMeta.BlockID.PartsHeader.Equals(prs.ProposalBlockPartsHeader) {
   802  			logger.Info("Peer ProposalBlockPartsHeader mismatch, sleeping",
   803  				"blockPartsHeader", blockMeta.BlockID.PartsHeader, "peerBlockPartsHeader", prs.ProposalBlockPartsHeader)
   804  			time.Sleep(conR.conS.config.PeerGossipSleepDuration)
   805  			return
   806  		}
   807  		// Load the part
   808  		part := conR.conS.blockStore.LoadBlockPart(prs.Height, index)
   809  		if part == nil {
   810  			logger.Error("Could not load part", "index", index,
   811  				"blockPartsHeader", blockMeta.BlockID.PartsHeader, "peerBlockPartsHeader", prs.ProposalBlockPartsHeader)
   812  			time.Sleep(conR.conS.config.PeerGossipSleepDuration)
   813  			return
   814  		}
   815  
   816  		// Send the part
   817  		msg := &BlockPartMessage{
   818  			Height: prs.Height, // Not our height, so it doesn't matter.
   819  			Round:  prs.Round,  // Not our height, so it doesn't matter.
   820  			Part:   part,
   821  		}
   822  		logger.Debug("Sending block part for catchup", "round", prs.Round, "index", index)
   823  		if peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg)) {
   824  			ps.SetHasProposalBlockPart(prs.Height, prs.Round, index, BP_CATCHUP, conR.conS.bt)
   825  		} else {
   826  			logger.Debug("Sending block part for catchup failed")
   827  		}
   828  		return
   829  	}
   830  	//logger.Info("No parts to send in catch-up, sleeping")
   831  	time.Sleep(conR.conS.config.PeerGossipSleepDuration)
   832  }
   833  
   834  func (conR *Reactor) gossipVotesRoutine(peer p2p.Peer, ps *PeerState) {
   835  	logger := conR.Logger.With("peer", peer)
   836  
   837  	// Simple hack to throttle logs upon sleep.
   838  	var sleeping = 0
   839  
   840  OUTER_LOOP:
   841  	for {
   842  		// Manage disconnects from self or peer.
   843  		if !peer.IsRunning() || !conR.IsRunning() {
   844  			logger.Info("Stopping gossipVotesRoutine for peer")
   845  			return
   846  		}
   847  		rs := conR.getRoundState()
   848  		prs := ps.GetRoundState()
   849  
   850  		switch sleeping {
   851  		case 1: // First sleep
   852  			sleeping = 2
   853  		case 2: // No more sleep
   854  			sleeping = 0
   855  		}
   856  
   857  		//logger.Debug("gossipVotesRoutine", "rsHeight", rs.Height, "rsRound", rs.Round,
   858  		//	"prsHeight", prs.Height, "prsRound", prs.Round, "prsStep", prs.Step)
   859  
   860  		// If height matches, then send LastCommit, Prevotes, Precommits.
   861  		if rs.Height == prs.Height {
   862  			heightLogger := logger.With("height", prs.Height)
   863  			if conR.gossipVotesForHeight(heightLogger, rs, prs, ps) {
   864  				continue OUTER_LOOP
   865  			}
   866  		}
   867  
   868  		// Special catchup logic.
   869  		// If peer is lagging by height 1, send LastCommit.
   870  		if prs.Height != 0 && rs.Height == prs.Height+1 {
   871  			if ps.PickSendVote(rs.LastCommit) {
   872  				logger.Debug("Picked rs.LastCommit to send", "height", prs.Height)
   873  				continue OUTER_LOOP
   874  			}
   875  		}
   876  
   877  		// Catchup logic
   878  		// If peer is lagging by more than 1, send Commit.
   879  		if prs.Height != 0 && rs.Height >= prs.Height+2 {
   880  			// Load the block commit for prs.Height,
   881  			// which contains precommit signatures for prs.Height.
   882  			commit := conR.conS.blockStore.LoadBlockCommit(prs.Height)
   883  			if ps.PickSendVote(commit) {
   884  				logger.Debug("Picked Catchup commit to send", "height", prs.Height)
   885  				continue OUTER_LOOP
   886  			}
   887  		}
   888  
   889  		if sleeping == 0 {
   890  			// We sent nothing. Sleep...
   891  			sleeping = 1
   892  			logger.Debug("No votes to send, sleeping", "rs.Height", rs.Height, "prs.Height", prs.Height,
   893  				"localPV", rs.Votes.Prevotes(rs.Round).BitArray(), "peerPV", prs.Prevotes,
   894  				"localPC", rs.Votes.Precommits(rs.Round).BitArray(), "peerPC", prs.Precommits)
   895  		} else if sleeping == 2 {
   896  			// Continued sleep...
   897  			sleeping = 1
   898  		}
   899  
   900  		time.Sleep(conR.conS.config.PeerGossipSleepDuration)
   901  		continue OUTER_LOOP
   902  	}
   903  }
   904  
   905  func (conR *Reactor) gossipVotesForHeight(
   906  	logger log.Logger,
   907  	rs *cstypes.RoundState,
   908  	prs *cstypes.PeerRoundState,
   909  	ps *PeerState,
   910  ) bool {
   911  
   912  	// If there are lastCommits to send...
   913  	if prs.Step == cstypes.RoundStepNewHeight {
   914  		if ps.PickSendVote(rs.LastCommit) {
   915  			logger.Debug("Picked rs.LastCommit to send")
   916  			return true
   917  		}
   918  	}
   919  	// If there are POL prevotes to send...
   920  	if prs.Step <= cstypes.RoundStepPropose && prs.Round != -1 && prs.Round <= rs.Round && prs.ProposalPOLRound != -1 {
   921  		if polPrevotes := rs.Votes.Prevotes(prs.ProposalPOLRound); polPrevotes != nil {
   922  			if ps.PickSendVote(polPrevotes) {
   923  				logger.Debug("Picked rs.Prevotes(prs.ProposalPOLRound) to send",
   924  					"round", prs.ProposalPOLRound)
   925  				return true
   926  			}
   927  		}
   928  	}
   929  	// If there are prevotes to send...
   930  	if prs.Step <= cstypes.RoundStepPrevoteWait && prs.Round != -1 && prs.Round <= rs.Round {
   931  		if ps.PickSendVote(rs.Votes.Prevotes(prs.Round)) {
   932  			logger.Debug("Picked rs.Prevotes(prs.Round) to send", "round", prs.Round)
   933  			return true
   934  		}
   935  	}
   936  	// If there are precommits to send...
   937  	if prs.Step <= cstypes.RoundStepPrecommitWait && prs.Round != -1 && prs.Round <= rs.Round {
   938  		if ps.PickSendVote(rs.Votes.Precommits(prs.Round)) {
   939  			logger.Debug("Picked rs.Precommits(prs.Round) to send", "round", prs.Round)
   940  			return true
   941  		}
   942  	}
   943  	// If there are prevotes to send...Needed because of validBlock mechanism
   944  	if prs.Round != -1 && prs.Round <= rs.Round {
   945  		if ps.PickSendVote(rs.Votes.Prevotes(prs.Round)) {
   946  			logger.Debug("Picked rs.Prevotes(prs.Round) to send", "round", prs.Round)
   947  			return true
   948  		}
   949  	}
   950  	// If there are POLPrevotes to send...
   951  	if prs.ProposalPOLRound != -1 {
   952  		if polPrevotes := rs.Votes.Prevotes(prs.ProposalPOLRound); polPrevotes != nil {
   953  			if ps.PickSendVote(polPrevotes) {
   954  				logger.Debug("Picked rs.Prevotes(prs.ProposalPOLRound) to send",
   955  					"round", prs.ProposalPOLRound)
   956  				return true
   957  			}
   958  		}
   959  	}
   960  
   961  	return false
   962  }
   963  
   964  func (conR *Reactor) gossipVCRoutine(peer p2p.Peer, ps *PeerState) {
   965  	logger := conR.Logger.With("peer", peer)
   966  
   967  OUTER_LOOP:
   968  	for {
   969  		time.Sleep(conR.conS.config.PeerGossipSleepDuration * 2)
   970  
   971  		// Manage disconnects from self or peer.
   972  		if !peer.IsRunning() || !conR.IsRunning() {
   973  			logger.Info("Stopping gossipDataRoutine for peer")
   974  			return
   975  		}
   976  
   977  		if !GetActiveVC() {
   978  			time.Sleep(time.Second)
   979  			continue OUTER_LOOP
   980  		}
   981  
   982  		rs := conR.getRoundState()
   983  		prs := ps.GetRoundState()
   984  		vcMsg := conR.conS.vcMsg
   985  
   986  		if vcMsg == nil || rs.Height > vcMsg.Height {
   987  			continue OUTER_LOOP
   988  		}
   989  		// only in round0 send vcMsg
   990  		if rs.Round != 0 || prs.Round != 0 {
   991  			continue OUTER_LOOP
   992  		}
   993  		// send vcMsg
   994  		if vcMsg.Height == prs.Height && prs.AVCHeight < vcMsg.Height {
   995  			peer.Send(ViewChangeChannel, cdc.MustMarshalBinaryBare(vcMsg))
   996  			//conR.Switch.Broadcast(ViewChangeChannel, cdc.MustMarshalBinaryBare(vcMsg))
   997  			ps.SetAvcHeight(vcMsg.Height)
   998  		}
   999  
  1000  		if rs.Height == vcMsg.Height {
  1001  			// send proposal
  1002  			if rs.Proposal != nil {
  1003  				msg := &ProposalMessage{Proposal: rs.Proposal}
  1004  				peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg))
  1005  			}
  1006  		}
  1007  
  1008  		continue OUTER_LOOP
  1009  	}
  1010  }
  1011  
  1012  // NOTE: `queryMaj23Routine` has a simple crude design since it only comes
  1013  // into play for liveness when there's a signature DDoS attack happening.
  1014  func (conR *Reactor) queryMaj23Routine(peer p2p.Peer, ps *PeerState) {
  1015  	logger := conR.Logger.With("peer", peer)
  1016  
  1017  OUTER_LOOP:
  1018  	for {
  1019  		// Manage disconnects from self or peer.
  1020  		if !peer.IsRunning() || !conR.IsRunning() {
  1021  			logger.Info("Stopping queryMaj23Routine for peer")
  1022  			return
  1023  		}
  1024  
  1025  		// Maybe send Height/Round/Prevotes
  1026  		{
  1027  			rs := conR.getRoundState()
  1028  			prs := ps.GetRoundState()
  1029  			if rs.Height == prs.Height {
  1030  				if maj23, ok := rs.Votes.Prevotes(prs.Round).TwoThirdsMajority(); ok {
  1031  					peer.TrySend(StateChannel, cdc.MustMarshalBinaryBare(&VoteSetMaj23Message{
  1032  						Height:  prs.Height,
  1033  						Round:   prs.Round,
  1034  						Type:    types.PrevoteType,
  1035  						BlockID: maj23,
  1036  					}))
  1037  					time.Sleep(conR.conS.config.PeerQueryMaj23SleepDuration)
  1038  				}
  1039  			}
  1040  		}
  1041  
  1042  		// Maybe send Height/Round/Precommits
  1043  		{
  1044  			rs := conR.getRoundState()
  1045  			prs := ps.GetRoundState()
  1046  			if rs.Height == prs.Height {
  1047  				if maj23, ok := rs.Votes.Precommits(prs.Round).TwoThirdsMajority(); ok {
  1048  					peer.TrySend(StateChannel, cdc.MustMarshalBinaryBare(&VoteSetMaj23Message{
  1049  						Height:  prs.Height,
  1050  						Round:   prs.Round,
  1051  						Type:    types.PrecommitType,
  1052  						BlockID: maj23,
  1053  					}))
  1054  					time.Sleep(conR.conS.config.PeerQueryMaj23SleepDuration)
  1055  				}
  1056  			}
  1057  		}
  1058  
  1059  		// Maybe send Height/Round/ProposalPOL
  1060  		{
  1061  			rs := conR.getRoundState()
  1062  			prs := ps.GetRoundState()
  1063  			if rs.Height == prs.Height && prs.ProposalPOLRound >= 0 {
  1064  				if maj23, ok := rs.Votes.Prevotes(prs.ProposalPOLRound).TwoThirdsMajority(); ok {
  1065  					peer.TrySend(StateChannel, cdc.MustMarshalBinaryBare(&VoteSetMaj23Message{
  1066  						Height:  prs.Height,
  1067  						Round:   prs.ProposalPOLRound,
  1068  						Type:    types.PrevoteType,
  1069  						BlockID: maj23,
  1070  					}))
  1071  					time.Sleep(conR.conS.config.PeerQueryMaj23SleepDuration)
  1072  				}
  1073  			}
  1074  		}
  1075  
  1076  		// Little point sending LastCommitRound/LastCommit,
  1077  		// These are fleeting and non-blocking.
  1078  
  1079  		// Maybe send Height/CatchupCommitRound/CatchupCommit.
  1080  		{
  1081  			prs := ps.GetRoundState()
  1082  			if prs.CatchupCommitRound != -1 && prs.Height > 0 && prs.Height <= conR.conS.blockStore.Height() &&
  1083  				prs.Height >= conR.conS.blockStore.Base() {
  1084  				if commit := conR.conS.LoadCommit(prs.Height); commit != nil {
  1085  					peer.TrySend(StateChannel, cdc.MustMarshalBinaryBare(&VoteSetMaj23Message{
  1086  						Height:  prs.Height,
  1087  						Round:   commit.Round,
  1088  						Type:    types.PrecommitType,
  1089  						BlockID: commit.BlockID,
  1090  					}))
  1091  					time.Sleep(conR.conS.config.PeerQueryMaj23SleepDuration)
  1092  				}
  1093  			}
  1094  		}
  1095  
  1096  		time.Sleep(conR.conS.config.PeerQueryMaj23SleepDuration)
  1097  
  1098  		continue OUTER_LOOP
  1099  	}
  1100  }
  1101  
  1102  func (conR *Reactor) peerStatsRoutine() {
  1103  	conR.resetSwitchToFastSyncTimer()
  1104  
  1105  	defer func() {
  1106  		conR.stopSwitchToFastSyncTimer()
  1107  	}()
  1108  
  1109  	for {
  1110  		if !conR.IsRunning() {
  1111  			conR.Logger.Info("Stopping peerStatsRoutine")
  1112  			return
  1113  		}
  1114  
  1115  		select {
  1116  		case msg := <-conR.conS.statsMsgQueue:
  1117  			// Get peer
  1118  			peer := conR.Switch.Peers().Get(msg.PeerID)
  1119  			if peer == nil {
  1120  				conR.Logger.Debug("Attempt to update stats for non-existent peer",
  1121  					"peer", msg.PeerID)
  1122  				continue
  1123  			}
  1124  			// Get peer state
  1125  			ps, ok := peer.Get(types.PeerStateKey).(*PeerState)
  1126  			if !ok {
  1127  				panic(fmt.Sprintf("Peer %v has no state", peer))
  1128  			}
  1129  			switch msg.Msg.(type) {
  1130  			case *VoteMessage:
  1131  				if numVotes := ps.RecordVote(); numVotes%votesToContributeToBecomeGoodPeer == 0 {
  1132  					conR.Switch.MarkPeerAsGood(peer)
  1133  				}
  1134  			case *BlockPartMessage:
  1135  				if numParts := ps.RecordBlockPart(); numParts%blocksToContributeToBecomeGoodPeer == 0 {
  1136  					conR.Switch.MarkPeerAsGood(peer)
  1137  				}
  1138  			}
  1139  		case <-conR.switchToFastSyncTimer.C:
  1140  			bcR, ok := conR.Switch.Reactor("BLOCKCHAIN").(blockchainReactor)
  1141  			if ok {
  1142  				bcR.CheckFastSyncCondition()
  1143  				conR.resetSwitchToFastSyncTimer()
  1144  			}
  1145  
  1146  		case <-conR.conS.Quit():
  1147  			return
  1148  
  1149  		case <-conR.Quit():
  1150  			return
  1151  		}
  1152  	}
  1153  }
  1154  
  1155  // String returns a string representation of the Reactor.
  1156  // NOTE: For now, it is just a hard-coded string to avoid accessing unprotected shared variables.
  1157  // TODO: improve!
  1158  func (conR *Reactor) String() string {
  1159  	// better not to access shared variables
  1160  	return "ConsensusReactor" // conR.StringIndented("")
  1161  }
  1162  
  1163  // StringIndented returns an indented string representation of the Reactor
  1164  func (conR *Reactor) StringIndented(indent string) string {
  1165  	s := "ConsensusReactor{\n"
  1166  	s += indent + "  " + conR.conS.StringIndented(indent+"  ") + "\n"
  1167  	for _, peer := range conR.Switch.Peers().List() {
  1168  		ps, ok := peer.Get(types.PeerStateKey).(*PeerState)
  1169  		if !ok {
  1170  			panic(fmt.Sprintf("Peer %v has no state", peer))
  1171  		}
  1172  		s += indent + "  " + ps.StringIndented(indent+"  ") + "\n"
  1173  	}
  1174  	s += indent + "}"
  1175  	return s
  1176  }
  1177  
  1178  func (conR *Reactor) updateFastSyncingMetric() {
  1179  	var fastSyncing float64
  1180  	if conR.fastSync {
  1181  		fastSyncing = 1
  1182  	} else {
  1183  		fastSyncing = 0
  1184  	}
  1185  	conR.metrics.FastSyncing.Set(fastSyncing)
  1186  }
  1187  
  1188  // ReactorMetrics sets the metrics
  1189  func ReactorMetrics(metrics *Metrics) ReactorOption {
  1190  	return func(conR *Reactor) { conR.metrics = metrics }
  1191  }
  1192  
  1193  //-----------------------------------------------------------------------------
  1194  
  1195  var (
  1196  	ErrPeerStateHeightRegression = errors.New("error peer state height regression")
  1197  	ErrPeerStateInvalidStartTime = errors.New("error peer state invalid startTime")
  1198  )
  1199  
  1200  // PeerState contains the known state of a peer, including its connection and
  1201  // threadsafe access to its PeerRoundState.
  1202  // NOTE: THIS GETS DUMPED WITH rpc/core/consensus.go.
  1203  // Be mindful of what you Expose.
  1204  type PeerState struct {
  1205  	peer   p2p.Peer
  1206  	logger log.Logger
  1207  
  1208  	mtx   sync.Mutex             // NOTE: Modify below using setters, never directly.
  1209  	PRS   cstypes.PeerRoundState `json:"round_state"` // Exposed.
  1210  	Stats *peerStateStats        `json:"stats"`       // Exposed.
  1211  }
  1212  
  1213  // peerStateStats holds internal statistics for a peer.
  1214  type peerStateStats struct {
  1215  	Votes      int `json:"votes"`
  1216  	BlockParts int `json:"block_parts"`
  1217  }
  1218  
  1219  func (pss peerStateStats) String() string {
  1220  	return fmt.Sprintf("peerStateStats{votes: %d, blockParts: %d}",
  1221  		pss.Votes, pss.BlockParts)
  1222  }
  1223  
  1224  // NewPeerState returns a new PeerState for the given Peer
  1225  func NewPeerState(peer p2p.Peer) *PeerState {
  1226  	return &PeerState{
  1227  		peer:   peer,
  1228  		logger: log.NewNopLogger(),
  1229  		PRS: cstypes.PeerRoundState{
  1230  			Round:              -1,
  1231  			ProposalPOLRound:   -1,
  1232  			LastCommitRound:    -1,
  1233  			CatchupCommitRound: -1,
  1234  		},
  1235  		Stats: &peerStateStats{},
  1236  	}
  1237  }
  1238  
  1239  // SetLogger allows to set a logger on the peer state. Returns the peer state
  1240  // itself.
  1241  func (ps *PeerState) SetLogger(logger log.Logger) *PeerState {
  1242  	ps.logger = logger
  1243  	return ps
  1244  }
  1245  
  1246  // GetRoundState returns an shallow copy of the PeerRoundState.
  1247  // There's no point in mutating it since it won't change PeerState.
  1248  func (ps *PeerState) GetRoundState() *cstypes.PeerRoundState {
  1249  	ps.mtx.Lock()
  1250  	defer ps.mtx.Unlock()
  1251  
  1252  	prs := ps.PRS // copy
  1253  	return &prs
  1254  }
  1255  
  1256  // ToJSON returns a json of PeerState, marshalled using go-amino.
  1257  func (ps *PeerState) ToJSON() ([]byte, error) {
  1258  	ps.mtx.Lock()
  1259  	defer ps.mtx.Unlock()
  1260  
  1261  	return cdc.MarshalJSON(ps)
  1262  }
  1263  
  1264  // GetHeight returns an atomic snapshot of the PeerRoundState's height
  1265  // used by the mempool to ensure peers are caught up before broadcasting new txs
  1266  func (ps *PeerState) GetHeight() int64 {
  1267  	ps.mtx.Lock()
  1268  	defer ps.mtx.Unlock()
  1269  	return ps.PRS.Height
  1270  }
  1271  
  1272  // SetAvcHeight sets the given hasVC as known for the peer
  1273  func (ps *PeerState) SetAvcHeight(height int64) {
  1274  	ps.mtx.Lock()
  1275  	defer ps.mtx.Unlock()
  1276  
  1277  	ps.PRS.AVCHeight = height
  1278  }
  1279  
  1280  // SetHasProposal sets the given proposal as known for the peer.
  1281  func (ps *PeerState) SetHasProposal(proposal *types.Proposal) {
  1282  	ps.mtx.Lock()
  1283  	defer ps.mtx.Unlock()
  1284  
  1285  	if ps.PRS.Height != proposal.Height || ps.PRS.Round != proposal.Round {
  1286  		return
  1287  	}
  1288  
  1289  	if ps.PRS.Proposal {
  1290  		return
  1291  	}
  1292  
  1293  	ps.PRS.Proposal = true
  1294  
  1295  	// ps.PRS.ProposalBlockParts is set due to NewValidBlockMessage
  1296  	if ps.PRS.ProposalBlockParts != nil {
  1297  		return
  1298  	}
  1299  
  1300  	ps.PRS.ProposalBlockPartsHeader = proposal.BlockID.PartsHeader
  1301  	ps.PRS.ProposalBlockParts = bits.NewBitArray(proposal.BlockID.PartsHeader.Total)
  1302  	ps.PRS.ProposalPOLRound = proposal.POLRound
  1303  	ps.PRS.ProposalPOL = nil // Nil until ProposalPOLMessage received.
  1304  }
  1305  
  1306  // InitProposalBlockParts initializes the peer's proposal block parts header and bit array.
  1307  func (ps *PeerState) InitProposalBlockParts(partsHeader types.PartSetHeader) {
  1308  	ps.mtx.Lock()
  1309  	defer ps.mtx.Unlock()
  1310  
  1311  	if ps.PRS.ProposalBlockParts != nil {
  1312  		return
  1313  	}
  1314  
  1315  	ps.PRS.ProposalBlockPartsHeader = partsHeader
  1316  	ps.PRS.ProposalBlockParts = bits.NewBitArray(partsHeader.Total)
  1317  }
  1318  
  1319  // SetHasProposalBlockPart sets the given block part index as known for the peer.
  1320  func (ps *PeerState) SetHasProposalBlockPart(height int64, round int, index int, t bpType, bt *BlockTransport) {
  1321  	ps.mtx.Lock()
  1322  	defer ps.mtx.Unlock()
  1323  
  1324  	if ps.PRS.Height != height || ps.PRS.Round != round {
  1325  		return
  1326  	}
  1327  
  1328  	switch t {
  1329  	case BP_SEND:
  1330  		bt.onBPSend()
  1331  	case BP_ACK:
  1332  		if !ps.PRS.ProposalBlockParts.GetIndex(index) {
  1333  			bt.onBPACKHit()
  1334  		}
  1335  	case BP_RECV:
  1336  		if !ps.PRS.ProposalBlockParts.GetIndex(index) {
  1337  			bt.onBPDataHit()
  1338  		}
  1339  	}
  1340  
  1341  	ps.PRS.ProposalBlockParts.SetIndex(index, true)
  1342  }
  1343  
  1344  // PickSendVote picks a vote and sends it to the peer.
  1345  // Returns true if vote was sent.
  1346  func (ps *PeerState) PickSendVote(votes types.VoteSetReader) bool {
  1347  	if vote, ok := ps.PickVoteToSend(votes); ok {
  1348  		msg := &VoteMessage{vote}
  1349  		ps.logger.Debug("Sending vote message", "ps", ps, "vote", vote)
  1350  		if ps.peer.Send(VoteChannel, cdc.MustMarshalBinaryBare(msg)) {
  1351  			ps.SetHasVote(vote)
  1352  			return true
  1353  		}
  1354  		return false
  1355  	}
  1356  	return false
  1357  }
  1358  
  1359  // PickVoteToSend picks a vote to send to the peer.
  1360  // Returns true if a vote was picked.
  1361  // NOTE: `votes` must be the correct Size() for the Height().
  1362  func (ps *PeerState) PickVoteToSend(votes types.VoteSetReader) (vote *types.Vote, ok bool) {
  1363  	ps.mtx.Lock()
  1364  	defer ps.mtx.Unlock()
  1365  
  1366  	if votes.Size() == 0 {
  1367  		return nil, false
  1368  	}
  1369  
  1370  	height, round, votesType, size := votes.GetHeight(), votes.GetRound(), types.SignedMsgType(votes.Type()), votes.Size()
  1371  
  1372  	// Lazily set data using 'votes'.
  1373  	if votes.IsCommit() {
  1374  		ps.ensureCatchupCommitRound(height, round, size)
  1375  	}
  1376  	ps.ensureVoteBitArrays(height, size)
  1377  
  1378  	psVotes := ps.getVoteBitArray(height, round, votesType)
  1379  	if psVotes == nil {
  1380  		return nil, false // Not something worth sending
  1381  	}
  1382  	if index, ok := votes.BitArray().Sub(psVotes).PickRandom(); ok {
  1383  		return votes.GetByIndex(index), true
  1384  	}
  1385  	return nil, false
  1386  }
  1387  
  1388  func (ps *PeerState) getVoteBitArray(height int64, round int, votesType types.SignedMsgType) *bits.BitArray {
  1389  	if !types.IsVoteTypeValid(votesType) {
  1390  		return nil
  1391  	}
  1392  
  1393  	if ps.PRS.Height == height {
  1394  		if ps.PRS.Round == round {
  1395  			switch votesType {
  1396  			case types.PrevoteType:
  1397  				return ps.PRS.Prevotes
  1398  			case types.PrecommitType:
  1399  				return ps.PRS.Precommits
  1400  			}
  1401  		}
  1402  		if ps.PRS.CatchupCommitRound == round {
  1403  			switch votesType {
  1404  			case types.PrevoteType:
  1405  				return nil
  1406  			case types.PrecommitType:
  1407  				return ps.PRS.CatchupCommit
  1408  			}
  1409  		}
  1410  		if ps.PRS.ProposalPOLRound == round {
  1411  			switch votesType {
  1412  			case types.PrevoteType:
  1413  				return ps.PRS.ProposalPOL
  1414  			case types.PrecommitType:
  1415  				return nil
  1416  			}
  1417  		}
  1418  		return nil
  1419  	}
  1420  	if ps.PRS.Height == height+1 {
  1421  		if ps.PRS.LastCommitRound == round {
  1422  			switch votesType {
  1423  			case types.PrevoteType:
  1424  				return nil
  1425  			case types.PrecommitType:
  1426  				return ps.PRS.LastCommit
  1427  			}
  1428  		}
  1429  		return nil
  1430  	}
  1431  	return nil
  1432  }
  1433  
  1434  // 'round': A round for which we have a +2/3 commit.
  1435  func (ps *PeerState) ensureCatchupCommitRound(height int64, round int, numValidators int) {
  1436  	if ps.PRS.Height != height {
  1437  		return
  1438  	}
  1439  	/*
  1440  		NOTE: This is wrong, 'round' could change.
  1441  		e.g. if orig round is not the same as block LastCommit round.
  1442  		if ps.CatchupCommitRound != -1 && ps.CatchupCommitRound != round {
  1443  			panic(fmt.Sprintf(
  1444  				"Conflicting CatchupCommitRound. Height: %v,
  1445  				Orig: %v,
  1446  				New: %v",
  1447  				height,
  1448  				ps.CatchupCommitRound,
  1449  				round))
  1450  		}
  1451  	*/
  1452  	if ps.PRS.CatchupCommitRound == round {
  1453  		return // Nothing to do!
  1454  	}
  1455  	ps.PRS.CatchupCommitRound = round
  1456  	if round == ps.PRS.Round {
  1457  		ps.PRS.CatchupCommit = ps.PRS.Precommits
  1458  	} else {
  1459  		ps.PRS.CatchupCommit = bits.NewBitArray(numValidators)
  1460  	}
  1461  }
  1462  
  1463  // EnsureVoteBitArrays ensures the bit-arrays have been allocated for tracking
  1464  // what votes this peer has received.
  1465  // NOTE: It's important to make sure that numValidators actually matches
  1466  // what the node sees as the number of validators for height.
  1467  func (ps *PeerState) EnsureVoteBitArrays(height int64, numValidators int) {
  1468  	ps.mtx.Lock()
  1469  	defer ps.mtx.Unlock()
  1470  	ps.ensureVoteBitArrays(height, numValidators)
  1471  }
  1472  
  1473  func (ps *PeerState) ensureVoteBitArrays(height int64, numValidators int) {
  1474  	if ps.PRS.Height == height {
  1475  		if ps.PRS.Prevotes == nil {
  1476  			ps.PRS.Prevotes = bits.NewBitArray(numValidators)
  1477  		}
  1478  		if ps.PRS.Precommits == nil {
  1479  			ps.PRS.Precommits = bits.NewBitArray(numValidators)
  1480  		}
  1481  		if ps.PRS.CatchupCommit == nil {
  1482  			ps.PRS.CatchupCommit = bits.NewBitArray(numValidators)
  1483  		}
  1484  		if ps.PRS.ProposalPOL == nil {
  1485  			ps.PRS.ProposalPOL = bits.NewBitArray(numValidators)
  1486  		}
  1487  	} else if ps.PRS.Height == height+1 {
  1488  		if ps.PRS.LastCommit == nil {
  1489  			ps.PRS.LastCommit = bits.NewBitArray(numValidators)
  1490  		}
  1491  	}
  1492  }
  1493  
  1494  // RecordVote increments internal votes related statistics for this peer.
  1495  // It returns the total number of added votes.
  1496  func (ps *PeerState) RecordVote() int {
  1497  	ps.mtx.Lock()
  1498  	defer ps.mtx.Unlock()
  1499  
  1500  	ps.Stats.Votes++
  1501  
  1502  	return ps.Stats.Votes
  1503  }
  1504  
  1505  // VotesSent returns the number of blocks for which peer has been sending us
  1506  // votes.
  1507  func (ps *PeerState) VotesSent() int {
  1508  	ps.mtx.Lock()
  1509  	defer ps.mtx.Unlock()
  1510  
  1511  	return ps.Stats.Votes
  1512  }
  1513  
  1514  // RecordBlockPart increments internal block part related statistics for this peer.
  1515  // It returns the total number of added block parts.
  1516  func (ps *PeerState) RecordBlockPart() int {
  1517  	ps.mtx.Lock()
  1518  	defer ps.mtx.Unlock()
  1519  
  1520  	ps.Stats.BlockParts++
  1521  	return ps.Stats.BlockParts
  1522  }
  1523  
  1524  // BlockPartsSent returns the number of useful block parts the peer has sent us.
  1525  func (ps *PeerState) BlockPartsSent() int {
  1526  	ps.mtx.Lock()
  1527  	defer ps.mtx.Unlock()
  1528  
  1529  	return ps.Stats.BlockParts
  1530  }
  1531  
  1532  // SetHasVote sets the given vote as known by the peer
  1533  func (ps *PeerState) SetHasVote(vote *types.Vote) {
  1534  	ps.mtx.Lock()
  1535  	defer ps.mtx.Unlock()
  1536  
  1537  	ps.setHasVote(vote.Height, vote.Round, vote.Type, vote.ValidatorIndex)
  1538  }
  1539  
  1540  func (ps *PeerState) setHasVote(height int64, round int, voteType types.SignedMsgType, index int) {
  1541  	ps.logger.Debug("setHasVote", "peerH", ps.PRS.Height, "peerR", ps.PRS.Round, "H", height, "R", round, "type", voteType, "index", index)
  1542  
  1543  	// NOTE: some may be nil BitArrays -> no side effects.
  1544  	psVotes := ps.getVoteBitArray(height, round, voteType)
  1545  	if psVotes != nil {
  1546  		psVotes.SetIndex(index, true)
  1547  	}
  1548  }
  1549  
  1550  // ApplyNewRoundStepMessage updates the peer state for the new round.
  1551  func (ps *PeerState) ApplyNewRoundStepMessage(msg *NewRoundStepMessage) {
  1552  	ps.mtx.Lock()
  1553  	defer ps.mtx.Unlock()
  1554  
  1555  	// Ignore duplicates or decreases
  1556  	if CompareHRS(msg.Height, msg.Round, msg.Step,
  1557  		ps.PRS.Height, ps.PRS.Round, ps.PRS.Step,
  1558  		msg.HasVC && msg.Step == cstypes.RoundStepPropose) <= 0 {
  1559  		return
  1560  	}
  1561  
  1562  	// Just remember these values.
  1563  	psHeight := ps.PRS.Height
  1564  	psRound := ps.PRS.Round
  1565  	psCatchupCommitRound := ps.PRS.CatchupCommitRound
  1566  	psCatchupCommit := ps.PRS.CatchupCommit
  1567  
  1568  	startTime := tmtime.Now().Add(-1 * time.Duration(msg.SecondsSinceStartTime) * time.Second)
  1569  	ps.PRS.Height = msg.Height
  1570  	ps.PRS.Round = msg.Round
  1571  	ps.PRS.Step = msg.Step
  1572  	ps.PRS.StartTime = startTime
  1573  	if psHeight != msg.Height || psRound != msg.Round {
  1574  		ps.PRS.Proposal = false
  1575  		ps.PRS.ProposalBlockPartsHeader = types.PartSetHeader{}
  1576  		ps.PRS.ProposalBlockParts = nil
  1577  		ps.PRS.ProposalPOLRound = -1
  1578  		ps.PRS.ProposalPOL = nil
  1579  		// We'll update the BitArray capacity later.
  1580  		ps.PRS.Prevotes = nil
  1581  		ps.PRS.Precommits = nil
  1582  	}
  1583  	if psHeight == msg.Height && psRound != msg.Round && msg.Round == psCatchupCommitRound {
  1584  		// Peer caught up to CatchupCommitRound.
  1585  		// Preserve psCatchupCommit!
  1586  		// NOTE: We prefer to use prs.Precommits if
  1587  		// pr.Round matches pr.CatchupCommitRound.
  1588  		ps.PRS.Precommits = psCatchupCommit
  1589  	}
  1590  	if psHeight != msg.Height {
  1591  		// Shift Precommits to LastCommit.
  1592  		if psHeight+1 == msg.Height && psRound == msg.LastCommitRound {
  1593  			ps.PRS.LastCommitRound = msg.LastCommitRound
  1594  			ps.PRS.LastCommit = ps.PRS.Precommits
  1595  		} else {
  1596  			ps.PRS.LastCommitRound = msg.LastCommitRound
  1597  			ps.PRS.LastCommit = nil
  1598  		}
  1599  		// We'll update the BitArray capacity later.
  1600  		ps.PRS.CatchupCommitRound = -1
  1601  		ps.PRS.CatchupCommit = nil
  1602  	}
  1603  }
  1604  
  1605  // ApplyNewValidBlockMessage updates the peer state for the new valid block.
  1606  func (ps *PeerState) ApplyNewValidBlockMessage(msg *NewValidBlockMessage) {
  1607  	ps.mtx.Lock()
  1608  	defer ps.mtx.Unlock()
  1609  
  1610  	if ps.PRS.Height != msg.Height {
  1611  		return
  1612  	}
  1613  
  1614  	if ps.PRS.Round != msg.Round && !msg.IsCommit {
  1615  		return
  1616  	}
  1617  
  1618  	ps.PRS.ProposalBlockPartsHeader = msg.BlockPartsHeader
  1619  	ps.PRS.ProposalBlockParts = msg.BlockParts
  1620  }
  1621  
  1622  // ApplyProposalPOLMessage updates the peer state for the new proposal POL.
  1623  func (ps *PeerState) ApplyProposalPOLMessage(msg *ProposalPOLMessage) {
  1624  	ps.mtx.Lock()
  1625  	defer ps.mtx.Unlock()
  1626  
  1627  	if ps.PRS.Height != msg.Height {
  1628  		return
  1629  	}
  1630  	if ps.PRS.ProposalPOLRound != msg.ProposalPOLRound {
  1631  		return
  1632  	}
  1633  
  1634  	// TODO: Merge onto existing ps.PRS.ProposalPOL?
  1635  	// We might have sent some prevotes in the meantime.
  1636  	ps.PRS.ProposalPOL = msg.ProposalPOL
  1637  }
  1638  
  1639  // ApplyHasVoteMessage updates the peer state for the new vote.
  1640  func (ps *PeerState) ApplyHasVoteMessage(msg *HasVoteMessage) {
  1641  	ps.mtx.Lock()
  1642  	defer ps.mtx.Unlock()
  1643  
  1644  	if ps.PRS.Height != msg.Height {
  1645  		return
  1646  	}
  1647  
  1648  	ps.setHasVote(msg.Height, msg.Round, msg.Type, msg.Index)
  1649  }
  1650  
  1651  // ApplyVoteSetBitsMessage updates the peer state for the bit-array of votes
  1652  // it claims to have for the corresponding BlockID.
  1653  // `ourVotes` is a BitArray of votes we have for msg.BlockID
  1654  // NOTE: if ourVotes is nil (e.g. msg.Height < rs.Height),
  1655  // we conservatively overwrite ps's votes w/ msg.Votes.
  1656  func (ps *PeerState) ApplyVoteSetBitsMessage(msg *VoteSetBitsMessage, ourVotes *bits.BitArray) {
  1657  	ps.mtx.Lock()
  1658  	defer ps.mtx.Unlock()
  1659  
  1660  	votes := ps.getVoteBitArray(msg.Height, msg.Round, msg.Type)
  1661  	if votes != nil {
  1662  		if ourVotes == nil {
  1663  			votes.Update(msg.Votes)
  1664  		} else {
  1665  			otherVotes := votes.Sub(ourVotes)
  1666  			hasVotes := otherVotes.Or(msg.Votes)
  1667  			votes.Update(hasVotes)
  1668  		}
  1669  	}
  1670  }
  1671  
  1672  // String returns a string representation of the PeerState
  1673  func (ps *PeerState) String() string {
  1674  	return ps.StringIndented("")
  1675  }
  1676  
  1677  // StringIndented returns a string representation of the PeerState
  1678  func (ps *PeerState) StringIndented(indent string) string {
  1679  	ps.mtx.Lock()
  1680  	defer ps.mtx.Unlock()
  1681  	return fmt.Sprintf(`PeerState{
  1682  %s  Key        %v
  1683  %s  RoundState %v
  1684  %s  Stats      %v
  1685  %s}`,
  1686  		indent, ps.peer.ID(),
  1687  		indent, ps.PRS.StringIndented(indent+"  "),
  1688  		indent, ps.Stats,
  1689  		indent)
  1690  }
  1691  
  1692  //-----------------------------------------------------------------------------
  1693  // Messages
  1694  
  1695  // Message is a message that can be sent and received on the Reactor
  1696  type Message interface {
  1697  	ValidateBasic() error
  1698  }
  1699  
  1700  func RegisterMessages(cdc *amino.Codec) {
  1701  	cdc.RegisterInterface((*Message)(nil), nil)
  1702  	cdc.RegisterConcrete(&NewRoundStepMessage{}, "tendermint/NewRoundStepMessage", nil)
  1703  	cdc.RegisterConcrete(&NewValidBlockMessage{}, "tendermint/NewValidBlockMessage", nil)
  1704  	cdc.RegisterConcrete(&ProposalMessage{}, "tendermint/Proposal", nil)
  1705  	cdc.RegisterConcrete(&ProposalPOLMessage{}, "tendermint/ProposalPOL", nil)
  1706  	cdc.RegisterConcrete(&BlockPartMessage{}, "tendermint/BlockPart", nil)
  1707  	cdc.RegisterConcrete(&VoteMessage{}, "tendermint/Vote", nil)
  1708  	cdc.RegisterConcrete(&HasVoteMessage{}, "tendermint/HasVote", nil)
  1709  	cdc.RegisterConcrete(&VoteSetMaj23Message{}, "tendermint/VoteSetMaj23", nil)
  1710  	cdc.RegisterConcrete(&VoteSetBitsMessage{}, "tendermint/VoteSetBits", nil)
  1711  	cdc.RegisterConcrete(&HasBlockPartMessage{}, "tendermint/HasBlockPart", nil)
  1712  	cdc.RegisterConcrete(&ProposeRequestMessage{}, "tendermint/ProposeRequestMessage", nil)
  1713  	cdc.RegisterConcrete(&ProposeResponseMessage{}, "tendermint/ProposeResponseMessage", nil)
  1714  	cdc.RegisterConcrete(&ViewChangeMessage{}, "tendermint/ChangeValidator", nil)
  1715  }
  1716  
  1717  func decodeMsg(bz []byte) (msg Message, err error) {
  1718  	if len(bz) > maxMsgSize {
  1719  		return msg, fmt.Errorf("msg exceeds max size (%d > %d)", len(bz), maxMsgSize)
  1720  	}
  1721  	err = cdc.UnmarshalBinaryBare(bz, &msg)
  1722  	return
  1723  }
  1724  
  1725  //-------------------------------------
  1726  
  1727  // NewRoundStepMessage is sent for every step taken in the ConsensusState.
  1728  // For every height/round/step transition
  1729  type NewRoundStepMessage struct {
  1730  	Height                int64
  1731  	Round                 int
  1732  	Step                  cstypes.RoundStepType
  1733  	SecondsSinceStartTime int
  1734  	LastCommitRound       int
  1735  	HasVC                 bool
  1736  }
  1737  
  1738  // ValidateBasic performs basic validation.
  1739  func (m *NewRoundStepMessage) ValidateBasic() error {
  1740  	if m.Height < 0 {
  1741  		return errors.New("negative Height")
  1742  	}
  1743  	if m.Round < 0 {
  1744  		return errors.New("negative Round")
  1745  	}
  1746  	if !m.Step.IsValid() {
  1747  		return errors.New("invalid Step")
  1748  	}
  1749  
  1750  	// NOTE: SecondsSinceStartTime may be negative
  1751  
  1752  	if (m.Height == types.GetStartBlockHeight()+1 && m.LastCommitRound != -1) ||
  1753  		(m.Height > types.GetStartBlockHeight()+1 && m.LastCommitRound < -1) {
  1754  		// TODO: #2737 LastCommitRound should always be >= 0 for heights > 1
  1755  		return errors.New("invalid LastCommitRound (for 1st block: -1, for others: >= 0)")
  1756  	}
  1757  	return nil
  1758  }
  1759  
  1760  // String returns a string representation.
  1761  func (m *NewRoundStepMessage) String() string {
  1762  	return fmt.Sprintf("[NewRoundStep H:%v R:%v S:%v LCR:%v]",
  1763  		m.Height, m.Round, m.Step, m.LastCommitRound)
  1764  }
  1765  
  1766  //-------------------------------------
  1767  
  1768  // NewValidBlockMessage is sent when a validator observes a valid block B in some round r,
  1769  // i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r.
  1770  // In case the block is also committed, then IsCommit flag is set to true.
  1771  type NewValidBlockMessage struct {
  1772  	Height           int64
  1773  	Round            int
  1774  	BlockPartsHeader types.PartSetHeader
  1775  	BlockParts       *bits.BitArray
  1776  	IsCommit         bool
  1777  }
  1778  
  1779  // ValidateBasic performs basic validation.
  1780  func (m *NewValidBlockMessage) ValidateBasic() error {
  1781  	if m.Height < 0 {
  1782  		return errors.New("negative Height")
  1783  	}
  1784  	if m.Round < 0 {
  1785  		return errors.New("negative Round")
  1786  	}
  1787  	if err := m.BlockPartsHeader.ValidateBasic(); err != nil {
  1788  		return fmt.Errorf("wrong BlockPartsHeader: %v", err)
  1789  	}
  1790  	if m.BlockParts.Size() == 0 {
  1791  		return errors.New("empty blockParts")
  1792  	}
  1793  	if m.BlockParts.Size() != m.BlockPartsHeader.Total {
  1794  		return fmt.Errorf("blockParts bit array size %d not equal to BlockPartsHeader.Total %d",
  1795  			m.BlockParts.Size(),
  1796  			m.BlockPartsHeader.Total)
  1797  	}
  1798  	if m.BlockParts.Size() > types.MaxBlockPartsCount {
  1799  		return errors.Errorf("blockParts bit array is too big: %d, max: %d", m.BlockParts.Size(), types.MaxBlockPartsCount)
  1800  	}
  1801  	return nil
  1802  }
  1803  
  1804  // String returns a string representation.
  1805  func (m *NewValidBlockMessage) String() string {
  1806  	return fmt.Sprintf("[ValidBlockMessage H:%v R:%v BP:%v BA:%v IsCommit:%v]",
  1807  		m.Height, m.Round, m.BlockPartsHeader, m.BlockParts, m.IsCommit)
  1808  }
  1809  
  1810  //-------------------------------------
  1811  
  1812  // ProposalMessage is sent when a new block is proposed.
  1813  type ProposalMessage struct {
  1814  	Proposal *types.Proposal
  1815  }
  1816  
  1817  // ValidateBasic performs basic validation.
  1818  func (m *ProposalMessage) ValidateBasic() error {
  1819  	return m.Proposal.ValidateBasic()
  1820  }
  1821  
  1822  // String returns a string representation.
  1823  func (m *ProposalMessage) String() string {
  1824  	return fmt.Sprintf("[Proposal %v]", m.Proposal)
  1825  }
  1826  
  1827  //-------------------------------------
  1828  
  1829  // ProposalPOLMessage is sent when a previous proposal is re-proposed.
  1830  type ProposalPOLMessage struct {
  1831  	Height           int64
  1832  	ProposalPOLRound int
  1833  	ProposalPOL      *bits.BitArray
  1834  }
  1835  
  1836  // ValidateBasic performs basic validation.
  1837  func (m *ProposalPOLMessage) ValidateBasic() error {
  1838  	if m.Height < 0 {
  1839  		return errors.New("negative Height")
  1840  	}
  1841  	if m.ProposalPOLRound < 0 {
  1842  		return errors.New("negative ProposalPOLRound")
  1843  	}
  1844  	if m.ProposalPOL.Size() == 0 {
  1845  		return errors.New("empty ProposalPOL bit array")
  1846  	}
  1847  	if m.ProposalPOL.Size() > types.MaxVotesCount {
  1848  		return errors.Errorf("ProposalPOL bit array is too big: %d, max: %d", m.ProposalPOL.Size(), types.MaxVotesCount)
  1849  	}
  1850  	return nil
  1851  }
  1852  
  1853  // String returns a string representation.
  1854  func (m *ProposalPOLMessage) String() string {
  1855  	return fmt.Sprintf("[ProposalPOL H:%v POLR:%v POL:%v]", m.Height, m.ProposalPOLRound, m.ProposalPOL)
  1856  }
  1857  
  1858  //-------------------------------------
  1859  
  1860  // BlockPartMessage is sent when gossipping a piece of the proposed block.
  1861  type BlockPartMessage struct {
  1862  	Height int64
  1863  	Round  int
  1864  	Part   *types.Part
  1865  }
  1866  
  1867  // ValidateBasic performs basic validation.
  1868  func (m *BlockPartMessage) ValidateBasic() error {
  1869  	if m.Height < 0 {
  1870  		return errors.New("negative Height")
  1871  	}
  1872  	if m.Round < 0 {
  1873  		return errors.New("negative Round")
  1874  	}
  1875  	if err := m.Part.ValidateBasic(); err != nil {
  1876  		return fmt.Errorf("wrong Part: %v", err)
  1877  	}
  1878  	return nil
  1879  }
  1880  
  1881  // String returns a string representation.
  1882  func (m *BlockPartMessage) String() string {
  1883  	return fmt.Sprintf("[BlockPart H:%v R:%v P:%v]", m.Height, m.Round, m.Part)
  1884  }
  1885  
  1886  //-------------------------------------
  1887  
  1888  // VoteMessage is sent when voting for a proposal (or lack thereof).
  1889  type VoteMessage struct {
  1890  	Vote *types.Vote
  1891  }
  1892  
  1893  // ValidateBasic performs basic validation.
  1894  func (m *VoteMessage) ValidateBasic() error {
  1895  	return m.Vote.ValidateBasic()
  1896  }
  1897  
  1898  // String returns a string representation.
  1899  func (m *VoteMessage) String() string {
  1900  	return fmt.Sprintf("[Vote %v]", m.Vote)
  1901  }
  1902  
  1903  //-------------------------------------
  1904  
  1905  // HasBlockPartMessage is sent to indicate that a particular vote has been received.
  1906  type HasBlockPartMessage struct {
  1907  	Height int64
  1908  	Round  int
  1909  	Index  int
  1910  }
  1911  
  1912  // ValidateBasic performs basic validation.
  1913  func (m *HasBlockPartMessage) ValidateBasic() error {
  1914  	if m.Height < 0 {
  1915  		return errors.New("negative Height")
  1916  	}
  1917  	if m.Round < 0 {
  1918  		return errors.New("negative Round")
  1919  	}
  1920  	if m.Index < 0 {
  1921  		return errors.New("negative Index")
  1922  	}
  1923  	return nil
  1924  }
  1925  
  1926  // String returns a string representation.
  1927  func (m *HasBlockPartMessage) String() string {
  1928  	return fmt.Sprintf("[HasBlockPart VI:%v V:{%v/%02d}]", m.Index, m.Height, m.Round)
  1929  }
  1930  
  1931  // HasVoteMessage is sent to indicate that a particular vote has been received.
  1932  type HasVoteMessage struct {
  1933  	Height int64
  1934  	Round  int
  1935  	Type   types.SignedMsgType
  1936  	Index  int
  1937  }
  1938  
  1939  // ValidateBasic performs basic validation.
  1940  func (m *HasVoteMessage) ValidateBasic() error {
  1941  	if m.Height < 0 {
  1942  		return errors.New("negative Height")
  1943  	}
  1944  	if m.Round < 0 {
  1945  		return errors.New("negative Round")
  1946  	}
  1947  	if !types.IsVoteTypeValid(m.Type) {
  1948  		return errors.New("invalid Type")
  1949  	}
  1950  	if m.Index < 0 {
  1951  		return errors.New("negative Index")
  1952  	}
  1953  	return nil
  1954  }
  1955  
  1956  // String returns a string representation.
  1957  func (m *HasVoteMessage) String() string {
  1958  	return fmt.Sprintf("[HasVote VI:%v V:{%v/%02d/%v}]", m.Index, m.Height, m.Round, m.Type)
  1959  }
  1960  
  1961  //-------------------------------------
  1962  
  1963  // VoteSetMaj23Message is sent to indicate that a given BlockID has seen +2/3 votes.
  1964  type VoteSetMaj23Message struct {
  1965  	Height  int64
  1966  	Round   int
  1967  	Type    types.SignedMsgType
  1968  	BlockID types.BlockID
  1969  }
  1970  
  1971  // ValidateBasic performs basic validation.
  1972  func (m *VoteSetMaj23Message) ValidateBasic() error {
  1973  	if m.Height < 0 {
  1974  		return errors.New("negative Height")
  1975  	}
  1976  	if m.Round < 0 {
  1977  		return errors.New("negative Round")
  1978  	}
  1979  	if !types.IsVoteTypeValid(m.Type) {
  1980  		return errors.New("invalid Type")
  1981  	}
  1982  	if err := m.BlockID.ValidateBasic(); err != nil {
  1983  		return fmt.Errorf("wrong BlockID: %v", err)
  1984  	}
  1985  	return nil
  1986  }
  1987  
  1988  // String returns a string representation.
  1989  func (m *VoteSetMaj23Message) String() string {
  1990  	return fmt.Sprintf("[VSM23 %v/%02d/%v %v]", m.Height, m.Round, m.Type, m.BlockID)
  1991  }
  1992  
  1993  //-------------------------------------
  1994  
  1995  // VoteSetBitsMessage is sent to communicate the bit-array of votes seen for the BlockID.
  1996  type VoteSetBitsMessage struct {
  1997  	Height  int64
  1998  	Round   int
  1999  	Type    types.SignedMsgType
  2000  	BlockID types.BlockID
  2001  	Votes   *bits.BitArray
  2002  }
  2003  
  2004  // ValidateBasic performs basic validation.
  2005  func (m *VoteSetBitsMessage) ValidateBasic() error {
  2006  	if m.Height < 0 {
  2007  		return errors.New("negative Height")
  2008  	}
  2009  	if m.Round < 0 {
  2010  		return errors.New("negative Round")
  2011  	}
  2012  	if !types.IsVoteTypeValid(m.Type) {
  2013  		return errors.New("invalid Type")
  2014  	}
  2015  	if err := m.BlockID.ValidateBasic(); err != nil {
  2016  		return fmt.Errorf("wrong BlockID: %v", err)
  2017  	}
  2018  	// NOTE: Votes.Size() can be zero if the node does not have any
  2019  	if m.Votes.Size() > types.MaxVotesCount {
  2020  		return fmt.Errorf("votes bit array is too big: %d, max: %d", m.Votes.Size(), types.MaxVotesCount)
  2021  	}
  2022  	return nil
  2023  }
  2024  
  2025  // String returns a string representation.
  2026  func (m *VoteSetBitsMessage) String() string {
  2027  	return fmt.Sprintf("[VSB %v/%02d/%v %v %v]", m.Height, m.Round, m.Type, m.BlockID, m.Votes)
  2028  }
  2029  
  2030  // ProposeRequestMessage from other peer for request the latest height of consensus block
  2031  type ProposeRequestMessage struct {
  2032  	Height          int64
  2033  	CurrentProposer types.Address
  2034  	NewProposer     types.Address
  2035  	Proposal        *types.Proposal
  2036  	Signature       []byte
  2037  }
  2038  
  2039  func (m *ProposeRequestMessage) ValidateBasic() error {
  2040  	if m.Height < 0 {
  2041  		return errors.New("negative Height")
  2042  	}
  2043  	return nil
  2044  }
  2045  
  2046  func (m *ProposeRequestMessage) SignBytes() []byte {
  2047  	return cdc.MustMarshalBinaryBare(ProposeRequestMessage{Height: m.Height, CurrentProposer: m.CurrentProposer, NewProposer: m.NewProposer, Proposal: m.Proposal})
  2048  }
  2049  
  2050  func (m *ProposeRequestMessage) Verify(pubKey crypto.PubKey) error {
  2051  	if !bytes.Equal(pubKey.Address(), m.NewProposer) {
  2052  		return errors.New("invalid validator address")
  2053  	}
  2054  
  2055  	if !pubKey.VerifyBytes(m.SignBytes(), m.Signature) {
  2056  		return errors.New("invalid signature")
  2057  	}
  2058  	return nil
  2059  }
  2060  
  2061  // ProposeResponseMessage is the response of prMsg
  2062  type ProposeResponseMessage struct {
  2063  	Height   int64
  2064  	Proposal *types.Proposal
  2065  }
  2066  
  2067  func (m *ProposeResponseMessage) ValidateBasic() error {
  2068  	if m.Height < 0 {
  2069  		return errors.New("negative Height")
  2070  	}
  2071  	return nil
  2072  }
  2073  
  2074  // ViewChangeMessage is sent for remind peer to do vc
  2075  type ViewChangeMessage struct {
  2076  	Height          int64
  2077  	CurrentProposer types.Address
  2078  	NewProposer     types.Address
  2079  	Signature       []byte
  2080  }
  2081  
  2082  func (m *ViewChangeMessage) ValidateBasic() error {
  2083  	return nil
  2084  }
  2085  
  2086  func (m *ViewChangeMessage) Validate(height int64, proposer types.Address) bool {
  2087  	if m.Height != height {
  2088  		return false
  2089  	}
  2090  	if !bytes.Equal(proposer, m.CurrentProposer) {
  2091  		return false
  2092  	}
  2093  
  2094  	return true
  2095  }
  2096  
  2097  func (m *ViewChangeMessage) SignBytes() []byte {
  2098  	return cdc.MustMarshalBinaryBare(ViewChangeMessage{Height: m.Height, CurrentProposer: m.CurrentProposer, NewProposer: m.NewProposer})
  2099  }
  2100  
  2101  func (m *ViewChangeMessage) Verify(pubKey crypto.PubKey) error {
  2102  	if !bytes.Equal(pubKey.Address(), m.CurrentProposer) {
  2103  		return errors.New("invalid validator address")
  2104  	}
  2105  
  2106  	if !pubKey.VerifyBytes(m.SignBytes(), m.Signature) {
  2107  		return errors.New("invalid signature")
  2108  	}
  2109  	return nil
  2110  }
  2111  
  2112  //-------------------------------------