github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/network/p2p/simulations/network.go (about)

     1  package simulations
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/json"
     7  	"fmt"
     8  	"io"
     9  	"sync"
    10  	"time"
    11  
    12  	"github.com/neatlab/neatio/chain/log"
    13  	"github.com/neatlab/neatio/network/p2p"
    14  	"github.com/neatlab/neatio/network/p2p/discover"
    15  	"github.com/neatlab/neatio/network/p2p/simulations/adapters"
    16  	"github.com/neatlab/neatio/utilities/event"
    17  )
    18  
    19  var dialBanTimeout = 200 * time.Millisecond
    20  
    21  type NetworkConfig struct {
    22  	ID             string `json:"id"`
    23  	DefaultService string `json:"default_service,omitempty"`
    24  }
    25  
    26  type Network struct {
    27  	NetworkConfig
    28  
    29  	Nodes   []*Node `json:"nodes"`
    30  	nodeMap map[discover.NodeID]int
    31  
    32  	Conns   []*Conn `json:"conns"`
    33  	connMap map[string]int
    34  
    35  	nodeAdapter adapters.NodeAdapter
    36  	events      event.Feed
    37  	lock        sync.RWMutex
    38  	quitc       chan struct{}
    39  }
    40  
    41  func NewNetwork(nodeAdapter adapters.NodeAdapter, conf *NetworkConfig) *Network {
    42  	return &Network{
    43  		NetworkConfig: *conf,
    44  		nodeAdapter:   nodeAdapter,
    45  		nodeMap:       make(map[discover.NodeID]int),
    46  		connMap:       make(map[string]int),
    47  		quitc:         make(chan struct{}),
    48  	}
    49  }
    50  
    51  func (self *Network) Events() *event.Feed {
    52  	return &self.events
    53  }
    54  
    55  func (self *Network) NewNode() (*Node, error) {
    56  	conf := adapters.RandomNodeConfig()
    57  	conf.Services = []string{self.DefaultService}
    58  	return self.NewNodeWithConfig(conf)
    59  }
    60  
    61  func (self *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error) {
    62  	self.lock.Lock()
    63  	defer self.lock.Unlock()
    64  
    65  	if conf.ID == (discover.NodeID{}) {
    66  		c := adapters.RandomNodeConfig()
    67  		conf.ID = c.ID
    68  		conf.PrivateKey = c.PrivateKey
    69  	}
    70  	id := conf.ID
    71  	if conf.Reachable == nil {
    72  		conf.Reachable = func(otherID discover.NodeID) bool {
    73  			_, err := self.InitConn(conf.ID, otherID)
    74  			return err == nil
    75  		}
    76  	}
    77  
    78  	if conf.Name == "" {
    79  		conf.Name = fmt.Sprintf("node%02d", len(self.Nodes)+1)
    80  	}
    81  
    82  	if node := self.getNode(id); node != nil {
    83  		return nil, fmt.Errorf("node with ID %q already exists", id)
    84  	}
    85  	if node := self.getNodeByName(conf.Name); node != nil {
    86  		return nil, fmt.Errorf("node with name %q already exists", conf.Name)
    87  	}
    88  
    89  	if len(conf.Services) == 0 {
    90  		conf.Services = []string{self.DefaultService}
    91  	}
    92  
    93  	adapterNode, err := self.nodeAdapter.NewNode(conf)
    94  	if err != nil {
    95  		return nil, err
    96  	}
    97  	node := &Node{
    98  		Node:   adapterNode,
    99  		Config: conf,
   100  	}
   101  	log.Trace(fmt.Sprintf("node %v created", id))
   102  	self.nodeMap[id] = len(self.Nodes)
   103  	self.Nodes = append(self.Nodes, node)
   104  
   105  	self.events.Send(ControlEvent(node))
   106  
   107  	return node, nil
   108  }
   109  
   110  func (self *Network) Config() *NetworkConfig {
   111  	return &self.NetworkConfig
   112  }
   113  
   114  func (self *Network) StartAll() error {
   115  	for _, node := range self.Nodes {
   116  		if node.Up {
   117  			continue
   118  		}
   119  		if err := self.Start(node.ID()); err != nil {
   120  			return err
   121  		}
   122  	}
   123  	return nil
   124  }
   125  
   126  func (self *Network) StopAll() error {
   127  	for _, node := range self.Nodes {
   128  		if !node.Up {
   129  			continue
   130  		}
   131  		if err := self.Stop(node.ID()); err != nil {
   132  			return err
   133  		}
   134  	}
   135  	return nil
   136  }
   137  
   138  func (self *Network) Start(id discover.NodeID) error {
   139  	return self.startWithSnapshots(id, nil)
   140  }
   141  
   142  func (self *Network) startWithSnapshots(id discover.NodeID, snapshots map[string][]byte) error {
   143  	node := self.GetNode(id)
   144  	if node == nil {
   145  		return fmt.Errorf("node %v does not exist", id)
   146  	}
   147  	if node.Up {
   148  		return fmt.Errorf("node %v already up", id)
   149  	}
   150  	log.Trace(fmt.Sprintf("starting node %v: %v using %v", id, node.Up, self.nodeAdapter.Name()))
   151  	if err := node.Start(snapshots); err != nil {
   152  		log.Warn(fmt.Sprintf("start up failed: %v", err))
   153  		return err
   154  	}
   155  	node.Up = true
   156  	log.Info(fmt.Sprintf("started node %v: %v", id, node.Up))
   157  
   158  	self.events.Send(NewEvent(node))
   159  
   160  	client, err := node.Client()
   161  	if err != nil {
   162  		return fmt.Errorf("error getting rpc client  for node %v: %s", id, err)
   163  	}
   164  	events := make(chan *p2p.PeerEvent)
   165  	sub, err := client.Subscribe(context.Background(), "admin", events, "peerEvents")
   166  	if err != nil {
   167  		return fmt.Errorf("error getting peer events for node %v: %s", id, err)
   168  	}
   169  	go self.watchPeerEvents(id, events, sub)
   170  	return nil
   171  }
   172  
   173  func (self *Network) watchPeerEvents(id discover.NodeID, events chan *p2p.PeerEvent, sub event.Subscription) {
   174  	defer func() {
   175  		sub.Unsubscribe()
   176  
   177  		self.lock.Lock()
   178  		node := self.getNode(id)
   179  		node.Up = false
   180  		self.lock.Unlock()
   181  		self.events.Send(NewEvent(node))
   182  	}()
   183  	for {
   184  		select {
   185  		case event, ok := <-events:
   186  			if !ok {
   187  				return
   188  			}
   189  			peer := event.Peer
   190  			switch event.Type {
   191  
   192  			case p2p.PeerEventTypeAdd:
   193  				self.DidConnect(id, peer)
   194  
   195  			case p2p.PeerEventTypeDrop:
   196  				self.DidDisconnect(id, peer)
   197  
   198  			case p2p.PeerEventTypeMsgSend:
   199  				self.DidSend(id, peer, event.Protocol, *event.MsgCode)
   200  
   201  			case p2p.PeerEventTypeMsgRecv:
   202  				self.DidReceive(peer, id, event.Protocol, *event.MsgCode)
   203  
   204  			}
   205  
   206  		case err := <-sub.Err():
   207  			if err != nil {
   208  				log.Error(fmt.Sprintf("error getting peer events for node %v", id), "err", err)
   209  			}
   210  			return
   211  		}
   212  	}
   213  }
   214  
   215  func (self *Network) Stop(id discover.NodeID) error {
   216  	node := self.GetNode(id)
   217  	if node == nil {
   218  		return fmt.Errorf("node %v does not exist", id)
   219  	}
   220  	if !node.Up {
   221  		return fmt.Errorf("node %v already down", id)
   222  	}
   223  	if err := node.Stop(); err != nil {
   224  		return err
   225  	}
   226  	node.Up = false
   227  	log.Info(fmt.Sprintf("stop node %v: %v", id, node.Up))
   228  
   229  	self.events.Send(ControlEvent(node))
   230  	return nil
   231  }
   232  
   233  func (self *Network) Connect(oneID, otherID discover.NodeID) error {
   234  	log.Debug(fmt.Sprintf("connecting %s to %s", oneID, otherID))
   235  	conn, err := self.InitConn(oneID, otherID)
   236  	if err != nil {
   237  		return err
   238  	}
   239  	client, err := conn.one.Client()
   240  	if err != nil {
   241  		return err
   242  	}
   243  	self.events.Send(ControlEvent(conn))
   244  	return client.Call(nil, "admin_addPeer", string(conn.other.Addr()))
   245  }
   246  
   247  func (self *Network) Disconnect(oneID, otherID discover.NodeID) error {
   248  	conn := self.GetConn(oneID, otherID)
   249  	if conn == nil {
   250  		return fmt.Errorf("connection between %v and %v does not exist", oneID, otherID)
   251  	}
   252  	if !conn.Up {
   253  		return fmt.Errorf("%v and %v already disconnected", oneID, otherID)
   254  	}
   255  	client, err := conn.one.Client()
   256  	if err != nil {
   257  		return err
   258  	}
   259  	self.events.Send(ControlEvent(conn))
   260  	return client.Call(nil, "admin_removePeer", string(conn.other.Addr()))
   261  }
   262  
   263  func (self *Network) DidConnect(one, other discover.NodeID) error {
   264  	conn, err := self.GetOrCreateConn(one, other)
   265  	if err != nil {
   266  		return fmt.Errorf("connection between %v and %v does not exist", one, other)
   267  	}
   268  	if conn.Up {
   269  		return fmt.Errorf("%v and %v already connected", one, other)
   270  	}
   271  	conn.Up = true
   272  	self.events.Send(NewEvent(conn))
   273  	return nil
   274  }
   275  
   276  func (self *Network) DidDisconnect(one, other discover.NodeID) error {
   277  	conn := self.GetConn(one, other)
   278  	if conn == nil {
   279  		return fmt.Errorf("connection between %v and %v does not exist", one, other)
   280  	}
   281  	if !conn.Up {
   282  		return fmt.Errorf("%v and %v already disconnected", one, other)
   283  	}
   284  	conn.Up = false
   285  	conn.initiated = time.Now().Add(-dialBanTimeout)
   286  	self.events.Send(NewEvent(conn))
   287  	return nil
   288  }
   289  
   290  func (self *Network) DidSend(sender, receiver discover.NodeID, proto string, code uint64) error {
   291  	msg := &Msg{
   292  		One:      sender,
   293  		Other:    receiver,
   294  		Protocol: proto,
   295  		Code:     code,
   296  		Received: false,
   297  	}
   298  	self.events.Send(NewEvent(msg))
   299  	return nil
   300  }
   301  
   302  func (self *Network) DidReceive(sender, receiver discover.NodeID, proto string, code uint64) error {
   303  	msg := &Msg{
   304  		One:      sender,
   305  		Other:    receiver,
   306  		Protocol: proto,
   307  		Code:     code,
   308  		Received: true,
   309  	}
   310  	self.events.Send(NewEvent(msg))
   311  	return nil
   312  }
   313  
   314  func (self *Network) GetNode(id discover.NodeID) *Node {
   315  	self.lock.Lock()
   316  	defer self.lock.Unlock()
   317  	return self.getNode(id)
   318  }
   319  
   320  func (self *Network) GetNodeByName(name string) *Node {
   321  	self.lock.Lock()
   322  	defer self.lock.Unlock()
   323  	return self.getNodeByName(name)
   324  }
   325  
   326  func (self *Network) getNode(id discover.NodeID) *Node {
   327  	i, found := self.nodeMap[id]
   328  	if !found {
   329  		return nil
   330  	}
   331  	return self.Nodes[i]
   332  }
   333  
   334  func (self *Network) getNodeByName(name string) *Node {
   335  	for _, node := range self.Nodes {
   336  		if node.Config.Name == name {
   337  			return node
   338  		}
   339  	}
   340  	return nil
   341  }
   342  
   343  func (self *Network) GetNodes() (nodes []*Node) {
   344  	self.lock.Lock()
   345  	defer self.lock.Unlock()
   346  
   347  	nodes = append(nodes, self.Nodes...)
   348  	return nodes
   349  }
   350  
   351  func (self *Network) GetConn(oneID, otherID discover.NodeID) *Conn {
   352  	self.lock.Lock()
   353  	defer self.lock.Unlock()
   354  	return self.getConn(oneID, otherID)
   355  }
   356  
   357  func (self *Network) GetOrCreateConn(oneID, otherID discover.NodeID) (*Conn, error) {
   358  	self.lock.Lock()
   359  	defer self.lock.Unlock()
   360  	return self.getOrCreateConn(oneID, otherID)
   361  }
   362  
   363  func (self *Network) getOrCreateConn(oneID, otherID discover.NodeID) (*Conn, error) {
   364  	if conn := self.getConn(oneID, otherID); conn != nil {
   365  		return conn, nil
   366  	}
   367  
   368  	one := self.getNode(oneID)
   369  	if one == nil {
   370  		return nil, fmt.Errorf("node %v does not exist", oneID)
   371  	}
   372  	other := self.getNode(otherID)
   373  	if other == nil {
   374  		return nil, fmt.Errorf("node %v does not exist", otherID)
   375  	}
   376  	conn := &Conn{
   377  		One:   oneID,
   378  		Other: otherID,
   379  		one:   one,
   380  		other: other,
   381  	}
   382  	label := ConnLabel(oneID, otherID)
   383  	self.connMap[label] = len(self.Conns)
   384  	self.Conns = append(self.Conns, conn)
   385  	return conn, nil
   386  }
   387  
   388  func (self *Network) getConn(oneID, otherID discover.NodeID) *Conn {
   389  	label := ConnLabel(oneID, otherID)
   390  	i, found := self.connMap[label]
   391  	if !found {
   392  		return nil
   393  	}
   394  	return self.Conns[i]
   395  }
   396  
   397  func (self *Network) InitConn(oneID, otherID discover.NodeID) (*Conn, error) {
   398  	self.lock.Lock()
   399  	defer self.lock.Unlock()
   400  	if oneID == otherID {
   401  		return nil, fmt.Errorf("refusing to connect to self %v", oneID)
   402  	}
   403  	conn, err := self.getOrCreateConn(oneID, otherID)
   404  	if err != nil {
   405  		return nil, err
   406  	}
   407  	if time.Since(conn.initiated) < dialBanTimeout {
   408  		return nil, fmt.Errorf("connection between %v and %v recently attempted", oneID, otherID)
   409  	}
   410  	if conn.Up {
   411  		return nil, fmt.Errorf("%v and %v already connected", oneID, otherID)
   412  	}
   413  	err = conn.nodesUp()
   414  	if err != nil {
   415  		return nil, fmt.Errorf("nodes not up: %v", err)
   416  	}
   417  	conn.initiated = time.Now()
   418  	return conn, nil
   419  }
   420  
   421  func (self *Network) Shutdown() {
   422  	for _, node := range self.Nodes {
   423  		log.Debug(fmt.Sprintf("stopping node %s", node.ID().TerminalString()))
   424  		if err := node.Stop(); err != nil {
   425  			log.Warn(fmt.Sprintf("error stopping node %s", node.ID().TerminalString()), "err", err)
   426  		}
   427  
   428  		if closer, ok := node.Node.(io.Closer); ok {
   429  			if err := closer.Close(); err != nil {
   430  				log.Warn("Can't close node", "id", node.ID(), "err", err)
   431  			}
   432  		}
   433  	}
   434  	close(self.quitc)
   435  }
   436  
   437  func (self *Network) Reset() {
   438  	self.lock.Lock()
   439  	defer self.lock.Unlock()
   440  
   441  	self.connMap = make(map[string]int)
   442  	self.nodeMap = make(map[discover.NodeID]int)
   443  
   444  	self.Nodes = nil
   445  	self.Conns = nil
   446  }
   447  
   448  type Node struct {
   449  	adapters.Node `json:"-"`
   450  
   451  	Config *adapters.NodeConfig `json:"config"`
   452  
   453  	Up bool `json:"up"`
   454  }
   455  
   456  func (self *Node) ID() discover.NodeID {
   457  	return self.Config.ID
   458  }
   459  
   460  func (self *Node) String() string {
   461  	return fmt.Sprintf("Node %v", self.ID().TerminalString())
   462  }
   463  
   464  func (self *Node) NodeInfo() *p2p.NodeInfo {
   465  
   466  	if self.Node == nil {
   467  		return nil
   468  	}
   469  	info := self.Node.NodeInfo()
   470  	info.Name = self.Config.Name
   471  	return info
   472  }
   473  
   474  func (self *Node) MarshalJSON() ([]byte, error) {
   475  	return json.Marshal(struct {
   476  		Info   *p2p.NodeInfo        `json:"info,omitempty"`
   477  		Config *adapters.NodeConfig `json:"config,omitempty"`
   478  		Up     bool                 `json:"up"`
   479  	}{
   480  		Info:   self.NodeInfo(),
   481  		Config: self.Config,
   482  		Up:     self.Up,
   483  	})
   484  }
   485  
   486  type Conn struct {
   487  	One discover.NodeID `json:"one"`
   488  
   489  	Other discover.NodeID `json:"other"`
   490  
   491  	Up bool `json:"up"`
   492  
   493  	initiated time.Time
   494  
   495  	one   *Node
   496  	other *Node
   497  }
   498  
   499  func (self *Conn) nodesUp() error {
   500  	if !self.one.Up {
   501  		return fmt.Errorf("one %v is not up", self.One)
   502  	}
   503  	if !self.other.Up {
   504  		return fmt.Errorf("other %v is not up", self.Other)
   505  	}
   506  	return nil
   507  }
   508  
   509  func (self *Conn) String() string {
   510  	return fmt.Sprintf("Conn %v->%v", self.One.TerminalString(), self.Other.TerminalString())
   511  }
   512  
   513  type Msg struct {
   514  	One      discover.NodeID `json:"one"`
   515  	Other    discover.NodeID `json:"other"`
   516  	Protocol string          `json:"protocol"`
   517  	Code     uint64          `json:"code"`
   518  	Received bool            `json:"received"`
   519  }
   520  
   521  func (self *Msg) String() string {
   522  	return fmt.Sprintf("Msg(%d) %v->%v", self.Code, self.One.TerminalString(), self.Other.TerminalString())
   523  }
   524  
   525  func ConnLabel(source, target discover.NodeID) string {
   526  	var first, second discover.NodeID
   527  	if bytes.Compare(source.Bytes(), target.Bytes()) > 0 {
   528  		first = target
   529  		second = source
   530  	} else {
   531  		first = source
   532  		second = target
   533  	}
   534  	return fmt.Sprintf("%v-%v", first, second)
   535  }
   536  
   537  type Snapshot struct {
   538  	Nodes []NodeSnapshot `json:"nodes,omitempty"`
   539  	Conns []Conn         `json:"conns,omitempty"`
   540  }
   541  
   542  type NodeSnapshot struct {
   543  	Node Node `json:"node,omitempty"`
   544  
   545  	Snapshots map[string][]byte `json:"snapshots,omitempty"`
   546  }
   547  
   548  func (self *Network) Snapshot() (*Snapshot, error) {
   549  	self.lock.Lock()
   550  	defer self.lock.Unlock()
   551  	snap := &Snapshot{
   552  		Nodes: make([]NodeSnapshot, len(self.Nodes)),
   553  		Conns: make([]Conn, len(self.Conns)),
   554  	}
   555  	for i, node := range self.Nodes {
   556  		snap.Nodes[i] = NodeSnapshot{Node: *node}
   557  		if !node.Up {
   558  			continue
   559  		}
   560  		snapshots, err := node.Snapshots()
   561  		if err != nil {
   562  			return nil, err
   563  		}
   564  		snap.Nodes[i].Snapshots = snapshots
   565  	}
   566  	for i, conn := range self.Conns {
   567  		snap.Conns[i] = *conn
   568  	}
   569  	return snap, nil
   570  }
   571  
   572  func (self *Network) Load(snap *Snapshot) error {
   573  	for _, n := range snap.Nodes {
   574  		if _, err := self.NewNodeWithConfig(n.Node.Config); err != nil {
   575  			return err
   576  		}
   577  		if !n.Node.Up {
   578  			continue
   579  		}
   580  		if err := self.startWithSnapshots(n.Node.Config.ID, n.Snapshots); err != nil {
   581  			return err
   582  		}
   583  	}
   584  	for _, conn := range snap.Conns {
   585  
   586  		if !self.GetNode(conn.One).Up || !self.GetNode(conn.Other).Up {
   587  
   588  			continue
   589  		}
   590  		if err := self.Connect(conn.One, conn.Other); err != nil {
   591  			return err
   592  		}
   593  	}
   594  	return nil
   595  }
   596  
   597  func (self *Network) Subscribe(events chan *Event) {
   598  	for {
   599  		select {
   600  		case event, ok := <-events:
   601  			if !ok {
   602  				return
   603  			}
   604  			if event.Control {
   605  				self.executeControlEvent(event)
   606  			}
   607  		case <-self.quitc:
   608  			return
   609  		}
   610  	}
   611  }
   612  
   613  func (self *Network) executeControlEvent(event *Event) {
   614  	log.Trace("execute control event", "type", event.Type, "event", event)
   615  	switch event.Type {
   616  	case EventTypeNode:
   617  		if err := self.executeNodeEvent(event); err != nil {
   618  			log.Error("error executing node event", "event", event, "err", err)
   619  		}
   620  	case EventTypeConn:
   621  		if err := self.executeConnEvent(event); err != nil {
   622  			log.Error("error executing conn event", "event", event, "err", err)
   623  		}
   624  	case EventTypeMsg:
   625  		log.Warn("ignoring control msg event")
   626  	}
   627  }
   628  
   629  func (self *Network) executeNodeEvent(e *Event) error {
   630  	if !e.Node.Up {
   631  		return self.Stop(e.Node.ID())
   632  	}
   633  
   634  	if _, err := self.NewNodeWithConfig(e.Node.Config); err != nil {
   635  		return err
   636  	}
   637  	return self.Start(e.Node.ID())
   638  }
   639  
   640  func (self *Network) executeConnEvent(e *Event) error {
   641  	if e.Conn.Up {
   642  		return self.Connect(e.Conn.One, e.Conn.Other)
   643  	} else {
   644  		return self.Disconnect(e.Conn.One, e.Conn.Other)
   645  	}
   646  }