github.com/phillinzzz/newBsc@v1.1.6/p2p/discover/table.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 discover implements the Node Discovery Protocol.
    18  //
    19  // The Node Discovery protocol provides a way to find RLPx nodes that
    20  // can be connected to. It uses a Kademlia-like protocol to maintain a
    21  // distributed database of the IDs and endpoints of all listening
    22  // nodes.
    23  package discover
    24  
    25  import (
    26  	crand "crypto/rand"
    27  	"encoding/binary"
    28  	"fmt"
    29  	mrand "math/rand"
    30  	"net"
    31  	"sort"
    32  	"sync"
    33  	"time"
    34  
    35  	"github.com/phillinzzz/newBsc/common"
    36  	"github.com/phillinzzz/newBsc/common/gopool"
    37  	"github.com/phillinzzz/newBsc/log"
    38  	"github.com/phillinzzz/newBsc/p2p/enode"
    39  	"github.com/phillinzzz/newBsc/p2p/netutil"
    40  )
    41  
    42  const (
    43  	alpha           = 3  // Kademlia concurrency factor
    44  	bucketSize      = 16 // Kademlia bucket size
    45  	maxReplacements = 10 // Size of per-bucket replacement list
    46  
    47  	// We keep buckets for the upper 1/15 of distances because
    48  	// it's very unlikely we'll ever encounter a node that's closer.
    49  	hashBits          = len(common.Hash{}) * 8
    50  	nBuckets          = hashBits / 15       // Number of buckets
    51  	bucketMinDistance = hashBits - nBuckets // Log distance of closest bucket
    52  
    53  	// IP address limits.
    54  	bucketIPLimit, bucketSubnet = 2, 24 // at most 2 addresses from the same /24
    55  	tableIPLimit, tableSubnet   = 10, 24
    56  
    57  	refreshInterval    = 30 * time.Minute
    58  	revalidateInterval = 10 * time.Second
    59  	copyNodesInterval  = 30 * time.Second
    60  	seedMinTableTime   = 5 * time.Minute
    61  	seedCount          = 30
    62  	seedMaxAge         = 5 * 24 * time.Hour
    63  )
    64  
    65  // Table is the 'node table', a Kademlia-like index of neighbor nodes. The table keeps
    66  // itself up-to-date by verifying the liveness of neighbors and requesting their node
    67  // records when announcements of a new record version are received.
    68  type Table struct {
    69  	mutex   sync.Mutex        // protects buckets, bucket content, nursery, rand
    70  	buckets [nBuckets]*bucket // index of known nodes by distance
    71  	nursery []*node           // bootstrap nodes
    72  	rand    *mrand.Rand       // source of randomness, periodically reseeded
    73  	ips     netutil.DistinctNetSet
    74  
    75  	log        log.Logger
    76  	db         *enode.DB // database of known nodes
    77  	net        transport
    78  	refreshReq chan chan struct{}
    79  	initDone   chan struct{}
    80  	closeReq   chan struct{}
    81  	closed     chan struct{}
    82  
    83  	nodeAddedHook func(*node) // for testing
    84  }
    85  
    86  // transport is implemented by the UDP transports.
    87  type transport interface {
    88  	Self() *enode.Node
    89  	RequestENR(*enode.Node) (*enode.Node, error)
    90  	lookupRandom() []*enode.Node
    91  	lookupSelf() []*enode.Node
    92  	ping(*enode.Node) (seq uint64, err error)
    93  }
    94  
    95  // bucket contains nodes, ordered by their last activity. the entry
    96  // that was most recently active is the first element in entries.
    97  type bucket struct {
    98  	entries      []*node // live entries, sorted by time of last contact
    99  	replacements []*node // recently seen nodes to be used if revalidation fails
   100  	ips          netutil.DistinctNetSet
   101  }
   102  
   103  func newTable(t transport, db *enode.DB, bootnodes []*enode.Node, log log.Logger) (*Table, error) {
   104  	tab := &Table{
   105  		net:        t,
   106  		db:         db,
   107  		refreshReq: make(chan chan struct{}),
   108  		initDone:   make(chan struct{}),
   109  		closeReq:   make(chan struct{}),
   110  		closed:     make(chan struct{}),
   111  		rand:       mrand.New(mrand.NewSource(0)),
   112  		ips:        netutil.DistinctNetSet{Subnet: tableSubnet, Limit: tableIPLimit},
   113  		log:        log,
   114  	}
   115  	if err := tab.setFallbackNodes(bootnodes); err != nil {
   116  		return nil, err
   117  	}
   118  	for i := range tab.buckets {
   119  		tab.buckets[i] = &bucket{
   120  			ips: netutil.DistinctNetSet{Subnet: bucketSubnet, Limit: bucketIPLimit},
   121  		}
   122  	}
   123  	tab.seedRand()
   124  	tab.loadSeedNodes()
   125  
   126  	return tab, nil
   127  }
   128  
   129  func (tab *Table) self() *enode.Node {
   130  	return tab.net.Self()
   131  }
   132  
   133  func (tab *Table) seedRand() {
   134  	var b [8]byte
   135  	crand.Read(b[:])
   136  
   137  	tab.mutex.Lock()
   138  	tab.rand.Seed(int64(binary.BigEndian.Uint64(b[:])))
   139  	tab.mutex.Unlock()
   140  }
   141  
   142  // ReadRandomNodes fills the given slice with random nodes from the table. The results
   143  // are guaranteed to be unique for a single invocation, no node will appear twice.
   144  func (tab *Table) ReadRandomNodes(buf []*enode.Node) (n int) {
   145  	if !tab.isInitDone() {
   146  		return 0
   147  	}
   148  	tab.mutex.Lock()
   149  	defer tab.mutex.Unlock()
   150  
   151  	var nodes []*enode.Node
   152  	for _, b := range &tab.buckets {
   153  		for _, n := range b.entries {
   154  			nodes = append(nodes, unwrapNode(n))
   155  		}
   156  	}
   157  	// Shuffle.
   158  	for i := 0; i < len(nodes); i++ {
   159  		j := tab.rand.Intn(len(nodes))
   160  		nodes[i], nodes[j] = nodes[j], nodes[i]
   161  	}
   162  	return copy(buf, nodes)
   163  }
   164  
   165  // getNode returns the node with the given ID or nil if it isn't in the table.
   166  func (tab *Table) getNode(id enode.ID) *enode.Node {
   167  	tab.mutex.Lock()
   168  	defer tab.mutex.Unlock()
   169  
   170  	b := tab.bucket(id)
   171  	for _, e := range b.entries {
   172  		if e.ID() == id {
   173  			return unwrapNode(e)
   174  		}
   175  	}
   176  	return nil
   177  }
   178  
   179  // close terminates the network listener and flushes the node database.
   180  func (tab *Table) close() {
   181  	close(tab.closeReq)
   182  	<-tab.closed
   183  }
   184  
   185  // setFallbackNodes sets the initial points of contact. These nodes
   186  // are used to connect to the network if the table is empty and there
   187  // are no known nodes in the database.
   188  func (tab *Table) setFallbackNodes(nodes []*enode.Node) error {
   189  	for _, n := range nodes {
   190  		if err := n.ValidateComplete(); err != nil {
   191  			return fmt.Errorf("bad bootstrap node %q: %v", n, err)
   192  		}
   193  	}
   194  	tab.nursery = wrapNodes(nodes)
   195  	return nil
   196  }
   197  
   198  // isInitDone returns whether the table's initial seeding procedure has completed.
   199  func (tab *Table) isInitDone() bool {
   200  	select {
   201  	case <-tab.initDone:
   202  		return true
   203  	default:
   204  		return false
   205  	}
   206  }
   207  
   208  func (tab *Table) refresh() <-chan struct{} {
   209  	done := make(chan struct{})
   210  	select {
   211  	case tab.refreshReq <- done:
   212  	case <-tab.closeReq:
   213  		close(done)
   214  	}
   215  	return done
   216  }
   217  
   218  // loop schedules runs of doRefresh, doRevalidate and copyLiveNodes.
   219  func (tab *Table) loop() {
   220  	var (
   221  		revalidate     = time.NewTimer(tab.nextRevalidateTime())
   222  		refresh        = time.NewTicker(refreshInterval)
   223  		copyNodes      = time.NewTicker(copyNodesInterval)
   224  		refreshDone    = make(chan struct{})           // where doRefresh reports completion
   225  		revalidateDone chan struct{}                   // where doRevalidate reports completion
   226  		waiting        = []chan struct{}{tab.initDone} // holds waiting callers while doRefresh runs
   227  	)
   228  	defer refresh.Stop()
   229  	defer revalidate.Stop()
   230  	defer copyNodes.Stop()
   231  
   232  	// Start initial refresh.
   233  	gopool.Submit(func() {
   234  		tab.doRefresh(refreshDone)
   235  	})
   236  loop:
   237  	for {
   238  		select {
   239  		case <-refresh.C:
   240  			tab.seedRand()
   241  			if refreshDone == nil {
   242  				refreshDone = make(chan struct{})
   243  				gopool.Submit(func() {
   244  					tab.doRefresh(refreshDone)
   245  				})
   246  			}
   247  		case req := <-tab.refreshReq:
   248  			waiting = append(waiting, req)
   249  			if refreshDone == nil {
   250  				refreshDone = make(chan struct{})
   251  				gopool.Submit(
   252  					func() {
   253  						tab.doRefresh(refreshDone)
   254  					})
   255  			}
   256  		case <-refreshDone:
   257  			for _, ch := range waiting {
   258  				close(ch)
   259  			}
   260  			waiting, refreshDone = nil, nil
   261  		case <-revalidate.C:
   262  			revalidateDone = make(chan struct{})
   263  			gopool.Submit(func() {
   264  				tab.doRevalidate(revalidateDone)
   265  			})
   266  		case <-revalidateDone:
   267  			revalidate.Reset(tab.nextRevalidateTime())
   268  			revalidateDone = nil
   269  		case <-copyNodes.C:
   270  			gopool.Submit(func() {
   271  				tab.copyLiveNodes()
   272  			})
   273  
   274  		case <-tab.closeReq:
   275  			break loop
   276  		}
   277  	}
   278  
   279  	if refreshDone != nil {
   280  		<-refreshDone
   281  	}
   282  	for _, ch := range waiting {
   283  		close(ch)
   284  	}
   285  	if revalidateDone != nil {
   286  		<-revalidateDone
   287  	}
   288  	close(tab.closed)
   289  }
   290  
   291  // doRefresh performs a lookup for a random target to keep buckets full. seed nodes are
   292  // inserted if the table is empty (initial bootstrap or discarded faulty peers).
   293  func (tab *Table) doRefresh(done chan struct{}) {
   294  	defer close(done)
   295  
   296  	// Load nodes from the database and insert
   297  	// them. This should yield a few previously seen nodes that are
   298  	// (hopefully) still alive.
   299  	tab.loadSeedNodes()
   300  
   301  	// Run self lookup to discover new neighbor nodes.
   302  	tab.net.lookupSelf()
   303  
   304  	// The Kademlia paper specifies that the bucket refresh should
   305  	// perform a lookup in the least recently used bucket. We cannot
   306  	// adhere to this because the findnode target is a 512bit value
   307  	// (not hash-sized) and it is not easily possible to generate a
   308  	// sha3 preimage that falls into a chosen bucket.
   309  	// We perform a few lookups with a random target instead.
   310  	for i := 0; i < 3; i++ {
   311  		tab.net.lookupRandom()
   312  	}
   313  }
   314  
   315  func (tab *Table) loadSeedNodes() {
   316  	seeds := wrapNodes(tab.db.QuerySeeds(seedCount, seedMaxAge))
   317  	seeds = append(seeds, tab.nursery...)
   318  	for i := range seeds {
   319  		seed := seeds[i]
   320  		age := log.Lazy{Fn: func() interface{} { return time.Since(tab.db.LastPongReceived(seed.ID(), seed.IP())) }}
   321  		tab.log.Trace("Found seed node in database", "id", seed.ID(), "addr", seed.addr(), "age", age)
   322  		tab.addSeenNode(seed)
   323  	}
   324  }
   325  
   326  // doRevalidate checks that the last node in a random bucket is still live and replaces or
   327  // deletes the node if it isn't.
   328  func (tab *Table) doRevalidate(done chan<- struct{}) {
   329  	defer func() { done <- struct{}{} }()
   330  
   331  	last, bi := tab.nodeToRevalidate()
   332  	if last == nil {
   333  		// No non-empty bucket found.
   334  		return
   335  	}
   336  
   337  	// Ping the selected node and wait for a pong.
   338  	remoteSeq, err := tab.net.ping(unwrapNode(last))
   339  
   340  	// Also fetch record if the node replied and returned a higher sequence number.
   341  	if last.Seq() < remoteSeq {
   342  		n, err := tab.net.RequestENR(unwrapNode(last))
   343  		if err != nil {
   344  			tab.log.Debug("ENR request failed", "id", last.ID(), "addr", last.addr(), "err", err)
   345  		} else {
   346  			last = &node{Node: *n, addedAt: last.addedAt, livenessChecks: last.livenessChecks}
   347  		}
   348  	}
   349  
   350  	tab.mutex.Lock()
   351  	defer tab.mutex.Unlock()
   352  	b := tab.buckets[bi]
   353  	if err == nil {
   354  		// The node responded, move it to the front.
   355  		last.livenessChecks++
   356  		tab.log.Debug("Revalidated node", "b", bi, "id", last.ID(), "checks", last.livenessChecks)
   357  		tab.bumpInBucket(b, last)
   358  		return
   359  	}
   360  	// No reply received, pick a replacement or delete the node if there aren't
   361  	// any replacements.
   362  	if r := tab.replace(b, last); r != nil {
   363  		tab.log.Debug("Replaced dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks, "r", r.ID(), "rip", r.IP())
   364  	} else {
   365  		tab.log.Debug("Removed dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks)
   366  	}
   367  }
   368  
   369  // nodeToRevalidate returns the last node in a random, non-empty bucket.
   370  func (tab *Table) nodeToRevalidate() (n *node, bi int) {
   371  	tab.mutex.Lock()
   372  	defer tab.mutex.Unlock()
   373  
   374  	for _, bi = range tab.rand.Perm(len(tab.buckets)) {
   375  		b := tab.buckets[bi]
   376  		if len(b.entries) > 0 {
   377  			last := b.entries[len(b.entries)-1]
   378  			return last, bi
   379  		}
   380  	}
   381  	return nil, 0
   382  }
   383  
   384  func (tab *Table) nextRevalidateTime() time.Duration {
   385  	tab.mutex.Lock()
   386  	defer tab.mutex.Unlock()
   387  
   388  	return time.Duration(tab.rand.Int63n(int64(revalidateInterval)))
   389  }
   390  
   391  // copyLiveNodes adds nodes from the table to the database if they have been in the table
   392  // longer than seedMinTableTime.
   393  func (tab *Table) copyLiveNodes() {
   394  	tab.mutex.Lock()
   395  	defer tab.mutex.Unlock()
   396  
   397  	now := time.Now()
   398  	for _, b := range &tab.buckets {
   399  		for _, n := range b.entries {
   400  			if n.livenessChecks > 0 && now.Sub(n.addedAt) >= seedMinTableTime {
   401  				tab.db.UpdateNode(unwrapNode(n))
   402  			}
   403  		}
   404  	}
   405  }
   406  
   407  // findnodeByID returns the n nodes in the table that are closest to the given id.
   408  // This is used by the FINDNODE/v4 handler.
   409  //
   410  // The preferLive parameter says whether the caller wants liveness-checked results. If
   411  // preferLive is true and the table contains any verified nodes, the result will not
   412  // contain unverified nodes. However, if there are no verified nodes at all, the result
   413  // will contain unverified nodes.
   414  func (tab *Table) findnodeByID(target enode.ID, nresults int, preferLive bool) *nodesByDistance {
   415  	tab.mutex.Lock()
   416  	defer tab.mutex.Unlock()
   417  
   418  	// Scan all buckets. There might be a better way to do this, but there aren't that many
   419  	// buckets, so this solution should be fine. The worst-case complexity of this loop
   420  	// is O(tab.len() * nresults).
   421  	nodes := &nodesByDistance{target: target}
   422  	liveNodes := &nodesByDistance{target: target}
   423  	for _, b := range &tab.buckets {
   424  		for _, n := range b.entries {
   425  			nodes.push(n, nresults)
   426  			if preferLive && n.livenessChecks > 0 {
   427  				liveNodes.push(n, nresults)
   428  			}
   429  		}
   430  	}
   431  
   432  	if preferLive && len(liveNodes.entries) > 0 {
   433  		return liveNodes
   434  	}
   435  	return nodes
   436  }
   437  
   438  // len returns the number of nodes in the table.
   439  func (tab *Table) len() (n int) {
   440  	tab.mutex.Lock()
   441  	defer tab.mutex.Unlock()
   442  
   443  	for _, b := range &tab.buckets {
   444  		n += len(b.entries)
   445  	}
   446  	return n
   447  }
   448  
   449  // bucketLen returns the number of nodes in the bucket for the given ID.
   450  func (tab *Table) bucketLen(id enode.ID) int {
   451  	tab.mutex.Lock()
   452  	defer tab.mutex.Unlock()
   453  
   454  	return len(tab.bucket(id).entries)
   455  }
   456  
   457  // bucket returns the bucket for the given node ID hash.
   458  func (tab *Table) bucket(id enode.ID) *bucket {
   459  	d := enode.LogDist(tab.self().ID(), id)
   460  	return tab.bucketAtDistance(d)
   461  }
   462  
   463  func (tab *Table) bucketAtDistance(d int) *bucket {
   464  	if d <= bucketMinDistance {
   465  		return tab.buckets[0]
   466  	}
   467  	return tab.buckets[d-bucketMinDistance-1]
   468  }
   469  
   470  // addSeenNode adds a node which may or may not be live to the end of a bucket. If the
   471  // bucket has space available, adding the node succeeds immediately. Otherwise, the node is
   472  // added to the replacements list.
   473  //
   474  // The caller must not hold tab.mutex.
   475  func (tab *Table) addSeenNode(n *node) {
   476  	if n.ID() == tab.self().ID() {
   477  		return
   478  	}
   479  
   480  	tab.mutex.Lock()
   481  	defer tab.mutex.Unlock()
   482  	b := tab.bucket(n.ID())
   483  	if contains(b.entries, n.ID()) {
   484  		// Already in bucket, don't add.
   485  		return
   486  	}
   487  	if len(b.entries) >= bucketSize {
   488  		// Bucket full, maybe add as replacement.
   489  		tab.addReplacement(b, n)
   490  		return
   491  	}
   492  	if !tab.addIP(b, n.IP()) {
   493  		// Can't add: IP limit reached.
   494  		return
   495  	}
   496  	// Add to end of bucket:
   497  	b.entries = append(b.entries, n)
   498  	b.replacements = deleteNode(b.replacements, n)
   499  	n.addedAt = time.Now()
   500  	if tab.nodeAddedHook != nil {
   501  		tab.nodeAddedHook(n)
   502  	}
   503  }
   504  
   505  // addVerifiedNode adds a node whose existence has been verified recently to the front of a
   506  // bucket. If the node is already in the bucket, it is moved to the front. If the bucket
   507  // has no space, the node is added to the replacements list.
   508  //
   509  // There is an additional safety measure: if the table is still initializing the node
   510  // is not added. This prevents an attack where the table could be filled by just sending
   511  // ping repeatedly.
   512  //
   513  // The caller must not hold tab.mutex.
   514  func (tab *Table) addVerifiedNode(n *node) {
   515  	if !tab.isInitDone() {
   516  		return
   517  	}
   518  	if n.ID() == tab.self().ID() {
   519  		return
   520  	}
   521  
   522  	tab.mutex.Lock()
   523  	defer tab.mutex.Unlock()
   524  	b := tab.bucket(n.ID())
   525  	if tab.bumpInBucket(b, n) {
   526  		// Already in bucket, moved to front.
   527  		return
   528  	}
   529  	if len(b.entries) >= bucketSize {
   530  		// Bucket full, maybe add as replacement.
   531  		tab.addReplacement(b, n)
   532  		return
   533  	}
   534  	if !tab.addIP(b, n.IP()) {
   535  		// Can't add: IP limit reached.
   536  		return
   537  	}
   538  	// Add to front of bucket.
   539  	b.entries, _ = pushNode(b.entries, n, bucketSize)
   540  	b.replacements = deleteNode(b.replacements, n)
   541  	n.addedAt = time.Now()
   542  	if tab.nodeAddedHook != nil {
   543  		tab.nodeAddedHook(n)
   544  	}
   545  }
   546  
   547  // delete removes an entry from the node table. It is used to evacuate dead nodes.
   548  func (tab *Table) delete(node *node) {
   549  	tab.mutex.Lock()
   550  	defer tab.mutex.Unlock()
   551  
   552  	tab.deleteInBucket(tab.bucket(node.ID()), node)
   553  }
   554  
   555  func (tab *Table) addIP(b *bucket, ip net.IP) bool {
   556  	if len(ip) == 0 {
   557  		return false // Nodes without IP cannot be added.
   558  	}
   559  	if netutil.IsLAN(ip) {
   560  		return true
   561  	}
   562  	if !tab.ips.Add(ip) {
   563  		tab.log.Debug("IP exceeds table limit", "ip", ip)
   564  		return false
   565  	}
   566  	if !b.ips.Add(ip) {
   567  		tab.log.Debug("IP exceeds bucket limit", "ip", ip)
   568  		tab.ips.Remove(ip)
   569  		return false
   570  	}
   571  	return true
   572  }
   573  
   574  func (tab *Table) removeIP(b *bucket, ip net.IP) {
   575  	if netutil.IsLAN(ip) {
   576  		return
   577  	}
   578  	tab.ips.Remove(ip)
   579  	b.ips.Remove(ip)
   580  }
   581  
   582  func (tab *Table) addReplacement(b *bucket, n *node) {
   583  	for _, e := range b.replacements {
   584  		if e.ID() == n.ID() {
   585  			return // already in list
   586  		}
   587  	}
   588  	if !tab.addIP(b, n.IP()) {
   589  		return
   590  	}
   591  	var removed *node
   592  	b.replacements, removed = pushNode(b.replacements, n, maxReplacements)
   593  	if removed != nil {
   594  		tab.removeIP(b, removed.IP())
   595  	}
   596  }
   597  
   598  // replace removes n from the replacement list and replaces 'last' with it if it is the
   599  // last entry in the bucket. If 'last' isn't the last entry, it has either been replaced
   600  // with someone else or became active.
   601  func (tab *Table) replace(b *bucket, last *node) *node {
   602  	if len(b.entries) == 0 || b.entries[len(b.entries)-1].ID() != last.ID() {
   603  		// Entry has moved, don't replace it.
   604  		return nil
   605  	}
   606  	// Still the last entry.
   607  	if len(b.replacements) == 0 {
   608  		tab.deleteInBucket(b, last)
   609  		return nil
   610  	}
   611  	r := b.replacements[tab.rand.Intn(len(b.replacements))]
   612  	b.replacements = deleteNode(b.replacements, r)
   613  	b.entries[len(b.entries)-1] = r
   614  	tab.removeIP(b, last.IP())
   615  	return r
   616  }
   617  
   618  // bumpInBucket moves the given node to the front of the bucket entry list
   619  // if it is contained in that list.
   620  func (tab *Table) bumpInBucket(b *bucket, n *node) bool {
   621  	for i := range b.entries {
   622  		if b.entries[i].ID() == n.ID() {
   623  			if !n.IP().Equal(b.entries[i].IP()) {
   624  				// Endpoint has changed, ensure that the new IP fits into table limits.
   625  				tab.removeIP(b, b.entries[i].IP())
   626  				if !tab.addIP(b, n.IP()) {
   627  					// It doesn't, put the previous one back.
   628  					tab.addIP(b, b.entries[i].IP())
   629  					return false
   630  				}
   631  			}
   632  			// Move it to the front.
   633  			copy(b.entries[1:], b.entries[:i])
   634  			b.entries[0] = n
   635  			return true
   636  		}
   637  	}
   638  	return false
   639  }
   640  
   641  func (tab *Table) deleteInBucket(b *bucket, n *node) {
   642  	b.entries = deleteNode(b.entries, n)
   643  	tab.removeIP(b, n.IP())
   644  }
   645  
   646  func contains(ns []*node, id enode.ID) bool {
   647  	for _, n := range ns {
   648  		if n.ID() == id {
   649  			return true
   650  		}
   651  	}
   652  	return false
   653  }
   654  
   655  // pushNode adds n to the front of list, keeping at most max items.
   656  func pushNode(list []*node, n *node, max int) ([]*node, *node) {
   657  	if len(list) < max {
   658  		list = append(list, nil)
   659  	}
   660  	removed := list[len(list)-1]
   661  	copy(list[1:], list)
   662  	list[0] = n
   663  	return list, removed
   664  }
   665  
   666  // deleteNode removes n from list.
   667  func deleteNode(list []*node, n *node) []*node {
   668  	for i := range list {
   669  		if list[i].ID() == n.ID() {
   670  			return append(list[:i], list[i+1:]...)
   671  		}
   672  	}
   673  	return list
   674  }
   675  
   676  // nodesByDistance is a list of nodes, ordered by distance to target.
   677  type nodesByDistance struct {
   678  	entries []*node
   679  	target  enode.ID
   680  }
   681  
   682  // push adds the given node to the list, keeping the total size below maxElems.
   683  func (h *nodesByDistance) push(n *node, maxElems int) {
   684  	ix := sort.Search(len(h.entries), func(i int) bool {
   685  		return enode.DistCmp(h.target, h.entries[i].ID(), n.ID()) > 0
   686  	})
   687  	if len(h.entries) < maxElems {
   688  		h.entries = append(h.entries, n)
   689  	}
   690  	if ix == len(h.entries) {
   691  		// farther away than all nodes we already have.
   692  		// if there was room for it, the node is now the last element.
   693  	} else {
   694  		// slide existing entries down to make room
   695  		// this will overwrite the entry we just appended.
   696  		copy(h.entries[ix+1:], h.entries[ix:])
   697  		h.entries[ix] = n
   698  	}
   699  }