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  }