github.com/FUSIONFoundation/efsn@v3.6.2-0.20200916075423-dbb5dd5d2cc7+incompatible/swarm/network/networkid_test.go (about) 1 // Copyright 2018 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 network 18 19 import ( 20 "bytes" 21 "context" 22 "flag" 23 "fmt" 24 "math/rand" 25 "strings" 26 "testing" 27 "time" 28 29 "github.com/FusionFoundation/efsn/log" 30 "github.com/FusionFoundation/efsn/node" 31 "github.com/FusionFoundation/efsn/p2p" 32 "github.com/FusionFoundation/efsn/p2p/discover" 33 "github.com/FusionFoundation/efsn/p2p/simulations" 34 "github.com/FusionFoundation/efsn/p2p/simulations/adapters" 35 "github.com/FusionFoundation/efsn/rpc" 36 ) 37 38 var ( 39 currentNetworkID int 40 cnt int 41 nodeMap map[int][]discover.NodeID 42 kademlias map[discover.NodeID]*Kademlia 43 ) 44 45 const ( 46 NumberOfNets = 4 47 MaxTimeout = 6 48 ) 49 50 func init() { 51 flag.Parse() 52 rand.Seed(time.Now().Unix()) 53 } 54 55 /* 56 Run the network ID test. 57 The test creates one simulations.Network instance, 58 a number of nodes, then connects nodes with each other in this network. 59 60 Each node gets a network ID assigned according to the number of networks. 61 Having more network IDs is just arbitrary in order to exclude 62 false positives. 63 64 Nodes should only connect with other nodes with the same network ID. 65 After the setup phase, the test checks on each node if it has the 66 expected node connections (excluding those not sharing the network ID). 67 */ 68 func TestNetworkID(t *testing.T) { 69 log.Debug("Start test") 70 //arbitrarily set the number of nodes. It could be any number 71 numNodes := 24 72 //the nodeMap maps all nodes (slice value) with the same network ID (key) 73 nodeMap = make(map[int][]discover.NodeID) 74 //set up the network and connect nodes 75 net, err := setupNetwork(numNodes) 76 if err != nil { 77 t.Fatalf("Error setting up network: %v", err) 78 } 79 defer func() { 80 //shutdown the snapshot network 81 log.Trace("Shutting down network") 82 net.Shutdown() 83 }() 84 //let's sleep to ensure all nodes are connected 85 time.Sleep(1 * time.Second) 86 //for each group sharing the same network ID... 87 for _, netIDGroup := range nodeMap { 88 log.Trace("netIDGroup size", "size", len(netIDGroup)) 89 //...check that their size of the kademlia is of the expected size 90 //the assumption is that it should be the size of the group minus 1 (the node itself) 91 for _, node := range netIDGroup { 92 if kademlias[node].addrs.Size() != len(netIDGroup)-1 { 93 t.Fatalf("Kademlia size has not expected peer size. Kademlia size: %d, expected size: %d", kademlias[node].addrs.Size(), len(netIDGroup)-1) 94 } 95 kademlias[node].EachAddr(nil, 0, func(addr *BzzAddr, _ int, _ bool) bool { 96 found := false 97 for _, nd := range netIDGroup { 98 p := ToOverlayAddr(nd.Bytes()) 99 if bytes.Equal(p, addr.Address()) { 100 found = true 101 } 102 } 103 if !found { 104 t.Fatalf("Expected node not found for node %s", node.String()) 105 } 106 return true 107 }) 108 } 109 } 110 log.Info("Test terminated successfully") 111 } 112 113 // setup simulated network with bzz/discovery and pss services. 114 // connects nodes in a circle 115 // if allowRaw is set, omission of builtin pss encryption is enabled (see PssParams) 116 func setupNetwork(numnodes int) (net *simulations.Network, err error) { 117 log.Debug("Setting up network") 118 quitC := make(chan struct{}) 119 errc := make(chan error) 120 nodes := make([]*simulations.Node, numnodes) 121 if numnodes < 16 { 122 return nil, fmt.Errorf("Minimum sixteen nodes in network") 123 } 124 adapter := adapters.NewSimAdapter(newServices()) 125 //create the network 126 net = simulations.NewNetwork(adapter, &simulations.NetworkConfig{ 127 ID: "NetworkIdTestNet", 128 DefaultService: "bzz", 129 }) 130 log.Debug("Creating networks and nodes") 131 132 var connCount int 133 134 //create nodes and connect them to each other 135 for i := 0; i < numnodes; i++ { 136 log.Trace("iteration: ", "i", i) 137 nodeconf := adapters.RandomNodeConfig() 138 nodes[i], err = net.NewNodeWithConfig(nodeconf) 139 if err != nil { 140 return nil, fmt.Errorf("error creating node %d: %v", i, err) 141 } 142 err = net.Start(nodes[i].ID()) 143 if err != nil { 144 return nil, fmt.Errorf("error starting node %d: %v", i, err) 145 } 146 client, err := nodes[i].Client() 147 if err != nil { 148 return nil, fmt.Errorf("create node %d rpc client fail: %v", i, err) 149 } 150 //now setup and start event watching in order to know when we can upload 151 ctx, watchCancel := context.WithTimeout(context.Background(), MaxTimeout*time.Second) 152 defer watchCancel() 153 watchSubscriptionEvents(ctx, nodes[i].ID(), client, errc, quitC) 154 //on every iteration we connect to all previous ones 155 for k := i - 1; k >= 0; k-- { 156 connCount++ 157 log.Debug(fmt.Sprintf("Connecting node %d with node %d; connection count is %d", i, k, connCount)) 158 err = net.Connect(nodes[i].ID(), nodes[k].ID()) 159 if err != nil { 160 if !strings.Contains(err.Error(), "already connected") { 161 return nil, fmt.Errorf("error connecting nodes: %v", err) 162 } 163 } 164 } 165 } 166 //now wait until the number of expected subscriptions has been finished 167 //`watchSubscriptionEvents` will write with a `nil` value to errc 168 for err := range errc { 169 if err != nil { 170 return nil, err 171 } 172 //`nil` received, decrement count 173 connCount-- 174 log.Trace("count down", "cnt", connCount) 175 //all subscriptions received 176 if connCount == 0 { 177 close(quitC) 178 break 179 } 180 } 181 log.Debug("Network setup phase terminated") 182 return net, nil 183 } 184 185 func newServices() adapters.Services { 186 kademlias = make(map[discover.NodeID]*Kademlia) 187 kademlia := func(id discover.NodeID) *Kademlia { 188 if k, ok := kademlias[id]; ok { 189 return k 190 } 191 addr := NewAddrFromNodeID(id) 192 params := NewKadParams() 193 params.MinProxBinSize = 2 194 params.MaxBinSize = 3 195 params.MinBinSize = 1 196 params.MaxRetries = 1000 197 params.RetryExponent = 2 198 params.RetryInterval = 1000000 199 kademlias[id] = NewKademlia(addr.Over(), params) 200 return kademlias[id] 201 } 202 return adapters.Services{ 203 "bzz": func(ctx *adapters.ServiceContext) (node.Service, error) { 204 addr := NewAddrFromNodeID(ctx.Config.ID) 205 hp := NewHiveParams() 206 hp.Discovery = false 207 cnt++ 208 //assign the network ID 209 currentNetworkID = cnt % NumberOfNets 210 if ok := nodeMap[currentNetworkID]; ok == nil { 211 nodeMap[currentNetworkID] = make([]discover.NodeID, 0) 212 } 213 //add this node to the group sharing the same network ID 214 nodeMap[currentNetworkID] = append(nodeMap[currentNetworkID], ctx.Config.ID) 215 log.Debug("current network ID:", "id", currentNetworkID) 216 config := &BzzConfig{ 217 OverlayAddr: addr.Over(), 218 UnderlayAddr: addr.Under(), 219 HiveParams: hp, 220 NetworkID: uint64(currentNetworkID), 221 } 222 return NewBzz(config, kademlia(ctx.Config.ID), nil, nil, nil), nil 223 }, 224 } 225 } 226 227 func watchSubscriptionEvents(ctx context.Context, id discover.NodeID, client *rpc.Client, errc chan error, quitC chan struct{}) { 228 events := make(chan *p2p.PeerEvent) 229 sub, err := client.Subscribe(context.Background(), "admin", events, "peerEvents") 230 if err != nil { 231 log.Error(err.Error()) 232 errc <- fmt.Errorf("error getting peer events for node %v: %s", id, err) 233 return 234 } 235 go func() { 236 defer func() { 237 sub.Unsubscribe() 238 log.Trace("watch subscription events: unsubscribe", "id", id) 239 }() 240 241 for { 242 select { 243 case <-quitC: 244 return 245 case <-ctx.Done(): 246 select { 247 case errc <- ctx.Err(): 248 case <-quitC: 249 } 250 return 251 case e := <-events: 252 if e.Type == p2p.PeerEventTypeAdd { 253 errc <- nil 254 } 255 case err := <-sub.Err(): 256 if err != nil { 257 select { 258 case errc <- fmt.Errorf("error getting peer events for node %v: %v", id, err): 259 case <-quitC: 260 } 261 return 262 } 263 } 264 } 265 }() 266 }