github.com/quinndk/ethereum_read@v0.0.0-20181211143958-29c55eec3237/go-ethereum-master_read/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/ethereum/go-ethereum/common"
    36  	"github.com/ethereum/go-ethereum/crypto"
    37  	"github.com/ethereum/go-ethereum/log"
    38  	"github.com/ethereum/go-ethereum/p2p/netutil"
    39  )
    40  
    41  const (
    42  	// 并发因子
    43  	alpha           = 3  // Kademlia concurrency factor
    44  	// k桶容量
    45  	bucketSize      = 16 // Kademlia bucket size
    46  	// 每个k桶更换清单的大小
    47  	maxReplacements = 10 // Size of per-bucket replacement list
    48  
    49  	// We keep buckets for the upper 1/15 of distances because
    50  	// it's very unlikely we'll ever encounter a node that's closer.
    51  	//
    52  	hashBits          = len(common.Hash{}) * 8
    53  	nBuckets          = hashBits / 15       // Number of buckets
    54  	// 最近k桶的距离
    55  	bucketMinDistance = hashBits - nBuckets // Log distance of closest bucket
    56  
    57  	// IP address limits.
    58  	bucketIPLimit, bucketSubnet = 2, 24 // at most 2 addresses from the same /24
    59  	tableIPLimit, tableSubnet   = 10, 24
    60  
    61  	// 节点丢弃的限制,超过这些限制的节点将被丢弃
    62  	maxFindnodeFailures = 5 // Nodes exceeding this limit are dropped
    63  	refreshInterval     = 30 * time.Minute
    64  	revalidateInterval  = 10 * time.Second
    65  	copyNodesInterval   = 30 * time.Second
    66  	seedMinTableTime    = 5 * time.Minute
    67  	seedCount           = 30
    68  	seedMaxAge          = 5 * 24 * time.Hour
    69  )
    70  
    71  //k-bucket表
    72  type Table struct {
    73  	mutex   sync.Mutex        // protects buckets, bucket content, nursery, rand
    74  	// k桶数组
    75  	buckets [nBuckets]*bucket // index of known nodes by distance
    76  	// 引导节点
    77  	nursery []*Node           // bootstrap nodes
    78  	// 随机源头
    79  	rand    *mrand.Rand       // source of randomness, periodically reseeded
    80  	ips     netutil.DistinctNetSet
    81  
    82  	// 节点数据库
    83  	db         *nodeDB // database of known nodes
    84  	refreshReq chan chan struct{}
    85  	initDone   chan struct{}
    86  	closeReq   chan struct{}
    87  	closed     chan struct{}
    88  
    89  	nodeAddedHook func(*Node) // for testing
    90  
    91  	net  transport
    92  	self *Node // metadata of the local node
    93  }
    94  
    95  // transport is implemented by the UDP transport.
    96  // it is an interface so we can test without opening lots of UDP
    97  // sockets and without generating a private key.
    98  // 真正寻找节点的接口
    99  type transport interface {
   100  	ping(NodeID, *net.UDPAddr) error
   101  	findnode(toid NodeID, addr *net.UDPAddr, target NodeID) ([]*Node, error)
   102  	close()
   103  }
   104  
   105  // bucket contains nodes, ordered by their last activity. the entry
   106  // that was most recently active is the first element in entries.
   107  // 按上一个活动排序的节点
   108  // 最近活动的条目是条目中的第一个元素
   109  type bucket struct {
   110  	// 实时节点列表
   111  	entries      []*Node // live entries, sorted by time of last contact
   112  	// 候补节点,entries满了后之后的节点会存储到这
   113  	replacements []*Node // recently seen nodes to be used if revalidation fails
   114  	ips          netutil.DistinctNetSet
   115  }
   116  
   117  func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, nodeDBPath string, bootnodes []*Node) (*Table, error) {
   118  	// If no node database was given, use an in-memory one
   119  	// 1.新建节点数据库
   120  	db, err := newNodeDB(nodeDBPath, nodeDBVersion, ourID)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  
   125  	// 2.构造k桶表
   126  	tab := &Table{
   127  		net:        t,
   128  		db:         db,
   129  		self:       NewNode(ourID, ourAddr.IP, uint16(ourAddr.Port), uint16(ourAddr.Port)),
   130  		refreshReq: make(chan chan struct{}),
   131  		initDone:   make(chan struct{}),
   132  		closeReq:   make(chan struct{}),
   133  		closed:     make(chan struct{}),
   134  		rand:       mrand.New(mrand.NewSource(0)),
   135  		ips:        netutil.DistinctNetSet{Subnet: tableSubnet, Limit: tableIPLimit},
   136  	}
   137  
   138  	// 3.设置初始连接点
   139  	if err := tab.setFallbackNodes(bootnodes); err != nil {
   140  		return nil, err
   141  	}
   142  
   143  	// 4.填充k桶
   144  	for i := range tab.buckets {
   145  		tab.buckets[i] = &bucket{
   146  			ips: netutil.DistinctNetSet{Subnet: bucketSubnet, Limit: bucketIPLimit},
   147  		}
   148  	}
   149  
   150  	// 4.加载种子节点
   151  	tab.seedRand()
   152  	tab.loadSeedNodes()
   153  	// Start the background expiration goroutine after loading seeds so that the search for
   154  	// seed nodes also considers older nodes that would otherwise be removed by the
   155  	// expiration.
   156  	tab.db.ensureExpirer()
   157  
   158  	// 5.开启协程循环更新
   159  	go tab.loop()
   160  	return tab, nil
   161  }
   162  
   163  func (tab *Table) seedRand() {
   164  	var b [8]byte
   165  	crand.Read(b[:])
   166  
   167  	tab.mutex.Lock()
   168  	tab.rand.Seed(int64(binary.BigEndian.Uint64(b[:])))
   169  	tab.mutex.Unlock()
   170  }
   171  
   172  // Self returns the local node.
   173  // The returned node should not be modified by the caller.
   174  func (tab *Table) Self() *Node {
   175  	return tab.self
   176  }
   177  
   178  // ReadRandomNodes fills the given slice with random nodes from the
   179  // table. It will not write the same node more than once. The nodes in
   180  // the slice are copies and can be modified by the caller.
   181  func (tab *Table) ReadRandomNodes(buf []*Node) (n int) {
   182  	if !tab.isInitDone() {
   183  		return 0
   184  	}
   185  	tab.mutex.Lock()
   186  	defer tab.mutex.Unlock()
   187  
   188  	// Find all non-empty buckets and get a fresh slice of their entries.
   189  	var buckets [][]*Node
   190  	for _, b := range tab.buckets {
   191  		if len(b.entries) > 0 {
   192  			buckets = append(buckets, b.entries[:])
   193  		}
   194  	}
   195  	if len(buckets) == 0 {
   196  		return 0
   197  	}
   198  	// Shuffle the buckets.
   199  	for i := len(buckets) - 1; i > 0; i-- {
   200  		j := tab.rand.Intn(len(buckets))
   201  		buckets[i], buckets[j] = buckets[j], buckets[i]
   202  	}
   203  	// Move head of each bucket into buf, removing buckets that become empty.
   204  	var i, j int
   205  	for ; i < len(buf); i, j = i+1, (j+1)%len(buckets) {
   206  		b := buckets[j]
   207  		buf[i] = &(*b[0])
   208  		buckets[j] = b[1:]
   209  		if len(b) == 1 {
   210  			buckets = append(buckets[:j], buckets[j+1:]...)
   211  		}
   212  		if len(buckets) == 0 {
   213  			break
   214  		}
   215  	}
   216  	return i + 1
   217  }
   218  
   219  // Close terminates the network listener and flushes the node database.
   220  func (tab *Table) Close() {
   221  	select {
   222  	case <-tab.closed:
   223  		// already closed.
   224  	case tab.closeReq <- struct{}{}:
   225  		<-tab.closed // wait for refreshLoop to end.
   226  	}
   227  }
   228  
   229  // setFallbackNodes sets the initial points of contact. These nodes
   230  // are used to connect to the network if the table is empty and there
   231  // are no known nodes in the database.
   232  func (tab *Table) setFallbackNodes(nodes []*Node) error {
   233  	for _, n := range nodes {
   234  		if err := n.validateComplete(); err != nil {
   235  			return fmt.Errorf("bad bootstrap/fallback node %q (%v)", n, err)
   236  		}
   237  	}
   238  	tab.nursery = make([]*Node, 0, len(nodes))
   239  	for _, n := range nodes {
   240  		cpy := *n
   241  		// Recompute cpy.sha because the node might not have been
   242  		// created by NewNode or ParseNode.
   243  		cpy.sha = crypto.Keccak256Hash(n.ID[:])
   244  		tab.nursery = append(tab.nursery, &cpy)
   245  	}
   246  	return nil
   247  }
   248  
   249  // isInitDone returns whether the table's initial seeding procedure has completed.
   250  func (tab *Table) isInitDone() bool {
   251  	select {
   252  	case <-tab.initDone:
   253  		return true
   254  	default:
   255  		return false
   256  	}
   257  }
   258  
   259  // Resolve searches for a specific node with the given ID.
   260  // It returns nil if the node could not be found.
   261  func (tab *Table) Resolve(targetID NodeID) *Node {
   262  	// If the node is present in the local table, no
   263  	// network interaction is required.
   264  	hash := crypto.Keccak256Hash(targetID[:])
   265  	tab.mutex.Lock()
   266  	cl := tab.closest(hash, 1)
   267  	tab.mutex.Unlock()
   268  	if len(cl.entries) > 0 && cl.entries[0].ID == targetID {
   269  		return cl.entries[0]
   270  	}
   271  	// Otherwise, do a network lookup.
   272  	result := tab.Lookup(targetID)
   273  	for _, n := range result {
   274  		if n.ID == targetID {
   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  // 搜索当前节点的附近节点
   287  func (tab *Table) Lookup(targetID NodeID) []*Node {
   288  	return tab.lookup(targetID, true)
   289  }
   290  
   291  func (tab *Table) lookup(targetID NodeID, refreshIfEmpty bool) []*Node {
   292  	var (
   293  		target         = crypto.Keccak256Hash(targetID[:])
   294  		asked          = make(map[NodeID]bool)
   295  		seen           = make(map[NodeID]bool)
   296  		reply          = make(chan []*Node, alpha)
   297  		pendingQueries = 0
   298  		result         *nodesByDistance
   299  	)
   300  	// don't query further if we hit ourself.
   301  	// unlikely to happen often in practice.
   302  	// 一般询问自己是没有意义的
   303  	asked[tab.self.ID] = true
   304  
   305  	for {
   306  		tab.mutex.Lock()
   307  		// generate initial result set
   308  		// 获取k桶表中给定节点id的n个节点
   309  		result = tab.closest(target, bucketSize)
   310  		tab.mutex.Unlock()
   311  		if len(result.entries) > 0 || !refreshIfEmpty {
   312  
   313  			// k桶表不为空
   314  			break
   315  		}
   316  		// The result set is empty, all nodes were dropped, refresh.
   317  		// We actually wait for the refresh to complete here. The very
   318  		// first query will hit this case and run the bootstrapping
   319  		// logic.
   320  
   321  		// k桶表为空
   322  		<-tab.refresh()
   323  		refreshIfEmpty = false
   324  	}
   325  
   326  	for {
   327  		// ask the alpha closest nodes that we haven't asked yet
   328  		// 询问尚未询问的最接近的节点
   329  		for i := 0; i < len(result.entries) && pendingQueries < alpha; i++ {
   330  			n := result.entries[i]
   331  			// 未被查询的节点
   332  			if !asked[n.ID] {
   333  				asked[n.ID] = true
   334  				pendingQueries++
   335  				// 查找节点
   336  				go tab.findnode(n, targetID, reply)
   337  			}
   338  		}
   339  		if pendingQueries == 0 {
   340  			// we have asked all closest nodes, stop the search
   341  			// 所有最近节点都询问过了
   342  			break
   343  		}
   344  		// wait for the next reply
   345  		for _, n := range <-reply {
   346  			if n != nil && !seen[n.ID] {
   347  				seen[n.ID] = true
   348  				result.push(n, bucketSize)
   349  			}
   350  		}
   351  		pendingQueries--
   352  	}
   353  	return result.entries
   354  }
   355  
   356  func (tab *Table) findnode(n *Node, targetID NodeID, reply chan<- []*Node) {
   357  	fails := tab.db.findFails(n.ID)
   358  	r, err := tab.net.findnode(n.ID, n.addr(), targetID)
   359  	if err != nil || len(r) == 0 {
   360  		fails++
   361  		tab.db.updateFindFails(n.ID, fails)
   362  		log.Trace("Findnode failed", "id", n.ID, "failcount", fails, "err", err)
   363  		if fails >= maxFindnodeFailures {
   364  			log.Trace("Too many findnode failures, dropping", "id", n.ID, "failcount", fails)
   365  			tab.delete(n)
   366  		}
   367  	} else if fails > 0 {
   368  		tab.db.updateFindFails(n.ID, fails-1)
   369  	}
   370  
   371  	// Grab as many nodes as possible. Some of them might not be alive anymore, but we'll
   372  	// just remove those again during revalidation.
   373  	// 将所有节点加入k桶表,尽管有些已经离线(我们会在重新验证时删除这些节点)
   374  	for _, n := range r {
   375  		tab.add(n)
   376  	}
   377  	reply <- r
   378  }
   379  
   380  func (tab *Table) refresh() <-chan struct{} {
   381  	done := make(chan struct{})
   382  	select {
   383  	case tab.refreshReq <- done:
   384  	case <-tab.closed:
   385  		close(done)
   386  	}
   387  	return done
   388  }
   389  
   390  // loop schedules refresh, revalidate runs and coordinates shutdown.
   391  func (tab *Table) loop() {
   392  	var (
   393  		revalidate     = time.NewTimer(tab.nextRevalidateTime())
   394  		refresh        = time.NewTicker(refreshInterval)
   395  		copyNodes      = time.NewTicker(copyNodesInterval)
   396  		revalidateDone = make(chan struct{})
   397  		refreshDone    = make(chan struct{})           // where doRefresh reports completion
   398  		waiting        = []chan struct{}{tab.initDone} // holds waiting callers while doRefresh runs
   399  	)
   400  	defer refresh.Stop()
   401  	defer revalidate.Stop()
   402  	defer copyNodes.Stop()
   403  
   404  	// Start initial refresh.
   405  	// 初始化刷新
   406  	go tab.doRefresh(refreshDone)
   407  
   408  loop:
   409  	for {
   410  		select {
   411  		case <-refresh.C:
   412  			tab.seedRand()
   413  			if refreshDone == nil {
   414  				refreshDone = make(chan struct{})
   415  				go tab.doRefresh(refreshDone)
   416  			}
   417  		case req := <-tab.refreshReq:
   418  			// 将刷新请求加入通道数组
   419  			waiting = append(waiting, req)
   420  			if refreshDone == nil {
   421  				refreshDone = make(chan struct{})
   422  				go tab.doRefresh(refreshDone)
   423  			}
   424  		case <-refreshDone:
   425  			// 刷新完毕,关闭通道
   426  			for _, ch := range waiting {
   427  				close(ch)
   428  			}
   429  			waiting, refreshDone = nil, nil
   430  		case <-revalidate.C:
   431  			// 重新验证
   432  			go tab.doRevalidate(revalidateDone)
   433  		case <-revalidateDone:
   434  			revalidate.Reset(tab.nextRevalidateTime())
   435  		case <-copyNodes.C:
   436  			// 拷贝活跃节点
   437  			go tab.copyLiveNodes()
   438  		case <-tab.closeReq:
   439  			break loop
   440  		}
   441  	}
   442  
   443  	if tab.net != nil {
   444  		tab.net.close()
   445  	}
   446  	if refreshDone != nil {
   447  		<-refreshDone
   448  	}
   449  	for _, ch := range waiting {
   450  		close(ch)
   451  	}
   452  	tab.db.close()
   453  	close(tab.closed)
   454  }
   455  
   456  // doRefresh performs a lookup for a random target to keep buckets
   457  // full. seed nodes are inserted if the table is empty (initial
   458  // bootstrap or discarded faulty peers).
   459  // 执行随机目标查找并保持桶满
   460  // 会在第一次k桶表为空的时候插入种子节点
   461  func (tab *Table) doRefresh(done chan struct{}) {
   462  	defer close(done)
   463  
   464  	// Load nodes from the database and insert
   465  	// them. This should yield a few previously seen nodes that are
   466  	// (hopefully) still alive.
   467  	// 加载种子节点
   468  	tab.loadSeedNodes()
   469  
   470  	// Run self lookup to discover new neighbor nodes.
   471  	// 发现当前节点的令居节点
   472  	tab.lookup(tab.self.ID, false)
   473  
   474  	// The Kademlia paper specifies that the bucket refresh should
   475  	// perform a lookup in the least recently used bucket. We cannot
   476  	// adhere to this because the findnode target is a 512bit value
   477  	// (not hash-sized) and it is not easily possible to generate a
   478  	// sha3 preimage that falls into a chosen bucket.
   479  	// We perform a few lookups with a random target instead.
   480  	// 使用随机的target进行查找,因为这里查找节点的id是一个512位的值,
   481  	// 我们不容易生成属于所选存储桶的sha3前缀映像
   482  	for i := 0; i < 3; i++ {
   483  		var target NodeID
   484  		crand.Read(target[:])
   485  		tab.lookup(target, false)
   486  	}
   487  }
   488  
   489  func (tab *Table) loadSeedNodes() {
   490  	seeds := tab.db.querySeeds(seedCount, seedMaxAge)
   491  	seeds = append(seeds, tab.nursery...)
   492  	for i := range seeds {
   493  		seed := seeds[i]
   494  		age := log.Lazy{Fn: func() interface{} { return time.Since(tab.db.lastPongReceived(seed.ID)) }}
   495  		log.Debug("Found seed node in database", "id", seed.ID, "addr", seed.addr(), "age", age)
   496  		tab.add(seed)
   497  	}
   498  }
   499  
   500  // doRevalidate checks that the last node in a random bucket is still live
   501  // and replaces or deletes the node if it isn't.
   502  // 检查最后一个节点是否在线,不在线就更换或删除
   503  func (tab *Table) doRevalidate(done chan<- struct{}) {
   504  	defer func() { done <- struct{}{} }()
   505  
   506  	last, bi := tab.nodeToRevalidate()
   507  	if last == nil {
   508  		// No non-empty bucket found.
   509  		return
   510  	}
   511  
   512  	// Ping the selected node and wait for a pong.
   513  	// 发出ping指令,等待pong回复
   514  	err := tab.net.ping(last.ID, last.addr())
   515  
   516  	tab.mutex.Lock()
   517  	defer tab.mutex.Unlock()
   518  	b := tab.buckets[bi]
   519  	if err == nil {
   520  		// The node responded, move it to the front.
   521  		log.Trace("Revalidated node", "b", bi, "id", last.ID)
   522  		b.bump(last)
   523  		return
   524  	}
   525  	// No reply received, pick a replacement or delete the node if there aren't
   526  	// any replacements.
   527  	// 没有事收到ping的回复,更换或删除节点
   528  	if r := tab.replace(b, last); r != nil {
   529  		log.Trace("Replaced dead node", "b", bi, "id", last.ID, "ip", last.IP, "r", r.ID, "rip", r.IP)
   530  	} else {
   531  		log.Trace("Removed dead node", "b", bi, "id", last.ID, "ip", last.IP)
   532  	}
   533  }
   534  
   535  // nodeToRevalidate returns the last node in a random, non-empty bucket.
   536  // 获取随机非空k桶的最后一个节点
   537  func (tab *Table) nodeToRevalidate() (n *Node, bi int) {
   538  	tab.mutex.Lock()
   539  	defer tab.mutex.Unlock()
   540  
   541  	for _, bi = range tab.rand.Perm(len(tab.buckets)) {
   542  		b := tab.buckets[bi]
   543  		if len(b.entries) > 0 {
   544  			last := b.entries[len(b.entries)-1]
   545  			return last, bi
   546  		}
   547  	}
   548  	return nil, 0
   549  }
   550  
   551  func (tab *Table) nextRevalidateTime() time.Duration {
   552  	tab.mutex.Lock()
   553  	defer tab.mutex.Unlock()
   554  
   555  	return time.Duration(tab.rand.Int63n(int64(revalidateInterval)))
   556  }
   557  
   558  // copyLiveNodes adds nodes from the table to the database if they have been in the table
   559  // longer then minTableTime.
   560  func (tab *Table) copyLiveNodes() {
   561  	tab.mutex.Lock()
   562  	defer tab.mutex.Unlock()
   563  
   564  	now := time.Now()
   565  	for _, b := range tab.buckets {
   566  		for _, n := range b.entries {
   567  			if now.Sub(n.addedAt) >= seedMinTableTime {
   568  				tab.db.updateNode(n)
   569  			}
   570  		}
   571  	}
   572  }
   573  
   574  // closest returns the n nodes in the table that are closest to the
   575  // given id. The caller must hold tab.mutex.
   576  // 获取k桶表中给定节点id的n个节点
   577  func (tab *Table) closest(target common.Hash, nresults int) *nodesByDistance {
   578  	// This is a very wasteful way to find the closest nodes but
   579  	// obviously correct. I believe that tree-based buckets would make
   580  	// this easier to implement efficiently.
   581  	close := &nodesByDistance{target: target}
   582  	for _, b := range tab.buckets {
   583  		for _, n := range b.entries {
   584  			close.push(n, nresults)
   585  		}
   586  	}
   587  	return close
   588  }
   589  
   590  func (tab *Table) len() (n int) {
   591  	for _, b := range tab.buckets {
   592  		n += len(b.entries)
   593  	}
   594  	return n
   595  }
   596  
   597  // bucket returns the bucket for the given node ID hash.
   598  func (tab *Table) bucket(sha common.Hash) *bucket {
   599  	d := logdist(tab.self.sha, sha)
   600  	if d <= bucketMinDistance {
   601  		return tab.buckets[0]
   602  	}
   603  	return tab.buckets[d-bucketMinDistance-1]
   604  }
   605  
   606  // add attempts to add the given node to its corresponding bucket. If the bucket has space
   607  // available, adding the node succeeds immediately. Otherwise, the node is added if the
   608  // least recently active node in the bucket does not respond to a ping packet.
   609  //
   610  // The caller must not hold tab.mutex.
   611  func (tab *Table) add(n *Node) {
   612  	tab.mutex.Lock()
   613  	defer tab.mutex.Unlock()
   614  
   615  	b := tab.bucket(n.sha)
   616  	if !tab.bumpOrAdd(b, n) {
   617  		// Node is not in table. Add it to the replacement list.
   618  		tab.addReplacement(b, n)
   619  	}
   620  }
   621  
   622  // addThroughPing adds the given node to the table. Compared to plain
   623  // 'add' there is an additional safety measure: if the table is still
   624  // initializing the node is not added. This prevents an attack where the
   625  // table could be filled by just sending ping repeatedly.
   626  //
   627  // The caller must not hold tab.mutex.
   628  //  与普通的“添加”相比,还有一个额外的安全措施:如果表仍在初始化,则不添加节点。
   629  // 	这样可以防止因重复发送ping而填充表的攻击
   630  func (tab *Table) addThroughPing(n *Node) {
   631  	if !tab.isInitDone() {
   632  		return
   633  	}
   634  	tab.add(n)
   635  }
   636  
   637  // stuff adds nodes the table to the end of their corresponding bucket
   638  // if the bucket is not full. The caller must not hold tab.mutex.
   639  func (tab *Table) stuff(nodes []*Node) {
   640  	tab.mutex.Lock()
   641  	defer tab.mutex.Unlock()
   642  
   643  	for _, n := range nodes {
   644  		if n.ID == tab.self.ID {
   645  			continue // don't add self
   646  		}
   647  		b := tab.bucket(n.sha)
   648  		if len(b.entries) < bucketSize {
   649  			tab.bumpOrAdd(b, n)
   650  		}
   651  	}
   652  }
   653  
   654  // delete removes an entry from the node table. It is used to evacuate dead nodes.
   655  func (tab *Table) delete(node *Node) {
   656  	tab.mutex.Lock()
   657  	defer tab.mutex.Unlock()
   658  
   659  	tab.deleteInBucket(tab.bucket(node.sha), node)
   660  }
   661  
   662  func (tab *Table) addIP(b *bucket, ip net.IP) bool {
   663  	if netutil.IsLAN(ip) {
   664  		return true
   665  	}
   666  	if !tab.ips.Add(ip) {
   667  		log.Debug("IP exceeds table limit", "ip", ip)
   668  		return false
   669  	}
   670  	if !b.ips.Add(ip) {
   671  		log.Debug("IP exceeds bucket limit", "ip", ip)
   672  		tab.ips.Remove(ip)
   673  		return false
   674  	}
   675  	return true
   676  }
   677  
   678  func (tab *Table) removeIP(b *bucket, ip net.IP) {
   679  	if netutil.IsLAN(ip) {
   680  		return
   681  	}
   682  	tab.ips.Remove(ip)
   683  	b.ips.Remove(ip)
   684  }
   685  
   686  func (tab *Table) addReplacement(b *bucket, n *Node) {
   687  	for _, e := range b.replacements {
   688  		if e.ID == n.ID {
   689  			return // already in list
   690  		}
   691  	}
   692  	if !tab.addIP(b, n.IP) {
   693  		return
   694  	}
   695  	var removed *Node
   696  	b.replacements, removed = pushNode(b.replacements, n, maxReplacements)
   697  	if removed != nil {
   698  		tab.removeIP(b, removed.IP)
   699  	}
   700  }
   701  
   702  // replace removes n from the replacement list and replaces 'last' with it if it is the
   703  // last entry in the bucket. If 'last' isn't the last entry, it has either been replaced
   704  // with someone else or became active.
   705  // 这里验证失败后会把前面buket结构里replacements里的节点候补到entries
   706  func (tab *Table) replace(b *bucket, last *Node) *Node {
   707  	if len(b.entries) == 0 || b.entries[len(b.entries)-1].ID != last.ID {
   708  		// Entry has moved, don't replace it.
   709  		return nil
   710  	}
   711  	// Still the last entry.
   712  	if len(b.replacements) == 0 {
   713  		tab.deleteInBucket(b, last)
   714  		return nil
   715  	}
   716  	r := b.replacements[tab.rand.Intn(len(b.replacements))]
   717  	b.replacements = deleteNode(b.replacements, r)
   718  	b.entries[len(b.entries)-1] = r
   719  	tab.removeIP(b, last.IP)
   720  	return r
   721  }
   722  
   723  // bump moves the given node to the front of the bucket entry list
   724  // if it is contained in that list.
   725  // 将节点node移动到最前
   726  func (b *bucket) bump(n *Node) bool {
   727  	for i := range b.entries {
   728  		if b.entries[i].ID == n.ID {
   729  			// move it to the front
   730  			copy(b.entries[1:], b.entries[:i])
   731  			b.entries[0] = n
   732  			return true
   733  		}
   734  	}
   735  	return false
   736  }
   737  
   738  // bumpOrAdd moves n to the front of the bucket entry list or adds it if the list isn't
   739  // full. The return value is true if n is in the bucket.
   740  func (tab *Table) bumpOrAdd(b *bucket, n *Node) bool {
   741  	if b.bump(n) {
   742  		return true
   743  	}
   744  	if len(b.entries) >= bucketSize || !tab.addIP(b, n.IP) {
   745  		return false
   746  	}
   747  	b.entries, _ = pushNode(b.entries, n, bucketSize)
   748  	b.replacements = deleteNode(b.replacements, n)
   749  	n.addedAt = time.Now()
   750  	if tab.nodeAddedHook != nil {
   751  		tab.nodeAddedHook(n)
   752  	}
   753  	return true
   754  }
   755  
   756  func (tab *Table) deleteInBucket(b *bucket, n *Node) {
   757  	b.entries = deleteNode(b.entries, n)
   758  	tab.removeIP(b, n.IP)
   759  }
   760  
   761  // pushNode adds n to the front of list, keeping at most max items.
   762  func pushNode(list []*Node, n *Node, max int) ([]*Node, *Node) {
   763  	if len(list) < max {
   764  		list = append(list, nil)
   765  	}
   766  	removed := list[len(list)-1]
   767  	copy(list[1:], list)
   768  	list[0] = n
   769  	return list, removed
   770  }
   771  
   772  // deleteNode removes n from list.
   773  func deleteNode(list []*Node, n *Node) []*Node {
   774  	for i := range list {
   775  		if list[i].ID == n.ID {
   776  			return append(list[:i], list[i+1:]...)
   777  		}
   778  	}
   779  	return list
   780  }
   781  
   782  // nodesByDistance is a list of nodes, ordered by
   783  // distance to target.
   784  // 根据距离远近排序的邻居节点
   785  type nodesByDistance struct {
   786  	entries []*Node
   787  	target  common.Hash
   788  }
   789  
   790  // push adds the given node to the list, keeping the total size below maxElems.
   791  // 将节点添加到给定列表并维持大小小于maxElems
   792  //
   793  func (h *nodesByDistance) push(n *Node, maxElems int) {
   794  
   795  	// 根据节点到target的距离排序
   796  	ix := sort.Search(len(h.entries), func(i int) bool {
   797  		return distcmp(h.target, h.entries[i].sha, n.sha) > 0
   798  	})
   799  
   800  	// 大小未超出限制,将节点加入
   801  	if len(h.entries) < maxElems {
   802  		h.entries = append(h.entries, n)
   803  	}
   804  	if ix == len(h.entries) {
   805  		// farther away than all nodes we already have.
   806  		// if there was room for it, the node is now the last element.
   807  	} else {
   808  		// slide existing entries down to make room
   809  		// this will overwrite the entry we just appended.
   810  		copy(h.entries[ix+1:], h.entries[ix:])
   811  		h.entries[ix] = n
   812  	}
   813  }