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