github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/les/handler.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package les implements the Light Ethereum Subprotocol.
    18  package les
    19  
    20  import (
    21  	"encoding/binary"
    22  	"errors"
    23  	"fmt"
    24  	"math/big"
    25  	"net"
    26  	"sync"
    27  	"time"
    28  
    29  	"github.com/atheioschain/go-atheios/common"
    30  	"github.com/atheioschain/go-atheios/core"
    31  	"github.com/atheioschain/go-atheios/core/state"
    32  	"github.com/atheioschain/go-atheios/core/types"
    33  	"github.com/atheioschain/go-atheios/eth"
    34  	"github.com/atheioschain/go-atheios/eth/downloader"
    35  	"github.com/atheioschain/go-atheios/ethdb"
    36  	"github.com/atheioschain/go-atheios/event"
    37  	"github.com/atheioschain/go-atheios/logger"
    38  	"github.com/atheioschain/go-atheios/logger/glog"
    39  	"github.com/atheioschain/go-atheios/p2p"
    40  	"github.com/atheioschain/go-atheios/p2p/discover"
    41  	"github.com/atheioschain/go-atheios/p2p/discv5"
    42  	"github.com/atheioschain/go-atheios/params"
    43  	"github.com/atheioschain/go-atheios/pow"
    44  	"github.com/atheioschain/go-atheios/rlp"
    45  	"github.com/atheioschain/go-atheios/trie"
    46  )
    47  
    48  const (
    49  	softResponseLimit = 2 * 1024 * 1024 // Target maximum size of returned blocks, headers or node data.
    50  	estHeaderRlpSize  = 500             // Approximate size of an RLP encoded block header
    51  
    52  	ethVersion = 63 // equivalent eth version for the downloader
    53  
    54  	MaxHeaderFetch       = 192 // Amount of block headers to be fetched per retrieval request
    55  	MaxBodyFetch         = 32  // Amount of block bodies to be fetched per retrieval request
    56  	MaxReceiptFetch      = 128 // Amount of transaction receipts to allow fetching per request
    57  	MaxCodeFetch         = 64  // Amount of contract codes to allow fetching per request
    58  	MaxProofsFetch       = 64  // Amount of merkle proofs to be fetched per retrieval request
    59  	MaxHeaderProofsFetch = 64  // Amount of merkle proofs to be fetched per retrieval request
    60  	MaxTxSend            = 64  // Amount of transactions to be send per request
    61  
    62  	disableClientRemovePeer = false
    63  )
    64  
    65  // errIncompatibleConfig is returned if the requested protocols and configs are
    66  // not compatible (low protocol version restrictions and high requirements).
    67  var errIncompatibleConfig = errors.New("incompatible configuration")
    68  
    69  func errResp(code errCode, format string, v ...interface{}) error {
    70  	return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...))
    71  }
    72  
    73  type hashFetcherFn func(common.Hash) error
    74  
    75  type BlockChain interface {
    76  	HasHeader(hash common.Hash) bool
    77  	GetHeader(hash common.Hash, number uint64) *types.Header
    78  	GetHeaderByHash(hash common.Hash) *types.Header
    79  	CurrentHeader() *types.Header
    80  	GetTdByHash(hash common.Hash) *big.Int
    81  	InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error)
    82  	Rollback(chain []common.Hash)
    83  	Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash)
    84  	GetHeaderByNumber(number uint64) *types.Header
    85  	GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash
    86  	LastBlockHash() common.Hash
    87  	Genesis() *types.Block
    88  }
    89  
    90  type txPool interface {
    91  	// AddTransactions should add the given transactions to the pool.
    92  	AddBatch([]*types.Transaction) error
    93  }
    94  
    95  type ProtocolManager struct {
    96  	lightSync   bool
    97  	txpool      txPool
    98  	txrelay     *LesTxRelay
    99  	networkId   int
   100  	chainConfig *params.ChainConfig
   101  	blockchain  BlockChain
   102  	chainDb     ethdb.Database
   103  	odr         *LesOdr
   104  	server      *LesServer
   105  	serverPool  *serverPool
   106  
   107  	downloader *downloader.Downloader
   108  	fetcher    *lightFetcher
   109  	peers      *peerSet
   110  
   111  	SubProtocols []p2p.Protocol
   112  
   113  	eventMux *event.TypeMux
   114  
   115  	// channels for fetcher, syncer, txsyncLoop
   116  	newPeerCh   chan *peer
   117  	quitSync    chan struct{}
   118  	noMorePeers chan struct{}
   119  
   120  	syncMu   sync.Mutex
   121  	syncing  bool
   122  	syncDone chan struct{}
   123  
   124  	// wait group is used for graceful shutdowns during downloading
   125  	// and processing
   126  	wg sync.WaitGroup
   127  }
   128  
   129  // NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
   130  // with the ethereum network.
   131  func NewProtocolManager(chainConfig *params.ChainConfig, lightSync bool, networkId int, mux *event.TypeMux, pow pow.PoW, blockchain BlockChain, txpool txPool, chainDb ethdb.Database, odr *LesOdr, txrelay *LesTxRelay) (*ProtocolManager, error) {
   132  	// Create the protocol manager with the base fields
   133  	manager := &ProtocolManager{
   134  		lightSync:   lightSync,
   135  		eventMux:    mux,
   136  		blockchain:  blockchain,
   137  		chainConfig: chainConfig,
   138  		chainDb:     chainDb,
   139  		networkId:   networkId,
   140  		txpool:      txpool,
   141  		txrelay:     txrelay,
   142  		odr:         odr,
   143  		peers:       newPeerSet(),
   144  		newPeerCh:   make(chan *peer),
   145  		quitSync:    make(chan struct{}),
   146  		noMorePeers: make(chan struct{}),
   147  	}
   148  	// Initiate a sub-protocol for every implemented version we can handle
   149  	manager.SubProtocols = make([]p2p.Protocol, 0, len(ProtocolVersions))
   150  	for i, version := range ProtocolVersions {
   151  		// Compatible, initialize the sub-protocol
   152  		version := version // Closure for the run
   153  		manager.SubProtocols = append(manager.SubProtocols, p2p.Protocol{
   154  			Name:    "les",
   155  			Version: version,
   156  			Length:  ProtocolLengths[i],
   157  			Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
   158  				var entry *poolEntry
   159  				peer := manager.newPeer(int(version), networkId, p, rw)
   160  				if manager.serverPool != nil {
   161  					addr := p.RemoteAddr().(*net.TCPAddr)
   162  					entry = manager.serverPool.connect(peer, addr.IP, uint16(addr.Port))
   163  				}
   164  				peer.poolEntry = entry
   165  				select {
   166  				case manager.newPeerCh <- peer:
   167  					manager.wg.Add(1)
   168  					defer manager.wg.Done()
   169  					err := manager.handle(peer)
   170  					if entry != nil {
   171  						manager.serverPool.disconnect(entry)
   172  					}
   173  					return err
   174  				case <-manager.quitSync:
   175  					if entry != nil {
   176  						manager.serverPool.disconnect(entry)
   177  					}
   178  					return p2p.DiscQuitting
   179  				}
   180  			},
   181  			NodeInfo: func() interface{} {
   182  				return manager.NodeInfo()
   183  			},
   184  			PeerInfo: func(id discover.NodeID) interface{} {
   185  				if p := manager.peers.Peer(fmt.Sprintf("%x", id[:8])); p != nil {
   186  					return p.Info()
   187  				}
   188  				return nil
   189  			},
   190  		})
   191  	}
   192  	if len(manager.SubProtocols) == 0 {
   193  		return nil, errIncompatibleConfig
   194  	}
   195  
   196  	removePeer := manager.removePeer
   197  	if disableClientRemovePeer {
   198  		removePeer = func(id string) {}
   199  	}
   200  
   201  	if lightSync {
   202  		glog.V(logger.Debug).Infof("LES: create downloader")
   203  		manager.downloader = downloader.New(downloader.LightSync, chainDb, manager.eventMux, blockchain.HasHeader, nil, blockchain.GetHeaderByHash,
   204  			nil, blockchain.CurrentHeader, nil, nil, nil, blockchain.GetTdByHash,
   205  			blockchain.InsertHeaderChain, nil, nil, blockchain.Rollback, removePeer)
   206  	}
   207  
   208  	if odr != nil {
   209  		odr.removePeer = removePeer
   210  	}
   211  
   212  	/*validator := func(block *types.Block, parent *types.Block) error {
   213  		return core.ValidateHeader(pow, block.Header(), parent.Header(), true, false)
   214  	}
   215  	heighter := func() uint64 {
   216  		return chainman.LastBlockNumberU64()
   217  	}
   218  	manager.fetcher = fetcher.New(chainman.GetBlockNoOdr, validator, nil, heighter, chainman.InsertChain, manager.removePeer)
   219  	*/
   220  	return manager, nil
   221  }
   222  
   223  func (pm *ProtocolManager) removePeer(id string) {
   224  	// Short circuit if the peer was already removed
   225  	peer := pm.peers.Peer(id)
   226  	if peer == nil {
   227  		return
   228  	}
   229  	if err := pm.peers.Unregister(id); err != nil {
   230  		if err == errNotRegistered {
   231  			return
   232  		}
   233  		glog.V(logger.Error).Infoln("Removal failed:", err)
   234  	}
   235  	glog.V(logger.Debug).Infoln("Removing peer", id)
   236  
   237  	// Unregister the peer from the downloader and Ethereum peer set
   238  	glog.V(logger.Debug).Infof("LES: unregister peer %v", id)
   239  	if pm.lightSync {
   240  		pm.downloader.UnregisterPeer(id)
   241  		if pm.txrelay != nil {
   242  			pm.txrelay.removePeer(id)
   243  		}
   244  		if pm.fetcher != nil {
   245  			pm.fetcher.removePeer(peer)
   246  		}
   247  	}
   248  	// Hard disconnect at the networking layer
   249  	if peer != nil {
   250  		peer.Peer.Disconnect(p2p.DiscUselessPeer)
   251  	}
   252  }
   253  
   254  func (pm *ProtocolManager) Start(srvr *p2p.Server) {
   255  	var topicDisc *discv5.Network
   256  	if srvr != nil {
   257  		topicDisc = srvr.DiscV5
   258  	}
   259  	lesTopic := discv5.Topic("LES@" + common.Bytes2Hex(pm.blockchain.Genesis().Hash().Bytes()[0:8]))
   260  	if pm.lightSync {
   261  		// start sync handler
   262  		if srvr != nil { // srvr is nil during testing
   263  			pm.serverPool = newServerPool(pm.chainDb, []byte("serverPool/"), srvr, lesTopic, pm.quitSync, &pm.wg)
   264  			pm.odr.serverPool = pm.serverPool
   265  			pm.fetcher = newLightFetcher(pm)
   266  		}
   267  		go pm.syncer()
   268  	} else {
   269  		if topicDisc != nil {
   270  			go func() {
   271  				glog.V(logger.Info).Infoln("Starting registering topic", string(lesTopic))
   272  				topicDisc.RegisterTopic(lesTopic, pm.quitSync)
   273  				glog.V(logger.Info).Infoln("Stopped registering topic", string(lesTopic))
   274  			}()
   275  		}
   276  		go func() {
   277  			for range pm.newPeerCh {
   278  			}
   279  		}()
   280  	}
   281  }
   282  
   283  func (pm *ProtocolManager) Stop() {
   284  	// Showing a log message. During download / process this could actually
   285  	// take between 5 to 10 seconds and therefor feedback is required.
   286  	glog.V(logger.Info).Infoln("Stopping light atheios protocol handler...")
   287  
   288  	// Quit the sync loop.
   289  	// After this send has completed, no new peers will be accepted.
   290  	pm.noMorePeers <- struct{}{}
   291  
   292  	close(pm.quitSync) // quits syncer, fetcher
   293  
   294  	// Disconnect existing sessions.
   295  	// This also closes the gate for any new registrations on the peer set.
   296  	// sessions which are already established but not added to pm.peers yet
   297  	// will exit when they try to register.
   298  	pm.peers.Close()
   299  
   300  	// Wait for any process action
   301  	pm.wg.Wait()
   302  
   303  	glog.V(logger.Info).Infoln("Light atheios protocol handler stopped")
   304  }
   305  
   306  func (pm *ProtocolManager) newPeer(pv, nv int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
   307  	return newPeer(pv, nv, p, newMeteredMsgWriter(rw))
   308  }
   309  
   310  // handle is the callback invoked to manage the life cycle of a les peer. When
   311  // this function terminates, the peer is disconnected.
   312  func (pm *ProtocolManager) handle(p *peer) error {
   313  	glog.V(logger.Debug).Infof("%v: peer connected [%s]", p, p.Name())
   314  
   315  	// Execute the LES handshake
   316  	td, head, genesis := pm.blockchain.Status()
   317  	headNum := core.GetBlockNumber(pm.chainDb, head)
   318  	if err := p.Handshake(td, head, headNum, genesis, pm.server); err != nil {
   319  		glog.V(logger.Debug).Infof("%v: handshake failed: %v", p, err)
   320  		return err
   321  	}
   322  	if rw, ok := p.rw.(*meteredMsgReadWriter); ok {
   323  		rw.Init(p.version)
   324  	}
   325  	// Register the peer locally
   326  	glog.V(logger.Detail).Infof("%v: adding peer", p)
   327  	if err := pm.peers.Register(p); err != nil {
   328  		glog.V(logger.Error).Infof("%v: addition failed: %v", p, err)
   329  		return err
   330  	}
   331  	defer func() {
   332  		if pm.server != nil && pm.server.fcManager != nil && p.fcClient != nil {
   333  			p.fcClient.Remove(pm.server.fcManager)
   334  		}
   335  		pm.removePeer(p.id)
   336  	}()
   337  
   338  	// Register the peer in the downloader. If the downloader considers it banned, we disconnect
   339  	glog.V(logger.Debug).Infof("LES: register peer %v", p.id)
   340  	if pm.lightSync {
   341  		requestHeadersByHash := func(origin common.Hash, amount int, skip int, reverse bool) error {
   342  			reqID := getNextReqID()
   343  			cost := p.GetRequestCost(GetBlockHeadersMsg, amount)
   344  			p.fcServer.MustAssignRequest(reqID)
   345  			p.fcServer.SendRequest(reqID, cost)
   346  			return p.RequestHeadersByHash(reqID, cost, origin, amount, skip, reverse)
   347  		}
   348  		requestHeadersByNumber := func(origin uint64, amount int, skip int, reverse bool) error {
   349  			reqID := getNextReqID()
   350  			cost := p.GetRequestCost(GetBlockHeadersMsg, amount)
   351  			p.fcServer.MustAssignRequest(reqID)
   352  			p.fcServer.SendRequest(reqID, cost)
   353  			return p.RequestHeadersByNumber(reqID, cost, origin, amount, skip, reverse)
   354  		}
   355  		if err := pm.downloader.RegisterPeer(p.id, ethVersion, p.HeadAndTd,
   356  			requestHeadersByHash, requestHeadersByNumber, nil, nil, nil); err != nil {
   357  			return err
   358  		}
   359  		if pm.txrelay != nil {
   360  			pm.txrelay.addPeer(p)
   361  		}
   362  
   363  		p.lock.Lock()
   364  		head := p.headInfo
   365  		p.lock.Unlock()
   366  		if pm.fetcher != nil {
   367  			pm.fetcher.addPeer(p)
   368  			pm.fetcher.announce(p, head)
   369  		}
   370  
   371  		if p.poolEntry != nil {
   372  			pm.serverPool.registered(p.poolEntry)
   373  		}
   374  	}
   375  
   376  	stop := make(chan struct{})
   377  	defer close(stop)
   378  	go func() {
   379  		// new block announce loop
   380  		for {
   381  			select {
   382  			case announce := <-p.announceChn:
   383  				p.SendAnnounce(announce)
   384  			case <-stop:
   385  				return
   386  			}
   387  		}
   388  	}()
   389  
   390  	// main loop. handle incoming messages.
   391  	for {
   392  		if err := pm.handleMsg(p); err != nil {
   393  			glog.V(logger.Debug).Infof("%v: message handling failed: %v", p, err)
   394  			return err
   395  		}
   396  	}
   397  }
   398  
   399  var reqList = []uint64{GetBlockHeadersMsg, GetBlockBodiesMsg, GetCodeMsg, GetReceiptsMsg, GetProofsMsg, SendTxMsg, GetHeaderProofsMsg}
   400  
   401  // handleMsg is invoked whenever an inbound message is received from a remote
   402  // peer. The remote connection is torn down upon returning any error.
   403  func (pm *ProtocolManager) handleMsg(p *peer) error {
   404  	// Read the next message from the remote peer, and ensure it's fully consumed
   405  	msg, err := p.rw.ReadMsg()
   406  	if err != nil {
   407  		return err
   408  	}
   409  
   410  	glog.V(logger.Debug).Infoln("msg:", msg.Code, msg.Size)
   411  
   412  	costs := p.fcCosts[msg.Code]
   413  	reject := func(reqCnt, maxCnt uint64) bool {
   414  		if p.fcClient == nil || reqCnt > maxCnt {
   415  			return true
   416  		}
   417  		bufValue, _ := p.fcClient.AcceptRequest()
   418  		cost := costs.baseCost + reqCnt*costs.reqCost
   419  		if cost > pm.server.defParams.BufLimit {
   420  			cost = pm.server.defParams.BufLimit
   421  		}
   422  		if cost > bufValue {
   423  			glog.V(logger.Error).Infof("Request from %v came %v too early", p.id, time.Duration((cost-bufValue)*1000000/pm.server.defParams.MinRecharge))
   424  			return true
   425  		}
   426  		return false
   427  	}
   428  
   429  	if msg.Size > ProtocolMaxMsgSize {
   430  		return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize)
   431  	}
   432  	defer msg.Discard()
   433  
   434  	var deliverMsg *Msg
   435  
   436  	// Handle the message depending on its contents
   437  	switch msg.Code {
   438  	case StatusMsg:
   439  		glog.V(logger.Debug).Infof("<=== StatusMsg from peer %v", p.id)
   440  		// Status messages should never arrive after the handshake
   441  		return errResp(ErrExtraStatusMsg, "uncontrolled status message")
   442  
   443  	// Block header query, collect the requested headers and reply
   444  	case AnnounceMsg:
   445  		glog.V(logger.Debug).Infoln("<=== AnnounceMsg from peer %v:", p.id)
   446  
   447  		var req announceData
   448  		if err := msg.Decode(&req); err != nil {
   449  			return errResp(ErrDecode, "%v: %v", msg, err)
   450  		}
   451  		glog.V(logger.Detail).Infoln("AnnounceMsg:", req.Number, req.Hash, req.Td, req.ReorgDepth)
   452  		if pm.fetcher != nil {
   453  			pm.fetcher.announce(p, &req)
   454  		}
   455  
   456  	case GetBlockHeadersMsg:
   457  		glog.V(logger.Debug).Infof("<=== GetBlockHeadersMsg from peer %v", p.id)
   458  		// Decode the complex header query
   459  		var req struct {
   460  			ReqID uint64
   461  			Query getBlockHeadersData
   462  		}
   463  		if err := msg.Decode(&req); err != nil {
   464  			return errResp(ErrDecode, "%v: %v", msg, err)
   465  		}
   466  
   467  		query := req.Query
   468  		if reject(query.Amount, MaxHeaderFetch) {
   469  			return errResp(ErrRequestRejected, "")
   470  		}
   471  
   472  		hashMode := query.Origin.Hash != (common.Hash{})
   473  
   474  		// Gather headers until the fetch or network limits is reached
   475  		var (
   476  			bytes   common.StorageSize
   477  			headers []*types.Header
   478  			unknown bool
   479  		)
   480  		for !unknown && len(headers) < int(query.Amount) && bytes < softResponseLimit {
   481  			// Retrieve the next header satisfying the query
   482  			var origin *types.Header
   483  			if hashMode {
   484  				origin = pm.blockchain.GetHeaderByHash(query.Origin.Hash)
   485  			} else {
   486  				origin = pm.blockchain.GetHeaderByNumber(query.Origin.Number)
   487  			}
   488  			if origin == nil {
   489  				break
   490  			}
   491  			number := origin.Number.Uint64()
   492  			headers = append(headers, origin)
   493  			bytes += estHeaderRlpSize
   494  
   495  			// Advance to the next header of the query
   496  			switch {
   497  			case query.Origin.Hash != (common.Hash{}) && query.Reverse:
   498  				// Hash based traversal towards the genesis block
   499  				for i := 0; i < int(query.Skip)+1; i++ {
   500  					if header := pm.blockchain.GetHeader(query.Origin.Hash, number); header != nil {
   501  						query.Origin.Hash = header.ParentHash
   502  						number--
   503  					} else {
   504  						unknown = true
   505  						break
   506  					}
   507  				}
   508  			case query.Origin.Hash != (common.Hash{}) && !query.Reverse:
   509  				// Hash based traversal towards the leaf block
   510  				if header := pm.blockchain.GetHeaderByNumber(origin.Number.Uint64() + query.Skip + 1); header != nil {
   511  					if pm.blockchain.GetBlockHashesFromHash(header.Hash(), query.Skip+1)[query.Skip] == query.Origin.Hash {
   512  						query.Origin.Hash = header.Hash()
   513  					} else {
   514  						unknown = true
   515  					}
   516  				} else {
   517  					unknown = true
   518  				}
   519  			case query.Reverse:
   520  				// Number based traversal towards the genesis block
   521  				if query.Origin.Number >= query.Skip+1 {
   522  					query.Origin.Number -= (query.Skip + 1)
   523  				} else {
   524  					unknown = true
   525  				}
   526  
   527  			case !query.Reverse:
   528  				// Number based traversal towards the leaf block
   529  				query.Origin.Number += (query.Skip + 1)
   530  			}
   531  		}
   532  
   533  		bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + query.Amount*costs.reqCost)
   534  		pm.server.fcCostStats.update(msg.Code, query.Amount, rcost)
   535  		return p.SendBlockHeaders(req.ReqID, bv, headers)
   536  
   537  	case BlockHeadersMsg:
   538  		if pm.downloader == nil {
   539  			return errResp(ErrUnexpectedResponse, "")
   540  		}
   541  
   542  		glog.V(logger.Debug).Infof("<=== BlockHeadersMsg from peer %v", p.id)
   543  		// A batch of headers arrived to one of our previous requests
   544  		var resp struct {
   545  			ReqID, BV uint64
   546  			Headers   []*types.Header
   547  		}
   548  		if err := msg.Decode(&resp); err != nil {
   549  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   550  		}
   551  		p.fcServer.GotReply(resp.ReqID, resp.BV)
   552  		if pm.fetcher != nil && pm.fetcher.requestedID(resp.ReqID) {
   553  			pm.fetcher.deliverHeaders(p, resp.ReqID, resp.Headers)
   554  		} else {
   555  			err := pm.downloader.DeliverHeaders(p.id, resp.Headers)
   556  			if err != nil {
   557  				glog.V(logger.Debug).Infoln(err)
   558  			}
   559  		}
   560  
   561  	case GetBlockBodiesMsg:
   562  		glog.V(logger.Debug).Infof("<===  GetBlockBodiesMsg from peer %v", p.id)
   563  		// Decode the retrieval message
   564  		var req struct {
   565  			ReqID  uint64
   566  			Hashes []common.Hash
   567  		}
   568  		if err := msg.Decode(&req); err != nil {
   569  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   570  		}
   571  		// Gather blocks until the fetch or network limits is reached
   572  		var (
   573  			bytes  int
   574  			bodies []rlp.RawValue
   575  		)
   576  		reqCnt := len(req.Hashes)
   577  		if reject(uint64(reqCnt), MaxBodyFetch) {
   578  			return errResp(ErrRequestRejected, "")
   579  		}
   580  		for _, hash := range req.Hashes {
   581  			if bytes >= softResponseLimit {
   582  				break
   583  			}
   584  			// Retrieve the requested block body, stopping if enough was found
   585  			if data := core.GetBodyRLP(pm.chainDb, hash, core.GetBlockNumber(pm.chainDb, hash)); len(data) != 0 {
   586  				bodies = append(bodies, data)
   587  				bytes += len(data)
   588  			}
   589  		}
   590  		bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
   591  		pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
   592  		return p.SendBlockBodiesRLP(req.ReqID, bv, bodies)
   593  
   594  	case BlockBodiesMsg:
   595  		if pm.odr == nil {
   596  			return errResp(ErrUnexpectedResponse, "")
   597  		}
   598  
   599  		glog.V(logger.Debug).Infof("<===  BlockBodiesMsg from peer %v", p.id)
   600  		// A batch of block bodies arrived to one of our previous requests
   601  		var resp struct {
   602  			ReqID, BV uint64
   603  			Data      []*types.Body
   604  		}
   605  		if err := msg.Decode(&resp); err != nil {
   606  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   607  		}
   608  		p.fcServer.GotReply(resp.ReqID, resp.BV)
   609  		deliverMsg = &Msg{
   610  			MsgType: MsgBlockBodies,
   611  			ReqID:   resp.ReqID,
   612  			Obj:     resp.Data,
   613  		}
   614  
   615  	case GetCodeMsg:
   616  		glog.V(logger.Debug).Infof("<===  GetCodeMsg from peer %v", p.id)
   617  		// Decode the retrieval message
   618  		var req struct {
   619  			ReqID uint64
   620  			Reqs  []CodeReq
   621  		}
   622  		if err := msg.Decode(&req); err != nil {
   623  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   624  		}
   625  		// Gather state data until the fetch or network limits is reached
   626  		var (
   627  			bytes int
   628  			data  [][]byte
   629  		)
   630  		reqCnt := len(req.Reqs)
   631  		if reject(uint64(reqCnt), MaxCodeFetch) {
   632  			return errResp(ErrRequestRejected, "")
   633  		}
   634  		for _, req := range req.Reqs {
   635  			// Retrieve the requested state entry, stopping if enough was found
   636  			if header := core.GetHeader(pm.chainDb, req.BHash, core.GetBlockNumber(pm.chainDb, req.BHash)); header != nil {
   637  				if trie, _ := trie.New(header.Root, pm.chainDb); trie != nil {
   638  					sdata := trie.Get(req.AccKey)
   639  					var acc state.Account
   640  					if err := rlp.DecodeBytes(sdata, &acc); err == nil {
   641  						entry, _ := pm.chainDb.Get(acc.CodeHash)
   642  						if bytes+len(entry) >= softResponseLimit {
   643  							break
   644  						}
   645  						data = append(data, entry)
   646  						bytes += len(entry)
   647  					}
   648  				}
   649  			}
   650  		}
   651  		bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
   652  		pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
   653  		return p.SendCode(req.ReqID, bv, data)
   654  
   655  	case CodeMsg:
   656  		if pm.odr == nil {
   657  			return errResp(ErrUnexpectedResponse, "")
   658  		}
   659  
   660  		glog.V(logger.Debug).Infof("<=== CodeMsg from peer %v", p.id)
   661  		// A batch of node state data arrived to one of our previous requests
   662  		var resp struct {
   663  			ReqID, BV uint64
   664  			Data      [][]byte
   665  		}
   666  		if err := msg.Decode(&resp); err != nil {
   667  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   668  		}
   669  		p.fcServer.GotReply(resp.ReqID, resp.BV)
   670  		deliverMsg = &Msg{
   671  			MsgType: MsgCode,
   672  			ReqID:   resp.ReqID,
   673  			Obj:     resp.Data,
   674  		}
   675  
   676  	case GetReceiptsMsg:
   677  		glog.V(logger.Debug).Infof("<===  GetReceiptsMsg from peer %v", p.id)
   678  		// Decode the retrieval message
   679  		var req struct {
   680  			ReqID  uint64
   681  			Hashes []common.Hash
   682  		}
   683  		if err := msg.Decode(&req); err != nil {
   684  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   685  		}
   686  		// Gather state data until the fetch or network limits is reached
   687  		var (
   688  			bytes    int
   689  			receipts []rlp.RawValue
   690  		)
   691  		reqCnt := len(req.Hashes)
   692  		if reject(uint64(reqCnt), MaxReceiptFetch) {
   693  			return errResp(ErrRequestRejected, "")
   694  		}
   695  		for _, hash := range req.Hashes {
   696  			if bytes >= softResponseLimit {
   697  				break
   698  			}
   699  			// Retrieve the requested block's receipts, skipping if unknown to us
   700  			results := core.GetBlockReceipts(pm.chainDb, hash, core.GetBlockNumber(pm.chainDb, hash))
   701  			if results == nil {
   702  				if header := pm.blockchain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash {
   703  					continue
   704  				}
   705  			}
   706  			// If known, encode and queue for response packet
   707  			if encoded, err := rlp.EncodeToBytes(results); err != nil {
   708  				glog.V(logger.Error).Infof("failed to encode receipt: %v", err)
   709  			} else {
   710  				receipts = append(receipts, encoded)
   711  				bytes += len(encoded)
   712  			}
   713  		}
   714  		bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
   715  		pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
   716  		return p.SendReceiptsRLP(req.ReqID, bv, receipts)
   717  
   718  	case ReceiptsMsg:
   719  		if pm.odr == nil {
   720  			return errResp(ErrUnexpectedResponse, "")
   721  		}
   722  
   723  		glog.V(logger.Debug).Infof("<=== ReceiptsMsg from peer %v", p.id)
   724  		// A batch of receipts arrived to one of our previous requests
   725  		var resp struct {
   726  			ReqID, BV uint64
   727  			Receipts  []types.Receipts
   728  		}
   729  		if err := msg.Decode(&resp); err != nil {
   730  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   731  		}
   732  		p.fcServer.GotReply(resp.ReqID, resp.BV)
   733  		deliverMsg = &Msg{
   734  			MsgType: MsgReceipts,
   735  			ReqID:   resp.ReqID,
   736  			Obj:     resp.Receipts,
   737  		}
   738  
   739  	case GetProofsMsg:
   740  		glog.V(logger.Debug).Infof("<=== GetProofsMsg from peer %v", p.id)
   741  		// Decode the retrieval message
   742  		var req struct {
   743  			ReqID uint64
   744  			Reqs  []ProofReq
   745  		}
   746  		if err := msg.Decode(&req); err != nil {
   747  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   748  		}
   749  		// Gather state data until the fetch or network limits is reached
   750  		var (
   751  			bytes  int
   752  			proofs proofsData
   753  		)
   754  		reqCnt := len(req.Reqs)
   755  		if reject(uint64(reqCnt), MaxProofsFetch) {
   756  			return errResp(ErrRequestRejected, "")
   757  		}
   758  		for _, req := range req.Reqs {
   759  			if bytes >= softResponseLimit {
   760  				break
   761  			}
   762  			// Retrieve the requested state entry, stopping if enough was found
   763  			if header := core.GetHeader(pm.chainDb, req.BHash, core.GetBlockNumber(pm.chainDb, req.BHash)); header != nil {
   764  				if tr, _ := trie.New(header.Root, pm.chainDb); tr != nil {
   765  					if len(req.AccKey) > 0 {
   766  						sdata := tr.Get(req.AccKey)
   767  						tr = nil
   768  						var acc state.Account
   769  						if err := rlp.DecodeBytes(sdata, &acc); err == nil {
   770  							tr, _ = trie.New(acc.Root, pm.chainDb)
   771  						}
   772  					}
   773  					if tr != nil {
   774  						proof := tr.Prove(req.Key)
   775  						proofs = append(proofs, proof)
   776  						bytes += len(proof)
   777  					}
   778  				}
   779  			}
   780  		}
   781  		bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
   782  		pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
   783  		return p.SendProofs(req.ReqID, bv, proofs)
   784  
   785  	case ProofsMsg:
   786  		if pm.odr == nil {
   787  			return errResp(ErrUnexpectedResponse, "")
   788  		}
   789  
   790  		glog.V(logger.Debug).Infof("<=== ProofsMsg from peer %v", p.id)
   791  		// A batch of merkle proofs arrived to one of our previous requests
   792  		var resp struct {
   793  			ReqID, BV uint64
   794  			Data      [][]rlp.RawValue
   795  		}
   796  		if err := msg.Decode(&resp); err != nil {
   797  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   798  		}
   799  		p.fcServer.GotReply(resp.ReqID, resp.BV)
   800  		deliverMsg = &Msg{
   801  			MsgType: MsgProofs,
   802  			ReqID:   resp.ReqID,
   803  			Obj:     resp.Data,
   804  		}
   805  
   806  	case GetHeaderProofsMsg:
   807  		glog.V(logger.Debug).Infof("<=== GetHeaderProofsMsg from peer %v", p.id)
   808  		// Decode the retrieval message
   809  		var req struct {
   810  			ReqID uint64
   811  			Reqs  []ChtReq
   812  		}
   813  		if err := msg.Decode(&req); err != nil {
   814  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   815  		}
   816  		// Gather state data until the fetch or network limits is reached
   817  		var (
   818  			bytes  int
   819  			proofs []ChtResp
   820  		)
   821  		reqCnt := len(req.Reqs)
   822  		if reject(uint64(reqCnt), MaxHeaderProofsFetch) {
   823  			return errResp(ErrRequestRejected, "")
   824  		}
   825  		for _, req := range req.Reqs {
   826  			if bytes >= softResponseLimit {
   827  				break
   828  			}
   829  
   830  			if header := pm.blockchain.GetHeaderByNumber(req.BlockNum); header != nil {
   831  				if root := getChtRoot(pm.chainDb, req.ChtNum); root != (common.Hash{}) {
   832  					if tr, _ := trie.New(root, pm.chainDb); tr != nil {
   833  						var encNumber [8]byte
   834  						binary.BigEndian.PutUint64(encNumber[:], req.BlockNum)
   835  						proof := tr.Prove(encNumber[:])
   836  						proofs = append(proofs, ChtResp{Header: header, Proof: proof})
   837  						bytes += len(proof) + estHeaderRlpSize
   838  					}
   839  				}
   840  			}
   841  		}
   842  		bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
   843  		pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
   844  		return p.SendHeaderProofs(req.ReqID, bv, proofs)
   845  
   846  	case HeaderProofsMsg:
   847  		if pm.odr == nil {
   848  			return errResp(ErrUnexpectedResponse, "")
   849  		}
   850  
   851  		glog.V(logger.Debug).Infof("<=== HeaderProofsMsg from peer %v", p.id)
   852  		var resp struct {
   853  			ReqID, BV uint64
   854  			Data      []ChtResp
   855  		}
   856  		if err := msg.Decode(&resp); err != nil {
   857  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   858  		}
   859  		p.fcServer.GotReply(resp.ReqID, resp.BV)
   860  		deliverMsg = &Msg{
   861  			MsgType: MsgHeaderProofs,
   862  			ReqID:   resp.ReqID,
   863  			Obj:     resp.Data,
   864  		}
   865  
   866  	case SendTxMsg:
   867  		if pm.txpool == nil {
   868  			return errResp(ErrUnexpectedResponse, "")
   869  		}
   870  		// Transactions arrived, parse all of them and deliver to the pool
   871  		var txs []*types.Transaction
   872  		if err := msg.Decode(&txs); err != nil {
   873  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   874  		}
   875  		reqCnt := len(txs)
   876  		if reject(uint64(reqCnt), MaxTxSend) {
   877  			return errResp(ErrRequestRejected, "")
   878  		}
   879  
   880  		if err := pm.txpool.AddBatch(txs); err != nil {
   881  			return errResp(ErrUnexpectedResponse, "msg: %v", err)
   882  		}
   883  
   884  		_, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
   885  		pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
   886  
   887  	default:
   888  		glog.V(logger.Debug).Infof("<=== unknown message with code %d from peer %v", msg.Code, p.id)
   889  		return errResp(ErrInvalidMsgCode, "%v", msg.Code)
   890  	}
   891  
   892  	if deliverMsg != nil {
   893  		return pm.odr.Deliver(p, deliverMsg)
   894  	}
   895  
   896  	return nil
   897  }
   898  
   899  // NodeInfo retrieves some protocol metadata about the running host node.
   900  func (self *ProtocolManager) NodeInfo() *eth.EthNodeInfo {
   901  	return &eth.EthNodeInfo{
   902  		Network:    self.networkId,
   903  		Difficulty: self.blockchain.GetTdByHash(self.blockchain.LastBlockHash()),
   904  		Genesis:    self.blockchain.Genesis().Hash(),
   905  		Head:       self.blockchain.LastBlockHash(),
   906  	}
   907  }