github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/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 12:09:47</date> 10 //</624342672609382400> 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/discover" 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][]discover.NodeID 38 kademlias map[discover.NodeID]*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][]discover.NodeID) 71 //设置网络并连接节点 72 net, err := setupNetwork(numNodes) 73 if err != nil { 74 t.Fatalf("Error setting up network: %v", err) 75 } 76 defer func() { 77 //关闭快照网络 78 log.Trace("Shutting down network") 79 net.Shutdown() 80 }() 81 //让我们休眠以确保所有节点都已连接 82 time.Sleep(1 * time.Second) 83 //对于共享相同网络ID的每个组… 84 for _, netIDGroup := range nodeMap { 85 log.Trace("netIDGroup size", "size", len(netIDGroup)) 86 //…检查他们的花冠尺寸是否符合预期尺寸 87 //假设它应该是组的大小减去1(节点本身)。 88 for _, node := range netIDGroup { 89 if kademlias[node].addrs.Size() != len(netIDGroup)-1 { 90 t.Fatalf("Kademlia size has not expected peer size. Kademlia size: %d, expected size: %d", kademlias[node].addrs.Size(), len(netIDGroup)-1) 91 } 92 kademlias[node].EachAddr(nil, 0, func(addr OverlayAddr, _ int, _ bool) bool { 93 found := false 94 for _, nd := range netIDGroup { 95 p := ToOverlayAddr(nd.Bytes()) 96 if bytes.Equal(p, addr.Address()) { 97 found = true 98 } 99 } 100 if !found { 101 t.Fatalf("Expected node not found for node %s", node.String()) 102 } 103 return true 104 }) 105 } 106 } 107 log.Info("Test terminated successfully") 108 } 109 110 //使用bzz/discovery和pss服务设置模拟网络。 111 //连接圆中的节点 112 //如果设置了allowraw,则启用了省略内置PSS加密(请参阅PSSPARAMS) 113 func setupNetwork(numnodes int) (net *simulations.Network, err error) { 114 log.Debug("Setting up network") 115 quitC := make(chan struct{}) 116 errc := make(chan error) 117 nodes := make([]*simulations.Node, numnodes) 118 if numnodes < 16 { 119 return nil, fmt.Errorf("Minimum sixteen nodes in network") 120 } 121 adapter := adapters.NewSimAdapter(newServices()) 122 //创建网络 123 net = simulations.NewNetwork(adapter, &simulations.NetworkConfig{ 124 ID: "NetworkIdTestNet", 125 DefaultService: "bzz", 126 }) 127 log.Debug("Creating networks and nodes") 128 129 var connCount int 130 131 //创建节点并相互连接 132 for i := 0; i < numnodes; i++ { 133 log.Trace("iteration: ", "i", i) 134 nodeconf := adapters.RandomNodeConfig() 135 nodes[i], err = net.NewNodeWithConfig(nodeconf) 136 if err != nil { 137 return nil, fmt.Errorf("error creating node %d: %v", i, err) 138 } 139 err = net.Start(nodes[i].ID()) 140 if err != nil { 141 return nil, fmt.Errorf("error starting node %d: %v", i, err) 142 } 143 client, err := nodes[i].Client() 144 if err != nil { 145 return nil, fmt.Errorf("create node %d rpc client fail: %v", i, err) 146 } 147 //现在设置并开始事件监视,以了解何时可以上载 148 ctx, watchCancel := context.WithTimeout(context.Background(), MaxTimeout*time.Second) 149 defer watchCancel() 150 watchSubscriptionEvents(ctx, nodes[i].ID(), client, errc, quitC) 151 //在每次迭代中,我们都连接到以前的所有迭代 152 for k := i - 1; k >= 0; k-- { 153 connCount++ 154 log.Debug(fmt.Sprintf("Connecting node %d with node %d; connection count is %d", i, k, connCount)) 155 err = net.Connect(nodes[i].ID(), nodes[k].ID()) 156 if err != nil { 157 if !strings.Contains(err.Error(), "already connected") { 158 return nil, fmt.Errorf("error connecting nodes: %v", err) 159 } 160 } 161 } 162 } 163 //现在等待,直到完成预期订阅的数量 164 //`watchsubscriptionEvents`将用'nil'值写入errc 165 for err := range errc { 166 if err != nil { 167 return nil, err 168 } 169 //收到“nil”,递减计数 170 connCount-- 171 log.Trace("count down", "cnt", connCount) 172 //收到的所有订阅 173 if connCount == 0 { 174 close(quitC) 175 break 176 } 177 } 178 log.Debug("Network setup phase terminated") 179 return net, nil 180 } 181 182 func newServices() adapters.Services { 183 kademlias = make(map[discover.NodeID]*Kademlia) 184 kademlia := func(id discover.NodeID) *Kademlia { 185 if k, ok := kademlias[id]; ok { 186 return k 187 } 188 addr := NewAddrFromNodeID(id) 189 params := NewKadParams() 190 params.MinProxBinSize = 2 191 params.MaxBinSize = 3 192 params.MinBinSize = 1 193 params.MaxRetries = 1000 194 params.RetryExponent = 2 195 params.RetryInterval = 1000000 196 kademlias[id] = NewKademlia(addr.Over(), params) 197 return kademlias[id] 198 } 199 return adapters.Services{ 200 "bzz": func(ctx *adapters.ServiceContext) (node.Service, error) { 201 addr := NewAddrFromNodeID(ctx.Config.ID) 202 hp := NewHiveParams() 203 hp.Discovery = false 204 cnt++ 205 //分配网络ID 206 currentNetworkID = cnt % NumberOfNets 207 if ok := nodeMap[currentNetworkID]; ok == nil { 208 nodeMap[currentNetworkID] = make([]discover.NodeID, 0) 209 } 210 //将此节点添加到共享相同网络ID的组中 211 nodeMap[currentNetworkID] = append(nodeMap[currentNetworkID], ctx.Config.ID) 212 log.Debug("current network ID:", "id", currentNetworkID) 213 config := &BzzConfig{ 214 OverlayAddr: addr.Over(), 215 UnderlayAddr: addr.Under(), 216 HiveParams: hp, 217 NetworkID: uint64(currentNetworkID), 218 } 219 return NewBzz(config, kademlia(ctx.Config.ID), nil, nil, nil), nil 220 }, 221 } 222 } 223 224 func watchSubscriptionEvents(ctx context.Context, id discover.NodeID, client *rpc.Client, errc chan error, quitC chan struct{}) { 225 events := make(chan *p2p.PeerEvent) 226 sub, err := client.Subscribe(context.Background(), "admin", events, "peerEvents") 227 if err != nil { 228 log.Error(err.Error()) 229 errc <- fmt.Errorf("error getting peer events for node %v: %s", id, err) 230 return 231 } 232 go func() { 233 defer func() { 234 sub.Unsubscribe() 235 log.Trace("watch subscription events: unsubscribe", "id", id) 236 }() 237 238 for { 239 select { 240 case <-quitC: 241 return 242 case <-ctx.Done(): 243 select { 244 case errc <- ctx.Err(): 245 case <-quitC: 246 } 247 return 248 case e := <-events: 249 if e.Type == p2p.PeerEventTypeAdd { 250 errc <- nil 251 } 252 case err := <-sub.Err(): 253 if err != nil { 254 select { 255 case errc <- fmt.Errorf("error getting peer events for node %v: %v", id, err): 256 case <-quitC: 257 } 258 return 259 } 260 } 261 } 262 }() 263 } 264