github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/network/simulation/node.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:47</date>
    10  //</624342674073194496>
    11  
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  //
    25  //
    26  //
    27  
    28  package simulation
    29  
    30  import (
    31  	"encoding/json"
    32  	"errors"
    33  	"io/ioutil"
    34  	"math/rand"
    35  	"os"
    36  	"time"
    37  
    38  	"github.com/ethereum/go-ethereum/log"
    39  	"github.com/ethereum/go-ethereum/p2p/discover"
    40  	"github.com/ethereum/go-ethereum/p2p/simulations"
    41  	"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
    42  )
    43  
    44  //
    45  func (s *Simulation) NodeIDs() (ids []discover.NodeID) {
    46  	nodes := s.Net.GetNodes()
    47  	ids = make([]discover.NodeID, len(nodes))
    48  	for i, node := range nodes {
    49  		ids[i] = node.ID()
    50  	}
    51  	return ids
    52  }
    53  
    54  //
    55  func (s *Simulation) UpNodeIDs() (ids []discover.NodeID) {
    56  	nodes := s.Net.GetNodes()
    57  	for _, node := range nodes {
    58  		if node.Up {
    59  			ids = append(ids, node.ID())
    60  		}
    61  	}
    62  	return ids
    63  }
    64  
    65  //
    66  func (s *Simulation) DownNodeIDs() (ids []discover.NodeID) {
    67  	nodes := s.Net.GetNodes()
    68  	for _, node := range nodes {
    69  		if !node.Up {
    70  			ids = append(ids, node.ID())
    71  		}
    72  	}
    73  	return ids
    74  }
    75  
    76  //
    77  //
    78  type AddNodeOption func(*adapters.NodeConfig)
    79  
    80  //
    81  //
    82  func AddNodeWithMsgEvents(enable bool) AddNodeOption {
    83  	return func(o *adapters.NodeConfig) {
    84  		o.EnableMsgEvents = enable
    85  	}
    86  }
    87  
    88  //
    89  //
    90  //
    91  //
    92  func AddNodeWithService(serviceName string) AddNodeOption {
    93  	return func(o *adapters.NodeConfig) {
    94  		o.Services = append(o.Services, serviceName)
    95  	}
    96  }
    97  
    98  //
    99  //
   100  //
   101  //
   102  func (s *Simulation) AddNode(opts ...AddNodeOption) (id discover.NodeID, err error) {
   103  	conf := adapters.RandomNodeConfig()
   104  	for _, o := range opts {
   105  		o(conf)
   106  	}
   107  	if len(conf.Services) == 0 {
   108  		conf.Services = s.serviceNames
   109  	}
   110  	node, err := s.Net.NewNodeWithConfig(conf)
   111  	if err != nil {
   112  		return id, err
   113  	}
   114  	return node.ID(), s.Net.Start(node.ID())
   115  }
   116  
   117  //
   118  //
   119  func (s *Simulation) AddNodes(count int, opts ...AddNodeOption) (ids []discover.NodeID, err error) {
   120  	ids = make([]discover.NodeID, 0, count)
   121  	for i := 0; i < count; i++ {
   122  		id, err := s.AddNode(opts...)
   123  		if err != nil {
   124  			return nil, err
   125  		}
   126  		ids = append(ids, id)
   127  	}
   128  	return ids, nil
   129  }
   130  
   131  //
   132  //
   133  func (s *Simulation) AddNodesAndConnectFull(count int, opts ...AddNodeOption) (ids []discover.NodeID, err error) {
   134  	if count < 2 {
   135  		return nil, errors.New("count of nodes must be at least 2")
   136  	}
   137  	ids, err = s.AddNodes(count, opts...)
   138  	if err != nil {
   139  		return nil, err
   140  	}
   141  	err = s.ConnectNodesFull(ids)
   142  	if err != nil {
   143  		return nil, err
   144  	}
   145  	return ids, nil
   146  }
   147  
   148  //
   149  //
   150  //
   151  func (s *Simulation) AddNodesAndConnectChain(count int, opts ...AddNodeOption) (ids []discover.NodeID, err error) {
   152  	if count < 2 {
   153  		return nil, errors.New("count of nodes must be at least 2")
   154  	}
   155  	id, err := s.AddNode(opts...)
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  	err = s.ConnectToLastNode(id)
   160  	if err != nil {
   161  		return nil, err
   162  	}
   163  	ids, err = s.AddNodes(count-1, opts...)
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  	ids = append([]discover.NodeID{id}, ids...)
   168  	err = s.ConnectNodesChain(ids)
   169  	if err != nil {
   170  		return nil, err
   171  	}
   172  	return ids, nil
   173  }
   174  
   175  //
   176  //
   177  func (s *Simulation) AddNodesAndConnectRing(count int, opts ...AddNodeOption) (ids []discover.NodeID, err error) {
   178  	if count < 2 {
   179  		return nil, errors.New("count of nodes must be at least 2")
   180  	}
   181  	ids, err = s.AddNodes(count, opts...)
   182  	if err != nil {
   183  		return nil, err
   184  	}
   185  	err = s.ConnectNodesRing(ids)
   186  	if err != nil {
   187  		return nil, err
   188  	}
   189  	return ids, nil
   190  }
   191  
   192  //
   193  //
   194  func (s *Simulation) AddNodesAndConnectStar(count int, opts ...AddNodeOption) (ids []discover.NodeID, err error) {
   195  	if count < 2 {
   196  		return nil, errors.New("count of nodes must be at least 2")
   197  	}
   198  	ids, err = s.AddNodes(count, opts...)
   199  	if err != nil {
   200  		return nil, err
   201  	}
   202  	err = s.ConnectNodesStar(ids[0], ids[1:])
   203  	if err != nil {
   204  		return nil, err
   205  	}
   206  	return ids, nil
   207  }
   208  
   209  //
   210  //
   211  //
   212  func (s *Simulation) UploadSnapshot(snapshotFile string, opts ...AddNodeOption) error {
   213  	f, err := os.Open(snapshotFile)
   214  	if err != nil {
   215  		return err
   216  	}
   217  	defer func() {
   218  		err := f.Close()
   219  		if err != nil {
   220  			log.Error("Error closing snapshot file", "err", err)
   221  		}
   222  	}()
   223  	jsonbyte, err := ioutil.ReadAll(f)
   224  	if err != nil {
   225  		return err
   226  	}
   227  	var snap simulations.Snapshot
   228  	err = json.Unmarshal(jsonbyte, &snap)
   229  	if err != nil {
   230  		return err
   231  	}
   232  
   233  //
   234  //
   235  //
   236  	for _, n := range snap.Nodes {
   237  		n.Node.Config.EnableMsgEvents = true
   238  		n.Node.Config.Services = s.serviceNames
   239  		for _, o := range opts {
   240  			o(n.Node.Config)
   241  		}
   242  	}
   243  
   244  	log.Info("Waiting for p2p connections to be established...")
   245  
   246  //
   247  	err = s.Net.Load(&snap)
   248  	if err != nil {
   249  		return err
   250  	}
   251  	log.Info("Snapshot loaded")
   252  	return nil
   253  }
   254  
   255  //
   256  //
   257  //
   258  //
   259  //
   260  func (s *Simulation) SetPivotNode(id discover.NodeID) {
   261  	s.mu.Lock()
   262  	defer s.mu.Unlock()
   263  	s.pivotNodeID = &id
   264  }
   265  
   266  //
   267  //
   268  func (s *Simulation) PivotNodeID() (id *discover.NodeID) {
   269  	s.mu.Lock()
   270  	defer s.mu.Unlock()
   271  	return s.pivotNodeID
   272  }
   273  
   274  //
   275  func (s *Simulation) StartNode(id discover.NodeID) (err error) {
   276  	return s.Net.Start(id)
   277  }
   278  
   279  //
   280  func (s *Simulation) StartRandomNode() (id discover.NodeID, err error) {
   281  	n := s.randomDownNode()
   282  	if n == nil {
   283  		return id, ErrNodeNotFound
   284  	}
   285  	return n.ID, s.Net.Start(n.ID)
   286  }
   287  
   288  //
   289  func (s *Simulation) StartRandomNodes(count int) (ids []discover.NodeID, err error) {
   290  	ids = make([]discover.NodeID, 0, count)
   291  	downIDs := s.DownNodeIDs()
   292  	for i := 0; i < count; i++ {
   293  		n := s.randomNode(downIDs, ids...)
   294  		if n == nil {
   295  			return nil, ErrNodeNotFound
   296  		}
   297  		err = s.Net.Start(n.ID)
   298  		if err != nil {
   299  			return nil, err
   300  		}
   301  		ids = append(ids, n.ID)
   302  	}
   303  	return ids, nil
   304  }
   305  
   306  //
   307  func (s *Simulation) StopNode(id discover.NodeID) (err error) {
   308  	return s.Net.Stop(id)
   309  }
   310  
   311  //
   312  func (s *Simulation) StopRandomNode() (id discover.NodeID, err error) {
   313  	n := s.RandomUpNode()
   314  	if n == nil {
   315  		return id, ErrNodeNotFound
   316  	}
   317  	return n.ID, s.Net.Stop(n.ID)
   318  }
   319  
   320  //
   321  func (s *Simulation) StopRandomNodes(count int) (ids []discover.NodeID, err error) {
   322  	ids = make([]discover.NodeID, 0, count)
   323  	upIDs := s.UpNodeIDs()
   324  	for i := 0; i < count; i++ {
   325  		n := s.randomNode(upIDs, ids...)
   326  		if n == nil {
   327  			return nil, ErrNodeNotFound
   328  		}
   329  		err = s.Net.Stop(n.ID)
   330  		if err != nil {
   331  			return nil, err
   332  		}
   333  		ids = append(ids, n.ID)
   334  	}
   335  	return ids, nil
   336  }
   337  
   338  //
   339  func init() {
   340  	rand.Seed(time.Now().UnixNano())
   341  }
   342  
   343  //
   344  //
   345  func (s *Simulation) RandomUpNode(exclude ...discover.NodeID) *adapters.SimNode {
   346  	return s.randomNode(s.UpNodeIDs(), exclude...)
   347  }
   348  
   349  //
   350  func (s *Simulation) randomDownNode(exclude ...discover.NodeID) *adapters.SimNode {
   351  	return s.randomNode(s.DownNodeIDs(), exclude...)
   352  }
   353  
   354  //
   355  func (s *Simulation) randomNode(ids []discover.NodeID, exclude ...discover.NodeID) *adapters.SimNode {
   356  	for _, e := range exclude {
   357  		var i int
   358  		for _, id := range ids {
   359  			if id == e {
   360  				ids = append(ids[:i], ids[i+1:]...)
   361  			} else {
   362  				i++
   363  			}
   364  		}
   365  	}
   366  	l := len(ids)
   367  	if l == 0 {
   368  		return nil
   369  	}
   370  	n := s.Net.GetNode(ids[rand.Intn(l)])
   371  	node, _ := n.Node.(*adapters.SimNode)
   372  	return node
   373  }
   374