github.com/Embreum/go-ethereum@v1.9.6/p2p/simulations/network.go (about)

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