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