github.com/aaa256/atlantis@v0.0.0-20210707112435-42ee889287a2/swarm/network/kademlia.go (about)

     1  // Copyright 2017 The go-athereum Authors
     2  // This file is part of the go-athereum library.
     3  //
     4  // The go-athereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-athereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-athereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package network
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"math/rand"
    23  	"strings"
    24  	"sync"
    25  	"time"
    26  
    27  	"github.com/athereum/go-athereum/common"
    28  	"github.com/athereum/go-athereum/swarm/log"
    29  	"github.com/athereum/go-athereum/swarm/pot"
    30  )
    31  
    32  /*
    33  
    34  Taking the proximity order relative to a fix point x classifies the points in
    35  the space (n byte long byte sequences) into bins. Items in each are at
    36  most half as distant from x as items in the previous bin. Given a sample of
    37  uniformly distributed items (a hash function over arbitrary sequence) the
    38  proximity scale maps onto series of subsets with cardinalities on a negative
    39  exponential scale.
    40  
    41  It also has the property that any two item belonging to the same bin are at
    42  most half as distant from each other as they are from x.
    43  
    44  If we think of random sample of items in the bins as connections in a network of
    45  interconnected nodes then relative proximity can serve as the basis for local
    46  decisions for graph traversal where the task is to find a route between two
    47  points. Since in every hop, the finite distance halves, there is
    48  a guaranteed constant maximum limit on the number of hops needed to reach one
    49  node from the other.
    50  */
    51  
    52  var pof = pot.DefaultPof(256)
    53  
    54  // KadParams holds the config params for Kademlia
    55  type KadParams struct {
    56  	// adjustable parameters
    57  	MaxProxDisplay int   // number of rows the table shows
    58  	MinProxBinSize int   // nearest neighbour core minimum cardinality
    59  	MinBinSize     int   // minimum number of peers in a row
    60  	MaxBinSize     int   // maximum number of peers in a row before pruning
    61  	RetryInterval  int64 // initial interval before a peer is first redialed
    62  	RetryExponent  int   // exponent to multiply retry intervals with
    63  	MaxRetries     int   // maximum number of redial attempts
    64  	// function to sanction or prevent suggesting a peer
    65  	Reachable func(OverlayAddr) bool
    66  }
    67  
    68  // NewKadParams returns a params struct with default values
    69  func NewKadParams() *KadParams {
    70  	return &KadParams{
    71  		MaxProxDisplay: 16,
    72  		MinProxBinSize: 2,
    73  		MinBinSize:     2,
    74  		MaxBinSize:     4,
    75  		RetryInterval:  4200000000, // 4.2 sec
    76  		MaxRetries:     42,
    77  		RetryExponent:  2,
    78  	}
    79  }
    80  
    81  // Kademlia is a table of live peers and a db of known peers (node records)
    82  type Kademlia struct {
    83  	lock       sync.RWMutex
    84  	*KadParams          // Kademlia configuration parameters
    85  	base       []byte   // immutable baseaddress of the table
    86  	addrs      *pot.Pot // pots container for known peer addresses
    87  	conns      *pot.Pot // pots container for live peer connections
    88  	depth      uint8    // stores the last current depth of saturation
    89  	nDepth     int      // stores the last neighbourhood depth
    90  	nDepthC    chan int // returned by DepthC function to signal neighbourhood depth change
    91  	addrCountC chan int // returned by AddrCountC function to signal peer count change
    92  }
    93  
    94  // NewKademlia creates a Kademlia table for base address addr
    95  // with parameters as in params
    96  // if params is nil, it uses default values
    97  func NewKademlia(addr []byte, params *KadParams) *Kademlia {
    98  	if params == nil {
    99  		params = NewKadParams()
   100  	}
   101  	return &Kademlia{
   102  		base:      addr,
   103  		KadParams: params,
   104  		addrs:     pot.NewPot(nil, 0),
   105  		conns:     pot.NewPot(nil, 0),
   106  	}
   107  }
   108  
   109  // OverlayPeer interface captures the common aspect of view of a peer from the Overlay
   110  // topology driver
   111  type OverlayPeer interface {
   112  	Address() []byte
   113  }
   114  
   115  // OverlayConn represents a connected peer
   116  type OverlayConn interface {
   117  	OverlayPeer
   118  	Drop(error)       // call to indicate a peer should be expunged
   119  	Off() OverlayAddr // call to return a persitent OverlayAddr
   120  }
   121  
   122  // OverlayAddr represents a kademlia peer record
   123  type OverlayAddr interface {
   124  	OverlayPeer
   125  	Update(OverlayAddr) OverlayAddr // returns the updated version of the original
   126  }
   127  
   128  // entry represents a Kademlia table entry (an extension of OverlayPeer)
   129  type entry struct {
   130  	OverlayPeer
   131  	seenAt  time.Time
   132  	retries int
   133  }
   134  
   135  // newEntry creates a kademlia peer from an OverlayPeer interface
   136  func newEntry(p OverlayPeer) *entry {
   137  	return &entry{
   138  		OverlayPeer: p,
   139  		seenAt:      time.Now(),
   140  	}
   141  }
   142  
   143  // Bin is the binary (bitvector) serialisation of the entry address
   144  func (e *entry) Bin() string {
   145  	return pot.ToBin(e.addr().Address())
   146  }
   147  
   148  // Label is a short tag for the entry for debug
   149  func Label(e *entry) string {
   150  	return fmt.Sprintf("%s (%d)", e.Hex()[:4], e.retries)
   151  }
   152  
   153  // Hex is the hexadecimal serialisation of the entry address
   154  func (e *entry) Hex() string {
   155  	return fmt.Sprintf("%x", e.addr().Address())
   156  }
   157  
   158  // String is the short tag for the entry
   159  func (e *entry) String() string {
   160  	return fmt.Sprintf("%s (%d)", e.Hex()[:8], e.retries)
   161  }
   162  
   163  // addr returns the kad peer record (OverlayAddr) corresponding to the entry
   164  func (e *entry) addr() OverlayAddr {
   165  	a, _ := e.OverlayPeer.(OverlayAddr)
   166  	return a
   167  }
   168  
   169  // conn returns the connected peer (OverlayPeer) corresponding to the entry
   170  func (e *entry) conn() OverlayConn {
   171  	c, _ := e.OverlayPeer.(OverlayConn)
   172  	return c
   173  }
   174  
   175  // Register enters each OverlayAddr as kademlia peer record into the
   176  // database of known peer addresses
   177  func (k *Kademlia) Register(peers []OverlayAddr) error {
   178  	k.lock.Lock()
   179  	defer k.lock.Unlock()
   180  	var known, size int
   181  	for _, p := range peers {
   182  		// error if self received, peer should know better
   183  		// and should be punished for this
   184  		if bytes.Equal(p.Address(), k.base) {
   185  			return fmt.Errorf("add peers: %x is self", k.base)
   186  		}
   187  		var found bool
   188  		k.addrs, _, found, _ = pot.Swap(k.addrs, p, pof, func(v pot.Val) pot.Val {
   189  			// if not found
   190  			if v == nil {
   191  				// insert new offline peer into conns
   192  				return newEntry(p)
   193  			}
   194  			// found among known peers, do nothing
   195  			return v
   196  		})
   197  		if found {
   198  			known++
   199  		}
   200  		size++
   201  	}
   202  	// send new address count value only if there are new addresses
   203  	if k.addrCountC != nil && size-known > 0 {
   204  		k.addrCountC <- k.addrs.Size()
   205  	}
   206  	// log.Trace(fmt.Sprintf("%x registered %v peers, %v known, total: %v", k.BaseAddr()[:4], size, known, k.addrs.Size()))
   207  
   208  	k.sendNeighbourhoodDepthChange()
   209  	return nil
   210  }
   211  
   212  // SuggestPeer returns a known peer for the lowest proximity bin for the
   213  // lowest bincount below depth
   214  // naturally if there is an empty row it returns a peer for that
   215  func (k *Kademlia) SuggestPeer() (a OverlayAddr, o int, want bool) {
   216  	k.lock.Lock()
   217  	defer k.lock.Unlock()
   218  	minsize := k.MinBinSize
   219  	depth := k.neighbourhoodDepth()
   220  	// if there is a callable neighbour within the current proxBin, connect
   221  	// this makes sure nearest neighbour set is fully connected
   222  	var ppo int
   223  	k.addrs.EachNeighbour(k.base, pof, func(val pot.Val, po int) bool {
   224  		if po < depth {
   225  			return false
   226  		}
   227  		a = k.callable(val)
   228  		ppo = po
   229  		return a == nil
   230  	})
   231  	if a != nil {
   232  		log.Trace(fmt.Sprintf("%08x candidate nearest neighbour found: %v (%v)", k.BaseAddr()[:4], a, ppo))
   233  		return a, 0, false
   234  	}
   235  	// log.Trace(fmt.Sprintf("%08x no candidate nearest neighbours to connect to (Depth: %v, minProxSize: %v) %#v", k.BaseAddr()[:4], depth, k.MinProxBinSize, a))
   236  
   237  	var bpo []int
   238  	prev := -1
   239  	k.conns.EachBin(k.base, pof, 0, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool {
   240  		prev++
   241  		for ; prev < po; prev++ {
   242  			bpo = append(bpo, prev)
   243  			minsize = 0
   244  		}
   245  		if size < minsize {
   246  			bpo = append(bpo, po)
   247  			minsize = size
   248  		}
   249  		return size > 0 && po < depth
   250  	})
   251  	// all buckets are full, ie., minsize == k.MinBinSize
   252  	if len(bpo) == 0 {
   253  		// log.Debug(fmt.Sprintf("%08x: all bins saturated", k.BaseAddr()[:4]))
   254  		return nil, 0, false
   255  	}
   256  	// as long as we got candidate peers to connect to
   257  	// dont ask for new peers (want = false)
   258  	// try to select a candidate peer
   259  	// find the first callable peer
   260  	nxt := bpo[0]
   261  	k.addrs.EachBin(k.base, pof, nxt, func(po, _ int, f func(func(pot.Val, int) bool) bool) bool {
   262  		// for each bin (up until depth) we find callable candidate peers
   263  		if po >= depth {
   264  			return false
   265  		}
   266  		return f(func(val pot.Val, _ int) bool {
   267  			a = k.callable(val)
   268  			return a == nil
   269  		})
   270  	})
   271  	// found a candidate
   272  	if a != nil {
   273  		return a, 0, false
   274  	}
   275  	// no candidate peer found, request for the short bin
   276  	var changed bool
   277  	if uint8(nxt) < k.depth {
   278  		k.depth = uint8(nxt)
   279  		changed = true
   280  	}
   281  	return a, nxt, changed
   282  }
   283  
   284  // On inserts the peer as a kademlia peer into the live peers
   285  func (k *Kademlia) On(p OverlayConn) (uint8, bool) {
   286  	k.lock.Lock()
   287  	defer k.lock.Unlock()
   288  	e := newEntry(p)
   289  	var ins bool
   290  	k.conns, _, _, _ = pot.Swap(k.conns, p, pof, func(v pot.Val) pot.Val {
   291  		// if not found live
   292  		if v == nil {
   293  			ins = true
   294  			// insert new online peer into conns
   295  			return e
   296  		}
   297  		// found among live peers, do nothing
   298  		return v
   299  	})
   300  	if ins {
   301  		// insert new online peer into addrs
   302  		k.addrs, _, _, _ = pot.Swap(k.addrs, p, pof, func(v pot.Val) pot.Val {
   303  			return e
   304  		})
   305  		// send new address count value only if the peer is inserted
   306  		if k.addrCountC != nil {
   307  			k.addrCountC <- k.addrs.Size()
   308  		}
   309  	}
   310  	log.Trace(k.string())
   311  	// calculate if depth of saturation changed
   312  	depth := uint8(k.saturation(k.MinBinSize))
   313  	var changed bool
   314  	if depth != k.depth {
   315  		changed = true
   316  		k.depth = depth
   317  	}
   318  	k.sendNeighbourhoodDepthChange()
   319  	return k.depth, changed
   320  }
   321  
   322  // NeighbourhoodDepthC returns the channel that sends a new kademlia
   323  // neighbourhood depth on each change.
   324  // Not receiving from the returned channel will block On function
   325  // when the neighbourhood depth is changed.
   326  func (k *Kademlia) NeighbourhoodDepthC() <-chan int {
   327  	if k.nDepthC == nil {
   328  		k.nDepthC = make(chan int)
   329  	}
   330  	return k.nDepthC
   331  }
   332  
   333  // sendNeighbourhoodDepthChange sends new neighbourhood depth to k.nDepth channel
   334  // if it is initialized.
   335  func (k *Kademlia) sendNeighbourhoodDepthChange() {
   336  	// nDepthC is initialized when NeighbourhoodDepthC is called and returned by it.
   337  	// It provides signaling of neighbourhood depth change.
   338  	// This part of the code is sending new neighbourhood depth to nDepthC if that condition is met.
   339  	if k.nDepthC != nil {
   340  		nDepth := k.neighbourhoodDepth()
   341  		if nDepth != k.nDepth {
   342  			k.nDepth = nDepth
   343  			k.nDepthC <- nDepth
   344  		}
   345  	}
   346  }
   347  
   348  // AddrCountC returns the channel that sends a new
   349  // address count value on each change.
   350  // Not receiving from the returned channel will block Register function
   351  // when address count value changes.
   352  func (k *Kademlia) AddrCountC() <-chan int {
   353  	if k.addrCountC == nil {
   354  		k.addrCountC = make(chan int)
   355  	}
   356  	return k.addrCountC
   357  }
   358  
   359  // Off removes a peer from among live peers
   360  func (k *Kademlia) Off(p OverlayConn) {
   361  	k.lock.Lock()
   362  	defer k.lock.Unlock()
   363  	var del bool
   364  	k.addrs, _, _, _ = pot.Swap(k.addrs, p, pof, func(v pot.Val) pot.Val {
   365  		// v cannot be nil, must check otherwise we overwrite entry
   366  		if v == nil {
   367  			panic(fmt.Sprintf("connected peer not found %v", p))
   368  		}
   369  		del = true
   370  		return newEntry(p.Off())
   371  	})
   372  
   373  	if del {
   374  		k.conns, _, _, _ = pot.Swap(k.conns, p, pof, func(_ pot.Val) pot.Val {
   375  			// v cannot be nil, but no need to check
   376  			return nil
   377  		})
   378  		// send new address count value only if the peer is deleted
   379  		if k.addrCountC != nil {
   380  			k.addrCountC <- k.addrs.Size()
   381  		}
   382  		k.sendNeighbourhoodDepthChange()
   383  	}
   384  }
   385  
   386  func (k *Kademlia) EachBin(base []byte, pof pot.Pof, o int, eachBinFunc func(conn OverlayConn, po int) bool) {
   387  	k.lock.RLock()
   388  	defer k.lock.RUnlock()
   389  
   390  	var startPo int
   391  	var endPo int
   392  	kadDepth := k.neighbourhoodDepth()
   393  
   394  	k.conns.EachBin(base, pof, o, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool {
   395  		if startPo > 0 && endPo != k.MaxProxDisplay {
   396  			startPo = endPo + 1
   397  		}
   398  		if po < kadDepth {
   399  			endPo = po
   400  		} else {
   401  			endPo = k.MaxProxDisplay
   402  		}
   403  
   404  		for bin := startPo; bin <= endPo; bin++ {
   405  			f(func(val pot.Val, _ int) bool {
   406  				return eachBinFunc(val.(*entry).conn(), bin)
   407  			})
   408  		}
   409  		return true
   410  	})
   411  }
   412  
   413  // EachConn is an iterator with args (base, po, f) applies f to each live peer
   414  // that has proximity order po or less as measured from the base
   415  // if base is nil, kademlia base address is used
   416  func (k *Kademlia) EachConn(base []byte, o int, f func(OverlayConn, int, bool) bool) {
   417  	k.lock.RLock()
   418  	defer k.lock.RUnlock()
   419  	k.eachConn(base, o, f)
   420  }
   421  
   422  func (k *Kademlia) eachConn(base []byte, o int, f func(OverlayConn, int, bool) bool) {
   423  	if len(base) == 0 {
   424  		base = k.base
   425  	}
   426  	depth := k.neighbourhoodDepth()
   427  	k.conns.EachNeighbour(base, pof, func(val pot.Val, po int) bool {
   428  		if po > o {
   429  			return true
   430  		}
   431  		return f(val.(*entry).conn(), po, po >= depth)
   432  	})
   433  }
   434  
   435  // EachAddr called with (base, po, f) is an iterator applying f to each known peer
   436  // that has proximity order po or less as measured from the base
   437  // if base is nil, kademlia base address is used
   438  func (k *Kademlia) EachAddr(base []byte, o int, f func(OverlayAddr, int, bool) bool) {
   439  	k.lock.RLock()
   440  	defer k.lock.RUnlock()
   441  	k.eachAddr(base, o, f)
   442  }
   443  
   444  func (k *Kademlia) eachAddr(base []byte, o int, f func(OverlayAddr, int, bool) bool) {
   445  	if len(base) == 0 {
   446  		base = k.base
   447  	}
   448  	depth := k.neighbourhoodDepth()
   449  	k.addrs.EachNeighbour(base, pof, func(val pot.Val, po int) bool {
   450  		if po > o {
   451  			return true
   452  		}
   453  		return f(val.(*entry).addr(), po, po >= depth)
   454  	})
   455  }
   456  
   457  // neighbourhoodDepth returns the proximity order that defines the distance of
   458  // the nearest neighbour set with cardinality >= MinProxBinSize
   459  // if there is altogather less than MinProxBinSize peers it returns 0
   460  // caller must hold the lock
   461  func (k *Kademlia) neighbourhoodDepth() (depth int) {
   462  	if k.conns.Size() < k.MinProxBinSize {
   463  		return 0
   464  	}
   465  	var size int
   466  	f := func(v pot.Val, i int) bool {
   467  		size++
   468  		depth = i
   469  		return size < k.MinProxBinSize
   470  	}
   471  	k.conns.EachNeighbour(k.base, pof, f)
   472  	return depth
   473  }
   474  
   475  // callable when called with val,
   476  func (k *Kademlia) callable(val pot.Val) OverlayAddr {
   477  	e := val.(*entry)
   478  	// not callable if peer is live or exceeded maxRetries
   479  	if e.conn() != nil || e.retries > k.MaxRetries {
   480  		return nil
   481  	}
   482  	// calculate the allowed number of retries based on time lapsed since last seen
   483  	timeAgo := int64(time.Since(e.seenAt))
   484  	div := int64(k.RetryExponent)
   485  	div += (150000 - rand.Int63n(300000)) * div / 1000000
   486  	var retries int
   487  	for delta := timeAgo; delta > k.RetryInterval; delta /= div {
   488  		retries++
   489  	}
   490  	// this is never called concurrently, so safe to increment
   491  	// peer can be retried again
   492  	if retries < e.retries {
   493  		log.Trace(fmt.Sprintf("%08x: %v long time since last try (at %v) needed before retry %v, wait only warrants %v", k.BaseAddr()[:4], e, timeAgo, e.retries, retries))
   494  		return nil
   495  	}
   496  	// function to sanction or prevent suggesting a peer
   497  	if k.Reachable != nil && !k.Reachable(e.addr()) {
   498  		log.Trace(fmt.Sprintf("%08x: peer %v is temporarily not callable", k.BaseAddr()[:4], e))
   499  		return nil
   500  	}
   501  	e.retries++
   502  	log.Trace(fmt.Sprintf("%08x: peer %v is callable", k.BaseAddr()[:4], e))
   503  
   504  	return e.addr()
   505  }
   506  
   507  // BaseAddr return the kademlia base address
   508  func (k *Kademlia) BaseAddr() []byte {
   509  	return k.base
   510  }
   511  
   512  // String returns kademlia table + kaddb table displayed with ascii
   513  func (k *Kademlia) String() string {
   514  	k.lock.RLock()
   515  	defer k.lock.RUnlock()
   516  	return k.string()
   517  }
   518  
   519  // String returns kademlia table + kaddb table displayed with ascii
   520  func (k *Kademlia) string() string {
   521  	wsrow := "                          "
   522  	var rows []string
   523  
   524  	rows = append(rows, "=========================================================================")
   525  	rows = append(rows, fmt.Sprintf("%v KΛÐΞMLIΛ hive: queen's address: %x", time.Now().UTC().Format(time.UnixDate), k.BaseAddr()[:3]))
   526  	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))
   527  
   528  	liverows := make([]string, k.MaxProxDisplay)
   529  	peersrows := make([]string, k.MaxProxDisplay)
   530  
   531  	depth := k.neighbourhoodDepth()
   532  	rest := k.conns.Size()
   533  	k.conns.EachBin(k.base, pof, 0, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool {
   534  		var rowlen int
   535  		if po >= k.MaxProxDisplay {
   536  			po = k.MaxProxDisplay - 1
   537  		}
   538  		row := []string{fmt.Sprintf("%2d", size)}
   539  		rest -= size
   540  		f(func(val pot.Val, vpo int) bool {
   541  			e := val.(*entry)
   542  			row = append(row, fmt.Sprintf("%x", e.Address()[:2]))
   543  			rowlen++
   544  			return rowlen < 4
   545  		})
   546  		r := strings.Join(row, " ")
   547  		r = r + wsrow
   548  		liverows[po] = r[:31]
   549  		return true
   550  	})
   551  
   552  	k.addrs.EachBin(k.base, pof, 0, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool {
   553  		var rowlen int
   554  		if po >= k.MaxProxDisplay {
   555  			po = k.MaxProxDisplay - 1
   556  		}
   557  		if size < 0 {
   558  			panic("wtf")
   559  		}
   560  		row := []string{fmt.Sprintf("%2d", size)}
   561  		// we are displaying live peers too
   562  		f(func(val pot.Val, vpo int) bool {
   563  			e := val.(*entry)
   564  			row = append(row, Label(e))
   565  			rowlen++
   566  			return rowlen < 4
   567  		})
   568  		peersrows[po] = strings.Join(row, " ")
   569  		return true
   570  	})
   571  
   572  	for i := 0; i < k.MaxProxDisplay; i++ {
   573  		if i == depth {
   574  			rows = append(rows, fmt.Sprintf("============ DEPTH: %d ==========================================", i))
   575  		}
   576  		left := liverows[i]
   577  		right := peersrows[i]
   578  		if len(left) == 0 {
   579  			left = " 0                             "
   580  		}
   581  		if len(right) == 0 {
   582  			right = " 0"
   583  		}
   584  		rows = append(rows, fmt.Sprintf("%03d %v | %v", i, left, right))
   585  	}
   586  	rows = append(rows, "=========================================================================")
   587  	return "\n" + strings.Join(rows, "\n")
   588  }
   589  
   590  // PeerPot keeps info about expected nearest neighbours and empty bins
   591  // used for testing only
   592  type PeerPot struct {
   593  	NNSet     [][]byte
   594  	EmptyBins []int
   595  }
   596  
   597  // NewPeerPotMap creates a map of pot record of OverlayAddr with keys
   598  // as hexadecimal representations of the address.
   599  func NewPeerPotMap(kadMinProxSize int, addrs [][]byte) map[string]*PeerPot {
   600  	// create a table of all nodes for health check
   601  	np := pot.NewPot(nil, 0)
   602  	for _, addr := range addrs {
   603  		np, _, _ = pot.Add(np, addr, pof)
   604  	}
   605  	ppmap := make(map[string]*PeerPot)
   606  
   607  	for i, a := range addrs {
   608  		pl := 256
   609  		prev := 256
   610  		var emptyBins []int
   611  		var nns [][]byte
   612  		np.EachNeighbour(addrs[i], pof, func(val pot.Val, po int) bool {
   613  			a := val.([]byte)
   614  			if po == 256 {
   615  				return true
   616  			}
   617  			if pl == 256 || pl == po {
   618  				nns = append(nns, a)
   619  			}
   620  			if pl == 256 && len(nns) >= kadMinProxSize {
   621  				pl = po
   622  				prev = po
   623  			}
   624  			if prev < pl {
   625  				for j := prev; j > po; j-- {
   626  					emptyBins = append(emptyBins, j)
   627  				}
   628  			}
   629  			prev = po - 1
   630  			return true
   631  		})
   632  		for j := prev; j >= 0; j-- {
   633  			emptyBins = append(emptyBins, j)
   634  		}
   635  		log.Trace(fmt.Sprintf("%x NNS: %s", addrs[i][:4], LogAddrs(nns)))
   636  		ppmap[common.Bytes2Hex(a)] = &PeerPot{nns, emptyBins}
   637  	}
   638  	return ppmap
   639  }
   640  
   641  // saturation returns the lowest proximity order that the bin for that order
   642  // has less than n peers
   643  func (k *Kademlia) saturation(n int) int {
   644  	prev := -1
   645  	k.addrs.EachBin(k.base, pof, 0, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool {
   646  		prev++
   647  		return prev == po && size >= n
   648  	})
   649  	depth := k.neighbourhoodDepth()
   650  	if depth < prev {
   651  		return depth
   652  	}
   653  	return prev
   654  }
   655  
   656  // full returns true if all required bins have connected peers.
   657  // It is used in Healthy function.
   658  func (k *Kademlia) full(emptyBins []int) (full bool) {
   659  	prev := 0
   660  	e := len(emptyBins)
   661  	ok := true
   662  	depth := k.neighbourhoodDepth()
   663  	k.conns.EachBin(k.base, pof, 0, func(po, _ int, _ func(func(val pot.Val, i int) bool) bool) bool {
   664  		if prev == depth+1 {
   665  			return true
   666  		}
   667  		for i := prev; i < po; i++ {
   668  			e--
   669  			if e < 0 {
   670  				ok = false
   671  				return false
   672  			}
   673  			if emptyBins[e] != i {
   674  				log.Trace(fmt.Sprintf("%08x po: %d, i: %d, e: %d, emptybins: %v", k.BaseAddr()[:4], po, i, e, logEmptyBins(emptyBins)))
   675  				if emptyBins[e] < i {
   676  					panic("incorrect peerpot")
   677  				}
   678  				ok = false
   679  				return false
   680  			}
   681  		}
   682  		prev = po + 1
   683  		return true
   684  	})
   685  	if !ok {
   686  		return false
   687  	}
   688  	return e == 0
   689  }
   690  
   691  func (k *Kademlia) knowNearestNeighbours(peers [][]byte) bool {
   692  	pm := make(map[string]bool)
   693  
   694  	k.eachAddr(nil, 255, func(p OverlayAddr, po int, nn bool) bool {
   695  		if !nn {
   696  			return false
   697  		}
   698  		pk := fmt.Sprintf("%x", p.Address())
   699  		pm[pk] = true
   700  		return true
   701  	})
   702  	for _, p := range peers {
   703  		pk := fmt.Sprintf("%x", p)
   704  		if !pm[pk] {
   705  			log.Trace(fmt.Sprintf("%08x: known nearest neighbour %s not found", k.BaseAddr()[:4], pk[:8]))
   706  			return false
   707  		}
   708  	}
   709  	return true
   710  }
   711  
   712  func (k *Kademlia) gotNearestNeighbours(peers [][]byte) (got bool, n int, missing [][]byte) {
   713  	pm := make(map[string]bool)
   714  
   715  	k.eachConn(nil, 255, func(p OverlayConn, po int, nn bool) bool {
   716  		if !nn {
   717  			return false
   718  		}
   719  		pk := fmt.Sprintf("%x", p.Address())
   720  		pm[pk] = true
   721  		return true
   722  	})
   723  	var gots int
   724  	var culprits [][]byte
   725  	for _, p := range peers {
   726  		pk := fmt.Sprintf("%x", p)
   727  		if pm[pk] {
   728  			gots++
   729  		} else {
   730  			log.Trace(fmt.Sprintf("%08x: ExpNN: %s not found", k.BaseAddr()[:4], pk[:8]))
   731  			culprits = append(culprits, p)
   732  		}
   733  	}
   734  	return gots == len(peers), gots, culprits
   735  }
   736  
   737  // Health state of the Kademlia
   738  type Health struct {
   739  	KnowNN     bool     // whather node knows all its nearest neighbours
   740  	GotNN      bool     // whather node is connected to all its nearest neighbours
   741  	CountNN    int      // amount of nearest neighbors connected to
   742  	CulpritsNN [][]byte // which known NNs are missing
   743  	Full       bool     // whather node has a peer in each kademlia bin (where there is such a peer)
   744  	Hive       string
   745  }
   746  
   747  // Healthy reports the health state of the kademlia connectivity
   748  // returns a Health struct
   749  func (k *Kademlia) Healthy(pp *PeerPot) *Health {
   750  	k.lock.RLock()
   751  	defer k.lock.RUnlock()
   752  	gotnn, countnn, culpritsnn := k.gotNearestNeighbours(pp.NNSet)
   753  	knownn := k.knowNearestNeighbours(pp.NNSet)
   754  	full := k.full(pp.EmptyBins)
   755  	log.Trace(fmt.Sprintf("%08x: healthy: knowNNs: %v, gotNNs: %v, full: %v\n", k.BaseAddr()[:4], knownn, gotnn, full))
   756  	return &Health{knownn, gotnn, countnn, culpritsnn, full, k.string()}
   757  }
   758  
   759  func logEmptyBins(ebs []int) string {
   760  	var ebss []string
   761  	for _, eb := range ebs {
   762  		ebss = append(ebss, fmt.Sprintf("%d", eb))
   763  	}
   764  	return strings.Join(ebss, ", ")
   765  }