github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/netsync/handle.go (about)

     1  package netsync
     2  
     3  import (
     4  	"errors"
     5  	"reflect"
     6  
     7  	log "github.com/sirupsen/logrus"
     8  
     9  	cfg "github.com/bytom/bytom/config"
    10  	"github.com/bytom/bytom/consensus"
    11  	"github.com/bytom/bytom/event"
    12  	"github.com/bytom/bytom/p2p"
    13  	"github.com/bytom/bytom/p2p/security"
    14  	core "github.com/bytom/bytom/protocol"
    15  	"github.com/bytom/bytom/protocol/bc"
    16  	"github.com/bytom/bytom/protocol/bc/types"
    17  	"github.com/tendermint/go-crypto"
    18  )
    19  
    20  const (
    21  	logModule             = "netsync"
    22  	maxTxChanSize         = 10000
    23  	maxFilterAddressSize  = 50
    24  	maxFilterAddressCount = 1000
    25  )
    26  
    27  var (
    28  	errVaultModeDialPeer = errors.New("can't dial peer in vault mode")
    29  )
    30  
    31  // Chain is the interface for Bytom core
    32  type Chain interface {
    33  	BestBlockHeader() *types.BlockHeader
    34  	BestBlockHeight() uint64
    35  	CalcNextSeed(*bc.Hash) (*bc.Hash, error)
    36  	GetBlockByHash(*bc.Hash) (*types.Block, error)
    37  	GetBlockByHeight(uint64) (*types.Block, error)
    38  	GetHeaderByHash(*bc.Hash) (*types.BlockHeader, error)
    39  	GetHeaderByHeight(uint64) (*types.BlockHeader, error)
    40  	GetTransactionStatus(*bc.Hash) (*bc.TransactionStatus, error)
    41  	InMainChain(bc.Hash) bool
    42  	ProcessBlock(*types.Block) (bool, error)
    43  	ValidateTx(*types.Tx) (bool, error)
    44  }
    45  
    46  type Switch interface {
    47  	AddReactor(name string, reactor p2p.Reactor) p2p.Reactor
    48  	StopPeerGracefully(string)
    49  	NodeInfo() *p2p.NodeInfo
    50  	Start() (bool, error)
    51  	Stop() bool
    52  	IsListening() bool
    53  	DialPeerWithAddress(addr *p2p.NetAddress) error
    54  	Peers() *p2p.PeerSet
    55  	IsBanned(peerID string, level byte, reason string) bool
    56  }
    57  
    58  //SyncManager Sync Manager is responsible for the business layer information synchronization
    59  type SyncManager struct {
    60  	sw           Switch
    61  	genesisHash  bc.Hash
    62  	chain        Chain
    63  	txPool       *core.TxPool
    64  	blockFetcher *blockFetcher
    65  	blockKeeper  *blockKeeper
    66  	peers        *peerSet
    67  
    68  	txSyncCh chan *txSyncMsg
    69  	quitSync chan struct{}
    70  	config   *cfg.Config
    71  
    72  	eventDispatcher *event.Dispatcher
    73  	minedBlockSub   *event.Subscription
    74  	txMsgSub        *event.Subscription
    75  }
    76  
    77  // CreateSyncManager create sync manager and set switch.
    78  func NewSyncManager(config *cfg.Config, chain Chain, txPool *core.TxPool, dispatcher *event.Dispatcher) (*SyncManager, error) {
    79  	sw, err := p2p.NewSwitch(config)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	return newSyncManager(config, sw, chain, txPool, dispatcher)
    85  }
    86  
    87  //NewSyncManager create a sync manager
    88  func newSyncManager(config *cfg.Config, sw Switch, chain Chain, txPool *core.TxPool, dispatcher *event.Dispatcher) (*SyncManager, error) {
    89  	genesisHeader, err := chain.GetHeaderByHeight(0)
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  	peers := newPeerSet(sw)
    94  	manager := &SyncManager{
    95  		sw:              sw,
    96  		genesisHash:     genesisHeader.Hash(),
    97  		txPool:          txPool,
    98  		chain:           chain,
    99  		blockFetcher:    newBlockFetcher(chain, peers),
   100  		blockKeeper:     newBlockKeeper(chain, peers),
   101  		peers:           peers,
   102  		txSyncCh:        make(chan *txSyncMsg),
   103  		quitSync:        make(chan struct{}),
   104  		config:          config,
   105  		eventDispatcher: dispatcher,
   106  	}
   107  
   108  	if !config.VaultMode {
   109  		protocolReactor := NewProtocolReactor(manager, peers)
   110  		manager.sw.AddReactor("PROTOCOL", protocolReactor)
   111  	}
   112  	return manager, nil
   113  }
   114  
   115  //BestPeer return the highest p2p peerInfo
   116  func (sm *SyncManager) BestPeer() *PeerInfo {
   117  	bestPeer := sm.peers.bestPeer(consensus.SFFullNode)
   118  	if bestPeer != nil {
   119  		return bestPeer.getPeerInfo()
   120  	}
   121  	return nil
   122  }
   123  
   124  func (sm *SyncManager) DialPeerWithAddress(addr *p2p.NetAddress) error {
   125  	if sm.config.VaultMode {
   126  		return errVaultModeDialPeer
   127  	}
   128  
   129  	return sm.sw.DialPeerWithAddress(addr)
   130  }
   131  
   132  func (sm *SyncManager) GetNetwork() string {
   133  	return sm.config.ChainID
   134  }
   135  
   136  //GetPeerInfos return peer info of all peers
   137  func (sm *SyncManager) GetPeerInfos() []*PeerInfo {
   138  	return sm.peers.getPeerInfos()
   139  }
   140  
   141  //IsCaughtUp check wheather the peer finish the sync
   142  func (sm *SyncManager) IsCaughtUp() bool {
   143  	peer := sm.peers.bestPeer(consensus.SFFullNode)
   144  	return peer == nil || peer.Height() <= sm.chain.BestBlockHeight()
   145  }
   146  
   147  //StopPeer try to stop peer by given ID
   148  func (sm *SyncManager) StopPeer(peerID string) error {
   149  	if peer := sm.peers.getPeer(peerID); peer == nil {
   150  		return errors.New("peerId not exist")
   151  	}
   152  	sm.peers.removePeer(peerID)
   153  	return nil
   154  }
   155  
   156  func (sm *SyncManager) handleBlockMsg(peer *peer, msg *BlockMessage) {
   157  	block, err := msg.GetBlock()
   158  	if err != nil {
   159  		return
   160  	}
   161  	sm.blockKeeper.processBlock(peer.ID(), block)
   162  }
   163  
   164  func (sm *SyncManager) handleBlocksMsg(peer *peer, msg *BlocksMessage) {
   165  	blocks, err := msg.GetBlocks()
   166  	if err != nil {
   167  		log.WithFields(log.Fields{"module": logModule, "err": err}).Debug("fail on handleBlocksMsg GetBlocks")
   168  		return
   169  	}
   170  
   171  	sm.blockKeeper.processBlocks(peer.ID(), blocks)
   172  }
   173  
   174  func (sm *SyncManager) handleFilterAddMsg(peer *peer, msg *FilterAddMessage) {
   175  	peer.addFilterAddress(msg.Address)
   176  }
   177  
   178  func (sm *SyncManager) handleFilterClearMsg(peer *peer) {
   179  	peer.filterAdds.Clear()
   180  }
   181  
   182  func (sm *SyncManager) handleFilterLoadMsg(peer *peer, msg *FilterLoadMessage) {
   183  	peer.addFilterAddresses(msg.Addresses)
   184  }
   185  
   186  func (sm *SyncManager) handleGetBlockMsg(peer *peer, msg *GetBlockMessage) {
   187  	var block *types.Block
   188  	var err error
   189  	if msg.Height != 0 {
   190  		block, err = sm.chain.GetBlockByHeight(msg.Height)
   191  	} else {
   192  		block, err = sm.chain.GetBlockByHash(msg.GetHash())
   193  	}
   194  	if err != nil {
   195  		log.WithFields(log.Fields{"module": logModule, "err": err}).Warning("fail on handleGetBlockMsg get block from chain")
   196  		return
   197  	}
   198  
   199  	ok, err := peer.sendBlock(block)
   200  	if !ok {
   201  		sm.peers.removePeer(peer.ID())
   202  	}
   203  	if err != nil {
   204  		log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on handleGetBlockMsg sentBlock")
   205  	}
   206  }
   207  
   208  func (sm *SyncManager) handleGetBlocksMsg(peer *peer, msg *GetBlocksMessage) {
   209  	blocks, err := sm.blockKeeper.locateBlocks(msg.GetBlockLocator(), msg.GetStopHash())
   210  	if err != nil || len(blocks) == 0 {
   211  		return
   212  	}
   213  
   214  	totalSize := 0
   215  	sendBlocks := []*types.Block{}
   216  	for _, block := range blocks {
   217  		rawData, err := block.MarshalText()
   218  		if err != nil {
   219  			log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on handleGetBlocksMsg marshal block")
   220  			continue
   221  		}
   222  
   223  		if totalSize+len(rawData) > maxBlockchainResponseSize/2 {
   224  			break
   225  		}
   226  		totalSize += len(rawData)
   227  		sendBlocks = append(sendBlocks, block)
   228  	}
   229  
   230  	ok, err := peer.sendBlocks(sendBlocks)
   231  	if !ok {
   232  		sm.peers.removePeer(peer.ID())
   233  	}
   234  	if err != nil {
   235  		log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on handleGetBlocksMsg sentBlock")
   236  	}
   237  }
   238  
   239  func (sm *SyncManager) handleGetHeadersMsg(peer *peer, msg *GetHeadersMessage) {
   240  	headers, err := sm.blockKeeper.locateHeaders(msg.GetBlockLocator(), msg.GetStopHash())
   241  	if err != nil || len(headers) == 0 {
   242  		log.WithFields(log.Fields{"module": logModule, "err": err}).Debug("fail on handleGetHeadersMsg locateHeaders")
   243  		return
   244  	}
   245  
   246  	ok, err := peer.sendHeaders(headers)
   247  	if !ok {
   248  		sm.peers.removePeer(peer.ID())
   249  	}
   250  	if err != nil {
   251  		log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on handleGetHeadersMsg sentBlock")
   252  	}
   253  }
   254  
   255  func (sm *SyncManager) handleGetMerkleBlockMsg(peer *peer, msg *GetMerkleBlockMessage) {
   256  	var err error
   257  	var block *types.Block
   258  	if msg.Height != 0 {
   259  		block, err = sm.chain.GetBlockByHeight(msg.Height)
   260  	} else {
   261  		block, err = sm.chain.GetBlockByHash(msg.GetHash())
   262  	}
   263  	if err != nil {
   264  		log.WithFields(log.Fields{"module": logModule, "err": err}).Warning("fail on handleGetMerkleBlockMsg get block from chain")
   265  		return
   266  	}
   267  
   268  	blockHash := block.Hash()
   269  	txStatus, err := sm.chain.GetTransactionStatus(&blockHash)
   270  	if err != nil {
   271  		log.WithFields(log.Fields{"module": logModule, "err": err}).Warning("fail on handleGetMerkleBlockMsg get transaction status")
   272  		return
   273  	}
   274  
   275  	ok, err := peer.sendMerkleBlock(block, txStatus)
   276  	if err != nil {
   277  		log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on handleGetMerkleBlockMsg sentMerkleBlock")
   278  		return
   279  	}
   280  
   281  	if !ok {
   282  		sm.peers.removePeer(peer.ID())
   283  	}
   284  }
   285  
   286  func (sm *SyncManager) handleHeadersMsg(peer *peer, msg *HeadersMessage) {
   287  	headers, err := msg.GetHeaders()
   288  	if err != nil {
   289  		log.WithFields(log.Fields{"module": logModule, "err": err}).Debug("fail on handleHeadersMsg GetHeaders")
   290  		return
   291  	}
   292  
   293  	sm.blockKeeper.processHeaders(peer.ID(), headers)
   294  }
   295  
   296  func (sm *SyncManager) handleMineBlockMsg(peer *peer, msg *MineBlockMessage) {
   297  	block, err := msg.GetMineBlock()
   298  	if err != nil {
   299  		log.WithFields(log.Fields{"module": logModule, "err": err}).Warning("fail on handleMineBlockMsg GetMineBlock")
   300  		return
   301  	}
   302  
   303  	hash := block.Hash()
   304  	peer.markBlock(&hash)
   305  	sm.blockFetcher.processNewBlock(&blockMsg{peerID: peer.ID(), block: block})
   306  	peer.setStatus(block.Height, &hash)
   307  }
   308  
   309  func (sm *SyncManager) handleStatusRequestMsg(peer BasePeer) {
   310  	bestHeader := sm.chain.BestBlockHeader()
   311  	genesisBlock, err := sm.chain.GetBlockByHeight(0)
   312  	if err != nil {
   313  		log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on handleStatusRequestMsg get genesis")
   314  	}
   315  
   316  	genesisHash := genesisBlock.Hash()
   317  	msg := NewStatusResponseMessage(bestHeader, &genesisHash)
   318  	if ok := peer.TrySend(BlockchainChannel, struct{ BlockchainMessage }{msg}); !ok {
   319  		sm.peers.removePeer(peer.ID())
   320  	}
   321  }
   322  
   323  func (sm *SyncManager) handleStatusResponseMsg(basePeer BasePeer, msg *StatusResponseMessage) {
   324  	if peer := sm.peers.getPeer(basePeer.ID()); peer != nil {
   325  		peer.setStatus(msg.Height, msg.GetHash())
   326  		return
   327  	}
   328  
   329  	if genesisHash := msg.GetGenesisHash(); sm.genesisHash != *genesisHash {
   330  		log.WithFields(log.Fields{"module": logModule, "remote genesis": genesisHash.String(), "local genesis": sm.genesisHash.String()}).Warn("fail hand shake due to differnt genesis")
   331  		return
   332  	}
   333  
   334  	sm.peers.addPeer(basePeer, msg.Height, msg.GetHash())
   335  }
   336  
   337  func (sm *SyncManager) handleTransactionMsg(peer *peer, msg *TransactionMessage) {
   338  	tx, err := msg.GetTransaction()
   339  	if err != nil {
   340  		sm.peers.ProcessIllegal(peer.ID(), security.LevelConnException, "fail on get txs from message")
   341  		return
   342  	}
   343  
   344  	if isOrphan, err := sm.chain.ValidateTx(tx); err != nil && err != core.ErrDustTx && !isOrphan {
   345  		sm.peers.ProcessIllegal(peer.ID(), security.LevelMsgIllegal, "fail on validate tx transaction")
   346  	}
   347  }
   348  
   349  func (sm *SyncManager) IsListening() bool {
   350  	if sm.config.VaultMode {
   351  		return false
   352  	}
   353  	return sm.sw.IsListening()
   354  }
   355  
   356  func (sm *SyncManager) NodeInfo() *p2p.NodeInfo {
   357  	if sm.config.VaultMode {
   358  		return p2p.NewNodeInfo(sm.config, crypto.PubKeyEd25519{}, "")
   359  	}
   360  	return sm.sw.NodeInfo()
   361  }
   362  
   363  func (sm *SyncManager) PeerCount() int {
   364  	if sm.config.VaultMode {
   365  		return 0
   366  	}
   367  	return len(sm.sw.Peers().List())
   368  }
   369  
   370  func (sm *SyncManager) processMsg(basePeer BasePeer, msgType byte, msg BlockchainMessage) {
   371  	peer := sm.peers.getPeer(basePeer.ID())
   372  	if peer == nil && msgType != StatusResponseByte && msgType != StatusRequestByte {
   373  		return
   374  	}
   375  
   376  	log.WithFields(log.Fields{
   377  		"module":  logModule,
   378  		"peer":    basePeer.Addr(),
   379  		"type":    reflect.TypeOf(msg),
   380  		"message": msg.String(),
   381  	}).Info("receive message from peer")
   382  
   383  	switch msg := msg.(type) {
   384  	case *GetBlockMessage:
   385  		sm.handleGetBlockMsg(peer, msg)
   386  
   387  	case *BlockMessage:
   388  		sm.handleBlockMsg(peer, msg)
   389  
   390  	case *StatusRequestMessage:
   391  		sm.handleStatusRequestMsg(basePeer)
   392  
   393  	case *StatusResponseMessage:
   394  		sm.handleStatusResponseMsg(basePeer, msg)
   395  
   396  	case *TransactionMessage:
   397  		sm.handleTransactionMsg(peer, msg)
   398  
   399  	case *MineBlockMessage:
   400  		sm.handleMineBlockMsg(peer, msg)
   401  
   402  	case *GetHeadersMessage:
   403  		sm.handleGetHeadersMsg(peer, msg)
   404  
   405  	case *HeadersMessage:
   406  		sm.handleHeadersMsg(peer, msg)
   407  
   408  	case *GetBlocksMessage:
   409  		sm.handleGetBlocksMsg(peer, msg)
   410  
   411  	case *BlocksMessage:
   412  		sm.handleBlocksMsg(peer, msg)
   413  
   414  	case *FilterLoadMessage:
   415  		sm.handleFilterLoadMsg(peer, msg)
   416  
   417  	case *FilterAddMessage:
   418  		sm.handleFilterAddMsg(peer, msg)
   419  
   420  	case *FilterClearMessage:
   421  		sm.handleFilterClearMsg(peer)
   422  
   423  	case *GetMerkleBlockMessage:
   424  		sm.handleGetMerkleBlockMsg(peer, msg)
   425  
   426  	default:
   427  		log.WithFields(log.Fields{
   428  			"module":       logModule,
   429  			"peer":         basePeer.Addr(),
   430  			"message_type": reflect.TypeOf(msg),
   431  		}).Error("unhandled message type")
   432  	}
   433  }
   434  
   435  func (sm *SyncManager) Start() error {
   436  	var err error
   437  	if _, err = sm.sw.Start(); err != nil {
   438  		log.Error("switch start err")
   439  		return err
   440  	}
   441  
   442  	sm.minedBlockSub, err = sm.eventDispatcher.Subscribe(event.NewMinedBlockEvent{})
   443  	if err != nil {
   444  		return err
   445  	}
   446  
   447  	sm.txMsgSub, err = sm.eventDispatcher.Subscribe(core.TxMsgEvent{})
   448  	if err != nil {
   449  		return err
   450  	}
   451  
   452  	// broadcast transactions
   453  	go sm.txBroadcastLoop()
   454  	go sm.minedBroadcastLoop()
   455  	go sm.txSyncLoop()
   456  
   457  	return nil
   458  }
   459  
   460  //Stop stop sync manager
   461  func (sm *SyncManager) Stop() {
   462  	close(sm.quitSync)
   463  	sm.minedBlockSub.Unsubscribe()
   464  	if !sm.config.VaultMode {
   465  		sm.sw.Stop()
   466  	}
   467  }
   468  
   469  func (sm *SyncManager) minedBroadcastLoop() {
   470  	for {
   471  		select {
   472  		case obj, ok := <-sm.minedBlockSub.Chan():
   473  			if !ok {
   474  				log.WithFields(log.Fields{"module": logModule}).Warning("mined block subscription channel closed")
   475  				return
   476  			}
   477  
   478  			ev, ok := obj.Data.(event.NewMinedBlockEvent)
   479  			if !ok {
   480  				log.WithFields(log.Fields{"module": logModule}).Error("event type error")
   481  				continue
   482  			}
   483  
   484  			if err := sm.peers.broadcastMinedBlock(&ev.Block); err != nil {
   485  				log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on broadcast mine block")
   486  				continue
   487  			}
   488  
   489  		case <-sm.quitSync:
   490  			return
   491  		}
   492  	}
   493  }