github.com/sonm-io/go-ethereum@v1.8.18/les/peer.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  	"errors"
    22  	"fmt"
    23  	"math/big"
    24  	"sync"
    25  	"time"
    26  
    27  	"github.com/ethereum/go-ethereum/common"
    28  	"github.com/ethereum/go-ethereum/core/types"
    29  	"github.com/ethereum/go-ethereum/eth"
    30  	"github.com/ethereum/go-ethereum/les/flowcontrol"
    31  	"github.com/ethereum/go-ethereum/light"
    32  	"github.com/ethereum/go-ethereum/p2p"
    33  	"github.com/ethereum/go-ethereum/rlp"
    34  )
    35  
    36  var (
    37  	errClosed             = errors.New("peer set is closed")
    38  	errAlreadyRegistered  = errors.New("peer is already registered")
    39  	errNotRegistered      = errors.New("peer is not registered")
    40  	errInvalidHelpTrieReq = errors.New("invalid help trie request")
    41  )
    42  
    43  const maxResponseErrors = 50 // number of invalid responses tolerated (makes the protocol less brittle but still avoids spam)
    44  
    45  const (
    46  	announceTypeNone = iota
    47  	announceTypeSimple
    48  	announceTypeSigned
    49  )
    50  
    51  type peer struct {
    52  	*p2p.Peer
    53  
    54  	rw p2p.MsgReadWriter
    55  
    56  	version int    // Protocol version negotiated
    57  	network uint64 // Network ID being on
    58  
    59  	announceType, requestAnnounceType uint64
    60  
    61  	id string
    62  
    63  	headInfo *announceData
    64  	lock     sync.RWMutex
    65  
    66  	announceChn chan announceData
    67  	sendQueue   *execQueue
    68  
    69  	poolEntry      *poolEntry
    70  	hasBlock       func(common.Hash, uint64, bool) bool
    71  	responseErrors int
    72  
    73  	fcClient       *flowcontrol.ClientNode // nil if the peer is server only
    74  	fcServer       *flowcontrol.ServerNode // nil if the peer is client only
    75  	fcServerParams *flowcontrol.ServerParams
    76  	fcCosts        requestCostTable
    77  }
    78  
    79  func newPeer(version int, network uint64, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
    80  	id := p.ID()
    81  
    82  	return &peer{
    83  		Peer:        p,
    84  		rw:          rw,
    85  		version:     version,
    86  		network:     network,
    87  		id:          fmt.Sprintf("%x", id[:8]),
    88  		announceChn: make(chan announceData, 20),
    89  	}
    90  }
    91  
    92  func (p *peer) canQueue() bool {
    93  	return p.sendQueue.canQueue()
    94  }
    95  
    96  func (p *peer) queueSend(f func()) {
    97  	p.sendQueue.queue(f)
    98  }
    99  
   100  // Info gathers and returns a collection of metadata known about a peer.
   101  func (p *peer) Info() *eth.PeerInfo {
   102  	return &eth.PeerInfo{
   103  		Version:    p.version,
   104  		Difficulty: p.Td(),
   105  		Head:       fmt.Sprintf("%x", p.Head()),
   106  	}
   107  }
   108  
   109  // Head retrieves a copy of the current head (most recent) hash of the peer.
   110  func (p *peer) Head() (hash common.Hash) {
   111  	p.lock.RLock()
   112  	defer p.lock.RUnlock()
   113  
   114  	copy(hash[:], p.headInfo.Hash[:])
   115  	return hash
   116  }
   117  
   118  func (p *peer) HeadAndTd() (hash common.Hash, td *big.Int) {
   119  	p.lock.RLock()
   120  	defer p.lock.RUnlock()
   121  
   122  	copy(hash[:], p.headInfo.Hash[:])
   123  	return hash, p.headInfo.Td
   124  }
   125  
   126  func (p *peer) headBlockInfo() blockInfo {
   127  	p.lock.RLock()
   128  	defer p.lock.RUnlock()
   129  
   130  	return blockInfo{Hash: p.headInfo.Hash, Number: p.headInfo.Number, Td: p.headInfo.Td}
   131  }
   132  
   133  // Td retrieves the current total difficulty of a peer.
   134  func (p *peer) Td() *big.Int {
   135  	p.lock.RLock()
   136  	defer p.lock.RUnlock()
   137  
   138  	return new(big.Int).Set(p.headInfo.Td)
   139  }
   140  
   141  // waitBefore implements distPeer interface
   142  func (p *peer) waitBefore(maxCost uint64) (time.Duration, float64) {
   143  	return p.fcServer.CanSend(maxCost)
   144  }
   145  
   146  func sendRequest(w p2p.MsgWriter, msgcode, reqID, cost uint64, data interface{}) error {
   147  	type req struct {
   148  		ReqID uint64
   149  		Data  interface{}
   150  	}
   151  	return p2p.Send(w, msgcode, req{reqID, data})
   152  }
   153  
   154  func sendResponse(w p2p.MsgWriter, msgcode, reqID, bv uint64, data interface{}) error {
   155  	type resp struct {
   156  		ReqID, BV uint64
   157  		Data      interface{}
   158  	}
   159  	return p2p.Send(w, msgcode, resp{reqID, bv, data})
   160  }
   161  
   162  func (p *peer) GetRequestCost(msgcode uint64, amount int) uint64 {
   163  	p.lock.RLock()
   164  	defer p.lock.RUnlock()
   165  
   166  	cost := p.fcCosts[msgcode].baseCost + p.fcCosts[msgcode].reqCost*uint64(amount)
   167  	if cost > p.fcServerParams.BufLimit {
   168  		cost = p.fcServerParams.BufLimit
   169  	}
   170  	return cost
   171  }
   172  
   173  // HasBlock checks if the peer has a given block
   174  func (p *peer) HasBlock(hash common.Hash, number uint64, hasState bool) bool {
   175  	p.lock.RLock()
   176  	hasBlock := p.hasBlock
   177  	p.lock.RUnlock()
   178  	return hasBlock != nil && hasBlock(hash, number, hasState)
   179  }
   180  
   181  // SendAnnounce announces the availability of a number of blocks through
   182  // a hash notification.
   183  func (p *peer) SendAnnounce(request announceData) error {
   184  	return p2p.Send(p.rw, AnnounceMsg, request)
   185  }
   186  
   187  // SendBlockHeaders sends a batch of block headers to the remote peer.
   188  func (p *peer) SendBlockHeaders(reqID, bv uint64, headers []*types.Header) error {
   189  	return sendResponse(p.rw, BlockHeadersMsg, reqID, bv, headers)
   190  }
   191  
   192  // SendBlockBodiesRLP sends a batch of block contents to the remote peer from
   193  // an already RLP encoded format.
   194  func (p *peer) SendBlockBodiesRLP(reqID, bv uint64, bodies []rlp.RawValue) error {
   195  	return sendResponse(p.rw, BlockBodiesMsg, reqID, bv, bodies)
   196  }
   197  
   198  // SendCodeRLP sends a batch of arbitrary internal data, corresponding to the
   199  // hashes requested.
   200  func (p *peer) SendCode(reqID, bv uint64, data [][]byte) error {
   201  	return sendResponse(p.rw, CodeMsg, reqID, bv, data)
   202  }
   203  
   204  // SendReceiptsRLP sends a batch of transaction receipts, corresponding to the
   205  // ones requested from an already RLP encoded format.
   206  func (p *peer) SendReceiptsRLP(reqID, bv uint64, receipts []rlp.RawValue) error {
   207  	return sendResponse(p.rw, ReceiptsMsg, reqID, bv, receipts)
   208  }
   209  
   210  // SendProofs sends a batch of legacy LES/1 merkle proofs, corresponding to the ones requested.
   211  func (p *peer) SendProofs(reqID, bv uint64, proofs proofsData) error {
   212  	return sendResponse(p.rw, ProofsV1Msg, reqID, bv, proofs)
   213  }
   214  
   215  // SendProofsV2 sends a batch of merkle proofs, corresponding to the ones requested.
   216  func (p *peer) SendProofsV2(reqID, bv uint64, proofs light.NodeList) error {
   217  	return sendResponse(p.rw, ProofsV2Msg, reqID, bv, proofs)
   218  }
   219  
   220  // SendHeaderProofs sends a batch of legacy LES/1 header proofs, corresponding to the ones requested.
   221  func (p *peer) SendHeaderProofs(reqID, bv uint64, proofs []ChtResp) error {
   222  	return sendResponse(p.rw, HeaderProofsMsg, reqID, bv, proofs)
   223  }
   224  
   225  // SendHelperTrieProofs sends a batch of HelperTrie proofs, corresponding to the ones requested.
   226  func (p *peer) SendHelperTrieProofs(reqID, bv uint64, resp HelperTrieResps) error {
   227  	return sendResponse(p.rw, HelperTrieProofsMsg, reqID, bv, resp)
   228  }
   229  
   230  // SendTxStatus sends a batch of transaction status records, corresponding to the ones requested.
   231  func (p *peer) SendTxStatus(reqID, bv uint64, stats []txStatus) error {
   232  	return sendResponse(p.rw, TxStatusMsg, reqID, bv, stats)
   233  }
   234  
   235  // RequestHeadersByHash fetches a batch of blocks' headers corresponding to the
   236  // specified header query, based on the hash of an origin block.
   237  func (p *peer) RequestHeadersByHash(reqID, cost uint64, origin common.Hash, amount int, skip int, reverse bool) error {
   238  	p.Log().Debug("Fetching batch of headers", "count", amount, "fromhash", origin, "skip", skip, "reverse", reverse)
   239  	return sendRequest(p.rw, GetBlockHeadersMsg, reqID, cost, &getBlockHeadersData{Origin: hashOrNumber{Hash: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse})
   240  }
   241  
   242  // RequestHeadersByNumber fetches a batch of blocks' headers corresponding to the
   243  // specified header query, based on the number of an origin block.
   244  func (p *peer) RequestHeadersByNumber(reqID, cost, origin uint64, amount int, skip int, reverse bool) error {
   245  	p.Log().Debug("Fetching batch of headers", "count", amount, "fromnum", origin, "skip", skip, "reverse", reverse)
   246  	return sendRequest(p.rw, GetBlockHeadersMsg, reqID, cost, &getBlockHeadersData{Origin: hashOrNumber{Number: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse})
   247  }
   248  
   249  // RequestBodies fetches a batch of blocks' bodies corresponding to the hashes
   250  // specified.
   251  func (p *peer) RequestBodies(reqID, cost uint64, hashes []common.Hash) error {
   252  	p.Log().Debug("Fetching batch of block bodies", "count", len(hashes))
   253  	return sendRequest(p.rw, GetBlockBodiesMsg, reqID, cost, hashes)
   254  }
   255  
   256  // RequestCode fetches a batch of arbitrary data from a node's known state
   257  // data, corresponding to the specified hashes.
   258  func (p *peer) RequestCode(reqID, cost uint64, reqs []CodeReq) error {
   259  	p.Log().Debug("Fetching batch of codes", "count", len(reqs))
   260  	return sendRequest(p.rw, GetCodeMsg, reqID, cost, reqs)
   261  }
   262  
   263  // RequestReceipts fetches a batch of transaction receipts from a remote node.
   264  func (p *peer) RequestReceipts(reqID, cost uint64, hashes []common.Hash) error {
   265  	p.Log().Debug("Fetching batch of receipts", "count", len(hashes))
   266  	return sendRequest(p.rw, GetReceiptsMsg, reqID, cost, hashes)
   267  }
   268  
   269  // RequestProofs fetches a batch of merkle proofs from a remote node.
   270  func (p *peer) RequestProofs(reqID, cost uint64, reqs []ProofReq) error {
   271  	p.Log().Debug("Fetching batch of proofs", "count", len(reqs))
   272  	switch p.version {
   273  	case lpv1:
   274  		return sendRequest(p.rw, GetProofsV1Msg, reqID, cost, reqs)
   275  	case lpv2:
   276  		return sendRequest(p.rw, GetProofsV2Msg, reqID, cost, reqs)
   277  	default:
   278  		panic(nil)
   279  	}
   280  }
   281  
   282  // RequestHelperTrieProofs fetches a batch of HelperTrie merkle proofs from a remote node.
   283  func (p *peer) RequestHelperTrieProofs(reqID, cost uint64, data interface{}) error {
   284  	switch p.version {
   285  	case lpv1:
   286  		reqs, ok := data.([]ChtReq)
   287  		if !ok {
   288  			return errInvalidHelpTrieReq
   289  		}
   290  		p.Log().Debug("Fetching batch of header proofs", "count", len(reqs))
   291  		return sendRequest(p.rw, GetHeaderProofsMsg, reqID, cost, reqs)
   292  	case lpv2:
   293  		reqs, ok := data.([]HelperTrieReq)
   294  		if !ok {
   295  			return errInvalidHelpTrieReq
   296  		}
   297  		p.Log().Debug("Fetching batch of HelperTrie proofs", "count", len(reqs))
   298  		return sendRequest(p.rw, GetHelperTrieProofsMsg, reqID, cost, reqs)
   299  	default:
   300  		panic(nil)
   301  	}
   302  }
   303  
   304  // RequestTxStatus fetches a batch of transaction status records from a remote node.
   305  func (p *peer) RequestTxStatus(reqID, cost uint64, txHashes []common.Hash) error {
   306  	p.Log().Debug("Requesting transaction status", "count", len(txHashes))
   307  	return sendRequest(p.rw, GetTxStatusMsg, reqID, cost, txHashes)
   308  }
   309  
   310  // SendTxStatus sends a batch of transactions to be added to the remote transaction pool.
   311  func (p *peer) SendTxs(reqID, cost uint64, txs types.Transactions) error {
   312  	p.Log().Debug("Fetching batch of transactions", "count", len(txs))
   313  	switch p.version {
   314  	case lpv1:
   315  		return p2p.Send(p.rw, SendTxMsg, txs) // old message format does not include reqID
   316  	case lpv2:
   317  		return sendRequest(p.rw, SendTxV2Msg, reqID, cost, txs)
   318  	default:
   319  		panic(nil)
   320  	}
   321  }
   322  
   323  type keyValueEntry struct {
   324  	Key   string
   325  	Value rlp.RawValue
   326  }
   327  type keyValueList []keyValueEntry
   328  type keyValueMap map[string]rlp.RawValue
   329  
   330  func (l keyValueList) add(key string, val interface{}) keyValueList {
   331  	var entry keyValueEntry
   332  	entry.Key = key
   333  	if val == nil {
   334  		val = uint64(0)
   335  	}
   336  	enc, err := rlp.EncodeToBytes(val)
   337  	if err == nil {
   338  		entry.Value = enc
   339  	}
   340  	return append(l, entry)
   341  }
   342  
   343  func (l keyValueList) decode() keyValueMap {
   344  	m := make(keyValueMap)
   345  	for _, entry := range l {
   346  		m[entry.Key] = entry.Value
   347  	}
   348  	return m
   349  }
   350  
   351  func (m keyValueMap) get(key string, val interface{}) error {
   352  	enc, ok := m[key]
   353  	if !ok {
   354  		return errResp(ErrMissingKey, "%s", key)
   355  	}
   356  	if val == nil {
   357  		return nil
   358  	}
   359  	return rlp.DecodeBytes(enc, val)
   360  }
   361  
   362  func (p *peer) sendReceiveHandshake(sendList keyValueList) (keyValueList, error) {
   363  	// Send out own handshake in a new thread
   364  	errc := make(chan error, 1)
   365  	go func() {
   366  		errc <- p2p.Send(p.rw, StatusMsg, sendList)
   367  	}()
   368  	// In the mean time retrieve the remote status message
   369  	msg, err := p.rw.ReadMsg()
   370  	if err != nil {
   371  		return nil, err
   372  	}
   373  	if msg.Code != StatusMsg {
   374  		return nil, errResp(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg)
   375  	}
   376  	if msg.Size > ProtocolMaxMsgSize {
   377  		return nil, errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize)
   378  	}
   379  	// Decode the handshake
   380  	var recvList keyValueList
   381  	if err := msg.Decode(&recvList); err != nil {
   382  		return nil, errResp(ErrDecode, "msg %v: %v", msg, err)
   383  	}
   384  	if err := <-errc; err != nil {
   385  		return nil, err
   386  	}
   387  	return recvList, nil
   388  }
   389  
   390  // Handshake executes the les protocol handshake, negotiating version number,
   391  // network IDs, difficulties, head and genesis blocks.
   392  func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis common.Hash, server *LesServer) error {
   393  	p.lock.Lock()
   394  	defer p.lock.Unlock()
   395  
   396  	var send keyValueList
   397  	send = send.add("protocolVersion", uint64(p.version))
   398  	send = send.add("networkId", p.network)
   399  	send = send.add("headTd", td)
   400  	send = send.add("headHash", head)
   401  	send = send.add("headNum", headNum)
   402  	send = send.add("genesisHash", genesis)
   403  	if server != nil {
   404  		send = send.add("serveHeaders", nil)
   405  		send = send.add("serveChainSince", uint64(0))
   406  		send = send.add("serveStateSince", uint64(0))
   407  		send = send.add("txRelay", nil)
   408  		send = send.add("flowControl/BL", server.defParams.BufLimit)
   409  		send = send.add("flowControl/MRR", server.defParams.MinRecharge)
   410  		list := server.fcCostStats.getCurrentList()
   411  		send = send.add("flowControl/MRC", list)
   412  		p.fcCosts = list.decode()
   413  	} else {
   414  		p.requestAnnounceType = announceTypeSimple // set to default until "very light" client mode is implemented
   415  		send = send.add("announceType", p.requestAnnounceType)
   416  	}
   417  	recvList, err := p.sendReceiveHandshake(send)
   418  	if err != nil {
   419  		return err
   420  	}
   421  	recv := recvList.decode()
   422  
   423  	var rGenesis, rHash common.Hash
   424  	var rVersion, rNetwork, rNum uint64
   425  	var rTd *big.Int
   426  
   427  	if err := recv.get("protocolVersion", &rVersion); err != nil {
   428  		return err
   429  	}
   430  	if err := recv.get("networkId", &rNetwork); err != nil {
   431  		return err
   432  	}
   433  	if err := recv.get("headTd", &rTd); err != nil {
   434  		return err
   435  	}
   436  	if err := recv.get("headHash", &rHash); err != nil {
   437  		return err
   438  	}
   439  	if err := recv.get("headNum", &rNum); err != nil {
   440  		return err
   441  	}
   442  	if err := recv.get("genesisHash", &rGenesis); err != nil {
   443  		return err
   444  	}
   445  
   446  	if rGenesis != genesis {
   447  		return errResp(ErrGenesisBlockMismatch, "%x (!= %x)", rGenesis[:8], genesis[:8])
   448  	}
   449  	if rNetwork != p.network {
   450  		return errResp(ErrNetworkIdMismatch, "%d (!= %d)", rNetwork, p.network)
   451  	}
   452  	if int(rVersion) != p.version {
   453  		return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", rVersion, p.version)
   454  	}
   455  	if server != nil {
   456  		// until we have a proper peer connectivity API, allow LES connection to other servers
   457  		/*if recv.get("serveStateSince", nil) == nil {
   458  			return errResp(ErrUselessPeer, "wanted client, got server")
   459  		}*/
   460  		if recv.get("announceType", &p.announceType) != nil {
   461  			p.announceType = announceTypeSimple
   462  		}
   463  		p.fcClient = flowcontrol.NewClientNode(server.fcManager, server.defParams)
   464  	} else {
   465  		if recv.get("serveChainSince", nil) != nil {
   466  			return errResp(ErrUselessPeer, "peer cannot serve chain")
   467  		}
   468  		if recv.get("serveStateSince", nil) != nil {
   469  			return errResp(ErrUselessPeer, "peer cannot serve state")
   470  		}
   471  		if recv.get("txRelay", nil) != nil {
   472  			return errResp(ErrUselessPeer, "peer cannot relay transactions")
   473  		}
   474  		params := &flowcontrol.ServerParams{}
   475  		if err := recv.get("flowControl/BL", &params.BufLimit); err != nil {
   476  			return err
   477  		}
   478  		if err := recv.get("flowControl/MRR", &params.MinRecharge); err != nil {
   479  			return err
   480  		}
   481  		var MRC RequestCostList
   482  		if err := recv.get("flowControl/MRC", &MRC); err != nil {
   483  			return err
   484  		}
   485  		p.fcServerParams = params
   486  		p.fcServer = flowcontrol.NewServerNode(params)
   487  		p.fcCosts = MRC.decode()
   488  	}
   489  
   490  	p.headInfo = &announceData{Td: rTd, Hash: rHash, Number: rNum}
   491  	return nil
   492  }
   493  
   494  // String implements fmt.Stringer.
   495  func (p *peer) String() string {
   496  	return fmt.Sprintf("Peer %s [%s]", p.id,
   497  		fmt.Sprintf("les/%d", p.version),
   498  	)
   499  }
   500  
   501  // peerSetNotify is a callback interface to notify services about added or
   502  // removed peers
   503  type peerSetNotify interface {
   504  	registerPeer(*peer)
   505  	unregisterPeer(*peer)
   506  }
   507  
   508  // peerSet represents the collection of active peers currently participating in
   509  // the Light Ethereum sub-protocol.
   510  type peerSet struct {
   511  	peers      map[string]*peer
   512  	lock       sync.RWMutex
   513  	notifyList []peerSetNotify
   514  	closed     bool
   515  }
   516  
   517  // newPeerSet creates a new peer set to track the active participants.
   518  func newPeerSet() *peerSet {
   519  	return &peerSet{
   520  		peers: make(map[string]*peer),
   521  	}
   522  }
   523  
   524  // notify adds a service to be notified about added or removed peers
   525  func (ps *peerSet) notify(n peerSetNotify) {
   526  	ps.lock.Lock()
   527  	ps.notifyList = append(ps.notifyList, n)
   528  	peers := make([]*peer, 0, len(ps.peers))
   529  	for _, p := range ps.peers {
   530  		peers = append(peers, p)
   531  	}
   532  	ps.lock.Unlock()
   533  
   534  	for _, p := range peers {
   535  		n.registerPeer(p)
   536  	}
   537  }
   538  
   539  // Register injects a new peer into the working set, or returns an error if the
   540  // peer is already known.
   541  func (ps *peerSet) Register(p *peer) error {
   542  	ps.lock.Lock()
   543  	if ps.closed {
   544  		ps.lock.Unlock()
   545  		return errClosed
   546  	}
   547  	if _, ok := ps.peers[p.id]; ok {
   548  		ps.lock.Unlock()
   549  		return errAlreadyRegistered
   550  	}
   551  	ps.peers[p.id] = p
   552  	p.sendQueue = newExecQueue(100)
   553  	peers := make([]peerSetNotify, len(ps.notifyList))
   554  	copy(peers, ps.notifyList)
   555  	ps.lock.Unlock()
   556  
   557  	for _, n := range peers {
   558  		n.registerPeer(p)
   559  	}
   560  	return nil
   561  }
   562  
   563  // Unregister removes a remote peer from the active set, disabling any further
   564  // actions to/from that particular entity. It also initiates disconnection at the networking layer.
   565  func (ps *peerSet) Unregister(id string) error {
   566  	ps.lock.Lock()
   567  	if p, ok := ps.peers[id]; !ok {
   568  		ps.lock.Unlock()
   569  		return errNotRegistered
   570  	} else {
   571  		delete(ps.peers, id)
   572  		peers := make([]peerSetNotify, len(ps.notifyList))
   573  		copy(peers, ps.notifyList)
   574  		ps.lock.Unlock()
   575  
   576  		for _, n := range peers {
   577  			n.unregisterPeer(p)
   578  		}
   579  		p.sendQueue.quit()
   580  		p.Peer.Disconnect(p2p.DiscUselessPeer)
   581  		return nil
   582  	}
   583  }
   584  
   585  // AllPeerIDs returns a list of all registered peer IDs
   586  func (ps *peerSet) AllPeerIDs() []string {
   587  	ps.lock.RLock()
   588  	defer ps.lock.RUnlock()
   589  
   590  	res := make([]string, len(ps.peers))
   591  	idx := 0
   592  	for id := range ps.peers {
   593  		res[idx] = id
   594  		idx++
   595  	}
   596  	return res
   597  }
   598  
   599  // Peer retrieves the registered peer with the given id.
   600  func (ps *peerSet) Peer(id string) *peer {
   601  	ps.lock.RLock()
   602  	defer ps.lock.RUnlock()
   603  
   604  	return ps.peers[id]
   605  }
   606  
   607  // Len returns if the current number of peers in the set.
   608  func (ps *peerSet) Len() int {
   609  	ps.lock.RLock()
   610  	defer ps.lock.RUnlock()
   611  
   612  	return len(ps.peers)
   613  }
   614  
   615  // BestPeer retrieves the known peer with the currently highest total difficulty.
   616  func (ps *peerSet) BestPeer() *peer {
   617  	ps.lock.RLock()
   618  	defer ps.lock.RUnlock()
   619  
   620  	var (
   621  		bestPeer *peer
   622  		bestTd   *big.Int
   623  	)
   624  	for _, p := range ps.peers {
   625  		if td := p.Td(); bestPeer == nil || td.Cmp(bestTd) > 0 {
   626  			bestPeer, bestTd = p, td
   627  		}
   628  	}
   629  	return bestPeer
   630  }
   631  
   632  // AllPeers returns all peers in a list
   633  func (ps *peerSet) AllPeers() []*peer {
   634  	ps.lock.RLock()
   635  	defer ps.lock.RUnlock()
   636  
   637  	list := make([]*peer, len(ps.peers))
   638  	i := 0
   639  	for _, peer := range ps.peers {
   640  		list[i] = peer
   641  		i++
   642  	}
   643  	return list
   644  }
   645  
   646  // Close disconnects all peers.
   647  // No new peers can be registered after Close has returned.
   648  func (ps *peerSet) Close() {
   649  	ps.lock.Lock()
   650  	defer ps.lock.Unlock()
   651  
   652  	for _, p := range ps.peers {
   653  		p.Disconnect(p2p.DiscQuitting)
   654  	}
   655  	ps.closed = true
   656  }