github.com/aswedchain/aswed@v1.0.1/p2p/simulations/network.go (about) 1 // Copyright 2017 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 simulations 18 19 import ( 20 "bytes" 21 "context" 22 "encoding/json" 23 "errors" 24 "fmt" 25 "io" 26 "math/rand" 27 "sync" 28 "time" 29 30 "github.com/aswedchain/aswed/event" 31 "github.com/aswedchain/aswed/log" 32 "github.com/aswedchain/aswed/p2p" 33 "github.com/aswedchain/aswed/p2p/enode" 34 "github.com/aswedchain/aswed/p2p/simulations/adapters" 35 ) 36 37 var DialBanTimeout = 200 * time.Millisecond 38 39 // NetworkConfig defines configuration options for starting a Network 40 type NetworkConfig struct { 41 ID string `json:"id"` 42 DefaultService string `json:"default_service,omitempty"` 43 } 44 45 // Network models a p2p simulation network which consists of a collection of 46 // simulated nodes and the connections which exist between them. 47 // 48 // The Network has a single NodeAdapter which is responsible for actually 49 // starting nodes and connecting them together. 50 // 51 // The Network emits events when nodes are started and stopped, when they are 52 // connected and disconnected, and also when messages are sent between nodes. 53 type Network struct { 54 NetworkConfig 55 56 Nodes []*Node `json:"nodes"` 57 nodeMap map[enode.ID]int 58 59 // Maps a node property string to node indexes of all nodes that hold this property 60 propertyMap map[string][]int 61 62 Conns []*Conn `json:"conns"` 63 connMap map[string]int 64 65 nodeAdapter adapters.NodeAdapter 66 events event.Feed 67 lock sync.RWMutex 68 quitc chan struct{} 69 } 70 71 // NewNetwork returns a Network which uses the given NodeAdapter and NetworkConfig 72 func NewNetwork(nodeAdapter adapters.NodeAdapter, conf *NetworkConfig) *Network { 73 return &Network{ 74 NetworkConfig: *conf, 75 nodeAdapter: nodeAdapter, 76 nodeMap: make(map[enode.ID]int), 77 propertyMap: make(map[string][]int), 78 connMap: make(map[string]int), 79 quitc: make(chan struct{}), 80 } 81 } 82 83 // Events returns the output event feed of the Network. 84 func (net *Network) Events() *event.Feed { 85 return &net.events 86 } 87 88 // NewNodeWithConfig adds a new node to the network with the given config, 89 // returning an error if a node with the same ID or name already exists 90 func (net *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error) { 91 net.lock.Lock() 92 defer net.lock.Unlock() 93 94 if conf.Reachable == nil { 95 conf.Reachable = func(otherID enode.ID) bool { 96 _, err := net.InitConn(conf.ID, otherID) 97 if err != nil && bytes.Compare(conf.ID.Bytes(), otherID.Bytes()) < 0 { 98 return false 99 } 100 return true 101 } 102 } 103 104 // check the node doesn't already exist 105 if node := net.getNode(conf.ID); node != nil { 106 return nil, fmt.Errorf("node with ID %q already exists", conf.ID) 107 } 108 if node := net.getNodeByName(conf.Name); node != nil { 109 return nil, fmt.Errorf("node with name %q already exists", conf.Name) 110 } 111 112 // if no services are configured, use the default service 113 if len(conf.Lifecycles) == 0 { 114 conf.Lifecycles = []string{net.DefaultService} 115 } 116 117 // use the NodeAdapter to create the node 118 adapterNode, err := net.nodeAdapter.NewNode(conf) 119 if err != nil { 120 return nil, err 121 } 122 node := newNode(adapterNode, conf, false) 123 log.Trace("Node created", "id", conf.ID) 124 125 nodeIndex := len(net.Nodes) 126 net.nodeMap[conf.ID] = nodeIndex 127 net.Nodes = append(net.Nodes, node) 128 129 // Register any node properties with the network-level propertyMap 130 for _, property := range conf.Properties { 131 net.propertyMap[property] = append(net.propertyMap[property], nodeIndex) 132 } 133 134 // emit a "control" event 135 net.events.Send(ControlEvent(node)) 136 137 return node, nil 138 } 139 140 // Config returns the network configuration 141 func (net *Network) Config() *NetworkConfig { 142 return &net.NetworkConfig 143 } 144 145 // StartAll starts all nodes in the network 146 func (net *Network) StartAll() error { 147 for _, node := range net.Nodes { 148 if node.Up() { 149 continue 150 } 151 if err := net.Start(node.ID()); err != nil { 152 return err 153 } 154 } 155 return nil 156 } 157 158 // StopAll stops all nodes in the network 159 func (net *Network) StopAll() error { 160 for _, node := range net.Nodes { 161 if !node.Up() { 162 continue 163 } 164 if err := net.Stop(node.ID()); err != nil { 165 return err 166 } 167 } 168 return nil 169 } 170 171 // Start starts the node with the given ID 172 func (net *Network) Start(id enode.ID) error { 173 return net.startWithSnapshots(id, nil) 174 } 175 176 // startWithSnapshots starts the node with the given ID using the give 177 // snapshots 178 func (net *Network) startWithSnapshots(id enode.ID, snapshots map[string][]byte) error { 179 net.lock.Lock() 180 defer net.lock.Unlock() 181 182 node := net.getNode(id) 183 if node == nil { 184 return fmt.Errorf("node %v does not exist", id) 185 } 186 if node.Up() { 187 return fmt.Errorf("node %v already up", id) 188 } 189 log.Trace("Starting node", "id", id, "adapter", net.nodeAdapter.Name()) 190 if err := node.Start(snapshots); err != nil { 191 log.Warn("Node startup failed", "id", id, "err", err) 192 return err 193 } 194 node.SetUp(true) 195 log.Info("Started node", "id", id) 196 ev := NewEvent(node) 197 net.events.Send(ev) 198 199 // subscribe to peer events 200 client, err := node.Client() 201 if err != nil { 202 return fmt.Errorf("error getting rpc client for node %v: %s", id, err) 203 } 204 events := make(chan *p2p.PeerEvent) 205 sub, err := client.Subscribe(context.Background(), "admin", events, "peerEvents") 206 if err != nil { 207 return fmt.Errorf("error getting peer events for node %v: %s", id, err) 208 } 209 go net.watchPeerEvents(id, events, sub) 210 return nil 211 } 212 213 // watchPeerEvents reads peer events from the given channel and emits 214 // corresponding network events 215 func (net *Network) watchPeerEvents(id enode.ID, events chan *p2p.PeerEvent, sub event.Subscription) { 216 defer func() { 217 sub.Unsubscribe() 218 219 // assume the node is now down 220 net.lock.Lock() 221 defer net.lock.Unlock() 222 223 node := net.getNode(id) 224 if node == nil { 225 return 226 } 227 node.SetUp(false) 228 ev := NewEvent(node) 229 net.events.Send(ev) 230 }() 231 for { 232 select { 233 case event, ok := <-events: 234 if !ok { 235 return 236 } 237 peer := event.Peer 238 switch event.Type { 239 240 case p2p.PeerEventTypeAdd: 241 net.DidConnect(id, peer) 242 243 case p2p.PeerEventTypeDrop: 244 net.DidDisconnect(id, peer) 245 246 case p2p.PeerEventTypeMsgSend: 247 net.DidSend(id, peer, event.Protocol, *event.MsgCode) 248 249 case p2p.PeerEventTypeMsgRecv: 250 net.DidReceive(peer, id, event.Protocol, *event.MsgCode) 251 252 } 253 254 case err := <-sub.Err(): 255 if err != nil { 256 log.Error("Error in peer event subscription", "id", id, "err", err) 257 } 258 return 259 } 260 } 261 } 262 263 // Stop stops the node with the given ID 264 func (net *Network) Stop(id enode.ID) error { 265 // IMPORTANT: node.Stop() must NOT be called under net.lock as 266 // node.Reachable() closure has a reference to the network and 267 // calls net.InitConn() what also locks the network. => DEADLOCK 268 // That holds until the following ticket is not resolved: 269 270 var err error 271 272 node, err := func() (*Node, error) { 273 net.lock.Lock() 274 defer net.lock.Unlock() 275 276 node := net.getNode(id) 277 if node == nil { 278 return nil, fmt.Errorf("node %v does not exist", id) 279 } 280 if !node.Up() { 281 return nil, fmt.Errorf("node %v already down", id) 282 } 283 node.SetUp(false) 284 return node, nil 285 }() 286 if err != nil { 287 return err 288 } 289 290 err = node.Stop() // must be called without net.lock 291 292 net.lock.Lock() 293 defer net.lock.Unlock() 294 295 if err != nil { 296 node.SetUp(true) 297 return err 298 } 299 log.Info("Stopped node", "id", id, "err", err) 300 ev := ControlEvent(node) 301 net.events.Send(ev) 302 return nil 303 } 304 305 // Connect connects two nodes together by calling the "admin_addPeer" RPC 306 // method on the "one" node so that it connects to the "other" node 307 func (net *Network) Connect(oneID, otherID enode.ID) error { 308 net.lock.Lock() 309 defer net.lock.Unlock() 310 return net.connect(oneID, otherID) 311 } 312 313 func (net *Network) connect(oneID, otherID enode.ID) error { 314 log.Debug("Connecting nodes with addPeer", "id", oneID, "other", otherID) 315 conn, err := net.initConn(oneID, otherID) 316 if err != nil { 317 return err 318 } 319 client, err := conn.one.Client() 320 if err != nil { 321 return err 322 } 323 net.events.Send(ControlEvent(conn)) 324 return client.Call(nil, "admin_addPeer", string(conn.other.Addr())) 325 } 326 327 // Disconnect disconnects two nodes by calling the "admin_removePeer" RPC 328 // method on the "one" node so that it disconnects from the "other" node 329 func (net *Network) Disconnect(oneID, otherID enode.ID) error { 330 conn := net.GetConn(oneID, otherID) 331 if conn == nil { 332 return fmt.Errorf("connection between %v and %v does not exist", oneID, otherID) 333 } 334 if !conn.Up { 335 return fmt.Errorf("%v and %v already disconnected", oneID, otherID) 336 } 337 client, err := conn.one.Client() 338 if err != nil { 339 return err 340 } 341 net.events.Send(ControlEvent(conn)) 342 return client.Call(nil, "admin_removePeer", string(conn.other.Addr())) 343 } 344 345 // DidConnect tracks the fact that the "one" node connected to the "other" node 346 func (net *Network) DidConnect(one, other enode.ID) error { 347 net.lock.Lock() 348 defer net.lock.Unlock() 349 conn, err := net.getOrCreateConn(one, other) 350 if err != nil { 351 return fmt.Errorf("connection between %v and %v does not exist", one, other) 352 } 353 if conn.Up { 354 return fmt.Errorf("%v and %v already connected", one, other) 355 } 356 conn.Up = true 357 net.events.Send(NewEvent(conn)) 358 return nil 359 } 360 361 // DidDisconnect tracks the fact that the "one" node disconnected from the 362 // "other" node 363 func (net *Network) DidDisconnect(one, other enode.ID) error { 364 net.lock.Lock() 365 defer net.lock.Unlock() 366 conn := net.getConn(one, other) 367 if conn == nil { 368 return fmt.Errorf("connection between %v and %v does not exist", one, other) 369 } 370 if !conn.Up { 371 return fmt.Errorf("%v and %v already disconnected", one, other) 372 } 373 conn.Up = false 374 conn.initiated = time.Now().Add(-DialBanTimeout) 375 net.events.Send(NewEvent(conn)) 376 return nil 377 } 378 379 // DidSend tracks the fact that "sender" sent a message to "receiver" 380 func (net *Network) DidSend(sender, receiver enode.ID, proto string, code uint64) error { 381 msg := &Msg{ 382 One: sender, 383 Other: receiver, 384 Protocol: proto, 385 Code: code, 386 Received: false, 387 } 388 net.events.Send(NewEvent(msg)) 389 return nil 390 } 391 392 // DidReceive tracks the fact that "receiver" received a message from "sender" 393 func (net *Network) DidReceive(sender, receiver enode.ID, proto string, code uint64) error { 394 msg := &Msg{ 395 One: sender, 396 Other: receiver, 397 Protocol: proto, 398 Code: code, 399 Received: true, 400 } 401 net.events.Send(NewEvent(msg)) 402 return nil 403 } 404 405 // GetNode gets the node with the given ID, returning nil if the node does not 406 // exist 407 func (net *Network) GetNode(id enode.ID) *Node { 408 net.lock.RLock() 409 defer net.lock.RUnlock() 410 return net.getNode(id) 411 } 412 413 func (net *Network) getNode(id enode.ID) *Node { 414 i, found := net.nodeMap[id] 415 if !found { 416 return nil 417 } 418 return net.Nodes[i] 419 } 420 421 // GetNodeByName gets the node with the given name, returning nil if the node does 422 // not exist 423 func (net *Network) GetNodeByName(name string) *Node { 424 net.lock.RLock() 425 defer net.lock.RUnlock() 426 return net.getNodeByName(name) 427 } 428 429 func (net *Network) getNodeByName(name string) *Node { 430 for _, node := range net.Nodes { 431 if node.Config.Name == name { 432 return node 433 } 434 } 435 return nil 436 } 437 438 // GetNodeIDs returns the IDs of all existing nodes 439 // Nodes can optionally be excluded by specifying their enode.ID. 440 func (net *Network) GetNodeIDs(excludeIDs ...enode.ID) []enode.ID { 441 net.lock.RLock() 442 defer net.lock.RUnlock() 443 444 return net.getNodeIDs(excludeIDs) 445 } 446 447 func (net *Network) getNodeIDs(excludeIDs []enode.ID) []enode.ID { 448 // Get all current nodeIDs 449 nodeIDs := make([]enode.ID, 0, len(net.nodeMap)) 450 for id := range net.nodeMap { 451 nodeIDs = append(nodeIDs, id) 452 } 453 454 if len(excludeIDs) > 0 { 455 // Return the difference of nodeIDs and excludeIDs 456 return filterIDs(nodeIDs, excludeIDs) 457 } else { 458 return nodeIDs 459 } 460 } 461 462 // GetNodes returns the existing nodes. 463 // Nodes can optionally be excluded by specifying their enode.ID. 464 func (net *Network) GetNodes(excludeIDs ...enode.ID) []*Node { 465 net.lock.RLock() 466 defer net.lock.RUnlock() 467 468 return net.getNodes(excludeIDs) 469 } 470 471 func (net *Network) getNodes(excludeIDs []enode.ID) []*Node { 472 if len(excludeIDs) > 0 { 473 nodeIDs := net.getNodeIDs(excludeIDs) 474 return net.getNodesByID(nodeIDs) 475 } else { 476 return net.Nodes 477 } 478 } 479 480 // GetNodesByID returns existing nodes with the given enode.IDs. 481 // If a node doesn't exist with a given enode.ID, it is ignored. 482 func (net *Network) GetNodesByID(nodeIDs []enode.ID) []*Node { 483 net.lock.RLock() 484 defer net.lock.RUnlock() 485 486 return net.getNodesByID(nodeIDs) 487 } 488 489 func (net *Network) getNodesByID(nodeIDs []enode.ID) []*Node { 490 nodes := make([]*Node, 0, len(nodeIDs)) 491 for _, id := range nodeIDs { 492 node := net.getNode(id) 493 if node != nil { 494 nodes = append(nodes, node) 495 } 496 } 497 498 return nodes 499 } 500 501 // GetNodesByProperty returns existing nodes that have the given property string registered in their NodeConfig 502 func (net *Network) GetNodesByProperty(property string) []*Node { 503 net.lock.RLock() 504 defer net.lock.RUnlock() 505 506 return net.getNodesByProperty(property) 507 } 508 509 func (net *Network) getNodesByProperty(property string) []*Node { 510 nodes := make([]*Node, 0, len(net.propertyMap[property])) 511 for _, nodeIndex := range net.propertyMap[property] { 512 nodes = append(nodes, net.Nodes[nodeIndex]) 513 } 514 515 return nodes 516 } 517 518 // GetNodeIDsByProperty returns existing node's enode IDs that have the given property string registered in the NodeConfig 519 func (net *Network) GetNodeIDsByProperty(property string) []enode.ID { 520 net.lock.RLock() 521 defer net.lock.RUnlock() 522 523 return net.getNodeIDsByProperty(property) 524 } 525 526 func (net *Network) getNodeIDsByProperty(property string) []enode.ID { 527 nodeIDs := make([]enode.ID, 0, len(net.propertyMap[property])) 528 for _, nodeIndex := range net.propertyMap[property] { 529 node := net.Nodes[nodeIndex] 530 nodeIDs = append(nodeIDs, node.ID()) 531 } 532 533 return nodeIDs 534 } 535 536 // GetRandomUpNode returns a random node on the network, which is running. 537 func (net *Network) GetRandomUpNode(excludeIDs ...enode.ID) *Node { 538 net.lock.RLock() 539 defer net.lock.RUnlock() 540 return net.getRandomUpNode(excludeIDs...) 541 } 542 543 // GetRandomUpNode returns a random node on the network, which is running. 544 func (net *Network) getRandomUpNode(excludeIDs ...enode.ID) *Node { 545 return net.getRandomNode(net.getUpNodeIDs(), excludeIDs) 546 } 547 548 func (net *Network) getUpNodeIDs() (ids []enode.ID) { 549 for _, node := range net.Nodes { 550 if node.Up() { 551 ids = append(ids, node.ID()) 552 } 553 } 554 return ids 555 } 556 557 // GetRandomDownNode returns a random node on the network, which is stopped. 558 func (net *Network) GetRandomDownNode(excludeIDs ...enode.ID) *Node { 559 net.lock.RLock() 560 defer net.lock.RUnlock() 561 return net.getRandomNode(net.getDownNodeIDs(), excludeIDs) 562 } 563 564 func (net *Network) getDownNodeIDs() (ids []enode.ID) { 565 for _, node := range net.Nodes { 566 if !node.Up() { 567 ids = append(ids, node.ID()) 568 } 569 } 570 return ids 571 } 572 573 // GetRandomNode returns a random node on the network, regardless of whether it is running or not 574 func (net *Network) GetRandomNode(excludeIDs ...enode.ID) *Node { 575 net.lock.RLock() 576 defer net.lock.RUnlock() 577 return net.getRandomNode(net.getNodeIDs(nil), excludeIDs) // no need to exclude twice 578 } 579 580 func (net *Network) getRandomNode(ids []enode.ID, excludeIDs []enode.ID) *Node { 581 filtered := filterIDs(ids, excludeIDs) 582 583 l := len(filtered) 584 if l == 0 { 585 return nil 586 } 587 return net.getNode(filtered[rand.Intn(l)]) 588 } 589 590 func filterIDs(ids []enode.ID, excludeIDs []enode.ID) []enode.ID { 591 exclude := make(map[enode.ID]bool) 592 for _, id := range excludeIDs { 593 exclude[id] = true 594 } 595 var filtered []enode.ID 596 for _, id := range ids { 597 if _, found := exclude[id]; !found { 598 filtered = append(filtered, id) 599 } 600 } 601 return filtered 602 } 603 604 // GetConn returns the connection which exists between "one" and "other" 605 // regardless of which node initiated the connection 606 func (net *Network) GetConn(oneID, otherID enode.ID) *Conn { 607 net.lock.RLock() 608 defer net.lock.RUnlock() 609 return net.getConn(oneID, otherID) 610 } 611 612 // GetOrCreateConn is like GetConn but creates the connection if it doesn't 613 // already exist 614 func (net *Network) GetOrCreateConn(oneID, otherID enode.ID) (*Conn, error) { 615 net.lock.Lock() 616 defer net.lock.Unlock() 617 return net.getOrCreateConn(oneID, otherID) 618 } 619 620 func (net *Network) getOrCreateConn(oneID, otherID enode.ID) (*Conn, error) { 621 if conn := net.getConn(oneID, otherID); conn != nil { 622 return conn, nil 623 } 624 625 one := net.getNode(oneID) 626 if one == nil { 627 return nil, fmt.Errorf("node %v does not exist", oneID) 628 } 629 other := net.getNode(otherID) 630 if other == nil { 631 return nil, fmt.Errorf("node %v does not exist", otherID) 632 } 633 conn := &Conn{ 634 One: oneID, 635 Other: otherID, 636 one: one, 637 other: other, 638 } 639 label := ConnLabel(oneID, otherID) 640 net.connMap[label] = len(net.Conns) 641 net.Conns = append(net.Conns, conn) 642 return conn, nil 643 } 644 645 func (net *Network) getConn(oneID, otherID enode.ID) *Conn { 646 label := ConnLabel(oneID, otherID) 647 i, found := net.connMap[label] 648 if !found { 649 return nil 650 } 651 return net.Conns[i] 652 } 653 654 // InitConn(one, other) retrieves the connection model for the connection between 655 // peers one and other, or creates a new one if it does not exist 656 // the order of nodes does not matter, i.e., Conn(i,j) == Conn(j, i) 657 // it checks if the connection is already up, and if the nodes are running 658 // NOTE: 659 // it also checks whether there has been recent attempt to connect the peers 660 // this is cheating as the simulation is used as an oracle and know about 661 // remote peers attempt to connect to a node which will then not initiate the connection 662 func (net *Network) InitConn(oneID, otherID enode.ID) (*Conn, error) { 663 net.lock.Lock() 664 defer net.lock.Unlock() 665 return net.initConn(oneID, otherID) 666 } 667 668 func (net *Network) initConn(oneID, otherID enode.ID) (*Conn, error) { 669 if oneID == otherID { 670 return nil, fmt.Errorf("refusing to connect to self %v", oneID) 671 } 672 conn, err := net.getOrCreateConn(oneID, otherID) 673 if err != nil { 674 return nil, err 675 } 676 if conn.Up { 677 return nil, fmt.Errorf("%v and %v already connected", oneID, otherID) 678 } 679 if time.Since(conn.initiated) < DialBanTimeout { 680 return nil, fmt.Errorf("connection between %v and %v recently attempted", oneID, otherID) 681 } 682 683 err = conn.nodesUp() 684 if err != nil { 685 log.Trace("Nodes not up", "err", err) 686 return nil, fmt.Errorf("nodes not up: %v", err) 687 } 688 log.Debug("Connection initiated", "id", oneID, "other", otherID) 689 conn.initiated = time.Now() 690 return conn, nil 691 } 692 693 // Shutdown stops all nodes in the network and closes the quit channel 694 func (net *Network) Shutdown() { 695 for _, node := range net.Nodes { 696 log.Debug("Stopping node", "id", node.ID()) 697 if err := node.Stop(); err != nil { 698 log.Warn("Can't stop node", "id", node.ID(), "err", err) 699 } 700 // If the node has the close method, call it. 701 if closer, ok := node.Node.(io.Closer); ok { 702 if err := closer.Close(); err != nil { 703 log.Warn("Can't close node", "id", node.ID(), "err", err) 704 } 705 } 706 } 707 close(net.quitc) 708 } 709 710 // Reset resets all network properties: 711 // empties the nodes and the connection list 712 func (net *Network) Reset() { 713 net.lock.Lock() 714 defer net.lock.Unlock() 715 716 //re-initialize the maps 717 net.connMap = make(map[string]int) 718 net.nodeMap = make(map[enode.ID]int) 719 net.propertyMap = make(map[string][]int) 720 721 net.Nodes = nil 722 net.Conns = nil 723 } 724 725 // Node is a wrapper around adapters.Node which is used to track the status 726 // of a node in the network 727 type Node struct { 728 adapters.Node `json:"-"` 729 730 // Config if the config used to created the node 731 Config *adapters.NodeConfig `json:"config"` 732 733 // up tracks whether or not the node is running 734 up bool 735 upMu *sync.RWMutex 736 } 737 738 func newNode(an adapters.Node, ac *adapters.NodeConfig, up bool) *Node { 739 return &Node{Node: an, Config: ac, up: up, upMu: new(sync.RWMutex)} 740 } 741 742 func (n *Node) copy() *Node { 743 configCpy := *n.Config 744 return newNode(n.Node, &configCpy, n.Up()) 745 } 746 747 // Up returns whether the node is currently up (online) 748 func (n *Node) Up() bool { 749 n.upMu.RLock() 750 defer n.upMu.RUnlock() 751 return n.up 752 } 753 754 // SetUp sets the up (online) status of the nodes with the given value 755 func (n *Node) SetUp(up bool) { 756 n.upMu.Lock() 757 defer n.upMu.Unlock() 758 n.up = up 759 } 760 761 // ID returns the ID of the node 762 func (n *Node) ID() enode.ID { 763 return n.Config.ID 764 } 765 766 // String returns a log-friendly string 767 func (n *Node) String() string { 768 return fmt.Sprintf("Node %v", n.ID().TerminalString()) 769 } 770 771 // NodeInfo returns information about the node 772 func (n *Node) NodeInfo() *p2p.NodeInfo { 773 // avoid a panic if the node is not started yet 774 if n.Node == nil { 775 return nil 776 } 777 info := n.Node.NodeInfo() 778 info.Name = n.Config.Name 779 return info 780 } 781 782 // MarshalJSON implements the json.Marshaler interface so that the encoded 783 // JSON includes the NodeInfo 784 func (n *Node) MarshalJSON() ([]byte, error) { 785 return json.Marshal(struct { 786 Info *p2p.NodeInfo `json:"info,omitempty"` 787 Config *adapters.NodeConfig `json:"config,omitempty"` 788 Up bool `json:"up"` 789 }{ 790 Info: n.NodeInfo(), 791 Config: n.Config, 792 Up: n.Up(), 793 }) 794 } 795 796 // UnmarshalJSON implements json.Unmarshaler interface so that we don't lose Node.up 797 // status. IMPORTANT: The implementation is incomplete; we lose p2p.NodeInfo. 798 func (n *Node) UnmarshalJSON(raw []byte) error { 799 // TODO: How should we turn back NodeInfo into n.Node? 800 // Ticket: https://github.com/ethersphere/go-ethereum/issues/1177 801 var node struct { 802 Config *adapters.NodeConfig `json:"config,omitempty"` 803 Up bool `json:"up"` 804 } 805 if err := json.Unmarshal(raw, &node); err != nil { 806 return err 807 } 808 *n = *newNode(nil, node.Config, node.Up) 809 return nil 810 } 811 812 // Conn represents a connection between two nodes in the network 813 type Conn struct { 814 // One is the node which initiated the connection 815 One enode.ID `json:"one"` 816 817 // Other is the node which the connection was made to 818 Other enode.ID `json:"other"` 819 820 // Up tracks whether or not the connection is active 821 Up bool `json:"up"` 822 // Registers when the connection was grabbed to dial 823 initiated time.Time 824 825 one *Node 826 other *Node 827 } 828 829 // nodesUp returns whether both nodes are currently up 830 func (c *Conn) nodesUp() error { 831 if !c.one.Up() { 832 return fmt.Errorf("one %v is not up", c.One) 833 } 834 if !c.other.Up() { 835 return fmt.Errorf("other %v is not up", c.Other) 836 } 837 return nil 838 } 839 840 // String returns a log-friendly string 841 func (c *Conn) String() string { 842 return fmt.Sprintf("Conn %v->%v", c.One.TerminalString(), c.Other.TerminalString()) 843 } 844 845 // Msg represents a p2p message sent between two nodes in the network 846 type Msg struct { 847 One enode.ID `json:"one"` 848 Other enode.ID `json:"other"` 849 Protocol string `json:"protocol"` 850 Code uint64 `json:"code"` 851 Received bool `json:"received"` 852 } 853 854 // String returns a log-friendly string 855 func (m *Msg) String() string { 856 return fmt.Sprintf("Msg(%d) %v->%v", m.Code, m.One.TerminalString(), m.Other.TerminalString()) 857 } 858 859 // ConnLabel generates a deterministic string which represents a connection 860 // between two nodes, used to compare if two connections are between the same 861 // nodes 862 func ConnLabel(source, target enode.ID) string { 863 var first, second enode.ID 864 if bytes.Compare(source.Bytes(), target.Bytes()) > 0 { 865 first = target 866 second = source 867 } else { 868 first = source 869 second = target 870 } 871 return fmt.Sprintf("%v-%v", first, second) 872 } 873 874 // Snapshot represents the state of a network at a single point in time and can 875 // be used to restore the state of a network 876 type Snapshot struct { 877 Nodes []NodeSnapshot `json:"nodes,omitempty"` 878 Conns []Conn `json:"conns,omitempty"` 879 } 880 881 // NodeSnapshot represents the state of a node in the network 882 type NodeSnapshot struct { 883 Node Node `json:"node,omitempty"` 884 885 // Snapshots is arbitrary data gathered from calling node.Snapshots() 886 Snapshots map[string][]byte `json:"snapshots,omitempty"` 887 } 888 889 // Snapshot creates a network snapshot 890 func (net *Network) Snapshot() (*Snapshot, error) { 891 return net.snapshot(nil, nil) 892 } 893 894 func (net *Network) SnapshotWithServices(addServices []string, removeServices []string) (*Snapshot, error) { 895 return net.snapshot(addServices, removeServices) 896 } 897 898 func (net *Network) snapshot(addServices []string, removeServices []string) (*Snapshot, error) { 899 net.lock.Lock() 900 defer net.lock.Unlock() 901 snap := &Snapshot{ 902 Nodes: make([]NodeSnapshot, len(net.Nodes)), 903 } 904 for i, node := range net.Nodes { 905 snap.Nodes[i] = NodeSnapshot{Node: *node.copy()} 906 if !node.Up() { 907 continue 908 } 909 snapshots, err := node.Snapshots() 910 if err != nil { 911 return nil, err 912 } 913 snap.Nodes[i].Snapshots = snapshots 914 for _, addSvc := range addServices { 915 haveSvc := false 916 for _, svc := range snap.Nodes[i].Node.Config.Lifecycles { 917 if svc == addSvc { 918 haveSvc = true 919 break 920 } 921 } 922 if !haveSvc { 923 snap.Nodes[i].Node.Config.Lifecycles = append(snap.Nodes[i].Node.Config.Lifecycles, addSvc) 924 } 925 } 926 if len(removeServices) > 0 { 927 var cleanedServices []string 928 for _, svc := range snap.Nodes[i].Node.Config.Lifecycles { 929 haveSvc := false 930 for _, rmSvc := range removeServices { 931 if rmSvc == svc { 932 haveSvc = true 933 break 934 } 935 } 936 if !haveSvc { 937 cleanedServices = append(cleanedServices, svc) 938 } 939 940 } 941 snap.Nodes[i].Node.Config.Lifecycles = cleanedServices 942 } 943 } 944 for _, conn := range net.Conns { 945 if conn.Up { 946 snap.Conns = append(snap.Conns, *conn) 947 } 948 } 949 return snap, nil 950 } 951 952 // longrunning tests may need a longer timeout 953 var snapshotLoadTimeout = 900 * time.Second 954 955 // Load loads a network snapshot 956 func (net *Network) Load(snap *Snapshot) error { 957 // Start nodes. 958 for _, n := range snap.Nodes { 959 if _, err := net.NewNodeWithConfig(n.Node.Config); err != nil { 960 return err 961 } 962 if !n.Node.Up() { 963 continue 964 } 965 if err := net.startWithSnapshots(n.Node.Config.ID, n.Snapshots); err != nil { 966 return err 967 } 968 } 969 970 // Prepare connection events counter. 971 allConnected := make(chan struct{}) // closed when all connections are established 972 done := make(chan struct{}) // ensures that the event loop goroutine is terminated 973 defer close(done) 974 975 // Subscribe to event channel. 976 // It needs to be done outside of the event loop goroutine (created below) 977 // to ensure that the event channel is blocking before connect calls are made. 978 events := make(chan *Event) 979 sub := net.Events().Subscribe(events) 980 defer sub.Unsubscribe() 981 982 go func() { 983 // Expected number of connections. 984 total := len(snap.Conns) 985 // Set of all established connections from the snapshot, not other connections. 986 // Key array element 0 is the connection One field value, and element 1 connection Other field. 987 connections := make(map[[2]enode.ID]struct{}, total) 988 989 for { 990 select { 991 case e := <-events: 992 // Ignore control events as they do not represent 993 // connect or disconnect (Up) state change. 994 if e.Control { 995 continue 996 } 997 // Detect only connection events. 998 if e.Type != EventTypeConn { 999 continue 1000 } 1001 connection := [2]enode.ID{e.Conn.One, e.Conn.Other} 1002 // Nodes are still not connected or have been disconnected. 1003 if !e.Conn.Up { 1004 // Delete the connection from the set of established connections. 1005 // This will prevent false positive in case disconnections happen. 1006 delete(connections, connection) 1007 log.Warn("load snapshot: unexpected disconnection", "one", e.Conn.One, "other", e.Conn.Other) 1008 continue 1009 } 1010 // Check that the connection is from the snapshot. 1011 for _, conn := range snap.Conns { 1012 if conn.One == e.Conn.One && conn.Other == e.Conn.Other { 1013 // Add the connection to the set of established connections. 1014 connections[connection] = struct{}{} 1015 if len(connections) == total { 1016 // Signal that all nodes are connected. 1017 close(allConnected) 1018 return 1019 } 1020 1021 break 1022 } 1023 } 1024 case <-done: 1025 // Load function returned, terminate this goroutine. 1026 return 1027 } 1028 } 1029 }() 1030 1031 // Start connecting. 1032 for _, conn := range snap.Conns { 1033 1034 if !net.GetNode(conn.One).Up() || !net.GetNode(conn.Other).Up() { 1035 //in this case, at least one of the nodes of a connection is not up, 1036 //so it would result in the snapshot `Load` to fail 1037 continue 1038 } 1039 if err := net.Connect(conn.One, conn.Other); err != nil { 1040 return err 1041 } 1042 } 1043 1044 select { 1045 // Wait until all connections from the snapshot are established. 1046 case <-allConnected: 1047 // Make sure that we do not wait forever. 1048 case <-time.After(snapshotLoadTimeout): 1049 return errors.New("snapshot connections not established") 1050 } 1051 return nil 1052 } 1053 1054 // Subscribe reads control events from a channel and executes them 1055 func (net *Network) Subscribe(events chan *Event) { 1056 for { 1057 select { 1058 case event, ok := <-events: 1059 if !ok { 1060 return 1061 } 1062 if event.Control { 1063 net.executeControlEvent(event) 1064 } 1065 case <-net.quitc: 1066 return 1067 } 1068 } 1069 } 1070 1071 func (net *Network) executeControlEvent(event *Event) { 1072 log.Trace("Executing control event", "type", event.Type, "event", event) 1073 switch event.Type { 1074 case EventTypeNode: 1075 if err := net.executeNodeEvent(event); err != nil { 1076 log.Error("Error executing node event", "event", event, "err", err) 1077 } 1078 case EventTypeConn: 1079 if err := net.executeConnEvent(event); err != nil { 1080 log.Error("Error executing conn event", "event", event, "err", err) 1081 } 1082 case EventTypeMsg: 1083 log.Warn("Ignoring control msg event") 1084 } 1085 } 1086 1087 func (net *Network) executeNodeEvent(e *Event) error { 1088 if !e.Node.Up() { 1089 return net.Stop(e.Node.ID()) 1090 } 1091 1092 if _, err := net.NewNodeWithConfig(e.Node.Config); err != nil { 1093 return err 1094 } 1095 return net.Start(e.Node.ID()) 1096 } 1097 1098 func (net *Network) executeConnEvent(e *Event) error { 1099 if e.Conn.Up { 1100 return net.Connect(e.Conn.One, e.Conn.Other) 1101 } else { 1102 return net.Disconnect(e.Conn.One, e.Conn.Other) 1103 } 1104 }