github.com/mrwater98/go-ethereum@v1.9.7/eth/peer.go (about)

     1  // Copyright 2015 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 eth
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"math/big"
    23  	"sync"
    24  	"time"
    25  
    26  	mapset "github.com/deckarep/golang-set"
    27  	"github.com/ethereum/go-ethereum/common"
    28  	"github.com/ethereum/go-ethereum/core/forkid"
    29  	"github.com/ethereum/go-ethereum/core/types"
    30  	"github.com/ethereum/go-ethereum/p2p"
    31  	"github.com/ethereum/go-ethereum/rlp"
    32  )
    33  
    34  var (
    35  	errClosed            = errors.New("peer set is closed")
    36  	errAlreadyRegistered = errors.New("peer is already registered")
    37  	errNotRegistered     = errors.New("peer is not registered")
    38  )
    39  
    40  const (
    41  	maxKnownTxs    = 32768 // Maximum transactions hashes to keep in the known list (prevent DOS)
    42  	maxKnownBlocks = 1024  // Maximum block hashes to keep in the known list (prevent DOS)
    43  
    44  	// maxQueuedTxs is the maximum number of transaction lists to queue up before
    45  	// dropping broadcasts. This is a sensitive number as a transaction list might
    46  	// contain a single transaction, or thousands.
    47  	maxQueuedTxs = 128
    48  
    49  	// maxQueuedProps is the maximum number of block propagations to queue up before
    50  	// dropping broadcasts. There's not much point in queueing stale blocks, so a few
    51  	// that might cover uncles should be enough.
    52  	maxQueuedProps = 4
    53  
    54  	// maxQueuedAnns is the maximum number of block announcements to queue up before
    55  	// dropping broadcasts. Similarly to block propagations, there's no point to queue
    56  	// above some healthy uncle limit, so use that.
    57  	maxQueuedAnns = 4
    58  
    59  	handshakeTimeout = 5 * time.Second
    60  )
    61  
    62  // PeerInfo represents a short summary of the Ethereum sub-protocol metadata known
    63  // about a connected peer.
    64  type PeerInfo struct {
    65  	Version    int      `json:"version"`    // Ethereum protocol version negotiated
    66  	Difficulty *big.Int `json:"difficulty"` // Total difficulty of the peer's blockchain
    67  	Head       string   `json:"head"`       // SHA3 hash of the peer's best owned block
    68  }
    69  
    70  // propEvent is a block propagation, waiting for its turn in the broadcast queue.
    71  type propEvent struct {
    72  	block *types.Block
    73  	td    *big.Int
    74  }
    75  
    76  type peer struct {
    77  	id string
    78  
    79  	*p2p.Peer
    80  	rw p2p.MsgReadWriter
    81  
    82  	version  int         // Protocol version negotiated
    83  	syncDrop *time.Timer // Timed connection dropper if sync progress isn't validated in time
    84  
    85  	head common.Hash
    86  	td   *big.Int
    87  	lock sync.RWMutex
    88  
    89  	knownTxs    mapset.Set                // Set of transaction hashes known to be known by this peer
    90  	knownBlocks mapset.Set                // Set of block hashes known to be known by this peer
    91  	queuedTxs   chan []*types.Transaction // Queue of transactions to broadcast to the peer
    92  	queuedProps chan *propEvent           // Queue of blocks to broadcast to the peer
    93  	queuedAnns  chan *types.Block         // Queue of blocks to announce to the peer
    94  	term        chan struct{}             // Termination channel to stop the broadcaster
    95  }
    96  
    97  func newPeer(version int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
    98  	return &peer{
    99  		Peer:        p,
   100  		rw:          rw,
   101  		version:     version,
   102  		id:          fmt.Sprintf("%x", p.ID().Bytes()[:8]),
   103  		knownTxs:    mapset.NewSet(),
   104  		knownBlocks: mapset.NewSet(),
   105  		queuedTxs:   make(chan []*types.Transaction, maxQueuedTxs),
   106  		queuedProps: make(chan *propEvent, maxQueuedProps),
   107  		queuedAnns:  make(chan *types.Block, maxQueuedAnns),
   108  		term:        make(chan struct{}),
   109  	}
   110  }
   111  
   112  // broadcast is a write loop that multiplexes block propagations, announcements
   113  // and transaction broadcasts into the remote peer. The goal is to have an async
   114  // writer that does not lock up node internals.
   115  func (p *peer) broadcast() {
   116  	for {
   117  		select {
   118  		case txs := <-p.queuedTxs:
   119  			if err := p.SendTransactions(txs); err != nil {
   120  				return
   121  			}
   122  			p.Log().Trace("Broadcast transactions", "count", len(txs))
   123  
   124  		case prop := <-p.queuedProps:
   125  			if err := p.SendNewBlock(prop.block, prop.td); err != nil {
   126  				return
   127  			}
   128  			p.Log().Trace("Propagated block", "number", prop.block.Number(), "hash", prop.block.Hash(), "td", prop.td)
   129  
   130  		case block := <-p.queuedAnns:
   131  			if err := p.SendNewBlockHashes([]common.Hash{block.Hash()}, []uint64{block.NumberU64()}); err != nil {
   132  				return
   133  			}
   134  			p.Log().Trace("Announced block", "number", block.Number(), "hash", block.Hash())
   135  
   136  		case <-p.term:
   137  			return
   138  		}
   139  	}
   140  }
   141  
   142  // close signals the broadcast goroutine to terminate.
   143  func (p *peer) close() {
   144  	close(p.term)
   145  }
   146  
   147  // Info gathers and returns a collection of metadata known about a peer.
   148  func (p *peer) Info() *PeerInfo {
   149  	hash, td := p.Head()
   150  
   151  	return &PeerInfo{
   152  		Version:    p.version,
   153  		Difficulty: td,
   154  		Head:       hash.Hex(),
   155  	}
   156  }
   157  
   158  // Head retrieves a copy of the current head hash and total difficulty of the
   159  // peer.
   160  func (p *peer) Head() (hash common.Hash, td *big.Int) {
   161  	p.lock.RLock()
   162  	defer p.lock.RUnlock()
   163  
   164  	copy(hash[:], p.head[:])
   165  	return hash, new(big.Int).Set(p.td)
   166  }
   167  
   168  // SetHead updates the head hash and total difficulty of the peer.
   169  func (p *peer) SetHead(hash common.Hash, td *big.Int) {
   170  	p.lock.Lock()
   171  	defer p.lock.Unlock()
   172  
   173  	copy(p.head[:], hash[:])
   174  	p.td.Set(td)
   175  }
   176  
   177  // MarkBlock marks a block as known for the peer, ensuring that the block will
   178  // never be propagated to this particular peer.
   179  func (p *peer) MarkBlock(hash common.Hash) {
   180  	// If we reached the memory allowance, drop a previously known block hash
   181  	for p.knownBlocks.Cardinality() >= maxKnownBlocks {
   182  		p.knownBlocks.Pop()
   183  	}
   184  	p.knownBlocks.Add(hash)
   185  }
   186  
   187  // MarkTransaction marks a transaction as known for the peer, ensuring that it
   188  // will never be propagated to this particular peer.
   189  func (p *peer) MarkTransaction(hash common.Hash) {
   190  	// If we reached the memory allowance, drop a previously known transaction hash
   191  	for p.knownTxs.Cardinality() >= maxKnownTxs {
   192  		p.knownTxs.Pop()
   193  	}
   194  	p.knownTxs.Add(hash)
   195  }
   196  
   197  // SendTransactions sends transactions to the peer and includes the hashes
   198  // in its transaction hash set for future reference.
   199  func (p *peer) SendTransactions(txs types.Transactions) error {
   200  	// Mark all the transactions as known, but ensure we don't overflow our limits
   201  	for _, tx := range txs {
   202  		p.knownTxs.Add(tx.Hash())
   203  	}
   204  	for p.knownTxs.Cardinality() >= maxKnownTxs {
   205  		p.knownTxs.Pop()
   206  	}
   207  	return p2p.Send(p.rw, TxMsg, txs)
   208  }
   209  
   210  // AsyncSendTransactions queues list of transactions propagation to a remote
   211  // peer. If the peer's broadcast queue is full, the event is silently dropped.
   212  func (p *peer) AsyncSendTransactions(txs []*types.Transaction) {
   213  	select {
   214  	case p.queuedTxs <- txs:
   215  		// Mark all the transactions as known, but ensure we don't overflow our limits
   216  		for _, tx := range txs {
   217  			p.knownTxs.Add(tx.Hash())
   218  		}
   219  		for p.knownTxs.Cardinality() >= maxKnownTxs {
   220  			p.knownTxs.Pop()
   221  		}
   222  	default:
   223  		p.Log().Debug("Dropping transaction propagation", "count", len(txs))
   224  	}
   225  }
   226  
   227  // SendNewBlockHashes announces the availability of a number of blocks through
   228  // a hash notification.
   229  func (p *peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error {
   230  	// Mark all the block hashes as known, but ensure we don't overflow our limits
   231  	for _, hash := range hashes {
   232  		p.knownBlocks.Add(hash)
   233  	}
   234  	for p.knownBlocks.Cardinality() >= maxKnownBlocks {
   235  		p.knownBlocks.Pop()
   236  	}
   237  	request := make(newBlockHashesData, len(hashes))
   238  	for i := 0; i < len(hashes); i++ {
   239  		request[i].Hash = hashes[i]
   240  		request[i].Number = numbers[i]
   241  	}
   242  	return p2p.Send(p.rw, NewBlockHashesMsg, request)
   243  }
   244  
   245  // AsyncSendNewBlockHash queues the availability of a block for propagation to a
   246  // remote peer. If the peer's broadcast queue is full, the event is silently
   247  // dropped.
   248  func (p *peer) AsyncSendNewBlockHash(block *types.Block) {
   249  	select {
   250  	case p.queuedAnns <- block:
   251  		// Mark all the block hash as known, but ensure we don't overflow our limits
   252  		p.knownBlocks.Add(block.Hash())
   253  		for p.knownBlocks.Cardinality() >= maxKnownBlocks {
   254  			p.knownBlocks.Pop()
   255  		}
   256  	default:
   257  		p.Log().Debug("Dropping block announcement", "number", block.NumberU64(), "hash", block.Hash())
   258  	}
   259  }
   260  
   261  // SendNewBlock propagates an entire block to a remote peer.
   262  func (p *peer) SendNewBlock(block *types.Block, td *big.Int) error {
   263  	// Mark all the block hash as known, but ensure we don't overflow our limits
   264  	p.knownBlocks.Add(block.Hash())
   265  	for p.knownBlocks.Cardinality() >= maxKnownBlocks {
   266  		p.knownBlocks.Pop()
   267  	}
   268  	return p2p.Send(p.rw, NewBlockMsg, []interface{}{block, td})
   269  }
   270  
   271  // AsyncSendNewBlock queues an entire block for propagation to a remote peer. If
   272  // the peer's broadcast queue is full, the event is silently dropped.
   273  func (p *peer) AsyncSendNewBlock(block *types.Block, td *big.Int) {
   274  	select {
   275  	case p.queuedProps <- &propEvent{block: block, td: td}:
   276  		// Mark all the block hash as known, but ensure we don't overflow our limits
   277  		p.knownBlocks.Add(block.Hash())
   278  		for p.knownBlocks.Cardinality() >= maxKnownBlocks {
   279  			p.knownBlocks.Pop()
   280  		}
   281  	default:
   282  		p.Log().Debug("Dropping block propagation", "number", block.NumberU64(), "hash", block.Hash())
   283  	}
   284  }
   285  
   286  // SendBlockHeaders sends a batch of block headers to the remote peer.
   287  func (p *peer) SendBlockHeaders(headers []*types.Header) error {
   288  	return p2p.Send(p.rw, BlockHeadersMsg, headers)
   289  }
   290  
   291  // SendBlockBodies sends a batch of block contents to the remote peer.
   292  func (p *peer) SendBlockBodies(bodies []*blockBody) error {
   293  	return p2p.Send(p.rw, BlockBodiesMsg, blockBodiesData(bodies))
   294  }
   295  
   296  // SendBlockBodiesRLP sends a batch of block contents to the remote peer from
   297  // an already RLP encoded format.
   298  func (p *peer) SendBlockBodiesRLP(bodies []rlp.RawValue) error {
   299  	return p2p.Send(p.rw, BlockBodiesMsg, bodies)
   300  }
   301  
   302  // SendNodeDataRLP sends a batch of arbitrary internal data, corresponding to the
   303  // hashes requested.
   304  func (p *peer) SendNodeData(data [][]byte) error {
   305  	return p2p.Send(p.rw, NodeDataMsg, data)
   306  }
   307  
   308  // SendReceiptsRLP sends a batch of transaction receipts, corresponding to the
   309  // ones requested from an already RLP encoded format.
   310  func (p *peer) SendReceiptsRLP(receipts []rlp.RawValue) error {
   311  	return p2p.Send(p.rw, ReceiptsMsg, receipts)
   312  }
   313  
   314  // RequestOneHeader is a wrapper around the header query functions to fetch a
   315  // single header. It is used solely by the fetcher.
   316  func (p *peer) RequestOneHeader(hash common.Hash) error {
   317  	p.Log().Debug("Fetching single header", "hash", hash)
   318  	return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: hash}, Amount: uint64(1), Skip: uint64(0), Reverse: false})
   319  }
   320  
   321  // RequestHeadersByHash fetches a batch of blocks' headers corresponding to the
   322  // specified header query, based on the hash of an origin block.
   323  func (p *peer) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error {
   324  	p.Log().Debug("Fetching batch of headers", "count", amount, "fromhash", origin, "skip", skip, "reverse", reverse)
   325  	return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse})
   326  }
   327  
   328  // RequestHeadersByNumber fetches a batch of blocks' headers corresponding to the
   329  // specified header query, based on the number of an origin block.
   330  func (p *peer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error {
   331  	p.Log().Debug("Fetching batch of headers", "count", amount, "fromnum", origin, "skip", skip, "reverse", reverse)
   332  	return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Number: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse})
   333  }
   334  
   335  // RequestBodies fetches a batch of blocks' bodies corresponding to the hashes
   336  // specified.
   337  func (p *peer) RequestBodies(hashes []common.Hash) error {
   338  	p.Log().Debug("Fetching batch of block bodies", "count", len(hashes))
   339  	return p2p.Send(p.rw, GetBlockBodiesMsg, hashes)
   340  }
   341  
   342  // RequestNodeData fetches a batch of arbitrary data from a node's known state
   343  // data, corresponding to the specified hashes.
   344  func (p *peer) RequestNodeData(hashes []common.Hash) error {
   345  	p.Log().Debug("Fetching batch of state data", "count", len(hashes))
   346  	return p2p.Send(p.rw, GetNodeDataMsg, hashes)
   347  }
   348  
   349  // RequestReceipts fetches a batch of transaction receipts from a remote node.
   350  func (p *peer) RequestReceipts(hashes []common.Hash) error {
   351  	p.Log().Debug("Fetching batch of receipts", "count", len(hashes))
   352  	return p2p.Send(p.rw, GetReceiptsMsg, hashes)
   353  }
   354  
   355  // Handshake executes the eth protocol handshake, negotiating version number,
   356  // network IDs, difficulties, head and genesis blocks.
   357  func (p *peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis common.Hash, forkID forkid.ID, forkFilter forkid.Filter) error {
   358  	// Send out own handshake in a new thread
   359  	errc := make(chan error, 2)
   360  
   361  	var (
   362  		status63 statusData63 // safe to read after two values have been received from errc
   363  		status   statusData   // safe to read after two values have been received from errc
   364  	)
   365  	go func() {
   366  		switch {
   367  		case p.version == eth63:
   368  			errc <- p2p.Send(p.rw, StatusMsg, &statusData63{
   369  				ProtocolVersion: uint32(p.version),
   370  				NetworkId:       network,
   371  				TD:              td,
   372  				CurrentBlock:    head,
   373  				GenesisBlock:    genesis,
   374  			})
   375  		case p.version == eth64:
   376  			errc <- p2p.Send(p.rw, StatusMsg, &statusData{
   377  				ProtocolVersion: uint32(p.version),
   378  				NetworkID:       network,
   379  				TD:              td,
   380  				Head:            head,
   381  				Genesis:         genesis,
   382  				ForkID:          forkID,
   383  			})
   384  		default:
   385  			panic(fmt.Sprintf("unsupported eth protocol version: %d", p.version))
   386  		}
   387  	}()
   388  	go func() {
   389  		switch {
   390  		case p.version == eth63:
   391  			errc <- p.readStatusLegacy(network, &status63, genesis)
   392  		case p.version == eth64:
   393  			errc <- p.readStatus(network, &status, genesis, forkFilter)
   394  		default:
   395  			panic(fmt.Sprintf("unsupported eth protocol version: %d", p.version))
   396  		}
   397  	}()
   398  	timeout := time.NewTimer(handshakeTimeout)
   399  	defer timeout.Stop()
   400  	for i := 0; i < 2; i++ {
   401  		select {
   402  		case err := <-errc:
   403  			if err != nil {
   404  				return err
   405  			}
   406  		case <-timeout.C:
   407  			return p2p.DiscReadTimeout
   408  		}
   409  	}
   410  	switch {
   411  	case p.version == eth63:
   412  		p.td, p.head = status63.TD, status63.CurrentBlock
   413  	case p.version == eth64:
   414  		p.td, p.head = status.TD, status.Head
   415  	default:
   416  		panic(fmt.Sprintf("unsupported eth protocol version: %d", p.version))
   417  	}
   418  	return nil
   419  }
   420  
   421  func (p *peer) readStatusLegacy(network uint64, status *statusData63, genesis common.Hash) error {
   422  	msg, err := p.rw.ReadMsg()
   423  	if err != nil {
   424  		return err
   425  	}
   426  	if msg.Code != StatusMsg {
   427  		return errResp(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg)
   428  	}
   429  	if msg.Size > protocolMaxMsgSize {
   430  		return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, protocolMaxMsgSize)
   431  	}
   432  	// Decode the handshake and make sure everything matches
   433  	if err := msg.Decode(&status); err != nil {
   434  		return errResp(ErrDecode, "msg %v: %v", msg, err)
   435  	}
   436  	if status.GenesisBlock != genesis {
   437  		return errResp(ErrGenesisMismatch, "%x (!= %x)", status.GenesisBlock[:8], genesis[:8])
   438  	}
   439  	if status.NetworkId != network {
   440  		return errResp(ErrNetworkIDMismatch, "%d (!= %d)", status.NetworkId, network)
   441  	}
   442  	if int(status.ProtocolVersion) != p.version {
   443  		return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version)
   444  	}
   445  	return nil
   446  }
   447  
   448  func (p *peer) readStatus(network uint64, status *statusData, genesis common.Hash, forkFilter forkid.Filter) error {
   449  	msg, err := p.rw.ReadMsg()
   450  	if err != nil {
   451  		return err
   452  	}
   453  	if msg.Code != StatusMsg {
   454  		return errResp(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg)
   455  	}
   456  	if msg.Size > protocolMaxMsgSize {
   457  		return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, protocolMaxMsgSize)
   458  	}
   459  	// Decode the handshake and make sure everything matches
   460  	if err := msg.Decode(&status); err != nil {
   461  		return errResp(ErrDecode, "msg %v: %v", msg, err)
   462  	}
   463  	if status.NetworkID != network {
   464  		return errResp(ErrNetworkIDMismatch, "%d (!= %d)", status.NetworkID, network)
   465  	}
   466  	if int(status.ProtocolVersion) != p.version {
   467  		return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version)
   468  	}
   469  	if status.Genesis != genesis {
   470  		return errResp(ErrGenesisMismatch, "%x (!= %x)", status.Genesis, genesis)
   471  	}
   472  	if err := forkFilter(status.ForkID); err != nil {
   473  		return errResp(ErrForkIDRejected, "%v", err)
   474  	}
   475  	return nil
   476  }
   477  
   478  // String implements fmt.Stringer.
   479  func (p *peer) String() string {
   480  	return fmt.Sprintf("Peer %s [%s]", p.id,
   481  		fmt.Sprintf("eth/%2d", p.version),
   482  	)
   483  }
   484  
   485  // peerSet represents the collection of active peers currently participating in
   486  // the Ethereum sub-protocol.
   487  type peerSet struct {
   488  	peers  map[string]*peer
   489  	lock   sync.RWMutex
   490  	closed bool
   491  }
   492  
   493  // newPeerSet creates a new peer set to track the active participants.
   494  func newPeerSet() *peerSet {
   495  	return &peerSet{
   496  		peers: make(map[string]*peer),
   497  	}
   498  }
   499  
   500  // Register injects a new peer into the working set, or returns an error if the
   501  // peer is already known. If a new peer it registered, its broadcast loop is also
   502  // started.
   503  func (ps *peerSet) Register(p *peer) error {
   504  	ps.lock.Lock()
   505  	defer ps.lock.Unlock()
   506  
   507  	if ps.closed {
   508  		return errClosed
   509  	}
   510  	if _, ok := ps.peers[p.id]; ok {
   511  		return errAlreadyRegistered
   512  	}
   513  	ps.peers[p.id] = p
   514  	go p.broadcast()
   515  
   516  	return nil
   517  }
   518  
   519  // Unregister removes a remote peer from the active set, disabling any further
   520  // actions to/from that particular entity.
   521  func (ps *peerSet) Unregister(id string) error {
   522  	ps.lock.Lock()
   523  	defer ps.lock.Unlock()
   524  
   525  	p, ok := ps.peers[id]
   526  	if !ok {
   527  		return errNotRegistered
   528  	}
   529  	delete(ps.peers, id)
   530  	p.close()
   531  
   532  	return nil
   533  }
   534  
   535  // Peer retrieves the registered peer with the given id.
   536  func (ps *peerSet) Peer(id string) *peer {
   537  	ps.lock.RLock()
   538  	defer ps.lock.RUnlock()
   539  
   540  	return ps.peers[id]
   541  }
   542  
   543  // Len returns if the current number of peers in the set.
   544  func (ps *peerSet) Len() int {
   545  	ps.lock.RLock()
   546  	defer ps.lock.RUnlock()
   547  
   548  	return len(ps.peers)
   549  }
   550  
   551  // PeersWithoutBlock retrieves a list of peers that do not have a given block in
   552  // their set of known hashes.
   553  func (ps *peerSet) PeersWithoutBlock(hash common.Hash) []*peer {
   554  	ps.lock.RLock()
   555  	defer ps.lock.RUnlock()
   556  
   557  	list := make([]*peer, 0, len(ps.peers))
   558  	for _, p := range ps.peers {
   559  		if !p.knownBlocks.Contains(hash) {
   560  			list = append(list, p)
   561  		}
   562  	}
   563  	return list
   564  }
   565  
   566  // PeersWithoutTx retrieves a list of peers that do not have a given transaction
   567  // in their set of known hashes.
   568  func (ps *peerSet) PeersWithoutTx(hash common.Hash) []*peer {
   569  	ps.lock.RLock()
   570  	defer ps.lock.RUnlock()
   571  
   572  	list := make([]*peer, 0, len(ps.peers))
   573  	for _, p := range ps.peers {
   574  		if !p.knownTxs.Contains(hash) {
   575  			list = append(list, p)
   576  		}
   577  	}
   578  	return list
   579  }
   580  
   581  // BestPeer retrieves the known peer with the currently highest total difficulty.
   582  func (ps *peerSet) BestPeer() *peer {
   583  	ps.lock.RLock()
   584  	defer ps.lock.RUnlock()
   585  
   586  	var (
   587  		bestPeer *peer
   588  		bestTd   *big.Int
   589  	)
   590  	for _, p := range ps.peers {
   591  		if _, td := p.Head(); bestPeer == nil || td.Cmp(bestTd) > 0 {
   592  			bestPeer, bestTd = p, td
   593  		}
   594  	}
   595  	return bestPeer
   596  }
   597  
   598  // Close disconnects all peers.
   599  // No new peers can be registered after Close has returned.
   600  func (ps *peerSet) Close() {
   601  	ps.lock.Lock()
   602  	defer ps.lock.Unlock()
   603  
   604  	for _, p := range ps.peers {
   605  		p.Disconnect(p2p.DiscQuitting)
   606  	}
   607  	ps.closed = true
   608  }