From 7710bb738ad10bfc6b43d80a65f45dad79c4b76c Mon Sep 17 00:00:00 2001 From: istae <14264581+esadakar@users.noreply.github.com> Date: Tue, 21 Sep 2021 19:32:10 +0300 Subject: [PATCH 1/3] feat: bin saturation based on exponential decay --- pkg/topology/kademlia/export_test.go | 12 +- pkg/topology/kademlia/kademlia.go | 170 +++++++++++++------------ pkg/topology/kademlia/kademlia_test.go | 73 +++++------ 3 files changed, 124 insertions(+), 131 deletions(-) diff --git a/pkg/topology/kademlia/export_test.go b/pkg/topology/kademlia/export_test.go index e0b48a58c96..bad343a05e5 100644 --- a/pkg/topology/kademlia/export_test.go +++ b/pkg/topology/kademlia/export_test.go @@ -5,13 +5,11 @@ package kademlia var ( - TimeToRetry = &timeToRetry - QuickSaturationPeers = &quickSaturationPeers - SaturationPeers = &saturationPeers - OverSaturationPeers = &overSaturationPeers - BootnodeOverSaturationPeers = &bootNodeOverSaturationPeers - LowWaterMark = &nnLowWatermark - PruneOversaturatedBinsFunc = func(k *Kad) func(uint8) { + TimeToRetry = &timeToRetry + QuickSaturationPeers = &quickSaturationPeers + SaturationPeers = &saturationPeers + LowWaterMark = &nnLowWatermark + PruneOversaturatedBinsFunc = func(k *Kad) func(uint8) { return k.pruneOversaturatedBins } GenerateCommonBinPrefixes = generateCommonBinPrefixes diff --git a/pkg/topology/kademlia/kademlia.go b/pkg/topology/kademlia/kademlia.go index fa0332e026c..89cd59eda8b 100644 --- a/pkg/topology/kademlia/kademlia.go +++ b/pkg/topology/kademlia/kademlia.go @@ -10,6 +10,7 @@ import ( "encoding/json" "errors" "fmt" + "math" "math/big" "net" "sync" @@ -47,15 +48,13 @@ const ( ) var ( - nnLowWatermark = 2 // the number of peers in consecutive deepest bins that constitute as nearest neighbours - quickSaturationPeers = 4 - saturationPeers = 8 - overSaturationPeers = 20 - bootNodeOverSaturationPeers = 20 - shortRetry = 30 * time.Second - timeToRetry = 2 * shortRetry - broadcastBinSize = 4 - peerPingPollTime = 10 * time.Second // how often to ping a peer + nnLowWatermark = 2 // the number of peers in consecutive deepest bins that constitute as nearest neighbours + quickSaturationPeers = 4 + saturationPeers = 8 + shortRetry = 30 * time.Second + timeToRetry = 2 * shortRetry + broadcastBinSize = 4 + peerPingPollTime = 10 * time.Second // how often to ping a peer ) var ( @@ -71,56 +70,59 @@ type ( pruneFunc func(depth uint8) staticPeerFunc func(peer swarm.Address) bool peerFilterFunc func(peer swarm.Address) bool + overSaturationCalc func(depth uint8) int ) var noopSanctionedPeerFn = func(_ swarm.Address) bool { return false } // Options for injecting services to Kademlia. type Options struct { - SaturationFunc binSaturationFunc - Bootnodes []ma.Multiaddr - BootnodeMode bool - BitSuffixLength int - PruneFunc pruneFunc - StaticNodes []swarm.Address - ReachabilityFunc peerFilterFunc + SaturationFunc binSaturationFunc + Bootnodes []ma.Multiaddr + BootnodeMode bool + BitSuffixLength int + PruneFunc pruneFunc + StaticNodes []swarm.Address + ReachabilityFunc peerFilterFunc + OverSaturationCalc overSaturationCalc } // Kad is the Swarm forwarding kademlia implementation. type Kad struct { - base swarm.Address // this node's overlay address - discovery discovery.Driver // the discovery driver - addressBook addressbook.Interface // address book to get underlays - p2p p2p.Service // p2p service to connect to nodes with - saturationFunc binSaturationFunc // pluggable saturation function - bitSuffixLength int // additional depth of common prefix for bin - commonBinPrefixes [][]swarm.Address // list of address prefixes for each bin - connectedPeers *pslice.PSlice // a slice of peers sorted and indexed by po, indexes kept in `bins` - knownPeers *pslice.PSlice // both are po aware slice of addresses - bootnodes []ma.Multiaddr - depth uint8 // current neighborhood depth - radius uint8 // storage area of responsibility - depthMu sync.RWMutex // protect depth changes - manageC chan struct{} // trigger the manage forever loop to connect to new peers - peerSig []chan struct{} - peerSigMtx sync.Mutex - logger logging.Logger // logger - bootnode bool // indicates whether the node is working in bootnode mode - collector *im.Collector - quit chan struct{} // quit channel - halt chan struct{} // halt channel - done chan struct{} // signal that `manage` has quit - wg sync.WaitGroup - waitNext *waitnext.WaitNext - metrics metrics - pruneFunc pruneFunc // pluggable prune function - pinger pingpong.Interface - staticPeer staticPeerFunc - bgBroadcastCtx context.Context - bgBroadcastCancel context.CancelFunc - blocker *blocker.Blocker - reachability p2p.ReachabilityStatus - peerFilter peerFilterFunc + base swarm.Address // this node's overlay address + discovery discovery.Driver // the discovery driver + addressBook addressbook.Interface // address book to get underlays + p2p p2p.Service // p2p service to connect to nodes with + saturationFunc binSaturationFunc // pluggable saturation function + bitSuffixLength int // additional depth of common prefix for bin + commonBinPrefixes [][]swarm.Address // list of address prefixes for each bin + connectedPeers *pslice.PSlice // a slice of peers sorted and indexed by po, indexes kept in `bins` + knownPeers *pslice.PSlice // both are po aware slice of addresses + bootnodes []ma.Multiaddr + depth uint8 // current neighborhood depth + radius uint8 // storage area of responsibility + depthMu sync.RWMutex // protect depth changes + manageC chan struct{} // trigger the manage forever loop to connect to new peers + peerSig []chan struct{} + peerSigMtx sync.Mutex + logger logging.Logger // logger + bootnode bool // indicates whether the node is working in bootnode mode + collector *im.Collector + quit chan struct{} // quit channel + halt chan struct{} // halt channel + done chan struct{} // signal that `manage` has quit + wg sync.WaitGroup + waitNext *waitnext.WaitNext + metrics metrics + pruneFunc pruneFunc // pluggable prune function + pinger pingpong.Interface + staticPeer staticPeerFunc + bgBroadcastCtx context.Context + bgBroadcastCancel context.CancelFunc + blocker *blocker.Blocker + reachability p2p.ReachabilityStatus + peerFilter peerFilterFunc + overSaturationCalc overSaturationCalc } // New returns a new Kademlia. @@ -134,17 +136,22 @@ func New( logger logging.Logger, o Options, ) (*Kad, error) { - if o.SaturationFunc == nil { - os := overSaturationPeers - if o.BootnodeMode { - os = bootNodeOverSaturationPeers + + if o.OverSaturationCalc == nil { + o.OverSaturationCalc = func(bin uint8) int { + return int(math.Exp(-float64(bin)/8.0)) * 50 } - o.SaturationFunc = binSaturated(os, isStaticPeer(o.StaticNodes)) } + + o.SaturationFunc = binSaturated(o.OverSaturationCalc, isStaticPeer(o.StaticNodes)) + if o.BitSuffixLength == 0 { o.BitSuffixLength = defaultBitSuffixLength } + for i := 0; i < int(swarm.MaxBins); i++ { + } + start := time.Now() imc, err := im.NewCollector(metricsDB) if err != nil { @@ -153,29 +160,30 @@ func New( logger.Debugf("kademlia: NewCollector(...) took %v", time.Since(start)) k := &Kad{ - base: base, - discovery: discovery, - addressBook: addressbook, - p2p: p2pSvc, - saturationFunc: o.SaturationFunc, - bitSuffixLength: o.BitSuffixLength, - commonBinPrefixes: make([][]swarm.Address, int(swarm.MaxBins)), - connectedPeers: pslice.New(int(swarm.MaxBins), base), - knownPeers: pslice.New(int(swarm.MaxBins), base), - bootnodes: o.Bootnodes, - manageC: make(chan struct{}, 1), - waitNext: waitnext.New(), - logger: logger, - bootnode: o.BootnodeMode, - collector: imc, - quit: make(chan struct{}), - halt: make(chan struct{}), - done: make(chan struct{}), - metrics: newMetrics(), - pruneFunc: o.PruneFunc, - pinger: pinger, - staticPeer: isStaticPeer(o.StaticNodes), - peerFilter: o.ReachabilityFunc, + base: base, + discovery: discovery, + addressBook: addressbook, + p2p: p2pSvc, + saturationFunc: o.SaturationFunc, + bitSuffixLength: o.BitSuffixLength, + commonBinPrefixes: make([][]swarm.Address, int(swarm.MaxBins)), + connectedPeers: pslice.New(int(swarm.MaxBins), base), + knownPeers: pslice.New(int(swarm.MaxBins), base), + bootnodes: o.Bootnodes, + manageC: make(chan struct{}, 1), + waitNext: waitnext.New(), + logger: logger, + bootnode: o.BootnodeMode, + collector: imc, + quit: make(chan struct{}), + halt: make(chan struct{}), + done: make(chan struct{}), + metrics: newMetrics(), + pruneFunc: o.PruneFunc, + pinger: pinger, + staticPeer: isStaticPeer(o.StaticNodes), + peerFilter: o.ReachabilityFunc, + overSaturationCalc: o.OverSaturationCalc, } blocklistCallback := func(a swarm.Address) { @@ -636,13 +644,13 @@ func (k *Kad) pruneOversaturatedBins(depth uint8) { } binPeersCount := k.connectedPeers.BinSize(uint8(i)) - if binPeersCount < overSaturationPeers { + if binPeersCount < k.overSaturationCalc(uint8(i)) { continue } binPeers := k.connectedPeers.BinPeers(uint8(i)) - peersToRemove := binPeersCount - overSaturationPeers + peersToRemove := binPeersCount - k.overSaturationCalc(uint8(i)) for j := 0; peersToRemove > 0 && j < len(k.commonBinPrefixes[i]); j++ { @@ -802,7 +810,7 @@ func (k *Kad) connectBootNodes(ctx context.Context) { // binSaturated indicates whether a certain bin is saturated or not. // when a bin is not saturated it means we would like to proactively // initiate connections to other peers in the bin. -func binSaturated(oversaturationAmount int, staticNode staticPeerFunc) binSaturationFunc { +func binSaturated(f overSaturationCalc, staticNode staticPeerFunc) binSaturationFunc { return func(bin uint8, peers, connected *pslice.PSlice, filter peerFilterFunc) (bool, bool) { potentialDepth := recalcDepth(peers, swarm.MaxPO, filter) @@ -826,7 +834,7 @@ func binSaturated(oversaturationAmount int, staticNode staticPeerFunc) binSatura return false, false, nil }) - return size >= saturationPeers, size >= oversaturationAmount + return size >= saturationPeers, size >= f(bin) } } diff --git a/pkg/topology/kademlia/kademlia_test.go b/pkg/topology/kademlia/kademlia_test.go index 7b7c88af305..2cecdc135e9 100644 --- a/pkg/topology/kademlia/kademlia_test.go +++ b/pkg/topology/kademlia/kademlia_test.go @@ -56,7 +56,8 @@ func TestNeighborhoodDepth(t *testing.T) { var ( conns int32 // how many connect calls were made to the p2p mock base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ - ReachabilityFunc: func(_ swarm.Address) bool { return false }, + ReachabilityFunc: func(_ swarm.Address) bool { return false }, + OverSaturationCalc: func(uint8) int { return 20 }, }) ) @@ -606,15 +607,12 @@ func TestBinSaturation(t *testing.T) { } func TestOversaturation(t *testing.T) { - defer func(p int) { - *kademlia.OverSaturationPeers = p - }(*kademlia.OverSaturationPeers) - *kademlia.OverSaturationPeers = 8 var ( conns int32 // how many connect calls were made to the p2p mock base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ - ReachabilityFunc: func(_ swarm.Address) bool { return false }, + ReachabilityFunc: func(_ swarm.Address) bool { return false }, + OverSaturationCalc: func(uint8) int { return 8 }, }) ) kad.SetRadius(swarm.MaxPO) // don't use radius for checks @@ -626,7 +624,7 @@ func TestOversaturation(t *testing.T) { // Add maximum accepted number of peers up until bin 5 without problems for i := 0; i < 6; i++ { - for j := 0; j < *kademlia.OverSaturationPeers; j++ { + for j := 0; j < 8; j++ { addr := test.RandomAddressAt(base, i) // if error is not nil as specified, connectOne goes fatal connectOne(t, signer, kad, ab, addr, nil) @@ -664,10 +662,6 @@ func TestOversaturation(t *testing.T) { } func TestOversaturationBootnode(t *testing.T) { - defer func(p int) { - *kademlia.OverSaturationPeers = p - }(*kademlia.OverSaturationPeers) - *kademlia.OverSaturationPeers = 4 defer func(p int) { *kademlia.SaturationPeers = p @@ -677,8 +671,9 @@ func TestOversaturationBootnode(t *testing.T) { var ( conns int32 // how many connect calls were made to the p2p mock base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ - BootnodeMode: true, - ReachabilityFunc: func(_ swarm.Address) bool { return false }, + BootnodeMode: true, + ReachabilityFunc: func(_ swarm.Address) bool { return false }, + OverSaturationCalc: func(uint8) int { return 4 }, }) ) kad.SetRadius(swarm.MaxPO) // don't use radius for checks @@ -690,7 +685,7 @@ func TestOversaturationBootnode(t *testing.T) { // Add maximum accepted number of peers up until bin 5 without problems for i := 0; i < 6; i++ { - for j := 0; j < *kademlia.OverSaturationPeers; j++ { + for j := 0; j < 4; j++ { addr := test.RandomAddressAt(base, i) // if error is not nil as specified, connectOne goes fatal connectOne(t, signer, kad, ab, addr, nil) @@ -728,10 +723,6 @@ func TestOversaturationBootnode(t *testing.T) { } func TestBootnodeMaxConnections(t *testing.T) { - defer func(p int) { - *kademlia.BootnodeOverSaturationPeers = p - }(*kademlia.BootnodeOverSaturationPeers) - *kademlia.BootnodeOverSaturationPeers = 4 defer func(p int) { *kademlia.SaturationPeers = p @@ -741,8 +732,9 @@ func TestBootnodeMaxConnections(t *testing.T) { var ( conns int32 // how many connect calls were made to the p2p mock base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ - BootnodeMode: true, - ReachabilityFunc: func(_ swarm.Address) bool { return false }, + BootnodeMode: true, + ReachabilityFunc: func(_ swarm.Address) bool { return false }, + OverSaturationCalc: func(uint8) int { return 4 }, }) ) kad.SetRadius(swarm.MaxPO) // don't use radius for checks @@ -754,7 +746,7 @@ func TestBootnodeMaxConnections(t *testing.T) { // Add maximum accepted number of peers up until bin 5 without problems for i := 0; i < 6; i++ { - for j := 0; j < *kademlia.BootnodeOverSaturationPeers; j++ { + for j := 0; j < 4; j++ { addr := test.RandomAddressAt(base, i) // if error is not nil as specified, connectOne goes fatal connectOne(t, signer, kad, ab, addr, nil) @@ -1376,11 +1368,6 @@ func TestOutofDepthPrune(t *testing.T) { }(*kademlia.SaturationPeers) *kademlia.SaturationPeers = 4 - defer func(p int) { - *kademlia.OverSaturationPeers = p - }(*kademlia.OverSaturationPeers) - *kademlia.OverSaturationPeers = 8 - var ( conns, failedConns int32 // how many connect calls were made to the p2p mock @@ -1394,8 +1381,9 @@ func TestOutofDepthPrune(t *testing.T) { } base, kad, ab, _, signer = newTestKademlia(t, &conns, &failedConns, kademlia.Options{ - PruneFunc: pruneFunc, - ReachabilityFunc: func(_ swarm.Address) bool { return false }, + PruneFunc: pruneFunc, + ReachabilityFunc: func(_ swarm.Address) bool { return false }, + OverSaturationCalc: func(uint8) int { return 8 }, }) ) @@ -1440,8 +1428,8 @@ func TestOutofDepthPrune(t *testing.T) { // check that no pruning has happened bins := binSizes(kad) for i := 0; i < 6; i++ { - if bins[i] <= *kademlia.OverSaturationPeers { - t.Fatalf("bin %d, got %d, want more than %d", i, bins[i], *kademlia.OverSaturationPeers) + if bins[i] <= 8 { + t.Fatalf("bin %d, got %d, want more than %d", i, bins[i], 8) } } @@ -1463,8 +1451,8 @@ func TestOutofDepthPrune(t *testing.T) { // check bins have been pruned bins = binSizes(kad) for i := uint8(0); i < 5; i++ { - if bins[i] != *kademlia.OverSaturationPeers { - t.Fatalf("bin %d, got %d, want %d", i, bins[i], *kademlia.OverSaturationPeers) + if bins[i] != 8 { + t.Fatalf("bin %d, got %d, want %d", i, bins[i], 8) } } @@ -1526,13 +1514,11 @@ func TestLatency(t *testing.T) { } func TestBootnodeProtectedNodes(t *testing.T) { - defer func(a, b, c, d int) { - *kademlia.BootnodeOverSaturationPeers = a - *kademlia.SaturationPeers = b - *kademlia.LowWaterMark = c - *kademlia.QuickSaturationPeers = d - }(*kademlia.BootnodeOverSaturationPeers, *kademlia.SaturationPeers, *kademlia.LowWaterMark, *kademlia.QuickSaturationPeers) - *kademlia.BootnodeOverSaturationPeers = 1 + defer func(a, b, c int) { + *kademlia.SaturationPeers = a + *kademlia.LowWaterMark = b + *kademlia.QuickSaturationPeers = c + }(*kademlia.SaturationPeers, *kademlia.LowWaterMark, *kademlia.QuickSaturationPeers) *kademlia.SaturationPeers = 1 *kademlia.LowWaterMark = 0 *kademlia.QuickSaturationPeers = 1 @@ -1548,16 +1534,17 @@ func TestBootnodeProtectedNodes(t *testing.T) { var ( conns int32 // how many connect calls were made to the p2p mock _, kad, ab, _, signer = newTestKademliaWithAddr(t, base, &conns, nil, kademlia.Options{ - BootnodeMode: true, - StaticNodes: protected, - ReachabilityFunc: func(_ swarm.Address) bool { return false }, + BootnodeMode: true, + StaticNodes: protected, + ReachabilityFunc: func(_ swarm.Address) bool { return false }, + OverSaturationCalc: func(uint8) int { return 1 }, }) ) kad.SetRadius(swarm.MaxPO) // don't use radius for checks // Add maximum accepted number of peers up until bin 5 without problems for i := 0; i < 6; i++ { - for j := 0; j < *kademlia.OverSaturationPeers; j++ { + for j := 0; j < 20; j++ { // if error is not nil as specified, connectOne goes fatal connectOne(t, signer, kad, ab, protected[i], nil) } From bd6a65e8aa7a03330bf2815d6f85a55048567a36 Mon Sep 17 00:00:00 2001 From: istae <14264581+esadakar@users.noreply.github.com> Date: Tue, 21 Sep 2021 19:50:21 +0300 Subject: [PATCH 2/3] chore: unit test --- pkg/topology/kademlia/export_test.go | 1 + pkg/topology/kademlia/kademlia.go | 10 +++++++--- pkg/topology/kademlia/kademlia_test.go | 9 +++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/pkg/topology/kademlia/export_test.go b/pkg/topology/kademlia/export_test.go index bad343a05e5..0ffba977e21 100644 --- a/pkg/topology/kademlia/export_test.go +++ b/pkg/topology/kademlia/export_test.go @@ -14,6 +14,7 @@ var ( } GenerateCommonBinPrefixes = generateCommonBinPrefixes PeerPingPollTime = &peerPingPollTime + DefaultOverSaturationCalc = defaultOverSaturationCalc ) type PeerFilterFunc = peerFilterFunc diff --git a/pkg/topology/kademlia/kademlia.go b/pkg/topology/kademlia/kademlia.go index 89cd59eda8b..7bd5d2260a9 100644 --- a/pkg/topology/kademlia/kademlia.go +++ b/pkg/topology/kademlia/kademlia.go @@ -138,9 +138,7 @@ func New( ) (*Kad, error) { if o.OverSaturationCalc == nil { - o.OverSaturationCalc = func(bin uint8) int { - return int(math.Exp(-float64(bin)/8.0)) * 50 - } + o.OverSaturationCalc = defaultOverSaturationCalc } o.SaturationFunc = binSaturated(o.OverSaturationCalc, isStaticPeer(o.StaticNodes)) @@ -211,6 +209,12 @@ func New( return k, nil } +// produces oversaturation values using an exponential decay formula, sequence is as follows: +// bin 0 -> 50, 44, 39, 34, 30, 27 +func defaultOverSaturationCalc(bin uint8) int { + return int(math.Round(50 * math.Exp(-float64(bin)/8.0))) +} + type peerConnInfo struct { po uint8 addr swarm.Address diff --git a/pkg/topology/kademlia/kademlia_test.go b/pkg/topology/kademlia/kademlia_test.go index 2cecdc135e9..102289ba9fe 100644 --- a/pkg/topology/kademlia/kademlia_test.go +++ b/pkg/topology/kademlia/kademlia_test.go @@ -1744,6 +1744,15 @@ func (b *boolgen) Bool() bool { return result } +func TestDefaultOverSaturationCalc(t *testing.T) { + nums := []int{50, 44, 39, 34, 30, 27, 24, 21, 18, 16, 14, 13, 11, 10} + for i, n := range nums { + if got := kademlia.DefaultOverSaturationCalc(uint8(i)); got != n { + t.Fatalf("want %d, got %d", n, got) + } + } +} + func mineBin(t *testing.T, base swarm.Address, bin, count int, isBalanced bool) []swarm.Address { var rndAddrs = make([]swarm.Address, count) From ef989848a3d3d38eac9c16b78981451b9af29ff6 Mon Sep 17 00:00:00 2001 From: istae <14264581+esadakar@users.noreply.github.com> Date: Wed, 24 Nov 2021 19:39:18 +0300 Subject: [PATCH 3/3] fix: rebase --- pkg/topology/kademlia/kademlia.go | 9 ++++----- pkg/topology/kademlia/kademlia_test.go | 22 ++++++++++++---------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/pkg/topology/kademlia/kademlia.go b/pkg/topology/kademlia/kademlia.go index 7bd5d2260a9..d746cbd47e8 100644 --- a/pkg/topology/kademlia/kademlia.go +++ b/pkg/topology/kademlia/kademlia.go @@ -55,6 +55,7 @@ var ( timeToRetry = 2 * shortRetry broadcastBinSize = 4 peerPingPollTime = 10 * time.Second // how often to ping a peer + maxFirstbin = float64(50) ) var ( @@ -137,6 +138,8 @@ func New( o Options, ) (*Kad, error) { + start := time.Now() + if o.OverSaturationCalc == nil { o.OverSaturationCalc = defaultOverSaturationCalc } @@ -147,10 +150,6 @@ func New( o.BitSuffixLength = defaultBitSuffixLength } - for i := 0; i < int(swarm.MaxBins); i++ { - } - - start := time.Now() imc, err := im.NewCollector(metricsDB) if err != nil { return nil, err @@ -212,7 +211,7 @@ func New( // produces oversaturation values using an exponential decay formula, sequence is as follows: // bin 0 -> 50, 44, 39, 34, 30, 27 func defaultOverSaturationCalc(bin uint8) int { - return int(math.Round(50 * math.Exp(-float64(bin)/8.0))) + return int(math.Round(maxFirstbin * math.Exp(-float64(bin)/8.0))) } type peerConnInfo struct { diff --git a/pkg/topology/kademlia/kademlia_test.go b/pkg/topology/kademlia/kademlia_test.go index 102289ba9fe..dec4334e996 100644 --- a/pkg/topology/kademlia/kademlia_test.go +++ b/pkg/topology/kademlia/kademlia_test.go @@ -213,7 +213,9 @@ func TestNeighborhoodDepthWithReachability(t *testing.T) { var ( conns int32 // how many connect calls were made to the p2p mock - base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{}) + base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ + OverSaturationCalc: func(uint8) int { return 20 }, + }) ) kad.SetRadius(swarm.MaxPO) // initial tests do not check for radius @@ -1726,6 +1728,15 @@ func TestIteratorOpts(t *testing.T) { }) } +func TestDefaultOverSaturationCalc(t *testing.T) { + nums := []int{50, 44, 39, 34, 30, 27, 24, 21, 18, 16, 14, 13, 11, 10} + for i, n := range nums { + if got := kademlia.DefaultOverSaturationCalc(uint8(i)); got != n { + t.Fatalf("want %d, got %d", n, got) + } + } +} + type boolgen struct { src rand.Source cache int64 @@ -1744,15 +1755,6 @@ func (b *boolgen) Bool() bool { return result } -func TestDefaultOverSaturationCalc(t *testing.T) { - nums := []int{50, 44, 39, 34, 30, 27, 24, 21, 18, 16, 14, 13, 11, 10} - for i, n := range nums { - if got := kademlia.DefaultOverSaturationCalc(uint8(i)); got != n { - t.Fatalf("want %d, got %d", n, got) - } - } -} - func mineBin(t *testing.T, base swarm.Address, bin, count int, isBalanced bool) []swarm.Address { var rndAddrs = make([]swarm.Address, count)