github.com/alexdevranger/node-1.8.27@v0.0.0-20221128213301-aa5841e41d2d/p2p/discover/table_util_test.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-dubxcoin library. 3 // 4 // The go-dubxcoin 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-dubxcoin 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-dubxcoin 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/alexdevranger/node-1.8.27/p2p/enode" 28 "github.com/alexdevranger/node-1.8.27/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 // fillTable adds nodes the table to the end of their corresponding bucket 87 // if the bucket is not full. The caller must not hold tab.mutex. 88 func fillTable(tab *Table, nodes []*node) { 89 for _, n := range nodes { 90 tab.addSeenNode(n) 91 } 92 } 93 94 type pingRecorder struct { 95 mu sync.Mutex 96 dead, pinged map[enode.ID]bool 97 n *enode.Node 98 } 99 100 func newPingRecorder() *pingRecorder { 101 var r enr.Record 102 r.Set(enr.IP{0, 0, 0, 0}) 103 n := enode.SignNull(&r, enode.ID{}) 104 105 return &pingRecorder{ 106 dead: make(map[enode.ID]bool), 107 pinged: make(map[enode.ID]bool), 108 n: n, 109 } 110 } 111 112 func (t *pingRecorder) self() *enode.Node { 113 return nullNode 114 } 115 116 func (t *pingRecorder) findnode(toid enode.ID, toaddr *net.UDPAddr, target encPubkey) ([]*node, error) { 117 return nil, nil 118 } 119 120 func (t *pingRecorder) ping(toid enode.ID, toaddr *net.UDPAddr) error { 121 t.mu.Lock() 122 defer t.mu.Unlock() 123 124 t.pinged[toid] = true 125 if t.dead[toid] { 126 return errTimeout 127 } else { 128 return nil 129 } 130 } 131 132 func (t *pingRecorder) close() {} 133 134 func hasDuplicates(slice []*node) bool { 135 seen := make(map[enode.ID]bool) 136 for i, e := range slice { 137 if e == nil { 138 panic(fmt.Sprintf("nil *Node at %d", i)) 139 } 140 if seen[e.ID()] { 141 return true 142 } 143 seen[e.ID()] = true 144 } 145 return false 146 } 147 148 func sortedByDistanceTo(distbase enode.ID, slice []*node) bool { 149 var last enode.ID 150 for i, e := range slice { 151 if i > 0 && enode.DistCmp(distbase, e.ID(), last) < 0 { 152 return false 153 } 154 last = e.ID() 155 } 156 return true 157 } 158 159 func hexEncPubkey(h string) (ret encPubkey) { 160 b, err := hex.DecodeString(h) 161 if err != nil { 162 panic(err) 163 } 164 if len(b) != len(ret) { 165 panic("invalid length") 166 } 167 copy(ret[:], b) 168 return ret 169 } 170 171 func hexPubkey(h string) *ecdsa.PublicKey { 172 k, err := decodePubkey(hexEncPubkey(h)) 173 if err != nil { 174 panic(err) 175 } 176 return k 177 }