区块链网络的节点发现机制深入探讨

在startNode中,一旦本地主机创建完成,需要将其纳入到区块链网络(P2P网络),我们执行:

err = SetupDiscovery(ctx, host)

我们再次把此函数的的实现copy如下:

  1. // SetupDiscovery 建立发现机制,并将本地主机连接到所有已经发现的对等端(peer)
  2. func SetupDiscovery(ctx context.Context, host host.Host) error {
  3. // 开启一个DHT,用于对等端(peer)发现。
  4. // 我们不仅仅是创建一个新的DHT,因为我们要求每一个端维护它自己的本地DHT副本,这样
  5. // 以来,DHT的引导节点可以关闭,不会影响后续的对等端发现
  6. kademliaDHT, err := dht.New(ctx, host)
  7. if err != nil {
  8. panic(err)
  9. }
  10. // 引导DHT。在缺省设置下,这生成一个后台线程,每5分钟刷新对等端表格
  11. log.Info("引导DHT")
  12. if err = kademliaDHT.Bootstrap(ctx); err != nil {
  13. panic(err)
  14. }
  15. // 让我们首先连接到所有的引导节点(bootstrap nodes),它们会告诉我们网络中的其他节点
  16. var wg sync.WaitGroup
  17. for _, peerAddr := range dht.DefaultBootstrapPeers {
  18. peerinfo, _ := peer.AddrInfoFromP2pAddr(peerAddr)
  19. wg.Add(1)
  20. //使用多个协程,加快连接处理
  21. go func() {
  22. defer wg.Done()
  23. if err := host.Connect(ctx, *peerinfo); err != nil {
  24. log.Error(err)
  25. } else {
  26. log.Info("连接已建立,使用的引导节点是:", *peerinfo)
  27. }
  28. }()
  29. }
  30. wg.Wait()//阻塞,确保所有的协程全部返回
  31. // 我们使用一个会合点“wlsell.com”来宣布我们的位置
  32. // 这就像告诉你的朋友在某个具体的地点会合
  33. log.Info("宣布我们自己...")
  34. routingDiscovery := discovery.NewRoutingDiscovery(kademliaDHT)
  35. discovery.Advertise(ctx, routingDiscovery, "rendezvous:wlsell.com")
  36. log.Info("成功宣布!")
  37. // 现在,查找那些已经宣布的对等端
  38. // 这就像你的朋友告诉你会合的地点
  39. log.Info("搜索其它的对等端...")
  40. peerChan, err := routingDiscovery.FindPeers(ctx, "rendezvous:wlsell.com")
  41. if err != nil {
  42. panic(err)
  43. }
  44. // 连接到所有新发现的对等端(peer)
  45. for peer := range peerChan {
  46. if peer.ID == host.ID() {
  47. continue//不连接自己
  48. }
  49. log.Debug("找到对等端:", peer)
  50. log.Debug("正在连接到:", peer)
  51. err := host.Connect(context.Background(), peer)
  52. if err != nil {
  53. log.Warningf("连接到对等端 %s:失败 %s\\n", peer.ID.Pretty(), err)
  54. continue
  55. }
  56. log.Info("已经连接到:", peer)
  57. }
  58. return nil
  59. }