table_util_test.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // Copyright 2018 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. package discover
  17. import (
  18. "bytes"
  19. "crypto/ecdsa"
  20. "encoding/hex"
  21. "errors"
  22. "fmt"
  23. "math/rand"
  24. "net"
  25. "reflect"
  26. "sort"
  27. "sync"
  28. "github.com/ethereum/go-ethereum/crypto"
  29. "github.com/ethereum/go-ethereum/log"
  30. "github.com/ethereum/go-ethereum/p2p/enode"
  31. "github.com/ethereum/go-ethereum/p2p/enr"
  32. )
  33. var nullNode *enode.Node
  34. func init() {
  35. var r enr.Record
  36. r.Set(enr.IP{0, 0, 0, 0})
  37. nullNode = enode.SignNull(&r, enode.ID{})
  38. }
  39. func newTestTable(t transport) (*Table, *enode.DB) {
  40. db, _ := enode.OpenDB("")
  41. tab, _ := newTable(t, db, nil, log.Root())
  42. go tab.loop()
  43. return tab, db
  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. // idAtDistance returns a random hash such that enode.LogDist(a, b) == n
  52. func idAtDistance(a enode.ID, n int) (b enode.ID) {
  53. if n == 0 {
  54. return a
  55. }
  56. // flip bit at position n, fill the rest with random bits
  57. b = a
  58. pos := len(a) - n/8 - 1
  59. bit := byte(0x01) << (byte(n%8) - 1)
  60. if bit == 0 {
  61. pos++
  62. bit = 0x80
  63. }
  64. b[pos] = a[pos]&^bit | ^a[pos]&bit // TODO: randomize end bits
  65. for i := pos + 1; i < len(a); i++ {
  66. b[i] = byte(rand.Intn(255))
  67. }
  68. return b
  69. }
  70. func intIP(i int) net.IP {
  71. return net.IP{byte(i), 0, 2, byte(i)}
  72. }
  73. // fillBucket inserts nodes into the given bucket until it is full.
  74. func fillBucket(tab *Table, n *node) (last *node) {
  75. ld := enode.LogDist(tab.self().ID(), n.ID())
  76. b := tab.bucket(n.ID())
  77. for len(b.entries) < bucketSize {
  78. b.entries = append(b.entries, nodeAtDistance(tab.self().ID(), ld, intIP(ld)))
  79. }
  80. return b.entries[bucketSize-1]
  81. }
  82. // fillTable adds nodes the table to the end of their corresponding bucket
  83. // if the bucket is not full. The caller must not hold tab.mutex.
  84. func fillTable(tab *Table, nodes []*node) {
  85. for _, n := range nodes {
  86. tab.addSeenNode(n)
  87. }
  88. }
  89. type pingRecorder struct {
  90. mu sync.Mutex
  91. dead, pinged map[enode.ID]bool
  92. records map[enode.ID]*enode.Node
  93. n *enode.Node
  94. }
  95. func newPingRecorder() *pingRecorder {
  96. var r enr.Record
  97. r.Set(enr.IP{0, 0, 0, 0})
  98. n := enode.SignNull(&r, enode.ID{})
  99. return &pingRecorder{
  100. dead: make(map[enode.ID]bool),
  101. pinged: make(map[enode.ID]bool),
  102. records: make(map[enode.ID]*enode.Node),
  103. n: n,
  104. }
  105. }
  106. // setRecord updates a node record. Future calls to ping and
  107. // requestENR will return this record.
  108. func (t *pingRecorder) updateRecord(n *enode.Node) {
  109. t.mu.Lock()
  110. defer t.mu.Unlock()
  111. t.records[n.ID()] = n
  112. }
  113. // Stubs to satisfy the transport interface.
  114. func (t *pingRecorder) Self() *enode.Node { return nullNode }
  115. func (t *pingRecorder) lookupSelf() []*enode.Node { return nil }
  116. func (t *pingRecorder) lookupRandom() []*enode.Node { return nil }
  117. func (t *pingRecorder) close() {}
  118. // ping simulates a ping request.
  119. func (t *pingRecorder) ping(n *enode.Node) (seq uint64, err error) {
  120. t.mu.Lock()
  121. defer t.mu.Unlock()
  122. t.pinged[n.ID()] = true
  123. if t.dead[n.ID()] {
  124. return 0, errTimeout
  125. }
  126. if t.records[n.ID()] != nil {
  127. seq = t.records[n.ID()].Seq()
  128. }
  129. return seq, nil
  130. }
  131. // requestENR simulates an ENR request.
  132. func (t *pingRecorder) RequestENR(n *enode.Node) (*enode.Node, error) {
  133. t.mu.Lock()
  134. defer t.mu.Unlock()
  135. if t.dead[n.ID()] || t.records[n.ID()] == nil {
  136. return nil, errTimeout
  137. }
  138. return t.records[n.ID()], nil
  139. }
  140. func hasDuplicates(slice []*node) bool {
  141. seen := make(map[enode.ID]bool)
  142. for i, e := range slice {
  143. if e == nil {
  144. panic(fmt.Sprintf("nil *Node at %d", i))
  145. }
  146. if seen[e.ID()] {
  147. return true
  148. }
  149. seen[e.ID()] = true
  150. }
  151. return false
  152. }
  153. func checkNodesEqual(got, want []*enode.Node) error {
  154. if reflect.DeepEqual(got, want) {
  155. return nil
  156. }
  157. output := new(bytes.Buffer)
  158. fmt.Fprintf(output, "got %d nodes:\n", len(got))
  159. for _, n := range got {
  160. fmt.Fprintf(output, " %v %v\n", n.ID(), n)
  161. }
  162. fmt.Fprintf(output, "want %d:\n", len(want))
  163. for _, n := range want {
  164. fmt.Fprintf(output, " %v %v\n", n.ID(), n)
  165. }
  166. return errors.New(output.String())
  167. }
  168. func sortByID(nodes []*enode.Node) {
  169. sort.Slice(nodes, func(i, j int) bool {
  170. return string(nodes[i].ID().Bytes()) < string(nodes[j].ID().Bytes())
  171. })
  172. }
  173. func sortedByDistanceTo(distbase enode.ID, slice []*node) bool {
  174. return sort.SliceIsSorted(slice, func(i, j int) bool {
  175. return enode.DistCmp(distbase, slice[i].ID(), slice[j].ID()) < 0
  176. })
  177. }
  178. func hexEncPrivkey(h string) *ecdsa.PrivateKey {
  179. b, err := hex.DecodeString(h)
  180. if err != nil {
  181. panic(err)
  182. }
  183. key, err := crypto.ToECDSA(b)
  184. if err != nil {
  185. panic(err)
  186. }
  187. return key
  188. }
  189. func hexEncPubkey(h string) (ret encPubkey) {
  190. b, err := hex.DecodeString(h)
  191. if err != nil {
  192. panic(err)
  193. }
  194. if len(b) != len(ret) {
  195. panic("invalid length")
  196. }
  197. copy(ret[:], b)
  198. return ret
  199. }