table.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  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. // Package discover implements the Node Discovery Protocol.
  17. //
  18. // The Node Discovery protocol provides a way to find RLPx nodes that
  19. // can be connected to. It uses a Kademlia-like protocol to maintain a
  20. // distributed database of the IDs and endpoints of all listening
  21. // nodes.
  22. package discover
  23. import (
  24. crand "crypto/rand"
  25. "encoding/binary"
  26. "fmt"
  27. mrand "math/rand"
  28. "net"
  29. "sort"
  30. "sync"
  31. "time"
  32. "blockchain-go/common"
  33. "blockchain-go/common/gopool"
  34. "blockchain-go/log"
  35. "blockchain-go/p2p/enode"
  36. "blockchain-go/p2p/netutil"
  37. )
  38. const (
  39. alpha = 3 // Kademlia concurrency factor
  40. bucketSize = 16 // Kademlia bucket size
  41. maxReplacements = 10 // Size of per-bucket replacement list
  42. // We keep buckets for the upper 1/15 of distances because
  43. // it's very unlikely we'll ever encounter a node that's closer.
  44. hashBits = len(common.Hash{}) * 8
  45. nBuckets = hashBits / 15 // Number of buckets
  46. bucketMinDistance = hashBits - nBuckets // Log distance of closest bucket
  47. // IP address limits.
  48. bucketIPLimit, bucketSubnet = 2, 24 // at most 2 addresses from the same /24
  49. tableIPLimit, tableSubnet = 10, 24
  50. refreshInterval = 30 * time.Minute
  51. revalidateInterval = 10 * time.Second
  52. copyNodesInterval = 30 * time.Second
  53. seedMinTableTime = 5 * time.Minute
  54. seedCount = 30
  55. seedMaxAge = 5 * 24 * time.Hour
  56. )
  57. // Table is the 'node table', a Kademlia-like index of neighbor nodes. The table keeps
  58. // itself up-to-date by verifying the liveness of neighbors and requesting their node
  59. // records when announcements of a new record version are received.
  60. type Table struct {
  61. mutex sync.Mutex // protects buckets, bucket content, nursery, rand
  62. buckets [nBuckets]*bucket // index of known nodes by distance
  63. nursery []*node // bootstrap nodes
  64. rand *mrand.Rand // source of randomness, periodically reseeded
  65. ips netutil.DistinctNetSet
  66. log log.Logger
  67. db *enode.DB // database of known nodes
  68. net transport
  69. refreshReq chan chan struct{}
  70. initDone chan struct{}
  71. closeReq chan struct{}
  72. closed chan struct{}
  73. nodeAddedHook func(*node) // for testing
  74. }
  75. // transport is implemented by the UDP transports.
  76. type transport interface {
  77. Self() *enode.Node
  78. RequestENR(*enode.Node) (*enode.Node, error)
  79. lookupRandom() []*enode.Node
  80. lookupSelf() []*enode.Node
  81. ping(*enode.Node) (seq uint64, err error)
  82. }
  83. // bucket contains nodes, ordered by their last activity. the entry
  84. // that was most recently active is the first element in entries.
  85. type bucket struct {
  86. entries []*node // live entries, sorted by time of last contact
  87. replacements []*node // recently seen nodes to be used if revalidation fails
  88. ips netutil.DistinctNetSet
  89. }
  90. func newTable(t transport, db *enode.DB, bootnodes []*enode.Node, log log.Logger) (*Table, error) {
  91. tab := &Table{
  92. net: t,
  93. db: db,
  94. refreshReq: make(chan chan struct{}),
  95. initDone: make(chan struct{}),
  96. closeReq: make(chan struct{}),
  97. closed: make(chan struct{}),
  98. rand: mrand.New(mrand.NewSource(0)),
  99. ips: netutil.DistinctNetSet{Subnet: tableSubnet, Limit: tableIPLimit},
  100. log: log,
  101. }
  102. if err := tab.setFallbackNodes(bootnodes); err != nil {
  103. return nil, err
  104. }
  105. for i := range tab.buckets {
  106. tab.buckets[i] = &bucket{
  107. ips: netutil.DistinctNetSet{Subnet: bucketSubnet, Limit: bucketIPLimit},
  108. }
  109. }
  110. tab.seedRand()
  111. tab.loadSeedNodes()
  112. return tab, nil
  113. }
  114. func (tab *Table) self() *enode.Node {
  115. return tab.net.Self()
  116. }
  117. func (tab *Table) seedRand() {
  118. var b [8]byte
  119. crand.Read(b[:])
  120. tab.mutex.Lock()
  121. tab.rand.Seed(int64(binary.BigEndian.Uint64(b[:])))
  122. tab.mutex.Unlock()
  123. }
  124. // ReadRandomNodes fills the given slice with random nodes from the table. The results
  125. // are guaranteed to be unique for a single invocation, no node will appear twice.
  126. func (tab *Table) ReadRandomNodes(buf []*enode.Node) (n int) {
  127. if !tab.isInitDone() {
  128. return 0
  129. }
  130. tab.mutex.Lock()
  131. defer tab.mutex.Unlock()
  132. var nodes []*enode.Node
  133. for _, b := range &tab.buckets {
  134. for _, n := range b.entries {
  135. nodes = append(nodes, unwrapNode(n))
  136. }
  137. }
  138. // Shuffle.
  139. for i := 0; i < len(nodes); i++ {
  140. j := tab.rand.Intn(len(nodes))
  141. nodes[i], nodes[j] = nodes[j], nodes[i]
  142. }
  143. return copy(buf, nodes)
  144. }
  145. // getNode returns the node with the given ID or nil if it isn't in the table.
  146. func (tab *Table) getNode(id enode.ID) *enode.Node {
  147. tab.mutex.Lock()
  148. defer tab.mutex.Unlock()
  149. b := tab.bucket(id)
  150. for _, e := range b.entries {
  151. if e.ID() == id {
  152. return unwrapNode(e)
  153. }
  154. }
  155. return nil
  156. }
  157. // close terminates the network listener and flushes the node database.
  158. func (tab *Table) close() {
  159. close(tab.closeReq)
  160. <-tab.closed
  161. }
  162. // setFallbackNodes sets the initial points of contact. These nodes
  163. // are used to connect to the network if the table is empty and there
  164. // are no known nodes in the database.
  165. func (tab *Table) setFallbackNodes(nodes []*enode.Node) error {
  166. for _, n := range nodes {
  167. if err := n.ValidateComplete(); err != nil {
  168. return fmt.Errorf("bad bootstrap node %q: %v", n, err)
  169. }
  170. }
  171. tab.nursery = wrapNodes(nodes)
  172. return nil
  173. }
  174. // isInitDone returns whether the table's initial seeding procedure has completed.
  175. func (tab *Table) isInitDone() bool {
  176. select {
  177. case <-tab.initDone:
  178. return true
  179. default:
  180. return false
  181. }
  182. }
  183. func (tab *Table) refresh() <-chan struct{} {
  184. done := make(chan struct{})
  185. select {
  186. case tab.refreshReq <- done:
  187. case <-tab.closeReq:
  188. close(done)
  189. }
  190. return done
  191. }
  192. // loop schedules runs of doRefresh, doRevalidate and copyLiveNodes.
  193. func (tab *Table) loop() {
  194. var (
  195. revalidate = time.NewTimer(tab.nextRevalidateTime())
  196. refresh = time.NewTicker(refreshInterval)
  197. copyNodes = time.NewTicker(copyNodesInterval)
  198. refreshDone = make(chan struct{}) // where doRefresh reports completion
  199. revalidateDone chan struct{} // where doRevalidate reports completion
  200. waiting = []chan struct{}{tab.initDone} // holds waiting callers while doRefresh runs
  201. )
  202. defer refresh.Stop()
  203. defer revalidate.Stop()
  204. defer copyNodes.Stop()
  205. // Start initial refresh.
  206. gopool.Submit(func() {
  207. tab.doRefresh(refreshDone)
  208. })
  209. loop:
  210. for {
  211. select {
  212. case <-refresh.C:
  213. tab.seedRand()
  214. if refreshDone == nil {
  215. refreshDone = make(chan struct{})
  216. gopool.Submit(func() {
  217. tab.doRefresh(refreshDone)
  218. })
  219. }
  220. case req := <-tab.refreshReq:
  221. waiting = append(waiting, req)
  222. if refreshDone == nil {
  223. refreshDone = make(chan struct{})
  224. gopool.Submit(
  225. func() {
  226. tab.doRefresh(refreshDone)
  227. })
  228. }
  229. case <-refreshDone:
  230. for _, ch := range waiting {
  231. close(ch)
  232. }
  233. waiting, refreshDone = nil, nil
  234. case <-revalidate.C:
  235. revalidateDone = make(chan struct{})
  236. gopool.Submit(func() {
  237. tab.doRevalidate(revalidateDone)
  238. })
  239. case <-revalidateDone:
  240. revalidate.Reset(tab.nextRevalidateTime())
  241. revalidateDone = nil
  242. case <-copyNodes.C:
  243. gopool.Submit(func() {
  244. tab.copyLiveNodes()
  245. })
  246. case <-tab.closeReq:
  247. break loop
  248. }
  249. }
  250. if refreshDone != nil {
  251. <-refreshDone
  252. }
  253. for _, ch := range waiting {
  254. close(ch)
  255. }
  256. if revalidateDone != nil {
  257. <-revalidateDone
  258. }
  259. close(tab.closed)
  260. }
  261. // doRefresh performs a lookup for a random target to keep buckets full. seed nodes are
  262. // inserted if the table is empty (initial bootstrap or discarded faulty peers).
  263. func (tab *Table) doRefresh(done chan struct{}) {
  264. defer close(done)
  265. // Load nodes from the database and insert
  266. // them. This should yield a few previously seen nodes that are
  267. // (hopefully) still alive.
  268. tab.loadSeedNodes()
  269. // Run self lookup to discover new neighbor nodes.
  270. tab.net.lookupSelf()
  271. // The Kademlia paper specifies that the bucket refresh should
  272. // perform a lookup in the least recently used bucket. We cannot
  273. // adhere to this because the findnode target is a 512bit value
  274. // (not hash-sized) and it is not easily possible to generate a
  275. // sha3 preimage that falls into a chosen bucket.
  276. // We perform a few lookups with a random target instead.
  277. for i := 0; i < 3; i++ {
  278. tab.net.lookupRandom()
  279. }
  280. }
  281. func (tab *Table) loadSeedNodes() {
  282. seeds := wrapNodes(tab.db.QuerySeeds(seedCount, seedMaxAge))
  283. seeds = append(seeds, tab.nursery...)
  284. for i := range seeds {
  285. seed := seeds[i]
  286. age := log.Lazy{Fn: func() interface{} { return time.Since(tab.db.LastPongReceived(seed.ID(), seed.IP())) }}
  287. tab.log.Trace("Found seed node in database", "id", seed.ID(), "addr", seed.addr(), "age", age)
  288. tab.addSeenNode(seed)
  289. }
  290. }
  291. // doRevalidate checks that the last node in a random bucket is still live and replaces or
  292. // deletes the node if it isn't.
  293. func (tab *Table) doRevalidate(done chan<- struct{}) {
  294. defer func() { done <- struct{}{} }()
  295. last, bi := tab.nodeToRevalidate()
  296. if last == nil {
  297. // No non-empty bucket found.
  298. return
  299. }
  300. // Ping the selected node and wait for a pong.
  301. remoteSeq, err := tab.net.ping(unwrapNode(last))
  302. // Also fetch record if the node replied and returned a higher sequence number.
  303. if last.Seq() < remoteSeq {
  304. n, err := tab.net.RequestENR(unwrapNode(last))
  305. if err != nil {
  306. tab.log.Debug("ENR request failed", "id", last.ID(), "addr", last.addr(), "err", err)
  307. } else {
  308. last = &node{Node: *n, addedAt: last.addedAt, livenessChecks: last.livenessChecks}
  309. }
  310. }
  311. tab.mutex.Lock()
  312. defer tab.mutex.Unlock()
  313. b := tab.buckets[bi]
  314. if err == nil {
  315. // The node responded, move it to the front.
  316. last.livenessChecks++
  317. tab.log.Debug("Revalidated node", "b", bi, "id", last.ID(), "checks", last.livenessChecks)
  318. tab.bumpInBucket(b, last)
  319. return
  320. }
  321. // No reply received, pick a replacement or delete the node if there aren't
  322. // any replacements.
  323. if r := tab.replace(b, last); r != nil {
  324. tab.log.Debug("Replaced dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks, "r", r.ID(), "rip", r.IP())
  325. } else {
  326. tab.log.Debug("Removed dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks)
  327. }
  328. }
  329. // nodeToRevalidate returns the last node in a random, non-empty bucket.
  330. func (tab *Table) nodeToRevalidate() (n *node, bi int) {
  331. tab.mutex.Lock()
  332. defer tab.mutex.Unlock()
  333. for _, bi = range tab.rand.Perm(len(tab.buckets)) {
  334. b := tab.buckets[bi]
  335. if len(b.entries) > 0 {
  336. last := b.entries[len(b.entries)-1]
  337. return last, bi
  338. }
  339. }
  340. return nil, 0
  341. }
  342. func (tab *Table) nextRevalidateTime() time.Duration {
  343. tab.mutex.Lock()
  344. defer tab.mutex.Unlock()
  345. return time.Duration(tab.rand.Int63n(int64(revalidateInterval)))
  346. }
  347. // copyLiveNodes adds nodes from the table to the database if they have been in the table
  348. // longer than seedMinTableTime.
  349. func (tab *Table) copyLiveNodes() {
  350. tab.mutex.Lock()
  351. defer tab.mutex.Unlock()
  352. now := time.Now()
  353. for _, b := range &tab.buckets {
  354. for _, n := range b.entries {
  355. if n.livenessChecks > 0 && now.Sub(n.addedAt) >= seedMinTableTime {
  356. tab.db.UpdateNode(unwrapNode(n))
  357. }
  358. }
  359. }
  360. }
  361. // findnodeByID returns the n nodes in the table that are closest to the given id.
  362. // This is used by the FINDNODE/v4 handler.
  363. //
  364. // The preferLive parameter says whether the caller wants liveness-checked results. If
  365. // preferLive is true and the table contains any verified nodes, the result will not
  366. // contain unverified nodes. However, if there are no verified nodes at all, the result
  367. // will contain unverified nodes.
  368. func (tab *Table) findnodeByID(target enode.ID, nresults int, preferLive bool) *nodesByDistance {
  369. tab.mutex.Lock()
  370. defer tab.mutex.Unlock()
  371. // Scan all buckets. There might be a better way to do this, but there aren't that many
  372. // buckets, so this solution should be fine. The worst-case complexity of this loop
  373. // is O(tab.len() * nresults).
  374. nodes := &nodesByDistance{target: target}
  375. liveNodes := &nodesByDistance{target: target}
  376. for _, b := range &tab.buckets {
  377. for _, n := range b.entries {
  378. nodes.push(n, nresults)
  379. if preferLive && n.livenessChecks > 0 {
  380. liveNodes.push(n, nresults)
  381. }
  382. }
  383. }
  384. if preferLive && len(liveNodes.entries) > 0 {
  385. return liveNodes
  386. }
  387. return nodes
  388. }
  389. // len returns the number of nodes in the table.
  390. func (tab *Table) len() (n int) {
  391. tab.mutex.Lock()
  392. defer tab.mutex.Unlock()
  393. for _, b := range &tab.buckets {
  394. n += len(b.entries)
  395. }
  396. return n
  397. }
  398. // bucketLen returns the number of nodes in the bucket for the given ID.
  399. func (tab *Table) bucketLen(id enode.ID) int {
  400. tab.mutex.Lock()
  401. defer tab.mutex.Unlock()
  402. return len(tab.bucket(id).entries)
  403. }
  404. // bucket returns the bucket for the given node ID hash.
  405. func (tab *Table) bucket(id enode.ID) *bucket {
  406. d := enode.LogDist(tab.self().ID(), id)
  407. return tab.bucketAtDistance(d)
  408. }
  409. func (tab *Table) bucketAtDistance(d int) *bucket {
  410. if d <= bucketMinDistance {
  411. return tab.buckets[0]
  412. }
  413. return tab.buckets[d-bucketMinDistance-1]
  414. }
  415. // addSeenNode adds a node which may or may not be live to the end of a bucket. If the
  416. // bucket has space available, adding the node succeeds immediately. Otherwise, the node is
  417. // added to the replacements list.
  418. //
  419. // The caller must not hold tab.mutex.
  420. func (tab *Table) addSeenNode(n *node) {
  421. if n.ID() == tab.self().ID() {
  422. return
  423. }
  424. tab.mutex.Lock()
  425. defer tab.mutex.Unlock()
  426. b := tab.bucket(n.ID())
  427. if contains(b.entries, n.ID()) {
  428. // Already in bucket, don't add.
  429. return
  430. }
  431. if len(b.entries) >= bucketSize {
  432. // Bucket full, maybe add as replacement.
  433. tab.addReplacement(b, n)
  434. return
  435. }
  436. if !tab.addIP(b, n.IP()) {
  437. // Can't add: IP limit reached.
  438. return
  439. }
  440. // Add to end of bucket:
  441. b.entries = append(b.entries, n)
  442. b.replacements = deleteNode(b.replacements, n)
  443. n.addedAt = time.Now()
  444. if tab.nodeAddedHook != nil {
  445. tab.nodeAddedHook(n)
  446. }
  447. }
  448. // addVerifiedNode adds a node whose existence has been verified recently to the front of a
  449. // bucket. If the node is already in the bucket, it is moved to the front. If the bucket
  450. // has no space, the node is added to the replacements list.
  451. //
  452. // There is an additional safety measure: if the table is still initializing the node
  453. // is not added. This prevents an attack where the table could be filled by just sending
  454. // ping repeatedly.
  455. //
  456. // The caller must not hold tab.mutex.
  457. func (tab *Table) addVerifiedNode(n *node) {
  458. if !tab.isInitDone() {
  459. return
  460. }
  461. if n.ID() == tab.self().ID() {
  462. return
  463. }
  464. tab.mutex.Lock()
  465. defer tab.mutex.Unlock()
  466. b := tab.bucket(n.ID())
  467. if tab.bumpInBucket(b, n) {
  468. // Already in bucket, moved to front.
  469. return
  470. }
  471. if len(b.entries) >= bucketSize {
  472. // Bucket full, maybe add as replacement.
  473. tab.addReplacement(b, n)
  474. return
  475. }
  476. if !tab.addIP(b, n.IP()) {
  477. // Can't add: IP limit reached.
  478. return
  479. }
  480. // Add to front of bucket.
  481. b.entries, _ = pushNode(b.entries, n, bucketSize)
  482. b.replacements = deleteNode(b.replacements, n)
  483. n.addedAt = time.Now()
  484. if tab.nodeAddedHook != nil {
  485. tab.nodeAddedHook(n)
  486. }
  487. }
  488. // delete removes an entry from the node table. It is used to evacuate dead nodes.
  489. func (tab *Table) delete(node *node) {
  490. tab.mutex.Lock()
  491. defer tab.mutex.Unlock()
  492. tab.deleteInBucket(tab.bucket(node.ID()), node)
  493. }
  494. func (tab *Table) addIP(b *bucket, ip net.IP) bool {
  495. if len(ip) == 0 {
  496. return false // Nodes without IP cannot be added.
  497. }
  498. if netutil.IsLAN(ip) {
  499. return true
  500. }
  501. if !tab.ips.Add(ip) {
  502. tab.log.Debug("IP exceeds table limit", "ip", ip)
  503. return false
  504. }
  505. if !b.ips.Add(ip) {
  506. tab.log.Debug("IP exceeds bucket limit", "ip", ip)
  507. tab.ips.Remove(ip)
  508. return false
  509. }
  510. return true
  511. }
  512. func (tab *Table) removeIP(b *bucket, ip net.IP) {
  513. if netutil.IsLAN(ip) {
  514. return
  515. }
  516. tab.ips.Remove(ip)
  517. b.ips.Remove(ip)
  518. }
  519. func (tab *Table) addReplacement(b *bucket, n *node) {
  520. for _, e := range b.replacements {
  521. if e.ID() == n.ID() {
  522. return // already in list
  523. }
  524. }
  525. if !tab.addIP(b, n.IP()) {
  526. return
  527. }
  528. var removed *node
  529. b.replacements, removed = pushNode(b.replacements, n, maxReplacements)
  530. if removed != nil {
  531. tab.removeIP(b, removed.IP())
  532. }
  533. }
  534. // replace removes n from the replacement list and replaces 'last' with it if it is the
  535. // last entry in the bucket. If 'last' isn't the last entry, it has either been replaced
  536. // with someone else or became active.
  537. func (tab *Table) replace(b *bucket, last *node) *node {
  538. if len(b.entries) == 0 || b.entries[len(b.entries)-1].ID() != last.ID() {
  539. // Entry has moved, don't replace it.
  540. return nil
  541. }
  542. // Still the last entry.
  543. if len(b.replacements) == 0 {
  544. tab.deleteInBucket(b, last)
  545. return nil
  546. }
  547. r := b.replacements[tab.rand.Intn(len(b.replacements))]
  548. b.replacements = deleteNode(b.replacements, r)
  549. b.entries[len(b.entries)-1] = r
  550. tab.removeIP(b, last.IP())
  551. return r
  552. }
  553. // bumpInBucket moves the given node to the front of the bucket entry list
  554. // if it is contained in that list.
  555. func (tab *Table) bumpInBucket(b *bucket, n *node) bool {
  556. for i := range b.entries {
  557. if b.entries[i].ID() == n.ID() {
  558. if !n.IP().Equal(b.entries[i].IP()) {
  559. // Endpoint has changed, ensure that the new IP fits into table limits.
  560. tab.removeIP(b, b.entries[i].IP())
  561. if !tab.addIP(b, n.IP()) {
  562. // It doesn't, put the previous one back.
  563. tab.addIP(b, b.entries[i].IP())
  564. return false
  565. }
  566. }
  567. // Move it to the front.
  568. copy(b.entries[1:], b.entries[:i])
  569. b.entries[0] = n
  570. return true
  571. }
  572. }
  573. return false
  574. }
  575. func (tab *Table) deleteInBucket(b *bucket, n *node) {
  576. b.entries = deleteNode(b.entries, n)
  577. tab.removeIP(b, n.IP())
  578. }
  579. func contains(ns []*node, id enode.ID) bool {
  580. for _, n := range ns {
  581. if n.ID() == id {
  582. return true
  583. }
  584. }
  585. return false
  586. }
  587. // pushNode adds n to the front of list, keeping at most max items.
  588. func pushNode(list []*node, n *node, max int) ([]*node, *node) {
  589. if len(list) < max {
  590. list = append(list, nil)
  591. }
  592. removed := list[len(list)-1]
  593. copy(list[1:], list)
  594. list[0] = n
  595. return list, removed
  596. }
  597. // deleteNode removes n from list.
  598. func deleteNode(list []*node, n *node) []*node {
  599. for i := range list {
  600. if list[i].ID() == n.ID() {
  601. return append(list[:i], list[i+1:]...)
  602. }
  603. }
  604. return list
  605. }
  606. // nodesByDistance is a list of nodes, ordered by distance to target.
  607. type nodesByDistance struct {
  608. entries []*node
  609. target enode.ID
  610. }
  611. // push adds the given node to the list, keeping the total size below maxElems.
  612. func (h *nodesByDistance) push(n *node, maxElems int) {
  613. ix := sort.Search(len(h.entries), func(i int) bool {
  614. return enode.DistCmp(h.target, h.entries[i].ID(), n.ID()) > 0
  615. })
  616. if len(h.entries) < maxElems {
  617. h.entries = append(h.entries, n)
  618. }
  619. if ix == len(h.entries) {
  620. // farther away than all nodes we already have.
  621. // if there was room for it, the node is now the last element.
  622. } else {
  623. // slide existing entries down to make room
  624. // this will overwrite the entry we just appended.
  625. copy(h.entries[ix+1:], h.entries[ix:])
  626. h.entries[ix] = n
  627. }
  628. }