github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/p2p/discv5/sim_test.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:44</date> 10 //</624342657384058880> 11 12 13 package discv5 14 15 import ( 16 "crypto/ecdsa" 17 "encoding/binary" 18 "fmt" 19 "math/rand" 20 "net" 21 "strconv" 22 "sync" 23 "sync/atomic" 24 "testing" 25 "time" 26 27 "github.com/ethereum/go-ethereum/common" 28 ) 29 30 //在这个测试中,节点试图随机地解析彼此。 31 func TestSimRandomResolve(t *testing.T) { 32 t.Skip("boring") 33 if runWithPlaygroundTime(t) { 34 return 35 } 36 37 sim := newSimulation() 38 bootnode := sim.launchNode(false) 39 40 //新节点每10秒联接一次。 41 launcher := time.NewTicker(10 * time.Second) 42 go func() { 43 for range launcher.C { 44 net := sim.launchNode(false) 45 go randomResolves(t, sim, net) 46 if err := net.SetFallbackNodes([]*Node{bootnode.Self()}); err != nil { 47 panic(err) 48 } 49 fmt.Printf("launched @ %v: %x\n", time.Now(), net.Self().ID[:16]) 50 } 51 }() 52 53 time.Sleep(3 * time.Hour) 54 launcher.Stop() 55 sim.shutdown() 56 sim.printStats() 57 } 58 59 func TestSimTopics(t *testing.T) { 60 t.Skip("NaCl test") 61 if runWithPlaygroundTime(t) { 62 return 63 } 64 sim := newSimulation() 65 bootnode := sim.launchNode(false) 66 67 go func() { 68 nets := make([]*Network, 1024) 69 for i := range nets { 70 net := sim.launchNode(false) 71 nets[i] = net 72 if err := net.SetFallbackNodes([]*Node{bootnode.Self()}); err != nil { 73 panic(err) 74 } 75 time.Sleep(time.Second * 5) 76 } 77 78 for i, net := range nets { 79 if i < 256 { 80 stop := make(chan struct{}) 81 go net.RegisterTopic(testTopic, stop) 82 go func() { 83 //时间.睡眠(time.second*36000) 84 time.Sleep(time.Second * 40000) 85 close(stop) 86 }() 87 time.Sleep(time.Millisecond * 100) 88 } 89 //时间.睡眠(time.second*10) 90 //时间.睡眠(时间.秒) 91 /*F I%500==499 92 时间.睡眠(time.second*9501) 93 }否则{ 94 时间.睡眠(时间.秒) 95 */ 96 97 } 98 }() 99 100 //新节点每10秒联接一次。 101 /*启动程序:=time.newticker(5*time.second) 102 CNT:=0 103 var printnet*网络 104 转到函数() 105 用于远程发射器.c 106 碳纳米管+ 107 如果cnt<=1000 108 日志:=false/(cnt==500) 109 网络:=sim.launchnode(日志) 110 如果log { 111 打印网 112 } 113 如果CNT>500 { 114 go net.registerTopic(测试主题,无) 115 } 116 如果错误:=net.setFallbackNodes([]*node bootnode.self());错误!= nIL{ 117 惊慌(错误) 118 } 119 } 120 //fmt.printf(“已启动@%v:%x\n”,time.now(),net.self().id[:16]) 121 } 122 }() 123 **/ 124 125 time.Sleep(55000 * time.Second) 126 //发射器 127 sim.shutdown() 128 //sim.printstats()。 129 //printnet.log.printlogs()。 130 } 131 132 /*unc testHierarchicalTopics(i int)[]主题 133 数字:=strconv.formatint(Int64(256+I/4),4) 134 回复:=制造([]主题,5) 135 对于i,:=范围分辨率 136 res[i]=主题(“foo”+数字[1:i+1]) 137 } 138 收益率 139 */ 140 141 142 func testHierarchicalTopics(i int) []Topic { 143 digits := strconv.FormatInt(int64(128+i/8), 2) 144 res := make([]Topic, 8) 145 for i := range res { 146 res[i] = Topic("foo" + digits[1:i+1]) 147 } 148 return res 149 } 150 151 func TestSimTopicHierarchy(t *testing.T) { 152 t.Skip("NaCl test") 153 if runWithPlaygroundTime(t) { 154 return 155 } 156 sim := newSimulation() 157 bootnode := sim.launchNode(false) 158 159 go func() { 160 nets := make([]*Network, 1024) 161 for i := range nets { 162 net := sim.launchNode(false) 163 nets[i] = net 164 if err := net.SetFallbackNodes([]*Node{bootnode.Self()}); err != nil { 165 panic(err) 166 } 167 time.Sleep(time.Second * 5) 168 } 169 170 stop := make(chan struct{}) 171 for i, net := range nets { 172 //如果i<256 { 173 for _, topic := range testHierarchicalTopics(i)[:5] { 174 //fmt.println(“注册”,主题) 175 go net.RegisterTopic(topic, stop) 176 } 177 time.Sleep(time.Millisecond * 100) 178 //} 179 } 180 time.Sleep(time.Second * 90000) 181 close(stop) 182 }() 183 184 time.Sleep(100000 * time.Second) 185 sim.shutdown() 186 } 187 188 func randomResolves(t *testing.T, s *simulation, net *Network) { 189 randtime := func() time.Duration { 190 return time.Duration(rand.Intn(50)+20) * time.Second 191 } 192 lookup := func(target NodeID) bool { 193 result := net.Resolve(target) 194 return result != nil && result.ID == target 195 } 196 197 timer := time.NewTimer(randtime()) 198 for { 199 select { 200 case <-timer.C: 201 target := s.randomNode().Self().ID 202 if !lookup(target) { 203 t.Errorf("node %x: target %x not found", net.Self().ID[:8], target[:8]) 204 } 205 timer.Reset(randtime()) 206 case <-net.closed: 207 return 208 } 209 } 210 } 211 212 type simulation struct { 213 mu sync.RWMutex 214 nodes map[NodeID]*Network 215 nodectr uint32 216 } 217 218 func newSimulation() *simulation { 219 return &simulation{nodes: make(map[NodeID]*Network)} 220 } 221 222 func (s *simulation) shutdown() { 223 s.mu.RLock() 224 alive := make([]*Network, 0, len(s.nodes)) 225 for _, n := range s.nodes { 226 alive = append(alive, n) 227 } 228 defer s.mu.RUnlock() 229 230 for _, n := range alive { 231 n.Close() 232 } 233 } 234 235 func (s *simulation) printStats() { 236 s.mu.Lock() 237 defer s.mu.Unlock() 238 fmt.Println("node counter:", s.nodectr) 239 fmt.Println("alive nodes:", len(s.nodes)) 240 241 //对于u,n:=范围s.nodes 242 //fmt.printf(“%x\n”,n.tab.self.id[:8]) 243 //传输:=N.conn.(*SimTransport) 244 //fmt.println(“已加入:”,transport.jointime) 245 //fmt.println(“发送:”,transport.hashctr) 246 //fmt.println(“表格大小:”,n.tab.count) 247 //} 248 249 /*或u,n:=范围s.nodes 250 打印文件() 251 fmt.printf(“***节点%x\n”,n.tab.self.id[:8]) 252 n.log.printlogs()。 253 */ 254 255 256 } 257 258 func (s *simulation) randomNode() *Network { 259 s.mu.Lock() 260 defer s.mu.Unlock() 261 262 n := rand.Intn(len(s.nodes)) 263 for _, net := range s.nodes { 264 if n == 0 { 265 return net 266 } 267 n-- 268 } 269 return nil 270 } 271 272 func (s *simulation) launchNode(log bool) *Network { 273 var ( 274 num = s.nodectr 275 key = newkey() 276 id = PubkeyID(&key.PublicKey) 277 ip = make(net.IP, 4) 278 ) 279 s.nodectr++ 280 binary.BigEndian.PutUint32(ip, num) 281 ip[0] = 10 282 addr := &net.UDPAddr{IP: ip, Port: 30303} 283 284 transport := &simTransport{joinTime: time.Now(), sender: id, senderAddr: addr, sim: s, priv: key} 285 net, err := newNetwork(transport, key.PublicKey, "<no database>", nil) 286 if err != nil { 287 panic("cannot launch new node: " + err.Error()) 288 } 289 290 s.mu.Lock() 291 s.nodes[id] = net 292 s.mu.Unlock() 293 294 return net 295 } 296 297 func (s *simulation) dropNode(id NodeID) { 298 s.mu.Lock() 299 n := s.nodes[id] 300 delete(s.nodes, id) 301 s.mu.Unlock() 302 303 n.Close() 304 } 305 306 type simTransport struct { 307 joinTime time.Time 308 sender NodeID 309 senderAddr *net.UDPAddr 310 sim *simulation 311 hashctr uint64 312 priv *ecdsa.PrivateKey 313 } 314 315 func (st *simTransport) localAddr() *net.UDPAddr { 316 return st.senderAddr 317 } 318 319 func (st *simTransport) Close() {} 320 321 func (st *simTransport) send(remote *Node, ptype nodeEvent, data interface{}) (hash []byte) { 322 hash = st.nextHash() 323 var raw []byte 324 if ptype == pongPacket { 325 var err error 326 raw, _, err = encodePacket(st.priv, byte(ptype), data) 327 if err != nil { 328 panic(err) 329 } 330 } 331 332 st.sendPacket(remote.ID, ingressPacket{ 333 remoteID: st.sender, 334 remoteAddr: st.senderAddr, 335 hash: hash, 336 ev: ptype, 337 data: data, 338 rawData: raw, 339 }) 340 return hash 341 } 342 343 func (st *simTransport) sendPing(remote *Node, remoteAddr *net.UDPAddr, topics []Topic) []byte { 344 hash := st.nextHash() 345 st.sendPacket(remote.ID, ingressPacket{ 346 remoteID: st.sender, 347 remoteAddr: st.senderAddr, 348 hash: hash, 349 ev: pingPacket, 350 data: &ping{ 351 Version: 4, 352 From: rpcEndpoint{IP: st.senderAddr.IP, UDP: uint16(st.senderAddr.Port), TCP: 30303}, 353 To: rpcEndpoint{IP: remoteAddr.IP, UDP: uint16(remoteAddr.Port), TCP: 30303}, 354 Expiration: uint64(time.Now().Unix() + int64(expiration)), 355 Topics: topics, 356 }, 357 }) 358 return hash 359 } 360 361 func (st *simTransport) sendPong(remote *Node, pingHash []byte) { 362 raddr := remote.addr() 363 364 st.sendPacket(remote.ID, ingressPacket{ 365 remoteID: st.sender, 366 remoteAddr: st.senderAddr, 367 hash: st.nextHash(), 368 ev: pongPacket, 369 data: &pong{ 370 To: rpcEndpoint{IP: raddr.IP, UDP: uint16(raddr.Port), TCP: 30303}, 371 ReplyTok: pingHash, 372 Expiration: uint64(time.Now().Unix() + int64(expiration)), 373 }, 374 }) 375 } 376 377 func (st *simTransport) sendFindnodeHash(remote *Node, target common.Hash) { 378 st.sendPacket(remote.ID, ingressPacket{ 379 remoteID: st.sender, 380 remoteAddr: st.senderAddr, 381 hash: st.nextHash(), 382 ev: findnodeHashPacket, 383 data: &findnodeHash{ 384 Target: target, 385 Expiration: uint64(time.Now().Unix() + int64(expiration)), 386 }, 387 }) 388 } 389 390 func (st *simTransport) sendTopicRegister(remote *Node, topics []Topic, idx int, pong []byte) { 391 //fmt.println(“发送”,主题,pong) 392 st.sendPacket(remote.ID, ingressPacket{ 393 remoteID: st.sender, 394 remoteAddr: st.senderAddr, 395 hash: st.nextHash(), 396 ev: topicRegisterPacket, 397 data: &topicRegister{ 398 Topics: topics, 399 Idx: uint(idx), 400 Pong: pong, 401 }, 402 }) 403 } 404 405 func (st *simTransport) sendTopicNodes(remote *Node, queryHash common.Hash, nodes []*Node) { 406 rnodes := make([]rpcNode, len(nodes)) 407 for i := range nodes { 408 rnodes[i] = nodeToRPC(nodes[i]) 409 } 410 st.sendPacket(remote.ID, ingressPacket{ 411 remoteID: st.sender, 412 remoteAddr: st.senderAddr, 413 hash: st.nextHash(), 414 ev: topicNodesPacket, 415 data: &topicNodes{Echo: queryHash, Nodes: rnodes}, 416 }) 417 } 418 419 func (st *simTransport) sendNeighbours(remote *Node, nodes []*Node) { 420 //TODO:发送多个数据包 421 rnodes := make([]rpcNode, len(nodes)) 422 for i := range nodes { 423 rnodes[i] = nodeToRPC(nodes[i]) 424 } 425 st.sendPacket(remote.ID, ingressPacket{ 426 remoteID: st.sender, 427 remoteAddr: st.senderAddr, 428 hash: st.nextHash(), 429 ev: neighborsPacket, 430 data: &neighbors{ 431 Nodes: rnodes, 432 Expiration: uint64(time.Now().Unix() + int64(expiration)), 433 }, 434 }) 435 } 436 437 func (st *simTransport) nextHash() []byte { 438 v := atomic.AddUint64(&st.hashctr, 1) 439 var hash common.Hash 440 binary.BigEndian.PutUint64(hash[:], v) 441 return hash[:] 442 } 443 444 const packetLoss = 0 //1/1000 445 446 func (st *simTransport) sendPacket(remote NodeID, p ingressPacket) { 447 if rand.Int31n(1000) >= packetLoss { 448 st.sim.mu.RLock() 449 recipient := st.sim.nodes[remote] 450 st.sim.mu.RUnlock() 451 452 time.AfterFunc(200*time.Millisecond, func() { 453 recipient.reqReadPacket(p) 454 }) 455 } 456 } 457