github.com/etherbanking/go-etherbanking@v1.7.1-0.20181009210156-cf649bca5aba/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  	"crypto/rand"
    27  	"encoding/binary"
    28  	"errors"
    29  	"fmt"
    30  	"net"
    31  	"sort"
    32  	"sync"
    33  	"time"
    34  	//"encoding/json"
    35  
    36  
    37  	"github.com/etherbanking/go-etherbanking/common"
    38  	"github.com/etherbanking/go-etherbanking/crypto"
    39  	"github.com/etherbanking/go-etherbanking/log"
    40  )
    41  
    42  const (
    43  	alpha      = 3  // Kademlia concurrency factor
    44  	bucketSize = 16 // Kademlia bucket size
    45  	hashBits   = len(common.Hash{}) * 8
    46  	nBuckets   = hashBits + 1 // Number of buckets
    47  
    48  	maxBondingPingPongs = 16
    49  	maxFindnodeFailures = 5
    50  
    51  	autoRefreshInterval = 1 * time.Hour
    52  	seedCount           = 30
    53  	seedMaxAge          = 5 * 24 * time.Hour
    54  )
    55  
    56  type Table struct {
    57  	mutex   sync.Mutex        // protects buckets, their content, and nursery
    58  	buckets [nBuckets]*bucket // index of known nodes by distance
    59  	nursery []*Node           // bootstrap nodes
    60  	db      *nodeDB           // database of known nodes
    61  
    62  	refreshReq chan chan struct{}
    63  	closeReq   chan struct{}
    64  	closed     chan struct{}
    65  
    66  	bondmu    sync.Mutex
    67  	bonding   map[NodeID]*bondproc
    68  	bondslots chan struct{} // limits total number of active bonding processes
    69  
    70  	nodeAddedHook func(*Node) // for testing
    71  
    72  	net  transport
    73  	self *Node // metadata of the local node
    74  }
    75  
    76  type bondproc struct {
    77  	err  error
    78  	n    *Node
    79  	done chan struct{}
    80  }
    81  
    82  // transport is implemented by the UDP transport.
    83  // it is an interface so we can test without opening lots of UDP
    84  // sockets and without generating a private key.
    85  type transport interface {
    86  	ping(NodeID, *net.UDPAddr) error
    87  	waitping(NodeID) error
    88  	findnode(toid NodeID, addr *net.UDPAddr, target NodeID) ([]*Node, error)
    89  	close()
    90  }
    91  
    92  // bucket contains nodes, ordered by their last activity. the entry
    93  // that was most recently active is the first element in entries.
    94  type bucket struct{ entries []*Node }
    95  
    96  func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, nodeDBPath string) (*Table, error) {
    97  	// If no node database was given, use an in-memory one
    98  	db, err := newNodeDB(nodeDBPath, Version, ourID)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  	tab := &Table{
   103  		net:        t,
   104  		db:         db,
   105  		self:       NewNode(ourID, ourAddr.IP, uint16(ourAddr.Port), uint16(ourAddr.Port)),
   106  		bonding:    make(map[NodeID]*bondproc),
   107  		bondslots:  make(chan struct{}, maxBondingPingPongs),
   108  		refreshReq: make(chan chan struct{}),
   109  		closeReq:   make(chan struct{}),
   110  		closed:     make(chan struct{}),
   111  	}
   112  	for i := 0; i < cap(tab.bondslots); i++ {
   113  		tab.bondslots <- struct{}{}
   114  	}
   115  	for i := range tab.buckets {
   116  		tab.buckets[i] = new(bucket)
   117  	}
   118  	go tab.refreshLoop()
   119  	return tab, nil
   120  }
   121  
   122  // Self returns the local node.
   123  // The returned node should not be modified by the caller.
   124  func (tab *Table) Self() *Node {
   125  	return tab.self
   126  }
   127  
   128  // ReadRandomNodes fills the given slice with random nodes from the
   129  // table. It will not write the same node more than once. The nodes in
   130  // the slice are copies and can be modified by the caller.
   131  func (tab *Table) ReadRandomNodes(buf []*Node) (n int) {
   132  	tab.mutex.Lock()
   133  	defer tab.mutex.Unlock()
   134  	// TODO: tree-based buckets would help here
   135  	// Find all non-empty buckets and get a fresh slice of their entries.
   136  	var buckets [][]*Node
   137  	for _, b := range tab.buckets {
   138  		if len(b.entries) > 0 {
   139  			buckets = append(buckets, b.entries[:])
   140  		}
   141  	}
   142  	if len(buckets) == 0 {
   143  		return 0
   144  	}
   145  	// Shuffle the buckets.
   146  	for i := uint32(len(buckets)) - 1; i > 0; i-- {
   147  		j := randUint(i)
   148  		buckets[i], buckets[j] = buckets[j], buckets[i]
   149  	}
   150  	// Move head of each bucket into buf, removing buckets that become empty.
   151  	var i, j int
   152  	for ; i < len(buf); i, j = i+1, (j+1)%len(buckets) {
   153  		b := buckets[j]
   154  		buf[i] = &(*b[0])
   155  		buckets[j] = b[1:]
   156  		if len(b) == 1 {
   157  			buckets = append(buckets[:j], buckets[j+1:]...)
   158  		}
   159  		if len(buckets) == 0 {
   160  			break
   161  		}
   162  	}
   163  	return i + 1
   164  }
   165  
   166  func randUint(max uint32) uint32 {
   167  	if max == 0 {
   168  		return 0
   169  	}
   170  	var b [4]byte
   171  	rand.Read(b[:])
   172  	return binary.BigEndian.Uint32(b[:]) % max
   173  }
   174  
   175  // Close terminates the network listener and flushes the node database.
   176  func (tab *Table) Close() {
   177  	select {
   178  	case <-tab.closed:
   179  		// already closed.
   180  	case tab.closeReq <- struct{}{}:
   181  		<-tab.closed // wait for refreshLoop to end.
   182  	}
   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 []*Node) error {
   189  	for _, n := range nodes {
   190  		if err := n.validateComplete(); err != nil {
   191  			return fmt.Errorf("bad bootstrap/fallback node %q (%v)", n, err)
   192  		}
   193  	}
   194  	tab.mutex.Lock()
   195  	tab.nursery = make([]*Node, 0, len(nodes))
   196  	for _, n := range nodes {
   197  		cpy := *n
   198  		// Recompute cpy.sha because the node might not have been
   199  		// created by NewNode or ParseNode.
   200  		cpy.sha = crypto.Keccak256Hash(n.ID[:])
   201  		tab.nursery = append(tab.nursery, &cpy)
   202  	}
   203  	tab.mutex.Unlock()
   204  	tab.refresh()
   205  	return nil
   206  }
   207  
   208  // Resolve searches for a specific node with the given ID.
   209  // It returns nil if the node could not be found.
   210  func (tab *Table) Resolve(targetID NodeID) *Node {
   211  	// If the node is present in the local table, no
   212  	// network interaction is required.
   213  	hash := crypto.Keccak256Hash(targetID[:])
   214  	tab.mutex.Lock()
   215  	cl := tab.closest(hash, 1)
   216  	tab.mutex.Unlock()
   217  	if len(cl.entries) > 0 && cl.entries[0].ID == targetID {
   218  		return cl.entries[0]
   219  	}
   220  	// Otherwise, do a network lookup.
   221  	result := tab.Lookup(targetID)
   222  	for _, n := range result {
   223  		if n.ID == targetID {
   224  			return n
   225  		}
   226  	}
   227  	return nil
   228  }
   229  
   230  // Lookup performs a network search for nodes close
   231  // to the given target. It approaches the target by querying
   232  // nodes that are closer to it on each iteration.
   233  // The given target does not need to be an actual node
   234  // identifier.
   235  func (tab *Table) Lookup(targetID NodeID) []*Node {
   236  	return tab.lookup(targetID, true)
   237  }
   238  
   239  func (tab *Table) lookup(targetID NodeID, refreshIfEmpty bool) []*Node {
   240  	var (
   241  		target         = crypto.Keccak256Hash(targetID[:])
   242  		asked          = make(map[NodeID]bool)
   243  		seen           = make(map[NodeID]bool)
   244  		reply          = make(chan []*Node, alpha)
   245  		pendingQueries = 0
   246  		result         *nodesByDistance
   247  	)
   248  	// don't query further if we hit ourself.
   249  	// unlikely to happen often in practice.
   250  	asked[tab.self.ID] = true
   251  
   252  	for {
   253  		tab.mutex.Lock()
   254  		// generate initial result set
   255  		result = tab.closest(target, bucketSize)
   256  		tab.mutex.Unlock()
   257  		if len(result.entries) > 0 || !refreshIfEmpty {
   258  			break
   259  		}
   260  		// The result set is empty, all nodes were dropped, refresh.
   261  		// We actually wait for the refresh to complete here. The very
   262  		// first query will hit this case and run the bootstrapping
   263  		// logic.
   264  		<-tab.refresh()
   265  		refreshIfEmpty = false
   266  	}
   267  
   268  	for {
   269  		// ask the alpha closest nodes that we haven't asked yet
   270  		for i := 0; i < len(result.entries) && pendingQueries < alpha; i++ {
   271  			n := result.entries[i]
   272  			if !asked[n.ID] {
   273  				asked[n.ID] = true
   274  				pendingQueries++
   275  				go func() {
   276  					// Find potential neighbors to bond with
   277  					r, err := tab.net.findnode(n.ID, n.addr(), targetID)
   278  					if err != nil {
   279  						// Bump the failure counter to detect and evacuate non-bonded entries
   280  						fails := tab.db.findFails(n.ID) + 1
   281  						tab.db.updateFindFails(n.ID, fails)
   282  						log.Trace("Bumping findnode failure counter", "id", n.ID, "failcount", fails)
   283  
   284  						if fails >= maxFindnodeFailures {
   285  							log.Trace("Too many findnode failures, dropping", "id", n.ID, "failcount", fails)
   286  							tab.delete(n)
   287  						}
   288  					}
   289  					reply <- tab.bondall(r)
   290  				}()
   291  			}
   292  		}
   293  		if pendingQueries == 0 {
   294  			// we have asked all closest nodes, stop the search
   295  			break
   296  		}
   297  		// wait for the next reply
   298  		for _, n := range <-reply {
   299  			if n != nil && !seen[n.ID] {
   300  				seen[n.ID] = true
   301  				result.push(n, bucketSize)
   302  			}
   303  		}
   304  		pendingQueries--
   305  	}
   306  	return result.entries
   307  }
   308  
   309  func (tab *Table) refresh() <-chan struct{} {
   310  	done := make(chan struct{})
   311  	select {
   312  	case tab.refreshReq <- done:
   313  	case <-tab.closed:
   314  		close(done)
   315  	}
   316  	return done
   317  }
   318  
   319  // refreshLoop schedules doRefresh runs and coordinates shutdown.
   320  func (tab *Table) refreshLoop() {
   321  	var (
   322  		timer   = time.NewTicker(autoRefreshInterval)
   323  		waiting []chan struct{} // accumulates waiting callers while doRefresh runs
   324  		done    chan struct{}   // where doRefresh reports completion
   325  	)
   326  loop:
   327  	for {
   328  		select {
   329  		case <-timer.C:
   330  			if done == nil {
   331  				done = make(chan struct{})
   332  				go tab.doRefresh(done)
   333  			}
   334  		case req := <-tab.refreshReq:
   335  			waiting = append(waiting, req)
   336  			if done == nil {
   337  				done = make(chan struct{})
   338  				go tab.doRefresh(done)
   339  			}
   340  		case <-done:
   341  			for _, ch := range waiting {
   342  				close(ch)
   343  			}
   344  			waiting = nil
   345  			done = nil
   346  		case <-tab.closeReq:
   347  			break loop
   348  		}
   349  	}
   350  
   351  	if tab.net != nil {
   352  		tab.net.close()
   353  	}
   354  	if done != nil {
   355  		<-done
   356  	}
   357  	for _, ch := range waiting {
   358  		close(ch)
   359  	}
   360  	tab.db.close()
   361  	close(tab.closed)
   362  }
   363  
   364  // doRefresh performs a lookup for a random target to keep buckets
   365  // full. seed nodes are inserted if the table is empty (initial
   366  // bootstrap or discarded faulty peers).
   367  func (tab *Table) doRefresh(done chan struct{}) {
   368  	defer close(done)
   369  
   370  	// The Kademlia paper specifies that the bucket refresh should
   371  	// perform a lookup in the least recently used bucket. We cannot
   372  	// adhere to this because the findnode target is a 512bit value
   373  	// (not hash-sized) and it is not easily possible to generate a
   374  	// sha3 preimage that falls into a chosen bucket.
   375  	// We perform a lookup with a random target instead.
   376  	var target NodeID
   377  	rand.Read(target[:])
   378  	result := tab.lookup(target, false)
   379  	if len(result) > 0 {
   380  		return
   381  	}
   382  
   383  	// The table is empty. Load nodes from the database and insert
   384  	// them. This should yield a few previously seen nodes that are
   385  	// (hopefully) still alive.
   386  	seeds := tab.db.querySeeds(seedCount, seedMaxAge)
   387  	seeds = tab.bondall(append(seeds, tab.nursery...))
   388  
   389  	if len(seeds) == 0 {
   390  		log.Debug("No discv4 seed nodes found")
   391  	}
   392  	for _, n := range seeds {
   393  		age := log.Lazy{Fn: func() time.Duration { return time.Since(tab.db.lastPong(n.ID)) }}
   394  		log.Trace("Found seed node in database", "id", n.ID, "addr", n.addr(), "age", age)
   395  	}
   396  	tab.mutex.Lock()
   397  	tab.stuff(seeds)
   398  	tab.mutex.Unlock()
   399  
   400  	// Finally, do a self lookup to fill up the buckets.
   401  	tab.lookup(tab.self.ID, false)
   402  }
   403  
   404  // closest returns the n nodes in the table that are closest to the
   405  // given id. The caller must hold tab.mutex.
   406  func (tab *Table) closest(target common.Hash, nresults int) *nodesByDistance {
   407  	// This is a very wasteful way to find the closest nodes but
   408  	// obviously correct. I believe that tree-based buckets would make
   409  	// this easier to implement efficiently.
   410  	close := &nodesByDistance{target: target}
   411  	for _, b := range tab.buckets {
   412  		for _, n := range b.entries {
   413  			close.push(n, nresults)
   414  		}
   415  	}
   416  	return close
   417  }
   418  
   419  func (tab *Table) len() (n int) {
   420  	for _, b := range tab.buckets {
   421  		n += len(b.entries)
   422  	}
   423  	return n
   424  }
   425  
   426  // bondall bonds with all given nodes concurrently and returns
   427  // those nodes for which bonding has probably succeeded.
   428  func (tab *Table) bondall(nodes []*Node) (result []*Node) {
   429  	rc := make(chan *Node, len(nodes))
   430  	for i := range nodes {
   431  		go func(n *Node) {
   432  			nn, _ := tab.bond(false, n.ID, n.addr(), uint16(n.TCP))
   433  			rc <- nn
   434  		}(nodes[i])
   435  	}
   436  	for range nodes {
   437  		if n := <-rc; n != nil {
   438  			result = append(result, n)
   439  		}
   440  	}
   441  	return result
   442  }
   443  
   444  // bond ensures the local node has a bond with the given remote node.
   445  // It also attempts to insert the node into the table if bonding succeeds.
   446  // The caller must not hold tab.mutex.
   447  //
   448  // A bond is must be established before sending findnode requests.
   449  // Both sides must have completed a ping/pong exchange for a bond to
   450  // exist. The total number of active bonding processes is limited in
   451  // order to restrain network use.
   452  //
   453  // bond is meant to operate idempotently in that bonding with a remote
   454  // node which still remembers a previously established bond will work.
   455  // The remote node will simply not send a ping back, causing waitping
   456  // to time out.
   457  //
   458  // If pinged is true, the remote node has just pinged us and one half
   459  // of the process can be skipped.
   460  func (tab *Table) bond(pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16) (*Node, error) {
   461  	if id == tab.self.ID {
   462  		return nil, errors.New("is self")
   463  	}
   464  	// Retrieve a previously known node and any recent findnode failures
   465  	node, fails := tab.db.node(id), 0
   466  	if node != nil {
   467  		fails = tab.db.findFails(id)
   468  	}
   469  	// If the node is unknown (non-bonded) or failed (remotely unknown), bond from scratch
   470  	var result error
   471  	age := time.Since(tab.db.lastPong(id))
   472  	if node == nil || fails > 0 || age > nodeDBNodeExpiration {
   473  		log.Trace("Starting bonding ping/pong", "id", id, "known", node != nil, "failcount", fails, "age", age)
   474  
   475  		tab.bondmu.Lock()
   476  		w := tab.bonding[id]
   477  		if w != nil {
   478  			// Wait for an existing bonding process to complete.
   479  			tab.bondmu.Unlock()
   480  			<-w.done
   481  		} else {
   482  			// Register a new bonding process.
   483  			w = &bondproc{done: make(chan struct{})}
   484  			tab.bonding[id] = w
   485  			tab.bondmu.Unlock()
   486  			// Do the ping/pong. The result goes into w.
   487  			tab.pingpong(w, pinged, id, addr, tcpPort)
   488  			// Unregister the process after it's done.
   489  			tab.bondmu.Lock()
   490  			delete(tab.bonding, id)
   491  			tab.bondmu.Unlock()
   492  		}
   493  		// Retrieve the bonding results
   494  		result = w.err
   495  		if result == nil {
   496  			node = w.n
   497  		}
   498  	}
   499  	if node != nil {
   500  		// Add the node to the table even if the bonding ping/pong
   501  		// fails. It will be relaced quickly if it continues to be
   502  		// unresponsive.
   503  		tab.add(node)
   504  		tab.db.updateFindFails(id, 0)
   505  	}
   506  	return node, result
   507  }
   508  
   509  func (tab *Table) pingpong(w *bondproc, pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16) {
   510  	// Request a bonding slot to limit network usage
   511  	<-tab.bondslots
   512  	defer func() { tab.bondslots <- struct{}{} }()
   513  
   514  	// Ping the remote side and wait for a pong.
   515  	if w.err = tab.ping(id, addr); w.err != nil {
   516  		close(w.done)
   517  		return
   518  	}
   519  	if !pinged {
   520  		// Give the remote node a chance to ping us before we start
   521  		// sending findnode requests. If they still remember us,
   522  		// waitping will simply time out.
   523  		tab.net.waitping(id)
   524  	}
   525  	// Bonding succeeded, update the node database.
   526  	w.n = NewNode(id, addr.IP, uint16(addr.Port), tcpPort)
   527  	tab.db.updateNode(w.n)
   528  	close(w.done)
   529  }
   530  
   531  // ping a remote endpoint and wait for a reply, also updating the node
   532  // database accordingly.
   533  func (tab *Table) ping(id NodeID, addr *net.UDPAddr) error {
   534  
   535  	tab.db.updateLastPing(id, time.Now())
   536  	if err := tab.net.ping(id, addr); err != nil {
   537  
   538  		return err
   539  	}
   540  	tab.db.updateLastPong(id, time.Now())
   541  
   542  	// Start the background expiration goroutine after the first
   543  	// successful communication. Subsequent calls have no effect if it
   544  	// is already running. We do this here instead of somewhere else
   545  	// so that the search for seed nodes also considers older nodes
   546  	// that would otherwise be removed by the expiration.
   547  	tab.db.ensureExpirer()
   548  	return nil
   549  }
   550  
   551  // add attempts to add the given node its corresponding bucket. If the
   552  // bucket has space available, adding the node succeeds immediately.
   553  // Otherwise, the node is added if the least recently active node in
   554  // the bucket does not respond to a ping packet.
   555  //
   556  // The caller must not hold tab.mutex.
   557  func (tab *Table) add(new *Node) {
   558  	b := tab.buckets[logdist(tab.self.sha, new.sha)]
   559  	tab.mutex.Lock()
   560  	defer tab.mutex.Unlock()
   561  	if b.bump(new) {
   562  		return
   563  	}
   564  	var oldest *Node
   565  	if len(b.entries) == bucketSize {
   566  		oldest = b.entries[bucketSize-1]
   567  		if oldest.contested {
   568  			// The node is already being replaced, don't attempt
   569  			// to replace it.
   570  			return
   571  		}
   572  		oldest.contested = true
   573  		// Let go of the mutex so other goroutines can access
   574  		// the table while we ping the least recently active node.
   575  		tab.mutex.Unlock()
   576  		err := tab.ping(oldest.ID, oldest.addr())
   577  		tab.mutex.Lock()
   578  		oldest.contested = false
   579  		if err == nil {
   580  			// The node responded, don't replace it.
   581  			return
   582  		}
   583  	}
   584  	added := b.replace(new, oldest)
   585  	if added && tab.nodeAddedHook != nil {
   586  		tab.nodeAddedHook(new)
   587  	}
   588  }
   589  
   590  // stuff adds nodes the table to the end of their corresponding bucket
   591  // if the bucket is not full. The caller must hold tab.mutex.
   592  func (tab *Table) stuff(nodes []*Node) {
   593  outer:
   594  	for _, n := range nodes {
   595  		if n.ID == tab.self.ID {
   596  			continue // don't add self
   597  		}
   598  		bucket := tab.buckets[logdist(tab.self.sha, n.sha)]
   599  		for i := range bucket.entries {
   600  			if bucket.entries[i].ID == n.ID {
   601  				continue outer // already in bucket
   602  			}
   603  		}
   604  		if len(bucket.entries) < bucketSize {
   605  			bucket.entries = append(bucket.entries, n)
   606  			if tab.nodeAddedHook != nil {
   607  				tab.nodeAddedHook(n)
   608  			}
   609  		}
   610  	}
   611  }
   612  
   613  // delete removes an entry from the node table (used to evacuate
   614  // failed/non-bonded discovery peers).
   615  func (tab *Table) delete(node *Node) {
   616  	tab.mutex.Lock()
   617  	defer tab.mutex.Unlock()
   618  	bucket := tab.buckets[logdist(tab.self.sha, node.sha)]
   619  	for i := range bucket.entries {
   620  		if bucket.entries[i].ID == node.ID {
   621  			bucket.entries = append(bucket.entries[:i], bucket.entries[i+1:]...)
   622  			return
   623  		}
   624  	}
   625  }
   626  
   627  func (b *bucket) replace(n *Node, last *Node) bool {
   628  	// Don't add if b already contains n.
   629  	for i := range b.entries {
   630  		if b.entries[i].ID == n.ID {
   631  			return false
   632  		}
   633  	}
   634  	// Replace last if it is still the last entry or just add n if b
   635  	// isn't full. If is no longer the last entry, it has either been
   636  	// replaced with someone else or became active.
   637  	if len(b.entries) == bucketSize && (last == nil || b.entries[bucketSize-1].ID != last.ID) {
   638  		return false
   639  	}
   640  	if len(b.entries) < bucketSize {
   641  		b.entries = append(b.entries, nil)
   642  	}
   643  	copy(b.entries[1:], b.entries)
   644  	b.entries[0] = n
   645  	return true
   646  }
   647  
   648  func (b *bucket) bump(n *Node) bool {
   649  	for i := range b.entries {
   650  		if b.entries[i].ID == n.ID {
   651  			// move it to the front
   652  			copy(b.entries[1:], b.entries[:i])
   653  			b.entries[0] = n
   654  			return true
   655  		}
   656  	}
   657  	return false
   658  }
   659  
   660  // nodesByDistance is a list of nodes, ordered by
   661  // distance to target.
   662  type nodesByDistance struct {
   663  	entries []*Node
   664  	target  common.Hash
   665  }
   666  
   667  // push adds the given node to the list, keeping the total size below maxElems.
   668  func (h *nodesByDistance) push(n *Node, maxElems int) {
   669  	ix := sort.Search(len(h.entries), func(i int) bool {
   670  		return distcmp(h.target, h.entries[i].sha, n.sha) > 0
   671  	})
   672  	if len(h.entries) < maxElems {
   673  		h.entries = append(h.entries, n)
   674  	}
   675  	if ix == len(h.entries) {
   676  		// farther away than all nodes we already have.
   677  		// if there was room for it, the node is now the last element.
   678  	} else {
   679  		// slide existing entries down to make room
   680  		// this will overwrite the entry we just appended.
   681  		copy(h.entries[ix+1:], h.entries[ix:])
   682  		h.entries[ix] = n
   683  	}
   684  }