Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mybee
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
mybee
Commits
78aba90f
Unverified
Commit
78aba90f
authored
Apr 13, 2021
by
acud
Committed by
GitHub
Apr 13, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kademlia: add unsaturated bins to depth calculation (#1553)
parent
63f2ef34
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
111 additions
and
84 deletions
+111
-84
kademlia.go
pkg/kademlia/kademlia.go
+30
-5
kademlia_test.go
pkg/kademlia/kademlia_test.go
+81
-79
No files found.
pkg/kademlia/kademlia.go
View file @
78aba90f
...
...
@@ -555,6 +555,32 @@ func recalcDepth(peers *pslice.PSlice) uint8 {
shallowestEmpty
,
noEmptyBins
=
peers
.
ShallowestEmpty
()
)
shallowestUnsaturated
:=
uint8
(
0
)
binCount
:=
0
_
=
peers
.
EachBinRev
(
func
(
_
swarm
.
Address
,
bin
uint8
)
(
bool
,
bool
,
error
)
{
if
bin
==
shallowestUnsaturated
{
binCount
++
return
false
,
false
,
nil
}
if
bin
>
shallowestUnsaturated
&&
binCount
<
saturationPeers
{
// this means we have less than saturationPeers in the previous bin
// therefore we can return assuming that bin is the unsaturated one.
return
true
,
false
,
nil
}
// bin > shallowestUnsaturated && binCount >= saturationPeers
shallowestUnsaturated
=
bin
binCount
=
1
return
false
,
false
,
nil
})
// if there are some empty bins and the shallowestEmpty is
// smaller than the shallowestUnsaturated then set shallowest
// unsaturated to the empty bin.
if
!
noEmptyBins
&&
shallowestEmpty
<
shallowestUnsaturated
{
shallowestUnsaturated
=
shallowestEmpty
}
_
=
peers
.
EachBin
(
func
(
_
swarm
.
Address
,
po
uint8
)
(
bool
,
bool
,
error
)
{
peersCtr
++
if
peersCtr
>=
nnLowWatermark
{
...
...
@@ -563,12 +589,11 @@ func recalcDepth(peers *pslice.PSlice) uint8 {
}
return
false
,
false
,
nil
})
if
noEmptyBins
||
shallowestEmpty
>
candidate
{
if
shallowestUnsaturated
>
candidate
{
return
candidate
}
return
shallowest
Empty
return
shallowest
Unsaturated
}
// connect connects to a peer and gossips its address to our connected peers,
...
...
@@ -889,8 +914,8 @@ func (k *Kad) ClosestPeer(addr swarm.Address, skipPeers ...swarm.Address) (swarm
}
// IsWithinDepth returns if an address is within the neighborhood depth of a node.
func
(
k
*
Kad
)
IsWithinDepth
(
adr
swarm
.
Address
)
bool
{
return
swarm
.
Proximity
(
k
.
base
.
Bytes
(),
adr
.
Bytes
())
>=
k
.
NeighborhoodDepth
()
func
(
k
*
Kad
)
IsWithinDepth
(
ad
d
r
swarm
.
Address
)
bool
{
return
swarm
.
Proximity
(
k
.
base
.
Bytes
(),
ad
d
r
.
Bytes
())
>=
k
.
NeighborhoodDepth
()
}
// // EachNeighbor iterates from closest bin to farthest of the neighborhood peers.
...
...
pkg/kademlia/kademlia_test.go
View file @
78aba90f
...
...
@@ -49,8 +49,6 @@ func TestNeighborhoodDepth(t *testing.T) {
var
(
conns
int32
// how many connect calls were made to the p2p mock
base
,
kad
,
ab
,
_
,
signer
=
newTestKademlia
(
&
conns
,
nil
,
kademlia
.
Options
{})
peers
[]
swarm
.
Address
binEight
[]
swarm
.
Address
)
if
err
:=
kad
.
Start
(
context
.
Background
());
err
!=
nil
{
...
...
@@ -58,123 +56,127 @@ func TestNeighborhoodDepth(t *testing.T) {
}
defer
kad
.
Close
()
for
i
:=
0
;
i
<
8
;
i
++
{
addr
:=
test
.
RandomAddressAt
(
base
,
i
)
peers
=
append
(
peers
,
addr
)
}
// add 2 peers in bin 8
for
i
:=
0
;
i
<
2
;
i
++
{
addr
:=
test
.
RandomAddressAt
(
base
,
8
)
binEight
=
append
(
binEight
,
addr
)
}
// check empty kademlia depth is 0
kDepth
(
t
,
kad
,
0
)
addOne
(
t
,
signer
,
kad
,
ab
,
addr
)
// add two bin 8 peers, verify depth still 0
add
(
t
,
signer
,
kad
,
ab
,
binEight
,
0
,
2
)
// wait for one connection
waitConn
(
t
,
&
conns
)
}
// depth is 0
kDepth
(
t
,
kad
,
0
)
var
shallowPeers
[]
swarm
.
Address
// add two first peers (po0,po1)
add
(
t
,
signer
,
kad
,
ab
,
peers
,
0
,
2
)
for
i
:=
0
;
i
<
2
;
i
++
{
addr
:=
test
.
RandomAddressAt
(
base
,
i
)
addOne
(
t
,
signer
,
kad
,
ab
,
addr
)
shallowPeers
=
append
(
shallowPeers
,
addr
)
// wait for 4 connections
waitCounter
(
t
,
&
conns
,
4
)
// wait for one connection
waitConn
(
t
,
&
conns
)
}
// depth 2 (shallowest empty bin)
kDepth
(
t
,
kad
,
2
)
for
_
,
a
:=
range
shallowPeers
{
if
!
kad
.
IsWithinDepth
(
a
)
{
t
.
Fatal
(
"expected address to be within depth"
)
}
}
for
i
:=
2
;
i
<
len
(
peers
)
-
1
;
i
++
{
addOne
(
t
,
signer
,
kad
,
ab
,
peers
[
i
])
// depth 0 - bin 0 is unsaturated
kDepth
(
t
,
kad
,
0
)
for
i
:=
2
;
i
<
8
;
i
++
{
addr
:=
test
.
RandomAddressAt
(
base
,
i
)
addOne
(
t
,
signer
,
kad
,
ab
,
addr
)
// wait for one connection
waitConn
(
t
,
&
conns
)
}
// still zero
kDepth
(
t
,
kad
,
0
)
// depth is i+1
// now add peers from bin 0 and expect the depth
// to shift. the depth will be that of the shallowest
// unsaturated bin.
for
i
:=
0
;
i
<
7
;
i
++
{
for
j
:=
0
;
j
<
3
;
j
++
{
addr
:=
test
.
RandomAddressAt
(
base
,
i
)
addOne
(
t
,
signer
,
kad
,
ab
,
addr
)
waitConn
(
t
,
&
conns
)
}
kDepth
(
t
,
kad
,
i
+
1
)
}
// the last peer in bin 7 which is empty we insert manually,
addOne
(
t
,
signer
,
kad
,
ab
,
peers
[
len
(
peers
)
-
1
])
waitConn
(
t
,
&
conns
)
// depth is 7 because bin 7 is unsaturated (1 peer)
kDepth
(
t
,
kad
,
7
)
// depth is 8 because we have nnLowWatermark neighbors in bin 8
kDepth
(
t
,
kad
,
8
)
// expect shallow peers not in depth
// now add another ONE peer at depth+1, and expect the depth to still
for
_
,
a
:=
range
shallowPeers
{
if
kad
.
IsWithinDepth
(
a
)
{
t
.
Fatal
(
"expected address to outside of depth"
)
}
}
// now add another ONE peer at depth, and expect the depth to still
// stay 8, because the counter for nnLowWatermark would be reached only at the next
// depth iteration when calculating depth
addr
:=
test
.
RandomAddressAt
(
base
,
9
)
addr
:=
test
.
RandomAddressAt
(
base
,
8
)
addOne
(
t
,
signer
,
kad
,
ab
,
addr
)
waitConn
(
t
,
&
conns
)
kDepth
(
t
,
kad
,
8
)
kDepth
(
t
,
kad
,
7
)
//
fill the rest up to the bin before last and check that everything works at the edges
for
i
:=
10
;
i
<
int
(
swarm
.
MaxBins
)
-
1
;
i
++
{
addr
:=
test
.
RandomAddressAt
(
base
,
i
)
//
now fill bin 7 so that it is saturated, expect depth 8
for
i
:=
0
;
i
<
3
;
i
++
{
addr
:=
test
.
RandomAddressAt
(
base
,
7
)
addOne
(
t
,
signer
,
kad
,
ab
,
addr
)
waitConn
(
t
,
&
conns
)
kDepth
(
t
,
kad
,
i
-
1
)
}
kDepth
(
t
,
kad
,
8
)
// add a whole bunch of peers in bin 13, expect depth to stay at 13
// saturate bin 8
addr
=
test
.
RandomAddressAt
(
base
,
8
)
addOne
(
t
,
signer
,
kad
,
ab
,
addr
)
waitConn
(
t
,
&
conns
)
kDepth
(
t
,
kad
,
8
)
var
addrs
[]
swarm
.
Address
// fill the rest up to the bin before last and check that everything works at the edges
for
i
:=
9
;
i
<
int
(
swarm
.
MaxBins
);
i
++
{
for
j
:=
0
;
j
<
4
;
j
++
{
addr
:=
test
.
RandomAddressAt
(
base
,
i
)
addOne
(
t
,
signer
,
kad
,
ab
,
addr
)
waitConn
(
t
,
&
conns
)
addrs
=
append
(
addrs
,
addr
)
}
kDepth
(
t
,
kad
,
i
)
}
// add a whole bunch of peers in bin 15, expect depth to stay at 15
for
i
:=
0
;
i
<
15
;
i
++
{
addr
=
test
.
RandomAddressAt
(
base
,
1
3
)
addr
=
test
.
RandomAddressAt
(
base
,
1
5
)
addOne
(
t
,
signer
,
kad
,
ab
,
addr
)
}
waitCounter
(
t
,
&
conns
,
15
)
kDepth
(
t
,
kad
,
13
)
// add one at 14 - depth should be now 14
addr
=
test
.
RandomAddressAt
(
base
,
14
)
addOne
(
t
,
signer
,
kad
,
ab
,
addr
)
kDepth
(
t
,
kad
,
14
)
addr2
:=
test
.
RandomAddressAt
(
base
,
15
)
addOne
(
t
,
signer
,
kad
,
ab
,
addr2
)
kDepth
(
t
,
kad
,
14
)
addr3
:=
test
.
RandomAddressAt
(
base
,
15
)
addOne
(
t
,
signer
,
kad
,
ab
,
addr3
)
kDepth
(
t
,
kad
,
15
)
//
now remove that peer and check that the depth is back at
14
removeOne
(
kad
,
addr
3
)
//
remove one at 14, depth should be
14
removeOne
(
kad
,
addr
s
[
len
(
addrs
)
-
5
]
)
kDepth
(
t
,
kad
,
14
)
// remove the peer at bin 1, depth should be 1
removeOne
(
kad
,
peers
[
1
])
kDepth
(
t
,
kad
,
1
)
}
func
TestIsWithinDepth
(
t
*
testing
.
T
)
{
var
(
conns
int32
// how many connect calls were made to the p2p mock
base
,
kad
,
ab
,
_
,
signer
=
newTestKademlia
(
&
conns
,
nil
,
kademlia
.
Options
{})
peers
[]
swarm
.
Address
)
if
err
:=
kad
.
Start
(
context
.
Background
());
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
kad
.
Close
()
for
i
:=
0
;
i
<
15
;
i
++
{
addr
:=
test
.
RandomAddressAt
(
base
,
i
)
peers
=
append
(
peers
,
addr
)
// empty bin 9 and expect depth 9
for
i
:=
0
;
i
<
4
;
i
++
{
removeOne
(
kad
,
addrs
[
i
])
}
kDepth
(
t
,
kad
,
9
)
add
(
t
,
signer
,
kad
,
ab
,
peers
,
0
,
15
)
waitCounter
(
t
,
&
conns
,
15
)
if
kad
.
IsWithinDepth
(
peers
[
kad
.
NeighborhoodDepth
()
-
1
])
{
t
.
Fatalf
(
"peer should NOT be in neignborhood"
)
if
!
kad
.
IsWithinDepth
(
addrs
[
0
])
{
t
.
Fatal
(
"expected address to be within depth"
)
}
if
!
kad
.
IsWithinDepth
(
peers
[
kad
.
NeighborhoodDepth
()])
{
t
.
Fatalf
(
"peer should be in neignborhood"
)
}
}
func
TestEachNeighbor
(
t
*
testing
.
T
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment