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.

138 lines
4.0 KiB

9 years ago
9 years ago
9 years ago
p2p: introduce peerConn to simplify peer creation (#1226) * expose AuthEnc in the P2P config if AuthEnc is true, dialed peers must have a node ID in the address and it must match the persistent pubkey from the secret handshake. Refs #1157 * fixes after my own review * fix docs * fix build failure ``` p2p/pex/pex_reactor_test.go:288:88: cannot use seed.NodeInfo().NetAddress() (type *p2p.NetAddress) as type string in array or slice literal ``` * p2p: introduce peerConn to simplify peer creation * Introduce `peerConn` containing the known fields of `peer` * `peer` only created in `sw.addPeer` once handshake is complete and NodeInfo is checked * Eliminates some mutable variables and makes the code flow better * Simplifies the `newXxxPeer` funcs * Use ID instead of PubKey where possible. * SetPubKeyFilter -> SetIDFilter * nodeInfo.Validate takes ID * remove peer.PubKey() * persistent node ids * fixes from review * test: use ip_plus_id.sh more * fix invalid memory panic during fast_sync test ``` 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: panic: runtime error: invalid memory address or nil pointer dereference 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: [signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x98dd3e] 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: goroutine 3432 [running]: 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.newOutboundPeerConn(0xc423fd1380, 0xc420933e00, 0x1, 0x1239a60, 0 xc420128c40, 0x2, 0x42caf6, 0xc42001f300, 0xc422831d98, 0xc4227951c0, ...) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/peer.go:123 +0x31e 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.(*Switch).addOutboundPeerWithConfig(0xc4200ad040, 0xc423fd1380, 0 xc420933e00, 0xc423f48801, 0x28, 0x2) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:455 +0x12b 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.(*Switch).DialPeerWithAddress(0xc4200ad040, 0xc423fd1380, 0x1, 0x 0, 0x0) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:371 +0xdc 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.(*Switch).reconnectToPeer(0xc4200ad040, 0x123e000, 0xc42007bb00) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:290 +0x25f 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: created by github.com/tendermint/tendermint/p2p.(*Switch).StopPeerForError 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:256 +0x1b7 ```
7 years ago
p2p: introduce peerConn to simplify peer creation (#1226) * expose AuthEnc in the P2P config if AuthEnc is true, dialed peers must have a node ID in the address and it must match the persistent pubkey from the secret handshake. Refs #1157 * fixes after my own review * fix docs * fix build failure ``` p2p/pex/pex_reactor_test.go:288:88: cannot use seed.NodeInfo().NetAddress() (type *p2p.NetAddress) as type string in array or slice literal ``` * p2p: introduce peerConn to simplify peer creation * Introduce `peerConn` containing the known fields of `peer` * `peer` only created in `sw.addPeer` once handshake is complete and NodeInfo is checked * Eliminates some mutable variables and makes the code flow better * Simplifies the `newXxxPeer` funcs * Use ID instead of PubKey where possible. * SetPubKeyFilter -> SetIDFilter * nodeInfo.Validate takes ID * remove peer.PubKey() * persistent node ids * fixes from review * test: use ip_plus_id.sh more * fix invalid memory panic during fast_sync test ``` 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: panic: runtime error: invalid memory address or nil pointer dereference 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: [signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x98dd3e] 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: goroutine 3432 [running]: 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.newOutboundPeerConn(0xc423fd1380, 0xc420933e00, 0x1, 0x1239a60, 0 xc420128c40, 0x2, 0x42caf6, 0xc42001f300, 0xc422831d98, 0xc4227951c0, ...) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/peer.go:123 +0x31e 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.(*Switch).addOutboundPeerWithConfig(0xc4200ad040, 0xc423fd1380, 0 xc420933e00, 0xc423f48801, 0x28, 0x2) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:455 +0x12b 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.(*Switch).DialPeerWithAddress(0xc4200ad040, 0xc423fd1380, 0x1, 0x 0, 0x0) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:371 +0xdc 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.(*Switch).reconnectToPeer(0xc4200ad040, 0x123e000, 0xc42007bb00) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:290 +0x25f 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: created by github.com/tendermint/tendermint/p2p.(*Switch).StopPeerForError 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:256 +0x1b7 ```
7 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package p2p
  2. import (
  3. "fmt"
  4. "strings"
  5. crypto "github.com/tendermint/go-crypto"
  6. )
  7. const (
  8. maxNodeInfoSize = 10240 // 10Kb
  9. maxNumChannels = 16 // plenty of room for upgrades, for now
  10. )
  11. func MaxNodeInfoSize() int {
  12. return maxNodeInfoSize
  13. }
  14. // NodeInfo is the basic node information exchanged
  15. // between two peers during the Tendermint P2P handshake.
  16. type NodeInfo struct {
  17. // Authenticate
  18. PubKey crypto.PubKey `json:"pub_key"` // authenticated pubkey
  19. ListenAddr string `json:"listen_addr"` // accepting incoming
  20. // Check compatibility
  21. Network string `json:"network"` // network/chain ID
  22. Version string `json:"version"` // major.minor.revision
  23. Channels []byte `json:"channels"` // channels this node knows about
  24. // Sanitize
  25. Moniker string `json:"moniker"` // arbitrary moniker
  26. Other []string `json:"other"` // other application specific data
  27. }
  28. // Validate checks the self-reported NodeInfo is safe.
  29. // It returns an error if there
  30. // are too many Channels or any duplicate Channels.
  31. // TODO: constraints for Moniker/Other? Or is that for the UI ?
  32. func (info NodeInfo) Validate() error {
  33. if len(info.Channels) > maxNumChannels {
  34. return fmt.Errorf("info.Channels is too long (%v). Max is %v", len(info.Channels), maxNumChannels)
  35. }
  36. channels := make(map[byte]struct{})
  37. for _, ch := range info.Channels {
  38. _, ok := channels[ch]
  39. if ok {
  40. return fmt.Errorf("info.Channels contains duplicate channel id %v", ch)
  41. }
  42. channels[ch] = struct{}{}
  43. }
  44. return nil
  45. }
  46. // CompatibleWith checks if two NodeInfo are compatible with eachother.
  47. // CONTRACT: two nodes are compatible if the major/minor versions match and network match
  48. // and they have at least one channel in common.
  49. func (info NodeInfo) CompatibleWith(other NodeInfo) error {
  50. iMajor, iMinor, _, iErr := splitVersion(info.Version)
  51. oMajor, oMinor, _, oErr := splitVersion(other.Version)
  52. // if our own version number is not formatted right, we messed up
  53. if iErr != nil {
  54. return iErr
  55. }
  56. // version number must be formatted correctly ("x.x.x")
  57. if oErr != nil {
  58. return oErr
  59. }
  60. // major version must match
  61. if iMajor != oMajor {
  62. return fmt.Errorf("Peer is on a different major version. Got %v, expected %v", oMajor, iMajor)
  63. }
  64. // minor version must match
  65. if iMinor != oMinor {
  66. return fmt.Errorf("Peer is on a different minor version. Got %v, expected %v", oMinor, iMinor)
  67. }
  68. // nodes must be on the same network
  69. if info.Network != other.Network {
  70. return fmt.Errorf("Peer is on a different network. Got %v, expected %v", other.Network, info.Network)
  71. }
  72. // if we have no channels, we're just testing
  73. if len(info.Channels) == 0 {
  74. return nil
  75. }
  76. // for each of our channels, check if they have it
  77. found := false
  78. OUTER_LOOP:
  79. for _, ch1 := range info.Channels {
  80. for _, ch2 := range other.Channels {
  81. if ch1 == ch2 {
  82. found = true
  83. break OUTER_LOOP // only need one
  84. }
  85. }
  86. }
  87. if !found {
  88. return fmt.Errorf("Peer has no common channels. Our channels: %v ; Peer channels: %v", info.Channels, other.Channels)
  89. }
  90. return nil
  91. }
  92. func (info NodeInfo) ID() ID {
  93. return PubKeyToID(info.PubKey)
  94. }
  95. // NetAddress returns a NetAddress derived from the NodeInfo -
  96. // it includes the authenticated peer ID and the self-reported
  97. // ListenAddr. Note that the ListenAddr is not authenticated and
  98. // may not match that address actually dialed if its an outbound peer.
  99. func (info NodeInfo) NetAddress() *NetAddress {
  100. id := PubKeyToID(info.PubKey)
  101. addr := info.ListenAddr
  102. netAddr, err := NewNetAddressString(IDAddressString(id, addr))
  103. if err != nil {
  104. panic(err) // everything should be well formed by now
  105. }
  106. return netAddr
  107. }
  108. func (info NodeInfo) String() string {
  109. return fmt.Sprintf("NodeInfo{pk: %v, moniker: %v, network: %v [listen %v], version: %v (%v)}", info.PubKey, info.Moniker, info.Network, info.ListenAddr, info.Version, info.Other)
  110. }
  111. func splitVersion(version string) (string, string, string, error) {
  112. spl := strings.Split(version, ".")
  113. if len(spl) != 3 {
  114. return "", "", "", fmt.Errorf("Invalid version format %v", version)
  115. }
  116. return spl[0], spl[1], spl[2], nil
  117. }