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