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