github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/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 19:16:43</date>
    10  //</624450114563346432>
    11  
    12  
    13  package simulation
    14  
    15  import (
    16  	"encoding/json"
    17  	"errors"
    18  	"io/ioutil"
    19  	"math/rand"
    20  	"os"
    21  	"time"
    22  
    23  	"github.com/ethereum/go-ethereum/log"
    24  	"github.com/ethereum/go-ethereum/p2p/enode"
    25  	"github.com/ethereum/go-ethereum/p2p/simulations"
    26  	"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
    27  )
    28  
    29  //nodeids返回网络中所有节点的nodeid。
    30  func (s *Simulation) NodeIDs() (ids []enode.ID) {
    31  	nodes := s.Net.GetNodes()
    32  	ids = make([]enode.ID, len(nodes))
    33  	for i, node := range nodes {
    34  		ids[i] = node.ID()
    35  	}
    36  	return ids
    37  }
    38  
    39  //up nodeids返回网络上的节点的nodeid。
    40  func (s *Simulation) UpNodeIDs() (ids []enode.ID) {
    41  	nodes := s.Net.GetNodes()
    42  	for _, node := range nodes {
    43  		if node.Up {
    44  			ids = append(ids, node.ID())
    45  		}
    46  	}
    47  	return ids
    48  }
    49  
    50  //downnodeids返回网络中停止的节点的nodeid。
    51  func (s *Simulation) DownNodeIDs() (ids []enode.ID) {
    52  	nodes := s.Net.GetNodes()
    53  	for _, node := range nodes {
    54  		if !node.Up {
    55  			ids = append(ids, node.ID())
    56  		}
    57  	}
    58  	return ids
    59  }
    60  
    61  //AddNodeOption定义可以传递的选项
    62  //到simulation.addnode方法。
    63  type AddNodeOption func(*adapters.NodeConfig)
    64  
    65  //addnodewithmsgevents设置启用msgevents选项
    66  //给NodeConfig。
    67  func AddNodeWithMsgEvents(enable bool) AddNodeOption {
    68  	return func(o *adapters.NodeConfig) {
    69  		o.EnableMsgEvents = enable
    70  	}
    71  }
    72  
    73  //addNodeWithService指定一个应为
    74  //在节点上启动。此选项可以作为变量重复
    75  //参数toe add node和其他与添加节点相关的方法。
    76  //如果未指定addNodeWithService,则将启动所有服务。
    77  func AddNodeWithService(serviceName string) AddNodeOption {
    78  	return func(o *adapters.NodeConfig) {
    79  		o.Services = append(o.Services, serviceName)
    80  	}
    81  }
    82  
    83  //addnode创建一个随机配置的新节点,
    84  //将提供的选项应用于配置并将节点添加到网络。
    85  //默认情况下,所有服务都将在一个节点上启动。如果一个或多个
    86  //提供了addnodeWithService选项,将仅启动指定的服务。
    87  func (s *Simulation) AddNode(opts ...AddNodeOption) (id enode.ID, err error) {
    88  	conf := adapters.RandomNodeConfig()
    89  	for _, o := range opts {
    90  		o(conf)
    91  	}
    92  	if len(conf.Services) == 0 {
    93  		conf.Services = s.serviceNames
    94  	}
    95  	node, err := s.Net.NewNodeWithConfig(conf)
    96  	if err != nil {
    97  		return id, err
    98  	}
    99  	return node.ID(), s.Net.Start(node.ID())
   100  }
   101  
   102  //addnodes创建具有随机配置的新节点,
   103  //将提供的选项应用于配置并将节点添加到网络。
   104  func (s *Simulation) AddNodes(count int, opts ...AddNodeOption) (ids []enode.ID, err error) {
   105  	ids = make([]enode.ID, 0, count)
   106  	for i := 0; i < count; i++ {
   107  		id, err := s.AddNode(opts...)
   108  		if err != nil {
   109  			return nil, err
   110  		}
   111  		ids = append(ids, id)
   112  	}
   113  	return ids, nil
   114  }
   115  
   116  //addnodesandconnectfull是一个结合了
   117  //addnodes和connectnodesfull。将只连接新节点。
   118  func (s *Simulation) AddNodesAndConnectFull(count int, opts ...AddNodeOption) (ids []enode.ID, err error) {
   119  	if count < 2 {
   120  		return nil, errors.New("count of nodes must be at least 2")
   121  	}
   122  	ids, err = s.AddNodes(count, opts...)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  	err = s.Net.ConnectNodesFull(ids)
   127  	if err != nil {
   128  		return nil, err
   129  	}
   130  	return ids, nil
   131  }
   132  
   133  //AddNodesAndConnectChain是一个结合了
   134  //添加节点和连接节点链。链条将从最后一个继续
   135  //添加节点,如果在使用connectToLastNode方法的模拟中有节点。
   136  func (s *Simulation) AddNodesAndConnectChain(count int, opts ...AddNodeOption) (ids []enode.ID, err error) {
   137  	if count < 2 {
   138  		return nil, errors.New("count of nodes must be at least 2")
   139  	}
   140  	id, err := s.AddNode(opts...)
   141  	if err != nil {
   142  		return nil, err
   143  	}
   144  	err = s.Net.ConnectToLastNode(id)
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  	ids, err = s.AddNodes(count-1, opts...)
   149  	if err != nil {
   150  		return nil, err
   151  	}
   152  	ids = append([]enode.ID{id}, ids...)
   153  	err = s.Net.ConnectNodesChain(ids)
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  	return ids, nil
   158  }
   159  
   160  //AddNodesAndConnectRing是一个结合了
   161  //添加节点和连接节点。
   162  func (s *Simulation) AddNodesAndConnectRing(count int, opts ...AddNodeOption) (ids []enode.ID, err error) {
   163  	if count < 2 {
   164  		return nil, errors.New("count of nodes must be at least 2")
   165  	}
   166  	ids, err = s.AddNodes(count, opts...)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  	err = s.Net.ConnectNodesRing(ids)
   171  	if err != nil {
   172  		return nil, err
   173  	}
   174  	return ids, nil
   175  }
   176  
   177  //addnodesandconnectstar是一个结合了
   178  //添加节点和ConnectNodesStar。
   179  func (s *Simulation) AddNodesAndConnectStar(count int, opts ...AddNodeOption) (ids []enode.ID, err error) {
   180  	if count < 2 {
   181  		return nil, errors.New("count of nodes must be at least 2")
   182  	}
   183  	ids, err = s.AddNodes(count, opts...)
   184  	if err != nil {
   185  		return nil, err
   186  	}
   187  	err = s.Net.ConnectNodesStar(ids[1:], ids[0])
   188  	if err != nil {
   189  		return nil, err
   190  	}
   191  	return ids, nil
   192  }
   193  
   194  //uploadSnapshot将快照上载到模拟
   195  //此方法尝试打开提供的JSON文件,将配置应用于所有节点。
   196  //然后将快照加载到仿真网络中
   197  func (s *Simulation) UploadSnapshot(snapshotFile string, opts ...AddNodeOption) error {
   198  	f, err := os.Open(snapshotFile)
   199  	if err != nil {
   200  		return err
   201  	}
   202  	defer func() {
   203  		err := f.Close()
   204  		if err != nil {
   205  			log.Error("Error closing snapshot file", "err", err)
   206  		}
   207  	}()
   208  	jsonbyte, err := ioutil.ReadAll(f)
   209  	if err != nil {
   210  		return err
   211  	}
   212  	var snap simulations.Snapshot
   213  	err = json.Unmarshal(jsonbyte, &snap)
   214  	if err != nil {
   215  		return err
   216  	}
   217  
   218  //快照可能未设置EnableMsgeEvents属性
   219  //以防万一,把它设为真!
   220  //(我们需要在上传前等待消息)
   221  	for _, n := range snap.Nodes {
   222  		n.Node.Config.EnableMsgEvents = true
   223  		n.Node.Config.Services = s.serviceNames
   224  		for _, o := range opts {
   225  			o(n.Node.Config)
   226  		}
   227  	}
   228  
   229  	log.Info("Waiting for p2p connections to be established...")
   230  
   231  //现在我们可以加载快照了
   232  	err = s.Net.Load(&snap)
   233  	if err != nil {
   234  		return err
   235  	}
   236  	log.Info("Snapshot loaded")
   237  	return nil
   238  }
   239  
   240  //startnode按nodeid启动节点。
   241  func (s *Simulation) StartNode(id enode.ID) (err error) {
   242  	return s.Net.Start(id)
   243  }
   244  
   245  //startrandomnode启动随机节点。
   246  func (s *Simulation) StartRandomNode() (id enode.ID, err error) {
   247  	n := s.Net.GetRandomDownNode()
   248  	if n == nil {
   249  		return id, ErrNodeNotFound
   250  	}
   251  	return n.ID(), s.Net.Start(n.ID())
   252  }
   253  
   254  //startrandomnodes启动随机节点。
   255  func (s *Simulation) StartRandomNodes(count int) (ids []enode.ID, err error) {
   256  	ids = make([]enode.ID, 0, count)
   257  	for i := 0; i < count; i++ {
   258  		n := s.Net.GetRandomDownNode()
   259  		if n == nil {
   260  			return nil, ErrNodeNotFound
   261  		}
   262  		err = s.Net.Start(n.ID())
   263  		if err != nil {
   264  			return nil, err
   265  		}
   266  		ids = append(ids, n.ID())
   267  	}
   268  	return ids, nil
   269  }
   270  
   271  //stopnode按nodeid停止节点。
   272  func (s *Simulation) StopNode(id enode.ID) (err error) {
   273  	return s.Net.Stop(id)
   274  }
   275  
   276  //StopRandomNode停止随机节点。
   277  func (s *Simulation) StopRandomNode() (id enode.ID, err error) {
   278  	n := s.Net.GetRandomUpNode()
   279  	if n == nil {
   280  		return id, ErrNodeNotFound
   281  	}
   282  	return n.ID(), s.Net.Stop(n.ID())
   283  }
   284  
   285  //StopRandomNodes停止随机节点。
   286  func (s *Simulation) StopRandomNodes(count int) (ids []enode.ID, err error) {
   287  	ids = make([]enode.ID, 0, count)
   288  	for i := 0; i < count; i++ {
   289  		n := s.Net.GetRandomUpNode()
   290  		if n == nil {
   291  			return nil, ErrNodeNotFound
   292  		}
   293  		err = s.Net.Stop(n.ID())
   294  		if err != nil {
   295  			return nil, err
   296  		}
   297  		ids = append(ids, n.ID())
   298  	}
   299  	return ids, nil
   300  }
   301  
   302  //为simulation.randomnode种子随机生成器。
   303  func init() {
   304  	rand.Seed(time.Now().UnixNano())
   305  }
   306