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.

821 lines
22 KiB

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