github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/network/networkid_test.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 19:16:43</date> 10 //</624450113946783744> 11 12 13 package network 14 15 import ( 16 "bytes" 17 "context" 18 "flag" 19 "fmt" 20 "math/rand" 21 "strings" 22 "testing" 23 "time" 24 25 "github.com/ethereum/go-ethereum/log" 26 "github.com/ethereum/go-ethereum/node" 27 "github.com/ethereum/go-ethereum/p2p" 28 "github.com/ethereum/go-ethereum/p2p/enode" 29 "github.com/ethereum/go-ethereum/p2p/simulations" 30 "github.com/ethereum/go-ethereum/p2p/simulations/adapters" 31 "github.com/ethereum/go-ethereum/rpc" 32 ) 33 34 var ( 35 currentNetworkID int 36 cnt int 37 nodeMap map[int][]enode.ID 38 kademlias map[enode.ID]*Kademlia 39 ) 40 41 const ( 42 NumberOfNets = 4 43 MaxTimeout = 6 44 ) 45 46 func init() { 47 flag.Parse() 48 rand.Seed(time.Now().Unix()) 49 } 50 51 /* 52 运行网络ID测试。 53 测试创建一个模拟。网络实例, 54 多个节点,然后在此网络中彼此连接节点。 55 56 每个节点都得到一个根据网络数量分配的网络ID。 57 拥有更多的网络ID只是为了排除 58 误报。 59 60 节点只能与具有相同网络ID的其他节点连接。 61 在设置阶段之后,测试将检查每个节点是否具有 62 预期的节点连接(不包括那些不共享网络ID的连接)。 63 **/ 64 65 func TestNetworkID(t *testing.T) { 66 log.Debug("Start test") 67 //任意设置节点数。可以是任何号码 68 numNodes := 24 69 //nodemap用相同的网络ID(key)映射所有节点(切片值) 70 nodeMap = make(map[int][]enode.ID) 71 //设置网络并连接节点 72 net, err := setupNetwork(numNodes) 73 if err != nil { 74 t.Fatalf("Error setting up network: %v", err) 75 } 76 //让我们休眠以确保所有节点都已连接 77 time.Sleep(1 * time.Second) 78 //关闭网络以避免竞争条件 79 //网络节点访问Kademlias全局地图的研究 80 //正在接受消息 81 net.Shutdown() 82 //对于共享相同网络ID的每个组… 83 for _, netIDGroup := range nodeMap { 84 log.Trace("netIDGroup size", "size", len(netIDGroup)) 85 //…检查他们的花冠尺寸是否符合预期尺寸 86 //假设它应该是组的大小减去1(节点本身)。 87 for _, node := range netIDGroup { 88 if kademlias[node].addrs.Size() != len(netIDGroup)-1 { 89 t.Fatalf("Kademlia size has not expected peer size. Kademlia size: %d, expected size: %d", kademlias[node].addrs.Size(), len(netIDGroup)-1) 90 } 91 kademlias[node].EachAddr(nil, 0, func(addr *BzzAddr, _ int) bool { 92 found := false 93 for _, nd := range netIDGroup { 94 if bytes.Equal(kademlias[nd].BaseAddr(), addr.Address()) { 95 found = true 96 } 97 } 98 if !found { 99 t.Fatalf("Expected node not found for node %s", node.String()) 100 } 101 return true 102 }) 103 } 104 } 105 log.Info("Test terminated successfully") 106 } 107 108 //使用bzz/discovery和pss服务设置模拟网络。 109 //连接圆中的节点 110 //如果设置了allowraw,则启用了省略内置PSS加密(请参阅PSSPARAMS) 111 func setupNetwork(numnodes int) (net *simulations.Network, err error) { 112 log.Debug("Setting up network") 113 quitC := make(chan struct{}) 114 errc := make(chan error) 115 nodes := make([]*simulations.Node, numnodes) 116 if numnodes < 16 { 117 return nil, fmt.Errorf("Minimum sixteen nodes in network") 118 } 119 adapter := adapters.NewSimAdapter(newServices()) 120 //创建网络 121 net = simulations.NewNetwork(adapter, &simulations.NetworkConfig{ 122 ID: "NetworkIdTestNet", 123 DefaultService: "bzz", 124 }) 125 log.Debug("Creating networks and nodes") 126 127 var connCount int 128 129 //创建节点并相互连接 130 for i := 0; i < numnodes; i++ { 131 log.Trace("iteration: ", "i", i) 132 nodeconf := adapters.RandomNodeConfig() 133 nodes[i], err = net.NewNodeWithConfig(nodeconf) 134 if err != nil { 135 return nil, fmt.Errorf("error creating node %d: %v", i, err) 136 } 137 err = net.Start(nodes[i].ID()) 138 if err != nil { 139 return nil, fmt.Errorf("error starting node %d: %v", i, err) 140 } 141 client, err := nodes[i].Client() 142 if err != nil { 143 return nil, fmt.Errorf("create node %d rpc client fail: %v", i, err) 144 } 145 //现在设置并开始事件监视,以了解何时可以上载 146 ctx, watchCancel := context.WithTimeout(context.Background(), MaxTimeout*time.Second) 147 defer watchCancel() 148 watchSubscriptionEvents(ctx, nodes[i].ID(), client, errc, quitC) 149 //在每次迭代中,我们都连接到以前的所有迭代 150 for k := i - 1; k >= 0; k-- { 151 connCount++ 152 log.Debug(fmt.Sprintf("Connecting node %d with node %d; connection count is %d", i, k, connCount)) 153 err = net.Connect(nodes[i].ID(), nodes[k].ID()) 154 if err != nil { 155 if !strings.Contains(err.Error(), "already connected") { 156 return nil, fmt.Errorf("error connecting nodes: %v", err) 157 } 158 } 159 } 160 } 161 //现在等待,直到完成预期订阅的数量 162 //`watchsubscriptionEvents`将用'nil'值写入errc 163 for err := range errc { 164 if err != nil { 165 return nil, err 166 } 167 //收到“nil”,递减计数 168 connCount-- 169 log.Trace("count down", "cnt", connCount) 170 //收到的所有订阅 171 if connCount == 0 { 172 close(quitC) 173 break 174 } 175 } 176 log.Debug("Network setup phase terminated") 177 return net, nil 178 } 179 180 func newServices() adapters.Services { 181 kademlias = make(map[enode.ID]*Kademlia) 182 kademlia := func(id enode.ID) *Kademlia { 183 if k, ok := kademlias[id]; ok { 184 return k 185 } 186 params := NewKadParams() 187 params.NeighbourhoodSize = 2 188 params.MaxBinSize = 3 189 params.MinBinSize = 1 190 params.MaxRetries = 1000 191 params.RetryExponent = 2 192 params.RetryInterval = 1000000 193 kademlias[id] = NewKademlia(id[:], params) 194 return kademlias[id] 195 } 196 return adapters.Services{ 197 "bzz": func(ctx *adapters.ServiceContext) (node.Service, error) { 198 addr := NewAddr(ctx.Config.Node()) 199 hp := NewHiveParams() 200 hp.Discovery = false 201 cnt++ 202 //分配网络ID 203 currentNetworkID = cnt % NumberOfNets 204 if ok := nodeMap[currentNetworkID]; ok == nil { 205 nodeMap[currentNetworkID] = make([]enode.ID, 0) 206 } 207 //将此节点添加到共享相同网络ID的组中 208 nodeMap[currentNetworkID] = append(nodeMap[currentNetworkID], ctx.Config.ID) 209 log.Debug("current network ID:", "id", currentNetworkID) 210 config := &BzzConfig{ 211 OverlayAddr: addr.Over(), 212 UnderlayAddr: addr.Under(), 213 HiveParams: hp, 214 NetworkID: uint64(currentNetworkID), 215 } 216 return NewBzz(config, kademlia(ctx.Config.ID), nil, nil, nil), nil 217 }, 218 } 219 } 220 221 func watchSubscriptionEvents(ctx context.Context, id enode.ID, client *rpc.Client, errc chan error, quitC chan struct{}) { 222 events := make(chan *p2p.PeerEvent) 223 sub, err := client.Subscribe(context.Background(), "admin", events, "peerEvents") 224 if err != nil { 225 log.Error(err.Error()) 226 errc <- fmt.Errorf("error getting peer events for node %v: %s", id, err) 227 return 228 } 229 go func() { 230 defer func() { 231 sub.Unsubscribe() 232 log.Trace("watch subscription events: unsubscribe", "id", id) 233 }() 234 235 for { 236 select { 237 case <-quitC: 238 return 239 case <-ctx.Done(): 240 select { 241 case errc <- ctx.Err(): 242 case <-quitC: 243 } 244 return 245 case e := <-events: 246 if e.Type == p2p.PeerEventTypeAdd { 247 errc <- nil 248 } 249 case err := <-sub.Err(): 250 if err != nil { 251 select { 252 case errc <- fmt.Errorf("error getting peer events for node %v: %v", id, err): 253 case <-quitC: 254 } 255 return 256 } 257 } 258 } 259 }() 260 } 261