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.

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