github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/p2p/discover/table.go (about)

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