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