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