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