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.

118 lines
5.2 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. # Tendermint Peers
  2. This document explains how Tendermint Peers are identified, how they connect to one another,
  3. and how other peers are found.
  4. ## Peer Identity
  5. Tendermint peers are expected to maintain long-term persistent identities in the form of a private key.
  6. Each peer has an ID defined as `peer.ID == peer.PrivKey.Address()`, where `Address` uses the scheme defined in go-crypto.
  7. Peer ID's must come with some Proof-of-Work; that is,
  8. they must satisfy `peer.PrivKey.Address() < target` for some difficulty target.
  9. This ensures they are not too easy to generate. To begin, let `target == 2^240`.
  10. A single peer ID can have multiple IP addresses associated with it.
  11. For simplicity, we only keep track of the latest one.
  12. When attempting to connect to a peer, we use the PeerURL: `<ID>@<IP>:<PORT>`.
  13. We will attempt to connect to the peer at IP:PORT, and verify,
  14. via authenticated encryption, that it is in possession of the private key
  15. corresponding to `<ID>`. This prevents man-in-the-middle attacks on the peer layer.
  16. Peers can also be connected to without specifying an ID, ie. just `<IP>:<PORT>`.
  17. In this case, the peer must be authenticated out-of-band of Tendermint,
  18. for instance via VPN
  19. ## Connections
  20. All p2p connections use TCP.
  21. Upon establishing a successful TCP connection with a peer,
  22. two handhsakes are performed: one for authenticated encryption, and one for Tendermint versioning.
  23. Both handshakes have configurable timeouts (they should complete quickly).
  24. ### Authenticated Encryption Handshake
  25. Tendermint implements the Station-to-Station protocol
  26. using ED25519 keys for Diffie-Helman key-exchange and NACL SecretBox for encryption.
  27. It goes as follows:
  28. - generate an emphemeral ED25519 keypair
  29. - send the ephemeral public key to the peer
  30. - wait to receive the peer's ephemeral public key
  31. - compute the Diffie-Hellman shared secret using the peers ephemeral public key and our ephemeral private key
  32. - generate two nonces to use for encryption (sending and receiving) as follows:
  33. - sort the ephemeral public keys in ascending order and concatenate them
  34. - RIPEMD160 the result
  35. - append 4 empty bytes (extending the hash to 24-bytes)
  36. - the result is nonce1
  37. - flip the last bit of nonce1 to get nonce2
  38. - if we had the smaller ephemeral pubkey, use nonce1 for receiving, nonce2 for sending;
  39. else the opposite
  40. - all communications from now on are encrypted using the shared secret and the nonces, where each nonce
  41. - we now have an encrypted channel, but still need to authenticate
  42. increments by 2 every time it is used
  43. - generate a common challenge to sign:
  44. - SHA256 of the sorted (lowest first) and concatenated ephemeral pub keys
  45. - sign the common challenge with our persistent private key
  46. - send the go-wire encoded persistent pubkey and signature to the peer
  47. - wait to receive the persistent public key and signature from the peer
  48. - verify the signature on the challenge using the peer's persistent public key
  49. If this is an outgoing connection (we dialed the peer) and we used a peer ID,
  50. then finally verify that the peer's persistent public key corresponds to the peer ID we dialed,
  51. ie. `peer.PubKey.Address() == <ID>`.
  52. The connection has now been authenticated. All traffic is encrypted.
  53. Note that only the dialer can authenticate the identity of the peer,
  54. but this is what we care about since when we join the network we wish to
  55. ensure we have reached the intended peer (and are not being MITMd).
  56. ### Peer Filter
  57. Before continuing, we check if the new peer has the same ID as ourselves or
  58. an existing peer. If so, we disconnect.
  59. We also check the peer's address and public key against
  60. an optional whitelist which can be managed through the ABCI app -
  61. if the whitelist is enabled and the peer does not qualigy, the connection is
  62. terminated.
  63. ### Tendermint Version Handshake
  64. The Tendermint Version Handshake allows the peers to exchange their NodeInfo:
  65. ```
  66. type NodeInfo struct {
  67. PubKey crypto.PubKey `json:"pub_key"`
  68. Moniker string `json:"moniker"`
  69. Network string `json:"network"`
  70. RemoteAddr string `json:"remote_addr"`
  71. ListenAddr string `json:"listen_addr"` // accepting in
  72. Version string `json:"version"` // major.minor.revision
  73. Channels []int8 `json:"channels"` // active reactor channels
  74. Other []string `json:"other"` // other application specific data
  75. }
  76. ```
  77. The connection is disconnected if:
  78. - `peer.NodeInfo.PubKey != peer.PubKey`
  79. - `peer.NodeInfo.Version` is not formatted as `X.X.X` where X are integers known as Major, Minor, and Revision
  80. - `peer.NodeInfo.Version` Major is not the same as ours
  81. - `peer.NodeInfo.Version` Minor is not the same as ours
  82. - `peer.NodeInfo.Network` is not the same as ours
  83. - `peer.Channels` does not intersect with our known Channels.
  84. At this point, if we have not disconnected, the peer is valid.
  85. It is added to the switch and hence all reactors via the `AddPeer` method.
  86. Note that each reactor may handle multiple channels.
  87. ## Connection Activity
  88. Once a peer is added, incoming messages for a given reactor are handled through
  89. that reactor's `Receive` method, and output messages are sent directly by the Reactors
  90. on each peer. A typical reactor maintains per-peer go-routine/s that handle this.