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