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.

811 lines
22 KiB

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