github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/network/kademlia.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2017 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package network
    26  
    27  import (
    28  	"bytes"
    29  	"fmt"
    30  	"math/rand"
    31  	"strings"
    32  	"sync"
    33  	"time"
    34  
    35  	"github.com/ethereum/go-ethereum/common"
    36  	"github.com/ethereum/go-ethereum/swarm/log"
    37  	"github.com/ethereum/go-ethereum/swarm/pot"
    38  )
    39  
    40  /*
    41  
    42  根据相对于固定点X的接近顺序,将点分类为
    43  将空间(n字节长的字节序列)放入容器中。每个项目位于
    44  最远距离X的一半是前一个箱中的项目。给出了一个
    45  均匀分布项(任意序列上的哈希函数)
    46  接近比例映射到一系列子集上,基数为负
    47  指数尺度。
    48  
    49  它还具有属于同一存储箱的任何两个项目所在的属性。
    50  最远的距离是彼此距离x的一半。
    51  
    52  如果我们把垃圾箱中的随机样本看作是网络中的连接,
    53  互联节点的相对邻近性可以作为局部
    54  当任务要在两个路径之间查找路径时,用于图形遍历的决策
    55  点。因为在每个跳跃中,有限距离的一半
    56  达到一个跳数所需的保证不变的最大跳数限制。
    57  节点。
    58  **/
    59  
    60  
    61  var pof = pot.DefaultPof(256)
    62  
    63  //kadparams保存kademlia的配置参数
    64  type KadParams struct {
    65  //可调参数
    66  MaxProxDisplay int   //表显示的行数
    67  MinProxBinSize int   //最近邻核最小基数
    68  MinBinSize     int   //一行中的最小对等数
    69  MaxBinSize     int   //修剪前一行中的最大对等数
    70  RetryInterval  int64 //对等机首次重新拨号前的初始间隔
    71  RetryExponent  int   //用指数乘以重试间隔
    72  MaxRetries     int   //重拨尝试的最大次数
    73  //制裁或阻止建议同伴的职能
    74  	Reachable func(OverlayAddr) bool
    75  }
    76  
    77  //newkadparams返回带有默认值的params结构
    78  func NewKadParams() *KadParams {
    79  	return &KadParams{
    80  		MaxProxDisplay: 16,
    81  		MinProxBinSize: 2,
    82  		MinBinSize:     2,
    83  		MaxBinSize:     4,
    84  RetryInterval:  4200000000, //4.2秒
    85  		MaxRetries:     42,
    86  		RetryExponent:  2,
    87  	}
    88  }
    89  
    90  //Kademlia是一个活动对等端表和一个已知对等端数据库(节点记录)
    91  type Kademlia struct {
    92  	lock       sync.RWMutex
    93  *KadParams          //Kademlia配置参数
    94  base       []byte   //表的不可变基址
    95  addrs      *pot.Pot //用于已知对等地址的POTS容器
    96  conns      *pot.Pot //用于实时对等连接的POTS容器
    97  depth      uint8    //存储上一个当前饱和深度
    98  nDepth     int      //存储上一个邻居深度
    99  nDepthC    chan int //由depthc函数返回,用于信号邻域深度变化
   100  addrCountC chan int //由addrcountc函数返回以指示对等计数更改
   101  }
   102  
   103  //newkademlia为基地址addr创建一个kademlia表
   104  //参数与参数相同
   105  //如果params为nil,则使用默认值
   106  func NewKademlia(addr []byte, params *KadParams) *Kademlia {
   107  	if params == nil {
   108  		params = NewKadParams()
   109  	}
   110  	return &Kademlia{
   111  		base:      addr,
   112  		KadParams: params,
   113  		addrs:     pot.NewPot(nil, 0),
   114  		conns:     pot.NewPot(nil, 0),
   115  	}
   116  }
   117  
   118  //覆盖对等接口从覆盖中捕获对等视图的公共方面
   119  //拓扑驱动程序
   120  type OverlayPeer interface {
   121  	Address() []byte
   122  }
   123  
   124  //overlayconn表示连接的对等机
   125  type OverlayConn interface {
   126  	OverlayPeer
   127  Drop(error)       //调用以指示应删除对等项
   128  Off() OverlayAddr //调用以返回Persistant OverlayAddr
   129  }
   130  
   131  //overlayAddr表示Kademlia对等记录
   132  type OverlayAddr interface {
   133  	OverlayPeer
   134  Update(OverlayAddr) OverlayAddr //返回原始版本的更新版本
   135  }
   136  
   137  //条目表示一个kademlia表条目(overlaypeer的扩展)
   138  type entry struct {
   139  	OverlayPeer
   140  	seenAt  time.Time
   141  	retries int
   142  }
   143  
   144  //NewEntry从重叠对等接口创建Kademlia对等
   145  func newEntry(p OverlayPeer) *entry {
   146  	return &entry{
   147  		OverlayPeer: p,
   148  		seenAt:      time.Now(),
   149  	}
   150  }
   151  
   152  //bin是入口地址的二进制(位向量)序列化
   153  func (e *entry) Bin() string {
   154  	return pot.ToBin(e.addr().Address())
   155  }
   156  
   157  //label是调试条目的短标记
   158  func Label(e *entry) string {
   159  	return fmt.Sprintf("%s (%d)", e.Hex()[:4], e.retries)
   160  }
   161  
   162  //十六进制是入口地址的十六进制序列化
   163  func (e *entry) Hex() string {
   164  	return fmt.Sprintf("%x", e.addr().Address())
   165  }
   166  
   167  //字符串是条目的短标记
   168  func (e *entry) String() string {
   169  	return fmt.Sprintf("%s (%d)", e.Hex()[:8], e.retries)
   170  }
   171  
   172  //addr返回条目对应的kad对等记录(overlayaddr)
   173  func (e *entry) addr() OverlayAddr {
   174  	a, _ := e.OverlayPeer.(OverlayAddr)
   175  	return a
   176  }
   177  
   178  //conn返回与条目相对应的已连接对等(overlaypeer)
   179  func (e *entry) conn() OverlayConn {
   180  	c, _ := e.OverlayPeer.(OverlayConn)
   181  	return c
   182  }
   183  
   184  //寄存器将每个overlayaddr作为kademlia对等记录输入
   185  //已知对等地址数据库
   186  func (k *Kademlia) Register(peers []OverlayAddr) error {
   187  	k.lock.Lock()
   188  	defer k.lock.Unlock()
   189  	var known, size int
   190  	for _, p := range peers {
   191  //如果自我接收错误,对等方应该知道得更好。
   192  //应该为此受到惩罚
   193  		if bytes.Equal(p.Address(), k.base) {
   194  			return fmt.Errorf("add peers: %x is self", k.base)
   195  		}
   196  		var found bool
   197  		k.addrs, _, found, _ = pot.Swap(k.addrs, p, pof, func(v pot.Val) pot.Val {
   198  //如果没有找到
   199  			if v == nil {
   200  //在conn中插入新的脱机对等
   201  				return newEntry(p)
   202  			}
   203  //在已知的同龄人中发现,什么都不做
   204  			return v
   205  		})
   206  		if found {
   207  			known++
   208  		}
   209  		size++
   210  	}
   211  //仅当有新地址时才发送新地址计数值
   212  	if k.addrCountC != nil && size-known > 0 {
   213  		k.addrCountC <- k.addrs.Size()
   214  	}
   215  //log.trace(fmt.sprintf(“%x注册了%v个对等点,已知的%v个,总数:%v”,k.baseaddr()[:4],大小,已知的,k.addrs.size()))
   216  
   217  	k.sendNeighbourhoodDepthChange()
   218  	return nil
   219  }
   220  
   221  //suggestpeer返回的最低接近箱的已知对等
   222  //深度以下的最低料位计数
   223  //当然,如果有一个空行,它将返回该行的对等方
   224  func (k *Kademlia) SuggestPeer() (a OverlayAddr, o int, want bool) {
   225  	k.lock.Lock()
   226  	defer k.lock.Unlock()
   227  	minsize := k.MinBinSize
   228  	depth := k.neighbourhoodDepth()
   229  //如果当前proxbin中存在可调用邻居,请连接
   230  //这将确保最近的邻居集完全连接
   231  	var ppo int
   232  	k.addrs.EachNeighbour(k.base, pof, func(val pot.Val, po int) bool {
   233  		if po < depth {
   234  			return false
   235  		}
   236  		a = k.callable(val)
   237  		ppo = po
   238  		return a == nil
   239  	})
   240  	if a != nil {
   241  		log.Trace(fmt.Sprintf("%08x candidate nearest neighbour found: %v (%v)", k.BaseAddr()[:4], a, ppo))
   242  		return a, 0, false
   243  	}
   244  //log.trace(fmt.sprintf(“%08X没有要连接到的最近邻居(深度:%v,minproxySize:%v)%v”,k.baseAddr()[:4],深度,k.minproxyBinSize,a))。
   245  
   246  	var bpo []int
   247  	prev := -1
   248  	k.conns.EachBin(k.base, pof, 0, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool {
   249  		prev++
   250  		for ; prev < po; prev++ {
   251  			bpo = append(bpo, prev)
   252  			minsize = 0
   253  		}
   254  		if size < minsize {
   255  			bpo = append(bpo, po)
   256  			minsize = size
   257  		}
   258  		return size > 0 && po < depth
   259  	})
   260  //所有桶都满了,即minSize==k.minBinSize
   261  	if len(bpo) == 0 {
   262  //log.debug(fmt.sprintf(“%08X:所有箱已饱和”,k.baseaddr()[:4]))
   263  		return nil, 0, false
   264  	}
   265  //只要我们有候选者可以联系到
   266  //不要要求新同事(want=false)
   267  //尝试选择一个候选对等
   268  //找到第一个可调用的对等
   269  	nxt := bpo[0]
   270  	k.addrs.EachBin(k.base, pof, nxt, func(po, _ int, f func(func(pot.Val, int) bool) bool) bool {
   271  //对于每个容器(直到深度),我们找到可调用的候选对等体
   272  		if po >= depth {
   273  			return false
   274  		}
   275  		return f(func(val pot.Val, _ int) bool {
   276  			a = k.callable(val)
   277  			return a == nil
   278  		})
   279  	})
   280  //找到一个候选人
   281  	if a != nil {
   282  		return a, 0, false
   283  	}
   284  //找不到候选对等,请求短箱
   285  	var changed bool
   286  	if uint8(nxt) < k.depth {
   287  		k.depth = uint8(nxt)
   288  		changed = true
   289  	}
   290  	return a, nxt, changed
   291  }
   292  
   293  //在上,将对等机作为Kademlia对等机插入活动对等机
   294  func (k *Kademlia) On(p OverlayConn) (uint8, bool) {
   295  	k.lock.Lock()
   296  	defer k.lock.Unlock()
   297  	e := newEntry(p)
   298  	var ins bool
   299  	k.conns, _, _, _ = pot.Swap(k.conns, p, pof, func(v pot.Val) pot.Val {
   300  //如果找不到现场
   301  		if v == nil {
   302  			ins = true
   303  //在conns中插入新的在线对等点
   304  			return e
   305  		}
   306  //在同龄人中找到,什么都不做
   307  		return v
   308  	})
   309  	if ins {
   310  //在加法器中插入新的在线对等点
   311  		k.addrs, _, _, _ = pot.Swap(k.addrs, p, pof, func(v pot.Val) pot.Val {
   312  			return e
   313  		})
   314  //仅当插入对等端时才发送新的地址计数值
   315  		if k.addrCountC != nil {
   316  			k.addrCountC <- k.addrs.Size()
   317  		}
   318  	}
   319  	log.Trace(k.string())
   320  //计算饱和深度是否改变
   321  	depth := uint8(k.saturation(k.MinBinSize))
   322  	var changed bool
   323  	if depth != k.depth {
   324  		changed = true
   325  		k.depth = depth
   326  	}
   327  	k.sendNeighbourhoodDepthChange()
   328  	return k.depth, changed
   329  }
   330  
   331  //Neighbourhooddepthc返回发送新Kademlia的频道
   332  //每一次变化的邻里深度。
   333  //不从返回通道接收将阻塞功能
   334  //当邻近深度改变时。
   335  func (k *Kademlia) NeighbourhoodDepthC() <-chan int {
   336  	if k.nDepthC == nil {
   337  		k.nDepthC = make(chan int)
   338  	}
   339  	return k.nDepthC
   340  }
   341  
   342  //sendnieghbourhooddepthchange向k.ndepth通道发送新的邻近深度
   343  //如果已初始化。
   344  func (k *Kademlia) sendNeighbourhoodDepthChange() {
   345  //当调用neighbourhooddepthc并由其返回时,将初始化ndepthc。
   346  //它提供了邻域深度变化的信号。
   347  //如果满足这个条件,代码的这一部分将向ndepthc发送新的邻域深度。
   348  	if k.nDepthC != nil {
   349  		nDepth := k.neighbourhoodDepth()
   350  		if nDepth != k.nDepth {
   351  			k.nDepth = nDepth
   352  			k.nDepthC <- nDepth
   353  		}
   354  	}
   355  }
   356  
   357  //addrCountc返回发送新的
   358  //每次更改的地址计数值。
   359  //不从返回通道接收将阻止寄存器功能
   360  //地址计数值更改时。
   361  func (k *Kademlia) AddrCountC() <-chan int {
   362  	if k.addrCountC == nil {
   363  		k.addrCountC = make(chan int)
   364  	}
   365  	return k.addrCountC
   366  }
   367  
   368  //关闭从活动对等中删除对等
   369  func (k *Kademlia) Off(p OverlayConn) {
   370  	k.lock.Lock()
   371  	defer k.lock.Unlock()
   372  	var del bool
   373  	k.addrs, _, _, _ = pot.Swap(k.addrs, p, pof, func(v pot.Val) pot.Val {
   374  //v不能为零,必须选中,否则我们将覆盖条目
   375  		if v == nil {
   376  			panic(fmt.Sprintf("connected peer not found %v", p))
   377  		}
   378  		del = true
   379  		return newEntry(p.Off())
   380  	})
   381  
   382  	if del {
   383  		k.conns, _, _, _ = pot.Swap(k.conns, p, pof, func(_ pot.Val) pot.Val {
   384  //V不能为零,但不需要检查
   385  			return nil
   386  		})
   387  //仅当对等端被删除时才发送新的地址计数值
   388  		if k.addrCountC != nil {
   389  			k.addrCountC <- k.addrs.Size()
   390  		}
   391  		k.sendNeighbourhoodDepthChange()
   392  	}
   393  }
   394  
   395  func (k *Kademlia) EachBin(base []byte, pof pot.Pof, o int, eachBinFunc func(conn OverlayConn, po int) bool) {
   396  	k.lock.RLock()
   397  	defer k.lock.RUnlock()
   398  
   399  	var startPo int
   400  	var endPo int
   401  	kadDepth := k.neighbourhoodDepth()
   402  
   403  	k.conns.EachBin(base, pof, o, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool {
   404  		if startPo > 0 && endPo != k.MaxProxDisplay {
   405  			startPo = endPo + 1
   406  		}
   407  		if po < kadDepth {
   408  			endPo = po
   409  		} else {
   410  			endPo = k.MaxProxDisplay
   411  		}
   412  
   413  		for bin := startPo; bin <= endPo; bin++ {
   414  			f(func(val pot.Val, _ int) bool {
   415  				return eachBinFunc(val.(*entry).conn(), bin)
   416  			})
   417  		}
   418  		return true
   419  	})
   420  }
   421  
   422  //eachconn是一个带有args(base、po、f)的迭代器,将f应用于每个活动对等端
   423  //从基地测量,接近订单为po或更低
   424  //如果基为零,则使用Kademlia基地址
   425  func (k *Kademlia) EachConn(base []byte, o int, f func(OverlayConn, int, bool) bool) {
   426  	k.lock.RLock()
   427  	defer k.lock.RUnlock()
   428  	k.eachConn(base, o, f)
   429  }
   430  
   431  func (k *Kademlia) eachConn(base []byte, o int, f func(OverlayConn, int, bool) bool) {
   432  	if len(base) == 0 {
   433  		base = k.base
   434  	}
   435  	depth := k.neighbourhoodDepth()
   436  	k.conns.EachNeighbour(base, pof, func(val pot.Val, po int) bool {
   437  		if po > o {
   438  			return true
   439  		}
   440  		return f(val.(*entry).conn(), po, po >= depth)
   441  	})
   442  }
   443  
   444  //用(base,po,f)调用的eachaddr是一个迭代器,将f应用于每个已知的对等端
   445  //从基地测量,接近订单为po或更低
   446  //如果基为零,则使用Kademlia基地址
   447  func (k *Kademlia) EachAddr(base []byte, o int, f func(OverlayAddr, int, bool) bool) {
   448  	k.lock.RLock()
   449  	defer k.lock.RUnlock()
   450  	k.eachAddr(base, o, f)
   451  }
   452  
   453  func (k *Kademlia) eachAddr(base []byte, o int, f func(OverlayAddr, int, bool) bool) {
   454  	if len(base) == 0 {
   455  		base = k.base
   456  	}
   457  	depth := k.neighbourhoodDepth()
   458  	k.addrs.EachNeighbour(base, pof, func(val pot.Val, po int) bool {
   459  		if po > o {
   460  			return true
   461  		}
   462  		return f(val.(*entry).addr(), po, po >= depth)
   463  	})
   464  }
   465  
   466  //neighbourhooddepth返回定义
   467  //基数大于等于minProxBinSize的最近邻集
   468  //如果总共小于minproxbinsize对等端,则返回0
   469  //呼叫方必须持有锁
   470  func (k *Kademlia) neighbourhoodDepth() (depth int) {
   471  	if k.conns.Size() < k.MinProxBinSize {
   472  		return 0
   473  	}
   474  	var size int
   475  	f := func(v pot.Val, i int) bool {
   476  		size++
   477  		depth = i
   478  		return size < k.MinProxBinSize
   479  	}
   480  	k.conns.EachNeighbour(k.base, pof, f)
   481  	return depth
   482  }
   483  
   484  //使用val调用时可调用,
   485  func (k *Kademlia) callable(val pot.Val) OverlayAddr {
   486  	e := val.(*entry)
   487  //如果对等方处于活动状态或超过了maxretries,则不可调用
   488  	if e.conn() != nil || e.retries > k.MaxRetries {
   489  		return nil
   490  	}
   491  //根据上次看到后经过的时间计算允许的重试次数
   492  	timeAgo := int64(time.Since(e.seenAt))
   493  	div := int64(k.RetryExponent)
   494  	div += (150000 - rand.Int63n(300000)) * div / 1000000
   495  	var retries int
   496  	for delta := timeAgo; delta > k.RetryInterval; delta /= div {
   497  		retries++
   498  	}
   499  //它从不并发调用,因此可以安全地递增
   500  //可以再次重试对等机
   501  	if retries < e.retries {
   502  		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))
   503  		return nil
   504  	}
   505  //制裁或阻止建议同伴的职能
   506  	if k.Reachable != nil && !k.Reachable(e.addr()) {
   507  		log.Trace(fmt.Sprintf("%08x: peer %v is temporarily not callable", k.BaseAddr()[:4], e))
   508  		return nil
   509  	}
   510  	e.retries++
   511  	log.Trace(fmt.Sprintf("%08x: peer %v is callable", k.BaseAddr()[:4], e))
   512  
   513  	return e.addr()
   514  }
   515  
   516  //baseaddr返回kademlia基地址
   517  func (k *Kademlia) BaseAddr() []byte {
   518  	return k.base
   519  }
   520  
   521  //字符串返回用ASCII显示的kademlia表+kaddb表
   522  func (k *Kademlia) String() string {
   523  	k.lock.RLock()
   524  	defer k.lock.RUnlock()
   525  	return k.string()
   526  }
   527  
   528  //字符串返回用ASCII显示的kademlia表+kaddb表
   529  func (k *Kademlia) string() string {
   530  	wsrow := "                          "
   531  	var rows []string
   532  
   533  	rows = append(rows, "=========================================================================")
   534  	rows = append(rows, fmt.Sprintf("%v KΛÐΞMLIΛ hive: queen's address: %x", time.Now().UTC().Format(time.UnixDate), k.BaseAddr()[:3]))
   535  	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))
   536  
   537  	liverows := make([]string, k.MaxProxDisplay)
   538  	peersrows := make([]string, k.MaxProxDisplay)
   539  
   540  	depth := k.neighbourhoodDepth()
   541  	rest := k.conns.Size()
   542  	k.conns.EachBin(k.base, pof, 0, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool {
   543  		var rowlen int
   544  		if po >= k.MaxProxDisplay {
   545  			po = k.MaxProxDisplay - 1
   546  		}
   547  		row := []string{fmt.Sprintf("%2d", size)}
   548  		rest -= size
   549  		f(func(val pot.Val, vpo int) bool {
   550  			e := val.(*entry)
   551  			row = append(row, fmt.Sprintf("%x", e.Address()[:2]))
   552  			rowlen++
   553  			return rowlen < 4
   554  		})
   555  		r := strings.Join(row, " ")
   556  		r = r + wsrow
   557  		liverows[po] = r[:31]
   558  		return true
   559  	})
   560  
   561  	k.addrs.EachBin(k.base, pof, 0, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool {
   562  		var rowlen int
   563  		if po >= k.MaxProxDisplay {
   564  			po = k.MaxProxDisplay - 1
   565  		}
   566  		if size < 0 {
   567  			panic("wtf")
   568  		}
   569  		row := []string{fmt.Sprintf("%2d", size)}
   570  //我们也在现场展示同龄人
   571  		f(func(val pot.Val, vpo int) bool {
   572  			e := val.(*entry)
   573  			row = append(row, Label(e))
   574  			rowlen++
   575  			return rowlen < 4
   576  		})
   577  		peersrows[po] = strings.Join(row, " ")
   578  		return true
   579  	})
   580  
   581  	for i := 0; i < k.MaxProxDisplay; i++ {
   582  		if i == depth {
   583  			rows = append(rows, fmt.Sprintf("============ DEPTH: %d ==========================================", i))
   584  		}
   585  		left := liverows[i]
   586  		right := peersrows[i]
   587  		if len(left) == 0 {
   588  			left = " 0                             "
   589  		}
   590  		if len(right) == 0 {
   591  			right = " 0"
   592  		}
   593  		rows = append(rows, fmt.Sprintf("%03d %v | %v", i, left, right))
   594  	}
   595  	rows = append(rows, "=========================================================================")
   596  	return "\n" + strings.Join(rows, "\n")
   597  }
   598  
   599  //Peerpot保存预期最近邻居和空箱子的信息
   600  //仅用于测试
   601  type PeerPot struct {
   602  	NNSet     [][]byte
   603  	EmptyBins []int
   604  }
   605  
   606  //newpeerpotmap用键创建overlayaddr的pot记录的映射
   607  //作为地址的十六进制表示。
   608  func NewPeerPotMap(kadMinProxSize int, addrs [][]byte) map[string]*PeerPot {
   609  //为运行状况检查创建所有节点的表
   610  	np := pot.NewPot(nil, 0)
   611  	for _, addr := range addrs {
   612  		np, _, _ = pot.Add(np, addr, pof)
   613  	}
   614  	ppmap := make(map[string]*PeerPot)
   615  
   616  	for i, a := range addrs {
   617  		pl := 256
   618  		prev := 256
   619  		var emptyBins []int
   620  		var nns [][]byte
   621  		np.EachNeighbour(addrs[i], pof, func(val pot.Val, po int) bool {
   622  			a := val.([]byte)
   623  			if po == 256 {
   624  				return true
   625  			}
   626  			if pl == 256 || pl == po {
   627  				nns = append(nns, a)
   628  			}
   629  			if pl == 256 && len(nns) >= kadMinProxSize {
   630  				pl = po
   631  				prev = po
   632  			}
   633  			if prev < pl {
   634  				for j := prev; j > po; j-- {
   635  					emptyBins = append(emptyBins, j)
   636  				}
   637  			}
   638  			prev = po - 1
   639  			return true
   640  		})
   641  		for j := prev; j >= 0; j-- {
   642  			emptyBins = append(emptyBins, j)
   643  		}
   644  		log.Trace(fmt.Sprintf("%x NNS: %s", addrs[i][:4], LogAddrs(nns)))
   645  		ppmap[common.Bytes2Hex(a)] = &PeerPot{nns, emptyBins}
   646  	}
   647  	return ppmap
   648  }
   649  
   650  //饱和返回该订单的箱的最低接近顺序
   651  //具有少于n个对等点
   652  func (k *Kademlia) saturation(n int) int {
   653  	prev := -1
   654  	k.addrs.EachBin(k.base, pof, 0, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool {
   655  		prev++
   656  		return prev == po && size >= n
   657  	})
   658  	depth := k.neighbourhoodDepth()
   659  	if depth < prev {
   660  		return depth
   661  	}
   662  	return prev
   663  }
   664  
   665  //如果所有必需的容器都连接了对等方,则full返回true。
   666  //用于健康功能。
   667  func (k *Kademlia) full(emptyBins []int) (full bool) {
   668  	prev := 0
   669  	e := len(emptyBins)
   670  	ok := true
   671  	depth := k.neighbourhoodDepth()
   672  	k.conns.EachBin(k.base, pof, 0, func(po, _ int, _ func(func(val pot.Val, i int) bool) bool) bool {
   673  		if prev == depth+1 {
   674  			return true
   675  		}
   676  		for i := prev; i < po; i++ {
   677  			e--
   678  			if e < 0 {
   679  				ok = false
   680  				return false
   681  			}
   682  			if emptyBins[e] != i {
   683  				log.Trace(fmt.Sprintf("%08x po: %d, i: %d, e: %d, emptybins: %v", k.BaseAddr()[:4], po, i, e, logEmptyBins(emptyBins)))
   684  				if emptyBins[e] < i {
   685  					panic("incorrect peerpot")
   686  				}
   687  				ok = false
   688  				return false
   689  			}
   690  		}
   691  		prev = po + 1
   692  		return true
   693  	})
   694  	if !ok {
   695  		return false
   696  	}
   697  	return e == 0
   698  }
   699  
   700  func (k *Kademlia) knowNearestNeighbours(peers [][]byte) bool {
   701  	pm := make(map[string]bool)
   702  
   703  	k.eachAddr(nil, 255, func(p OverlayAddr, po int, nn bool) bool {
   704  		if !nn {
   705  			return false
   706  		}
   707  		pk := fmt.Sprintf("%x", p.Address())
   708  		pm[pk] = true
   709  		return true
   710  	})
   711  	for _, p := range peers {
   712  		pk := fmt.Sprintf("%x", p)
   713  		if !pm[pk] {
   714  			log.Trace(fmt.Sprintf("%08x: known nearest neighbour %s not found", k.BaseAddr()[:4], pk[:8]))
   715  			return false
   716  		}
   717  	}
   718  	return true
   719  }
   720  
   721  func (k *Kademlia) gotNearestNeighbours(peers [][]byte) (got bool, n int, missing [][]byte) {
   722  	pm := make(map[string]bool)
   723  
   724  	k.eachConn(nil, 255, func(p OverlayConn, po int, nn bool) bool {
   725  		if !nn {
   726  			return false
   727  		}
   728  		pk := fmt.Sprintf("%x", p.Address())
   729  		pm[pk] = true
   730  		return true
   731  	})
   732  	var gots int
   733  	var culprits [][]byte
   734  	for _, p := range peers {
   735  		pk := fmt.Sprintf("%x", p)
   736  		if pm[pk] {
   737  			gots++
   738  		} else {
   739  			log.Trace(fmt.Sprintf("%08x: ExpNN: %s not found", k.BaseAddr()[:4], pk[:8]))
   740  			culprits = append(culprits, p)
   741  		}
   742  	}
   743  	return gots == len(peers), gots, culprits
   744  }
   745  
   746  //卡德米利亚的健康状况
   747  type Health struct {
   748  KnowNN     bool     //节点是否知道所有最近的邻居
   749  GotNN      bool     //节点是否连接到其所有最近的邻居
   750  CountNN    int      //连接到的最近邻居的数量
   751  CulpritsNN [][]byte //哪些已知的nns丢失了
   752  Full       bool     //节点在每个kademlia bin中是否有一个对等点(如果有这样的对等点)
   753  	Hive       string
   754  }
   755  
   756  //健康报告Kademlia连接性的健康状态
   757  //返回健康结构
   758  func (k *Kademlia) Healthy(pp *PeerPot) *Health {
   759  	k.lock.RLock()
   760  	defer k.lock.RUnlock()
   761  	gotnn, countnn, culpritsnn := k.gotNearestNeighbours(pp.NNSet)
   762  	knownn := k.knowNearestNeighbours(pp.NNSet)
   763  	full := k.full(pp.EmptyBins)
   764  	log.Trace(fmt.Sprintf("%08x: healthy: knowNNs: %v, gotNNs: %v, full: %v\n", k.BaseAddr()[:4], knownn, gotnn, full))
   765  	return &Health{knownn, gotnn, countnn, culpritsnn, full, k.string()}
   766  }
   767  
   768  func logEmptyBins(ebs []int) string {
   769  	var ebss []string
   770  	for _, eb := range ebs {
   771  		ebss = append(ebss, fmt.Sprintf("%d", eb))
   772  	}
   773  	return strings.Join(ebss, ", ")
   774  }