github.com/aidoskuneen/adk-node@v0.0.0-20220315131952-2e32567cb7f4/p2p/simulations/network.go (about)

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