|
|
|
@ -177,7 +177,7 @@ func (k *Kademlia) SuggestPeer() (a *BzzAddr, o int, want bool) { |
|
|
|
|
k.lock.Lock() |
|
|
|
|
defer k.lock.Unlock() |
|
|
|
|
minsize := k.MinBinSize |
|
|
|
|
depth := k.neighbourhoodDepth() |
|
|
|
|
depth := depthForPot(k.conns, k.MinProxBinSize, k.base) |
|
|
|
|
// if there is a callable neighbour within the current proxBin, connect
|
|
|
|
|
// this makes sure nearest neighbour set is fully connected
|
|
|
|
|
var ppo int |
|
|
|
@ -308,7 +308,7 @@ func (k *Kademlia) sendNeighbourhoodDepthChange() { |
|
|
|
|
// It provides signaling of neighbourhood depth change.
|
|
|
|
|
// This part of the code is sending new neighbourhood depth to nDepthC if that condition is met.
|
|
|
|
|
if k.nDepthC != nil { |
|
|
|
|
nDepth := k.neighbourhoodDepth() |
|
|
|
|
nDepth := depthForPot(k.conns, k.MinProxBinSize, k.base) |
|
|
|
|
if nDepth != k.nDepth { |
|
|
|
|
k.nDepth = nDepth |
|
|
|
|
k.nDepthC <- nDepth |
|
|
|
@ -364,7 +364,7 @@ func (k *Kademlia) EachBin(base []byte, pof pot.Pof, o int, eachBinFunc func(con |
|
|
|
|
|
|
|
|
|
var startPo int |
|
|
|
|
var endPo int |
|
|
|
|
kadDepth := k.neighbourhoodDepth() |
|
|
|
|
kadDepth := depthForPot(k.conns, k.MinProxBinSize, k.base) |
|
|
|
|
|
|
|
|
|
k.conns.EachBin(base, pof, o, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool { |
|
|
|
|
if startPo > 0 && endPo != k.MaxProxDisplay { |
|
|
|
@ -398,7 +398,7 @@ func (k *Kademlia) eachConn(base []byte, o int, f func(*Peer, int, bool) bool) { |
|
|
|
|
if len(base) == 0 { |
|
|
|
|
base = k.base |
|
|
|
|
} |
|
|
|
|
depth := k.neighbourhoodDepth() |
|
|
|
|
depth := depthForPot(k.conns, k.MinProxBinSize, k.base) |
|
|
|
|
k.conns.EachNeighbour(base, pof, func(val pot.Val, po int) bool { |
|
|
|
|
if po > o { |
|
|
|
|
return true |
|
|
|
@ -420,7 +420,7 @@ func (k *Kademlia) eachAddr(base []byte, o int, f func(*BzzAddr, int, bool) bool |
|
|
|
|
if len(base) == 0 { |
|
|
|
|
base = k.base |
|
|
|
|
} |
|
|
|
|
depth := k.neighbourhoodDepth() |
|
|
|
|
depth := depthForPot(k.conns, k.MinProxBinSize, k.base) |
|
|
|
|
k.addrs.EachNeighbour(base, pof, func(val pot.Val, po int) bool { |
|
|
|
|
if po > o { |
|
|
|
|
return true |
|
|
|
@ -429,26 +429,72 @@ func (k *Kademlia) eachAddr(base []byte, o int, f func(*BzzAddr, int, bool) bool |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// neighbourhoodDepth returns the proximity order that defines the distance of
|
|
|
|
|
// the nearest neighbour set with cardinality >= MinProxBinSize
|
|
|
|
|
// if there is altogether less than MinProxBinSize peers it returns 0
|
|
|
|
|
func (k *Kademlia) NeighbourhoodDepth() (depth int) { |
|
|
|
|
k.lock.RLock() |
|
|
|
|
defer k.lock.RUnlock() |
|
|
|
|
return k.neighbourhoodDepth() |
|
|
|
|
return depthForPot(k.conns, k.MinProxBinSize, k.base) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (k *Kademlia) neighbourhoodDepth() (depth int) { |
|
|
|
|
if k.conns.Size() < k.MinProxBinSize { |
|
|
|
|
// depthForPot returns the proximity order that defines the distance of
|
|
|
|
|
// the nearest neighbour set with cardinality >= MinProxBinSize
|
|
|
|
|
// if there is altogether less than MinProxBinSize peers it returns 0
|
|
|
|
|
// caller must hold the lock
|
|
|
|
|
func depthForPot(p *pot.Pot, minProxBinSize int, pivotAddr []byte) (depth int) { |
|
|
|
|
if p.Size() <= minProxBinSize { |
|
|
|
|
return 0 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// total number of peers in iteration
|
|
|
|
|
var size int |
|
|
|
|
|
|
|
|
|
// true if iteration has all prox peers
|
|
|
|
|
var b bool |
|
|
|
|
|
|
|
|
|
// last po recorded in iteration
|
|
|
|
|
var lastPo int |
|
|
|
|
|
|
|
|
|
f := func(v pot.Val, i int) bool { |
|
|
|
|
// po == 256 means that addr is the pivot address(self)
|
|
|
|
|
if i == 256 { |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
size++ |
|
|
|
|
depth = i |
|
|
|
|
return size < k.MinProxBinSize |
|
|
|
|
|
|
|
|
|
// this means we have all nn-peers.
|
|
|
|
|
// depth is by default set to the bin of the farthest nn-peer
|
|
|
|
|
if size == minProxBinSize { |
|
|
|
|
b = true |
|
|
|
|
depth = i |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// if there are empty bins between farthest nn and current node,
|
|
|
|
|
// the depth should recalculated to be
|
|
|
|
|
// the farthest of those empty bins
|
|
|
|
|
//
|
|
|
|
|
// 0 abac ccde
|
|
|
|
|
// 1 2a2a
|
|
|
|
|
// 2 589f <--- nearest non-nn
|
|
|
|
|
// ============ DEPTH 3 ===========
|
|
|
|
|
// 3 <--- don't count as empty bins
|
|
|
|
|
// 4 <--- don't count as empty bins
|
|
|
|
|
// 5 cbcb cdcd <---- furthest nn
|
|
|
|
|
// 6 a1a2 b3c4
|
|
|
|
|
if b && i < depth { |
|
|
|
|
depth = i + 1 |
|
|
|
|
lastPo = i |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
lastPo = i |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
p.EachNeighbour(pivotAddr, pof, f) |
|
|
|
|
|
|
|
|
|
// cover edge case where more than one farthest nn
|
|
|
|
|
// AND we only have nn-peers
|
|
|
|
|
if lastPo == depth { |
|
|
|
|
depth = 0 |
|
|
|
|
} |
|
|
|
|
k.conns.EachNeighbour(k.base, pof, f) |
|
|
|
|
return depth |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -508,7 +554,7 @@ func (k *Kademlia) string() string { |
|
|
|
|
liverows := make([]string, k.MaxProxDisplay) |
|
|
|
|
peersrows := make([]string, k.MaxProxDisplay) |
|
|
|
|
|
|
|
|
|
depth := k.neighbourhoodDepth() |
|
|
|
|
depth := depthForPot(k.conns, k.MinProxBinSize, k.base) |
|
|
|
|
rest := k.conns.Size() |
|
|
|
|
k.conns.EachBin(k.base, pof, 0, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool { |
|
|
|
|
var rowlen int |
|
|
|
@ -578,6 +624,7 @@ type PeerPot struct { |
|
|
|
|
// as hexadecimal representations of the address.
|
|
|
|
|
// used for testing only
|
|
|
|
|
func NewPeerPotMap(kadMinProxSize int, addrs [][]byte) map[string]*PeerPot { |
|
|
|
|
|
|
|
|
|
// create a table of all nodes for health check
|
|
|
|
|
np := pot.NewPot(nil, 0) |
|
|
|
|
for _, addr := range addrs { |
|
|
|
@ -586,34 +633,47 @@ func NewPeerPotMap(kadMinProxSize int, addrs [][]byte) map[string]*PeerPot { |
|
|
|
|
ppmap := make(map[string]*PeerPot) |
|
|
|
|
|
|
|
|
|
for i, a := range addrs { |
|
|
|
|
pl := 256 |
|
|
|
|
prev := 256 |
|
|
|
|
|
|
|
|
|
// actual kademlia depth
|
|
|
|
|
depth := depthForPot(np, kadMinProxSize, a) |
|
|
|
|
|
|
|
|
|
// upon entering a new iteration
|
|
|
|
|
// this will hold the value the po should be
|
|
|
|
|
// if it's one higher than the po in the last iteration
|
|
|
|
|
prevPo := 256 |
|
|
|
|
|
|
|
|
|
// all empty bins which are outside neighbourhood depth
|
|
|
|
|
var emptyBins []int |
|
|
|
|
|
|
|
|
|
// all nn-peers
|
|
|
|
|
var nns [][]byte |
|
|
|
|
np.EachNeighbour(addrs[i], pof, func(val pot.Val, po int) bool { |
|
|
|
|
a := val.([]byte) |
|
|
|
|
|
|
|
|
|
np.EachNeighbour(a, pof, func(val pot.Val, po int) bool { |
|
|
|
|
addr := val.([]byte) |
|
|
|
|
// po == 256 means that addr is the pivot address(self)
|
|
|
|
|
if po == 256 { |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
if pl == 256 || pl == po { |
|
|
|
|
nns = append(nns, a) |
|
|
|
|
} |
|
|
|
|
if pl == 256 && len(nns) >= kadMinProxSize { |
|
|
|
|
pl = po |
|
|
|
|
prev = po |
|
|
|
|
|
|
|
|
|
// iterate through the neighbours, going from the closest to the farthest
|
|
|
|
|
// we calculate the nearest neighbours that should be in the set
|
|
|
|
|
// depth in this case equates to:
|
|
|
|
|
// 1. Within all bins that are higher or equal than depth there are
|
|
|
|
|
// at least minProxBinSize peers connected
|
|
|
|
|
// 2. depth-1 bin is not empty
|
|
|
|
|
if po >= depth { |
|
|
|
|
nns = append(nns, addr) |
|
|
|
|
prevPo = depth - 1 |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
if prev < pl { |
|
|
|
|
for j := prev; j > po; j-- { |
|
|
|
|
emptyBins = append(emptyBins, j) |
|
|
|
|
} |
|
|
|
|
for j := prevPo; j > po; j-- { |
|
|
|
|
emptyBins = append(emptyBins, j) |
|
|
|
|
} |
|
|
|
|
prev = po - 1 |
|
|
|
|
prevPo = po - 1 |
|
|
|
|
return true |
|
|
|
|
}) |
|
|
|
|
for j := prev; j >= 0; j-- { |
|
|
|
|
emptyBins = append(emptyBins, j) |
|
|
|
|
} |
|
|
|
|
log.Trace(fmt.Sprintf("%x NNS: %s", addrs[i][:4], LogAddrs(nns))) |
|
|
|
|
|
|
|
|
|
log.Trace(fmt.Sprintf("%x NNS: %s, emptyBins: %s", addrs[i][:4], LogAddrs(nns), logEmptyBins(emptyBins))) |
|
|
|
|
ppmap[common.Bytes2Hex(a)] = &PeerPot{nns, emptyBins} |
|
|
|
|
} |
|
|
|
|
return ppmap |
|
|
|
@ -628,7 +688,7 @@ func (k *Kademlia) saturation(n int) int { |
|
|
|
|
prev++ |
|
|
|
|
return prev == po && size >= n |
|
|
|
|
}) |
|
|
|
|
depth := k.neighbourhoodDepth() |
|
|
|
|
depth := depthForPot(k.conns, k.MinProxBinSize, k.base) |
|
|
|
|
if depth < prev { |
|
|
|
|
return depth |
|
|
|
|
} |
|
|
|
@ -641,8 +701,11 @@ func (k *Kademlia) full(emptyBins []int) (full bool) { |
|
|
|
|
prev := 0 |
|
|
|
|
e := len(emptyBins) |
|
|
|
|
ok := true |
|
|
|
|
depth := k.neighbourhoodDepth() |
|
|
|
|
depth := depthForPot(k.conns, k.MinProxBinSize, k.base) |
|
|
|
|
k.conns.EachBin(k.base, pof, 0, func(po, _ int, _ func(func(val pot.Val, i int) bool) bool) bool { |
|
|
|
|
if po >= depth { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
if prev == depth+1 { |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|