github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/discv5/table_test.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  //版权所有2016 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 discv5
    26  
    27  import (
    28  	"crypto/ecdsa"
    29  	"fmt"
    30  	"math/rand"
    31  
    32  	"net"
    33  	"reflect"
    34  	"testing"
    35  	"testing/quick"
    36  	"time"
    37  
    38  	"github.com/ethereum/go-ethereum/common"
    39  	"github.com/ethereum/go-ethereum/crypto"
    40  )
    41  
    42  type nullTransport struct{}
    43  
    44  func (nullTransport) sendPing(remote *Node, remoteAddr *net.UDPAddr) []byte { return []byte{1} }
    45  func (nullTransport) sendPong(remote *Node, pingHash []byte)                {}
    46  func (nullTransport) sendFindnode(remote *Node, target NodeID)              {}
    47  func (nullTransport) sendNeighbours(remote *Node, nodes []*Node)            {}
    48  func (nullTransport) localAddr() *net.UDPAddr                               { return new(net.UDPAddr) }
    49  func (nullTransport) Close()                                                {}
    50  
    51  //func测试表_pingreplace(t*testing.t)
    52  //doit:=func(newnodeisresponding,lastinbuckettisresponding bool)
    53  //传输:=newPingRecorder())
    54  //tab,:=newTable(传输,节点ID,&net.udpaddr)
    55  //延迟tab.close()
    56  //Pinsender:=新节点(musthexid(“A502AF0F59B2AAB774695408C79E9CA312D2793CC997E44FC55EDA62F0150BBB8C59A6F9269BA3A081518B62699EE807C7C19C20125DDFCCCA872608AF9E370”),net.ip,99,99)
    57  //
    58  ////填满发送方的桶。
    59  //最后:=FillBucket(tab,253)
    60  //
    61  ////此绑定调用应替换最后一个节点
    62  ////如果节点没有响应,则在其存储桶中。
    63  //transport.responding[last.id]=上次BucketisResponding
    64  //transport.responding[pinsender.id]=新节点响应
    65  //tab.bond(真,pinsender.id,&net.udpaddr,0)
    66  //
    67  ////第一个ping转到发送方(绑定pingback)
    68  //如果!transport.pinged[pingender.id]
    69  //t.error(“表没有ping回发送方”)
    70  //}
    71  //如果newnodeisresponding
    72  ////第二个ping转到bucket中最早的节点
    73  //看它是否还活着。
    74  //如果!transport.pinged[上一个.id]
    75  //t.error(“table did not ping last node in bucket”)。
    76  //}
    77  //}
    78  //
    79  //tab.mutex.lock()。
    80  //延迟tab.mutex.unlock()
    81  //如果l:=len(tab.buckets[253].entries);l!= BukStige{
    82  //t.errorf(“绑定后的存储桶大小错误:得到%d,想要%d”,l,bucket size)
    83  //}
    84  //
    85  //如果最后一个问题是响应!新节点响应
    86  //如果!包含(tab.buckets[253].entries,last.id)
    87  //t.error(“删除最后一个条目”)
    88  //}
    89  //如果包含(tab.buckets[253].entries,pinsender.id)
    90  //t.error(“添加新条目”)
    91  //}
    92  //}否则{
    93  //如果包含(tab.buckets[253].entries,last.id)
    94  //t.error(“最后一项未删除”)
    95  //}
    96  //如果!包含(tab.buckets[253].entries,pinsender.id)
    97  //t.error(“未添加新条目”)
    98  //}
    99  //}
   100  //}
   101  //
   102  //doit(真,真)
   103  //doit(假,真)
   104  //doit(对,错)
   105  //doit(假,假)
   106  //}
   107  
   108  func TestBucket_bumpNoDuplicates(t *testing.T) {
   109  	t.Parallel()
   110  	cfg := &quick.Config{
   111  		MaxCount: 1000,
   112  		Rand:     rand.New(rand.NewSource(time.Now().Unix())),
   113  		Values: func(args []reflect.Value, rand *rand.Rand) {
   114  //生成节点的随机列表。这将是存储桶的内容。
   115  			n := rand.Intn(bucketSize-1) + 1
   116  			nodes := make([]*Node, n)
   117  			for i := range nodes {
   118  				nodes[i] = nodeAtDistance(common.Hash{}, 200)
   119  			}
   120  			args[0] = reflect.ValueOf(nodes)
   121  //生成随机凹凸位置。
   122  			bumps := make([]int, rand.Intn(100))
   123  			for i := range bumps {
   124  				bumps[i] = rand.Intn(len(nodes))
   125  			}
   126  			args[1] = reflect.ValueOf(bumps)
   127  		},
   128  	}
   129  
   130  	prop := func(nodes []*Node, bumps []int) (ok bool) {
   131  		b := &bucket{entries: make([]*Node, len(nodes))}
   132  		copy(b.entries, nodes)
   133  		for i, pos := range bumps {
   134  			b.bump(b.entries[pos])
   135  			if hasDuplicates(b.entries) {
   136  				t.Logf("bucket has duplicates after %d/%d bumps:", i+1, len(bumps))
   137  				for _, n := range b.entries {
   138  					t.Logf("  %p", n)
   139  				}
   140  				return false
   141  			}
   142  		}
   143  		return true
   144  	}
   145  	if err := quick.Check(prop, cfg); err != nil {
   146  		t.Error(err)
   147  	}
   148  }
   149  
   150  //FillBucket将节点插入给定的bucket,直到
   151  //它已经满了。节点的ID与
   152  //散列。
   153  func fillBucket(tab *Table, ld int) (last *Node) {
   154  	b := tab.buckets[ld]
   155  	for len(b.entries) < bucketSize {
   156  		b.entries = append(b.entries, nodeAtDistance(tab.self.sha, ld))
   157  	}
   158  	return b.entries[bucketSize-1]
   159  }
   160  
   161  //nodeAtDistance为其创建logDist(base,n.sha)=ld的节点。
   162  //节点的ID与n.sha不对应。
   163  func nodeAtDistance(base common.Hash, ld int) (n *Node) {
   164  	n = new(Node)
   165  	n.sha = hashAtDistance(base, ld)
   166  copy(n.ID[:], n.sha[:]) //确保节点仍然具有唯一的ID
   167  	return n
   168  }
   169  
   170  type pingRecorder struct{ responding, pinged map[NodeID]bool }
   171  
   172  func newPingRecorder() *pingRecorder {
   173  	return &pingRecorder{make(map[NodeID]bool), make(map[NodeID]bool)}
   174  }
   175  
   176  func (t *pingRecorder) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) {
   177  	panic("findnode called on pingRecorder")
   178  }
   179  func (t *pingRecorder) close() {}
   180  func (t *pingRecorder) waitping(from NodeID) error {
   181  return nil //远程总是ping
   182  }
   183  func (t *pingRecorder) ping(toid NodeID, toaddr *net.UDPAddr) error {
   184  	t.pinged[toid] = true
   185  	if t.responding[toid] {
   186  		return nil
   187  	} else {
   188  		return errTimeout
   189  	}
   190  }
   191  
   192  func TestTable_closest(t *testing.T) {
   193  	t.Parallel()
   194  
   195  	test := func(test *closeTest) bool {
   196  //对于任何节点表、目标和n
   197  		tab := newTable(test.Self, &net.UDPAddr{})
   198  		tab.stuff(test.All)
   199  
   200  //检查doclosest(target,n)是否返回节点
   201  		result := tab.closest(test.Target, test.N).entries
   202  		if hasDuplicates(result) {
   203  			t.Errorf("result contains duplicates")
   204  			return false
   205  		}
   206  		if !sortedByDistanceTo(test.Target, result) {
   207  			t.Errorf("result is not sorted by distance to target")
   208  			return false
   209  		}
   210  
   211  //检查结果数是否为min(n,tablen)
   212  		wantN := test.N
   213  		if tab.count < test.N {
   214  			wantN = tab.count
   215  		}
   216  		if len(result) != wantN {
   217  			t.Errorf("wrong number of nodes: got %d, want %d", len(result), wantN)
   218  			return false
   219  		} else if len(result) == 0 {
   220  return true //不需要检查距离
   221  		}
   222  
   223  //检查结果节点与目标的距离是否最小。
   224  		for _, b := range tab.buckets {
   225  			for _, n := range b.entries {
   226  				if contains(result, n.ID) {
   227  continue //不要对结果中的节点运行下面的检查
   228  				}
   229  				farthestResult := result[len(result)-1].sha
   230  				if distcmp(test.Target, n.sha, farthestResult) < 0 {
   231  					t.Errorf("table contains node that is closer to target but it's not in result")
   232  					t.Logf("  Target:          %v", test.Target)
   233  					t.Logf("  Farthest Result: %v", farthestResult)
   234  					t.Logf("  ID:              %v", n.ID)
   235  					return false
   236  				}
   237  			}
   238  		}
   239  		return true
   240  	}
   241  	if err := quick.Check(test, quickcfg()); err != nil {
   242  		t.Error(err)
   243  	}
   244  }
   245  
   246  func TestTable_ReadRandomNodesGetAll(t *testing.T) {
   247  	cfg := &quick.Config{
   248  		MaxCount: 200,
   249  		Rand:     rand.New(rand.NewSource(time.Now().Unix())),
   250  		Values: func(args []reflect.Value, rand *rand.Rand) {
   251  			args[0] = reflect.ValueOf(make([]*Node, rand.Intn(1000)))
   252  		},
   253  	}
   254  	test := func(buf []*Node) bool {
   255  		tab := newTable(NodeID{}, &net.UDPAddr{})
   256  		for i := 0; i < len(buf); i++ {
   257  			ld := cfg.Rand.Intn(len(tab.buckets))
   258  			tab.stuff([]*Node{nodeAtDistance(tab.self.sha, ld)})
   259  		}
   260  		gotN := tab.readRandomNodes(buf)
   261  		if gotN != tab.count {
   262  			t.Errorf("wrong number of nodes, got %d, want %d", gotN, tab.count)
   263  			return false
   264  		}
   265  		if hasDuplicates(buf[:gotN]) {
   266  			t.Errorf("result contains duplicates")
   267  			return false
   268  		}
   269  		return true
   270  	}
   271  	if err := quick.Check(test, cfg); err != nil {
   272  		t.Error(err)
   273  	}
   274  }
   275  
   276  type closeTest struct {
   277  	Self   NodeID
   278  	Target common.Hash
   279  	All    []*Node
   280  	N      int
   281  }
   282  
   283  func (*closeTest) Generate(rand *rand.Rand, size int) reflect.Value {
   284  	t := &closeTest{
   285  		Self:   gen(NodeID{}, rand).(NodeID),
   286  		Target: gen(common.Hash{}, rand).(common.Hash),
   287  		N:      rand.Intn(bucketSize),
   288  	}
   289  	for _, id := range gen([]NodeID{}, rand).([]NodeID) {
   290  		t.All = append(t.All, &Node{ID: id})
   291  	}
   292  	return reflect.ValueOf(t)
   293  }
   294  
   295  func hasDuplicates(slice []*Node) bool {
   296  	seen := make(map[NodeID]bool)
   297  	for i, e := range slice {
   298  		if e == nil {
   299  			panic(fmt.Sprintf("nil *Node at %d", i))
   300  		}
   301  		if seen[e.ID] {
   302  			return true
   303  		}
   304  		seen[e.ID] = true
   305  	}
   306  	return false
   307  }
   308  
   309  func sortedByDistanceTo(distbase common.Hash, slice []*Node) bool {
   310  	var last common.Hash
   311  	for i, e := range slice {
   312  		if i > 0 && distcmp(distbase, e.sha, last) < 0 {
   313  			return false
   314  		}
   315  		last = e.sha
   316  	}
   317  	return true
   318  }
   319  
   320  func contains(ns []*Node, id NodeID) bool {
   321  	for _, n := range ns {
   322  		if n.ID == id {
   323  			return true
   324  		}
   325  	}
   326  	return false
   327  }
   328  
   329  //Gen包装速度快,价值高,使用方便。
   330  //它生成给定值类型的随机值。
   331  func gen(typ interface{}, rand *rand.Rand) interface{} {
   332  	v, ok := quick.Value(reflect.TypeOf(typ), rand)
   333  	if !ok {
   334  		panic(fmt.Sprintf("couldn't generate random value of type %T", typ))
   335  	}
   336  	return v.Interface()
   337  }
   338  
   339  func newkey() *ecdsa.PrivateKey {
   340  	key, err := crypto.GenerateKey()
   341  	if err != nil {
   342  		panic("couldn't generate key: " + err.Error())
   343  	}
   344  	return key
   345  }