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.

177 lines
7.1 KiB

  1. ---
  2. order: 1
  3. parent:
  4. title: Peer Exchange
  5. order: 5
  6. ---
  7. # Peer Strategy and Exchange
  8. Here we outline the design of the PeerStore
  9. and how it used by the Peer Exchange Reactor (PEX) to ensure we are connected
  10. to good peers and to gossip peers to others.
  11. ## Peer Types
  12. Certain peers are special in that they are specified by the user as `persistent`,
  13. which means we auto-redial them if the connection fails, or if we fail to dial
  14. them.
  15. Some peers can be marked as `private`, which means
  16. we will not put them in the peer store or gossip them to others.
  17. All peers except private peers and peers coming from them are tracked using the
  18. peer store.
  19. The rest of our peers are only distinguished by being either
  20. inbound (they dialed our public address) or outbound (we dialed them).
  21. ## Discovery
  22. Peer discovery begins with a list of seeds.
  23. When we don't have enough peers, we
  24. 1. ask existing peers
  25. 2. dial seeds if we're not dialing anyone currently
  26. On startup, we will also immediately dial the given list of `persistent_peers`,
  27. and will attempt to maintain persistent connections with them. If the
  28. connections die, or we fail to dial, we will redial every 5s for a few minutes,
  29. then switch to an exponential backoff schedule, and after about a day of
  30. trying, stop dialing the peer. This behavior is when `persistent_peers_max_dial_period` is configured to zero.
  31. But If `persistent_peers_max_dial_period` is set greater than zero, terms between each dial to each persistent peer
  32. will not exceed `persistent_peers_max_dial_period` during exponential backoff.
  33. Therefore, `dial_period` = min(`persistent_peers_max_dial_period`, `exponential_backoff_dial_period`)
  34. and we keep trying again regardless of `maxAttemptsToDial`
  35. As long as we have less than `MaxNumOutboundPeers`, we periodically request
  36. additional peers from each of our own and try seeds.
  37. ## Listening
  38. Peers listen on a configurable ListenAddr that they self-report in their
  39. NodeInfo during handshakes with other peers. Peers accept up to
  40. `MaxNumInboundPeers` incoming peers.
  41. ## Address Book
  42. Peers are tracked via their ID (their PubKey.Address()).
  43. Peers are added to the peer store from the PEX when they first connect to us or
  44. when we hear about them from other peers.
  45. The peer store is arranged in sets of buckets, and distinguishes between
  46. vetted (old) and unvetted (new) peers. It keeps different sets of buckets for
  47. vetted and unvetted peers. Buckets provide randomization over peer selection.
  48. Peers are put in buckets according to their IP groups.
  49. IP group can be a masked IP (e.g. `1.2.0.0` or `2602:100::`) or `local` for
  50. local addresses or `unroutable` for unroutable addresses. The mask which
  51. corresponds to the `/16` subnet is used for IPv4, `/32` subnet - for IPv6.
  52. Each group has a limited number of buckets to prevent DoS attacks coming from
  53. that group (e.g. an attacker buying a `/16` block of IPs and launching a DoS
  54. attack).
  55. [highwayhash](https://arxiv.org/abs/1612.06257) is used as a hashing function
  56. when calculating a bucket.
  57. When placing a peer into a new bucket:
  58. ```md
  59. hash(key + sourcegroup + int64(hash(key + group + sourcegroup)) % bucket_per_group) % num_new_buckets
  60. ```
  61. When placing a peer into an old bucket:
  62. ```md
  63. hash(key + group + int64(hash(key + addr)) % buckets_per_group) % num_old_buckets
  64. ```
  65. where `key` - random 24 HEX string, `group` - IP group of the peer (e.g. `1.2.0.0`),
  66. `sourcegroup` - IP group of the sender (peer who sent us this address) (e.g. `174.11.0.0`),
  67. `addr` - string representation of the peer's address (e.g. `174.11.10.2:26656`).
  68. A vetted peer can only be in one bucket. An unvetted peer can be in multiple buckets, and
  69. each instance of the peer can have a different IP:PORT.
  70. If we're trying to add a new peer but there's no space in its bucket, we'll
  71. remove the worst peer from that bucket to make room.
  72. ## Vetting
  73. When a peer is first added, it is unvetted.
  74. Marking a peer as vetted is outside the scope of the `p2p` package.
  75. For Tendermint, a Peer becomes vetted once it has contributed sufficiently
  76. at the consensus layer; ie. once it has sent us valid and not-yet-known
  77. votes and/or block parts for `NumBlocksForVetted` blocks.
  78. Other users of the p2p package can determine their own conditions for when a peer is marked vetted.
  79. If a peer becomes vetted but there are already too many vetted peers,
  80. a randomly selected one of the vetted peers becomes unvetted.
  81. If a peer becomes unvetted (either a new peer, or one that was previously vetted),
  82. a randomly selected one of the unvetted peers is removed from the peer store.
  83. More fine-grained tracking of peer behaviour can be done using
  84. a trust metric (see below), but it's best to start with something simple.
  85. ## Select Peers to Dial
  86. When we need more peers, we pick addresses randomly from the addrbook with some
  87. configurable bias for unvetted peers. The bias should be lower when we have
  88. fewer peers and can increase as we obtain more, ensuring that our first peers
  89. are more trustworthy, but always giving us the chance to discover new good
  90. peers.
  91. We track the last time we dialed a peer and the number of unsuccessful attempts
  92. we've made. If too many attempts are made, we mark the peer as bad.
  93. Connection attempts are made with exponential backoff (plus jitter). Because
  94. the selection process happens every `ensurePeersPeriod`, we might not end up
  95. dialing a peer for much longer than the backoff duration.
  96. If we fail to connect to the peer after 16 tries (with exponential backoff), we
  97. remove from peer store completely. But for persistent peers, we indefinitely try to
  98. dial all persistent peers unless `persistent_peers_max_dial_period` is configured to zero
  99. ## Select Peers to Exchange
  100. When we’re asked for peers, we select them as follows:
  101. - select at most `maxGetSelection` peers
  102. - try to select at least `minGetSelection` peers - if we have less than that, select them all.
  103. - select a random, unbiased `getSelectionPercent` of the peers
  104. Send the selected peers. Note we select peers for sending without bias for vetted/unvetted.
  105. ## Preventing Spam
  106. There are various cases where we decide a peer has misbehaved and we disconnect from them.
  107. When this happens, the peer is removed from the peer store and black listed for
  108. some amount of time. We call this "Disconnect and Mark".
  109. Note that the bad behaviour may be detected outside the PEX reactor itself
  110. (for instance, in the mconnection, or another reactor), but it must be communicated to the PEX reactor
  111. so it can remove and mark the peer.
  112. In the PEX, if a peer sends us an unsolicited list of peers,
  113. or if the peer sends a request too soon after another one,
  114. we Disconnect and MarkBad.
  115. ## Trust Metric
  116. The quality of peers can be tracked in more fine-grained detail using a
  117. Proportional-Integral-Derivative (PID) controller that incorporates
  118. current, past, and rate-of-change data to inform peer quality.
  119. While a PID trust metric has been implemented, it remains for future work
  120. to use it in the PEX.
  121. See the [trustmetric](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-006-trust-metric.md)
  122. and [trustmetric useage](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-007-trust-metric-usage.md)
  123. architecture docs for more details.
  124. <!-- todo: diagrams!!! -->