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