github.com/oskarth/go-ethereum@v1.6.8-0.20191013093314-dac24a9d3494/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 "fmt" 24 "sync" 25 "time" 26 27 "github.com/ethereum/go-ethereum/event" 28 "github.com/ethereum/go-ethereum/log" 29 "github.com/ethereum/go-ethereum/p2p" 30 "github.com/ethereum/go-ethereum/p2p/enode" 31 "github.com/ethereum/go-ethereum/p2p/simulations/adapters" 32 ) 33 34 var DialBanTimeout = 200 * time.Millisecond 35 36 // NetworkConfig defines configuration options for starting a Network 37 type NetworkConfig struct { 38 ID string `json:"id"` 39 DefaultService string `json:"default_service,omitempty"` 40 } 41 42 // Network models a p2p simulation network which consists of a collection of 43 // simulated nodes and the connections which exist between them. 44 // 45 // The Network has a single NodeAdapter which is responsible for actually 46 // starting nodes and connecting them together. 47 // 48 // The Network emits events when nodes are started and stopped, when they are 49 // connected and disconnected, and also when messages are sent between nodes. 50 type Network struct { 51 NetworkConfig 52 53 Nodes []*Node `json:"nodes"` 54 nodeMap map[enode.ID]int 55 56 Conns []*Conn `json:"conns"` 57 connMap map[string]int 58 59 nodeAdapter adapters.NodeAdapter 60 events event.Feed 61 lock sync.RWMutex 62 quitc chan struct{} 63 } 64 65 // NewNetwork returns a Network which uses the given NodeAdapter and NetworkConfig 66 func NewNetwork(nodeAdapter adapters.NodeAdapter, conf *NetworkConfig) *Network { 67 return &Network{ 68 NetworkConfig: *conf, 69 nodeAdapter: nodeAdapter, 70 nodeMap: make(map[enode.ID]int), 71 connMap: make(map[string]int), 72 quitc: make(chan struct{}), 73 } 74 } 75 76 // Events returns the output event feed of the Network. 77 func (net *Network) Events() *event.Feed { 78 return &net.events 79 } 80 81 // NewNodeWithConfig adds a new node to the network with the given config, 82 // returning an error if a node with the same ID or name already exists 83 func (net *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error) { 84 net.lock.Lock() 85 defer net.lock.Unlock() 86 87 if conf.Reachable == nil { 88 conf.Reachable = func(otherID enode.ID) bool { 89 _, err := net.InitConn(conf.ID, otherID) 90 if err != nil && bytes.Compare(conf.ID.Bytes(), otherID.Bytes()) < 0 { 91 return false 92 } 93 return true 94 } 95 } 96 97 // check the node doesn't already exist 98 if node := net.getNode(conf.ID); node != nil { 99 return nil, fmt.Errorf("node with ID %q already exists", conf.ID) 100 } 101 if node := net.getNodeByName(conf.Name); node != nil { 102 return nil, fmt.Errorf("node with name %q already exists", conf.Name) 103 } 104 105 // if no services are configured, use the default service 106 if len(conf.Services) == 0 { 107 conf.Services = []string{net.DefaultService} 108 } 109 110 // use the NodeAdapter to create the node 111 adapterNode, err := net.nodeAdapter.NewNode(conf) 112 if err != nil { 113 return nil, err 114 } 115 node := &Node{ 116 Node: adapterNode, 117 Config: conf, 118 } 119 log.Trace("Node created", "id", conf.ID) 120 net.nodeMap[conf.ID] = len(net.Nodes) 121 net.Nodes = append(net.Nodes, node) 122 123 // emit a "control" event 124 net.events.Send(ControlEvent(node)) 125 126 return node, nil 127 } 128 129 // Config returns the network configuration 130 func (net *Network) Config() *NetworkConfig { 131 return &net.NetworkConfig 132 } 133 134 // StartAll starts all nodes in the network 135 func (net *Network) StartAll() error { 136 for _, node := range net.Nodes { 137 if node.Up { 138 continue 139 } 140 if err := net.Start(node.ID()); err != nil { 141 return err 142 } 143 } 144 return nil 145 } 146 147 // StopAll stops all nodes in the network 148 func (net *Network) StopAll() error { 149 for _, node := range net.Nodes { 150 if !node.Up { 151 continue 152 } 153 if err := net.Stop(node.ID()); err != nil { 154 return err 155 } 156 } 157 return nil 158 } 159 160 // Start starts the node with the given ID 161 func (net *Network) Start(id enode.ID) error { 162 return net.startWithSnapshots(id, nil) 163 } 164 165 // startWithSnapshots starts the node with the given ID using the give 166 // snapshots 167 func (net *Network) startWithSnapshots(id enode.ID, snapshots map[string][]byte) error { 168 net.lock.Lock() 169 defer net.lock.Unlock() 170 171 node := net.getNode(id) 172 if node == nil { 173 return fmt.Errorf("node %v does not exist", id) 174 } 175 if node.Up { 176 return fmt.Errorf("node %v already up", id) 177 } 178 log.Trace("Starting node", "id", id, "adapter", net.nodeAdapter.Name()) 179 if err := node.Start(snapshots); err != nil { 180 log.Warn("Node startup failed", "id", id, "err", err) 181 return err 182 } 183 node.Up = true 184 log.Info("Started node", "id", id) 185 186 net.events.Send(NewEvent(node)) 187 188 // subscribe to peer events 189 client, err := node.Client() 190 if err != nil { 191 return fmt.Errorf("error getting rpc client for node %v: %s", id, err) 192 } 193 events := make(chan *p2p.PeerEvent) 194 sub, err := client.Subscribe(context.Background(), "admin", events, "peerEvents") 195 if err != nil { 196 return fmt.Errorf("error getting peer events for node %v: %s", id, err) 197 } 198 go net.watchPeerEvents(id, events, sub) 199 return nil 200 } 201 202 // watchPeerEvents reads peer events from the given channel and emits 203 // corresponding network events 204 func (net *Network) watchPeerEvents(id enode.ID, events chan *p2p.PeerEvent, sub event.Subscription) { 205 defer func() { 206 sub.Unsubscribe() 207 208 // assume the node is now down 209 net.lock.Lock() 210 defer net.lock.Unlock() 211 node := net.getNode(id) 212 if node == nil { 213 return 214 } 215 node.Up = false 216 net.events.Send(NewEvent(node)) 217 }() 218 for { 219 select { 220 case event, ok := <-events: 221 if !ok { 222 return 223 } 224 peer := event.Peer 225 switch event.Type { 226 227 case p2p.PeerEventTypeAdd: 228 net.DidConnect(id, peer) 229 230 case p2p.PeerEventTypeDrop: 231 net.DidDisconnect(id, peer) 232 233 case p2p.PeerEventTypeMsgSend: 234 net.DidSend(id, peer, event.Protocol, *event.MsgCode) 235 236 case p2p.PeerEventTypeMsgRecv: 237 net.DidReceive(peer, id, event.Protocol, *event.MsgCode) 238 239 } 240 241 case err := <-sub.Err(): 242 if err != nil { 243 log.Error("Error in peer event subscription", "id", id, "err", err) 244 } 245 return 246 } 247 } 248 } 249 250 // Stop stops the node with the given ID 251 func (net *Network) Stop(id enode.ID) error { 252 net.lock.Lock() 253 node := net.getNode(id) 254 if node == nil { 255 return fmt.Errorf("node %v does not exist", id) 256 } 257 if !node.Up { 258 return fmt.Errorf("node %v already down", id) 259 } 260 node.Up = false 261 net.lock.Unlock() 262 263 err := node.Stop() 264 if err != nil { 265 net.lock.Lock() 266 node.Up = true 267 net.lock.Unlock() 268 return err 269 } 270 log.Info("Stopped node", "id", id, "err", err) 271 net.events.Send(ControlEvent(node)) 272 return nil 273 } 274 275 // Connect connects two nodes together by calling the "admin_addPeer" RPC 276 // method on the "one" node so that it connects to the "other" node 277 func (net *Network) Connect(oneID, otherID enode.ID) error { 278 log.Debug("Connecting nodes with addPeer", "id", oneID, "other", otherID) 279 conn, err := net.InitConn(oneID, otherID) 280 if err != nil { 281 return err 282 } 283 client, err := conn.one.Client() 284 if err != nil { 285 return err 286 } 287 net.events.Send(ControlEvent(conn)) 288 return client.Call(nil, "admin_addPeer", string(conn.other.Addr())) 289 } 290 291 // Disconnect disconnects two nodes by calling the "admin_removePeer" RPC 292 // method on the "one" node so that it disconnects from the "other" node 293 func (net *Network) Disconnect(oneID, otherID enode.ID) error { 294 conn := net.GetConn(oneID, otherID) 295 if conn == nil { 296 return fmt.Errorf("connection between %v and %v does not exist", oneID, otherID) 297 } 298 if !conn.Up { 299 return fmt.Errorf("%v and %v already disconnected", oneID, otherID) 300 } 301 client, err := conn.one.Client() 302 if err != nil { 303 return err 304 } 305 net.events.Send(ControlEvent(conn)) 306 return client.Call(nil, "admin_removePeer", string(conn.other.Addr())) 307 } 308 309 // DidConnect tracks the fact that the "one" node connected to the "other" node 310 func (net *Network) DidConnect(one, other enode.ID) error { 311 net.lock.Lock() 312 defer net.lock.Unlock() 313 conn, err := net.getOrCreateConn(one, other) 314 if err != nil { 315 return fmt.Errorf("connection between %v and %v does not exist", one, other) 316 } 317 if conn.Up { 318 return fmt.Errorf("%v and %v already connected", one, other) 319 } 320 conn.Up = true 321 net.events.Send(NewEvent(conn)) 322 return nil 323 } 324 325 // DidDisconnect tracks the fact that the "one" node disconnected from the 326 // "other" node 327 func (net *Network) DidDisconnect(one, other enode.ID) error { 328 net.lock.Lock() 329 defer net.lock.Unlock() 330 conn := net.getConn(one, other) 331 if conn == nil { 332 return fmt.Errorf("connection between %v and %v does not exist", one, other) 333 } 334 if !conn.Up { 335 return fmt.Errorf("%v and %v already disconnected", one, other) 336 } 337 conn.Up = false 338 conn.initiated = time.Now().Add(-DialBanTimeout) 339 net.events.Send(NewEvent(conn)) 340 return nil 341 } 342 343 // DidSend tracks the fact that "sender" sent a message to "receiver" 344 func (net *Network) DidSend(sender, receiver enode.ID, proto string, code uint64) error { 345 msg := &Msg{ 346 One: sender, 347 Other: receiver, 348 Protocol: proto, 349 Code: code, 350 Received: false, 351 } 352 net.events.Send(NewEvent(msg)) 353 return nil 354 } 355 356 // DidReceive tracks the fact that "receiver" received a message from "sender" 357 func (net *Network) DidReceive(sender, receiver enode.ID, proto string, code uint64) error { 358 msg := &Msg{ 359 One: sender, 360 Other: receiver, 361 Protocol: proto, 362 Code: code, 363 Received: true, 364 } 365 net.events.Send(NewEvent(msg)) 366 return nil 367 } 368 369 // GetNode gets the node with the given ID, returning nil if the node does not 370 // exist 371 func (net *Network) GetNode(id enode.ID) *Node { 372 net.lock.Lock() 373 defer net.lock.Unlock() 374 return net.getNode(id) 375 } 376 377 // GetNode gets the node with the given name, returning nil if the node does 378 // not exist 379 func (net *Network) GetNodeByName(name string) *Node { 380 net.lock.Lock() 381 defer net.lock.Unlock() 382 return net.getNodeByName(name) 383 } 384 385 // GetNodes returns the existing nodes 386 func (net *Network) GetNodes() (nodes []*Node) { 387 net.lock.Lock() 388 defer net.lock.Unlock() 389 390 nodes = append(nodes, net.Nodes...) 391 return nodes 392 } 393 394 func (net *Network) getNode(id enode.ID) *Node { 395 i, found := net.nodeMap[id] 396 if !found { 397 return nil 398 } 399 return net.Nodes[i] 400 } 401 402 func (net *Network) getNodeByName(name string) *Node { 403 for _, node := range net.Nodes { 404 if node.Config.Name == name { 405 return node 406 } 407 } 408 return nil 409 } 410 411 // GetConn returns the connection which exists between "one" and "other" 412 // regardless of which node initiated the connection 413 func (net *Network) GetConn(oneID, otherID enode.ID) *Conn { 414 net.lock.Lock() 415 defer net.lock.Unlock() 416 return net.getConn(oneID, otherID) 417 } 418 419 // GetOrCreateConn is like GetConn but creates the connection if it doesn't 420 // already exist 421 func (net *Network) GetOrCreateConn(oneID, otherID enode.ID) (*Conn, error) { 422 net.lock.Lock() 423 defer net.lock.Unlock() 424 return net.getOrCreateConn(oneID, otherID) 425 } 426 427 func (net *Network) getOrCreateConn(oneID, otherID enode.ID) (*Conn, error) { 428 if conn := net.getConn(oneID, otherID); conn != nil { 429 return conn, nil 430 } 431 432 one := net.getNode(oneID) 433 if one == nil { 434 return nil, fmt.Errorf("node %v does not exist", oneID) 435 } 436 other := net.getNode(otherID) 437 if other == nil { 438 return nil, fmt.Errorf("node %v does not exist", otherID) 439 } 440 conn := &Conn{ 441 One: oneID, 442 Other: otherID, 443 one: one, 444 other: other, 445 } 446 label := ConnLabel(oneID, otherID) 447 net.connMap[label] = len(net.Conns) 448 net.Conns = append(net.Conns, conn) 449 return conn, nil 450 } 451 452 func (net *Network) getConn(oneID, otherID enode.ID) *Conn { 453 label := ConnLabel(oneID, otherID) 454 i, found := net.connMap[label] 455 if !found { 456 return nil 457 } 458 return net.Conns[i] 459 } 460 461 // InitConn(one, other) retrieves the connectiton model for the connection between 462 // peers one and other, or creates a new one if it does not exist 463 // the order of nodes does not matter, i.e., Conn(i,j) == Conn(j, i) 464 // it checks if the connection is already up, and if the nodes are running 465 // NOTE: 466 // it also checks whether there has been recent attempt to connect the peers 467 // this is cheating as the simulation is used as an oracle and know about 468 // remote peers attempt to connect to a node which will then not initiate the connection 469 func (net *Network) InitConn(oneID, otherID enode.ID) (*Conn, error) { 470 net.lock.Lock() 471 defer net.lock.Unlock() 472 if oneID == otherID { 473 return nil, fmt.Errorf("refusing to connect to self %v", oneID) 474 } 475 conn, err := net.getOrCreateConn(oneID, otherID) 476 if err != nil { 477 return nil, err 478 } 479 if conn.Up { 480 return nil, fmt.Errorf("%v and %v already connected", oneID, otherID) 481 } 482 if time.Since(conn.initiated) < DialBanTimeout { 483 return nil, fmt.Errorf("connection between %v and %v recently attempted", oneID, otherID) 484 } 485 486 err = conn.nodesUp() 487 if err != nil { 488 log.Trace("Nodes not up", "err", err) 489 return nil, fmt.Errorf("nodes not up: %v", err) 490 } 491 log.Debug("Connection initiated", "id", oneID, "other", otherID) 492 conn.initiated = time.Now() 493 return conn, nil 494 } 495 496 // Shutdown stops all nodes in the network and closes the quit channel 497 func (net *Network) Shutdown() { 498 for _, node := range net.Nodes { 499 log.Debug("Stopping node", "id", node.ID()) 500 if err := node.Stop(); err != nil { 501 log.Warn("Can't stop node", "id", node.ID(), "err", err) 502 } 503 } 504 close(net.quitc) 505 } 506 507 //Reset resets all network properties: 508 //emtpies the nodes and the connection list 509 func (net *Network) Reset() { 510 net.lock.Lock() 511 defer net.lock.Unlock() 512 513 //re-initialize the maps 514 net.connMap = make(map[string]int) 515 net.nodeMap = make(map[enode.ID]int) 516 517 net.Nodes = nil 518 net.Conns = nil 519 } 520 521 // Node is a wrapper around adapters.Node which is used to track the status 522 // of a node in the network 523 type Node struct { 524 adapters.Node `json:"-"` 525 526 // Config if the config used to created the node 527 Config *adapters.NodeConfig `json:"config"` 528 529 // Up tracks whether or not the node is running 530 Up bool `json:"up"` 531 } 532 533 // ID returns the ID of the node 534 func (n *Node) ID() enode.ID { 535 return n.Config.ID 536 } 537 538 // String returns a log-friendly string 539 func (n *Node) String() string { 540 return fmt.Sprintf("Node %v", n.ID().TerminalString()) 541 } 542 543 // NodeInfo returns information about the node 544 func (n *Node) NodeInfo() *p2p.NodeInfo { 545 // avoid a panic if the node is not started yet 546 if n.Node == nil { 547 return nil 548 } 549 info := n.Node.NodeInfo() 550 info.Name = n.Config.Name 551 return info 552 } 553 554 // MarshalJSON implements the json.Marshaler interface so that the encoded 555 // JSON includes the NodeInfo 556 func (n *Node) MarshalJSON() ([]byte, error) { 557 return json.Marshal(struct { 558 Info *p2p.NodeInfo `json:"info,omitempty"` 559 Config *adapters.NodeConfig `json:"config,omitempty"` 560 Up bool `json:"up"` 561 }{ 562 Info: n.NodeInfo(), 563 Config: n.Config, 564 Up: n.Up, 565 }) 566 } 567 568 // Conn represents a connection between two nodes in the network 569 type Conn struct { 570 // One is the node which initiated the connection 571 One enode.ID `json:"one"` 572 573 // Other is the node which the connection was made to 574 Other enode.ID `json:"other"` 575 576 // Up tracks whether or not the connection is active 577 Up bool `json:"up"` 578 // Registers when the connection was grabbed to dial 579 initiated time.Time 580 581 one *Node 582 other *Node 583 } 584 585 // nodesUp returns whether both nodes are currently up 586 func (c *Conn) nodesUp() error { 587 if !c.one.Up { 588 return fmt.Errorf("one %v is not up", c.One) 589 } 590 if !c.other.Up { 591 return fmt.Errorf("other %v is not up", c.Other) 592 } 593 return nil 594 } 595 596 // String returns a log-friendly string 597 func (c *Conn) String() string { 598 return fmt.Sprintf("Conn %v->%v", c.One.TerminalString(), c.Other.TerminalString()) 599 } 600 601 // Msg represents a p2p message sent between two nodes in the network 602 type Msg struct { 603 One enode.ID `json:"one"` 604 Other enode.ID `json:"other"` 605 Protocol string `json:"protocol"` 606 Code uint64 `json:"code"` 607 Received bool `json:"received"` 608 } 609 610 // String returns a log-friendly string 611 func (m *Msg) String() string { 612 return fmt.Sprintf("Msg(%d) %v->%v", m.Code, m.One.TerminalString(), m.Other.TerminalString()) 613 } 614 615 // ConnLabel generates a deterministic string which represents a connection 616 // between two nodes, used to compare if two connections are between the same 617 // nodes 618 func ConnLabel(source, target enode.ID) string { 619 var first, second enode.ID 620 if bytes.Compare(source.Bytes(), target.Bytes()) > 0 { 621 first = target 622 second = source 623 } else { 624 first = source 625 second = target 626 } 627 return fmt.Sprintf("%v-%v", first, second) 628 } 629 630 // Snapshot represents the state of a network at a single point in time and can 631 // be used to restore the state of a network 632 type Snapshot struct { 633 Nodes []NodeSnapshot `json:"nodes,omitempty"` 634 Conns []Conn `json:"conns,omitempty"` 635 } 636 637 // NodeSnapshot represents the state of a node in the network 638 type NodeSnapshot struct { 639 Node Node `json:"node,omitempty"` 640 641 // Snapshots is arbitrary data gathered from calling node.Snapshots() 642 Snapshots map[string][]byte `json:"snapshots,omitempty"` 643 } 644 645 // Snapshot creates a network snapshot 646 func (net *Network) Snapshot() (*Snapshot, error) { 647 net.lock.Lock() 648 defer net.lock.Unlock() 649 snap := &Snapshot{ 650 Nodes: make([]NodeSnapshot, len(net.Nodes)), 651 Conns: make([]Conn, len(net.Conns)), 652 } 653 for i, node := range net.Nodes { 654 snap.Nodes[i] = NodeSnapshot{Node: *node} 655 if !node.Up { 656 continue 657 } 658 snapshots, err := node.Snapshots() 659 if err != nil { 660 return nil, err 661 } 662 snap.Nodes[i].Snapshots = snapshots 663 } 664 for i, conn := range net.Conns { 665 snap.Conns[i] = *conn 666 } 667 return snap, nil 668 } 669 670 // Load loads a network snapshot 671 func (net *Network) Load(snap *Snapshot) error { 672 for _, n := range snap.Nodes { 673 if _, err := net.NewNodeWithConfig(n.Node.Config); err != nil { 674 return err 675 } 676 if !n.Node.Up { 677 continue 678 } 679 if err := net.startWithSnapshots(n.Node.Config.ID, n.Snapshots); err != nil { 680 return err 681 } 682 } 683 for _, conn := range snap.Conns { 684 685 if !net.GetNode(conn.One).Up || !net.GetNode(conn.Other).Up { 686 //in this case, at least one of the nodes of a connection is not up, 687 //so it would result in the snapshot `Load` to fail 688 continue 689 } 690 if err := net.Connect(conn.One, conn.Other); err != nil { 691 return err 692 } 693 } 694 return nil 695 } 696 697 // Subscribe reads control events from a channel and executes them 698 func (net *Network) Subscribe(events chan *Event) { 699 for { 700 select { 701 case event, ok := <-events: 702 if !ok { 703 return 704 } 705 if event.Control { 706 net.executeControlEvent(event) 707 } 708 case <-net.quitc: 709 return 710 } 711 } 712 } 713 714 func (net *Network) executeControlEvent(event *Event) { 715 log.Trace("Executing control event", "type", event.Type, "event", event) 716 switch event.Type { 717 case EventTypeNode: 718 if err := net.executeNodeEvent(event); err != nil { 719 log.Error("Error executing node event", "event", event, "err", err) 720 } 721 case EventTypeConn: 722 if err := net.executeConnEvent(event); err != nil { 723 log.Error("Error executing conn event", "event", event, "err", err) 724 } 725 case EventTypeMsg: 726 log.Warn("Ignoring control msg event") 727 } 728 } 729 730 func (net *Network) executeNodeEvent(e *Event) error { 731 if !e.Node.Up { 732 return net.Stop(e.Node.ID()) 733 } 734 735 if _, err := net.NewNodeWithConfig(e.Node.Config); err != nil { 736 return err 737 } 738 return net.Start(e.Node.ID()) 739 } 740 741 func (net *Network) executeConnEvent(e *Event) error { 742 if e.Conn.Up { 743 return net.Connect(e.Conn.One, e.Conn.Other) 744 } else { 745 return net.Disconnect(e.Conn.One, e.Conn.Other) 746 } 747 }