github.com/pslzym/go-ethereum@v1.8.17-0.20180926104442-4b6824e07b1b/p2p/discover/table_util_test.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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-ethereum 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-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package discover 18 19 import ( 20 "crypto/ecdsa" 21 "encoding/hex" 22 "fmt" 23 "math/rand" 24 "net" 25 "sync" 26 27 "github.com/ethereum/go-ethereum/p2p/enode" 28 "github.com/ethereum/go-ethereum/p2p/enr" 29 ) 30 31 func newTestTable(t transport) (*Table, *enode.DB) { 32 var r enr.Record 33 r.Set(enr.IP{0, 0, 0, 0}) 34 n := enode.SignNull(&r, enode.ID{}) 35 db, _ := enode.OpenDB("") 36 tab, _ := newTable(t, n, db, nil) 37 return tab, db 38 } 39 40 // nodeAtDistance creates a node for which enode.LogDist(base, n.id) == ld. 41 func nodeAtDistance(base enode.ID, ld int, ip net.IP) *node { 42 var r enr.Record 43 r.Set(enr.IP(ip)) 44 return wrapNode(enode.SignNull(&r, idAtDistance(base, ld))) 45 } 46 47 // idAtDistance returns a random hash such that enode.LogDist(a, b) == n 48 func idAtDistance(a enode.ID, n int) (b enode.ID) { 49 if n == 0 { 50 return a 51 } 52 // flip bit at position n, fill the rest with random bits 53 b = a 54 pos := len(a) - n/8 - 1 55 bit := byte(0x01) << (byte(n%8) - 1) 56 if bit == 0 { 57 pos++ 58 bit = 0x80 59 } 60 b[pos] = a[pos]&^bit | ^a[pos]&bit // TODO: randomize end bits 61 for i := pos + 1; i < len(a); i++ { 62 b[i] = byte(rand.Intn(255)) 63 } 64 return b 65 } 66 67 func intIP(i int) net.IP { 68 return net.IP{byte(i), 0, 2, byte(i)} 69 } 70 71 // fillBucket inserts nodes into the given bucket until it is full. 72 func fillBucket(tab *Table, n *node) (last *node) { 73 ld := enode.LogDist(tab.self.ID(), n.ID()) 74 b := tab.bucket(n.ID()) 75 for len(b.entries) < bucketSize { 76 b.entries = append(b.entries, nodeAtDistance(tab.self.ID(), ld, intIP(ld))) 77 } 78 return b.entries[bucketSize-1] 79 } 80 81 type pingRecorder struct { 82 mu sync.Mutex 83 dead, pinged map[enode.ID]bool 84 } 85 86 func newPingRecorder() *pingRecorder { 87 return &pingRecorder{ 88 dead: make(map[enode.ID]bool), 89 pinged: make(map[enode.ID]bool), 90 } 91 } 92 93 func (t *pingRecorder) findnode(toid enode.ID, toaddr *net.UDPAddr, target encPubkey) ([]*node, error) { 94 return nil, nil 95 } 96 97 func (t *pingRecorder) waitping(from enode.ID) error { 98 return nil // remote always pings 99 } 100 101 func (t *pingRecorder) ping(toid enode.ID, toaddr *net.UDPAddr) error { 102 t.mu.Lock() 103 defer t.mu.Unlock() 104 105 t.pinged[toid] = true 106 if t.dead[toid] { 107 return errTimeout 108 } else { 109 return nil 110 } 111 } 112 113 func (t *pingRecorder) close() {} 114 115 func hasDuplicates(slice []*node) bool { 116 seen := make(map[enode.ID]bool) 117 for i, e := range slice { 118 if e == nil { 119 panic(fmt.Sprintf("nil *Node at %d", i)) 120 } 121 if seen[e.ID()] { 122 return true 123 } 124 seen[e.ID()] = true 125 } 126 return false 127 } 128 129 func contains(ns []*node, id enode.ID) bool { 130 for _, n := range ns { 131 if n.ID() == id { 132 return true 133 } 134 } 135 return false 136 } 137 138 func sortedByDistanceTo(distbase enode.ID, slice []*node) bool { 139 var last enode.ID 140 for i, e := range slice { 141 if i > 0 && enode.DistCmp(distbase, e.ID(), last) < 0 { 142 return false 143 } 144 last = e.ID() 145 } 146 return true 147 } 148 149 func hexEncPubkey(h string) (ret encPubkey) { 150 b, err := hex.DecodeString(h) 151 if err != nil { 152 panic(err) 153 } 154 if len(b) != len(ret) { 155 panic("invalid length") 156 } 157 copy(ret[:], b) 158 return ret 159 } 160 161 func hexPubkey(h string) *ecdsa.PublicKey { 162 k, err := decodePubkey(hexEncPubkey(h)) 163 if err != nil { 164 panic(err) 165 } 166 return k 167 }