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