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