github.com/letterj/go-ethereum@v1.8.22-0.20190204142846-520024dfd689/swarm/network/kademlia_test.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package network 18 19 import ( 20 "fmt" 21 "os" 22 "testing" 23 "time" 24 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/log" 27 "github.com/ethereum/go-ethereum/p2p" 28 "github.com/ethereum/go-ethereum/p2p/enode" 29 "github.com/ethereum/go-ethereum/p2p/protocols" 30 "github.com/ethereum/go-ethereum/swarm/pot" 31 ) 32 33 func init() { 34 h := log.LvlFilterHandler(log.LvlWarn, log.StreamHandler(os.Stderr, log.TerminalFormat(true))) 35 log.Root().SetHandler(h) 36 } 37 38 func testKadPeerAddr(s string) *BzzAddr { 39 a := pot.NewAddressFromString(s) 40 return &BzzAddr{OAddr: a, UAddr: a} 41 } 42 43 func newTestKademliaParams() *KadParams { 44 params := NewKadParams() 45 params.MinBinSize = 2 46 params.NeighbourhoodSize = 2 47 return params 48 } 49 50 type testKademlia struct { 51 *Kademlia 52 t *testing.T 53 } 54 55 func newTestKademlia(t *testing.T, b string) *testKademlia { 56 base := pot.NewAddressFromString(b) 57 return &testKademlia{ 58 Kademlia: NewKademlia(base, newTestKademliaParams()), 59 t: t, 60 } 61 } 62 63 func (tk *testKademlia) newTestKadPeer(s string, lightNode bool) *Peer { 64 return NewPeer(&BzzPeer{BzzAddr: testKadPeerAddr(s), LightNode: lightNode}, tk.Kademlia) 65 } 66 67 func (tk *testKademlia) On(ons ...string) { 68 for _, s := range ons { 69 tk.Kademlia.On(tk.newTestKadPeer(s, false)) 70 } 71 } 72 73 func (tk *testKademlia) Off(offs ...string) { 74 for _, s := range offs { 75 tk.Kademlia.Off(tk.newTestKadPeer(s, false)) 76 } 77 } 78 79 func (tk *testKademlia) Register(regs ...string) { 80 var as []*BzzAddr 81 for _, s := range regs { 82 as = append(as, testKadPeerAddr(s)) 83 } 84 err := tk.Kademlia.Register(as...) 85 if err != nil { 86 panic(err.Error()) 87 } 88 } 89 90 // tests the validity of neighborhood depth calculations 91 // 92 // in particular, it tests that if there are one or more consecutive 93 // empty bins above the farthest "nearest neighbor-peer" then 94 // the depth should be set at the farthest of those empty bins 95 // 96 // TODO: Make test adapt to change in NeighbourhoodSize 97 func TestNeighbourhoodDepth(t *testing.T) { 98 baseAddressBytes := RandomAddr().OAddr 99 kad := NewKademlia(baseAddressBytes, NewKadParams()) 100 101 baseAddress := pot.NewAddressFromBytes(baseAddressBytes) 102 103 // generate the peers 104 var peers []*Peer 105 for i := 0; i < 7; i++ { 106 addr := pot.RandomAddressAt(baseAddress, i) 107 peers = append(peers, newTestDiscoveryPeer(addr, kad)) 108 } 109 var sevenPeers []*Peer 110 for i := 0; i < 2; i++ { 111 addr := pot.RandomAddressAt(baseAddress, 7) 112 sevenPeers = append(sevenPeers, newTestDiscoveryPeer(addr, kad)) 113 } 114 115 testNum := 0 116 // first try with empty kademlia 117 depth := kad.NeighbourhoodDepth() 118 if depth != 0 { 119 t.Fatalf("%d expected depth 0, was %d", testNum, depth) 120 } 121 testNum++ 122 123 // add one peer on 7 124 kad.On(sevenPeers[0]) 125 depth = kad.NeighbourhoodDepth() 126 if depth != 0 { 127 t.Fatalf("%d expected depth 0, was %d", testNum, depth) 128 } 129 testNum++ 130 131 // add a second on 7 132 kad.On(sevenPeers[1]) 133 depth = kad.NeighbourhoodDepth() 134 if depth != 0 { 135 t.Fatalf("%d expected depth 0, was %d", testNum, depth) 136 } 137 testNum++ 138 139 // add from 0 to 6 140 for i, p := range peers { 141 kad.On(p) 142 depth = kad.NeighbourhoodDepth() 143 if depth != i+1 { 144 t.Fatalf("%d.%d expected depth %d, was %d", i+1, testNum, i, depth) 145 } 146 } 147 testNum++ 148 149 kad.Off(sevenPeers[1]) 150 depth = kad.NeighbourhoodDepth() 151 if depth != 6 { 152 t.Fatalf("%d expected depth 6, was %d", testNum, depth) 153 } 154 testNum++ 155 156 kad.Off(peers[4]) 157 depth = kad.NeighbourhoodDepth() 158 if depth != 4 { 159 t.Fatalf("%d expected depth 4, was %d", testNum, depth) 160 } 161 testNum++ 162 163 kad.Off(peers[3]) 164 depth = kad.NeighbourhoodDepth() 165 if depth != 3 { 166 t.Fatalf("%d expected depth 3, was %d", testNum, depth) 167 } 168 testNum++ 169 } 170 171 // TestHealthStrict tests the simplest definition of health 172 // Which means whether we are connected to all neighbors we know of 173 func TestHealthStrict(t *testing.T) { 174 175 // base address is all zeros 176 // no peers 177 // unhealthy (and lonely) 178 tk := newTestKademlia(t, "11111111") 179 tk.checkHealth(false, false) 180 181 // know one peer but not connected 182 // unhealthy 183 tk.Register("11100000") 184 tk.checkHealth(false, false) 185 186 // know one peer and connected 187 // healthy 188 tk.On("11100000") 189 tk.checkHealth(true, false) 190 191 // know two peers, only one connected 192 // unhealthy 193 tk.Register("11111100") 194 tk.checkHealth(false, false) 195 196 // know two peers and connected to both 197 // healthy 198 tk.On("11111100") 199 tk.checkHealth(true, false) 200 201 // know three peers, connected to the two deepest 202 // healthy 203 tk.Register("00000000") 204 tk.checkHealth(true, false) 205 206 // know three peers, connected to all three 207 // healthy 208 tk.On("00000000") 209 tk.checkHealth(true, false) 210 211 // add fourth peer deeper than current depth 212 // unhealthy 213 tk.Register("11110000") 214 tk.checkHealth(false, false) 215 216 // connected to three deepest peers 217 // healthy 218 tk.On("11110000") 219 tk.checkHealth(true, false) 220 221 // add additional peer in same bin as deepest peer 222 // unhealthy 223 tk.Register("11111101") 224 tk.checkHealth(false, false) 225 226 // four deepest of five peers connected 227 // healthy 228 tk.On("11111101") 229 tk.checkHealth(true, false) 230 } 231 232 func (tk *testKademlia) checkHealth(expectHealthy bool, expectSaturation bool) { 233 tk.t.Helper() 234 kid := common.Bytes2Hex(tk.BaseAddr()) 235 addrs := [][]byte{tk.BaseAddr()} 236 tk.EachAddr(nil, 255, func(addr *BzzAddr, po int) bool { 237 addrs = append(addrs, addr.Address()) 238 return true 239 }) 240 241 pp := NewPeerPotMap(tk.NeighbourhoodSize, addrs) 242 healthParams := tk.Healthy(pp[kid]) 243 244 // definition of health, all conditions but be true: 245 // - we at least know one peer 246 // - we know all neighbors 247 // - we are connected to all known neighbors 248 health := healthParams.KnowNN && healthParams.ConnectNN && healthParams.CountKnowNN > 0 249 if expectHealthy != health { 250 tk.t.Fatalf("expected kademlia health %v, is %v\n%v", expectHealthy, health, tk.String()) 251 } 252 } 253 254 func (tk *testKademlia) checkSuggestPeer(expAddr string, expDepth int, expChanged bool) { 255 tk.t.Helper() 256 addr, depth, changed := tk.SuggestPeer() 257 log.Trace("suggestPeer return", "addr", addr, "depth", depth, "changed", changed) 258 if binStr(addr) != expAddr { 259 tk.t.Fatalf("incorrect peer address suggested. expected %v, got %v", expAddr, binStr(addr)) 260 } 261 if depth != expDepth { 262 tk.t.Fatalf("incorrect saturation depth suggested. expected %v, got %v", expDepth, depth) 263 } 264 if changed != expChanged { 265 tk.t.Fatalf("expected depth change = %v, got %v", expChanged, changed) 266 } 267 } 268 269 func binStr(a *BzzAddr) string { 270 if a == nil { 271 return "<nil>" 272 } 273 return pot.ToBin(a.Address())[:8] 274 } 275 276 func TestSuggestPeerFindPeers(t *testing.T) { 277 tk := newTestKademlia(t, "00000000") 278 tk.On("00100000") 279 tk.checkSuggestPeer("<nil>", 0, false) 280 281 tk.On("00010000") 282 tk.checkSuggestPeer("<nil>", 0, false) 283 284 tk.On("10000000", "10000001") 285 tk.checkSuggestPeer("<nil>", 0, false) 286 287 tk.On("01000000") 288 tk.Off("10000001") 289 tk.checkSuggestPeer("10000001", 0, true) 290 291 tk.On("00100001") 292 tk.Off("01000000") 293 tk.checkSuggestPeer("01000000", 0, false) 294 295 // second time disconnected peer not callable 296 // with reasonably set Interval 297 tk.checkSuggestPeer("<nil>", 0, false) 298 299 // on and off again, peer callable again 300 tk.On("01000000") 301 tk.Off("01000000") 302 tk.checkSuggestPeer("01000000", 0, false) 303 304 tk.On("01000000", "10000001") 305 tk.checkSuggestPeer("<nil>", 0, false) 306 307 tk.Register("00010001") 308 tk.checkSuggestPeer("00010001", 0, false) 309 310 tk.On("00010001") 311 tk.Off("01000000") 312 tk.checkSuggestPeer("01000000", 0, false) 313 314 tk.On("01000000") 315 tk.checkSuggestPeer("<nil>", 0, false) 316 317 tk.Register("01000001") 318 tk.checkSuggestPeer("01000001", 0, false) 319 320 tk.On("01000001") 321 tk.checkSuggestPeer("<nil>", 0, false) 322 323 tk.Register("10000010", "01000010", "00100010") 324 tk.checkSuggestPeer("<nil>", 0, false) 325 326 tk.Register("00010010") 327 tk.checkSuggestPeer("00010010", 0, false) 328 329 tk.Off("00100001") 330 tk.checkSuggestPeer("00100010", 2, true) 331 332 tk.Off("01000001") 333 tk.checkSuggestPeer("01000010", 1, true) 334 335 tk.checkSuggestPeer("01000001", 0, false) 336 tk.checkSuggestPeer("00100001", 0, false) 337 tk.checkSuggestPeer("<nil>", 0, false) 338 339 tk.On("01000001", "00100001") 340 tk.Register("10000100", "01000100", "00100100") 341 tk.Register("00000100", "00000101", "00000110") 342 tk.Register("00000010", "00000011", "00000001") 343 344 tk.checkSuggestPeer("00000110", 0, false) 345 tk.checkSuggestPeer("00000101", 0, false) 346 tk.checkSuggestPeer("00000100", 0, false) 347 tk.checkSuggestPeer("00000011", 0, false) 348 tk.checkSuggestPeer("00000010", 0, false) 349 tk.checkSuggestPeer("00000001", 0, false) 350 tk.checkSuggestPeer("<nil>", 0, false) 351 352 } 353 354 // a node should stay in the address book if it's removed from the kademlia 355 func TestOffEffectingAddressBookNormalNode(t *testing.T) { 356 tk := newTestKademlia(t, "00000000") 357 // peer added to kademlia 358 tk.On("01000000") 359 // peer should be in the address book 360 if tk.addrs.Size() != 1 { 361 t.Fatal("known peer addresses should contain 1 entry") 362 } 363 // peer should be among live connections 364 if tk.conns.Size() != 1 { 365 t.Fatal("live peers should contain 1 entry") 366 } 367 // remove peer from kademlia 368 tk.Off("01000000") 369 // peer should be in the address book 370 if tk.addrs.Size() != 1 { 371 t.Fatal("known peer addresses should contain 1 entry") 372 } 373 // peer should not be among live connections 374 if tk.conns.Size() != 0 { 375 t.Fatal("live peers should contain 0 entry") 376 } 377 } 378 379 // a light node should not be in the address book 380 func TestOffEffectingAddressBookLightNode(t *testing.T) { 381 tk := newTestKademlia(t, "00000000") 382 // light node peer added to kademlia 383 tk.Kademlia.On(tk.newTestKadPeer("01000000", true)) 384 // peer should not be in the address book 385 if tk.addrs.Size() != 0 { 386 t.Fatal("known peer addresses should contain 0 entry") 387 } 388 // peer should be among live connections 389 if tk.conns.Size() != 1 { 390 t.Fatal("live peers should contain 1 entry") 391 } 392 // remove peer from kademlia 393 tk.Kademlia.Off(tk.newTestKadPeer("01000000", true)) 394 // peer should not be in the address book 395 if tk.addrs.Size() != 0 { 396 t.Fatal("known peer addresses should contain 0 entry") 397 } 398 // peer should not be among live connections 399 if tk.conns.Size() != 0 { 400 t.Fatal("live peers should contain 0 entry") 401 } 402 } 403 404 func TestSuggestPeerRetries(t *testing.T) { 405 tk := newTestKademlia(t, "00000000") 406 tk.RetryInterval = int64(300 * time.Millisecond) // cycle 407 tk.MaxRetries = 50 408 tk.RetryExponent = 2 409 sleep := func(n int) { 410 ts := tk.RetryInterval 411 for i := 1; i < n; i++ { 412 ts *= int64(tk.RetryExponent) 413 } 414 time.Sleep(time.Duration(ts)) 415 } 416 417 tk.Register("01000000") 418 tk.On("00000001", "00000010") 419 tk.checkSuggestPeer("01000000", 0, false) 420 421 tk.checkSuggestPeer("<nil>", 0, false) 422 423 sleep(1) 424 tk.checkSuggestPeer("01000000", 0, false) 425 426 tk.checkSuggestPeer("<nil>", 0, false) 427 428 sleep(1) 429 tk.checkSuggestPeer("01000000", 0, false) 430 431 tk.checkSuggestPeer("<nil>", 0, false) 432 433 sleep(2) 434 tk.checkSuggestPeer("01000000", 0, false) 435 436 tk.checkSuggestPeer("<nil>", 0, false) 437 438 sleep(2) 439 tk.checkSuggestPeer("<nil>", 0, false) 440 } 441 442 func TestKademliaHiveString(t *testing.T) { 443 tk := newTestKademlia(t, "00000000") 444 tk.On("01000000", "00100000") 445 tk.Register("10000000", "10000001") 446 tk.MaxProxDisplay = 8 447 h := tk.String() 448 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=========================================================================" 449 if expH[104:] != h[104:] { 450 t.Fatalf("incorrect hive output. expected %v, got %v", expH, h) 451 } 452 } 453 454 func newTestDiscoveryPeer(addr pot.Address, kad *Kademlia) *Peer { 455 rw := &p2p.MsgPipeRW{} 456 p := p2p.NewPeer(enode.ID{}, "foo", []p2p.Cap{}) 457 pp := protocols.NewPeer(p, rw, &protocols.Spec{}) 458 bp := &BzzPeer{ 459 Peer: pp, 460 BzzAddr: &BzzAddr{ 461 OAddr: addr.Bytes(), 462 UAddr: []byte(fmt.Sprintf("%x", addr[:])), 463 }, 464 } 465 return NewPeer(bp, kad) 466 }