p2p: update NodeInfo for versions

This commit is contained in:
Ethan Buchman 2018-09-26 18:47:58 -07:00
parent ccd04587ff
commit 0254cbf1e6
9 changed files with 286 additions and 164 deletions

View File

@ -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 {

View File

@ -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"`
TxIndex string `json:"tx_index"`
RPCAddress string `json:"rpc_address"`
} }
func (o NodeInfoOther) String() string { // ServiceInfo describes the services this peer offers to other peers and to users.
return fmt.Sprintf( type ServiceInfo struct {
"{amino_version: %v, p2p_version: %v, consensus_version: %v, rpc_version: %v, tx_index: %v, rpc_address: %v}", Peers PeerServices `json:"peers`
o.AminoVersion, Users UserServices `json:"users"`
o.P2PVersion, }
o.ConsensusVersion,
o.RPCVersion, // PeerServices describes the services this peer offers to other peers,
o.TxIndex, // in terms of active Reactor channels.
o.RPCAddress, 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"`
RPCAddress string `json:"rpc_address"`
}
//--------------------------------------------------------------------------
func (info NodeInfo) ID() ID {
return info.Address.ID
} }
// 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) return nil
} }
channels[ch] = struct{}{}
// 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) {

View File

@ -102,7 +102,7 @@ type peer struct {
// User data // User data
Data *cmn.CMap Data *cmn.CMap
metrics *Metrics metrics *Metrics
metricsTicker *time.Ticker metricsTicker *time.Ticker
} }
@ -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.

View File

@ -21,8 +21,10 @@ func randPeer(ip net.IP) *peer {
nodeKey := NodeKey{PrivKey: ed25519.GenPrivKey()} nodeKey := NodeKey{PrivKey: ed25519.GenPrivKey()}
p := &peer{ p := &peer{
nodeInfo: NodeInfo{ nodeInfo: NodeInfo{
ID: nodeKey.ID(), Address: AddressInfo{
ListenAddr: fmt.Sprintf("%v.%v.%v.%v:26656", cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256), ID: nodeKey.ID(),
ListenAddr: fmt.Sprintf("%v.%v.%v.%v:26656", cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256),
},
}, },
metrics: NopMetrics(), metrics: NopMetrics(),
} }

View File

@ -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{
ID: addr.ID, Address: AddressInfo{
Moniker: "host_peer", ID: addr.ID,
Network: "testing", Moniker: "host_peer",
Version: "123.123.123", },
Channels: []byte{testCh}, Network: NetworkInfo{"testing"},
Version: VersionInfo{
Software: version.Software{
Tendermint: "123.123.123",
},
},
Services: ServiceInfo{
Peers: PeerServices{
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{
ID: rp.Addr().ID, Address: AddressInfo{
Moniker: "remote_peer", ID: rp.Addr().ID,
Network: "testing", Moniker: "remote_peer",
Version: "123.123.123", ListenAddr: l.Addr().String(),
ListenAddr: l.Addr().String(), },
Channels: rp.channels, Network: NetworkInfo{"testing"},
Services: ServiceInfo{
Peers: PeerServices{
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)

View File

@ -25,8 +25,10 @@ func CreateRandomPeer(outbound bool) *peer {
outbound: outbound, outbound: outbound,
}, },
nodeInfo: NodeInfo{ nodeInfo: NodeInfo{
ID: netAddr.ID, Address: AddressInfo{
ListenAddr: netAddr.DialString(), ID: netAddr.ID,
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{
ID: nodeKey.ID(), Address: AddressInfo{
Moniker: fmt.Sprintf("switch%d", i), ID: nodeKey.ID(),
Network: network, ListenAddr: fmt.Sprintf("127.0.0.1:%d", cmn.RandIntn(64512)+1023),
Version: version, Moniker: fmt.Sprintf("switch%d", i),
ListenAddr: fmt.Sprintf("127.0.0.1:%d", cmn.RandIntn(64512)+1023), },
Other: NodeInfoOther{ Network: NetworkInfo{network},
AminoVersion: "1.0", Version: VersionInfo{}, // version,
P2PVersion: "1.0", Services: ServiceInfo{
ConsensusVersion: "1.0", Users: UserServices{
RPCVersion: "1.0", 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

View File

@ -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,
} }
} }

View File

@ -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{
ID: PubKeyToID(fastNodePV.PubKey()), Address: AddressInfo{
ListenAddr: "127.0.0.1:0", ID: PubKeyToID(fastNodePV.PubKey()),
Moniker: "fastNode", ListenAddr: "127.0.0.1:0",
Version: "1.0.0", Moniker: "fastNode",
},
} }
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{
ID: PubKeyToID(ed25519.GenPrivKey().PubKey()), Address: AddressInfo{
ListenAddr: "127.0.0.1:0", ID: PubKeyToID(ed25519.GenPrivKey().PubKey()),
Moniker: "slow_peer", ListenAddr: "127.0.0.1:0",
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{
ID: PubKeyToID(pv.PubKey()), Address: AddressInfo{
ListenAddr: "127.0.0.1:0", ID: PubKeyToID(pv.PubKey()),
Moniker: "", // Should not be empty. ListenAddr: "127.0.0.1:0",
Version: "1.0.0", Moniker: "", // Should not be empty.
},
}, },
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{
ID: PubKeyToID(ed25519.GenPrivKey().PubKey()), Address: AddressInfo{
ListenAddr: "127.0.0.1:0", ID: PubKeyToID(ed25519.GenPrivKey().PubKey()),
Moniker: "dialer", ListenAddr: "127.0.0.1:0",
Version: "1.0.0", Moniker: "dialer",
},
}, },
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{
ID: PubKeyToID(pv.PubKey()), Address: AddressInfo{
ListenAddr: "127.0.0.1:0", ID: PubKeyToID(pv.PubKey()),
Moniker: "dialer", ListenAddr: "127.0.0.1:0",
Version: "2.0.0", Moniker: "dialer",
},
}, },
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{
ID: PubKeyToID(peerPV.PubKey()), Address: AddressInfo{
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{
ID: PubKeyToID(pv.PubKey()), Address: AddressInfo{
ListenAddr: "127.0.0.1:0", ID: PubKeyToID(pv.PubKey()),
Moniker: "transport", ListenAddr: "127.0.0.1:0",
Version: "1.0.0", Moniker: "transport",
},
}, },
NodeKey{ NodeKey{
PrivKey: pv, PrivKey: pv,

View File

@ -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