Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

swarm/network: Rename minproxbinsize, add as member of simulation #18408

Merged
merged 2 commits into from Jan 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
70 changes: 37 additions & 33 deletions swarm/network/kademlia.go
Expand Up @@ -54,27 +54,27 @@ var Pof = pot.DefaultPof(256)
// KadParams holds the config params for Kademlia
type KadParams struct {
// adjustable parameters
MaxProxDisplay int // number of rows the table shows
MinProxBinSize int // nearest neighbour core minimum cardinality
MinBinSize int // minimum number of peers in a row
MaxBinSize int // maximum number of peers in a row before pruning
RetryInterval int64 // initial interval before a peer is first redialed
RetryExponent int // exponent to multiply retry intervals with
MaxRetries int // maximum number of redial attempts
MaxProxDisplay int // number of rows the table shows
NeighbourhoodSize int // nearest neighbour core minimum cardinality
MinBinSize int // minimum number of peers in a row
MaxBinSize int // maximum number of peers in a row before pruning
RetryInterval int64 // initial interval before a peer is first redialed
RetryExponent int // exponent to multiply retry intervals with
MaxRetries int // maximum number of redial attempts
// function to sanction or prevent suggesting a peer
Reachable func(*BzzAddr) bool `json:"-"`
}

// NewKadParams returns a params struct with default values
func NewKadParams() *KadParams {
return &KadParams{
MaxProxDisplay: 16,
MinProxBinSize: 2,
MinBinSize: 2,
MaxBinSize: 4,
RetryInterval: 4200000000, // 4.2 sec
MaxRetries: 42,
RetryExponent: 2,
MaxProxDisplay: 16,
NeighbourhoodSize: 2,
MinBinSize: 2,
MaxBinSize: 4,
RetryInterval: 4200000000, // 4.2 sec
MaxRetries: 42,
RetryExponent: 2,
}
}

Expand Down Expand Up @@ -175,7 +175,7 @@ func (k *Kademlia) SuggestPeer() (a *BzzAddr, o int, want bool) {
k.lock.Lock()
defer k.lock.Unlock()
minsize := k.MinBinSize
depth := depthForPot(k.conns, k.MinProxBinSize, k.base)
depth := depthForPot(k.conns, k.NeighbourhoodSize, 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
Expand Down Expand Up @@ -306,7 +306,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 := depthForPot(k.conns, k.MinProxBinSize, k.base)
nDepth := depthForPot(k.conns, k.NeighbourhoodSize, k.base)
if nDepth != k.nDepth {
k.nDepth = nDepth
k.nDepthC <- nDepth
Expand Down Expand Up @@ -366,7 +366,7 @@ func (k *Kademlia) EachBin(base []byte, pof pot.Pof, o int, eachBinFunc func(con

var startPo int
var endPo int
kadDepth := depthForPot(k.conns, k.MinProxBinSize, k.base)
kadDepth := depthForPot(k.conns, k.NeighbourhoodSize, 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 {
Expand Down Expand Up @@ -432,23 +432,23 @@ func (k *Kademlia) eachAddr(base []byte, o int, f func(*BzzAddr, int) bool) {
func (k *Kademlia) NeighbourhoodDepth() (depth int) {
k.lock.RLock()
defer k.lock.RUnlock()
return depthForPot(k.conns, k.MinProxBinSize, k.base)
return depthForPot(k.conns, k.NeighbourhoodSize, k.base)
}

// 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
// the nearest neighbour set with cardinality >= NeighbourhoodSize
// if there is altogether less than NeighbourhoodSize peers it returns 0
// caller must hold the lock
func depthForPot(p *pot.Pot, minProxBinSize int, pivotAddr []byte) (depth int) {
if p.Size() <= minProxBinSize {
func depthForPot(p *pot.Pot, neighbourhoodSize int, pivotAddr []byte) (depth int) {
if p.Size() <= neighbourhoodSize {
return 0
}

// total number of peers in iteration
var size int

// determining the depth is a two-step process
// first we find the proximity bin of the shallowest of the MinProxBinSize peers
// first we find the proximity bin of the shallowest of the NeighbourhoodSize peers
// the numeric value of depth cannot be higher than this
var maxDepth int

Expand All @@ -461,7 +461,7 @@ func depthForPot(p *pot.Pot, minProxBinSize int, pivotAddr []byte) (depth int) {

// this means we have all nn-peers.
// depth is by default set to the bin of the farthest nn-peer
if size == minProxBinSize {
if size == neighbourhoodSize {
maxDepth = i
return false
}
Expand Down Expand Up @@ -538,12 +538,12 @@ func (k *Kademlia) string() string {

rows = append(rows, "=========================================================================")
rows = append(rows, fmt.Sprintf("%v KΛÐΞMLIΛ hive: queen's address: %x", time.Now().UTC().Format(time.UnixDate), k.BaseAddr()[:3]))
rows = append(rows, fmt.Sprintf("population: %d (%d), MinProxBinSize: %d, MinBinSize: %d, MaxBinSize: %d", k.conns.Size(), k.addrs.Size(), k.MinProxBinSize, k.MinBinSize, k.MaxBinSize))
rows = append(rows, fmt.Sprintf("population: %d (%d), NeighbourhoodSize: %d, MinBinSize: %d, MaxBinSize: %d", k.conns.Size(), k.addrs.Size(), k.NeighbourhoodSize, k.MinBinSize, k.MaxBinSize))

liverows := make([]string, k.MaxProxDisplay)
peersrows := make([]string, k.MaxProxDisplay)

depth := depthForPot(k.conns, k.MinProxBinSize, k.base)
depth := depthForPot(k.conns, k.NeighbourhoodSize, 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
Expand Down Expand Up @@ -611,10 +611,10 @@ type PeerPot struct {

// NewPeerPotMap creates a map of pot record of *BzzAddr with keys
// as hexadecimal representations of the address.
// the MinProxBinSize of the passed kademlia is used
// the NeighbourhoodSize of the passed kademlia is used
// used for testing only
// TODO move to separate testing tools file
func NewPeerPotMap(minProxBinSize int, addrs [][]byte) map[string]*PeerPot {
func NewPeerPotMap(neighbourhoodSize int, addrs [][]byte) map[string]*PeerPot {

// create a table of all nodes for health check
np := pot.NewPot(nil, 0)
Expand All @@ -628,7 +628,7 @@ func NewPeerPotMap(minProxBinSize int, addrs [][]byte) map[string]*PeerPot {
for i, a := range addrs {

// actual kademlia depth
depth := depthForPot(np, minProxBinSize, a)
depth := depthForPot(np, neighbourhoodSize, a)

// all nn-peers
var nns [][]byte
Expand Down Expand Up @@ -670,7 +670,7 @@ func (k *Kademlia) saturation() int {
return prev == po && size >= k.MinBinSize
})
// TODO evaluate whether this check cannot just as well be done within the eachbin
depth := depthForPot(k.conns, k.MinProxBinSize, k.base)
depth := depthForPot(k.conns, k.NeighbourhoodSize, k.base)
if depth < prev {
return depth
}
Expand All @@ -683,7 +683,7 @@ func (k *Kademlia) saturation() int {
// TODO move to separate testing tools file
func (k *Kademlia) knowNeighbours(addrs [][]byte) (got bool, n int, missing [][]byte) {
pm := make(map[string]bool)
depth := depthForPot(k.conns, k.MinProxBinSize, k.base)
depth := depthForPot(k.conns, k.NeighbourhoodSize, k.base)
// create a map with all peers at depth and deeper known in the kademlia
k.eachAddr(nil, 255, func(p *BzzAddr, po int) bool {
// in order deepest to shallowest compared to the kademlia base address
Expand Down Expand Up @@ -719,7 +719,11 @@ func (k *Kademlia) knowNeighbours(addrs [][]byte) (got bool, n int, missing [][]
// It is used in Healthy function for testing only
func (k *Kademlia) connectedNeighbours(peers [][]byte) (got bool, n int, missing [][]byte) {
pm := make(map[string]bool)
depth := depthForPot(k.conns, k.MinProxBinSize, k.base)

// create a map with all peers at depth and deeper that are connected in the kademlia
// in order deepest to shallowest compared to the kademlia base address
// all bins (except self) are included (0 <= bin <= 255)
depth := depthForPot(k.conns, k.NeighbourhoodSize, k.base)
k.eachConn(nil, 255, func(p *Peer, po int) bool {
if po < depth {
return false
Expand Down Expand Up @@ -772,7 +776,7 @@ func (k *Kademlia) Healthy(pp *PeerPot) *Health {
defer k.lock.RUnlock()
gotnn, countgotnn, culpritsgotnn := k.connectedNeighbours(pp.NNSet)
knownn, countknownn, culpritsknownn := k.knowNeighbours(pp.NNSet)
depth := depthForPot(k.conns, k.MinProxBinSize, k.base)
depth := depthForPot(k.conns, k.NeighbourhoodSize, k.base)
saturated := k.saturation() < depth
log.Trace(fmt.Sprintf("%08x: healthy: knowNNs: %v, gotNNs: %v, saturated: %v\n", k.base, knownn, gotnn, saturated))
return &Health{
Expand Down
20 changes: 10 additions & 10 deletions swarm/network/kademlia_test.go
Expand Up @@ -45,7 +45,7 @@ func newTestKademliaParams() *KadParams {
params := NewKadParams()
// TODO why is this 1?
params.MinBinSize = 1
params.MinProxBinSize = 2
params.NeighbourhoodSize = 2
return params
}

Expand Down Expand Up @@ -87,7 +87,7 @@ func Register(k *Kademlia, regs ...string) {
// empty bins above the farthest "nearest neighbor-peer" then
// the depth should be set at the farthest of those empty bins
//
// TODO: Make test adapt to change in MinProxBinSize
// TODO: Make test adapt to change in NeighbourhoodSize
func TestNeighbourhoodDepth(t *testing.T) {
baseAddressBytes := RandomAddr().OAddr
kad := NewKademlia(baseAddressBytes, NewKadParams())
Expand Down Expand Up @@ -237,7 +237,7 @@ func assertHealth(t *testing.T, k *Kademlia, expectHealthy bool, expectSaturatio
return true
})

pp := NewPeerPotMap(k.MinProxBinSize, addrs)
pp := NewPeerPotMap(k.NeighbourhoodSize, addrs)
healthParams := k.Healthy(pp[kid])

// definition of health, all conditions but be true:
Expand Down Expand Up @@ -605,7 +605,7 @@ func TestKademliaHiveString(t *testing.T) {
Register(k, "10000000", "10000001")
k.MaxProxDisplay = 8
h := k.String()
expH := "\n=========================================================================\nMon Feb 27 12:10:28 UTC 2017 KΛÐΞMLIΛ hive: queen's address: 000000\npopulation: 2 (4), MinProxBinSize: 2, MinBinSize: 1, MaxBinSize: 4\n============ DEPTH: 0 ==========================================\n000 0 | 2 8100 (0) 8000 (0)\n001 1 4000 | 1 4000 (0)\n002 1 2000 | 1 2000 (0)\n003 0 | 0\n004 0 | 0\n005 0 | 0\n006 0 | 0\n007 0 | 0\n========================================================================="
expH := "\n=========================================================================\nMon Feb 27 12:10:28 UTC 2017 KΛÐΞMLIΛ hive: queen's address: 000000\npopulation: 2 (4), NeighbourhoodSize: 2, MinBinSize: 1, MaxBinSize: 4\n============ DEPTH: 0 ==========================================\n000 0 | 2 8100 (0) 8000 (0)\n001 1 4000 | 1 4000 (0)\n002 1 2000 | 1 2000 (0)\n003 0 | 0\n004 0 | 0\n005 0 | 0\n006 0 | 0\n007 0 | 0\n========================================================================="
if expH[104:] != h[104:] {
t.Fatalf("incorrect hive output. expected %v, got %v", expH, h)
}
Expand Down Expand Up @@ -636,7 +636,7 @@ func testKademliaCase(t *testing.T, pivotAddr string, addrs ...string) {
}
}

ppmap := NewPeerPotMap(k.MinProxBinSize, byteAddrs)
ppmap := NewPeerPotMap(k.NeighbourhoodSize, byteAddrs)

pp := ppmap[pivotAddr]

Expand All @@ -662,7 +662,7 @@ in higher level tests for streaming. They were generated randomly.

=========================================================================
Mon Apr 9 12:18:24 UTC 2018 KΛÐΞMLIΛ hive: queen's address: 7efef1
population: 9 (49), MinProxBinSize: 2, MinBinSize: 2, MaxBinSize: 4
population: 9 (49), NeighbourhoodSize: 2, MinBinSize: 2, MaxBinSize: 4
000 2 d7e5 ec56 | 18 ec56 (0) d7e5 (0) d9e0 (0) c735 (0)
001 2 18f1 3176 | 14 18f1 (0) 10bb (0) 10d1 (0) 0421 (0)
002 2 52aa 47cd | 11 52aa (0) 51d9 (0) 5161 (0) 5130 (0)
Expand Down Expand Up @@ -745,7 +745,7 @@ in higher level tests for streaming. They were generated randomly.

=========================================================================
Mon Apr 9 18:43:48 UTC 2018 KΛÐΞMLIΛ hive: queen's address: bc7f3b
population: 9 (49), MinProxBinSize: 2, MinBinSize: 2, MaxBinSize: 4
population: 9 (49), NeighbourhoodSize: 2, MinBinSize: 2, MaxBinSize: 4
000 2 0f49 67ff | 28 0f49 (0) 0211 (0) 07b2 (0) 0703 (0)
001 2 e84b f3a4 | 13 f3a4 (0) e84b (0) e58b (0) e60b (0)
002 1 8dba | 1 8dba (0)
Expand Down Expand Up @@ -779,7 +779,7 @@ in higher level tests for streaming. They were generated randomly.

=========================================================================
Mon Apr 9 19:04:35 UTC 2018 KΛÐΞMLIΛ hive: queen's address: b4822e
population: 8 (49), MinProxBinSize: 2, MinBinSize: 2, MaxBinSize: 4
population: 8 (49), NeighbourhoodSize: 2, MinBinSize: 2, MaxBinSize: 4
000 2 786c 774b | 29 774b (0) 786c (0) 7a79 (0) 7d2f (0)
001 2 d9de cf19 | 10 cf19 (0) d9de (0) d2ff (0) d2a2 (0)
002 2 8ca1 8d74 | 5 8d74 (0) 8ca1 (0) 9793 (0) 9f51 (0)
Expand Down Expand Up @@ -813,7 +813,7 @@ in higher level tests for streaming. They were generated randomly.

=========================================================================
Mon Apr 9 19:16:25 UTC 2018 KΛÐΞMLIΛ hive: queen's address: 9a90fe
population: 8 (49), MinProxBinSize: 2, MinBinSize: 2, MaxBinSize: 4
population: 8 (49), NeighbourhoodSize: 2, MinBinSize: 2, MaxBinSize: 4
000 2 72ef 4e6c | 24 0b1e (0) 0d66 (0) 17f5 (0) 17e8 (0)
001 2 fc2b fa47 | 13 fa47 (0) fc2b (0) fffd (0) ecef (0)
002 2 b847 afa8 | 6 afa8 (0) ad77 (0) bb7c (0) b847 (0)
Expand Down Expand Up @@ -848,7 +848,7 @@ in higher level tests for streaming. They were generated randomly.

=========================================================================
Mon Apr 9 19:25:18 UTC 2018 KΛÐΞMLIΛ hive: queen's address: 5dd5c7
population: 13 (49), MinProxBinSize: 2, MinBinSize: 2, MaxBinSize: 4
population: 13 (49), NeighbourhoodSize: 2, MinBinSize: 2, MaxBinSize: 4
000 2 e528 fad0 | 22 fad0 (0) e528 (0) e3bb (0) ed13 (0)
001 3 3f30 18e0 1dd3 | 7 3f30 (0) 23db (0) 10b6 (0) 18e0 (0)
002 4 7c54 7804 61e4 60f9 | 10 61e4 (0) 60f9 (0) 636c (0) 7186 (0)
Expand Down
2 changes: 1 addition & 1 deletion swarm/network/networkid_test.go
Expand Up @@ -188,7 +188,7 @@ func newServices() adapters.Services {
return k
}
params := NewKadParams()
params.MinProxBinSize = 2
params.NeighbourhoodSize = 2
params.MaxBinSize = 3
params.MinBinSize = 1
params.MaxRetries = 1000
Expand Down
13 changes: 7 additions & 6 deletions swarm/network/simulation/example_test.go
Expand Up @@ -18,8 +18,14 @@ package simulation_test

import (
"context"
"fmt"
"sync"
"time"

"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
"github.com/ethereum/go-ethereum/swarm/network"
"github.com/ethereum/go-ethereum/swarm/network/simulation"
)

Expand All @@ -28,10 +34,6 @@ import (
// all nodes have the their Kademlias healthy.
func ExampleSimulation_WaitTillHealthy() {

log.Error("temporarily disabled as simulations.WaitTillHealthy cannot be trusted")

/* Commented out to avoid go vet errors/warnings

sim := simulation.New(map[string]simulation.ServiceFunc{
"bzz": func(ctx *adapters.ServiceContext, b *sync.Map) (node.Service, func(), error) {
addr := network.NewAddr(ctx.Config.Node())
Expand Down Expand Up @@ -59,7 +61,7 @@ func ExampleSimulation_WaitTillHealthy() {

ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
ill, err := sim.WaitTillHealthy(ctx, 2)
ill, err := sim.WaitTillHealthy(ctx)
if err != nil {
// inspect the latest detected not healthy kademlias
for id, kad := range ill {
Expand All @@ -71,7 +73,6 @@ func ExampleSimulation_WaitTillHealthy() {

// continue with the test

*/
}

// Watch all peer events in the simulation network, buy receiving from a channel.
Expand Down
4 changes: 2 additions & 2 deletions swarm/network/simulation/kademlia.go
Expand Up @@ -34,7 +34,7 @@ var BucketKeyKademlia BucketKey = "kademlia"
// WaitTillHealthy is blocking until the health of all kademlias is true.
// If error is not nil, a map of kademlia that was found not healthy is returned.
// TODO: Check correctness since change in kademlia depth calculation logic
func (s *Simulation) WaitTillHealthy(ctx context.Context, kadMinProxSize int) (ill map[enode.ID]*network.Kademlia, err error) {
func (s *Simulation) WaitTillHealthy(ctx context.Context) (ill map[enode.ID]*network.Kademlia, err error) {
// Prepare PeerPot map for checking Kademlia health
var ppmap map[string]*network.PeerPot
kademlias := s.kademlias()
Expand All @@ -43,7 +43,7 @@ func (s *Simulation) WaitTillHealthy(ctx context.Context, kadMinProxSize int) (i
for _, k := range kademlias {
addrs = append(addrs, k.BaseAddr())
}
ppmap = network.NewPeerPotMap(kadMinProxSize, addrs)
ppmap = network.NewPeerPotMap(s.neighbourhoodSize, addrs)

// Wait for healthy Kademlia on every node before checking files
ticker := time.NewTicker(200 * time.Millisecond)
Expand Down
3 changes: 2 additions & 1 deletion swarm/network/simulation/kademlia_test.go
Expand Up @@ -28,6 +28,7 @@ import (
)

func TestWaitTillHealthy(t *testing.T) {
t.Skip("WaitTillHealthy depends on discovery, which relies on a reliable SuggestPeer, which is not reliable")

sim := New(map[string]ServiceFunc{
"bzz": func(ctx *adapters.ServiceContext, b *sync.Map) (node.Service, func(), error) {
Expand All @@ -54,7 +55,7 @@ func TestWaitTillHealthy(t *testing.T) {

ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
defer cancel()
ill, err := sim.WaitTillHealthy(ctx, 2)
ill, err := sim.WaitTillHealthy(ctx)
if err != nil {
for id, kad := range ill {
t.Log("Node", id)
Expand Down