github.com/etherbanking/go-etherbanking@v1.7.1-0.20181009210156-cf649bca5aba/p2p/discover/table.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 implements the Node Discovery Protocol. 18 // 19 // The Node Discovery protocol provides a way to find RLPx nodes that 20 // can be connected to. It uses a Kademlia-like protocol to maintain a 21 // distributed database of the IDs and endpoints of all listening 22 // nodes. 23 package discover 24 25 import ( 26 "crypto/rand" 27 "encoding/binary" 28 "errors" 29 "fmt" 30 "net" 31 "sort" 32 "sync" 33 "time" 34 //"encoding/json" 35 36 37 "github.com/etherbanking/go-etherbanking/common" 38 "github.com/etherbanking/go-etherbanking/crypto" 39 "github.com/etherbanking/go-etherbanking/log" 40 ) 41 42 const ( 43 alpha = 3 // Kademlia concurrency factor 44 bucketSize = 16 // Kademlia bucket size 45 hashBits = len(common.Hash{}) * 8 46 nBuckets = hashBits + 1 // Number of buckets 47 48 maxBondingPingPongs = 16 49 maxFindnodeFailures = 5 50 51 autoRefreshInterval = 1 * time.Hour 52 seedCount = 30 53 seedMaxAge = 5 * 24 * time.Hour 54 ) 55 56 type Table struct { 57 mutex sync.Mutex // protects buckets, their content, and nursery 58 buckets [nBuckets]*bucket // index of known nodes by distance 59 nursery []*Node // bootstrap nodes 60 db *nodeDB // database of known nodes 61 62 refreshReq chan chan struct{} 63 closeReq chan struct{} 64 closed chan struct{} 65 66 bondmu sync.Mutex 67 bonding map[NodeID]*bondproc 68 bondslots chan struct{} // limits total number of active bonding processes 69 70 nodeAddedHook func(*Node) // for testing 71 72 net transport 73 self *Node // metadata of the local node 74 } 75 76 type bondproc struct { 77 err error 78 n *Node 79 done chan struct{} 80 } 81 82 // transport is implemented by the UDP transport. 83 // it is an interface so we can test without opening lots of UDP 84 // sockets and without generating a private key. 85 type transport interface { 86 ping(NodeID, *net.UDPAddr) error 87 waitping(NodeID) error 88 findnode(toid NodeID, addr *net.UDPAddr, target NodeID) ([]*Node, error) 89 close() 90 } 91 92 // bucket contains nodes, ordered by their last activity. the entry 93 // that was most recently active is the first element in entries. 94 type bucket struct{ entries []*Node } 95 96 func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, nodeDBPath string) (*Table, error) { 97 // If no node database was given, use an in-memory one 98 db, err := newNodeDB(nodeDBPath, Version, ourID) 99 if err != nil { 100 return nil, err 101 } 102 tab := &Table{ 103 net: t, 104 db: db, 105 self: NewNode(ourID, ourAddr.IP, uint16(ourAddr.Port), uint16(ourAddr.Port)), 106 bonding: make(map[NodeID]*bondproc), 107 bondslots: make(chan struct{}, maxBondingPingPongs), 108 refreshReq: make(chan chan struct{}), 109 closeReq: make(chan struct{}), 110 closed: make(chan struct{}), 111 } 112 for i := 0; i < cap(tab.bondslots); i++ { 113 tab.bondslots <- struct{}{} 114 } 115 for i := range tab.buckets { 116 tab.buckets[i] = new(bucket) 117 } 118 go tab.refreshLoop() 119 return tab, nil 120 } 121 122 // Self returns the local node. 123 // The returned node should not be modified by the caller. 124 func (tab *Table) Self() *Node { 125 return tab.self 126 } 127 128 // ReadRandomNodes fills the given slice with random nodes from the 129 // table. It will not write the same node more than once. The nodes in 130 // the slice are copies and can be modified by the caller. 131 func (tab *Table) ReadRandomNodes(buf []*Node) (n int) { 132 tab.mutex.Lock() 133 defer tab.mutex.Unlock() 134 // TODO: tree-based buckets would help here 135 // Find all non-empty buckets and get a fresh slice of their entries. 136 var buckets [][]*Node 137 for _, b := range tab.buckets { 138 if len(b.entries) > 0 { 139 buckets = append(buckets, b.entries[:]) 140 } 141 } 142 if len(buckets) == 0 { 143 return 0 144 } 145 // Shuffle the buckets. 146 for i := uint32(len(buckets)) - 1; i > 0; i-- { 147 j := randUint(i) 148 buckets[i], buckets[j] = buckets[j], buckets[i] 149 } 150 // Move head of each bucket into buf, removing buckets that become empty. 151 var i, j int 152 for ; i < len(buf); i, j = i+1, (j+1)%len(buckets) { 153 b := buckets[j] 154 buf[i] = &(*b[0]) 155 buckets[j] = b[1:] 156 if len(b) == 1 { 157 buckets = append(buckets[:j], buckets[j+1:]...) 158 } 159 if len(buckets) == 0 { 160 break 161 } 162 } 163 return i + 1 164 } 165 166 func randUint(max uint32) uint32 { 167 if max == 0 { 168 return 0 169 } 170 var b [4]byte 171 rand.Read(b[:]) 172 return binary.BigEndian.Uint32(b[:]) % max 173 } 174 175 // Close terminates the network listener and flushes the node database. 176 func (tab *Table) Close() { 177 select { 178 case <-tab.closed: 179 // already closed. 180 case tab.closeReq <- struct{}{}: 181 <-tab.closed // wait for refreshLoop to end. 182 } 183 } 184 185 // SetFallbackNodes sets the initial points of contact. These nodes 186 // are used to connect to the network if the table is empty and there 187 // are no known nodes in the database. 188 func (tab *Table) SetFallbackNodes(nodes []*Node) error { 189 for _, n := range nodes { 190 if err := n.validateComplete(); err != nil { 191 return fmt.Errorf("bad bootstrap/fallback node %q (%v)", n, err) 192 } 193 } 194 tab.mutex.Lock() 195 tab.nursery = make([]*Node, 0, len(nodes)) 196 for _, n := range nodes { 197 cpy := *n 198 // Recompute cpy.sha because the node might not have been 199 // created by NewNode or ParseNode. 200 cpy.sha = crypto.Keccak256Hash(n.ID[:]) 201 tab.nursery = append(tab.nursery, &cpy) 202 } 203 tab.mutex.Unlock() 204 tab.refresh() 205 return nil 206 } 207 208 // Resolve searches for a specific node with the given ID. 209 // It returns nil if the node could not be found. 210 func (tab *Table) Resolve(targetID NodeID) *Node { 211 // If the node is present in the local table, no 212 // network interaction is required. 213 hash := crypto.Keccak256Hash(targetID[:]) 214 tab.mutex.Lock() 215 cl := tab.closest(hash, 1) 216 tab.mutex.Unlock() 217 if len(cl.entries) > 0 && cl.entries[0].ID == targetID { 218 return cl.entries[0] 219 } 220 // Otherwise, do a network lookup. 221 result := tab.Lookup(targetID) 222 for _, n := range result { 223 if n.ID == targetID { 224 return n 225 } 226 } 227 return nil 228 } 229 230 // Lookup performs a network search for nodes close 231 // to the given target. It approaches the target by querying 232 // nodes that are closer to it on each iteration. 233 // The given target does not need to be an actual node 234 // identifier. 235 func (tab *Table) Lookup(targetID NodeID) []*Node { 236 return tab.lookup(targetID, true) 237 } 238 239 func (tab *Table) lookup(targetID NodeID, refreshIfEmpty bool) []*Node { 240 var ( 241 target = crypto.Keccak256Hash(targetID[:]) 242 asked = make(map[NodeID]bool) 243 seen = make(map[NodeID]bool) 244 reply = make(chan []*Node, alpha) 245 pendingQueries = 0 246 result *nodesByDistance 247 ) 248 // don't query further if we hit ourself. 249 // unlikely to happen often in practice. 250 asked[tab.self.ID] = true 251 252 for { 253 tab.mutex.Lock() 254 // generate initial result set 255 result = tab.closest(target, bucketSize) 256 tab.mutex.Unlock() 257 if len(result.entries) > 0 || !refreshIfEmpty { 258 break 259 } 260 // The result set is empty, all nodes were dropped, refresh. 261 // We actually wait for the refresh to complete here. The very 262 // first query will hit this case and run the bootstrapping 263 // logic. 264 <-tab.refresh() 265 refreshIfEmpty = false 266 } 267 268 for { 269 // ask the alpha closest nodes that we haven't asked yet 270 for i := 0; i < len(result.entries) && pendingQueries < alpha; i++ { 271 n := result.entries[i] 272 if !asked[n.ID] { 273 asked[n.ID] = true 274 pendingQueries++ 275 go func() { 276 // Find potential neighbors to bond with 277 r, err := tab.net.findnode(n.ID, n.addr(), targetID) 278 if err != nil { 279 // Bump the failure counter to detect and evacuate non-bonded entries 280 fails := tab.db.findFails(n.ID) + 1 281 tab.db.updateFindFails(n.ID, fails) 282 log.Trace("Bumping findnode failure counter", "id", n.ID, "failcount", fails) 283 284 if fails >= maxFindnodeFailures { 285 log.Trace("Too many findnode failures, dropping", "id", n.ID, "failcount", fails) 286 tab.delete(n) 287 } 288 } 289 reply <- tab.bondall(r) 290 }() 291 } 292 } 293 if pendingQueries == 0 { 294 // we have asked all closest nodes, stop the search 295 break 296 } 297 // wait for the next reply 298 for _, n := range <-reply { 299 if n != nil && !seen[n.ID] { 300 seen[n.ID] = true 301 result.push(n, bucketSize) 302 } 303 } 304 pendingQueries-- 305 } 306 return result.entries 307 } 308 309 func (tab *Table) refresh() <-chan struct{} { 310 done := make(chan struct{}) 311 select { 312 case tab.refreshReq <- done: 313 case <-tab.closed: 314 close(done) 315 } 316 return done 317 } 318 319 // refreshLoop schedules doRefresh runs and coordinates shutdown. 320 func (tab *Table) refreshLoop() { 321 var ( 322 timer = time.NewTicker(autoRefreshInterval) 323 waiting []chan struct{} // accumulates waiting callers while doRefresh runs 324 done chan struct{} // where doRefresh reports completion 325 ) 326 loop: 327 for { 328 select { 329 case <-timer.C: 330 if done == nil { 331 done = make(chan struct{}) 332 go tab.doRefresh(done) 333 } 334 case req := <-tab.refreshReq: 335 waiting = append(waiting, req) 336 if done == nil { 337 done = make(chan struct{}) 338 go tab.doRefresh(done) 339 } 340 case <-done: 341 for _, ch := range waiting { 342 close(ch) 343 } 344 waiting = nil 345 done = nil 346 case <-tab.closeReq: 347 break loop 348 } 349 } 350 351 if tab.net != nil { 352 tab.net.close() 353 } 354 if done != nil { 355 <-done 356 } 357 for _, ch := range waiting { 358 close(ch) 359 } 360 tab.db.close() 361 close(tab.closed) 362 } 363 364 // doRefresh performs a lookup for a random target to keep buckets 365 // full. seed nodes are inserted if the table is empty (initial 366 // bootstrap or discarded faulty peers). 367 func (tab *Table) doRefresh(done chan struct{}) { 368 defer close(done) 369 370 // The Kademlia paper specifies that the bucket refresh should 371 // perform a lookup in the least recently used bucket. We cannot 372 // adhere to this because the findnode target is a 512bit value 373 // (not hash-sized) and it is not easily possible to generate a 374 // sha3 preimage that falls into a chosen bucket. 375 // We perform a lookup with a random target instead. 376 var target NodeID 377 rand.Read(target[:]) 378 result := tab.lookup(target, false) 379 if len(result) > 0 { 380 return 381 } 382 383 // The table is empty. Load nodes from the database and insert 384 // them. This should yield a few previously seen nodes that are 385 // (hopefully) still alive. 386 seeds := tab.db.querySeeds(seedCount, seedMaxAge) 387 seeds = tab.bondall(append(seeds, tab.nursery...)) 388 389 if len(seeds) == 0 { 390 log.Debug("No discv4 seed nodes found") 391 } 392 for _, n := range seeds { 393 age := log.Lazy{Fn: func() time.Duration { return time.Since(tab.db.lastPong(n.ID)) }} 394 log.Trace("Found seed node in database", "id", n.ID, "addr", n.addr(), "age", age) 395 } 396 tab.mutex.Lock() 397 tab.stuff(seeds) 398 tab.mutex.Unlock() 399 400 // Finally, do a self lookup to fill up the buckets. 401 tab.lookup(tab.self.ID, false) 402 } 403 404 // closest returns the n nodes in the table that are closest to the 405 // given id. The caller must hold tab.mutex. 406 func (tab *Table) closest(target common.Hash, nresults int) *nodesByDistance { 407 // This is a very wasteful way to find the closest nodes but 408 // obviously correct. I believe that tree-based buckets would make 409 // this easier to implement efficiently. 410 close := &nodesByDistance{target: target} 411 for _, b := range tab.buckets { 412 for _, n := range b.entries { 413 close.push(n, nresults) 414 } 415 } 416 return close 417 } 418 419 func (tab *Table) len() (n int) { 420 for _, b := range tab.buckets { 421 n += len(b.entries) 422 } 423 return n 424 } 425 426 // bondall bonds with all given nodes concurrently and returns 427 // those nodes for which bonding has probably succeeded. 428 func (tab *Table) bondall(nodes []*Node) (result []*Node) { 429 rc := make(chan *Node, len(nodes)) 430 for i := range nodes { 431 go func(n *Node) { 432 nn, _ := tab.bond(false, n.ID, n.addr(), uint16(n.TCP)) 433 rc <- nn 434 }(nodes[i]) 435 } 436 for range nodes { 437 if n := <-rc; n != nil { 438 result = append(result, n) 439 } 440 } 441 return result 442 } 443 444 // bond ensures the local node has a bond with the given remote node. 445 // It also attempts to insert the node into the table if bonding succeeds. 446 // The caller must not hold tab.mutex. 447 // 448 // A bond is must be established before sending findnode requests. 449 // Both sides must have completed a ping/pong exchange for a bond to 450 // exist. The total number of active bonding processes is limited in 451 // order to restrain network use. 452 // 453 // bond is meant to operate idempotently in that bonding with a remote 454 // node which still remembers a previously established bond will work. 455 // The remote node will simply not send a ping back, causing waitping 456 // to time out. 457 // 458 // If pinged is true, the remote node has just pinged us and one half 459 // of the process can be skipped. 460 func (tab *Table) bond(pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16) (*Node, error) { 461 if id == tab.self.ID { 462 return nil, errors.New("is self") 463 } 464 // Retrieve a previously known node and any recent findnode failures 465 node, fails := tab.db.node(id), 0 466 if node != nil { 467 fails = tab.db.findFails(id) 468 } 469 // If the node is unknown (non-bonded) or failed (remotely unknown), bond from scratch 470 var result error 471 age := time.Since(tab.db.lastPong(id)) 472 if node == nil || fails > 0 || age > nodeDBNodeExpiration { 473 log.Trace("Starting bonding ping/pong", "id", id, "known", node != nil, "failcount", fails, "age", age) 474 475 tab.bondmu.Lock() 476 w := tab.bonding[id] 477 if w != nil { 478 // Wait for an existing bonding process to complete. 479 tab.bondmu.Unlock() 480 <-w.done 481 } else { 482 // Register a new bonding process. 483 w = &bondproc{done: make(chan struct{})} 484 tab.bonding[id] = w 485 tab.bondmu.Unlock() 486 // Do the ping/pong. The result goes into w. 487 tab.pingpong(w, pinged, id, addr, tcpPort) 488 // Unregister the process after it's done. 489 tab.bondmu.Lock() 490 delete(tab.bonding, id) 491 tab.bondmu.Unlock() 492 } 493 // Retrieve the bonding results 494 result = w.err 495 if result == nil { 496 node = w.n 497 } 498 } 499 if node != nil { 500 // Add the node to the table even if the bonding ping/pong 501 // fails. It will be relaced quickly if it continues to be 502 // unresponsive. 503 tab.add(node) 504 tab.db.updateFindFails(id, 0) 505 } 506 return node, result 507 } 508 509 func (tab *Table) pingpong(w *bondproc, pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16) { 510 // Request a bonding slot to limit network usage 511 <-tab.bondslots 512 defer func() { tab.bondslots <- struct{}{} }() 513 514 // Ping the remote side and wait for a pong. 515 if w.err = tab.ping(id, addr); w.err != nil { 516 close(w.done) 517 return 518 } 519 if !pinged { 520 // Give the remote node a chance to ping us before we start 521 // sending findnode requests. If they still remember us, 522 // waitping will simply time out. 523 tab.net.waitping(id) 524 } 525 // Bonding succeeded, update the node database. 526 w.n = NewNode(id, addr.IP, uint16(addr.Port), tcpPort) 527 tab.db.updateNode(w.n) 528 close(w.done) 529 } 530 531 // ping a remote endpoint and wait for a reply, also updating the node 532 // database accordingly. 533 func (tab *Table) ping(id NodeID, addr *net.UDPAddr) error { 534 535 tab.db.updateLastPing(id, time.Now()) 536 if err := tab.net.ping(id, addr); err != nil { 537 538 return err 539 } 540 tab.db.updateLastPong(id, time.Now()) 541 542 // Start the background expiration goroutine after the first 543 // successful communication. Subsequent calls have no effect if it 544 // is already running. We do this here instead of somewhere else 545 // so that the search for seed nodes also considers older nodes 546 // that would otherwise be removed by the expiration. 547 tab.db.ensureExpirer() 548 return nil 549 } 550 551 // add attempts to add the given node its corresponding bucket. If the 552 // bucket has space available, adding the node succeeds immediately. 553 // Otherwise, the node is added if the least recently active node in 554 // the bucket does not respond to a ping packet. 555 // 556 // The caller must not hold tab.mutex. 557 func (tab *Table) add(new *Node) { 558 b := tab.buckets[logdist(tab.self.sha, new.sha)] 559 tab.mutex.Lock() 560 defer tab.mutex.Unlock() 561 if b.bump(new) { 562 return 563 } 564 var oldest *Node 565 if len(b.entries) == bucketSize { 566 oldest = b.entries[bucketSize-1] 567 if oldest.contested { 568 // The node is already being replaced, don't attempt 569 // to replace it. 570 return 571 } 572 oldest.contested = true 573 // Let go of the mutex so other goroutines can access 574 // the table while we ping the least recently active node. 575 tab.mutex.Unlock() 576 err := tab.ping(oldest.ID, oldest.addr()) 577 tab.mutex.Lock() 578 oldest.contested = false 579 if err == nil { 580 // The node responded, don't replace it. 581 return 582 } 583 } 584 added := b.replace(new, oldest) 585 if added && tab.nodeAddedHook != nil { 586 tab.nodeAddedHook(new) 587 } 588 } 589 590 // stuff adds nodes the table to the end of their corresponding bucket 591 // if the bucket is not full. The caller must hold tab.mutex. 592 func (tab *Table) stuff(nodes []*Node) { 593 outer: 594 for _, n := range nodes { 595 if n.ID == tab.self.ID { 596 continue // don't add self 597 } 598 bucket := tab.buckets[logdist(tab.self.sha, n.sha)] 599 for i := range bucket.entries { 600 if bucket.entries[i].ID == n.ID { 601 continue outer // already in bucket 602 } 603 } 604 if len(bucket.entries) < bucketSize { 605 bucket.entries = append(bucket.entries, n) 606 if tab.nodeAddedHook != nil { 607 tab.nodeAddedHook(n) 608 } 609 } 610 } 611 } 612 613 // delete removes an entry from the node table (used to evacuate 614 // failed/non-bonded discovery peers). 615 func (tab *Table) delete(node *Node) { 616 tab.mutex.Lock() 617 defer tab.mutex.Unlock() 618 bucket := tab.buckets[logdist(tab.self.sha, node.sha)] 619 for i := range bucket.entries { 620 if bucket.entries[i].ID == node.ID { 621 bucket.entries = append(bucket.entries[:i], bucket.entries[i+1:]...) 622 return 623 } 624 } 625 } 626 627 func (b *bucket) replace(n *Node, last *Node) bool { 628 // Don't add if b already contains n. 629 for i := range b.entries { 630 if b.entries[i].ID == n.ID { 631 return false 632 } 633 } 634 // Replace last if it is still the last entry or just add n if b 635 // isn't full. If is no longer the last entry, it has either been 636 // replaced with someone else or became active. 637 if len(b.entries) == bucketSize && (last == nil || b.entries[bucketSize-1].ID != last.ID) { 638 return false 639 } 640 if len(b.entries) < bucketSize { 641 b.entries = append(b.entries, nil) 642 } 643 copy(b.entries[1:], b.entries) 644 b.entries[0] = n 645 return true 646 } 647 648 func (b *bucket) bump(n *Node) bool { 649 for i := range b.entries { 650 if b.entries[i].ID == n.ID { 651 // move it to the front 652 copy(b.entries[1:], b.entries[:i]) 653 b.entries[0] = n 654 return true 655 } 656 } 657 return false 658 } 659 660 // nodesByDistance is a list of nodes, ordered by 661 // distance to target. 662 type nodesByDistance struct { 663 entries []*Node 664 target common.Hash 665 } 666 667 // push adds the given node to the list, keeping the total size below maxElems. 668 func (h *nodesByDistance) push(n *Node, maxElems int) { 669 ix := sort.Search(len(h.entries), func(i int) bool { 670 return distcmp(h.target, h.entries[i].sha, n.sha) > 0 671 }) 672 if len(h.entries) < maxElems { 673 h.entries = append(h.entries, n) 674 } 675 if ix == len(h.entries) { 676 // farther away than all nodes we already have. 677 // if there was room for it, the node is now the last element. 678 } else { 679 // slide existing entries down to make room 680 // this will overwrite the entry we just appended. 681 copy(h.entries[ix+1:], h.entries[ix:]) 682 h.entries[ix] = n 683 } 684 }