You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

851 lines
23 KiB

  1. // Modified for Tendermint
  2. // Originally Copyright (c) 2013-2014 Conformal Systems LLC.
  3. // https://github.com/conformal/btcd/blob/master/LICENSE
  4. package pex
  5. import (
  6. "crypto/sha256"
  7. "encoding/binary"
  8. "fmt"
  9. "math"
  10. "net"
  11. "sync"
  12. "time"
  13. crypto "github.com/tendermint/tendermint/crypto"
  14. cmn "github.com/tendermint/tendermint/libs/common"
  15. "github.com/tendermint/tendermint/p2p"
  16. )
  17. const (
  18. bucketTypeNew = 0x01
  19. bucketTypeOld = 0x02
  20. )
  21. // AddrBook is an address book used for tracking peers
  22. // so we can gossip about them to others and select
  23. // peers to dial.
  24. // TODO: break this up?
  25. type AddrBook interface {
  26. cmn.Service
  27. // Add our own addresses so we don't later add ourselves
  28. AddOurAddress(*p2p.NetAddress)
  29. // Check if it is our address
  30. OurAddress(*p2p.NetAddress) bool
  31. AddPrivateIDs([]string)
  32. // Add and remove an address
  33. AddAddress(addr *p2p.NetAddress, src *p2p.NetAddress) error
  34. RemoveAddress(*p2p.NetAddress)
  35. // Check if the address is in the book
  36. HasAddress(*p2p.NetAddress) bool
  37. // Do we need more peers?
  38. NeedMoreAddrs() bool
  39. // Is Address Book Empty? Answer should not depend on being in your own
  40. // address book, or private peers
  41. Empty() bool
  42. // Pick an address to dial
  43. PickAddress(biasTowardsNewAddrs int) *p2p.NetAddress
  44. // Mark address
  45. MarkGood(*p2p.NetAddress)
  46. MarkAttempt(*p2p.NetAddress)
  47. MarkBad(*p2p.NetAddress)
  48. IsGood(*p2p.NetAddress) bool
  49. // Send a selection of addresses to peers
  50. GetSelection() []*p2p.NetAddress
  51. // Send a selection of addresses with bias
  52. GetSelectionWithBias(biasTowardsNewAddrs int) []*p2p.NetAddress
  53. // TODO: remove
  54. ListOfKnownAddresses() []*knownAddress
  55. // Persist to disk
  56. Save()
  57. }
  58. var _ AddrBook = (*addrBook)(nil)
  59. // addrBook - concurrency safe peer address manager.
  60. // Implements AddrBook.
  61. type addrBook struct {
  62. cmn.BaseService
  63. // immutable after creation
  64. filePath string
  65. routabilityStrict bool
  66. key string // random prefix for bucket placement
  67. // accessed concurrently
  68. mtx sync.Mutex
  69. rand *cmn.Rand
  70. ourAddrs map[string]struct{}
  71. privateIDs map[p2p.ID]struct{}
  72. addrLookup map[p2p.ID]*knownAddress // new & old
  73. bucketsOld []map[string]*knownAddress
  74. bucketsNew []map[string]*knownAddress
  75. nOld int
  76. nNew int
  77. wg sync.WaitGroup
  78. }
  79. // NewAddrBook creates a new address book.
  80. // Use Start to begin processing asynchronous address updates.
  81. func NewAddrBook(filePath string, routabilityStrict bool) *addrBook {
  82. am := &addrBook{
  83. rand: cmn.NewRand(),
  84. ourAddrs: make(map[string]struct{}),
  85. privateIDs: make(map[p2p.ID]struct{}),
  86. addrLookup: make(map[p2p.ID]*knownAddress),
  87. filePath: filePath,
  88. routabilityStrict: routabilityStrict,
  89. }
  90. am.init()
  91. am.BaseService = *cmn.NewBaseService(nil, "AddrBook", am)
  92. return am
  93. }
  94. // Initialize the buckets.
  95. // When modifying this, don't forget to update loadFromFile()
  96. func (a *addrBook) init() {
  97. a.key = crypto.CRandHex(24) // 24/2 * 8 = 96 bits
  98. // New addr buckets
  99. a.bucketsNew = make([]map[string]*knownAddress, newBucketCount)
  100. for i := range a.bucketsNew {
  101. a.bucketsNew[i] = make(map[string]*knownAddress)
  102. }
  103. // Old addr buckets
  104. a.bucketsOld = make([]map[string]*knownAddress, oldBucketCount)
  105. for i := range a.bucketsOld {
  106. a.bucketsOld[i] = make(map[string]*knownAddress)
  107. }
  108. }
  109. // OnStart implements Service.
  110. func (a *addrBook) OnStart() error {
  111. if err := a.BaseService.OnStart(); err != nil {
  112. return err
  113. }
  114. a.loadFromFile(a.filePath)
  115. // wg.Add to ensure that any invocation of .Wait()
  116. // later on will wait for saveRoutine to terminate.
  117. a.wg.Add(1)
  118. go a.saveRoutine()
  119. return nil
  120. }
  121. // OnStop implements Service.
  122. func (a *addrBook) OnStop() {
  123. a.BaseService.OnStop()
  124. }
  125. func (a *addrBook) Wait() {
  126. a.wg.Wait()
  127. }
  128. func (a *addrBook) FilePath() string {
  129. return a.filePath
  130. }
  131. //-------------------------------------------------------
  132. // AddOurAddress one of our addresses.
  133. func (a *addrBook) AddOurAddress(addr *p2p.NetAddress) {
  134. a.mtx.Lock()
  135. defer a.mtx.Unlock()
  136. a.Logger.Info("Add our address to book", "addr", addr)
  137. a.ourAddrs[addr.String()] = struct{}{}
  138. }
  139. // OurAddress returns true if it is our address.
  140. func (a *addrBook) OurAddress(addr *p2p.NetAddress) bool {
  141. a.mtx.Lock()
  142. _, ok := a.ourAddrs[addr.String()]
  143. a.mtx.Unlock()
  144. return ok
  145. }
  146. func (a *addrBook) AddPrivateIDs(IDs []string) {
  147. a.mtx.Lock()
  148. defer a.mtx.Unlock()
  149. for _, id := range IDs {
  150. a.privateIDs[p2p.ID(id)] = struct{}{}
  151. }
  152. }
  153. // AddAddress implements AddrBook
  154. // Add address to a "new" bucket. If it's already in one, only add it probabilistically.
  155. // Returns error if the addr is non-routable. Does not add self.
  156. // NOTE: addr must not be nil
  157. func (a *addrBook) AddAddress(addr *p2p.NetAddress, src *p2p.NetAddress) error {
  158. a.mtx.Lock()
  159. defer a.mtx.Unlock()
  160. return a.addAddress(addr, src)
  161. }
  162. // RemoveAddress implements AddrBook - removes the address from the book.
  163. func (a *addrBook) RemoveAddress(addr *p2p.NetAddress) {
  164. a.mtx.Lock()
  165. defer a.mtx.Unlock()
  166. ka := a.addrLookup[addr.ID]
  167. if ka == nil {
  168. return
  169. }
  170. a.Logger.Info("Remove address from book", "addr", ka.Addr, "ID", ka.ID())
  171. a.removeFromAllBuckets(ka)
  172. }
  173. // IsGood returns true if peer was ever marked as good and haven't
  174. // done anything wrong since then.
  175. func (a *addrBook) IsGood(addr *p2p.NetAddress) bool {
  176. a.mtx.Lock()
  177. defer a.mtx.Unlock()
  178. return a.addrLookup[addr.ID].isOld()
  179. }
  180. // HasAddress returns true if the address is in the book.
  181. func (a *addrBook) HasAddress(addr *p2p.NetAddress) bool {
  182. a.mtx.Lock()
  183. defer a.mtx.Unlock()
  184. ka := a.addrLookup[addr.ID]
  185. return ka != nil
  186. }
  187. // NeedMoreAddrs implements AddrBook - returns true if there are not have enough addresses in the book.
  188. func (a *addrBook) NeedMoreAddrs() bool {
  189. return a.Size() < needAddressThreshold
  190. }
  191. // Empty implements AddrBook - returns true if there are no addresses in the address book.
  192. // Does not count the peer appearing in its own address book, or private peers.
  193. func (a *addrBook) Empty() bool {
  194. return a.Size() == 0
  195. }
  196. // PickAddress implements AddrBook. It picks an address to connect to.
  197. // The address is picked randomly from an old or new bucket according
  198. // to the biasTowardsNewAddrs argument, which must be between [0, 100] (or else is truncated to that range)
  199. // and determines how biased we are to pick an address from a new bucket.
  200. // PickAddress returns nil if the AddrBook is empty or if we try to pick
  201. // from an empty bucket.
  202. func (a *addrBook) PickAddress(biasTowardsNewAddrs int) *p2p.NetAddress {
  203. a.mtx.Lock()
  204. defer a.mtx.Unlock()
  205. bookSize := a.size()
  206. if bookSize <= 0 {
  207. if bookSize < 0 {
  208. a.Logger.Error("Addrbook size less than 0", "nNew", a.nNew, "nOld", a.nOld)
  209. }
  210. return nil
  211. }
  212. if biasTowardsNewAddrs > 100 {
  213. biasTowardsNewAddrs = 100
  214. }
  215. if biasTowardsNewAddrs < 0 {
  216. biasTowardsNewAddrs = 0
  217. }
  218. // Bias between new and old addresses.
  219. oldCorrelation := math.Sqrt(float64(a.nOld)) * (100.0 - float64(biasTowardsNewAddrs))
  220. newCorrelation := math.Sqrt(float64(a.nNew)) * float64(biasTowardsNewAddrs)
  221. // pick a random peer from a random bucket
  222. var bucket map[string]*knownAddress
  223. pickFromOldBucket := (newCorrelation+oldCorrelation)*a.rand.Float64() < oldCorrelation
  224. if (pickFromOldBucket && a.nOld == 0) ||
  225. (!pickFromOldBucket && a.nNew == 0) {
  226. return nil
  227. }
  228. // loop until we pick a random non-empty bucket
  229. for len(bucket) == 0 {
  230. if pickFromOldBucket {
  231. bucket = a.bucketsOld[a.rand.Intn(len(a.bucketsOld))]
  232. } else {
  233. bucket = a.bucketsNew[a.rand.Intn(len(a.bucketsNew))]
  234. }
  235. }
  236. // pick a random index and loop over the map to return that index
  237. randIndex := a.rand.Intn(len(bucket))
  238. for _, ka := range bucket {
  239. if randIndex == 0 {
  240. return ka.Addr
  241. }
  242. randIndex--
  243. }
  244. return nil
  245. }
  246. // MarkGood implements AddrBook - it marks the peer as good and
  247. // moves it into an "old" bucket.
  248. func (a *addrBook) MarkGood(addr *p2p.NetAddress) {
  249. a.mtx.Lock()
  250. defer a.mtx.Unlock()
  251. ka := a.addrLookup[addr.ID]
  252. if ka == nil {
  253. return
  254. }
  255. ka.markGood()
  256. if ka.isNew() {
  257. a.moveToOld(ka)
  258. }
  259. }
  260. // MarkAttempt implements AddrBook - it marks that an attempt was made to connect to the address.
  261. func (a *addrBook) MarkAttempt(addr *p2p.NetAddress) {
  262. a.mtx.Lock()
  263. defer a.mtx.Unlock()
  264. ka := a.addrLookup[addr.ID]
  265. if ka == nil {
  266. return
  267. }
  268. ka.markAttempt()
  269. }
  270. // MarkBad implements AddrBook. Currently it just ejects the address.
  271. // TODO: black list for some amount of time
  272. func (a *addrBook) MarkBad(addr *p2p.NetAddress) {
  273. a.RemoveAddress(addr)
  274. }
  275. // GetSelection implements AddrBook.
  276. // It randomly selects some addresses (old & new). Suitable for peer-exchange protocols.
  277. // Must never return a nil address.
  278. func (a *addrBook) GetSelection() []*p2p.NetAddress {
  279. a.mtx.Lock()
  280. defer a.mtx.Unlock()
  281. bookSize := a.size()
  282. if bookSize <= 0 {
  283. if bookSize < 0 {
  284. a.Logger.Error("Addrbook size less than 0", "nNew", a.nNew, "nOld", a.nOld)
  285. }
  286. return nil
  287. }
  288. numAddresses := cmn.MaxInt(
  289. cmn.MinInt(minGetSelection, bookSize),
  290. bookSize*getSelectionPercent/100)
  291. numAddresses = cmn.MinInt(maxGetSelection, numAddresses)
  292. // XXX: instead of making a list of all addresses, shuffling, and slicing a random chunk,
  293. // could we just select a random numAddresses of indexes?
  294. allAddr := make([]*p2p.NetAddress, bookSize)
  295. i := 0
  296. for _, ka := range a.addrLookup {
  297. allAddr[i] = ka.Addr
  298. i++
  299. }
  300. // Fisher-Yates shuffle the array. We only need to do the first
  301. // `numAddresses' since we are throwing the rest.
  302. for i := 0; i < numAddresses; i++ {
  303. // pick a number between current index and the end
  304. j := cmn.RandIntn(len(allAddr)-i) + i
  305. allAddr[i], allAddr[j] = allAddr[j], allAddr[i]
  306. }
  307. // slice off the limit we are willing to share.
  308. return allAddr[:numAddresses]
  309. }
  310. // GetSelectionWithBias implements AddrBook.
  311. // It randomly selects some addresses (old & new). Suitable for peer-exchange protocols.
  312. // Must never return a nil address.
  313. //
  314. // Each address is picked randomly from an old or new bucket according to the
  315. // biasTowardsNewAddrs argument, which must be between [0, 100] (or else is truncated to
  316. // that range) and determines how biased we are to pick an address from a new
  317. // bucket.
  318. func (a *addrBook) GetSelectionWithBias(biasTowardsNewAddrs int) []*p2p.NetAddress {
  319. a.mtx.Lock()
  320. defer a.mtx.Unlock()
  321. bookSize := a.size()
  322. if bookSize <= 0 {
  323. if bookSize < 0 {
  324. a.Logger.Error("Addrbook size less than 0", "nNew", a.nNew, "nOld", a.nOld)
  325. }
  326. return nil
  327. }
  328. if biasTowardsNewAddrs > 100 {
  329. biasTowardsNewAddrs = 100
  330. }
  331. if biasTowardsNewAddrs < 0 {
  332. biasTowardsNewAddrs = 0
  333. }
  334. numAddresses := cmn.MaxInt(
  335. cmn.MinInt(minGetSelection, bookSize),
  336. bookSize*getSelectionPercent/100)
  337. numAddresses = cmn.MinInt(maxGetSelection, numAddresses)
  338. selection := make([]*p2p.NetAddress, numAddresses)
  339. oldBucketToAddrsMap := make(map[int]map[string]struct{})
  340. var oldIndex int
  341. newBucketToAddrsMap := make(map[int]map[string]struct{})
  342. var newIndex int
  343. selectionIndex := 0
  344. ADDRS_LOOP:
  345. for selectionIndex < numAddresses {
  346. pickFromOldBucket := int((float64(selectionIndex)/float64(numAddresses))*100) >= biasTowardsNewAddrs
  347. pickFromOldBucket = (pickFromOldBucket && a.nOld > 0) || a.nNew == 0
  348. bucket := make(map[string]*knownAddress)
  349. // loop until we pick a random non-empty bucket
  350. for len(bucket) == 0 {
  351. if pickFromOldBucket {
  352. oldIndex = a.rand.Intn(len(a.bucketsOld))
  353. bucket = a.bucketsOld[oldIndex]
  354. } else {
  355. newIndex = a.rand.Intn(len(a.bucketsNew))
  356. bucket = a.bucketsNew[newIndex]
  357. }
  358. }
  359. // pick a random index
  360. randIndex := a.rand.Intn(len(bucket))
  361. // loop over the map to return that index
  362. var selectedAddr *p2p.NetAddress
  363. for _, ka := range bucket {
  364. if randIndex == 0 {
  365. selectedAddr = ka.Addr
  366. break
  367. }
  368. randIndex--
  369. }
  370. // if we have selected the address before, restart the loop
  371. // otherwise, record it and continue
  372. if pickFromOldBucket {
  373. if addrsMap, ok := oldBucketToAddrsMap[oldIndex]; ok {
  374. if _, ok = addrsMap[selectedAddr.String()]; ok {
  375. continue ADDRS_LOOP
  376. }
  377. } else {
  378. oldBucketToAddrsMap[oldIndex] = make(map[string]struct{})
  379. }
  380. oldBucketToAddrsMap[oldIndex][selectedAddr.String()] = struct{}{}
  381. } else {
  382. if addrsMap, ok := newBucketToAddrsMap[newIndex]; ok {
  383. if _, ok = addrsMap[selectedAddr.String()]; ok {
  384. continue ADDRS_LOOP
  385. }
  386. } else {
  387. newBucketToAddrsMap[newIndex] = make(map[string]struct{})
  388. }
  389. newBucketToAddrsMap[newIndex][selectedAddr.String()] = struct{}{}
  390. }
  391. selection[selectionIndex] = selectedAddr
  392. selectionIndex++
  393. }
  394. return selection
  395. }
  396. // ListOfKnownAddresses returns the new and old addresses.
  397. func (a *addrBook) ListOfKnownAddresses() []*knownAddress {
  398. a.mtx.Lock()
  399. defer a.mtx.Unlock()
  400. addrs := []*knownAddress{}
  401. for _, addr := range a.addrLookup {
  402. addrs = append(addrs, addr.copy())
  403. }
  404. return addrs
  405. }
  406. //------------------------------------------------
  407. // Size returns the number of addresses in the book.
  408. func (a *addrBook) Size() int {
  409. a.mtx.Lock()
  410. defer a.mtx.Unlock()
  411. return a.size()
  412. }
  413. func (a *addrBook) size() int {
  414. return a.nNew + a.nOld
  415. }
  416. //----------------------------------------------------------
  417. // Save persists the address book to disk.
  418. func (a *addrBook) Save() {
  419. a.saveToFile(a.filePath) // thread safe
  420. }
  421. func (a *addrBook) saveRoutine() {
  422. defer a.wg.Done()
  423. saveFileTicker := time.NewTicker(dumpAddressInterval)
  424. out:
  425. for {
  426. select {
  427. case <-saveFileTicker.C:
  428. a.saveToFile(a.filePath)
  429. case <-a.Quit():
  430. break out
  431. }
  432. }
  433. saveFileTicker.Stop()
  434. a.saveToFile(a.filePath)
  435. }
  436. //----------------------------------------------------------
  437. func (a *addrBook) getBucket(bucketType byte, bucketIdx int) map[string]*knownAddress {
  438. switch bucketType {
  439. case bucketTypeNew:
  440. return a.bucketsNew[bucketIdx]
  441. case bucketTypeOld:
  442. return a.bucketsOld[bucketIdx]
  443. default:
  444. cmn.PanicSanity("Should not happen")
  445. return nil
  446. }
  447. }
  448. // Adds ka to new bucket. Returns false if it couldn't do it cuz buckets full.
  449. // NOTE: currently it always returns true.
  450. func (a *addrBook) addToNewBucket(ka *knownAddress, bucketIdx int) {
  451. // Sanity check
  452. if ka.isOld() {
  453. a.Logger.Error("Failed Sanity Check! Cant add old address to new bucket", "ka", ka, "bucket", bucketIdx)
  454. return
  455. }
  456. addrStr := ka.Addr.String()
  457. bucket := a.getBucket(bucketTypeNew, bucketIdx)
  458. // Already exists?
  459. if _, ok := bucket[addrStr]; ok {
  460. return
  461. }
  462. // Enforce max addresses.
  463. if len(bucket) > newBucketSize {
  464. a.Logger.Info("new bucket is full, expiring new")
  465. a.expireNew(bucketIdx)
  466. }
  467. // Add to bucket.
  468. bucket[addrStr] = ka
  469. // increment nNew if the peer doesnt already exist in a bucket
  470. if ka.addBucketRef(bucketIdx) == 1 {
  471. a.nNew++
  472. }
  473. // Add it to addrLookup
  474. a.addrLookup[ka.ID()] = ka
  475. }
  476. // Adds ka to old bucket. Returns false if it couldn't do it cuz buckets full.
  477. func (a *addrBook) addToOldBucket(ka *knownAddress, bucketIdx int) bool {
  478. // Sanity check
  479. if ka.isNew() {
  480. a.Logger.Error(fmt.Sprintf("Cannot add new address to old bucket: %v", ka))
  481. return false
  482. }
  483. if len(ka.Buckets) != 0 {
  484. a.Logger.Error(fmt.Sprintf("Cannot add already old address to another old bucket: %v", ka))
  485. return false
  486. }
  487. addrStr := ka.Addr.String()
  488. bucket := a.getBucket(bucketTypeOld, bucketIdx)
  489. // Already exists?
  490. if _, ok := bucket[addrStr]; ok {
  491. return true
  492. }
  493. // Enforce max addresses.
  494. if len(bucket) > oldBucketSize {
  495. return false
  496. }
  497. // Add to bucket.
  498. bucket[addrStr] = ka
  499. if ka.addBucketRef(bucketIdx) == 1 {
  500. a.nOld++
  501. }
  502. // Ensure in addrLookup
  503. a.addrLookup[ka.ID()] = ka
  504. return true
  505. }
  506. func (a *addrBook) removeFromBucket(ka *knownAddress, bucketType byte, bucketIdx int) {
  507. if ka.BucketType != bucketType {
  508. a.Logger.Error(fmt.Sprintf("Bucket type mismatch: %v", ka))
  509. return
  510. }
  511. bucket := a.getBucket(bucketType, bucketIdx)
  512. delete(bucket, ka.Addr.String())
  513. if ka.removeBucketRef(bucketIdx) == 0 {
  514. if bucketType == bucketTypeNew {
  515. a.nNew--
  516. } else {
  517. a.nOld--
  518. }
  519. delete(a.addrLookup, ka.ID())
  520. }
  521. }
  522. func (a *addrBook) removeFromAllBuckets(ka *knownAddress) {
  523. for _, bucketIdx := range ka.Buckets {
  524. bucket := a.getBucket(ka.BucketType, bucketIdx)
  525. delete(bucket, ka.Addr.String())
  526. }
  527. ka.Buckets = nil
  528. if ka.BucketType == bucketTypeNew {
  529. a.nNew--
  530. } else {
  531. a.nOld--
  532. }
  533. delete(a.addrLookup, ka.ID())
  534. }
  535. //----------------------------------------------------------
  536. func (a *addrBook) pickOldest(bucketType byte, bucketIdx int) *knownAddress {
  537. bucket := a.getBucket(bucketType, bucketIdx)
  538. var oldest *knownAddress
  539. for _, ka := range bucket {
  540. if oldest == nil || ka.LastAttempt.Before(oldest.LastAttempt) {
  541. oldest = ka
  542. }
  543. }
  544. return oldest
  545. }
  546. // adds the address to a "new" bucket. if its already in one,
  547. // it only adds it probabilistically
  548. func (a *addrBook) addAddress(addr, src *p2p.NetAddress) error {
  549. if addr == nil || src == nil {
  550. return ErrAddrBookNilAddr{addr, src}
  551. }
  552. if a.routabilityStrict && !addr.Routable() {
  553. return ErrAddrBookNonRoutable{addr}
  554. }
  555. if !addr.Valid() {
  556. return ErrAddrBookInvalidAddr{addr}
  557. }
  558. if !addr.HasID() {
  559. return ErrAddrBookInvalidAddrNoID{addr}
  560. }
  561. // TODO: we should track ourAddrs by ID and by IP:PORT and refuse both.
  562. if _, ok := a.ourAddrs[addr.String()]; ok {
  563. return ErrAddrBookSelf{addr}
  564. }
  565. if _, ok := a.privateIDs[addr.ID]; ok {
  566. return ErrAddrBookPrivate{addr}
  567. }
  568. if _, ok := a.privateIDs[src.ID]; ok {
  569. return ErrAddrBookPrivateSrc{src}
  570. }
  571. ka := a.addrLookup[addr.ID]
  572. if ka != nil {
  573. // If its already old and the addr is the same, ignore it.
  574. if ka.isOld() && ka.Addr.Equals(addr) {
  575. return nil
  576. }
  577. // Already in max new buckets.
  578. if len(ka.Buckets) == maxNewBucketsPerAddress {
  579. return nil
  580. }
  581. // The more entries we have, the less likely we are to add more.
  582. factor := int32(2 * len(ka.Buckets))
  583. if a.rand.Int31n(factor) != 0 {
  584. return nil
  585. }
  586. } else {
  587. ka = newKnownAddress(addr, src)
  588. }
  589. bucket := a.calcNewBucket(addr, src)
  590. a.addToNewBucket(ka, bucket)
  591. return nil
  592. }
  593. // Make space in the new buckets by expiring the really bad entries.
  594. // If no bad entries are available we remove the oldest.
  595. func (a *addrBook) expireNew(bucketIdx int) {
  596. for addrStr, ka := range a.bucketsNew[bucketIdx] {
  597. // If an entry is bad, throw it away
  598. if ka.isBad() {
  599. a.Logger.Info(fmt.Sprintf("expiring bad address %v", addrStr))
  600. a.removeFromBucket(ka, bucketTypeNew, bucketIdx)
  601. return
  602. }
  603. }
  604. // If we haven't thrown out a bad entry, throw out the oldest entry
  605. oldest := a.pickOldest(bucketTypeNew, bucketIdx)
  606. a.removeFromBucket(oldest, bucketTypeNew, bucketIdx)
  607. }
  608. // Promotes an address from new to old. If the destination bucket is full,
  609. // demote the oldest one to a "new" bucket.
  610. // TODO: Demote more probabilistically?
  611. func (a *addrBook) moveToOld(ka *knownAddress) {
  612. // Sanity check
  613. if ka.isOld() {
  614. a.Logger.Error(fmt.Sprintf("Cannot promote address that is already old %v", ka))
  615. return
  616. }
  617. if len(ka.Buckets) == 0 {
  618. a.Logger.Error(fmt.Sprintf("Cannot promote address that isn't in any new buckets %v", ka))
  619. return
  620. }
  621. // Remove from all (new) buckets.
  622. a.removeFromAllBuckets(ka)
  623. // It's officially old now.
  624. ka.BucketType = bucketTypeOld
  625. // Try to add it to its oldBucket destination.
  626. oldBucketIdx := a.calcOldBucket(ka.Addr)
  627. added := a.addToOldBucket(ka, oldBucketIdx)
  628. if !added {
  629. // No room; move the oldest to a new bucket
  630. oldest := a.pickOldest(bucketTypeOld, oldBucketIdx)
  631. a.removeFromBucket(oldest, bucketTypeOld, oldBucketIdx)
  632. newBucketIdx := a.calcNewBucket(oldest.Addr, oldest.Src)
  633. a.addToNewBucket(oldest, newBucketIdx)
  634. // Finally, add our ka to old bucket again.
  635. added = a.addToOldBucket(ka, oldBucketIdx)
  636. if !added {
  637. a.Logger.Error(fmt.Sprintf("Could not re-add ka %v to oldBucketIdx %v", ka, oldBucketIdx))
  638. }
  639. }
  640. }
  641. //---------------------------------------------------------------------
  642. // calculate bucket placements
  643. // doublesha256( key + sourcegroup +
  644. // int64(doublesha256(key + group + sourcegroup))%bucket_per_group ) % num_new_buckets
  645. func (a *addrBook) calcNewBucket(addr, src *p2p.NetAddress) int {
  646. data1 := []byte{}
  647. data1 = append(data1, []byte(a.key)...)
  648. data1 = append(data1, []byte(a.groupKey(addr))...)
  649. data1 = append(data1, []byte(a.groupKey(src))...)
  650. hash1 := doubleSha256(data1)
  651. hash64 := binary.BigEndian.Uint64(hash1)
  652. hash64 %= newBucketsPerGroup
  653. var hashbuf [8]byte
  654. binary.BigEndian.PutUint64(hashbuf[:], hash64)
  655. data2 := []byte{}
  656. data2 = append(data2, []byte(a.key)...)
  657. data2 = append(data2, a.groupKey(src)...)
  658. data2 = append(data2, hashbuf[:]...)
  659. hash2 := doubleSha256(data2)
  660. return int(binary.BigEndian.Uint64(hash2) % newBucketCount)
  661. }
  662. // doublesha256( key + group +
  663. // int64(doublesha256(key + addr))%buckets_per_group ) % num_old_buckets
  664. func (a *addrBook) calcOldBucket(addr *p2p.NetAddress) int {
  665. data1 := []byte{}
  666. data1 = append(data1, []byte(a.key)...)
  667. data1 = append(data1, []byte(addr.String())...)
  668. hash1 := doubleSha256(data1)
  669. hash64 := binary.BigEndian.Uint64(hash1)
  670. hash64 %= oldBucketsPerGroup
  671. var hashbuf [8]byte
  672. binary.BigEndian.PutUint64(hashbuf[:], hash64)
  673. data2 := []byte{}
  674. data2 = append(data2, []byte(a.key)...)
  675. data2 = append(data2, a.groupKey(addr)...)
  676. data2 = append(data2, hashbuf[:]...)
  677. hash2 := doubleSha256(data2)
  678. return int(binary.BigEndian.Uint64(hash2) % oldBucketCount)
  679. }
  680. // Return a string representing the network group of this address.
  681. // This is the /16 for IPv4, the /32 (/36 for he.net) for IPv6, the string
  682. // "local" for a local address and the string "unroutable" for an unroutable
  683. // address.
  684. func (a *addrBook) groupKey(na *p2p.NetAddress) string {
  685. if a.routabilityStrict && na.Local() {
  686. return "local"
  687. }
  688. if a.routabilityStrict && !na.Routable() {
  689. return "unroutable"
  690. }
  691. if ipv4 := na.IP.To4(); ipv4 != nil {
  692. return (&net.IPNet{IP: na.IP, Mask: net.CIDRMask(16, 32)}).String()
  693. }
  694. if na.RFC6145() || na.RFC6052() {
  695. // last four bytes are the ip address
  696. ip := net.IP(na.IP[12:16])
  697. return (&net.IPNet{IP: ip, Mask: net.CIDRMask(16, 32)}).String()
  698. }
  699. if na.RFC3964() {
  700. ip := net.IP(na.IP[2:7])
  701. return (&net.IPNet{IP: ip, Mask: net.CIDRMask(16, 32)}).String()
  702. }
  703. if na.RFC4380() {
  704. // teredo tunnels have the last 4 bytes as the v4 address XOR
  705. // 0xff.
  706. ip := net.IP(make([]byte, 4))
  707. for i, byte := range na.IP[12:16] {
  708. ip[i] = byte ^ 0xff
  709. }
  710. return (&net.IPNet{IP: ip, Mask: net.CIDRMask(16, 32)}).String()
  711. }
  712. // OK, so now we know ourselves to be a IPv6 address.
  713. // bitcoind uses /32 for everything, except for Hurricane Electric's
  714. // (he.net) IP range, which it uses /36 for.
  715. bits := 32
  716. heNet := &net.IPNet{IP: net.ParseIP("2001:470::"),
  717. Mask: net.CIDRMask(32, 128)}
  718. if heNet.Contains(na.IP) {
  719. bits = 36
  720. }
  721. return (&net.IPNet{IP: na.IP, Mask: net.CIDRMask(bits, 128)}).String()
  722. }
  723. // doubleSha256 calculates sha256(sha256(b)) and returns the resulting bytes.
  724. func doubleSha256(b []byte) []byte {
  725. hasher := sha256.New()
  726. hasher.Write(b) // nolint: errcheck, gas
  727. sum := hasher.Sum(nil)
  728. hasher.Reset()
  729. hasher.Write(sum) // nolint: errcheck, gas
  730. return hasher.Sum(nil)
  731. }