github.com/etsc3259/etsc@v0.0.0-20190109113336-a9c2c10f9c95/swarm/network/networkid_test.go (about) 1 // Copyright 2018 The go-etsc Authors 2 // This file is part of the go-etsc library. 3 // 4 // The go-etsc 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-etsc 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-etsc 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/ETSC3259/etsc/log" 30 "github.com/ETSC3259/etsc/node" 31 "github.com/ETSC3259/etsc/p2p" 32 "github.com/ETSC3259/etsc/p2p/enode" 33 "github.com/ETSC3259/etsc/p2p/simulations" 34 "github.com/ETSC3259/etsc/p2p/simulations/adapters" 35 "github.com/ETSC3259/etsc/rpc" 36 ) 37 38 var ( 39 currentNetworkID int 40 cnt int 41 nodeMap map[int][]enode.ID 42 kademlias map[enode.ID]*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][]enode.ID) 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 := 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[enode.ID]*Kademlia) 187 kademlia := func(id enode.ID) *Kademlia { 188 if k, ok := kademlias[id]; ok { 189 return k 190 } 191 params := NewKadParams() 192 params.MinProxBinSize = 2 193 params.MaxBinSize = 3 194 params.MinBinSize = 1 195 params.MaxRetries = 1000 196 params.RetryExponent = 2 197 params.RetryInterval = 1000000 198 kademlias[id] = NewKademlia(id[:], params) 199 return kademlias[id] 200 } 201 return adapters.Services{ 202 "bzz": func(ctx *adapters.ServiceContext) (node.Service, error) { 203 addr := NewAddr(ctx.Config.Node()) 204 hp := NewHiveParams() 205 hp.Discovery = false 206 cnt++ 207 //assign the network ID 208 currentNetworkID = cnt % NumberOfNets 209 if ok := nodeMap[currentNetworkID]; ok == nil { 210 nodeMap[currentNetworkID] = make([]enode.ID, 0) 211 } 212 //add this node to the group sharing the same network ID 213 nodeMap[currentNetworkID] = append(nodeMap[currentNetworkID], ctx.Config.ID) 214 log.Debug("current network ID:", "id", currentNetworkID) 215 config := &BzzConfig{ 216 OverlayAddr: addr.Over(), 217 UnderlayAddr: addr.Under(), 218 HiveParams: hp, 219 NetworkID: uint64(currentNetworkID), 220 } 221 return NewBzz(config, kademlia(ctx.Config.ID), nil, nil, nil), nil 222 }, 223 } 224 } 225 226 func watchSubscriptionEvents(ctx context.Context, id enode.ID, client *rpc.Client, errc chan error, quitC chan struct{}) { 227 events := make(chan *p2p.PeerEvent) 228 sub, err := client.Subscribe(context.Background(), "admin", events, "peerEvents") 229 if err != nil { 230 log.Error(err.Error()) 231 errc <- fmt.Errorf("error getting peer events for node %v: %s", id, err) 232 return 233 } 234 go func() { 235 defer func() { 236 sub.Unsubscribe() 237 log.Trace("watch subscription events: unsubscribe", "id", id) 238 }() 239 240 for { 241 select { 242 case <-quitC: 243 return 244 case <-ctx.Done(): 245 select { 246 case errc <- ctx.Err(): 247 case <-quitC: 248 } 249 return 250 case e := <-events: 251 if e.Type == p2p.PeerEventTypeAdd { 252 errc <- nil 253 } 254 case err := <-sub.Err(): 255 if err != nil { 256 select { 257 case errc <- fmt.Errorf("error getting peer events for node %v: %v", id, err): 258 case <-quitC: 259 } 260 return 261 } 262 } 263 } 264 }() 265 }