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