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