github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/p2p/discv5/net.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:43</date>
    10  //</624342656805244928>
    11  
    12  
    13  package discv5
    14  
    15  import (
    16  	"bytes"
    17  	"crypto/ecdsa"
    18  	"errors"
    19  	"fmt"
    20  	"net"
    21  	"time"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/common/mclock"
    25  	"github.com/ethereum/go-ethereum/crypto"
    26  	"github.com/ethereum/go-ethereum/crypto/sha3"
    27  	"github.com/ethereum/go-ethereum/log"
    28  	"github.com/ethereum/go-ethereum/p2p/netutil"
    29  	"github.com/ethereum/go-ethereum/rlp"
    30  )
    31  
    32  var (
    33  	errInvalidEvent = errors.New("invalid in current state")
    34  	errNoQuery      = errors.New("no pending query")
    35  )
    36  
    37  const (
    38  	autoRefreshInterval   = 1 * time.Hour
    39  	bucketRefreshInterval = 1 * time.Minute
    40  	seedCount             = 30
    41  	seedMaxAge            = 5 * 24 * time.Hour
    42  	lowPort               = 1024
    43  )
    44  
    45  const testTopic = "foo"
    46  
    47  const (
    48  	printTestImgLogs = false
    49  )
    50  
    51  //网络管理表和所有协议交互。
    52  type Network struct {
    53  db          *nodeDB //已知节点数据库
    54  	conn        transport
    55  	netrestrict *netutil.Netlist
    56  
    57  closed           chan struct{}          //循环完成时关闭
    58  closeReq         chan struct{}          //'关闭请求'
    59  refreshReq       chan []*Node           //查找要求刷新此频道
    60  refreshResp      chan (<-chan struct{}) //…让这个频道阻止
    61  read             chan ingressPacket     //入口包到达这里
    62  	timeout          chan timeoutEvent
    63  queryReq         chan *findnodeQuery //查找在此频道上提交findnode查询
    64  	tableOpReq       chan func()
    65  	tableOpResp      chan struct{}
    66  	topicRegisterReq chan topicRegisterReq
    67  	topicSearchReq   chan topicSearchReq
    68  
    69  //主循环的状态。
    70  	tab           *Table
    71  	topictab      *topicTable
    72  	ticketStore   *ticketStore
    73  	nursery       []*Node
    74  nodes         map[NodeID]*Node //用状态跟踪活动节点!=已知
    75  	timeoutTimers map[timeoutEvent]*time.Timer
    76  
    77  //重新验证队列。
    78  //放置在这些队列上的节点最终将被ping。
    79  	slowRevalidateQueue []*Node
    80  	fastRevalidateQueue []*Node
    81  
    82  //状态转换缓冲区。
    83  	sendBuf []*ingressPacket
    84  }
    85  
    86  //传输由UDP传输实现。
    87  //它是一个接口,因此我们可以在不打开大量UDP的情况下进行测试
    88  //不生成私钥的套接字。
    89  type transport interface {
    90  	sendPing(remote *Node, remoteAddr *net.UDPAddr, topics []Topic) (hash []byte)
    91  	sendNeighbours(remote *Node, nodes []*Node)
    92  	sendFindnodeHash(remote *Node, target common.Hash)
    93  	sendTopicRegister(remote *Node, topics []Topic, topicIdx int, pong []byte)
    94  	sendTopicNodes(remote *Node, queryHash common.Hash, nodes []*Node)
    95  
    96  	send(remote *Node, ptype nodeEvent, p interface{}) (hash []byte)
    97  
    98  	localAddr() *net.UDPAddr
    99  	Close()
   100  }
   101  
   102  type findnodeQuery struct {
   103  	remote   *Node
   104  	target   common.Hash
   105  	reply    chan<- []*Node
   106  nresults int //接收节点计数器
   107  }
   108  
   109  type topicRegisterReq struct {
   110  	add   bool
   111  	topic Topic
   112  }
   113  
   114  type topicSearchReq struct {
   115  	topic  Topic
   116  	found  chan<- *Node
   117  	lookup chan<- bool
   118  	delay  time.Duration
   119  }
   120  
   121  type topicSearchResult struct {
   122  	target lookupInfo
   123  	nodes  []*Node
   124  }
   125  
   126  type timeoutEvent struct {
   127  	ev   nodeEvent
   128  	node *Node
   129  }
   130  
   131  func newNetwork(conn transport, ourPubkey ecdsa.PublicKey, dbPath string, netrestrict *netutil.Netlist) (*Network, error) {
   132  	ourID := PubkeyID(&ourPubkey)
   133  
   134  	var db *nodeDB
   135  	if dbPath != "<no database>" {
   136  		var err error
   137  		if db, err = newNodeDB(dbPath, Version, ourID); err != nil {
   138  			return nil, err
   139  		}
   140  	}
   141  
   142  	tab := newTable(ourID, conn.localAddr())
   143  	net := &Network{
   144  		db:               db,
   145  		conn:             conn,
   146  		netrestrict:      netrestrict,
   147  		tab:              tab,
   148  		topictab:         newTopicTable(db, tab.self),
   149  		ticketStore:      newTicketStore(),
   150  		refreshReq:       make(chan []*Node),
   151  		refreshResp:      make(chan (<-chan struct{})),
   152  		closed:           make(chan struct{}),
   153  		closeReq:         make(chan struct{}),
   154  		read:             make(chan ingressPacket, 100),
   155  		timeout:          make(chan timeoutEvent),
   156  		timeoutTimers:    make(map[timeoutEvent]*time.Timer),
   157  		tableOpReq:       make(chan func()),
   158  		tableOpResp:      make(chan struct{}),
   159  		queryReq:         make(chan *findnodeQuery),
   160  		topicRegisterReq: make(chan topicRegisterReq),
   161  		topicSearchReq:   make(chan topicSearchReq),
   162  		nodes:            make(map[NodeID]*Node),
   163  	}
   164  	go net.loop()
   165  	return net, nil
   166  }
   167  
   168  //close终止网络侦听器并刷新节点数据库。
   169  func (net *Network) Close() {
   170  	net.conn.Close()
   171  	select {
   172  	case <-net.closed:
   173  	case net.closeReq <- struct{}{}:
   174  		<-net.closed
   175  	}
   176  }
   177  
   178  //self返回本地节点。
   179  //调用方不应修改返回的节点。
   180  func (net *Network) Self() *Node {
   181  	return net.tab.self
   182  }
   183  
   184  //readrandomnodes用来自
   185  //表。它不会多次写入同一节点。节点
   186  //切片是副本,可以由调用方修改。
   187  func (net *Network) ReadRandomNodes(buf []*Node) (n int) {
   188  	net.reqTableOp(func() { n = net.tab.readRandomNodes(buf) })
   189  	return n
   190  }
   191  
   192  //setFallbackNodes设置初始接触点。这些节点
   193  //如果表为空,则用于连接到网络
   194  //数据库中没有已知节点。
   195  func (net *Network) SetFallbackNodes(nodes []*Node) error {
   196  	nursery := make([]*Node, 0, len(nodes))
   197  	for _, n := range nodes {
   198  		if err := n.validateComplete(); err != nil {
   199  			return fmt.Errorf("bad bootstrap/fallback node %q (%v)", n, err)
   200  		}
   201  //重新计算cpy.sha,因为节点可能没有
   202  //由newnode或parsenode创建。
   203  		cpy := *n
   204  		cpy.sha = crypto.Keccak256Hash(n.ID[:])
   205  		nursery = append(nursery, &cpy)
   206  	}
   207  	net.reqRefresh(nursery)
   208  	return nil
   209  }
   210  
   211  //解析搜索具有给定ID的特定节点。
   212  //如果找不到节点,则返回nil。
   213  func (net *Network) Resolve(targetID NodeID) *Node {
   214  	result := net.lookup(crypto.Keccak256Hash(targetID[:]), true)
   215  	for _, n := range result {
   216  		if n.ID == targetID {
   217  			return n
   218  		}
   219  	}
   220  	return nil
   221  }
   222  
   223  //查找对关闭的节点执行网络搜索
   224  //目标。它通过查询接近目标
   225  //在每次迭代中离它更近的节点。
   226  //给定目标不需要是实际节点
   227  //标识符。
   228  //
   229  //结果中可能包含本地节点。
   230  func (net *Network) Lookup(targetID NodeID) []*Node {
   231  	return net.lookup(crypto.Keccak256Hash(targetID[:]), false)
   232  }
   233  
   234  func (net *Network) lookup(target common.Hash, stopOnMatch bool) []*Node {
   235  	var (
   236  		asked          = make(map[NodeID]bool)
   237  		seen           = make(map[NodeID]bool)
   238  		reply          = make(chan []*Node, alpha)
   239  		result         = nodesByDistance{target: target}
   240  		pendingQueries = 0
   241  	)
   242  //从本地节点获取初始答案。
   243  	result.push(net.tab.self, bucketSize)
   244  	for {
   245  //询问我们尚未询问的α最近的节点。
   246  		for i := 0; i < len(result.entries) && pendingQueries < alpha; i++ {
   247  			n := result.entries[i]
   248  			if !asked[n.ID] {
   249  				asked[n.ID] = true
   250  				pendingQueries++
   251  				net.reqQueryFindnode(n, target, reply)
   252  			}
   253  		}
   254  		if pendingQueries == 0 {
   255  //我们要求所有最近的节点停止搜索。
   256  			break
   257  		}
   258  //等待下一个答复。
   259  		select {
   260  		case nodes := <-reply:
   261  			for _, n := range nodes {
   262  				if n != nil && !seen[n.ID] {
   263  					seen[n.ID] = true
   264  					result.push(n, bucketSize)
   265  					if stopOnMatch && n.sha == target {
   266  						return result.entries
   267  					}
   268  				}
   269  			}
   270  			pendingQueries--
   271  		case <-time.After(respTimeout):
   272  //忽略所有挂起的请求,启动新的请求
   273  			pendingQueries = 0
   274  			reply = make(chan []*Node, alpha)
   275  		}
   276  	}
   277  	return result.entries
   278  }
   279  
   280  func (net *Network) RegisterTopic(topic Topic, stop <-chan struct{}) {
   281  	select {
   282  	case net.topicRegisterReq <- topicRegisterReq{true, topic}:
   283  	case <-net.closed:
   284  		return
   285  	}
   286  	select {
   287  	case <-net.closed:
   288  	case <-stop:
   289  		select {
   290  		case net.topicRegisterReq <- topicRegisterReq{false, topic}:
   291  		case <-net.closed:
   292  		}
   293  	}
   294  }
   295  
   296  func (net *Network) SearchTopic(topic Topic, setPeriod <-chan time.Duration, found chan<- *Node, lookup chan<- bool) {
   297  	for {
   298  		select {
   299  		case <-net.closed:
   300  			return
   301  		case delay, ok := <-setPeriod:
   302  			select {
   303  			case net.topicSearchReq <- topicSearchReq{topic: topic, found: found, lookup: lookup, delay: delay}:
   304  			case <-net.closed:
   305  				return
   306  			}
   307  			if !ok {
   308  				return
   309  			}
   310  		}
   311  	}
   312  }
   313  
   314  func (net *Network) reqRefresh(nursery []*Node) <-chan struct{} {
   315  	select {
   316  	case net.refreshReq <- nursery:
   317  		return <-net.refreshResp
   318  	case <-net.closed:
   319  		return net.closed
   320  	}
   321  }
   322  
   323  func (net *Network) reqQueryFindnode(n *Node, target common.Hash, reply chan []*Node) bool {
   324  	q := &findnodeQuery{remote: n, target: target, reply: reply}
   325  	select {
   326  	case net.queryReq <- q:
   327  		return true
   328  	case <-net.closed:
   329  		return false
   330  	}
   331  }
   332  
   333  func (net *Network) reqReadPacket(pkt ingressPacket) {
   334  	select {
   335  	case net.read <- pkt:
   336  	case <-net.closed:
   337  	}
   338  }
   339  
   340  func (net *Network) reqTableOp(f func()) (called bool) {
   341  	select {
   342  	case net.tableOpReq <- f:
   343  		<-net.tableOpResp
   344  		return true
   345  	case <-net.closed:
   346  		return false
   347  	}
   348  }
   349  
   350  //TODO:外部地址处理。
   351  
   352  type topicSearchInfo struct {
   353  	lookupChn chan<- bool
   354  	period    time.Duration
   355  }
   356  
   357  const maxSearchCount = 5
   358  
   359  func (net *Network) loop() {
   360  	var (
   361  		refreshTimer       = time.NewTicker(autoRefreshInterval)
   362  		bucketRefreshTimer = time.NewTimer(bucketRefreshInterval)
   363  refreshDone        chan struct{} //“刷新”查找结束时关闭
   364  	)
   365  
   366  //跟踪下一张要注册的票据。
   367  	var (
   368  		nextTicket        *ticketRef
   369  		nextRegisterTimer *time.Timer
   370  		nextRegisterTime  <-chan time.Time
   371  	)
   372  	defer func() {
   373  		if nextRegisterTimer != nil {
   374  			nextRegisterTimer.Stop()
   375  		}
   376  	}()
   377  	resetNextTicket := func() {
   378  		ticket, timeout := net.ticketStore.nextFilteredTicket()
   379  		if nextTicket != ticket {
   380  			nextTicket = ticket
   381  			if nextRegisterTimer != nil {
   382  				nextRegisterTimer.Stop()
   383  				nextRegisterTime = nil
   384  			}
   385  			if ticket != nil {
   386  				nextRegisterTimer = time.NewTimer(timeout)
   387  				nextRegisterTime = nextRegisterTimer.C
   388  			}
   389  		}
   390  	}
   391  
   392  //跟踪注册和搜索查找。
   393  	var (
   394  		topicRegisterLookupTarget lookupInfo
   395  		topicRegisterLookupDone   chan []*Node
   396  		topicRegisterLookupTick   = time.NewTimer(0)
   397  		searchReqWhenRefreshDone  []topicSearchReq
   398  		searchInfo                = make(map[Topic]topicSearchInfo)
   399  		activeSearchCount         int
   400  	)
   401  	topicSearchLookupDone := make(chan topicSearchResult, 100)
   402  	topicSearch := make(chan Topic, 100)
   403  	<-topicRegisterLookupTick.C
   404  
   405  	statsDump := time.NewTicker(10 * time.Second)
   406  
   407  loop:
   408  	for {
   409  		resetNextTicket()
   410  
   411  		select {
   412  		case <-net.closeReq:
   413  			log.Trace("<-net.closeReq")
   414  			break loop
   415  
   416  //入口包处理。
   417  		case pkt := <-net.read:
   418  //fmt.println(“读取”,pkt.ev)
   419  			log.Trace("<-net.read")
   420  			n := net.internNode(&pkt)
   421  			prestate := n.state
   422  			status := "ok"
   423  			if err := net.handle(n, pkt.ev, &pkt); err != nil {
   424  				status = err.Error()
   425  			}
   426  			log.Trace("", "msg", log.Lazy{Fn: func() string {
   427  				return fmt.Sprintf("<<< (%d) %v from %x@%v: %v -> %v (%v)",
   428  					net.tab.count, pkt.ev, pkt.remoteID[:8], pkt.remoteAddr, prestate, n.state, status)
   429  			}})
   430  //TODO:如果n.state变为大于等于known,则保持状态;如果n.state变为小于等于known,则删除。
   431  
   432  //状态转换超时。
   433  		case timeout := <-net.timeout:
   434  			log.Trace("<-net.timeout")
   435  			if net.timeoutTimers[timeout] == nil {
   436  //过时计时器(已中止)。
   437  				continue
   438  			}
   439  			delete(net.timeoutTimers, timeout)
   440  			prestate := timeout.node.state
   441  			status := "ok"
   442  			if err := net.handle(timeout.node, timeout.ev, nil); err != nil {
   443  				status = err.Error()
   444  			}
   445  			log.Trace("", "msg", log.Lazy{Fn: func() string {
   446  				return fmt.Sprintf("--- (%d) %v for %x@%v: %v -> %v (%v)",
   447  					net.tab.count, timeout.ev, timeout.node.ID[:8], timeout.node.addr(), prestate, timeout.node.state, status)
   448  			}})
   449  
   450  //查询。
   451  		case q := <-net.queryReq:
   452  			log.Trace("<-net.queryReq")
   453  			if !q.start(net) {
   454  				q.remote.deferQuery(q)
   455  			}
   456  
   457  //与表交互。
   458  		case f := <-net.tableOpReq:
   459  			log.Trace("<-net.tableOpReq")
   460  			f()
   461  			net.tableOpResp <- struct{}{}
   462  
   463  //主题注册资料。
   464  		case req := <-net.topicRegisterReq:
   465  			log.Trace("<-net.topicRegisterReq")
   466  			if !req.add {
   467  				net.ticketStore.removeRegisterTopic(req.topic)
   468  				continue
   469  			}
   470  			net.ticketStore.addTopic(req.topic, true)
   471  //如果我们正在等待空闲(没有可查找的内容),请给售票处
   472  //有机会早点开始。这将加速半径的收敛
   473  //确定新主题。
   474  //如果topicRegisterLookupDone==nil
   475  			if topicRegisterLookupTarget.target == (common.Hash{}) {
   476  				log.Trace("topicRegisterLookupTarget == null")
   477  				if topicRegisterLookupTick.Stop() {
   478  					<-topicRegisterLookupTick.C
   479  				}
   480  				target, delay := net.ticketStore.nextRegisterLookup()
   481  				topicRegisterLookupTarget = target
   482  				topicRegisterLookupTick.Reset(delay)
   483  			}
   484  
   485  		case nodes := <-topicRegisterLookupDone:
   486  			log.Trace("<-topicRegisterLookupDone")
   487  			net.ticketStore.registerLookupDone(topicRegisterLookupTarget, nodes, func(n *Node) []byte {
   488  				net.ping(n, n.addr())
   489  				return n.pingEcho
   490  			})
   491  			target, delay := net.ticketStore.nextRegisterLookup()
   492  			topicRegisterLookupTarget = target
   493  			topicRegisterLookupTick.Reset(delay)
   494  			topicRegisterLookupDone = nil
   495  
   496  		case <-topicRegisterLookupTick.C:
   497  			log.Trace("<-topicRegisterLookupTick")
   498  			if (topicRegisterLookupTarget.target == common.Hash{}) {
   499  				target, delay := net.ticketStore.nextRegisterLookup()
   500  				topicRegisterLookupTarget = target
   501  				topicRegisterLookupTick.Reset(delay)
   502  				topicRegisterLookupDone = nil
   503  			} else {
   504  				topicRegisterLookupDone = make(chan []*Node)
   505  				target := topicRegisterLookupTarget.target
   506  				go func() { topicRegisterLookupDone <- net.lookup(target, false) }()
   507  			}
   508  
   509  		case <-nextRegisterTime:
   510  			log.Trace("<-nextRegisterTime")
   511  			net.ticketStore.ticketRegistered(*nextTicket)
   512  //fmt.println(“sendtopicregister”,nextTicket.t.node.addr().string(),nextTicket.t.topics,nextTicket.idx,nextTicket.t.pong)
   513  			net.conn.sendTopicRegister(nextTicket.t.node, nextTicket.t.topics, nextTicket.idx, nextTicket.t.pong)
   514  
   515  		case req := <-net.topicSearchReq:
   516  			if refreshDone == nil {
   517  				log.Trace("<-net.topicSearchReq")
   518  				info, ok := searchInfo[req.topic]
   519  				if ok {
   520  					if req.delay == time.Duration(0) {
   521  						delete(searchInfo, req.topic)
   522  						net.ticketStore.removeSearchTopic(req.topic)
   523  					} else {
   524  						info.period = req.delay
   525  						searchInfo[req.topic] = info
   526  					}
   527  					continue
   528  				}
   529  				if req.delay != time.Duration(0) {
   530  					var info topicSearchInfo
   531  					info.period = req.delay
   532  					info.lookupChn = req.lookup
   533  					searchInfo[req.topic] = info
   534  					net.ticketStore.addSearchTopic(req.topic, req.found)
   535  					topicSearch <- req.topic
   536  				}
   537  			} else {
   538  				searchReqWhenRefreshDone = append(searchReqWhenRefreshDone, req)
   539  			}
   540  
   541  		case topic := <-topicSearch:
   542  			if activeSearchCount < maxSearchCount {
   543  				activeSearchCount++
   544  				target := net.ticketStore.nextSearchLookup(topic)
   545  				go func() {
   546  					nodes := net.lookup(target.target, false)
   547  					topicSearchLookupDone <- topicSearchResult{target: target, nodes: nodes}
   548  				}()
   549  			}
   550  			period := searchInfo[topic].period
   551  			if period != time.Duration(0) {
   552  				go func() {
   553  					time.Sleep(period)
   554  					topicSearch <- topic
   555  				}()
   556  			}
   557  
   558  		case res := <-topicSearchLookupDone:
   559  			activeSearchCount--
   560  			if lookupChn := searchInfo[res.target.topic].lookupChn; lookupChn != nil {
   561  				lookupChn <- net.ticketStore.radius[res.target.topic].converged
   562  			}
   563  			net.ticketStore.searchLookupDone(res.target, res.nodes, func(n *Node, topic Topic) []byte {
   564  				if n.state != nil && n.state.canQuery {
   565  return net.conn.send(n, topicQueryPacket, topicQuery{Topic: topic}) //TODO:设置过期
   566  				} else {
   567  					if n.state == unknown {
   568  						net.ping(n, n.addr())
   569  					}
   570  					return nil
   571  				}
   572  			})
   573  
   574  		case <-statsDump.C:
   575  			log.Trace("<-statsDump.C")
   576     /*,确定:=net.ticketstore.radius[testTopic]
   577     如果!好吧{
   578      fmt.printf(“(%x)no radius@%v\n”,net.tab.self.id[:8],time.now())
   579     }否则{
   580      主题:=len(net.ticketstore.tickets)
   581      票据:=len(net.ticketstore.nodes)
   582      半径:=r.radius/(maxradius/10000+1)
   583      fmt.printf(“(%x)主题:%d半径:%d票证:%d@%v\n”,net.tab.self.id[:8],主题,rad,票证,time.now())
   584     */
   585  
   586  
   587  			tm := mclock.Now()
   588  			for topic, r := range net.ticketStore.radius {
   589  				if printTestImgLogs {
   590  					rad := r.radius / (maxRadius/1000000 + 1)
   591  					minrad := r.minRadius / (maxRadius/1000000 + 1)
   592  					fmt.Printf("*R %d %v %016x %v\n", tm/1000000, topic, net.tab.self.sha[:8], rad)
   593  					fmt.Printf("*MR %d %v %016x %v\n", tm/1000000, topic, net.tab.self.sha[:8], minrad)
   594  				}
   595  			}
   596  			for topic, t := range net.topictab.topics {
   597  				wp := t.wcl.nextWaitPeriod(tm)
   598  				if printTestImgLogs {
   599  					fmt.Printf("*W %d %v %016x %d\n", tm/1000000, topic, net.tab.self.sha[:8], wp/1000000)
   600  				}
   601  			}
   602  
   603  //定期/查找启动的存储桶刷新。
   604  		case <-refreshTimer.C:
   605  			log.Trace("<-refreshTimer.C")
   606  //TODO:理想情况下,我们会在
   607  //第一次设置了回退节点。
   608  			if refreshDone == nil {
   609  				refreshDone = make(chan struct{})
   610  				net.refresh(refreshDone)
   611  			}
   612  		case <-bucketRefreshTimer.C:
   613  			target := net.tab.chooseBucketRefreshTarget()
   614  			go func() {
   615  				net.lookup(target, false)
   616  				bucketRefreshTimer.Reset(bucketRefreshInterval)
   617  			}()
   618  		case newNursery := <-net.refreshReq:
   619  			log.Trace("<-net.refreshReq")
   620  			if newNursery != nil {
   621  				net.nursery = newNursery
   622  			}
   623  			if refreshDone == nil {
   624  				refreshDone = make(chan struct{})
   625  				net.refresh(refreshDone)
   626  			}
   627  			net.refreshResp <- refreshDone
   628  		case <-refreshDone:
   629  			log.Trace("<-net.refreshDone", "table size", net.tab.count)
   630  			if net.tab.count != 0 {
   631  				refreshDone = nil
   632  				list := searchReqWhenRefreshDone
   633  				searchReqWhenRefreshDone = nil
   634  				go func() {
   635  					for _, req := range list {
   636  						net.topicSearchReq <- req
   637  					}
   638  				}()
   639  			} else {
   640  				refreshDone = make(chan struct{})
   641  				net.refresh(refreshDone)
   642  			}
   643  		}
   644  	}
   645  	log.Trace("loop stopped")
   646  
   647  	log.Debug(fmt.Sprintf("shutting down"))
   648  	if net.conn != nil {
   649  		net.conn.Close()
   650  	}
   651  	if refreshDone != nil {
   652  //TODO:等待挂起的刷新。
   653  //<-刷新结果
   654  	}
   655  //取消所有挂起的超时。
   656  	for _, timer := range net.timeoutTimers {
   657  		timer.Stop()
   658  	}
   659  	if net.db != nil {
   660  		net.db.close()
   661  	}
   662  	close(net.closed)
   663  }
   664  
   665  //下面的所有内容都在network.loop goroutine上运行
   666  //可随时修改节点、表和网络,无需锁定。
   667  
   668  func (net *Network) refresh(done chan<- struct{}) {
   669  	var seeds []*Node
   670  	if net.db != nil {
   671  		seeds = net.db.querySeeds(seedCount, seedMaxAge)
   672  	}
   673  	if len(seeds) == 0 {
   674  		seeds = net.nursery
   675  	}
   676  	if len(seeds) == 0 {
   677  		log.Trace("no seed nodes found")
   678  		time.AfterFunc(time.Second*10, func() { close(done) })
   679  		return
   680  	}
   681  	for _, n := range seeds {
   682  		log.Debug("", "msg", log.Lazy{Fn: func() string {
   683  			var age string
   684  			if net.db != nil {
   685  				age = time.Since(net.db.lastPong(n.ID)).String()
   686  			} else {
   687  				age = "unknown"
   688  			}
   689  			return fmt.Sprintf("seed node (age %s): %v", age, n)
   690  		}})
   691  		n = net.internNodeFromDB(n)
   692  		if n.state == unknown {
   693  			net.transition(n, verifyinit)
   694  		}
   695  //强制添加种子节点,以便查找可以执行某些操作。
   696  //如果验证失败,将再次删除。
   697  		net.tab.add(n)
   698  	}
   699  //开始自查找以填充存储桶。
   700  	go func() {
   701  		net.Lookup(net.tab.self.ID)
   702  		close(done)
   703  	}()
   704  }
   705  
   706  //节点交互。
   707  
   708  func (net *Network) internNode(pkt *ingressPacket) *Node {
   709  	if n := net.nodes[pkt.remoteID]; n != nil {
   710  		n.IP = pkt.remoteAddr.IP
   711  		n.UDP = uint16(pkt.remoteAddr.Port)
   712  		n.TCP = uint16(pkt.remoteAddr.Port)
   713  		return n
   714  	}
   715  	n := NewNode(pkt.remoteID, pkt.remoteAddr.IP, uint16(pkt.remoteAddr.Port), uint16(pkt.remoteAddr.Port))
   716  	n.state = unknown
   717  	net.nodes[pkt.remoteID] = n
   718  	return n
   719  }
   720  
   721  func (net *Network) internNodeFromDB(dbn *Node) *Node {
   722  	if n := net.nodes[dbn.ID]; n != nil {
   723  		return n
   724  	}
   725  	n := NewNode(dbn.ID, dbn.IP, dbn.UDP, dbn.TCP)
   726  	n.state = unknown
   727  	net.nodes[n.ID] = n
   728  	return n
   729  }
   730  
   731  func (net *Network) internNodeFromNeighbours(sender *net.UDPAddr, rn rpcNode) (n *Node, err error) {
   732  	if rn.ID == net.tab.self.ID {
   733  		return nil, errors.New("is self")
   734  	}
   735  	if rn.UDP <= lowPort {
   736  		return nil, errors.New("low port")
   737  	}
   738  	n = net.nodes[rn.ID]
   739  	if n == nil {
   740  //我们以前没有见过这个节点。
   741  		n, err = nodeFromRPC(sender, rn)
   742  		if net.netrestrict != nil && !net.netrestrict.Contains(n.IP) {
   743  			return n, errors.New("not contained in netrestrict whitelist")
   744  		}
   745  		if err == nil {
   746  			n.state = unknown
   747  			net.nodes[n.ID] = n
   748  		}
   749  		return n, err
   750  	}
   751  	if !n.IP.Equal(rn.IP) || n.UDP != rn.UDP || n.TCP != rn.TCP {
   752  		if n.state == known {
   753  //如果我们知道节点,则拒绝地址更改
   754  			err = fmt.Errorf("metadata mismatch: got %v, want %v", rn, n)
   755  		} else {
   756  //否则接受;这将通过签署的ENR更好地处理。
   757  			n.IP = rn.IP
   758  			n.UDP = rn.UDP
   759  			n.TCP = rn.TCP
   760  		}
   761  	}
   762  	return n, err
   763  }
   764  
   765  //节点网嵌入在节点中,包含字段。
   766  type nodeNetGuts struct {
   767  //这是用于节点的sha3(id)的缓存副本
   768  //距离计算。这是节点的一部分,以便
   769  //可以编写在一定距离需要节点的测试。
   770  //在这些测试中,sha的内容实际上并不对应
   771  //和ID.
   772  	sha common.Hash
   773  
   774  //状态机字段。访问这些字段
   775  //仅限于network.loop goroutine。
   776  	state             *nodeState
   777  pingEcho          []byte           //我们发送的最后一个ping的哈希
   778  pingTopics        []Topic          //上次Ping中我们发送的主题集
   779  deferredQueries   []*findnodeQuery //尚未发送的查询
   780  pendingNeighbours *findnodeQuery   //当前查询,等待答复
   781  	queryTimeouts     int
   782  }
   783  
   784  func (n *nodeNetGuts) deferQuery(q *findnodeQuery) {
   785  	n.deferredQueries = append(n.deferredQueries, q)
   786  }
   787  
   788  func (n *nodeNetGuts) startNextQuery(net *Network) {
   789  	if len(n.deferredQueries) == 0 {
   790  		return
   791  	}
   792  	nextq := n.deferredQueries[0]
   793  	if nextq.start(net) {
   794  		n.deferredQueries = append(n.deferredQueries[:0], n.deferredQueries[1:]...)
   795  	}
   796  }
   797  
   798  func (q *findnodeQuery) start(net *Network) bool {
   799  //直接满足对本地节点的查询。
   800  	if q.remote == net.tab.self {
   801  		closest := net.tab.closest(crypto.Keccak256Hash(q.target[:]), bucketSize)
   802  		q.reply <- closest.entries
   803  		return true
   804  	}
   805  	if q.remote.state.canQuery && q.remote.pendingNeighbours == nil {
   806  		net.conn.sendFindnodeHash(q.remote, q.target)
   807  		net.timedEvent(respTimeout, q.remote, neighboursTimeout)
   808  		q.remote.pendingNeighbours = q
   809  		return true
   810  	}
   811  //如果还不知道节点,它将不接受查询。
   812  //启动到已知的转换。
   813  //稍后当节点达到已知状态时,将发送请求。
   814  	if q.remote.state == unknown {
   815  		net.transition(q.remote, verifyinit)
   816  	}
   817  	return false
   818  }
   819  
   820  //节点事件(状态机的输入)。
   821  
   822  type nodeEvent uint
   823  
   824  //go:生成字符串-type=nodeEvent
   825  
   826  const (
   827  
   828  //数据包类型事件。
   829  //它们对应于UDP协议中的数据包类型。
   830  	pingPacket = iota + 1
   831  	pongPacket
   832  	findnodePacket
   833  	neighborsPacket
   834  	findnodeHashPacket
   835  	topicRegisterPacket
   836  	topicQueryPacket
   837  	topicNodesPacket
   838  
   839  //非数据包事件。
   840  //此类别中的事件值在外部分配
   841  //数据包类型范围(数据包类型编码为单字节)。
   842  	pongTimeout nodeEvent = iota + 256
   843  	pingTimeout
   844  	neighboursTimeout
   845  )
   846  
   847  //节点状态机。
   848  
   849  type nodeState struct {
   850  	name     string
   851  	handle   func(*Network, *Node, nodeEvent, *ingressPacket) (next *nodeState, err error)
   852  	enter    func(*Network, *Node)
   853  	canQuery bool
   854  }
   855  
   856  func (s *nodeState) String() string {
   857  	return s.name
   858  }
   859  
   860  var (
   861  	unknown          *nodeState
   862  	verifyinit       *nodeState
   863  	verifywait       *nodeState
   864  	remoteverifywait *nodeState
   865  	known            *nodeState
   866  	contested        *nodeState
   867  	unresponsive     *nodeState
   868  )
   869  
   870  func init() {
   871  	unknown = &nodeState{
   872  		name: "unknown",
   873  		enter: func(net *Network, n *Node) {
   874  			net.tab.delete(n)
   875  			n.pingEcho = nil
   876  //中止活动查询。
   877  			for _, q := range n.deferredQueries {
   878  				q.reply <- nil
   879  			}
   880  			n.deferredQueries = nil
   881  			if n.pendingNeighbours != nil {
   882  				n.pendingNeighbours.reply <- nil
   883  				n.pendingNeighbours = nil
   884  			}
   885  			n.queryTimeouts = 0
   886  		},
   887  		handle: func(net *Network, n *Node, ev nodeEvent, pkt *ingressPacket) (*nodeState, error) {
   888  			switch ev {
   889  			case pingPacket:
   890  				net.handlePing(n, pkt)
   891  				net.ping(n, pkt.remoteAddr)
   892  				return verifywait, nil
   893  			default:
   894  				return unknown, errInvalidEvent
   895  			}
   896  		},
   897  	}
   898  
   899  	verifyinit = &nodeState{
   900  		name: "verifyinit",
   901  		enter: func(net *Network, n *Node) {
   902  			net.ping(n, n.addr())
   903  		},
   904  		handle: func(net *Network, n *Node, ev nodeEvent, pkt *ingressPacket) (*nodeState, error) {
   905  			switch ev {
   906  			case pingPacket:
   907  				net.handlePing(n, pkt)
   908  				return verifywait, nil
   909  			case pongPacket:
   910  				err := net.handleKnownPong(n, pkt)
   911  				return remoteverifywait, err
   912  			case pongTimeout:
   913  				return unknown, nil
   914  			default:
   915  				return verifyinit, errInvalidEvent
   916  			}
   917  		},
   918  	}
   919  
   920  	verifywait = &nodeState{
   921  		name: "verifywait",
   922  		handle: func(net *Network, n *Node, ev nodeEvent, pkt *ingressPacket) (*nodeState, error) {
   923  			switch ev {
   924  			case pingPacket:
   925  				net.handlePing(n, pkt)
   926  				return verifywait, nil
   927  			case pongPacket:
   928  				err := net.handleKnownPong(n, pkt)
   929  				return known, err
   930  			case pongTimeout:
   931  				return unknown, nil
   932  			default:
   933  				return verifywait, errInvalidEvent
   934  			}
   935  		},
   936  	}
   937  
   938  	remoteverifywait = &nodeState{
   939  		name: "remoteverifywait",
   940  		enter: func(net *Network, n *Node) {
   941  			net.timedEvent(respTimeout, n, pingTimeout)
   942  		},
   943  		handle: func(net *Network, n *Node, ev nodeEvent, pkt *ingressPacket) (*nodeState, error) {
   944  			switch ev {
   945  			case pingPacket:
   946  				net.handlePing(n, pkt)
   947  				return remoteverifywait, nil
   948  			case pingTimeout:
   949  				return known, nil
   950  			default:
   951  				return remoteverifywait, errInvalidEvent
   952  			}
   953  		},
   954  	}
   955  
   956  	known = &nodeState{
   957  		name:     "known",
   958  		canQuery: true,
   959  		enter: func(net *Network, n *Node) {
   960  			n.queryTimeouts = 0
   961  			n.startNextQuery(net)
   962  //插入到表中并开始最后一个节点的重新验证
   963  //在桶里,如果满了。
   964  			last := net.tab.add(n)
   965  			if last != nil && last.state == known {
   966  //TODO:异步执行此操作
   967  				net.transition(last, contested)
   968  			}
   969  		},
   970  		handle: func(net *Network, n *Node, ev nodeEvent, pkt *ingressPacket) (*nodeState, error) {
   971  			switch ev {
   972  			case pingPacket:
   973  				net.handlePing(n, pkt)
   974  				return known, nil
   975  			case pongPacket:
   976  				err := net.handleKnownPong(n, pkt)
   977  				return known, err
   978  			default:
   979  				return net.handleQueryEvent(n, ev, pkt)
   980  			}
   981  		},
   982  	}
   983  
   984  	contested = &nodeState{
   985  		name:     "contested",
   986  		canQuery: true,
   987  		enter: func(net *Network, n *Node) {
   988  			net.ping(n, n.addr())
   989  		},
   990  		handle: func(net *Network, n *Node, ev nodeEvent, pkt *ingressPacket) (*nodeState, error) {
   991  			switch ev {
   992  			case pongPacket:
   993  //节点仍处于活动状态。
   994  				err := net.handleKnownPong(n, pkt)
   995  				return known, err
   996  			case pongTimeout:
   997  				net.tab.deleteReplace(n)
   998  				return unresponsive, nil
   999  			case pingPacket:
  1000  				net.handlePing(n, pkt)
  1001  				return contested, nil
  1002  			default:
  1003  				return net.handleQueryEvent(n, ev, pkt)
  1004  			}
  1005  		},
  1006  	}
  1007  
  1008  	unresponsive = &nodeState{
  1009  		name:     "unresponsive",
  1010  		canQuery: true,
  1011  		handle: func(net *Network, n *Node, ev nodeEvent, pkt *ingressPacket) (*nodeState, error) {
  1012  			switch ev {
  1013  			case pingPacket:
  1014  				net.handlePing(n, pkt)
  1015  				return known, nil
  1016  			case pongPacket:
  1017  				err := net.handleKnownPong(n, pkt)
  1018  				return known, err
  1019  			default:
  1020  				return net.handleQueryEvent(n, ev, pkt)
  1021  			}
  1022  		},
  1023  	}
  1024  }
  1025  
  1026  //处理由n发送的包和与n相关的事件。
  1027  func (net *Network) handle(n *Node, ev nodeEvent, pkt *ingressPacket) error {
  1028  //fmt.println(“handle”,n.addr().string(),n.state,ev)
  1029  	if pkt != nil {
  1030  		if err := net.checkPacket(n, ev, pkt); err != nil {
  1031  //fmt.println(“检查错误:”,err)
  1032  			return err
  1033  		}
  1034  //在第一个到期之后启动后台到期goroutine
  1035  //沟通成功。如果后续调用
  1036  //已经在运行。我们在这里而不是其他地方做这个
  1037  //因此搜索种子节点也会考虑较旧的节点
  1038  //否则将由到期人删除。
  1039  		if net.db != nil {
  1040  			net.db.ensureExpirer()
  1041  		}
  1042  	}
  1043  	if n.state == nil {
  1044  n.state = unknown //????
  1045  	}
  1046  	next, err := n.state.handle(net, n, ev, pkt)
  1047  	net.transition(n, next)
  1048  //fmt.println(“新状态:”,n.state)
  1049  	return err
  1050  }
  1051  
  1052  func (net *Network) checkPacket(n *Node, ev nodeEvent, pkt *ingressPacket) error {
  1053  //重播预防检查。
  1054  	switch ev {
  1055  	case pingPacket, findnodeHashPacket, neighborsPacket:
  1056  //TODO:检查日期>看到的最后一个日期
  1057  //TODO:检查ping版本
  1058  	case pongPacket:
  1059  		if !bytes.Equal(pkt.data.(*pong).ReplyTok, n.pingEcho) {
  1060  //fmt.println(“pong reply token mismatch”)。
  1061  			return fmt.Errorf("pong reply token mismatch")
  1062  		}
  1063  		n.pingEcho = nil
  1064  	}
  1065  //地址验证。
  1066  //托多:理想情况下,我们将执行以下操作:
  1067  //-拒绝所有地址错误的数据包,ping除外。
  1068  //-对于使用新地址的ping,转换到verifywait,但保留
  1069  //上一个节点(带旧地址)周围。如果新的发现,
  1070  //把它换出来。
  1071  	return nil
  1072  }
  1073  
  1074  func (net *Network) transition(n *Node, next *nodeState) {
  1075  	if n.state != next {
  1076  		n.state = next
  1077  		if next.enter != nil {
  1078  			next.enter(net, n)
  1079  		}
  1080  	}
  1081  
  1082  //TODO:持久/非持久节点
  1083  }
  1084  
  1085  func (net *Network) timedEvent(d time.Duration, n *Node, ev nodeEvent) {
  1086  	timeout := timeoutEvent{ev, n}
  1087  	net.timeoutTimers[timeout] = time.AfterFunc(d, func() {
  1088  		select {
  1089  		case net.timeout <- timeout:
  1090  		case <-net.closed:
  1091  		}
  1092  	})
  1093  }
  1094  
  1095  func (net *Network) abortTimedEvent(n *Node, ev nodeEvent) {
  1096  	timer := net.timeoutTimers[timeoutEvent{ev, n}]
  1097  	if timer != nil {
  1098  		timer.Stop()
  1099  		delete(net.timeoutTimers, timeoutEvent{ev, n})
  1100  	}
  1101  }
  1102  
  1103  func (net *Network) ping(n *Node, addr *net.UDPAddr) {
  1104  //fmt.println(“ping”,n.addr().string(),n.id.string(),n.sha.hex())
  1105  	if n.pingEcho != nil || n.ID == net.tab.self.ID {
  1106  //fmt.println(“未发送”)
  1107  		return
  1108  	}
  1109  	log.Trace("Pinging remote node", "node", n.ID)
  1110  	n.pingTopics = net.ticketStore.regTopicSet()
  1111  	n.pingEcho = net.conn.sendPing(n, addr, n.pingTopics)
  1112  	net.timedEvent(respTimeout, n, pongTimeout)
  1113  }
  1114  
  1115  func (net *Network) handlePing(n *Node, pkt *ingressPacket) {
  1116  	log.Trace("Handling remote ping", "node", n.ID)
  1117  	ping := pkt.data.(*ping)
  1118  	n.TCP = ping.From.TCP
  1119  	t := net.topictab.getTicket(n, ping.Topics)
  1120  
  1121  	pong := &pong{
  1122  To:         makeEndpoint(n.addr(), n.TCP), //TODO:可能使用数据库中已知的TCP端口
  1123  		ReplyTok:   pkt.hash,
  1124  		Expiration: uint64(time.Now().Add(expiration).Unix()),
  1125  	}
  1126  	ticketToPong(t, pong)
  1127  	net.conn.send(n, pongPacket, pong)
  1128  }
  1129  
  1130  func (net *Network) handleKnownPong(n *Node, pkt *ingressPacket) error {
  1131  	log.Trace("Handling known pong", "node", n.ID)
  1132  	net.abortTimedEvent(n, pongTimeout)
  1133  	now := mclock.Now()
  1134  	ticket, err := pongToTicket(now, n.pingTopics, n, pkt)
  1135  	if err == nil {
  1136  //fmt.printf(“(%x)票据:%+v\n”,net.tab.self.id[:8],pkt.data)
  1137  		net.ticketStore.addTicket(now, pkt.data.(*pong).ReplyTok, ticket)
  1138  	} else {
  1139  		log.Trace("Failed to convert pong to ticket", "err", err)
  1140  	}
  1141  	n.pingEcho = nil
  1142  	n.pingTopics = nil
  1143  	return err
  1144  }
  1145  
  1146  func (net *Network) handleQueryEvent(n *Node, ev nodeEvent, pkt *ingressPacket) (*nodeState, error) {
  1147  	switch ev {
  1148  	case findnodePacket:
  1149  		target := crypto.Keccak256Hash(pkt.data.(*findnode).Target[:])
  1150  		results := net.tab.closest(target, bucketSize).entries
  1151  		net.conn.sendNeighbours(n, results)
  1152  		return n.state, nil
  1153  	case neighborsPacket:
  1154  		err := net.handleNeighboursPacket(n, pkt)
  1155  		return n.state, err
  1156  	case neighboursTimeout:
  1157  		if n.pendingNeighbours != nil {
  1158  			n.pendingNeighbours.reply <- nil
  1159  			n.pendingNeighbours = nil
  1160  		}
  1161  		n.queryTimeouts++
  1162  		if n.queryTimeouts > maxFindnodeFailures && n.state == known {
  1163  			return contested, errors.New("too many timeouts")
  1164  		}
  1165  		return n.state, nil
  1166  
  1167  //V5
  1168  
  1169  	case findnodeHashPacket:
  1170  		results := net.tab.closest(pkt.data.(*findnodeHash).Target, bucketSize).entries
  1171  		net.conn.sendNeighbours(n, results)
  1172  		return n.state, nil
  1173  	case topicRegisterPacket:
  1174  //fmt.println(“获取到MicroregisterPacket”)
  1175  		regdata := pkt.data.(*topicRegister)
  1176  		pong, err := net.checkTopicRegister(regdata)
  1177  		if err != nil {
  1178  //fmt.println(错误)
  1179  			return n.state, fmt.Errorf("bad waiting ticket: %v", err)
  1180  		}
  1181  		net.topictab.useTicket(n, pong.TicketSerial, regdata.Topics, int(regdata.Idx), pong.Expiration, pong.WaitPeriods)
  1182  		return n.state, nil
  1183  	case topicQueryPacket:
  1184  //TODO:句柄过期
  1185  		topic := pkt.data.(*topicQuery).Topic
  1186  		results := net.topictab.getEntries(topic)
  1187  		if _, ok := net.ticketStore.tickets[topic]; ok {
  1188  results = append(results, net.tab.self) //我们没有在自己的桌子上登记,但如果我们在做广告,也要把自己还给我们自己。
  1189  		}
  1190  		if len(results) > 10 {
  1191  			results = results[:10]
  1192  		}
  1193  		var hash common.Hash
  1194  		copy(hash[:], pkt.hash)
  1195  		net.conn.sendTopicNodes(n, hash, results)
  1196  		return n.state, nil
  1197  	case topicNodesPacket:
  1198  		p := pkt.data.(*topicNodes)
  1199  		if net.ticketStore.gotTopicNodes(n, p.Echo, p.Nodes) {
  1200  			n.queryTimeouts++
  1201  			if n.queryTimeouts > maxFindnodeFailures && n.state == known {
  1202  				return contested, errors.New("too many timeouts")
  1203  			}
  1204  		}
  1205  		return n.state, nil
  1206  
  1207  	default:
  1208  		return n.state, errInvalidEvent
  1209  	}
  1210  }
  1211  
  1212  func (net *Network) checkTopicRegister(data *topicRegister) (*pong, error) {
  1213  	var pongpkt ingressPacket
  1214  	if err := decodePacket(data.Pong, &pongpkt); err != nil {
  1215  		return nil, err
  1216  	}
  1217  	if pongpkt.ev != pongPacket {
  1218  		return nil, errors.New("is not pong packet")
  1219  	}
  1220  	if pongpkt.remoteID != net.tab.self.ID {
  1221  		return nil, errors.New("not signed by us")
  1222  	}
  1223  //检查我们以前授权的所有主题
  1224  //对方正在尝试注册。
  1225  	if rlpHash(data.Topics) != pongpkt.data.(*pong).TopicHash {
  1226  		return nil, errors.New("topic hash mismatch")
  1227  	}
  1228  	if int(data.Idx) < 0 || int(data.Idx) >= len(data.Topics) {
  1229  		return nil, errors.New("topic index out of range")
  1230  	}
  1231  	return pongpkt.data.(*pong), nil
  1232  }
  1233  
  1234  func rlpHash(x interface{}) (h common.Hash) {
  1235  	hw := sha3.NewKeccak256()
  1236  	rlp.Encode(hw, x)
  1237  	hw.Sum(h[:0])
  1238  	return h
  1239  }
  1240  
  1241  func (net *Network) handleNeighboursPacket(n *Node, pkt *ingressPacket) error {
  1242  	if n.pendingNeighbours == nil {
  1243  		return errNoQuery
  1244  	}
  1245  	net.abortTimedEvent(n, neighboursTimeout)
  1246  
  1247  	req := pkt.data.(*neighbors)
  1248  	nodes := make([]*Node, len(req.Nodes))
  1249  	for i, rn := range req.Nodes {
  1250  		nn, err := net.internNodeFromNeighbours(pkt.remoteAddr, rn)
  1251  		if err != nil {
  1252  			log.Debug(fmt.Sprintf("invalid neighbour (%v) from %x@%v: %v", rn.IP, n.ID[:8], pkt.remoteAddr, err))
  1253  			continue
  1254  		}
  1255  		nodes[i] = nn
  1256  //立即开始验证查询结果。
  1257  //这很快就填满了桌子。
  1258  //TODO:生成的数据包太多,可能是通过队列生成的。
  1259  		if nn.state == unknown {
  1260  			net.transition(nn, verifyinit)
  1261  		}
  1262  	}
  1263  //TODO:不要忽略第二个数据包
  1264  	n.pendingNeighbours.reply <- nodes
  1265  	n.pendingNeighbours = nil
  1266  //既然这个查询完成了,就开始下一个查询。
  1267  	n.startNextQuery(net)
  1268  	return nil
  1269  }
  1270