github.com/ethersphere/bee/v2@v2.2.0/pkg/topology/kademlia/kademlia_test.go (about) 1 // Copyright 2020 The Swarm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package kademlia_test 6 7 import ( 8 "context" 9 "errors" 10 "fmt" 11 "math" 12 "math/rand" 13 "reflect" 14 "sync" 15 "sync/atomic" 16 "testing" 17 "time" 18 19 ma "github.com/multiformats/go-multiaddr" 20 21 "github.com/ethersphere/bee/v2/pkg/addressbook" 22 "github.com/ethersphere/bee/v2/pkg/bzz" 23 beeCrypto "github.com/ethersphere/bee/v2/pkg/crypto" 24 "github.com/ethersphere/bee/v2/pkg/discovery/mock" 25 "github.com/ethersphere/bee/v2/pkg/log" 26 "github.com/ethersphere/bee/v2/pkg/p2p" 27 p2pmock "github.com/ethersphere/bee/v2/pkg/p2p/mock" 28 "github.com/ethersphere/bee/v2/pkg/spinlock" 29 mockstate "github.com/ethersphere/bee/v2/pkg/statestore/mock" 30 "github.com/ethersphere/bee/v2/pkg/swarm" 31 "github.com/ethersphere/bee/v2/pkg/topology" 32 "github.com/ethersphere/bee/v2/pkg/topology/kademlia" 33 im "github.com/ethersphere/bee/v2/pkg/topology/kademlia/internal/metrics" 34 "github.com/ethersphere/bee/v2/pkg/topology/pslice" 35 "github.com/ethersphere/bee/v2/pkg/util/testutil" 36 ) 37 38 const spinLockWaitTime = time.Second * 5 39 40 var nonConnectableAddress, _ = ma.NewMultiaddr(underlayBase + "16Uiu2HAkx8ULY8cTXhdVAcMmLcH9AsTKz6uBQ7DPLKRjMLgBVYkA") 41 var defaultExcludeFunc kademlia.ExcludeFunc = func(...im.ExcludeOp) kademlia.PeerExcludeFunc { 42 return func(swarm.Address) bool { return false } 43 } 44 45 // TestNeighborhoodDepth tests that the kademlia depth changes correctly 46 // according to the change to known peers slice. This inadvertently tests 47 // the functionality in `manage()` method, however this is not the main aim of the 48 // test, since depth calculation happens there and in the disconnect method. 49 // A more in depth testing of the functionality in `manage()` is explicitly 50 // tested in TestManage below. 51 func TestNeighborhoodDepth(t *testing.T) { 52 t.Parallel() 53 54 var ( 55 conns int32 // how many connect calls were made to the p2p mock 56 base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ 57 SaturationPeers: ptrInt(4), 58 ExcludeFunc: defaultExcludeFunc, 59 }) 60 ) 61 kad.SetStorageRadius(0) 62 63 if err := kad.Start(context.Background()); err != nil { 64 t.Fatal(err) 65 } 66 testutil.CleanupCloser(t, kad) 67 68 // add 2 peers in bin 8 69 for i := 0; i < 2; i++ { 70 addr := swarm.RandAddressAt(t, base, 8) 71 addOne(t, signer, kad, ab, addr) 72 73 // wait for one connection 74 waitConn(t, &conns) 75 } 76 // depth is 0 77 kDepth(t, kad, 0) 78 79 var shallowPeers []swarm.Address 80 // add two first peers (po0,po1) 81 for i := 0; i < 2; i++ { 82 addr := swarm.RandAddressAt(t, base, i) 83 addOne(t, signer, kad, ab, addr) 84 shallowPeers = append(shallowPeers, addr) 85 86 // wait for one connection 87 waitConn(t, &conns) 88 } 89 90 for _, a := range shallowPeers { 91 if !kad.IsWithinConnectionDepth(a) { 92 t.Fatal("expected address to be within depth") 93 } 94 } 95 96 kad.SetStorageRadius(0) 97 98 // depth 0 - bin 0 is unsaturated 99 kDepth(t, kad, 0) 100 101 for i := 2; i < 8; i++ { 102 addr := swarm.RandAddressAt(t, base, i) 103 addOne(t, signer, kad, ab, addr) 104 105 // wait for one connection 106 waitConn(t, &conns) 107 } 108 // still zero 109 kDepth(t, kad, 0) 110 111 // now add peers from bin 0 and expect the depth 112 // to shift. the depth will be that of the shallowest 113 // unsaturated bin. 114 for i := 0; i < 7; i++ { 115 for j := 0; j < 3; j++ { 116 addr := swarm.RandAddressAt(t, base, i) 117 addOne(t, signer, kad, ab, addr) 118 waitConn(t, &conns) 119 } 120 kDepth(t, kad, i+1) 121 } 122 123 // depth is 7 because bin 7 is unsaturated (1 peer) 124 kDepth(t, kad, 7) 125 126 // set the radius to be lower than unsaturated, expect radius as depth 127 kad.SetStorageRadius(6) 128 kRadius(t, kad, 6) 129 130 kad.SetStorageRadius(0) 131 132 // expect shallow peers not in depth 133 for _, a := range shallowPeers { 134 if kad.IsWithinConnectionDepth(a) { 135 t.Fatal("expected address to outside of depth") 136 } 137 } 138 139 // now add another ONE peer at depth, and expect the depth to still 140 // stay 8, because the counter for nnLowWatermark would be reached only at the next 141 // depth iteration when calculating depth 142 addr := swarm.RandAddressAt(t, base, 8) 143 addOne(t, signer, kad, ab, addr) 144 waitConn(t, &conns) 145 kDepth(t, kad, 7) 146 147 // now fill bin 7 so that it is saturated, expect depth 8 148 for i := 0; i < 3; i++ { 149 addr := swarm.RandAddressAt(t, base, 7) 150 addOne(t, signer, kad, ab, addr) 151 waitConn(t, &conns) 152 } 153 kDepth(t, kad, 8) 154 155 // saturate bin 8 156 addr = swarm.RandAddressAt(t, base, 8) 157 addOne(t, signer, kad, ab, addr) 158 waitConn(t, &conns) 159 kDepth(t, kad, 8) 160 161 var addrs []swarm.Address 162 // fill the rest up to the bin before last and check that everything works at the edges 163 for i := 9; i < int(swarm.MaxBins); i++ { 164 for j := 0; j < 4; j++ { 165 addr := swarm.RandAddressAt(t, base, i) 166 addOne(t, signer, kad, ab, addr) 167 waitConn(t, &conns) 168 addrs = append(addrs, addr) 169 } 170 kDepth(t, kad, i) 171 } 172 173 // add a whole bunch of peers in the last bin, expect depth to stay at 31 174 for i := 0; i < 15; i++ { 175 addr = swarm.RandAddressAt(t, base, int(swarm.MaxPO)) 176 addOne(t, signer, kad, ab, addr) 177 } 178 179 waitCounter(t, &conns, 15) 180 kDepth(t, kad, 31) 181 182 // remove one at 14, depth should be 14 183 removeOne(kad, addrs[len(addrs)-5]) 184 kDepth(t, kad, 30) 185 186 // empty bin 9 and expect depth 9 187 for i := 0; i < 4; i++ { 188 removeOne(kad, addrs[i]) 189 } 190 kDepth(t, kad, 9) 191 192 if !kad.IsWithinConnectionDepth(addrs[0]) { 193 t.Fatal("expected address to be within depth") 194 } 195 196 } 197 198 // Run the same test with reachability filter and setting the peers are reachable 199 func TestNeighborhoodDepthWithReachability(t *testing.T) { 200 t.Parallel() 201 202 var ( 203 conns int32 // how many connect calls were made to the p2p mock 204 base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ 205 SaturationPeers: ptrInt(4), 206 }) 207 ) 208 209 if err := kad.Start(context.Background()); err != nil { 210 t.Fatal(err) 211 } 212 testutil.CleanupCloser(t, kad) 213 214 kad.SetStorageRadius(0) 215 216 // add 2 peers in bin 8 217 for i := 0; i < 2; i++ { 218 addr := swarm.RandAddressAt(t, base, 8) 219 addOne(t, signer, kad, ab, addr) 220 kad.Reachable(addr, p2p.ReachabilityStatusPublic) 221 222 // wait for one connection 223 waitConn(t, &conns) 224 } 225 // depth is 0 226 kDepth(t, kad, 0) 227 228 var shallowPeers []swarm.Address 229 // add two first peers (po0,po1) 230 for i := 0; i < 2; i++ { 231 addr := swarm.RandAddressAt(t, base, i) 232 addOne(t, signer, kad, ab, addr) 233 kad.Reachable(addr, p2p.ReachabilityStatusPublic) 234 shallowPeers = append(shallowPeers, addr) 235 236 // wait for one connection 237 waitConn(t, &conns) 238 } 239 240 for _, a := range shallowPeers { 241 if !kad.IsWithinConnectionDepth(a) { 242 t.Fatal("expected address to be within depth") 243 } 244 } 245 246 // depth 0 - bin 0 is unsaturated 247 kDepth(t, kad, 0) 248 249 for i := 2; i < 8; i++ { 250 addr := swarm.RandAddressAt(t, base, i) 251 addOne(t, signer, kad, ab, addr) 252 kad.Reachable(addr, p2p.ReachabilityStatusPublic) 253 254 // wait for one connection 255 waitConn(t, &conns) 256 } 257 // still zero 258 kDepth(t, kad, 0) 259 260 // now add peers from bin 0 and expect the depth 261 // to shift. the depth will be that of the shallowest 262 // unsaturated bin. 263 for i := 0; i < 7; i++ { 264 for j := 0; j < 3; j++ { 265 addr := swarm.RandAddressAt(t, base, i) 266 addOne(t, signer, kad, ab, addr) 267 kad.Reachable(addr, p2p.ReachabilityStatusPublic) 268 waitConn(t, &conns) 269 } 270 kDepth(t, kad, i+1) 271 } 272 273 // depth is 7 because bin 7 is unsaturated (1 peer) 274 kDepth(t, kad, 7) 275 276 // expect shallow peers not in depth 277 for _, a := range shallowPeers { 278 if kad.IsWithinConnectionDepth(a) { 279 t.Fatal("expected address to outside of depth") 280 } 281 } 282 283 // now add another ONE peer at depth, and expect the depth to still 284 // stay 8, because the counter for nnLowWatermark would be reached only at the next 285 // depth iteration when calculating depth 286 addr := swarm.RandAddressAt(t, base, 8) 287 addOne(t, signer, kad, ab, addr) 288 kad.Reachable(addr, p2p.ReachabilityStatusPublic) 289 waitConn(t, &conns) 290 kDepth(t, kad, 7) 291 292 // now fill bin 7 so that it is saturated, expect depth 8 293 for i := 0; i < 3; i++ { 294 addr := swarm.RandAddressAt(t, base, 7) 295 addOne(t, signer, kad, ab, addr) 296 kad.Reachable(addr, p2p.ReachabilityStatusPublic) 297 waitConn(t, &conns) 298 } 299 kDepth(t, kad, 8) 300 301 // saturate bin 8 302 addr = swarm.RandAddressAt(t, base, 8) 303 addOne(t, signer, kad, ab, addr) 304 kad.Reachable(addr, p2p.ReachabilityStatusPublic) 305 waitConn(t, &conns) 306 kDepth(t, kad, 8) 307 308 var addrs []swarm.Address 309 // fill the rest up to the bin before last and check that everything works at the edges 310 for i := 9; i < int(swarm.MaxBins); i++ { 311 for j := 0; j < 4; j++ { 312 addr := swarm.RandAddressAt(t, base, i) 313 addOne(t, signer, kad, ab, addr) 314 kad.Reachable(addr, p2p.ReachabilityStatusPublic) 315 waitConn(t, &conns) 316 addrs = append(addrs, addr) 317 } 318 kDepth(t, kad, i) 319 } 320 321 // add a whole bunch of peers in the last bin, expect depth to stay at 31 322 for i := 0; i < 15; i++ { 323 addr = swarm.RandAddressAt(t, base, int(swarm.MaxPO)) 324 addOne(t, signer, kad, ab, addr) 325 kad.Reachable(addr, p2p.ReachabilityStatusPublic) 326 } 327 328 waitCounter(t, &conns, 15) 329 kDepth(t, kad, 31) 330 331 // remove one at 14, depth should be 14 332 removeOne(kad, addrs[len(addrs)-5]) 333 kDepth(t, kad, 30) 334 335 // empty bin 9 and expect depth 9 336 for i := 0; i < 4; i++ { 337 removeOne(kad, addrs[i]) 338 } 339 kDepth(t, kad, 9) 340 341 if !kad.IsWithinConnectionDepth(addrs[0]) { 342 t.Fatal("expected address to be within depth") 343 } 344 } 345 346 func TestManage(t *testing.T) { 347 t.Parallel() 348 349 var ( 350 conns int32 // how many connect calls were made to the p2p mock 351 saturation = kademlia.DefaultSaturationPeers 352 base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ 353 BitSuffixLength: ptrInt(-1), 354 ExcludeFunc: defaultExcludeFunc, 355 }) 356 ) 357 358 if err := kad.Start(context.Background()); err != nil { 359 t.Fatal(err) 360 } 361 testutil.CleanupCloser(t, kad) 362 363 kad.SetStorageRadius(0) 364 365 // first, we add peers to bin 0 366 for i := 0; i < saturation; i++ { 367 addr := swarm.RandAddressAt(t, base, 0) 368 addOne(t, signer, kad, ab, addr) 369 } 370 371 waitCounter(t, &conns, int32(saturation)) 372 373 // next, we add peers to the next bin 374 for i := 0; i < saturation; i++ { 375 addr := swarm.RandAddressAt(t, base, 1) 376 addOne(t, signer, kad, ab, addr) 377 } 378 379 waitCounter(t, &conns, int32(saturation)) 380 381 kad.SetStorageRadius(1) 382 383 // here, we attempt to add to bin 0, but bin is saturated, so no new peers should connect to it 384 for i := 0; i < saturation; i++ { 385 addr := swarm.RandAddressAt(t, base, 0) 386 addOne(t, signer, kad, ab, addr) 387 } 388 389 waitCounter(t, &conns, 0) 390 } 391 392 func TestManageWithBalancing(t *testing.T) { 393 t.Parallel() 394 395 var ( 396 conns int32 // how many connect calls were made to the p2p mock 397 398 saturationFuncImpl *func(bin uint8, connected *pslice.PSlice, _ kademlia.PeerExcludeFunc) bool 399 saturationFunc = func(bin uint8, connected *pslice.PSlice, filter kademlia.PeerExcludeFunc) bool { 400 f := *saturationFuncImpl 401 return f(bin, connected, filter) 402 } 403 base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ 404 SaturationFunc: saturationFunc, 405 SaturationPeers: ptrInt(4), 406 BitSuffixLength: ptrInt(2), 407 ExcludeFunc: defaultExcludeFunc, 408 }) 409 ) 410 411 // implement saturation function (while having access to Kademlia instance) 412 sfImpl := func(bin uint8, connected *pslice.PSlice, _ kademlia.PeerExcludeFunc) bool { 413 return false 414 } 415 saturationFuncImpl = &sfImpl 416 417 if err := kad.Start(context.Background()); err != nil { 418 t.Fatal(err) 419 } 420 testutil.CleanupCloser(t, kad) 421 422 // add peers for bin '0', enough to have balanced connections 423 add(t, signer, kad, ab, mineBin(t, base, 0, 20, true), 0, 20) 424 425 waitBalanced(t, kad, 0) 426 427 // add peers for other bins, enough to have balanced connections 428 for i := 1; i <= int(swarm.MaxPO); i++ { 429 add(t, signer, kad, ab, mineBin(t, base, i, 20, true), 0, 20) 430 // sanity check depth 431 kDepth(t, kad, i) 432 } 433 434 for i := 1; i <= int(swarm.MaxPO); i++ { 435 waitBalanced(t, kad, uint8(i)) 436 } 437 } 438 439 // TestBinSaturation tests the builtin binSaturated function. 440 // the test must have two phases of adding peers so that the section 441 // beyond the first flow control statement gets hit (if po >= depth), 442 // meaning, on the first iteration we add peer and this condition will always 443 // be true since depth is increasingly moving deeper, but then we add more peers 444 // in shallower depth for the rest of the function to be executed 445 func TestBinSaturation(t *testing.T) { 446 t.Parallel() 447 448 var ( 449 conns int32 // how many connect calls were made to the p2p mock 450 base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ 451 SaturationPeers: ptrInt(2), 452 BitSuffixLength: ptrInt(-1), 453 ExcludeFunc: defaultExcludeFunc, 454 }) 455 ) 456 457 if err := kad.Start(context.Background()); err != nil { 458 t.Fatal(err) 459 } 460 testutil.CleanupCloser(t, kad) 461 462 kad.SetStorageRadius(0) 463 464 // add two peers in a few bins to generate some depth >= 0, this will 465 // make the next iteration result in binSaturated==true, causing no new 466 // connections to be made 467 for i := 0; i < 5; i++ { 468 for j := 0; j < 2; j++ { 469 addr := swarm.RandAddressAt(t, base, i) 470 addOne(t, signer, kad, ab, addr) 471 } 472 } 473 waitCounter(t, &conns, 10) 474 475 kad.SetStorageRadius(3) 476 477 // add one more peer in each bin shallower than depth and 478 // expect no connections due to saturation. if we add a peer within 479 // depth, the short circuit will be hit and we will connect to the peer 480 for i := 0; i < 3; i++ { 481 addr := swarm.RandAddressAt(t, base, i) 482 addOne(t, signer, kad, ab, addr) 483 } 484 waitCounter(t, &conns, 0) 485 486 // add one peer in a bin higher (unsaturated) and expect one connection 487 addr := swarm.RandAddressAt(t, base, 6) 488 addOne(t, signer, kad, ab, addr) 489 490 waitCounter(t, &conns, 1) 491 492 // again, one bin higher 493 addr = swarm.RandAddressAt(t, base, 7) 494 addOne(t, signer, kad, ab, addr) 495 496 waitCounter(t, &conns, 1) 497 498 } 499 500 func TestOversaturation(t *testing.T) { 501 t.Parallel() 502 503 var ( 504 conns int32 // how many connect calls were made to the p2p mock 505 base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ 506 ExcludeFunc: defaultExcludeFunc, 507 }) 508 ) 509 510 if err := kad.Start(context.Background()); err != nil { 511 t.Fatal(err) 512 } 513 testutil.CleanupCloser(t, kad) 514 515 // Add maximum accepted number of peers up until bin 5 without problems 516 for i := 0; i < 6; i++ { 517 for j := 0; j < kademlia.DefaultOverSaturationPeers; j++ { 518 addr := swarm.RandAddressAt(t, base, i) 519 // if error is not nil as specified, connectOne goes fatal 520 connectOne(t, signer, kad, ab, addr, nil) 521 } 522 // see depth is limited to currently added peers proximity 523 kDepth(t, kad, i) 524 } 525 526 // see depth is 5 527 kDepth(t, kad, 5) 528 529 for k := 0; k < 5; k++ { 530 // no further connections can be made 531 for l := 0; l < 3; l++ { 532 addr := swarm.RandAddressAt(t, base, k) 533 // if error is not as specified, connectOne goes fatal 534 connectOne(t, signer, kad, ab, addr, topology.ErrOversaturated) 535 // check that pick works correctly 536 if kad.Pick(p2p.Peer{Address: addr, FullNode: true}) { 537 t.Fatal("should not pick the peer") 538 } 539 if !kad.Pick(p2p.Peer{Address: addr, FullNode: false}) { 540 t.Fatal("should pick the peer") 541 } 542 } 543 // see depth is still as expected 544 kDepth(t, kad, 5) 545 } 546 } 547 548 func TestOversaturationBootnode(t *testing.T) { 549 t.Parallel() 550 551 var ( 552 overSaturationPeers = 4 553 conns int32 // how many connect calls were made to the p2p mock 554 base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ 555 OverSaturationPeers: ptrInt(overSaturationPeers), 556 SaturationPeers: ptrInt(4), 557 BootnodeMode: true, 558 ExcludeFunc: defaultExcludeFunc, 559 }) 560 ) 561 562 if err := kad.Start(context.Background()); err != nil { 563 t.Fatal(err) 564 } 565 testutil.CleanupCloser(t, kad) 566 567 // Add maximum accepted number of peers up until bin 5 without problems 568 for i := 0; i < 6; i++ { 569 for j := 0; j < overSaturationPeers; j++ { 570 addr := swarm.RandAddressAt(t, base, i) 571 // if error is not nil as specified, connectOne goes fatal 572 connectOne(t, signer, kad, ab, addr, nil) 573 } 574 // see depth is limited to currently added peers proximity 575 kDepth(t, kad, i) 576 } 577 578 // see depth is 5 579 kDepth(t, kad, 5) 580 581 for k := 0; k < 5; k++ { 582 // further connections should succeed outside of depth 583 for l := 0; l < 3; l++ { 584 addr := swarm.RandAddressAt(t, base, k) 585 // if error is not as specified, connectOne goes fatal 586 connectOne(t, signer, kad, ab, addr, nil) 587 // check that pick works correctly 588 if !kad.Pick(p2p.Peer{Address: addr}) { 589 t.Fatal("should pick the peer but didn't") 590 } 591 } 592 // see depth is still as expected 593 kDepth(t, kad, 5) 594 } 595 596 // see we can still add / not limiting more peers in neighborhood depth 597 for m := 0; m < 12; m++ { 598 addr := swarm.RandAddressAt(t, base, 5) 599 // if error is not nil as specified, connectOne goes fatal 600 connectOne(t, signer, kad, ab, addr, nil) 601 // see depth is still as expected 602 kDepth(t, kad, 5) 603 } 604 } 605 606 func TestBootnodeMaxConnections(t *testing.T) { 607 t.Parallel() 608 609 var ( 610 bootnodeOverSaturationPeers = 4 611 conns int32 // how many connect calls were made to the p2p mock 612 base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ 613 BootnodeOverSaturationPeers: ptrInt(bootnodeOverSaturationPeers), 614 SaturationPeers: ptrInt(4), 615 BootnodeMode: true, 616 ExcludeFunc: defaultExcludeFunc, 617 }) 618 ) 619 620 if err := kad.Start(context.Background()); err != nil { 621 t.Fatal(err) 622 } 623 testutil.CleanupCloser(t, kad) 624 625 // Add maximum accepted number of peers up until bin 5 without problems 626 for i := 0; i < 6; i++ { 627 for j := 0; j < bootnodeOverSaturationPeers; j++ { 628 addr := swarm.RandAddressAt(t, base, i) 629 // if error is not nil as specified, connectOne goes fatal 630 connectOne(t, signer, kad, ab, addr, nil) 631 } 632 // see depth is limited to currently added peers proximity 633 kDepth(t, kad, i) 634 } 635 636 // see depth is 5 637 kDepth(t, kad, 5) 638 639 depth := 5 640 outSideDepthPeers := 5 641 642 for k := 0; k < depth; k++ { 643 // further connections should succeed outside of depth 644 for l := 0; l < outSideDepthPeers; l++ { 645 addr := swarm.RandAddressAt(t, base, k) 646 // if error is not as specified, connectOne goes fatal 647 connectOne(t, signer, kad, ab, addr, nil) 648 // check that pick works correctly 649 if !kad.Pick(p2p.Peer{Address: addr}) { 650 t.Fatal("should pick the peer but didn't") 651 } 652 } 653 } 654 655 got := atomic.LoadInt32(&conns) 656 want := -int32(depth * outSideDepthPeers) 657 if got != want { 658 t.Fatalf("got %d, want %d", got, want) 659 } 660 } 661 662 // TestNotifierHooks tests that the Connected/Disconnected hooks 663 // result in the correct behavior once called. 664 func TestNotifierHooks(t *testing.T) { 665 t.Parallel() 666 t.Skip("disabled due to kademlia inconsistencies hotfix") 667 668 var ( 669 base, kad, ab, _, signer = newTestKademlia(t, nil, nil, kademlia.Options{}) 670 peer = swarm.RandAddressAt(t, base, 3) 671 addr = swarm.RandAddressAt(t, peer, 4) // address which is closer to peer 672 ) 673 674 if err := kad.Start(context.Background()); err != nil { 675 t.Fatal(err) 676 } 677 testutil.CleanupCloser(t, kad) 678 679 connectOne(t, signer, kad, ab, peer, nil) 680 681 p, err := kad.ClosestPeer(addr, true, topology.Select{}) 682 if err != nil { 683 t.Fatal(err) 684 } 685 686 if !p.Equal(peer) { 687 t.Fatal("got wrong peer address") 688 } 689 690 // disconnect the peer, expect error 691 kad.Disconnected(p2p.Peer{Address: peer}) 692 _, err = kad.ClosestPeer(addr, true, topology.Select{}) 693 if !errors.Is(err, topology.ErrNotFound) { 694 t.Fatalf("expected topology.ErrNotFound but got %v", err) 695 } 696 } 697 698 // TestDiscoveryHooks check that a peer is gossiped to other peers 699 // once we establish a connection to this peer. This could be as a result of 700 // us proactively dialing in to a peer, or when a peer dials in. 701 func TestDiscoveryHooks(t *testing.T) { 702 t.Parallel() 703 704 var ( 705 conns int32 706 _, kad, ab, disc, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ 707 ExcludeFunc: defaultExcludeFunc, 708 }) 709 p1, p2, p3 = swarm.RandAddress(t), swarm.RandAddress(t), swarm.RandAddress(t) 710 ) 711 712 kad.SetStorageRadius(0) 713 714 if err := kad.Start(context.Background()); err != nil { 715 t.Fatal(err) 716 } 717 testutil.CleanupCloser(t, kad) 718 719 // first add a peer from AddPeers, wait for the connection 720 addOne(t, signer, kad, ab, p1) 721 waitConn(t, &conns) 722 // add another peer from AddPeers, wait for the connection 723 // then check that peers are gossiped to each other via discovery 724 addOne(t, signer, kad, ab, p2) 725 waitConn(t, &conns) 726 waitBcast(t, disc, p1, p2) 727 waitBcast(t, disc, p2, p1) 728 729 disc.Reset() 730 731 // add another peer that dialed in, check that all peers gossiped 732 // correctly to each other 733 connectOne(t, signer, kad, ab, p3, nil) 734 waitBcast(t, disc, p1, p3) 735 waitBcast(t, disc, p2, p3) 736 waitBcast(t, disc, p3, p1, p2) 737 } 738 739 func TestAnnounceTo(t *testing.T) { 740 t.Parallel() 741 742 var ( 743 conns int32 744 _, kad, ab, disc, signer = newTestKademlia(t, &conns, nil, kademlia.Options{}) 745 p1, p2 = swarm.RandAddress(t), swarm.RandAddress(t) 746 ) 747 748 if err := kad.Start(context.Background()); err != nil { 749 t.Fatal(err) 750 } 751 testutil.CleanupCloser(t, kad) 752 753 // first add a peer from AddPeers, wait for the connection 754 addOne(t, signer, kad, ab, p1) 755 waitConn(t, &conns) 756 757 if err := kad.AnnounceTo(context.Background(), p1, p2, true); err != nil { 758 t.Fatal(err) 759 } 760 waitBcast(t, disc, p1, p2) 761 762 if err := kad.AnnounceTo(context.Background(), p1, p2, false); err == nil { 763 t.Fatal("expected error") 764 } 765 } 766 767 func TestBackoff(t *testing.T) { 768 t.Parallel() 769 770 var ( 771 conns int32 // how many connect calls were made to the p2p mock 772 base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ 773 TimeToRetry: ptrDuration(500 * time.Millisecond), 774 }) 775 ) 776 kad.SetStorageRadius(0) 777 778 if err := kad.Start(context.Background()); err != nil { 779 t.Fatal(err) 780 } 781 testutil.CleanupCloser(t, kad) 782 783 // add one peer, wait for connection 784 addr := swarm.RandAddressAt(t, base, 1) 785 addOne(t, signer, kad, ab, addr) 786 787 waitCounter(t, &conns, 1) 788 789 // remove that peer 790 removeOne(kad, addr) 791 792 waitCounter(t, &conns, 0) 793 794 // wait for 100ms, add another peer, expect just one more connection 795 time.Sleep(100 * time.Millisecond) 796 addr = swarm.RandAddressAt(t, base, 1) 797 addOne(t, signer, kad, ab, addr) 798 799 waitCounter(t, &conns, 1) 800 801 // wait for another 400ms, add another, expect 2 connections 802 time.Sleep(400 * time.Millisecond) 803 addr = swarm.RandAddressAt(t, base, 1) 804 addOne(t, signer, kad, ab, addr) 805 806 waitCounter(t, &conns, 2) 807 } 808 809 // test pruning addressbook after successive failed connect attempts 810 func TestAddressBookPrune(t *testing.T) { 811 t.Parallel() 812 813 var ( 814 conns, failedConns int32 // how many connect calls were made to the p2p mock 815 base, kad, ab, _, signer = newTestKademlia(t, &conns, &failedConns, kademlia.Options{ 816 TimeToRetry: ptrDuration(0), 817 }) 818 ) 819 820 kad.SetStorageRadius(0) 821 822 if err := kad.Start(context.Background()); err != nil { 823 t.Fatal(err) 824 } 825 testutil.CleanupCloser(t, kad) 826 827 nonConnPeer, err := bzz.NewAddress(signer, nonConnectableAddress, swarm.RandAddressAt(t, base, 1), 0, nil) 828 if err != nil { 829 t.Fatal(err) 830 } 831 if err := ab.Put(nonConnPeer.Overlay, *nonConnPeer); err != nil { 832 t.Fatal(err) 833 } 834 835 // add non connectable peer, check connection and failed connection counters 836 kad.AddPeers(nonConnPeer.Overlay) 837 838 kad.Trigger() 839 kad.Trigger() 840 841 waitCounter(t, &conns, 0) 842 waitCounter(t, &failedConns, 3) 843 844 _, err = ab.Get(nonConnPeer.Overlay) 845 if !errors.Is(err, addressbook.ErrNotFound) { 846 t.Fatal(err) 847 } 848 849 addr := swarm.RandAddressAt(t, base, 1) 850 addr1 := swarm.RandAddressAt(t, base, 1) 851 addr2 := swarm.RandAddressAt(t, base, 1) 852 853 // add one valid peer to initiate the retry, check connection and failed connection counters 854 addOne(t, signer, kad, ab, addr) 855 waitCounter(t, &conns, 1) 856 waitCounter(t, &failedConns, 0) 857 858 _, err = ab.Get(nonConnPeer.Overlay) 859 if !errors.Is(err, addressbook.ErrNotFound) { 860 t.Fatal(err) 861 } 862 863 time.Sleep(50 * time.Millisecond) 864 // add one valid peer to initiate the retry, check connection and failed connection counters 865 addOne(t, signer, kad, ab, addr1) 866 waitCounter(t, &conns, 1) 867 waitCounter(t, &failedConns, 0) 868 869 _, err = ab.Get(nonConnPeer.Overlay) 870 if !errors.Is(err, addressbook.ErrNotFound) { 871 t.Fatal(err) 872 } 873 874 time.Sleep(50 * time.Millisecond) 875 // add one valid peer to initiate the retry, check connection and failed connection counters 876 addOne(t, signer, kad, ab, addr2) 877 waitCounter(t, &conns, 1) 878 waitCounter(t, &failedConns, 0) 879 880 _, err = ab.Get(nonConnPeer.Overlay) 881 if !errors.Is(err, addressbook.ErrNotFound) { 882 t.Fatal(err) 883 } 884 } 885 886 // test pruning addressbook after successive failed connect attempts 887 func TestAddressBookQuickPrune_FLAKY(t *testing.T) { 888 t.Parallel() 889 890 var ( 891 conns, failedConns int32 // how many connect calls were made to the p2p mock 892 base, kad, ab, _, signer = newTestKademlia(t, &conns, &failedConns, kademlia.Options{ 893 TimeToRetry: ptrDuration(time.Millisecond), 894 }) 895 ) 896 kad.SetStorageRadius(2) 897 898 if err := kad.Start(context.Background()); err != nil { 899 t.Fatal(err) 900 } 901 testutil.CleanupCloser(t, kad) 902 903 time.Sleep(100 * time.Millisecond) 904 905 nonConnPeer, err := bzz.NewAddress(signer, nonConnectableAddress, swarm.RandAddressAt(t, base, 1), 0, nil) 906 if err != nil { 907 t.Fatal(err) 908 } 909 if err := ab.Put(nonConnPeer.Overlay, *nonConnPeer); err != nil { 910 t.Fatal(err) 911 } 912 913 addr := swarm.RandAddressAt(t, base, 1) 914 // add one valid peer 915 addOne(t, signer, kad, ab, addr) 916 waitCounter(t, &conns, 1) 917 waitCounter(t, &failedConns, 0) 918 919 // add non connectable peer, check connection and failed connection counters 920 kad.AddPeers(nonConnPeer.Overlay) 921 waitCounter(t, &conns, 0) 922 waitCounter(t, &failedConns, 1) 923 924 _, err = ab.Get(nonConnPeer.Overlay) 925 if !errors.Is(err, addressbook.ErrNotFound) { 926 t.Fatal(err) 927 } 928 } 929 930 func TestClosestPeer(t *testing.T) { 931 t.Parallel() 932 t.Skip("disabled due to kademlia inconsistencies hotfix") 933 934 _ = waitPeers 935 936 logger := log.Noop 937 base := swarm.MustParseHexAddress("0000000000000000000000000000000000000000000000000000000000000000") // base is 0000 938 connectedPeers := []p2p.Peer{ 939 { 940 Address: swarm.MustParseHexAddress("8000000000000000000000000000000000000000000000000000000000000000"), // binary 1000 -> po 0 to base 941 }, 942 { 943 Address: swarm.MustParseHexAddress("4000000000000000000000000000000000000000000000000000000000000000"), // binary 0100 -> po 1 to base 944 }, 945 { 946 Address: swarm.MustParseHexAddress("6000000000000000000000000000000000000000000000000000000000000000"), // binary 0110 -> po 1 to base 947 }, 948 } 949 950 disc := mock.NewDiscovery() 951 ab := addressbook.New(mockstate.NewStateStore()) 952 953 kad, err := kademlia.New(base, ab, disc, p2pMock(t, ab, nil, nil, nil), logger, kademlia.Options{}) 954 if err != nil { 955 t.Fatal(err) 956 } 957 if err := kad.Start(context.Background()); err != nil { 958 t.Fatal(err) 959 } 960 testutil.CleanupCloser(t, kad) 961 962 pk, _ := beeCrypto.GenerateSecp256k1Key() 963 for _, v := range connectedPeers { 964 addOne(t, beeCrypto.NewDefaultSigner(pk), kad, ab, v.Address) 965 } 966 967 waitPeers(t, kad, 3) 968 969 for _, tc := range []struct { 970 chunkAddress swarm.Address // chunk address to test 971 expectedPeer int // points to the index of the connectedPeers slice. -1 means self (baseOverlay) 972 includeSelf bool 973 }{ 974 { 975 chunkAddress: swarm.MustParseHexAddress("7000000000000000000000000000000000000000000000000000000000000000"), // 0111, wants peer 2 976 expectedPeer: 2, 977 includeSelf: true, 978 }, 979 { 980 chunkAddress: swarm.MustParseHexAddress("c000000000000000000000000000000000000000000000000000000000000000"), // 1100, want peer 0 981 expectedPeer: 0, 982 includeSelf: true, 983 }, 984 { 985 chunkAddress: swarm.MustParseHexAddress("e000000000000000000000000000000000000000000000000000000000000000"), // 1110, want peer 0 986 expectedPeer: 0, 987 includeSelf: true, 988 }, 989 { 990 chunkAddress: swarm.MustParseHexAddress("a000000000000000000000000000000000000000000000000000000000000000"), // 1010, want peer 0 991 expectedPeer: 0, 992 includeSelf: true, 993 }, 994 { 995 chunkAddress: swarm.MustParseHexAddress("4000000000000000000000000000000000000000000000000000000000000000"), // 0100, want peer 1 996 expectedPeer: 1, 997 includeSelf: true, 998 }, 999 { 1000 chunkAddress: swarm.MustParseHexAddress("5000000000000000000000000000000000000000000000000000000000000000"), // 0101, want peer 1 1001 expectedPeer: 1, 1002 includeSelf: true, 1003 }, 1004 { 1005 chunkAddress: swarm.MustParseHexAddress("0000001000000000000000000000000000000000000000000000000000000000"), // 1000 want self 1006 expectedPeer: -1, 1007 includeSelf: true, 1008 }, 1009 { 1010 chunkAddress: swarm.MustParseHexAddress("0000001000000000000000000000000000000000000000000000000000000000"), // 1000 want peer 1 1011 expectedPeer: 1, // smallest distance: 2894... 1012 includeSelf: false, 1013 }, 1014 } { 1015 peer, err := kad.ClosestPeer(tc.chunkAddress, tc.includeSelf, topology.Select{}) 1016 if err != nil { 1017 if tc.expectedPeer == -1 && !errors.Is(err, topology.ErrWantSelf) { 1018 t.Fatalf("wanted %v but got %v", topology.ErrWantSelf, err) 1019 } 1020 continue 1021 } 1022 1023 expected := connectedPeers[tc.expectedPeer].Address 1024 1025 if !peer.Equal(expected) { 1026 t.Fatalf("peers not equal. got %s expected %s", peer, expected) 1027 } 1028 } 1029 } 1030 1031 func TestKademlia_SubscribeTopologyChange(t *testing.T) { 1032 t.Parallel() 1033 1034 testSignal := func(t *testing.T, c <-chan struct{}) { 1035 t.Helper() 1036 1037 select { 1038 case _, ok := <-c: 1039 if !ok { 1040 t.Error("closed signal channel") 1041 } 1042 case <-time.After(1 * time.Second): 1043 t.Error("timeout") 1044 } 1045 } 1046 1047 t.Run("single subscription", func(t *testing.T) { 1048 t.Parallel() 1049 1050 base, kad, ab, _, sg := newTestKademlia(t, nil, nil, kademlia.Options{}) 1051 if err := kad.Start(context.Background()); err != nil { 1052 t.Fatal(err) 1053 } 1054 testutil.CleanupCloser(t, kad) 1055 1056 c, u := kad.SubscribeTopologyChange() 1057 defer u() 1058 1059 addr := swarm.RandAddressAt(t, base, 9) 1060 addOne(t, sg, kad, ab, addr) 1061 1062 testSignal(t, c) 1063 }) 1064 1065 t.Run("single subscription, remove peer", func(t *testing.T) { 1066 t.Parallel() 1067 1068 base, kad, ab, _, sg := newTestKademlia(t, nil, nil, kademlia.Options{}) 1069 if err := kad.Start(context.Background()); err != nil { 1070 t.Fatal(err) 1071 } 1072 testutil.CleanupCloser(t, kad) 1073 1074 c, u := kad.SubscribeTopologyChange() 1075 defer u() 1076 1077 addr := swarm.RandAddressAt(t, base, 9) 1078 addOne(t, sg, kad, ab, addr) 1079 1080 testSignal(t, c) 1081 1082 removeOne(kad, addr) 1083 testSignal(t, c) 1084 }) 1085 1086 t.Run("multiple subscriptions", func(t *testing.T) { 1087 t.Parallel() 1088 1089 base, kad, ab, _, sg := newTestKademlia(t, nil, nil, kademlia.Options{}) 1090 if err := kad.Start(context.Background()); err != nil { 1091 t.Fatal(err) 1092 } 1093 testutil.CleanupCloser(t, kad) 1094 1095 c1, u1 := kad.SubscribeTopologyChange() 1096 defer u1() 1097 1098 c2, u2 := kad.SubscribeTopologyChange() 1099 defer u2() 1100 1101 for i := 0; i < 4; i++ { 1102 addr := swarm.RandAddressAt(t, base, i) 1103 addOne(t, sg, kad, ab, addr) 1104 } 1105 testSignal(t, c1) 1106 testSignal(t, c2) 1107 }) 1108 1109 t.Run("multiple changes", func(t *testing.T) { 1110 t.Parallel() 1111 1112 base, kad, ab, _, sg := newTestKademlia(t, nil, nil, kademlia.Options{}) 1113 if err := kad.Start(context.Background()); err != nil { 1114 t.Fatal(err) 1115 } 1116 testutil.CleanupCloser(t, kad) 1117 1118 c, u := kad.SubscribeTopologyChange() 1119 defer u() 1120 1121 for i := 0; i < 4; i++ { 1122 addr := swarm.RandAddressAt(t, base, i) 1123 addOne(t, sg, kad, ab, addr) 1124 } 1125 1126 testSignal(t, c) 1127 1128 for i := 0; i < 4; i++ { 1129 addr := swarm.RandAddressAt(t, base, i) 1130 addOne(t, sg, kad, ab, addr) 1131 } 1132 1133 testSignal(t, c) 1134 }) 1135 1136 t.Run("no depth change", func(t *testing.T) { 1137 t.Parallel() 1138 1139 _, kad, _, _, _ := newTestKademlia(t, nil, nil, kademlia.Options{}) 1140 if err := kad.Start(context.Background()); err != nil { 1141 t.Fatal(err) 1142 } 1143 testutil.CleanupCloser(t, kad) 1144 1145 c, u := kad.SubscribeTopologyChange() 1146 defer u() 1147 1148 select { 1149 case _, ok := <-c: 1150 if !ok { 1151 t.Error("closed signal channel") 1152 } 1153 t.Error("signal received") 1154 case <-time.After(1 * time.Second): 1155 // all fine 1156 } 1157 }) 1158 } 1159 1160 func TestSnapshot_FLAKY(t *testing.T) { 1161 t.Parallel() 1162 1163 var conns = new(int32) 1164 sa, kad, ab, _, signer := newTestKademlia(t, conns, nil, kademlia.Options{}) 1165 if err := kad.Start(context.Background()); err != nil { 1166 t.Fatal(err) 1167 } 1168 testutil.CleanupCloser(t, kad) 1169 1170 a := swarm.RandAddress(t) 1171 addOne(t, signer, kad, ab, a) 1172 1173 waitConn(t, conns) 1174 1175 snap := kad.Snapshot() 1176 1177 if snap.Connected != 1 { 1178 t.Errorf("expected %d connected peers but got %d", 1, snap.Connected) 1179 } 1180 if snap.Population != 1 { 1181 t.Errorf("expected population %d but got %d", 1, snap.Population) 1182 } 1183 1184 po := swarm.Proximity(sa.Bytes(), a.Bytes()) 1185 1186 if binP := getBinPopulation(&snap.Bins, po); binP != 1 { 1187 t.Errorf("expected bin(%d) to have population %d but got %d", po, 1, snap.Population) 1188 } 1189 } 1190 1191 func getBinPopulation(bins *topology.KadBins, po uint8) uint64 { 1192 rv := reflect.ValueOf(bins) 1193 bin := fmt.Sprintf("Bin%d", po) 1194 b0 := reflect.Indirect(rv).FieldByName(bin) 1195 bp := b0.FieldByName("BinPopulation") 1196 return bp.Uint() 1197 } 1198 1199 func TestStart(t *testing.T) { 1200 t.Parallel() 1201 1202 var bootnodes []ma.Multiaddr 1203 for i := 0; i < 10; i++ { 1204 multiaddr, err := ma.NewMultiaddr(underlayBase + swarm.RandAddress(t).String()) 1205 if err != nil { 1206 t.Fatal(err) 1207 } 1208 1209 bootnodes = append(bootnodes, multiaddr) 1210 } 1211 1212 t.Run("non-empty addressbook", func(t *testing.T) { 1213 t.Parallel() 1214 t.Skip("test flakes") 1215 1216 var conns, failedConns int32 // how many connect calls were made to the p2p mock 1217 _, kad, ab, _, signer := newTestKademlia(t, &conns, &failedConns, kademlia.Options{Bootnodes: bootnodes}) 1218 1219 for i := 0; i < 3; i++ { 1220 peer := swarm.RandAddress(t) 1221 multiaddr, err := ma.NewMultiaddr(underlayBase + peer.String()) 1222 if err != nil { 1223 t.Fatal(err) 1224 } 1225 bzzAddr, err := bzz.NewAddress(signer, multiaddr, peer, 0, nil) 1226 if err != nil { 1227 t.Fatal(err) 1228 } 1229 if err := ab.Put(peer, *bzzAddr); err != nil { 1230 t.Fatal(err) 1231 } 1232 } 1233 1234 if err := kad.Start(context.Background()); err != nil { 1235 t.Fatal(err) 1236 } 1237 testutil.CleanupCloser(t, kad) 1238 1239 waitCounter(t, &conns, 3) 1240 waitCounter(t, &failedConns, 0) 1241 }) 1242 1243 t.Run("empty addressbook", func(t *testing.T) { 1244 t.Parallel() 1245 1246 var conns, failedConns int32 // how many connect calls were made to the p2p mock 1247 _, kad, _, _, _ := newTestKademlia(t, &conns, &failedConns, kademlia.Options{Bootnodes: bootnodes}) 1248 1249 if err := kad.Start(context.Background()); err != nil { 1250 t.Fatal(err) 1251 } 1252 testutil.CleanupCloser(t, kad) 1253 1254 waitCounter(t, &conns, 3) 1255 waitCounter(t, &failedConns, 0) 1256 }) 1257 } 1258 1259 func TestOutofDepthPrune(t *testing.T) { 1260 t.Parallel() 1261 1262 var ( 1263 conns, failedConns int32 // how many connect calls were made to the p2p mock 1264 1265 saturationPeers = 4 1266 overSaturationPeers = 16 1267 pruneWakeup = time.Millisecond * 100 1268 pruneFuncImpl *func(uint8) 1269 pruneMux = sync.Mutex{} 1270 pruneFunc = func(depth uint8) { 1271 pruneMux.Lock() 1272 defer pruneMux.Unlock() 1273 f := *pruneFuncImpl 1274 f(depth) 1275 } 1276 1277 base, kad, ab, _, signer = newTestKademlia(t, &conns, &failedConns, kademlia.Options{ 1278 SaturationPeers: ptrInt(saturationPeers), 1279 OverSaturationPeers: ptrInt(overSaturationPeers), 1280 PruneFunc: pruneFunc, 1281 ExcludeFunc: defaultExcludeFunc, 1282 PruneWakeup: &pruneWakeup, 1283 }) 1284 ) 1285 1286 kad.SetStorageRadius(0) 1287 1288 // implement empty prune func 1289 pruneMux.Lock() 1290 pruneImpl := func(uint8) {} 1291 pruneFuncImpl = &(pruneImpl) 1292 pruneMux.Unlock() 1293 1294 if err := kad.Start(context.Background()); err != nil { 1295 t.Fatal(err) 1296 } 1297 testutil.CleanupCloser(t, kad) 1298 1299 // bin 0,1 balanced, rest not 1300 for i := 0; i < 6; i++ { 1301 var peers []swarm.Address 1302 if i < 2 { 1303 peers = mineBin(t, base, i, 20, true) 1304 } else { 1305 peers = mineBin(t, base, i, 20, false) 1306 } 1307 for _, peer := range peers { 1308 addOne(t, signer, kad, ab, peer) 1309 } 1310 time.Sleep(time.Millisecond * 10) 1311 kDepth(t, kad, i) 1312 } 1313 1314 // check that bin 0, 1 are balanced, but not 2 1315 waitBalanced(t, kad, 0) 1316 waitBalanced(t, kad, 1) 1317 if kad.IsBalanced(2) { 1318 t.Fatal("bin 2 should not be balanced") 1319 } 1320 1321 // wait for kademlia connectors and pruning to finish 1322 time.Sleep(time.Millisecond * 500) 1323 1324 // check that no pruning has happened 1325 bins := binSizes(kad) 1326 for i := 0; i < 6; i++ { 1327 if bins[i] <= overSaturationPeers { 1328 t.Fatalf("bin %d, got %d, want more than %d", i, bins[i], overSaturationPeers) 1329 } 1330 } 1331 1332 kad.SetStorageRadius(6) 1333 1334 // set prune func to the default 1335 pruneMux.Lock() 1336 pruneImpl = func(depth uint8) { 1337 kademlia.PruneOversaturatedBinsFunc(kad)(depth) 1338 } 1339 pruneFuncImpl = &(pruneImpl) 1340 pruneMux.Unlock() 1341 1342 // add a peer to kick start pruning 1343 addr := swarm.RandAddressAt(t, base, 6) 1344 addOne(t, signer, kad, ab, addr) 1345 1346 // wait for kademlia connectors and pruning to finish 1347 time.Sleep(time.Millisecond * 500) 1348 1349 // check bins have been pruned 1350 bins = binSizes(kad) 1351 for i := uint8(0); i < 5; i++ { 1352 if bins[i] != overSaturationPeers { 1353 t.Fatalf("bin %d, got %d, want %d", i, bins[i], overSaturationPeers) 1354 } 1355 } 1356 1357 // check that bin 0,1 remains balanced after pruning 1358 waitBalanced(t, kad, 0) 1359 waitBalanced(t, kad, 1) 1360 } 1361 1362 // TestPruneExcludeOps tests that the prune bin func counts peers in each bin correctly using the peer's reachability status and does not over prune. 1363 func TestPruneExcludeOps(t *testing.T) { 1364 t.Parallel() 1365 1366 var ( 1367 conns, failedConns int32 // how many connect calls were made to the p2p mock 1368 1369 saturationPeers = 4 1370 overSaturationPeers = 16 1371 perBin = 20 1372 pruneFuncImpl *func(uint8) 1373 pruneMux = sync.Mutex{} 1374 pruneFunc = func(depth uint8) { 1375 pruneMux.Lock() 1376 defer pruneMux.Unlock() 1377 f := *pruneFuncImpl 1378 f(depth) 1379 } 1380 1381 base, kad, ab, _, signer = newTestKademlia(t, &conns, &failedConns, kademlia.Options{ 1382 SaturationPeers: ptrInt(saturationPeers), 1383 OverSaturationPeers: ptrInt(overSaturationPeers), 1384 PruneFunc: pruneFunc, 1385 }) 1386 ) 1387 1388 kad.SetStorageRadius(0) 1389 1390 // implement empty prune func 1391 pruneMux.Lock() 1392 pruneImpl := func(uint8) {} 1393 pruneFuncImpl = &(pruneImpl) 1394 pruneMux.Unlock() 1395 1396 if err := kad.Start(context.Background()); err != nil { 1397 t.Fatal(err) 1398 } 1399 testutil.CleanupCloser(t, kad) 1400 1401 // bin 0,1 balanced, rest not 1402 for i := 0; i < 6; i++ { 1403 var peers []swarm.Address 1404 if i < 2 { 1405 peers = mineBin(t, base, i, perBin, true) 1406 } else { 1407 peers = mineBin(t, base, i, perBin, false) 1408 } 1409 for i, peer := range peers { 1410 addOne(t, signer, kad, ab, peer) 1411 if i < 4 { 1412 kad.Reachable(peers[i], p2p.ReachabilityStatusPrivate) 1413 } else { 1414 kad.Reachable(peers[i], p2p.ReachabilityStatusPublic) 1415 } 1416 } 1417 for i := 0; i < 4; i++ { 1418 } 1419 time.Sleep(time.Millisecond * 10) 1420 kDepth(t, kad, i) 1421 } 1422 1423 // check that bin 0, 1 are balanced, but not 2 1424 waitBalanced(t, kad, 0) 1425 waitBalanced(t, kad, 1) 1426 if kad.IsBalanced(2) { 1427 t.Fatal("bin 2 should not be balanced") 1428 } 1429 1430 // wait for kademlia connectors and pruning to finish 1431 time.Sleep(time.Millisecond * 500) 1432 1433 // check that no pruning has happened 1434 bins := binSizes(kad) 1435 for i := 0; i < 6; i++ { 1436 if bins[i] <= overSaturationPeers { 1437 t.Fatalf("bin %d, got %d, want more than %d", i, bins[i], overSaturationPeers) 1438 } 1439 } 1440 1441 kad.SetStorageRadius(6) 1442 1443 // set prune func to the default 1444 pruneMux.Lock() 1445 pruneImpl = func(depth uint8) { 1446 kademlia.PruneOversaturatedBinsFunc(kad)(depth) 1447 } 1448 pruneFuncImpl = &(pruneImpl) 1449 pruneMux.Unlock() 1450 1451 // add a peer to kick start pruning 1452 addr := swarm.RandAddressAt(t, base, 6) 1453 addOne(t, signer, kad, ab, addr) 1454 1455 // wait for kademlia connectors and pruning to finish 1456 time.Sleep(time.Millisecond * 500) 1457 1458 // check bins have NOT been pruned because the peer count func excluded unreachable peers 1459 bins = binSizes(kad) 1460 for i := uint8(0); i < 5; i++ { 1461 if bins[i] != perBin { 1462 t.Fatalf("bin %d, got %d, want %d", i, bins[i], perBin) 1463 } 1464 } 1465 1466 // check that bin 0,1 remains balanced after pruning 1467 waitBalanced(t, kad, 0) 1468 waitBalanced(t, kad, 1) 1469 } 1470 1471 func TestBootnodeProtectedNodes(t *testing.T) { 1472 t.Parallel() 1473 1474 // create base and protected nodes addresses 1475 base := swarm.RandAddress(t) 1476 protected := make([]swarm.Address, 6) 1477 for i := 0; i < 6; i++ { 1478 addr := swarm.RandAddressAt(t, base, i) 1479 protected[i] = addr 1480 } 1481 1482 var ( 1483 conns int32 // how many connect calls were made to the p2p mock 1484 overSaturationPeers = 1 1485 _, kad, ab, _, signer = newTestKademliaWithAddr(t, base, &conns, nil, kademlia.Options{ 1486 BootnodeOverSaturationPeers: ptrInt(1), 1487 OverSaturationPeers: ptrInt(overSaturationPeers), 1488 SaturationPeers: ptrInt(1), 1489 LowWaterMark: ptrInt(0), 1490 BootnodeMode: true, 1491 StaticNodes: protected, 1492 ExcludeFunc: defaultExcludeFunc, 1493 }) 1494 ) 1495 1496 if err := kad.Start(context.Background()); err != nil { 1497 t.Fatal(err) 1498 } 1499 testutil.CleanupCloser(t, kad) 1500 1501 // Add maximum accepted number of peers up until bin 5 without problems 1502 for i := 0; i < 6; i++ { 1503 for j := 0; j < overSaturationPeers; j++ { 1504 // if error is not nil as specified, connectOne goes fatal 1505 connectOne(t, signer, kad, ab, protected[i], nil) 1506 } 1507 // see depth is limited to currently added peers proximity 1508 kDepth(t, kad, i) 1509 } 1510 1511 // see depth is 5 1512 kDepth(t, kad, 5) 1513 1514 for k := 0; k < 5; k++ { 1515 // further connections should succeed outside of depth 1516 addr := swarm.RandAddressAt(t, base, k) 1517 // if error is not as specified, connectOne goes fatal 1518 connectOne(t, signer, kad, ab, addr, nil) 1519 // see depth is still as expected 1520 kDepth(t, kad, 5) 1521 } 1522 // ensure protected node was not kicked out and we have more than oversaturation 1523 // amount 1524 sizes := binSizes(kad) 1525 for k := 0; k < 5; k++ { 1526 if sizes[k] != 2 { 1527 t.Fatalf("invalid bin size expected 2 found %d", sizes[k]) 1528 } 1529 } 1530 for k := 0; k < 5; k++ { 1531 // further connections should succeed outside of depth 1532 for l := 0; l < 3; l++ { 1533 addr := swarm.RandAddressAt(t, base, k) 1534 // if error is not as specified, connectOne goes fatal 1535 connectOne(t, signer, kad, ab, addr, nil) 1536 } 1537 // see depth is still as expected 1538 kDepth(t, kad, 5) 1539 } 1540 // ensure unprotected nodes are kicked out to make room for new peers and protected 1541 // nodes are still present 1542 sizes = binSizes(kad) 1543 for k := 0; k < 5; k++ { 1544 if sizes[k] != 2 { 1545 t.Fatalf("invalid bin size expected 2 found %d", sizes[k]) 1546 } 1547 } 1548 for _, pn := range protected { 1549 found := false 1550 _ = kad.EachConnectedPeer(func(addr swarm.Address, _ uint8) (bool, bool, error) { 1551 if addr.Equal(pn) { 1552 found = true 1553 return true, false, nil 1554 } 1555 return false, false, nil 1556 }, topology.Select{}) 1557 if !found { 1558 t.Fatalf("protected node %s not found in connected list", pn) 1559 } 1560 } 1561 } 1562 1563 func TestAnnounceBgBroadcast_FLAKY(t *testing.T) { 1564 t.Parallel() 1565 1566 var ( 1567 conns int32 1568 bgDone = make(chan struct{}) 1569 p1, p2 = swarm.RandAddress(t), swarm.RandAddress(t) 1570 disc = mock.NewDiscovery( 1571 mock.WithBroadcastPeers(func(ctx context.Context, p swarm.Address, _ ...swarm.Address) error { 1572 // For the broadcast back to connected peer return early 1573 if p.Equal(p2) { 1574 return nil 1575 } 1576 defer close(bgDone) 1577 <-ctx.Done() 1578 return ctx.Err() 1579 }), 1580 ) 1581 _, kad, ab, _, signer = newTestKademliaWithDiscovery(t, disc, &conns, nil, kademlia.Options{ 1582 ExcludeFunc: defaultExcludeFunc, 1583 }) 1584 ) 1585 1586 if err := kad.Start(context.Background()); err != nil { 1587 t.Fatal(err) 1588 } 1589 1590 // first add a peer from AddPeers, wait for the connection 1591 addOne(t, signer, kad, ab, p1) 1592 waitConn(t, &conns) 1593 1594 // Create a context to cancel and call Announce manually. On the cancellation of 1595 // this context ensure that the BroadcastPeers call in the background is unaffected 1596 ctx, cancel := context.WithCancel(context.Background()) 1597 1598 if err := kad.Announce(ctx, p2, true); err != nil { 1599 t.Fatal(err) 1600 } 1601 1602 // cancellation should not close background broadcast 1603 cancel() 1604 1605 select { 1606 case <-bgDone: 1607 t.Fatal("background broadcast exited") 1608 case <-time.After(time.Millisecond * 100): 1609 } 1610 1611 // All background broadcasts will be cancelled on Close. Ensure that the BroadcastPeers 1612 // call gets the context cancellation 1613 if err := kad.Close(); err != nil { 1614 t.Fatal(err) 1615 } 1616 1617 select { 1618 case <-bgDone: 1619 case <-time.After(time.Millisecond * 100): 1620 t.Fatal("background broadcast did not exit on close") 1621 } 1622 } 1623 1624 func TestAnnounceNeighborhoodToNeighbor(t *testing.T) { 1625 t.Parallel() 1626 1627 done := make(chan struct{}) 1628 1629 mtx := sync.Mutex{} 1630 1631 var neighborAddr swarm.Address 1632 const broadCastSize = 18 1633 1634 var ( 1635 conns int32 1636 disc = mock.NewDiscovery( 1637 mock.WithBroadcastPeers(func(ctx context.Context, p swarm.Address, addrs ...swarm.Address) error { 1638 mtx.Lock() 1639 defer mtx.Unlock() 1640 if p.Equal(neighborAddr) { 1641 if len(addrs) == broadCastSize { 1642 close(done) 1643 } else { 1644 t.Fatal("broadcasted size did not match neighborhood size", "got", len(addrs), "want", broadCastSize) 1645 } 1646 } 1647 return nil 1648 }), 1649 ) 1650 base, kad, ab, _, signer = newTestKademliaWithDiscovery(t, disc, &conns, nil, kademlia.Options{ 1651 ExcludeFunc: defaultExcludeFunc, 1652 OverSaturationPeers: ptrInt(4), 1653 SaturationPeers: ptrInt(4), 1654 }) 1655 ) 1656 1657 kad.SetStorageRadius(0) 1658 1659 neighborAddr = swarm.RandAddressAt(t, base, 2) 1660 1661 if err := kad.Start(context.Background()); err != nil { 1662 t.Fatal(err) 1663 } 1664 testutil.CleanupCloser(t, kad) 1665 1666 // add some peers 1667 for bin := 0; bin < 2; bin++ { 1668 for i := 0; i < 4; i++ { 1669 addr := swarm.RandAddressAt(t, base, bin) 1670 addOne(t, signer, kad, ab, addr) 1671 waitCounter(t, &conns, 1) 1672 } 1673 } 1674 1675 waitPeers(t, kad, 8) 1676 kDepth(t, kad, 1) 1677 1678 // add many more neighbors 1679 for i := 0; i < 10; i++ { 1680 addr := swarm.RandAddressAt(t, base, 2) 1681 addOne(t, signer, kad, ab, addr) 1682 waitCounter(t, &conns, 1) 1683 } 1684 1685 waitPeers(t, kad, broadCastSize) 1686 kDepth(t, kad, 2) 1687 1688 // add one neighbor to track how many peers are broadcasted to it 1689 addOne(t, signer, kad, ab, neighborAddr) 1690 1691 waitCounter(t, &conns, 1) 1692 waitPeers(t, kad, broadCastSize+1) 1693 kDepth(t, kad, 2) 1694 1695 select { 1696 case <-done: 1697 case <-time.After(time.Second): 1698 t.Fatal("broadcast did not fire for broadcastTo peer") 1699 } 1700 } 1701 1702 func TestIteratorOpts(t *testing.T) { 1703 t.Parallel() 1704 1705 var ( 1706 conns int32 // how many connect calls were made to the p2p mock 1707 base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{}) 1708 randBool = &boolgen{} 1709 ) 1710 1711 if err := kad.Start(context.Background()); err != nil { 1712 t.Fatal(err) 1713 } 1714 testutil.CleanupCloser(t, kad) 1715 1716 for i := 0; i < 6; i++ { 1717 for j := 0; j < 4; j++ { 1718 addr := swarm.RandAddressAt(t, base, i) 1719 // if error is not nil as specified, connectOne goes fatal 1720 connectOne(t, signer, kad, ab, addr, nil) 1721 } 1722 } 1723 1724 // randomly mark some nodes as reachable 1725 totalReachable := 0 1726 totalHealthy := 0 1727 reachable := make(map[string]struct{}) 1728 healthy := make(map[string]struct{}) 1729 1730 _ = kad.EachConnectedPeer(func(addr swarm.Address, _ uint8) (bool, bool, error) { 1731 if randBool.Bool() { 1732 kad.Reachable(addr, p2p.ReachabilityStatusPublic) 1733 reachable[addr.ByteString()] = struct{}{} 1734 totalReachable++ 1735 } 1736 if randBool.Bool() { 1737 healthy[addr.ByteString()] = struct{}{} 1738 totalHealthy++ 1739 kad.UpdatePeerHealth(addr, true, 0) 1740 } 1741 return false, false, nil 1742 }, topology.Select{}) 1743 1744 t.Run("EachConnectedPeer reachable", func(t *testing.T) { 1745 t.Parallel() 1746 1747 count := 0 1748 err := kad.EachConnectedPeer(func(addr swarm.Address, _ uint8) (bool, bool, error) { 1749 if _, exists := reachable[addr.ByteString()]; !exists { 1750 t.Fatal("iterator returned incorrect peer") 1751 } 1752 count++ 1753 return false, false, nil 1754 }, topology.Select{Reachable: true}) 1755 if err != nil { 1756 t.Fatal("iterator returned error") 1757 } 1758 if count != totalReachable { 1759 t.Fatal("iterator returned incorrect no of peers", count, "expected", totalReachable) 1760 } 1761 }) 1762 1763 t.Run("EachConnectedPeer healthy", func(t *testing.T) { 1764 t.Parallel() 1765 1766 count := 0 1767 err := kad.EachConnectedPeer(func(addr swarm.Address, _ uint8) (bool, bool, error) { 1768 if _, exists := healthy[addr.ByteString()]; !exists { 1769 t.Fatal("iterator returned incorrect peer") 1770 } 1771 count++ 1772 return false, false, nil 1773 }, topology.Select{Healthy: true}) 1774 if err != nil { 1775 t.Fatal("iterator returned error") 1776 } 1777 if count != totalHealthy { 1778 t.Fatal("iterator returned incorrect no of peers", count, "expected", totalHealthy) 1779 } 1780 }) 1781 1782 t.Run("EachConnectedPeer reachable healthy", func(t *testing.T) { 1783 t.Parallel() 1784 err := kad.EachConnectedPeer(func(addr swarm.Address, _ uint8) (bool, bool, error) { 1785 if _, exists := reachable[addr.ByteString()]; !exists { 1786 t.Fatal("iterator returned incorrect peer") 1787 } 1788 if _, exists := healthy[addr.ByteString()]; !exists { 1789 t.Fatal("iterator returned incorrect peer") 1790 } 1791 return false, false, nil 1792 }, topology.Select{Reachable: true, Healthy: true}) 1793 if err != nil { 1794 t.Fatal("iterator returned error") 1795 } 1796 }) 1797 1798 t.Run("EachConnectedPeerRev reachable", func(t *testing.T) { 1799 t.Parallel() 1800 1801 count := 0 1802 err := kad.EachConnectedPeerRev(func(addr swarm.Address, _ uint8) (bool, bool, error) { 1803 if _, exists := reachable[addr.ByteString()]; !exists { 1804 t.Fatal("iterator returned incorrect peer") 1805 } 1806 count++ 1807 return false, false, nil 1808 }, topology.Select{Reachable: true}) 1809 if err != nil { 1810 t.Fatal("iterator returned error") 1811 } 1812 if count != totalReachable { 1813 t.Fatal("iterator returned incorrect no of peers", count, "expected", totalReachable) 1814 } 1815 }) 1816 1817 t.Run("EachConnectedPeerRev healthy", func(t *testing.T) { 1818 t.Parallel() 1819 1820 count := 0 1821 err := kad.EachConnectedPeerRev(func(addr swarm.Address, _ uint8) (bool, bool, error) { 1822 if _, exists := healthy[addr.ByteString()]; !exists { 1823 t.Fatal("iterator returned incorrect peer") 1824 } 1825 count++ 1826 return false, false, nil 1827 }, topology.Select{Healthy: true}) 1828 if err != nil { 1829 t.Fatal("iterator returned error") 1830 } 1831 if count != totalHealthy { 1832 t.Fatal("iterator returned incorrect no of peers", count, "expected", totalHealthy) 1833 } 1834 }) 1835 1836 t.Run("EachConnectedPeerRev reachable healthy", func(t *testing.T) { 1837 t.Parallel() 1838 err := kad.EachConnectedPeerRev(func(addr swarm.Address, _ uint8) (bool, bool, error) { 1839 if _, exists := reachable[addr.ByteString()]; !exists { 1840 t.Fatal("iterator returned incorrect peer") 1841 } 1842 if _, exists := healthy[addr.ByteString()]; !exists { 1843 t.Fatal("iterator returned incorrect peer") 1844 } 1845 return false, false, nil 1846 }, topology.Select{Reachable: true, Healthy: true}) 1847 if err != nil { 1848 t.Fatal("iterator returned error") 1849 } 1850 }) 1851 } 1852 1853 type boolgen struct { 1854 cache int64 1855 remaining int 1856 } 1857 1858 func (b *boolgen) Bool() bool { 1859 if b.remaining == 0 { 1860 b.cache, b.remaining = rand.Int63(), 63 1861 } 1862 1863 result := b.cache&0x01 == 1 1864 b.cache >>= 1 1865 b.remaining-- 1866 1867 return result 1868 } 1869 1870 func mineBin(t *testing.T, base swarm.Address, bin, count int, isBalanced bool) []swarm.Address { 1871 t.Helper() 1872 1873 var rndAddrs = make([]swarm.Address, count) 1874 1875 if count < 8 && isBalanced { 1876 t.Fatal("peersCount must be greater than 8 for balanced bins") 1877 } 1878 1879 for i := 0; i < count; i++ { 1880 rndAddrs[i] = swarm.RandAddressAt(t, base, bin) 1881 } 1882 1883 if isBalanced { 1884 prefixes := kademlia.GenerateCommonBinPrefixes(base, kademlia.DefaultBitSuffixLength) 1885 for i := 0; i < int(math.Pow(2, float64(kademlia.DefaultBitSuffixLength))); i++ { 1886 rndAddrs[i] = prefixes[bin][i] 1887 } 1888 } else { 1889 for i := range rndAddrs { 1890 bytes := rndAddrs[i].Bytes() 1891 setBits(bytes, bin+1, 3, 0) // set 3 bits to '000' to mess with balance 1892 rndAddrs[i] = swarm.NewAddress(bytes) 1893 } 1894 } 1895 1896 return rndAddrs 1897 } 1898 1899 func setBits(data []byte, startBit, bitCount int, b int) { 1900 1901 index := startBit / 8 1902 bitPos := startBit % 8 1903 1904 for bitCount > 0 { 1905 1906 bitValue := b >> (bitCount - 1) 1907 1908 if bitValue == 1 { 1909 data[index] = data[index] | (1 << (7 - bitPos)) // set bit to 1 1910 } else { 1911 data[index] = data[index] & (^(1 << (7 - bitPos))) // set bit to 0 1912 } 1913 1914 bitCount-- 1915 bitPos++ 1916 1917 if bitPos == 8 { 1918 bitPos = 0 1919 index++ 1920 } 1921 } 1922 } 1923 1924 func binSizes(kad *kademlia.Kad) []int { 1925 bins := make([]int, swarm.MaxBins) 1926 1927 _ = kad.EachConnectedPeer(func(a swarm.Address, u uint8) (stop bool, jumpToNext bool, err error) { 1928 bins[u]++ 1929 return false, false, nil 1930 }, topology.Select{}) 1931 1932 return bins 1933 } 1934 1935 func newTestKademliaWithAddrDiscovery( 1936 t *testing.T, 1937 base swarm.Address, 1938 disc *mock.Discovery, 1939 connCounter, failedConnCounter *int32, 1940 kadOpts kademlia.Options, 1941 ) (swarm.Address, *kademlia.Kad, addressbook.Interface, *mock.Discovery, beeCrypto.Signer) { 1942 t.Helper() 1943 1944 var ( 1945 pk, _ = beeCrypto.GenerateSecp256k1Key() // random private key 1946 signer = beeCrypto.NewDefaultSigner(pk) // signer 1947 ssMock = mockstate.NewStateStore() // state store 1948 ab = addressbook.New(ssMock) // address book 1949 p2p = p2pMock(t, ab, signer, connCounter, failedConnCounter) // p2p mock 1950 logger = log.Noop // logger 1951 ) 1952 kad, err := kademlia.New(base, ab, disc, p2p, logger, kadOpts) 1953 if err != nil { 1954 t.Fatal(err) 1955 } 1956 1957 p2p.SetPickyNotifier(kad) 1958 1959 return base, kad, ab, disc, signer 1960 } 1961 1962 func newTestKademlia(t *testing.T, connCounter, failedConnCounter *int32, kadOpts kademlia.Options) (swarm.Address, *kademlia.Kad, addressbook.Interface, *mock.Discovery, beeCrypto.Signer) { 1963 t.Helper() 1964 1965 base := swarm.RandAddress(t) 1966 disc := mock.NewDiscovery() // mock discovery protocols 1967 return newTestKademliaWithAddrDiscovery(t, base, disc, connCounter, failedConnCounter, kadOpts) 1968 } 1969 1970 func newTestKademliaWithAddr(t *testing.T, base swarm.Address, connCounter, failedConnCounter *int32, kadOpts kademlia.Options) (swarm.Address, *kademlia.Kad, addressbook.Interface, *mock.Discovery, beeCrypto.Signer) { 1971 t.Helper() 1972 1973 disc := mock.NewDiscovery() // mock discovery protocol 1974 return newTestKademliaWithAddrDiscovery(t, base, disc, connCounter, failedConnCounter, kadOpts) 1975 } 1976 1977 func newTestKademliaWithDiscovery( 1978 t *testing.T, 1979 disc *mock.Discovery, 1980 connCounter, failedConnCounter *int32, 1981 kadOpts kademlia.Options, 1982 ) (swarm.Address, *kademlia.Kad, addressbook.Interface, *mock.Discovery, beeCrypto.Signer) { 1983 t.Helper() 1984 1985 base := swarm.RandAddress(t) 1986 return newTestKademliaWithAddrDiscovery(t, base, disc, connCounter, failedConnCounter, kadOpts) 1987 } 1988 1989 func p2pMock(t *testing.T, ab addressbook.Interface, signer beeCrypto.Signer, counter, failedCounter *int32) p2p.Service { 1990 t.Helper() 1991 1992 p2ps := p2pmock.New( 1993 p2pmock.WithConnectFunc(func(ctx context.Context, addr ma.Multiaddr) (*bzz.Address, error) { 1994 if addr.Equal(nonConnectableAddress) { 1995 _ = atomic.AddInt32(failedCounter, 1) 1996 return nil, errors.New("non reachable node") 1997 } 1998 if counter != nil { 1999 _ = atomic.AddInt32(counter, 1) 2000 } 2001 2002 addresses, err := ab.Addresses() 2003 if err != nil { 2004 return nil, errors.New("could not fetch addresbook addresses") 2005 } 2006 2007 for _, a := range addresses { 2008 if a.Underlay.Equal(addr) { 2009 return &a, nil 2010 } 2011 } 2012 2013 address := swarm.RandAddress(t) 2014 bzzAddr, err := bzz.NewAddress(signer, addr, address, 0, nil) 2015 if err != nil { 2016 return nil, err 2017 } 2018 2019 if err := ab.Put(address, *bzzAddr); err != nil { 2020 return nil, err 2021 } 2022 2023 return bzzAddr, nil 2024 }), 2025 p2pmock.WithDisconnectFunc(func(swarm.Address, string) error { 2026 if counter != nil { 2027 _ = atomic.AddInt32(counter, -1) 2028 } 2029 return nil 2030 }), 2031 ) 2032 2033 return p2ps 2034 } 2035 2036 func removeOne(k *kademlia.Kad, peer swarm.Address) { 2037 k.Disconnected(p2p.Peer{Address: peer}) 2038 } 2039 2040 const underlayBase = "/ip4/127.0.0.1/tcp/1634/dns/" 2041 2042 func connectOne(t *testing.T, signer beeCrypto.Signer, k *kademlia.Kad, ab addressbook.Putter, peer swarm.Address, expErr error) { 2043 t.Helper() 2044 multiaddr, err := ma.NewMultiaddr(underlayBase + peer.String()) 2045 if err != nil { 2046 t.Fatal(err) 2047 } 2048 2049 bzzAddr, err := bzz.NewAddress(signer, multiaddr, peer, 0, nil) 2050 if err != nil { 2051 t.Fatal(err) 2052 } 2053 if err := ab.Put(peer, *bzzAddr); err != nil { 2054 t.Fatal(err) 2055 } 2056 err = k.Connected(context.Background(), p2p.Peer{Address: peer}, false) 2057 2058 if !errors.Is(err, expErr) { 2059 t.Fatalf("expected error %v , got %v", expErr, err) 2060 } 2061 } 2062 2063 func addOne(t *testing.T, signer beeCrypto.Signer, k *kademlia.Kad, ab addressbook.Putter, peer swarm.Address) { 2064 t.Helper() 2065 multiaddr, err := ma.NewMultiaddr(underlayBase + peer.String()) 2066 if err != nil { 2067 t.Fatal(err) 2068 } 2069 bzzAddr, err := bzz.NewAddress(signer, multiaddr, peer, 0, nil) 2070 if err != nil { 2071 t.Fatal(err) 2072 } 2073 if err := ab.Put(peer, *bzzAddr); err != nil { 2074 t.Fatal(err) 2075 } 2076 k.AddPeers(peer) 2077 } 2078 2079 func add(t *testing.T, signer beeCrypto.Signer, k *kademlia.Kad, ab addressbook.Putter, peers []swarm.Address, offset, number int) { 2080 t.Helper() 2081 for i := offset; i < offset+number; i++ { 2082 addOne(t, signer, k, ab, peers[i]) 2083 } 2084 } 2085 2086 func kDepth(t *testing.T, k *kademlia.Kad, d int) { 2087 t.Helper() 2088 2089 var depth int 2090 err := spinlock.Wait(spinLockWaitTime, func() bool { 2091 depth = int(k.ConnectionDepth()) 2092 return depth == d 2093 }) 2094 if err != nil { 2095 t.Fatalf("timed out waiting for depth. want %d got %d", d, depth) 2096 } 2097 } 2098 2099 func kRadius(t *testing.T, k *kademlia.Kad, d int) { 2100 t.Helper() 2101 2102 var radius int 2103 err := spinlock.Wait(spinLockWaitTime, func() bool { 2104 radius = int(k.StorageRadius()) 2105 return radius == d 2106 }) 2107 if err != nil { 2108 t.Fatalf("timed out waiting for radius. want %d got %d", d, radius) 2109 } 2110 } 2111 2112 func waitConn(t *testing.T, conns *int32) { 2113 t.Helper() 2114 waitCounter(t, conns, 1) 2115 } 2116 2117 // waits for counter for some time. resets the pointer value 2118 // if the correct number have been reached. 2119 func waitCounter(t *testing.T, conns *int32, exp int32) { 2120 t.Helper() 2121 var got int32 2122 2123 err := spinlock.Wait(spinLockWaitTime, func() bool { 2124 if got = atomic.LoadInt32(conns); got == exp { 2125 atomic.StoreInt32(conns, 0) 2126 return true 2127 } 2128 return false 2129 }) 2130 if err != nil { 2131 t.Fatalf("timed out waiting for counter to reach expected value. got %d want %d", got, exp) 2132 } 2133 } 2134 2135 func waitPeers(t *testing.T, k *kademlia.Kad, peers int) { 2136 t.Helper() 2137 2138 err := spinlock.Wait(spinLockWaitTime, func() bool { 2139 i := 0 2140 _ = k.EachConnectedPeer(func(_ swarm.Address, _ uint8) (bool, bool, error) { 2141 i++ 2142 return false, false, nil 2143 }, topology.Select{}) 2144 return i == peers 2145 }) 2146 if err != nil { 2147 t.Fatal("timed out waiting for peers") 2148 } 2149 } 2150 2151 // wait for discovery BroadcastPeers to happen 2152 func waitBcast(t *testing.T, d *mock.Discovery, pivot swarm.Address, addrs ...swarm.Address) { 2153 t.Helper() 2154 2155 err := spinlock.Wait(spinLockWaitTime, func() bool { 2156 if d.Broadcasts() > 0 { 2157 recs, ok := d.AddresseeRecords(pivot) 2158 if !ok { 2159 return false 2160 } 2161 2162 oks := 0 2163 for _, a := range addrs { 2164 if !swarm.ContainsAddress(recs, a) { 2165 t.Fatalf("address %s not found in discovery records: %s", a, addrs) 2166 } 2167 oks++ 2168 } 2169 2170 return oks == len(addrs) 2171 } 2172 return false 2173 }) 2174 if err != nil { 2175 t.Fatalf("timed out waiting for broadcast to happen") 2176 } 2177 } 2178 2179 // waitBalanced waits for kademlia to be balanced for specified bin. 2180 func waitBalanced(t *testing.T, k *kademlia.Kad, bin uint8) { 2181 t.Helper() 2182 2183 err := spinlock.Wait(spinLockWaitTime, func() bool { 2184 return k.IsBalanced(bin) 2185 }) 2186 if err != nil { 2187 t.Fatalf("timed out waiting to be balanced for bin: %d", int(bin)) 2188 } 2189 } 2190 2191 func ptrInt(v int) *int { 2192 return &v 2193 } 2194 2195 func ptrDuration(v time.Duration) *time.Duration { 2196 return &v 2197 }