github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/network/kademlia_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 19:16:43</date> 10 //</624450113879674880> 11 12 13 package network 14 15 import ( 16 "fmt" 17 "os" 18 "testing" 19 "time" 20 21 "github.com/ethereum/go-ethereum/common" 22 "github.com/ethereum/go-ethereum/log" 23 "github.com/ethereum/go-ethereum/p2p" 24 "github.com/ethereum/go-ethereum/p2p/enode" 25 "github.com/ethereum/go-ethereum/p2p/protocols" 26 "github.com/ethereum/go-ethereum/swarm/pot" 27 ) 28 29 func init() { 30 h := log.LvlFilterHandler(log.LvlWarn, log.StreamHandler(os.Stderr, log.TerminalFormat(true))) 31 log.Root().SetHandler(h) 32 } 33 34 func testKadPeerAddr(s string) *BzzAddr { 35 a := pot.NewAddressFromString(s) 36 return &BzzAddr{OAddr: a, UAddr: a} 37 } 38 39 func newTestKademliaParams() *KadParams { 40 params := NewKadParams() 41 params.MinBinSize = 2 42 params.NeighbourhoodSize = 2 43 return params 44 } 45 46 type testKademlia struct { 47 *Kademlia 48 t *testing.T 49 } 50 51 func newTestKademlia(t *testing.T, b string) *testKademlia { 52 base := pot.NewAddressFromString(b) 53 return &testKademlia{ 54 Kademlia: NewKademlia(base, newTestKademliaParams()), 55 t: t, 56 } 57 } 58 59 func (tk *testKademlia) newTestKadPeer(s string, lightNode bool) *Peer { 60 return NewPeer(&BzzPeer{BzzAddr: testKadPeerAddr(s), LightNode: lightNode}, tk.Kademlia) 61 } 62 63 func (tk *testKademlia) On(ons ...string) { 64 for _, s := range ons { 65 tk.Kademlia.On(tk.newTestKadPeer(s, false)) 66 } 67 } 68 69 func (tk *testKademlia) Off(offs ...string) { 70 for _, s := range offs { 71 tk.Kademlia.Off(tk.newTestKadPeer(s, false)) 72 } 73 } 74 75 func (tk *testKademlia) Register(regs ...string) { 76 var as []*BzzAddr 77 for _, s := range regs { 78 as = append(as, testKadPeerAddr(s)) 79 } 80 err := tk.Kademlia.Register(as...) 81 if err != nil { 82 panic(err.Error()) 83 } 84 } 85 86 //检验邻域深度计算的有效性 87 // 88 //特别是,它测试如果有一个或多个连续的 89 //然后清空最远“最近邻居”上方的垃圾箱。 90 //深度应该设置在那些空箱子的最远处。 91 // 92 //TODO:使测试适应邻里关系的变化 93 func TestNeighbourhoodDepth(t *testing.T) { 94 baseAddressBytes := RandomAddr().OAddr 95 kad := NewKademlia(baseAddressBytes, NewKadParams()) 96 97 baseAddress := pot.NewAddressFromBytes(baseAddressBytes) 98 99 //生成对等点 100 var peers []*Peer 101 for i := 0; i < 7; i++ { 102 addr := pot.RandomAddressAt(baseAddress, i) 103 peers = append(peers, newTestDiscoveryPeer(addr, kad)) 104 } 105 var sevenPeers []*Peer 106 for i := 0; i < 2; i++ { 107 addr := pot.RandomAddressAt(baseAddress, 7) 108 sevenPeers = append(sevenPeers, newTestDiscoveryPeer(addr, kad)) 109 } 110 111 testNum := 0 112 //第一次尝试空花环 113 depth := kad.NeighbourhoodDepth() 114 if depth != 0 { 115 t.Fatalf("%d expected depth 0, was %d", testNum, depth) 116 } 117 testNum++ 118 119 //在7上添加一个对等点 120 kad.On(sevenPeers[0]) 121 depth = kad.NeighbourhoodDepth() 122 if depth != 0 { 123 t.Fatalf("%d expected depth 0, was %d", testNum, depth) 124 } 125 testNum++ 126 127 //7点再加一秒 128 kad.On(sevenPeers[1]) 129 depth = kad.NeighbourhoodDepth() 130 if depth != 0 { 131 t.Fatalf("%d expected depth 0, was %d", testNum, depth) 132 } 133 testNum++ 134 135 //从0增加到6 136 for i, p := range peers { 137 kad.On(p) 138 depth = kad.NeighbourhoodDepth() 139 if depth != i+1 { 140 t.Fatalf("%d.%d expected depth %d, was %d", i+1, testNum, i, depth) 141 } 142 } 143 testNum++ 144 145 kad.Off(sevenPeers[1]) 146 depth = kad.NeighbourhoodDepth() 147 if depth != 6 { 148 t.Fatalf("%d expected depth 6, was %d", testNum, depth) 149 } 150 testNum++ 151 152 kad.Off(peers[4]) 153 depth = kad.NeighbourhoodDepth() 154 if depth != 4 { 155 t.Fatalf("%d expected depth 4, was %d", testNum, depth) 156 } 157 testNum++ 158 159 kad.Off(peers[3]) 160 depth = kad.NeighbourhoodDepth() 161 if depth != 3 { 162 t.Fatalf("%d expected depth 3, was %d", testNum, depth) 163 } 164 testNum++ 165 } 166 167 //testHealthStrict测试最简单的健康定义 168 //这意味着我们是否与我们所认识的所有邻居都有联系 169 func TestHealthStrict(t *testing.T) { 170 171 //基址都是零 172 //没有对等体 173 //不健康(和孤独) 174 tk := newTestKademlia(t, "11111111") 175 tk.checkHealth(false, false) 176 177 //知道一个对等点但没有连接 178 //不健康的 179 tk.Register("11100000") 180 tk.checkHealth(false, false) 181 182 //认识一个同伴并建立联系 183 //健康的 184 tk.On("11100000") 185 tk.checkHealth(true, false) 186 187 //认识两个同龄人,只有一个相连 188 //不健康的 189 tk.Register("11111100") 190 tk.checkHealth(false, false) 191 192 //认识两个同龄人并与两个同龄人都有联系 193 //健康的 194 tk.On("11111100") 195 tk.checkHealth(true, false) 196 197 //认识三个同龄人,连到两个最深的 198 //健康的 199 tk.Register("00000000") 200 tk.checkHealth(true, false) 201 202 //认识三个同龄人,连接到所有三个 203 //健康的 204 tk.On("00000000") 205 tk.checkHealth(true, false) 206 207 //添加比当前深度更深的第四个对等点 208 //不健康的 209 tk.Register("11110000") 210 tk.checkHealth(false, false) 211 212 //连接到三个最深的对等点 213 //健康的 214 tk.On("11110000") 215 tk.checkHealth(true, false) 216 217 //在同一个bin中添加其他对等机作为最深对等机 218 //不健康的 219 tk.Register("11111101") 220 tk.checkHealth(false, false) 221 222 //五个对等点中连接最深的四个 223 //健康的 224 tk.On("11111101") 225 tk.checkHealth(true, false) 226 } 227 228 func (tk *testKademlia) checkHealth(expectHealthy bool, expectSaturation bool) { 229 tk.t.Helper() 230 kid := common.Bytes2Hex(tk.BaseAddr()) 231 addrs := [][]byte{tk.BaseAddr()} 232 tk.EachAddr(nil, 255, func(addr *BzzAddr, po int) bool { 233 addrs = append(addrs, addr.Address()) 234 return true 235 }) 236 237 pp := NewPeerPotMap(tk.NeighbourhoodSize, addrs) 238 healthParams := tk.Healthy(pp[kid]) 239 240 //健康的定义,所有条件,但必须真实: 241 //-我们至少认识一个同伴 242 //我们认识所有的邻居 243 //-我们与所有已知的邻居都有联系 244 health := healthParams.KnowNN && healthParams.ConnectNN && healthParams.CountKnowNN > 0 245 if expectHealthy != health { 246 tk.t.Fatalf("expected kademlia health %v, is %v\n%v", expectHealthy, health, tk.String()) 247 } 248 } 249 250 func (tk *testKademlia) checkSuggestPeer(expAddr string, expDepth int, expChanged bool) { 251 tk.t.Helper() 252 addr, depth, changed := tk.SuggestPeer() 253 log.Trace("suggestPeer return", "addr", addr, "depth", depth, "changed", changed) 254 if binStr(addr) != expAddr { 255 tk.t.Fatalf("incorrect peer address suggested. expected %v, got %v", expAddr, binStr(addr)) 256 } 257 if depth != expDepth { 258 tk.t.Fatalf("incorrect saturation depth suggested. expected %v, got %v", expDepth, depth) 259 } 260 if changed != expChanged { 261 tk.t.Fatalf("expected depth change = %v, got %v", expChanged, changed) 262 } 263 } 264 265 func binStr(a *BzzAddr) string { 266 if a == nil { 267 return "<nil>" 268 } 269 return pot.ToBin(a.Address())[:8] 270 } 271 272 func TestSuggestPeerFindPeers(t *testing.T) { 273 tk := newTestKademlia(t, "00000000") 274 tk.On("00100000") 275 tk.checkSuggestPeer("<nil>", 0, false) 276 277 tk.On("00010000") 278 tk.checkSuggestPeer("<nil>", 0, false) 279 280 tk.On("10000000", "10000001") 281 tk.checkSuggestPeer("<nil>", 0, false) 282 283 tk.On("01000000") 284 tk.Off("10000001") 285 tk.checkSuggestPeer("10000001", 0, true) 286 287 tk.On("00100001") 288 tk.Off("01000000") 289 tk.checkSuggestPeer("01000000", 0, false) 290 291 //第二次断开连接的对等机不可调用 292 //间隔合理 293 tk.checkSuggestPeer("<nil>", 0, false) 294 295 //一次又一次地打开和关闭,对等呼叫再次 296 tk.On("01000000") 297 tk.Off("01000000") 298 tk.checkSuggestPeer("01000000", 0, false) 299 300 tk.On("01000000", "10000001") 301 tk.checkSuggestPeer("<nil>", 0, false) 302 303 tk.Register("00010001") 304 tk.checkSuggestPeer("00010001", 0, false) 305 306 tk.On("00010001") 307 tk.Off("01000000") 308 tk.checkSuggestPeer("01000000", 0, false) 309 310 tk.On("01000000") 311 tk.checkSuggestPeer("<nil>", 0, false) 312 313 tk.Register("01000001") 314 tk.checkSuggestPeer("01000001", 0, false) 315 316 tk.On("01000001") 317 tk.checkSuggestPeer("<nil>", 0, false) 318 319 tk.Register("10000010", "01000010", "00100010") 320 tk.checkSuggestPeer("<nil>", 0, false) 321 322 tk.Register("00010010") 323 tk.checkSuggestPeer("00010010", 0, false) 324 325 tk.Off("00100001") 326 tk.checkSuggestPeer("00100010", 2, true) 327 328 tk.Off("01000001") 329 tk.checkSuggestPeer("01000010", 1, true) 330 331 tk.checkSuggestPeer("01000001", 0, false) 332 tk.checkSuggestPeer("00100001", 0, false) 333 tk.checkSuggestPeer("<nil>", 0, false) 334 335 tk.On("01000001", "00100001") 336 tk.Register("10000100", "01000100", "00100100") 337 tk.Register("00000100", "00000101", "00000110") 338 tk.Register("00000010", "00000011", "00000001") 339 340 tk.checkSuggestPeer("00000110", 0, false) 341 tk.checkSuggestPeer("00000101", 0, false) 342 tk.checkSuggestPeer("00000100", 0, false) 343 tk.checkSuggestPeer("00000011", 0, false) 344 tk.checkSuggestPeer("00000010", 0, false) 345 tk.checkSuggestPeer("00000001", 0, false) 346 tk.checkSuggestPeer("<nil>", 0, false) 347 348 } 349 350 //如果一个节点从Kademlia中删除,它应该留在通讯簿中。 351 func TestOffEffectingAddressBookNormalNode(t *testing.T) { 352 tk := newTestKademlia(t, "00000000") 353 //添加到Kademlia的对等 354 tk.On("01000000") 355 //对等机应该在通讯簿中 356 if tk.addrs.Size() != 1 { 357 t.Fatal("known peer addresses should contain 1 entry") 358 } 359 //对等端应位于活动连接之间 360 if tk.conns.Size() != 1 { 361 t.Fatal("live peers should contain 1 entry") 362 } 363 //从Kademlia中删除对等 364 tk.Off("01000000") 365 //对等机应该在通讯簿中 366 if tk.addrs.Size() != 1 { 367 t.Fatal("known peer addresses should contain 1 entry") 368 } 369 //对等端不应位于活动连接之间 370 if tk.conns.Size() != 0 { 371 t.Fatal("live peers should contain 0 entry") 372 } 373 } 374 375 //轻节点不应在通讯簿中 376 func TestOffEffectingAddressBookLightNode(t *testing.T) { 377 tk := newTestKademlia(t, "00000000") 378 //添加到Kademlia的光节点对等体 379 tk.Kademlia.On(tk.newTestKadPeer("01000000", true)) 380 //对等机不应在通讯簿中 381 if tk.addrs.Size() != 0 { 382 t.Fatal("known peer addresses should contain 0 entry") 383 } 384 //对等端应位于活动连接之间 385 if tk.conns.Size() != 1 { 386 t.Fatal("live peers should contain 1 entry") 387 } 388 //从Kademlia中删除对等 389 tk.Kademlia.Off(tk.newTestKadPeer("01000000", true)) 390 //对等机不应在通讯簿中 391 if tk.addrs.Size() != 0 { 392 t.Fatal("known peer addresses should contain 0 entry") 393 } 394 //对等端不应位于活动连接之间 395 if tk.conns.Size() != 0 { 396 t.Fatal("live peers should contain 0 entry") 397 } 398 } 399 400 func TestSuggestPeerRetries(t *testing.T) { 401 tk := newTestKademlia(t, "00000000") 402 tk.RetryInterval = int64(300 * time.Millisecond) //周期 403 tk.MaxRetries = 50 404 tk.RetryExponent = 2 405 sleep := func(n int) { 406 ts := tk.RetryInterval 407 for i := 1; i < n; i++ { 408 ts *= int64(tk.RetryExponent) 409 } 410 time.Sleep(time.Duration(ts)) 411 } 412 413 tk.Register("01000000") 414 tk.On("00000001", "00000010") 415 tk.checkSuggestPeer("01000000", 0, false) 416 417 tk.checkSuggestPeer("<nil>", 0, false) 418 419 sleep(1) 420 tk.checkSuggestPeer("01000000", 0, false) 421 422 tk.checkSuggestPeer("<nil>", 0, false) 423 424 sleep(1) 425 tk.checkSuggestPeer("01000000", 0, false) 426 427 tk.checkSuggestPeer("<nil>", 0, false) 428 429 sleep(2) 430 tk.checkSuggestPeer("01000000", 0, false) 431 432 tk.checkSuggestPeer("<nil>", 0, false) 433 434 sleep(2) 435 tk.checkSuggestPeer("<nil>", 0, false) 436 } 437 438 func TestKademliaHiveString(t *testing.T) { 439 tk := newTestKademlia(t, "00000000") 440 tk.On("01000000", "00100000") 441 tk.Register("10000000", "10000001") 442 tk.MaxProxDisplay = 8 443 h := tk.String() 444 expH := "\n=========================================================================\nMon Feb 27 12:10:28 UTC 2017 KΛÐΞMLIΛ hive: queen's address: 000000\npopulation: 2 (4), NeighbourhoodSize: 2, MinBinSize: 2, MaxBinSize: 4\n============ DEPTH: 0 ==========================================\n000 0 | 2 8100 (0) 8000 (0)\n001 1 4000 | 1 4000 (0)\n002 1 2000 | 1 2000 (0)\n003 0 | 0\n004 0 | 0\n005 0 | 0\n006 0 | 0\n007 0 | 0\n=========================================================================" 445 if expH[104:] != h[104:] { 446 t.Fatalf("incorrect hive output. expected %v, got %v", expH, h) 447 } 448 } 449 450 func newTestDiscoveryPeer(addr pot.Address, kad *Kademlia) *Peer { 451 rw := &p2p.MsgPipeRW{} 452 p := p2p.NewPeer(enode.ID{}, "foo", []p2p.Cap{}) 453 pp := protocols.NewPeer(p, rw, &protocols.Spec{}) 454 bp := &BzzPeer{ 455 Peer: pp, 456 BzzAddr: &BzzAddr{ 457 OAddr: addr.Bytes(), 458 UAddr: []byte(fmt.Sprintf("%x", addr[:])), 459 }, 460 } 461 return NewPeer(bp, kad) 462 } 463