github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/p2p/discover/table_util_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:41</date>
    10  //</624450103121285120>
    11  
    12  
    13  package discover
    14  
    15  import (
    16  	"crypto/ecdsa"
    17  	"encoding/hex"
    18  	"fmt"
    19  	"math/rand"
    20  	"net"
    21  	"sync"
    22  
    23  	"github.com/ethereum/go-ethereum/p2p/enode"
    24  	"github.com/ethereum/go-ethereum/p2p/enr"
    25  )
    26  
    27  var nullNode *enode.Node
    28  
    29  func init() {
    30  	var r enr.Record
    31  	r.Set(enr.IP{0, 0, 0, 0})
    32  	nullNode = enode.SignNull(&r, enode.ID{})
    33  }
    34  
    35  func newTestTable(t transport) (*Table, *enode.DB) {
    36  	db, _ := enode.OpenDB("")
    37  	tab, _ := newTable(t, db, nil)
    38  	return tab, db
    39  }
    40  
    41  //nodeAtDistance为其创建一个enode.logDist(base,n.id)=ld的节点。
    42  func nodeAtDistance(base enode.ID, ld int, ip net.IP) *node {
    43  	var r enr.Record
    44  	r.Set(enr.IP(ip))
    45  	return wrapNode(enode.SignNull(&r, idAtDistance(base, ld)))
    46  }
    47  
    48  //IDATInstance返回一个随机哈希,使enode.logdist(a,b)==n
    49  func idAtDistance(a enode.ID, n int) (b enode.ID) {
    50  	if n == 0 {
    51  		return a
    52  	}
    53  //在n位置翻转钻头,其余部分用随机钻头填满。
    54  	b = a
    55  	pos := len(a) - n/8 - 1
    56  	bit := byte(0x01) << (byte(n%8) - 1)
    57  	if bit == 0 {
    58  		pos++
    59  		bit = 0x80
    60  	}
    61  b[pos] = a[pos]&^bit | ^a[pos]&bit //TODO:随机结束位
    62  	for i := pos + 1; i < len(a); i++ {
    63  		b[i] = byte(rand.Intn(255))
    64  	}
    65  	return b
    66  }
    67  
    68  func intIP(i int) net.IP {
    69  	return net.IP{byte(i), 0, 2, byte(i)}
    70  }
    71  
    72  //FillBucket将节点插入给定的bucket,直到它满为止。
    73  func fillBucket(tab *Table, n *node) (last *node) {
    74  	ld := enode.LogDist(tab.self().ID(), n.ID())
    75  	b := tab.bucket(n.ID())
    76  	for len(b.entries) < bucketSize {
    77  		b.entries = append(b.entries, nodeAtDistance(tab.self().ID(), ld, intIP(ld)))
    78  	}
    79  	return b.entries[bucketSize-1]
    80  }
    81  
    82  type pingRecorder struct {
    83  	mu           sync.Mutex
    84  	dead, pinged map[enode.ID]bool
    85  	n            *enode.Node
    86  }
    87  
    88  func newPingRecorder() *pingRecorder {
    89  	var r enr.Record
    90  	r.Set(enr.IP{0, 0, 0, 0})
    91  	n := enode.SignNull(&r, enode.ID{})
    92  
    93  	return &pingRecorder{
    94  		dead:   make(map[enode.ID]bool),
    95  		pinged: make(map[enode.ID]bool),
    96  		n:      n,
    97  	}
    98  }
    99  
   100  func (t *pingRecorder) self() *enode.Node {
   101  	return nullNode
   102  }
   103  
   104  func (t *pingRecorder) findnode(toid enode.ID, toaddr *net.UDPAddr, target encPubkey) ([]*node, error) {
   105  	return nil, nil
   106  }
   107  
   108  func (t *pingRecorder) waitping(from enode.ID) error {
   109  return nil //远程总是ping
   110  }
   111  
   112  func (t *pingRecorder) ping(toid enode.ID, toaddr *net.UDPAddr) error {
   113  	t.mu.Lock()
   114  	defer t.mu.Unlock()
   115  
   116  	t.pinged[toid] = true
   117  	if t.dead[toid] {
   118  		return errTimeout
   119  	} else {
   120  		return nil
   121  	}
   122  }
   123  
   124  func (t *pingRecorder) close() {}
   125  
   126  func hasDuplicates(slice []*node) bool {
   127  	seen := make(map[enode.ID]bool)
   128  	for i, e := range slice {
   129  		if e == nil {
   130  			panic(fmt.Sprintf("nil *Node at %d", i))
   131  		}
   132  		if seen[e.ID()] {
   133  			return true
   134  		}
   135  		seen[e.ID()] = true
   136  	}
   137  	return false
   138  }
   139  
   140  func contains(ns []*node, id enode.ID) bool {
   141  	for _, n := range ns {
   142  		if n.ID() == id {
   143  			return true
   144  		}
   145  	}
   146  	return false
   147  }
   148  
   149  func sortedByDistanceTo(distbase enode.ID, slice []*node) bool {
   150  	var last enode.ID
   151  	for i, e := range slice {
   152  		if i > 0 && enode.DistCmp(distbase, e.ID(), last) < 0 {
   153  			return false
   154  		}
   155  		last = e.ID()
   156  	}
   157  	return true
   158  }
   159  
   160  func hexEncPubkey(h string) (ret encPubkey) {
   161  	b, err := hex.DecodeString(h)
   162  	if err != nil {
   163  		panic(err)
   164  	}
   165  	if len(b) != len(ret) {
   166  		panic("invalid length")
   167  	}
   168  	copy(ret[:], b)
   169  	return ret
   170  }
   171  
   172  func hexPubkey(h string) *ecdsa.PublicKey {
   173  	k, err := decodePubkey(hexEncPubkey(h))
   174  	if err != nil {
   175  		panic(err)
   176  	}
   177  	return k
   178  }
   179