mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 14:52:17 +00:00
p2p: update NodeInfo for versions
This commit is contained in:
parent
ccd04587ff
commit
0254cbf1e6
@ -772,6 +772,9 @@ func makeNodeInfo(
|
|||||||
TxIndex: txIndexerStatus,
|
TxIndex: txIndexerStatus,
|
||||||
RPCAddress: config.RPC.ListenAddress,
|
RPCAddress: config.RPC.ListenAddress,
|
||||||
},
|
},
|
||||||
|
NodeVersion: p2p.NodeVersion{
|
||||||
|
P2P: version.P2PProtocol,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.P2P.PexReactor {
|
if config.P2P.PexReactor {
|
||||||
|
240
p2p/node_info.go
240
p2p/node_info.go
@ -5,6 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
cmn "github.com/tendermint/tendermint/libs/common"
|
cmn "github.com/tendermint/tendermint/libs/common"
|
||||||
|
"github.com/tendermint/tendermint/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -20,42 +21,67 @@ func MaxNodeInfoSize() int {
|
|||||||
// NodeInfo is the basic node information exchanged
|
// NodeInfo is the basic node information exchanged
|
||||||
// between two peers during the Tendermint P2P handshake.
|
// between two peers during the Tendermint P2P handshake.
|
||||||
type NodeInfo struct {
|
type NodeInfo struct {
|
||||||
|
Version VersionInfo `json:"version"`
|
||||||
|
Address AddressInfo `json:"id"`
|
||||||
|
Network NetworkInfo `json:"network"`
|
||||||
|
Services ServiceInfo `json:"services"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// VersionInfo contains all protocol and software version information for the node.
|
||||||
|
type VersionInfo struct {
|
||||||
|
Protocol ProtocolVersion `json:"protocol"`
|
||||||
|
Software version.Software `json:"software"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProtocolVersion contains the p2p, block, and app protocol versions.
|
||||||
|
type ProtocolVersion struct {
|
||||||
|
P2P version.Protocol `json:"p2p"`
|
||||||
|
Block version.Protocol `json:"block"`
|
||||||
|
|
||||||
|
// Don't bother with App for now until we can update it live
|
||||||
|
// App version.Protocol `json:"app"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddressInfo contains info about the peers ID and network address.
|
||||||
|
type AddressInfo struct {
|
||||||
// Authenticate
|
// Authenticate
|
||||||
// TODO: replace with NetAddress
|
// TODO: replace with NetAddress
|
||||||
ID ID `json:"id"` // authenticated identifier
|
ID ID `json:"id"` // authenticated identifier
|
||||||
ListenAddr string `json:"listen_addr"` // accepting incoming
|
ListenAddr string `json:"listen_addr"` // accepting incoming
|
||||||
|
|
||||||
// Check compatibility.
|
|
||||||
// Channels are HexBytes so easier to read as JSON
|
|
||||||
Network string `json:"network"` // network/chain ID
|
|
||||||
Version string `json:"version"` // major.minor.revision
|
|
||||||
Channels cmn.HexBytes `json:"channels"` // channels this node knows about
|
|
||||||
|
|
||||||
// ASCIIText fields
|
// ASCIIText fields
|
||||||
Moniker string `json:"moniker"` // arbitrary moniker
|
Moniker string `json:"moniker"` // arbitrary moniker
|
||||||
Other NodeInfoOther `json:"other"` // other application specific data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeInfoOther is the misc. applcation specific data
|
// NetworkInfo contains info about the network this peer is operating on.
|
||||||
type NodeInfoOther struct {
|
// Currently, the only identifier is the ChainID, known here as the Name.
|
||||||
AminoVersion string `json:"amino_version"`
|
type NetworkInfo struct {
|
||||||
P2PVersion string `json:"p2p_version"`
|
Name string `json:"name"`
|
||||||
ConsensusVersion string `json:"consensus_version"`
|
}
|
||||||
RPCVersion string `json:"rpc_version"`
|
|
||||||
|
// ServiceInfo describes the services this peer offers to other peers and to users.
|
||||||
|
type ServiceInfo struct {
|
||||||
|
Peers PeerServices `json:"peers`
|
||||||
|
Users UserServices `json:"users"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerServices describes the services this peer offers to other peers,
|
||||||
|
// in terms of active Reactor channels.
|
||||||
|
type PeerServices struct {
|
||||||
|
// Channels are HexBytes so easier to read as JSON
|
||||||
|
Channels cmn.HexBytes `json:"channels"` // channels this node knows about
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserServices describes the set of services exposed to the user.
|
||||||
|
type UserServices struct {
|
||||||
TxIndex string `json:"tx_index"`
|
TxIndex string `json:"tx_index"`
|
||||||
RPCAddress string `json:"rpc_address"`
|
RPCAddress string `json:"rpc_address"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o NodeInfoOther) String() string {
|
//--------------------------------------------------------------------------
|
||||||
return fmt.Sprintf(
|
|
||||||
"{amino_version: %v, p2p_version: %v, consensus_version: %v, rpc_version: %v, tx_index: %v, rpc_address: %v}",
|
func (info NodeInfo) ID() ID {
|
||||||
o.AminoVersion,
|
return info.Address.ID
|
||||||
o.P2PVersion,
|
|
||||||
o.ConsensusVersion,
|
|
||||||
o.RPCVersion,
|
|
||||||
o.TxIndex,
|
|
||||||
o.RPCAddress,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks the self-reported NodeInfo is safe.
|
// Validate checks the self-reported NodeInfo is safe.
|
||||||
@ -72,86 +98,144 @@ func (o NodeInfoOther) String() string {
|
|||||||
// url-encoding), and we just need to be careful with how we handle that in our
|
// url-encoding), and we just need to be careful with how we handle that in our
|
||||||
// clients. (e.g. off by default).
|
// clients. (e.g. off by default).
|
||||||
func (info NodeInfo) Validate() error {
|
func (info NodeInfo) Validate() error {
|
||||||
if len(info.Channels) > maxNumChannels {
|
|
||||||
return fmt.Errorf("info.Channels is too long (%v). Max is %v", len(info.Channels), maxNumChannels)
|
if err := info.Version.Validate(); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanitize ASCII text fields.
|
if err := info.Address.Validate(); err != nil {
|
||||||
if !cmn.IsASCIIText(info.Moniker) || cmn.ASCIITrim(info.Moniker) == "" {
|
return err
|
||||||
return fmt.Errorf("info.Moniker must be valid non-empty ASCII text without tabs, but got %v", info.Moniker)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanitize versions
|
if err := info.Network.Validate(); err != nil {
|
||||||
// XXX: Should we be more strict about version and address formats?
|
return err
|
||||||
other := info.Other
|
|
||||||
versions := []string{
|
|
||||||
other.AminoVersion,
|
|
||||||
other.P2PVersion,
|
|
||||||
other.ConsensusVersion,
|
|
||||||
other.RPCVersion}
|
|
||||||
for i, v := range versions {
|
|
||||||
if cmn.ASCIITrim(v) != "" && !cmn.IsASCIIText(v) {
|
|
||||||
return fmt.Errorf("info.Other[%d]=%v must be valid non-empty ASCII text without tabs", i, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cmn.ASCIITrim(other.TxIndex) != "" && (other.TxIndex != "on" && other.TxIndex != "off") {
|
|
||||||
return fmt.Errorf("info.Other.TxIndex should be either 'on' or 'off', got '%v'", other.TxIndex)
|
|
||||||
}
|
|
||||||
if cmn.ASCIITrim(other.RPCAddress) != "" && !cmn.IsASCIIText(other.RPCAddress) {
|
|
||||||
return fmt.Errorf("info.Other.RPCAddress=%v must be valid non-empty ASCII text without tabs", other.RPCAddress)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
channels := make(map[byte]struct{})
|
if err := info.Services.Validate(); err != nil {
|
||||||
for _, ch := range info.Channels {
|
return err
|
||||||
_, ok := channels[ch]
|
|
||||||
if ok {
|
|
||||||
return fmt.Errorf("info.Channels contains duplicate channel id %v", ch)
|
|
||||||
}
|
}
|
||||||
channels[ch] = struct{}{}
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks that the protocol versions are non-zero and that the software versions are ASCII.
|
||||||
|
func (info VersionInfo) Validate() error {
|
||||||
|
// TODO
|
||||||
|
// ProtocolVersion - {P2P, Block} greater than 0
|
||||||
|
// SoftwareVersion - ASCII
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks that the ListenAddr is well formed and that the moniker is ASCII.
|
||||||
|
// The ID should have already been checked.
|
||||||
|
func (info AddressInfo) Validate() error {
|
||||||
|
if _, err := sanitizeASCII(info.Moniker); err != nil {
|
||||||
|
return fmt.Errorf("Moniker %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure ListenAddr is good
|
// ensure ListenAddr is good
|
||||||
_, err := NewNetAddressString(IDAddressString(info.ID, info.ListenAddr))
|
_, err := NewNetAddressString(IDAddressString(info.ID, info.ListenAddr))
|
||||||
return err
|
return err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks that the NetworkInfo.Name is ASCII.
|
||||||
|
func (info NetworkInfo) Validate() error {
|
||||||
|
if _, err := sanitizeASCII(info.Name); err != nil {
|
||||||
|
return fmt.Errorf("Name %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates the PeerServices and UserServices
|
||||||
|
func (info ServiceInfo) Validate() error {
|
||||||
|
|
||||||
|
if err := info.Peers.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := info.Users.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks that there are not too many channels or any duplicate channels.
|
||||||
|
func (services PeerServices) Validate() error {
|
||||||
|
channelBytes := services.Channels
|
||||||
|
if len(channelBytes) > maxNumChannels {
|
||||||
|
return fmt.Errorf("Channels is too long (%v). Max is %v", len(channelBytes), maxNumChannels)
|
||||||
|
}
|
||||||
|
|
||||||
|
channels := make(map[byte]struct{})
|
||||||
|
for _, ch := range channelBytes {
|
||||||
|
_, ok := channels[ch]
|
||||||
|
if ok {
|
||||||
|
return fmt.Errorf("Channels contains duplicate channel id %v", ch)
|
||||||
|
}
|
||||||
|
channels[ch] = struct{}{}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (services UserServices) Validate() error {
|
||||||
|
txIndex, err := sanitizeASCII(services.TxIndex)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("TxIndex %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := sanitizeASCII(services.RPCAddress); err != nil {
|
||||||
|
return fmt.Errorf("RPCAddress %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch cmn.ASCIITrim(txIndex) {
|
||||||
|
case "on", "off":
|
||||||
|
// do nothing
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("TxIndex should be either 'on' or 'off', got '%v'", txIndex)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sanitizeASCII(input string) (string, error) {
|
||||||
|
if !cmn.IsASCIIText(input) || cmn.ASCIITrim(input) == "" {
|
||||||
|
return "", fmt.Errorf("must be valid non-empty ASCII text without tabs, but got %v", input)
|
||||||
|
}
|
||||||
|
return cmn.ASCIITrim(input), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompatibleWith checks if two NodeInfo are compatible with eachother.
|
// CompatibleWith checks if two NodeInfo are compatible with eachother.
|
||||||
// CONTRACT: two nodes are compatible if the major version matches and network match
|
// CONTRACT: two nodes are compatible if the major version matches and network match
|
||||||
// and they have at least one channel in common.
|
// and they have at least one channel in common.
|
||||||
func (info NodeInfo) CompatibleWith(other NodeInfo) error {
|
func (info NodeInfo) CompatibleWith(other NodeInfo) error {
|
||||||
iMajor, _, _, iErr := splitVersion(info.Version)
|
|
||||||
oMajor, _, _, oErr := splitVersion(other.Version)
|
|
||||||
|
|
||||||
// if our own version number is not formatted right, we messed up
|
// if we have no channels, we're just testing
|
||||||
if iErr != nil {
|
ourChannels := info.Services.Peers.Channels
|
||||||
return iErr
|
otherChannels := other.Services.Peers.Channels
|
||||||
|
if len(ourChannels) == 0 {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// version number must be formatted correctly ("x.x.x")
|
// nodes must have the same block version
|
||||||
if oErr != nil {
|
if info.Version.Protocol.Block != other.Version.Protocol.Block {
|
||||||
return oErr
|
return fmt.Errorf(
|
||||||
}
|
"Peer is running a different block protocol. Got %v, expected %v",
|
||||||
|
other.Version.Protocol.Block,
|
||||||
// major version must match
|
info.Version.Protocol.Block,
|
||||||
if iMajor != oMajor {
|
)
|
||||||
return fmt.Errorf("Peer is on a different major version. Got %v, expected %v", oMajor, iMajor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// nodes must be on the same network
|
// nodes must be on the same network
|
||||||
if info.Network != other.Network {
|
if info.Network.Name != other.Network.Name {
|
||||||
return fmt.Errorf("Peer is on a different network. Got %v, expected %v", other.Network, info.Network)
|
return fmt.Errorf("Peer is on a different network. Got %v, expected %v", other.Network.Name, info.Network.Name)
|
||||||
}
|
|
||||||
|
|
||||||
// if we have no channels, we're just testing
|
|
||||||
if len(info.Channels) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// for each of our channels, check if they have it
|
// for each of our channels, check if they have it
|
||||||
found := false
|
found := false
|
||||||
OUTER_LOOP:
|
OUTER_LOOP:
|
||||||
for _, ch1 := range info.Channels {
|
for _, ch1 := range ourChannels {
|
||||||
for _, ch2 := range other.Channels {
|
for _, ch2 := range otherChannels {
|
||||||
if ch1 == ch2 {
|
if ch1 == ch2 {
|
||||||
found = true
|
found = true
|
||||||
break OUTER_LOOP // only need one
|
break OUTER_LOOP // only need one
|
||||||
@ -159,7 +243,7 @@ OUTER_LOOP:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
return fmt.Errorf("Peer has no common channels. Our channels: %v ; Peer channels: %v", info.Channels, other.Channels)
|
return fmt.Errorf("Peer has no common channels. Our channels: %v ; Peer channels: %v", ourChannels, otherChannels)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -169,7 +253,7 @@ OUTER_LOOP:
|
|||||||
// ListenAddr. Note that the ListenAddr is not authenticated and
|
// ListenAddr. Note that the ListenAddr is not authenticated and
|
||||||
// may not match that address actually dialed if its an outbound peer.
|
// may not match that address actually dialed if its an outbound peer.
|
||||||
func (info NodeInfo) NetAddress() *NetAddress {
|
func (info NodeInfo) NetAddress() *NetAddress {
|
||||||
netAddr, err := NewNetAddressString(IDAddressString(info.ID, info.ListenAddr))
|
netAddr, err := NewNetAddressString(IDAddressString(info.Address.ID, info.Address.ListenAddr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
case ErrNetAddressLookup:
|
case ErrNetAddressLookup:
|
||||||
@ -184,8 +268,8 @@ func (info NodeInfo) NetAddress() *NetAddress {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (info NodeInfo) String() string {
|
func (info NodeInfo) String() string {
|
||||||
return fmt.Sprintf("NodeInfo{id: %v, moniker: %v, network: %v [listen %v], version: %v (%v)}",
|
return "TODO" // fmt.Sprintf("NodeInfo{id: %v, moniker: %v, network: %v [listen %v], version: %v (%v)}",
|
||||||
info.ID, info.Moniker, info.Network, info.ListenAddr, info.Version, info.Other)
|
// info.ID, info.Moniker, info.Network, info.ListenAddr, info.Version, info.Other)
|
||||||
}
|
}
|
||||||
|
|
||||||
func splitVersion(version string) (string, string, string, error) {
|
func splitVersion(version string) (string, string, string, error) {
|
||||||
|
@ -120,7 +120,7 @@ func newPeer(
|
|||||||
p := &peer{
|
p := &peer{
|
||||||
peerConn: pc,
|
peerConn: pc,
|
||||||
nodeInfo: nodeInfo,
|
nodeInfo: nodeInfo,
|
||||||
channels: nodeInfo.Channels,
|
channels: nodeInfo.Services.Peers.Channels,
|
||||||
Data: cmn.NewCMap(),
|
Data: cmn.NewCMap(),
|
||||||
metricsTicker: time.NewTicker(metricsTickerDuration),
|
metricsTicker: time.NewTicker(metricsTickerDuration),
|
||||||
metrics: NopMetrics(),
|
metrics: NopMetrics(),
|
||||||
@ -177,7 +177,7 @@ func (p *peer) OnStop() {
|
|||||||
|
|
||||||
// ID returns the peer's ID - the hex encoded hash of its pubkey.
|
// ID returns the peer's ID - the hex encoded hash of its pubkey.
|
||||||
func (p *peer) ID() ID {
|
func (p *peer) ID() ID {
|
||||||
return p.nodeInfo.ID
|
return p.nodeInfo.ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsOutbound returns true if the connection is outbound, false otherwise.
|
// IsOutbound returns true if the connection is outbound, false otherwise.
|
||||||
|
@ -21,9 +21,11 @@ func randPeer(ip net.IP) *peer {
|
|||||||
nodeKey := NodeKey{PrivKey: ed25519.GenPrivKey()}
|
nodeKey := NodeKey{PrivKey: ed25519.GenPrivKey()}
|
||||||
p := &peer{
|
p := &peer{
|
||||||
nodeInfo: NodeInfo{
|
nodeInfo: NodeInfo{
|
||||||
|
Address: AddressInfo{
|
||||||
ID: nodeKey.ID(),
|
ID: nodeKey.ID(),
|
||||||
ListenAddr: fmt.Sprintf("%v.%v.%v.%v:26656", cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256),
|
ListenAddr: fmt.Sprintf("%v.%v.%v.%v:26656", cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256),
|
||||||
},
|
},
|
||||||
|
},
|
||||||
metrics: NopMetrics(),
|
metrics: NopMetrics(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||||
cmn "github.com/tendermint/tendermint/libs/common"
|
cmn "github.com/tendermint/tendermint/libs/common"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
|
"github.com/tendermint/tendermint/version"
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/config"
|
"github.com/tendermint/tendermint/config"
|
||||||
tmconn "github.com/tendermint/tendermint/p2p/conn"
|
tmconn "github.com/tendermint/tendermint/p2p/conn"
|
||||||
@ -82,11 +83,21 @@ func createOutboundPeerAndPerformHandshake(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
nodeInfo, err := pc.HandshakeTimeout(NodeInfo{
|
nodeInfo, err := pc.HandshakeTimeout(NodeInfo{
|
||||||
|
Address: AddressInfo{
|
||||||
ID: addr.ID,
|
ID: addr.ID,
|
||||||
Moniker: "host_peer",
|
Moniker: "host_peer",
|
||||||
Network: "testing",
|
},
|
||||||
Version: "123.123.123",
|
Network: NetworkInfo{"testing"},
|
||||||
|
Version: VersionInfo{
|
||||||
|
Software: version.Software{
|
||||||
|
Tendermint: "123.123.123",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Services: ServiceInfo{
|
||||||
|
Peers: PeerServices{
|
||||||
Channels: []byte{testCh},
|
Channels: []byte{testCh},
|
||||||
|
},
|
||||||
|
},
|
||||||
}, 1*time.Second)
|
}, 1*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -192,12 +203,17 @@ func (rp *remotePeer) accept(l net.Listener) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, err = handshake(pc.conn, time.Second, NodeInfo{
|
_, err = handshake(pc.conn, time.Second, NodeInfo{
|
||||||
|
Address: AddressInfo{
|
||||||
ID: rp.Addr().ID,
|
ID: rp.Addr().ID,
|
||||||
Moniker: "remote_peer",
|
Moniker: "remote_peer",
|
||||||
Network: "testing",
|
|
||||||
Version: "123.123.123",
|
|
||||||
ListenAddr: l.Addr().String(),
|
ListenAddr: l.Addr().String(),
|
||||||
|
},
|
||||||
|
Network: NetworkInfo{"testing"},
|
||||||
|
Services: ServiceInfo{
|
||||||
|
Peers: PeerServices{
|
||||||
Channels: rp.channels,
|
Channels: rp.channels,
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Fatalf("Failed to perform handshake: %+v", err)
|
golog.Fatalf("Failed to perform handshake: %+v", err)
|
||||||
|
@ -25,9 +25,11 @@ func CreateRandomPeer(outbound bool) *peer {
|
|||||||
outbound: outbound,
|
outbound: outbound,
|
||||||
},
|
},
|
||||||
nodeInfo: NodeInfo{
|
nodeInfo: NodeInfo{
|
||||||
|
Address: AddressInfo{
|
||||||
ID: netAddr.ID,
|
ID: netAddr.ID,
|
||||||
ListenAddr: netAddr.DialString(),
|
ListenAddr: netAddr.DialString(),
|
||||||
},
|
},
|
||||||
|
},
|
||||||
mconn: &conn.MConnection{},
|
mconn: &conn.MConnection{},
|
||||||
metrics: NopMetrics(),
|
metrics: NopMetrics(),
|
||||||
}
|
}
|
||||||
@ -164,24 +166,24 @@ func MakeSwitch(
|
|||||||
PrivKey: ed25519.GenPrivKey(),
|
PrivKey: ed25519.GenPrivKey(),
|
||||||
}
|
}
|
||||||
ni = NodeInfo{
|
ni = NodeInfo{
|
||||||
|
Address: AddressInfo{
|
||||||
ID: nodeKey.ID(),
|
ID: nodeKey.ID(),
|
||||||
Moniker: fmt.Sprintf("switch%d", i),
|
|
||||||
Network: network,
|
|
||||||
Version: version,
|
|
||||||
ListenAddr: fmt.Sprintf("127.0.0.1:%d", cmn.RandIntn(64512)+1023),
|
ListenAddr: fmt.Sprintf("127.0.0.1:%d", cmn.RandIntn(64512)+1023),
|
||||||
Other: NodeInfoOther{
|
Moniker: fmt.Sprintf("switch%d", i),
|
||||||
AminoVersion: "1.0",
|
},
|
||||||
P2PVersion: "1.0",
|
Network: NetworkInfo{network},
|
||||||
ConsensusVersion: "1.0",
|
Version: VersionInfo{}, // version,
|
||||||
RPCVersion: "1.0",
|
Services: ServiceInfo{
|
||||||
|
Users: UserServices{
|
||||||
TxIndex: "off",
|
TxIndex: "off",
|
||||||
RPCAddress: fmt.Sprintf("127.0.0.1:%d", cmn.RandIntn(64512)+1023),
|
RPCAddress: fmt.Sprintf("127.0.0.1:%d", cmn.RandIntn(64512)+1023),
|
||||||
},
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
addr, err := NewNetAddressStringWithOptionalID(
|
addr, err := NewNetAddressStringWithOptionalID(
|
||||||
IDAddressString(nodeKey.ID(), ni.ListenAddr),
|
IDAddressString(nodeKey.ID(), ni.Address.ListenAddr),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -199,7 +201,7 @@ func MakeSwitch(
|
|||||||
sw.SetNodeKey(&nodeKey)
|
sw.SetNodeKey(&nodeKey)
|
||||||
|
|
||||||
for ch := range sw.reactorsByCh {
|
for ch := range sw.reactorsByCh {
|
||||||
ni.Channels = append(ni.Channels, ch)
|
ni.Services.Peers.Channels = append(ni.Services.Peers.Channels, ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: We need to setup reactors ahead of time so the NodeInfo is properly
|
// TODO: We need to setup reactors ahead of time so the NodeInfo is properly
|
||||||
|
@ -351,6 +351,32 @@ func (mt *MultiplexTransport) upgrade(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nodeID := nodeInfo.NetAddress().ID
|
||||||
|
|
||||||
|
// Ensure connection key matches self reported key.
|
||||||
|
if connID := PubKeyToID(secretConn.RemotePubKey()); connID != nodeID {
|
||||||
|
return nil, NodeInfo{}, ErrRejected{
|
||||||
|
conn: c,
|
||||||
|
id: connID,
|
||||||
|
err: fmt.Errorf(
|
||||||
|
"conn.ID (%v) NodeInfo.ID (%v) missmatch",
|
||||||
|
connID,
|
||||||
|
nodeID,
|
||||||
|
),
|
||||||
|
isAuthFailure: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reject self.
|
||||||
|
if mt.nodeInfo.NetAddress().ID == nodeID {
|
||||||
|
return nil, NodeInfo{}, ErrRejected{
|
||||||
|
addr: *nodeInfo.NetAddress(),
|
||||||
|
conn: c,
|
||||||
|
id: nodeID,
|
||||||
|
isSelf: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := nodeInfo.Validate(); err != nil {
|
if err := nodeInfo.Validate(); err != nil {
|
||||||
return nil, NodeInfo{}, ErrRejected{
|
return nil, NodeInfo{}, ErrRejected{
|
||||||
conn: c,
|
conn: c,
|
||||||
@ -359,35 +385,11 @@ func (mt *MultiplexTransport) upgrade(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure connection key matches self reported key.
|
|
||||||
if connID := PubKeyToID(secretConn.RemotePubKey()); connID != nodeInfo.ID {
|
|
||||||
return nil, NodeInfo{}, ErrRejected{
|
|
||||||
conn: c,
|
|
||||||
id: connID,
|
|
||||||
err: fmt.Errorf(
|
|
||||||
"conn.ID (%v) NodeInfo.ID (%v) missmatch",
|
|
||||||
connID,
|
|
||||||
nodeInfo.ID,
|
|
||||||
),
|
|
||||||
isAuthFailure: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reject self.
|
|
||||||
if mt.nodeInfo.ID == nodeInfo.ID {
|
|
||||||
return nil, NodeInfo{}, ErrRejected{
|
|
||||||
addr: *NewNetAddress(nodeInfo.ID, c.RemoteAddr()),
|
|
||||||
conn: c,
|
|
||||||
id: nodeInfo.ID,
|
|
||||||
isSelf: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := mt.nodeInfo.CompatibleWith(nodeInfo); err != nil {
|
if err := mt.nodeInfo.CompatibleWith(nodeInfo); err != nil {
|
||||||
return nil, NodeInfo{}, ErrRejected{
|
return nil, NodeInfo{}, ErrRejected{
|
||||||
conn: c,
|
conn: c,
|
||||||
err: err,
|
err: err,
|
||||||
id: nodeInfo.ID,
|
id: nodeInfo.ID(),
|
||||||
isIncompatible: true,
|
isIncompatible: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,6 @@ func TestTransportMultiplexAcceptMultiple(t *testing.T) {
|
|||||||
ID: PubKeyToID(pv.PubKey()),
|
ID: PubKeyToID(pv.PubKey()),
|
||||||
ListenAddr: "127.0.0.1:0",
|
ListenAddr: "127.0.0.1:0",
|
||||||
Moniker: "dialer",
|
Moniker: "dialer",
|
||||||
Version: "1.0.0",
|
|
||||||
},
|
},
|
||||||
NodeKey{
|
NodeKey{
|
||||||
PrivKey: pv,
|
PrivKey: pv,
|
||||||
@ -208,10 +207,11 @@ func TestTransportMultiplexAcceptNonBlocking(t *testing.T) {
|
|||||||
var (
|
var (
|
||||||
fastNodePV = ed25519.GenPrivKey()
|
fastNodePV = ed25519.GenPrivKey()
|
||||||
fastNodeInfo = NodeInfo{
|
fastNodeInfo = NodeInfo{
|
||||||
|
Address: AddressInfo{
|
||||||
ID: PubKeyToID(fastNodePV.PubKey()),
|
ID: PubKeyToID(fastNodePV.PubKey()),
|
||||||
ListenAddr: "127.0.0.1:0",
|
ListenAddr: "127.0.0.1:0",
|
||||||
Moniker: "fastNode",
|
Moniker: "fastNode",
|
||||||
Version: "1.0.0",
|
},
|
||||||
}
|
}
|
||||||
errc = make(chan error)
|
errc = make(chan error)
|
||||||
fastc = make(chan struct{})
|
fastc = make(chan struct{})
|
||||||
@ -249,9 +249,11 @@ func TestTransportMultiplexAcceptNonBlocking(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, err = handshake(sc, 20*time.Millisecond, NodeInfo{
|
_, err = handshake(sc, 20*time.Millisecond, NodeInfo{
|
||||||
|
Address: AddressInfo{
|
||||||
ID: PubKeyToID(ed25519.GenPrivKey().PubKey()),
|
ID: PubKeyToID(ed25519.GenPrivKey().PubKey()),
|
||||||
ListenAddr: "127.0.0.1:0",
|
ListenAddr: "127.0.0.1:0",
|
||||||
Moniker: "slow_peer",
|
Moniker: "slow_peer",
|
||||||
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errc <- err
|
errc <- err
|
||||||
@ -312,10 +314,11 @@ func TestTransportMultiplexValidateNodeInfo(t *testing.T) {
|
|||||||
pv = ed25519.GenPrivKey()
|
pv = ed25519.GenPrivKey()
|
||||||
dialer = NewMultiplexTransport(
|
dialer = NewMultiplexTransport(
|
||||||
NodeInfo{
|
NodeInfo{
|
||||||
|
Address: AddressInfo{
|
||||||
ID: PubKeyToID(pv.PubKey()),
|
ID: PubKeyToID(pv.PubKey()),
|
||||||
ListenAddr: "127.0.0.1:0",
|
ListenAddr: "127.0.0.1:0",
|
||||||
Moniker: "", // Should not be empty.
|
Moniker: "", // Should not be empty.
|
||||||
Version: "1.0.0",
|
},
|
||||||
},
|
},
|
||||||
NodeKey{
|
NodeKey{
|
||||||
PrivKey: pv,
|
PrivKey: pv,
|
||||||
@ -360,10 +363,11 @@ func TestTransportMultiplexRejectMissmatchID(t *testing.T) {
|
|||||||
go func() {
|
go func() {
|
||||||
dialer := NewMultiplexTransport(
|
dialer := NewMultiplexTransport(
|
||||||
NodeInfo{
|
NodeInfo{
|
||||||
|
Address: AddressInfo{
|
||||||
ID: PubKeyToID(ed25519.GenPrivKey().PubKey()),
|
ID: PubKeyToID(ed25519.GenPrivKey().PubKey()),
|
||||||
ListenAddr: "127.0.0.1:0",
|
ListenAddr: "127.0.0.1:0",
|
||||||
Moniker: "dialer",
|
Moniker: "dialer",
|
||||||
Version: "1.0.0",
|
},
|
||||||
},
|
},
|
||||||
NodeKey{
|
NodeKey{
|
||||||
PrivKey: ed25519.GenPrivKey(),
|
PrivKey: ed25519.GenPrivKey(),
|
||||||
@ -409,10 +413,11 @@ func TestTransportMultiplexRejectIncompatible(t *testing.T) {
|
|||||||
pv = ed25519.GenPrivKey()
|
pv = ed25519.GenPrivKey()
|
||||||
dialer = NewMultiplexTransport(
|
dialer = NewMultiplexTransport(
|
||||||
NodeInfo{
|
NodeInfo{
|
||||||
|
Address: AddressInfo{
|
||||||
ID: PubKeyToID(pv.PubKey()),
|
ID: PubKeyToID(pv.PubKey()),
|
||||||
ListenAddr: "127.0.0.1:0",
|
ListenAddr: "127.0.0.1:0",
|
||||||
Moniker: "dialer",
|
Moniker: "dialer",
|
||||||
Version: "2.0.0",
|
},
|
||||||
},
|
},
|
||||||
NodeKey{
|
NodeKey{
|
||||||
PrivKey: pv,
|
PrivKey: pv,
|
||||||
@ -522,7 +527,9 @@ func TestTransportHandshake(t *testing.T) {
|
|||||||
var (
|
var (
|
||||||
peerPV = ed25519.GenPrivKey()
|
peerPV = ed25519.GenPrivKey()
|
||||||
peerNodeInfo = NodeInfo{
|
peerNodeInfo = NodeInfo{
|
||||||
|
Address: AddressInfo{
|
||||||
ID: PubKeyToID(peerPV.PubKey()),
|
ID: PubKeyToID(peerPV.PubKey()),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -573,10 +580,11 @@ func testSetupMultiplexTransport(t *testing.T) *MultiplexTransport {
|
|||||||
pv = ed25519.GenPrivKey()
|
pv = ed25519.GenPrivKey()
|
||||||
mt = NewMultiplexTransport(
|
mt = NewMultiplexTransport(
|
||||||
NodeInfo{
|
NodeInfo{
|
||||||
|
Address: AddressInfo{
|
||||||
ID: PubKeyToID(pv.PubKey()),
|
ID: PubKeyToID(pv.PubKey()),
|
||||||
ListenAddr: "127.0.0.1:0",
|
ListenAddr: "127.0.0.1:0",
|
||||||
Moniker: "transport",
|
Moniker: "transport",
|
||||||
Version: "1.0.0",
|
},
|
||||||
},
|
},
|
||||||
NodeKey{
|
NodeKey{
|
||||||
PrivKey: pv,
|
PrivKey: pv,
|
||||||
|
@ -25,6 +25,11 @@ const (
|
|||||||
ABCIVersion = ABCISemVer
|
ABCIVersion = ABCISemVer
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Software struct {
|
||||||
|
Tendermint string
|
||||||
|
App string
|
||||||
|
}
|
||||||
|
|
||||||
// Protocol is used for implementation agnostic versioning.
|
// Protocol is used for implementation agnostic versioning.
|
||||||
type Protocol uint64
|
type Protocol uint64
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user