github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/neatptc/handler.go (about)

     1  package neatptc
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"math"
     8  	"math/big"
     9  	"sync"
    10  	"sync/atomic"
    11  	"time"
    12  
    13  	"github.com/neatlab/neatio/chain/core/rawdb"
    14  
    15  	"github.com/neatlab/neatio/chain/consensus"
    16  	"github.com/neatlab/neatio/chain/core"
    17  	"github.com/neatlab/neatio/chain/core/types"
    18  	"github.com/neatlab/neatio/chain/log"
    19  	"github.com/neatlab/neatio/neatdb"
    20  	"github.com/neatlab/neatio/neatptc/downloader"
    21  	"github.com/neatlab/neatio/neatptc/fetcher"
    22  	"github.com/neatlab/neatio/network/p2p"
    23  	"github.com/neatlab/neatio/network/p2p/discover"
    24  	"github.com/neatlab/neatio/params"
    25  	"github.com/neatlab/neatio/utilities/common"
    26  	"github.com/neatlab/neatio/utilities/crypto"
    27  	"github.com/neatlab/neatio/utilities/event"
    28  	"github.com/neatlab/neatio/utilities/rlp"
    29  )
    30  
    31  const (
    32  	softResponseLimit = 2 * 1024 * 1024
    33  	estHeaderRlpSize  = 500
    34  
    35  	txChanSize = 4096
    36  
    37  	tx3PrfDtChainSize = 4096
    38  )
    39  
    40  var (
    41  	daoChallengeTimeout = 15 * time.Second
    42  )
    43  
    44  var errIncompatibleConfig = errors.New("incompatible configuration")
    45  
    46  func errResp(code errCode, format string, v ...interface{}) error {
    47  	return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...))
    48  }
    49  
    50  type ProtocolManager struct {
    51  	networkId uint64
    52  
    53  	fastSync  uint32
    54  	acceptTxs uint32
    55  
    56  	txpool      txPool
    57  	blockchain  *core.BlockChain
    58  	chainconfig *params.ChainConfig
    59  	maxPeers    int
    60  
    61  	downloader *downloader.Downloader
    62  	fetcher    *fetcher.Fetcher
    63  	peers      *peerSet
    64  
    65  	SubProtocols []p2p.Protocol
    66  
    67  	eventMux *event.TypeMux
    68  	txCh     chan core.TxPreEvent
    69  	txSub    event.Subscription
    70  
    71  	tx3PrfDtCh    chan core.Tx3ProofDataEvent
    72  	tx3PrfDtFeed  event.Feed
    73  	tx3PrfDtScope event.SubscriptionScope
    74  	tx3PrfDtSub   event.Subscription
    75  
    76  	minedBlockSub *event.TypeMuxSubscription
    77  
    78  	newPeerCh   chan *peer
    79  	txsyncCh    chan *txsync
    80  	quitSync    chan struct{}
    81  	noMorePeers chan struct{}
    82  
    83  	wg sync.WaitGroup
    84  
    85  	engine consensus.Engine
    86  
    87  	cch core.CrossChainHelper
    88  
    89  	logger         log.Logger
    90  	preimageLogger log.Logger
    91  }
    92  
    93  func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkId uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb neatdb.Database, cch core.CrossChainHelper) (*ProtocolManager, error) {
    94  
    95  	manager := &ProtocolManager{
    96  		networkId:      networkId,
    97  		eventMux:       mux,
    98  		txpool:         txpool,
    99  		blockchain:     blockchain,
   100  		chainconfig:    config,
   101  		peers:          newPeerSet(),
   102  		newPeerCh:      make(chan *peer),
   103  		noMorePeers:    make(chan struct{}),
   104  		txsyncCh:       make(chan *txsync),
   105  		quitSync:       make(chan struct{}),
   106  		engine:         engine,
   107  		cch:            cch,
   108  		logger:         config.ChainLogger,
   109  		preimageLogger: config.ChainLogger.New("module", "preimages"),
   110  	}
   111  
   112  	if handler, ok := manager.engine.(consensus.Handler); ok {
   113  		handler.SetBroadcaster(manager)
   114  	}
   115  
   116  	if mode == downloader.FastSync && blockchain.CurrentBlock().NumberU64() > 0 {
   117  		manager.logger.Warn("Blockchain not empty, fast sync disabled")
   118  		mode = downloader.FullSync
   119  	}
   120  	if mode == downloader.FastSync {
   121  		manager.fastSync = uint32(1)
   122  	}
   123  	protocol := engine.Protocol()
   124  
   125  	manager.SubProtocols = make([]p2p.Protocol, 0, len(protocol.Versions))
   126  	for i, version := range protocol.Versions {
   127  
   128  		if mode == downloader.FastSync && version < consensus.Eth63 {
   129  			continue
   130  		}
   131  
   132  		version := version
   133  		manager.SubProtocols = append(manager.SubProtocols, p2p.Protocol{
   134  			Name:    protocol.Name,
   135  			Version: version,
   136  			Length:  protocol.Lengths[i],
   137  			Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
   138  				peer := manager.newPeer(int(version), p, rw)
   139  				select {
   140  				case manager.newPeerCh <- peer:
   141  					manager.wg.Add(1)
   142  					defer manager.wg.Done()
   143  					return manager.handle(peer)
   144  				case <-manager.quitSync:
   145  					return p2p.DiscQuitting
   146  				}
   147  			},
   148  			NodeInfo: func() interface{} {
   149  				return manager.NodeInfo()
   150  			},
   151  			PeerInfo: func(id discover.NodeID) interface{} {
   152  				if p := manager.peers.Peer(fmt.Sprintf("%x", id[:8])); p != nil {
   153  					return p.Info()
   154  				}
   155  				return nil
   156  			},
   157  		})
   158  	}
   159  	if len(manager.SubProtocols) == 0 {
   160  		return nil, errIncompatibleConfig
   161  	}
   162  
   163  	manager.downloader = downloader.New(mode, chaindb, manager.eventMux, blockchain, nil, manager.removePeer, manager.logger)
   164  
   165  	validator := func(header *types.Header) error {
   166  		return engine.VerifyHeader(blockchain, header, true)
   167  	}
   168  	heighter := func() uint64 {
   169  		return blockchain.CurrentBlock().NumberU64()
   170  	}
   171  	inserter := func(blocks types.Blocks) (int, error) {
   172  
   173  		if atomic.LoadUint32(&manager.fastSync) == 1 {
   174  			manager.logger.Warn("Discarded bad propagated block", "number", blocks[0].Number(), "hash", blocks[0].Hash())
   175  			return 0, nil
   176  		}
   177  		atomic.StoreUint32(&manager.acceptTxs, 1)
   178  		return manager.blockchain.InsertChain(blocks)
   179  	}
   180  	manager.fetcher = fetcher.New(blockchain.GetBlockByHash, validator, manager.BroadcastBlock, heighter, inserter, manager.removePeer)
   181  
   182  	return manager, nil
   183  }
   184  
   185  func (pm *ProtocolManager) removePeer(id string) {
   186  
   187  	peer := pm.peers.Peer(id)
   188  	if peer == nil {
   189  		return
   190  	}
   191  	pm.logger.Debug("Removing NEAT Blockchain peer", "peer", id)
   192  
   193  	pm.downloader.UnregisterPeer(id)
   194  	if err := pm.peers.Unregister(id); err != nil {
   195  		pm.logger.Error("Peer removal failed", "peer", id, "err", err)
   196  	}
   197  
   198  	if peer != nil {
   199  		peer.Peer.Disconnect(p2p.DiscUselessPeer)
   200  	}
   201  }
   202  
   203  func (pm *ProtocolManager) Start(maxPeers int) {
   204  	pm.maxPeers = maxPeers
   205  
   206  	pm.txCh = make(chan core.TxPreEvent, txChanSize)
   207  	pm.txSub = pm.txpool.SubscribeTxPreEvent(pm.txCh)
   208  	go pm.txBroadcastLoop()
   209  
   210  	pm.tx3PrfDtCh = make(chan core.Tx3ProofDataEvent, tx3PrfDtChainSize)
   211  	pm.tx3PrfDtSub = pm.tx3PrfDtScope.Track(pm.tx3PrfDtFeed.Subscribe(pm.tx3PrfDtCh))
   212  	go pm.tx3PrfDtBroadcastLoop()
   213  
   214  	pm.minedBlockSub = pm.eventMux.Subscribe(core.NewMinedBlockEvent{})
   215  	go pm.minedBroadcastLoop()
   216  
   217  	go pm.syncer()
   218  	go pm.txsyncLoop()
   219  }
   220  
   221  func (pm *ProtocolManager) Stop() {
   222  	pm.logger.Info("Stopping Neatio protocol")
   223  
   224  	pm.txSub.Unsubscribe()
   225  	pm.tx3PrfDtSub.Unsubscribe()
   226  	pm.minedBlockSub.Unsubscribe()
   227  
   228  	pm.noMorePeers <- struct{}{}
   229  
   230  	close(pm.quitSync)
   231  
   232  	pm.peers.Close()
   233  
   234  	pm.wg.Wait()
   235  
   236  	pm.logger.Info("Neatio protocol stopped")
   237  }
   238  
   239  func (pm *ProtocolManager) newPeer(pv int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
   240  	return newPeer(pv, p, newMeteredMsgWriter(rw))
   241  }
   242  
   243  func (pm *ProtocolManager) handle(p *peer) error {
   244  
   245  	if pm.peers.Len() >= pm.maxPeers && !p.Peer.Info().Network.Trusted {
   246  		return p2p.DiscTooManyPeers
   247  	}
   248  	p.Log().Debug("NEAT Blockchain peer connected", "name", p.Name())
   249  
   250  	var (
   251  		genesis = pm.blockchain.Genesis()
   252  		head    = pm.blockchain.CurrentHeader()
   253  		hash    = head.Hash()
   254  		number  = head.Number.Uint64()
   255  		td      = pm.blockchain.GetTd(hash, number)
   256  	)
   257  	if err := p.Handshake(pm.networkId, td, hash, genesis.Hash()); err != nil {
   258  		p.Log().Debug("NEAT Blockchain handshake failed", "err", err)
   259  		return err
   260  	}
   261  	if rw, ok := p.rw.(*meteredMsgReadWriter); ok {
   262  		rw.Init(p.version)
   263  	}
   264  
   265  	if err := pm.peers.Register(p); err != nil {
   266  		p.Log().Error("NEAT Blockchain peer registration failed", "err", err)
   267  		return err
   268  	}
   269  
   270  	defer func() {
   271  		pm.removePeer(p.id)
   272  		if handler, ok := pm.engine.(consensus.Handler); ok {
   273  			handler.RemovePeer(p)
   274  		}
   275  	}()
   276  
   277  	if err := pm.downloader.RegisterPeer(p.id, p.version, p); err != nil {
   278  		return err
   279  	}
   280  
   281  	pm.syncTransactions(p)
   282  
   283  	if handler, ok := pm.engine.(consensus.Handler); ok {
   284  		handler.AddPeer(p)
   285  	} else {
   286  		p.Log().Info("AddPeer not executed")
   287  	}
   288  
   289  	for {
   290  		if err := pm.handleMsg(p); err != nil {
   291  			p.Log().Debug("NEAT Blockchain message handling failed", "err", err)
   292  			return err
   293  		}
   294  	}
   295  }
   296  
   297  func (pm *ProtocolManager) handleMsg(p *peer) error {
   298  
   299  	msg, err := p.rw.ReadMsg()
   300  	if err != nil {
   301  		return err
   302  	}
   303  	if msg.Size > ProtocolMaxMsgSize {
   304  		return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize)
   305  	}
   306  	defer msg.Discard()
   307  
   308  	switch {
   309  
   310  	case msg.Code >= 0x20 && msg.Code <= 0x23:
   311  		if handler, ok := pm.engine.(consensus.Handler); ok {
   312  			var msgBytes []byte
   313  			if err := msg.Decode(&msgBytes); err != nil {
   314  				return errResp(ErrDecode, "msg %v: %v", msg, err)
   315  			}
   316  			handler.HandleMsg(msg.Code, p, msgBytes)
   317  		}
   318  	case msg.Code == StatusMsg:
   319  
   320  		return errResp(ErrExtraStatusMsg, "uncontrolled status message")
   321  
   322  	case msg.Code == GetBlockHeadersMsg:
   323  
   324  		var query getBlockHeadersData
   325  		if err := msg.Decode(&query); err != nil {
   326  			return errResp(ErrDecode, "%v: %v", msg, err)
   327  		}
   328  		hashMode := query.Origin.Hash != (common.Hash{})
   329  
   330  		var (
   331  			bytes   common.StorageSize
   332  			headers []*types.Header
   333  			unknown bool
   334  		)
   335  		for !unknown && len(headers) < int(query.Amount) && bytes < softResponseLimit && len(headers) < downloader.MaxHeaderFetch {
   336  
   337  			var origin *types.Header
   338  			if hashMode {
   339  				origin = pm.blockchain.GetHeaderByHash(query.Origin.Hash)
   340  			} else {
   341  				origin = pm.blockchain.GetHeaderByNumber(query.Origin.Number)
   342  			}
   343  			if origin == nil {
   344  				break
   345  			}
   346  			number := origin.Number.Uint64()
   347  			headers = append(headers, origin)
   348  			bytes += estHeaderRlpSize
   349  
   350  			switch {
   351  			case query.Origin.Hash != (common.Hash{}) && query.Reverse:
   352  
   353  				for i := 0; i < int(query.Skip)+1; i++ {
   354  					if header := pm.blockchain.GetHeader(query.Origin.Hash, number); header != nil {
   355  						query.Origin.Hash = header.ParentHash
   356  						number--
   357  					} else {
   358  						unknown = true
   359  						break
   360  					}
   361  				}
   362  			case query.Origin.Hash != (common.Hash{}) && !query.Reverse:
   363  
   364  				var (
   365  					current = origin.Number.Uint64()
   366  					next    = current + query.Skip + 1
   367  				)
   368  				if next <= current {
   369  					infos, _ := json.MarshalIndent(p.Peer.Info(), "", "  ")
   370  					p.Log().Warn("GetBlockHeaders skip overflow attack", "current", current, "skip", query.Skip, "next", next, "attacker", infos)
   371  					unknown = true
   372  				} else {
   373  					if header := pm.blockchain.GetHeaderByNumber(next); header != nil {
   374  						if pm.blockchain.GetBlockHashesFromHash(header.Hash(), query.Skip+1)[query.Skip] == query.Origin.Hash {
   375  							query.Origin.Hash = header.Hash()
   376  						} else {
   377  							unknown = true
   378  						}
   379  					} else {
   380  						unknown = true
   381  					}
   382  				}
   383  			case query.Reverse:
   384  
   385  				if query.Origin.Number >= query.Skip+1 {
   386  					query.Origin.Number -= query.Skip + 1
   387  				} else {
   388  					unknown = true
   389  				}
   390  
   391  			case !query.Reverse:
   392  
   393  				query.Origin.Number += query.Skip + 1
   394  			}
   395  		}
   396  		return p.SendBlockHeaders(headers)
   397  
   398  	case msg.Code == BlockHeadersMsg:
   399  
   400  		var headers []*types.Header
   401  		if err := msg.Decode(&headers); err != nil {
   402  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   403  		}
   404  
   405  		filter := len(headers) == 1
   406  		if filter {
   407  
   408  			headers = pm.fetcher.FilterHeaders(p.id, headers, time.Now())
   409  		}
   410  		if len(headers) > 0 || !filter {
   411  			err := pm.downloader.DeliverHeaders(p.id, headers)
   412  			if err != nil {
   413  				pm.logger.Debug("Failed to deliver headers", "err", err)
   414  			}
   415  		}
   416  
   417  	case msg.Code == GetBlockBodiesMsg:
   418  
   419  		msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size))
   420  		if _, err := msgStream.List(); err != nil {
   421  			return err
   422  		}
   423  
   424  		var (
   425  			hash   common.Hash
   426  			bytes  int
   427  			bodies []rlp.RawValue
   428  		)
   429  		for bytes < softResponseLimit && len(bodies) < downloader.MaxBlockFetch {
   430  
   431  			if err := msgStream.Decode(&hash); err == rlp.EOL {
   432  				break
   433  			} else if err != nil {
   434  				return errResp(ErrDecode, "msg %v: %v", msg, err)
   435  			}
   436  
   437  			if data := pm.blockchain.GetBodyRLP(hash); len(data) != 0 {
   438  				bodies = append(bodies, data)
   439  				bytes += len(data)
   440  			}
   441  		}
   442  		return p.SendBlockBodiesRLP(bodies)
   443  
   444  	case msg.Code == BlockBodiesMsg:
   445  
   446  		var request blockBodiesData
   447  		if err := msg.Decode(&request); err != nil {
   448  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   449  		}
   450  
   451  		trasactions := make([][]*types.Transaction, len(request))
   452  		uncles := make([][]*types.Header, len(request))
   453  
   454  		for i, body := range request {
   455  			trasactions[i] = body.Transactions
   456  			uncles[i] = body.Uncles
   457  		}
   458  
   459  		filter := len(trasactions) > 0 || len(uncles) > 0
   460  		if filter {
   461  			trasactions, uncles = pm.fetcher.FilterBodies(p.id, trasactions, uncles, time.Now())
   462  		}
   463  		if len(trasactions) > 0 || len(uncles) > 0 || !filter {
   464  			err := pm.downloader.DeliverBodies(p.id, trasactions, uncles)
   465  			if err != nil {
   466  				pm.logger.Debug("Failed to deliver bodies", "err", err)
   467  			}
   468  		}
   469  
   470  	case p.version >= consensus.Eth63 && msg.Code == GetNodeDataMsg:
   471  
   472  		msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size))
   473  		if _, err := msgStream.List(); err != nil {
   474  			return err
   475  		}
   476  
   477  		var (
   478  			hash  common.Hash
   479  			bytes int
   480  			data  [][]byte
   481  		)
   482  		for bytes < softResponseLimit && len(data) < downloader.MaxStateFetch {
   483  
   484  			if err := msgStream.Decode(&hash); err == rlp.EOL {
   485  				break
   486  			} else if err != nil {
   487  				return errResp(ErrDecode, "msg %v: %v", msg, err)
   488  			}
   489  
   490  			if entry, err := pm.blockchain.TrieNode(hash); err == nil {
   491  				data = append(data, entry)
   492  				bytes += len(entry)
   493  			}
   494  		}
   495  		return p.SendNodeData(data)
   496  
   497  	case p.version >= consensus.Eth63 && msg.Code == NodeDataMsg:
   498  
   499  		var data [][]byte
   500  		if err := msg.Decode(&data); err != nil {
   501  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   502  		}
   503  
   504  		if err := pm.downloader.DeliverNodeData(p.id, data); err != nil {
   505  			pm.logger.Debug("Failed to deliver node state data", "err", err)
   506  		}
   507  
   508  	case p.version >= consensus.Eth63 && msg.Code == GetReceiptsMsg:
   509  
   510  		msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size))
   511  		if _, err := msgStream.List(); err != nil {
   512  			return err
   513  		}
   514  
   515  		var (
   516  			hash     common.Hash
   517  			bytes    int
   518  			receipts []rlp.RawValue
   519  		)
   520  		for bytes < softResponseLimit && len(receipts) < downloader.MaxReceiptFetch {
   521  
   522  			if err := msgStream.Decode(&hash); err == rlp.EOL {
   523  				break
   524  			} else if err != nil {
   525  				return errResp(ErrDecode, "msg %v: %v", msg, err)
   526  			}
   527  
   528  			results := pm.blockchain.GetReceiptsByHash(hash)
   529  			if results == nil {
   530  				if header := pm.blockchain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash {
   531  					continue
   532  				}
   533  			}
   534  
   535  			if encoded, err := rlp.EncodeToBytes(results); err != nil {
   536  				pm.logger.Error("Failed to encode receipt", "err", err)
   537  			} else {
   538  				receipts = append(receipts, encoded)
   539  				bytes += len(encoded)
   540  			}
   541  		}
   542  		return p.SendReceiptsRLP(receipts)
   543  
   544  	case p.version >= consensus.Eth63 && msg.Code == ReceiptsMsg:
   545  
   546  		var receipts [][]*types.Receipt
   547  		if err := msg.Decode(&receipts); err != nil {
   548  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   549  		}
   550  
   551  		if err := pm.downloader.DeliverReceipts(p.id, receipts); err != nil {
   552  			pm.logger.Debug("Failed to deliver receipts", "err", err)
   553  		}
   554  
   555  	case msg.Code == NewBlockHashesMsg:
   556  		var announces newBlockHashesData
   557  		if err := msg.Decode(&announces); err != nil {
   558  			return errResp(ErrDecode, "%v: %v", msg, err)
   559  		}
   560  
   561  		for _, block := range announces {
   562  			p.MarkBlock(block.Hash)
   563  		}
   564  
   565  		unknown := make(newBlockHashesData, 0, len(announces))
   566  		for _, block := range announces {
   567  			if !pm.blockchain.HasBlock(block.Hash, block.Number) {
   568  				unknown = append(unknown, block)
   569  			}
   570  		}
   571  		for _, block := range unknown {
   572  			pm.fetcher.Notify(p.id, block.Hash, block.Number, time.Now(), p.RequestOneHeader, p.RequestBodies)
   573  		}
   574  
   575  	case msg.Code == NewBlockMsg:
   576  
   577  		var request newBlockData
   578  		if err := msg.Decode(&request); err != nil {
   579  			return errResp(ErrDecode, "%v: %v", msg, err)
   580  		}
   581  		request.Block.ReceivedAt = msg.ReceivedAt
   582  		request.Block.ReceivedFrom = p
   583  
   584  		p.MarkBlock(request.Block.Hash())
   585  		pm.fetcher.Enqueue(p.id, request.Block)
   586  
   587  		var (
   588  			trueHead = request.Block.ParentHash()
   589  			trueTD   = new(big.Int).Sub(request.TD, request.Block.Difficulty())
   590  		)
   591  
   592  		if _, td := p.Head(); trueTD.Cmp(td) > 0 {
   593  			p.SetHead(trueHead, trueTD)
   594  
   595  			currentBlock := pm.blockchain.CurrentBlock()
   596  			if trueTD.Cmp(pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64())) > 0 {
   597  				go pm.synchronise(p)
   598  			}
   599  		}
   600  
   601  	case msg.Code == TxMsg:
   602  
   603  		if atomic.LoadUint32(&pm.acceptTxs) == 0 {
   604  			break
   605  		}
   606  
   607  		var txs []*types.Transaction
   608  		if err := msg.Decode(&txs); err != nil {
   609  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   610  		}
   611  		for i, tx := range txs {
   612  
   613  			if tx == nil {
   614  				return errResp(ErrDecode, "transaction %d is nil", i)
   615  			}
   616  			p.MarkTransaction(tx.Hash())
   617  		}
   618  		pm.txpool.AddRemotes(txs)
   619  
   620  	case msg.Code == TX3ProofDataMsg:
   621  		pm.logger.Debug("TX3ProofDataMsg received")
   622  		var proofDatas []*types.TX3ProofData
   623  		if err := msg.Decode(&proofDatas); err != nil {
   624  			pm.logger.Error("TX3ProofDataMsg decode error", "msg", msg, "error", err)
   625  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   626  		}
   627  		for _, proofData := range proofDatas {
   628  
   629  			if err := pm.cch.ValidateTX3ProofData(proofData); err != nil {
   630  				pm.logger.Error("TX3ProofDataMsg validate error", "msg", msg, "error", err)
   631  				return errResp(ErrTX3ValidateFail, "msg %v: %v", msg, err)
   632  			}
   633  			p.MarkTX3ProofData(proofData.Header.Hash())
   634  
   635  			if err := pm.cch.WriteTX3ProofData(proofData); err != nil {
   636  				pm.logger.Error("TX3ProofDataMsg write error", "msg", msg, "error", err)
   637  			}
   638  
   639  			go pm.tx3PrfDtFeed.Send(core.Tx3ProofDataEvent{proofData})
   640  		}
   641  
   642  	case msg.Code == GetPreImagesMsg:
   643  		pm.preimageLogger.Debug("GetPreImagesMsg received")
   644  
   645  		msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size))
   646  		if _, err := msgStream.List(); err != nil {
   647  			return err
   648  		}
   649  
   650  		var (
   651  			hash      common.Hash
   652  			bytes     int
   653  			preimages [][]byte
   654  		)
   655  
   656  		for bytes < softResponseLimit && len(preimages) < downloader.MaxReceiptFetch {
   657  
   658  			if err := msgStream.Decode(&hash); err == rlp.EOL {
   659  				break
   660  			} else if err != nil {
   661  
   662  				return errResp(ErrDecode, "msg %v: %v", msg, err)
   663  			}
   664  
   665  			preimage := rawdb.ReadPreimage(pm.blockchain.StateCache().TrieDB().DiskDB(), hash)
   666  
   667  			if hash != crypto.Keccak256Hash(preimage) {
   668  				pm.preimageLogger.Errorf("Failed to pass the preimage double check. Request hash %x, Local Preimage %x", hash, preimage)
   669  				continue
   670  			}
   671  
   672  			preimages = append(preimages, preimage)
   673  			bytes += len(preimage)
   674  		}
   675  		return p.SendPreimagesRLP(preimages)
   676  
   677  	case msg.Code == PreImagesMsg:
   678  		pm.preimageLogger.Debug("PreImagesMsg received")
   679  		var preimages [][]byte
   680  		if err := msg.Decode(&preimages); err != nil {
   681  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   682  		}
   683  
   684  		preimagesMap := make(map[common.Hash][]byte)
   685  		for _, preimage := range preimages {
   686  			pm.preimageLogger.Debugf("PreImagesMsg received: %x", preimage)
   687  			preimagesMap[crypto.Keccak256Hash(preimage)] = common.CopyBytes(preimage)
   688  		}
   689  		if len(preimagesMap) > 0 {
   690  			db, _ := pm.blockchain.StateCache().TrieDB().DiskDB().(neatdb.Database)
   691  			rawdb.WritePreimages(db, preimagesMap)
   692  			pm.preimageLogger.Info("PreImages wrote into database")
   693  		}
   694  	case msg.Code == TrieNodeDataMsg:
   695  		pm.logger.Debug("TrieNodeDataMsg received")
   696  		var trienodes [][]byte
   697  		if err := msg.Decode(&trienodes); err != nil {
   698  			pm.logger.Warnf("Unable decode TrieNodeData %v", err)
   699  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   700  		}
   701  		pm.logger.Debugf("%d TrieNodeData received", len(trienodes))
   702  
   703  		db, _ := pm.blockchain.StateCache().TrieDB().DiskDB().(neatdb.Database)
   704  		for _, tnode := range trienodes {
   705  			thash := crypto.Keccak256Hash(tnode)
   706  			if has, herr := db.Has(thash.Bytes()); !has && herr == nil {
   707  				puterr := db.Put(thash.Bytes(), tnode)
   708  				if puterr == nil {
   709  					pm.logger.Debugf("Insert TrieNodeData %x", thash)
   710  				}
   711  			} else if has {
   712  				pm.logger.Debugf("TrieNodeData %x already existed", thash)
   713  			}
   714  		}
   715  	default:
   716  		return errResp(ErrInvalidMsgCode, "%v", msg.Code)
   717  	}
   718  	return nil
   719  }
   720  
   721  func (pm *ProtocolManager) Enqueue(id string, block *types.Block) {
   722  	pm.fetcher.Enqueue(id, block)
   723  }
   724  
   725  func (pm *ProtocolManager) BroadcastBlock(block *types.Block, propagate bool) {
   726  	hash := block.Hash()
   727  	peers := pm.peers.PeersWithoutBlock(hash)
   728  
   729  	if propagate {
   730  
   731  		var td *big.Int
   732  		if parent := pm.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1); parent != nil {
   733  			td = new(big.Int).Add(block.Difficulty(), pm.blockchain.GetTd(block.ParentHash(), block.NumberU64()-1))
   734  		} else {
   735  			pm.logger.Error("Propagating dangling block", "number", block.Number(), "hash", hash)
   736  			return
   737  		}
   738  
   739  		transfer := peers[:int(math.Sqrt(float64(len(peers))))]
   740  		for _, peer := range transfer {
   741  			peer.SendNewBlock(block, td)
   742  		}
   743  		pm.logger.Trace("Propagated block", "hash", hash, "recipients", len(transfer), "duration", common.PrettyDuration(time.Since(block.ReceivedAt)))
   744  		return
   745  	}
   746  
   747  	if pm.blockchain.HasBlock(hash, block.NumberU64()) {
   748  		for _, peer := range peers {
   749  			peer.SendNewBlockHashes([]common.Hash{hash}, []uint64{block.NumberU64()})
   750  		}
   751  		pm.logger.Trace("Announced block", "hash", hash, "recipients", len(peers), "duration", common.PrettyDuration(time.Since(block.ReceivedAt)))
   752  	}
   753  }
   754  
   755  func (pm *ProtocolManager) BroadcastTx(hash common.Hash, tx *types.Transaction) {
   756  
   757  	peers := pm.peers.PeersWithoutTx(hash)
   758  
   759  	for _, peer := range peers {
   760  		peer.SendTransactions(types.Transactions{tx})
   761  	}
   762  	pm.logger.Trace("Broadcast transaction", "hash", hash, "recipients", len(peers))
   763  }
   764  
   765  func (pm *ProtocolManager) BroadcastTX3ProofData(hash common.Hash, proofData *types.TX3ProofData) {
   766  
   767  	peers := pm.peers.PeersWithoutTX3ProofData(hash)
   768  	for _, peer := range peers {
   769  		peer.SendTX3ProofData([]*types.TX3ProofData{proofData})
   770  	}
   771  	pm.logger.Trace("Broadcast TX3ProofData", "hash", hash, "recipients", len(peers))
   772  }
   773  
   774  func (pm *ProtocolManager) BroadcastMessage(msgcode uint64, data interface{}) {
   775  	recipients := 0
   776  	for _, peer := range pm.peers.Peers() {
   777  		peer.Send(msgcode, data)
   778  		recipients++
   779  	}
   780  	pm.logger.Trace("Broadcast p2p message", "code", msgcode, "recipients", recipients, "msg", data)
   781  }
   782  
   783  func (pm *ProtocolManager) TryFixBadPreimages() {
   784  
   785  	images := make(map[common.Hash][]byte)
   786  
   787  	var hashes []common.Hash
   788  
   789  	db, _ := pm.blockchain.StateCache().TrieDB().DiskDB().(neatdb.Database)
   790  	it := db.NewIteratorWithPrefix([]byte("secure-key-"))
   791  	for it.Next() {
   792  		keyHash := common.BytesToHash(it.Key())
   793  		valueHash := crypto.Keccak256Hash(it.Value())
   794  		if keyHash != valueHash {
   795  
   796  			hashes = append(hashes, keyHash)
   797  		}
   798  
   799  		images[keyHash] = common.CopyBytes(it.Value())
   800  	}
   801  	it.Release()
   802  
   803  	if len(hashes) > 0 {
   804  		pm.preimageLogger.Critf("Found %d Bad Preimage(s)", len(hashes))
   805  		pm.preimageLogger.Critf("Bad Preimages: %x", hashes)
   806  
   807  		pm.peers.BestPeer().RequestPreimages(hashes)
   808  	}
   809  
   810  }
   811  
   812  func (self *ProtocolManager) minedBroadcastLoop() {
   813  
   814  	for obj := range self.minedBlockSub.Chan() {
   815  		switch ev := obj.Data.(type) {
   816  		case core.NewMinedBlockEvent:
   817  			self.BroadcastBlock(ev.Block, true)
   818  			self.BroadcastBlock(ev.Block, false)
   819  		}
   820  	}
   821  }
   822  
   823  func (self *ProtocolManager) txBroadcastLoop() {
   824  	for {
   825  		select {
   826  		case event := <-self.txCh:
   827  			self.BroadcastTx(event.Tx.Hash(), event.Tx)
   828  
   829  		case <-self.txSub.Err():
   830  			return
   831  		}
   832  	}
   833  }
   834  
   835  func (self *ProtocolManager) tx3PrfDtBroadcastLoop() {
   836  	for {
   837  		select {
   838  		case event := <-self.tx3PrfDtCh:
   839  			self.BroadcastTX3ProofData(event.Tx3PrfDt.Header.Hash(), event.Tx3PrfDt)
   840  
   841  		case <-self.tx3PrfDtSub.Err():
   842  			return
   843  		}
   844  	}
   845  }
   846  
   847  type NodeInfo struct {
   848  	Network    uint64              `json:"network"`
   849  	Difficulty *big.Int            `json:"difficulty"`
   850  	Genesis    common.Hash         `json:"genesis"`
   851  	Config     *params.ChainConfig `json:"config"`
   852  	Head       common.Hash         `json:"head"`
   853  }
   854  
   855  func (self *ProtocolManager) NodeInfo() *NodeInfo {
   856  	currentBlock := self.blockchain.CurrentBlock()
   857  	return &NodeInfo{
   858  		Network:    self.networkId,
   859  		Difficulty: self.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()),
   860  		Genesis:    self.blockchain.Genesis().Hash(),
   861  		Config:     self.blockchain.Config(),
   862  		Head:       currentBlock.Hash(),
   863  	}
   864  }
   865  
   866  func (self *ProtocolManager) FindPeers(targets map[common.Address]bool) map[common.Address]consensus.Peer {
   867  	m := make(map[common.Address]consensus.Peer)
   868  	for _, p := range self.peers.Peers() {
   869  		pubKey, err := p.ID().Pubkey()
   870  		if err != nil {
   871  			continue
   872  		}
   873  		addr := crypto.PubkeyToAddress(*pubKey)
   874  		if targets[addr] {
   875  			m[addr] = p
   876  		}
   877  	}
   878  	return m
   879  }