types: move NodeInfo from p2p (#6618)

This commit is contained in:
Sam Kleinman
2021-06-24 12:18:19 -04:00
committed by GitHub
parent 2cc872543b
commit 9ffa7e8a2b
28 changed files with 219 additions and 177 deletions

View File

@@ -45,8 +45,8 @@ func (mp mockPeer) IsOutbound() bool { return true }
func (mp mockPeer) IsPersistent() bool { return true }
func (mp mockPeer) CloseConn() error { return nil }
func (mp mockPeer) NodeInfo() p2p.NodeInfo {
return p2p.NodeInfo{
func (mp mockPeer) NodeInfo() types.NodeInfo {
return types.NodeInfo{
NodeID: "",
ListenAddr: "",
}

View File

@@ -45,8 +45,8 @@ func NewPeer(ip net.IP) *Peer {
func (mp *Peer) FlushStop() { mp.Stop() } //nolint:errcheck //ignore error
func (mp *Peer) TrySend(chID byte, msgBytes []byte) bool { return true }
func (mp *Peer) Send(chID byte, msgBytes []byte) bool { return true }
func (mp *Peer) NodeInfo() p2p.NodeInfo {
return p2p.NodeInfo{
func (mp *Peer) NodeInfo() types.NodeInfo {
return types.NodeInfo{
NodeID: mp.addr.ID,
ListenAddr: mp.addr.DialString(),
}

View File

@@ -12,6 +12,8 @@ import (
mock "github.com/stretchr/testify/mock"
p2p "github.com/tendermint/tendermint/internal/p2p"
types "github.com/tendermint/tendermint/types"
)
// Connection is an autogenerated mock type for the Connection type
@@ -48,18 +50,18 @@ func (_m *Connection) FlushClose() error {
}
// Handshake provides a mock function with given fields: _a0, _a1, _a2
func (_m *Connection) Handshake(_a0 context.Context, _a1 p2p.NodeInfo, _a2 crypto.PrivKey) (p2p.NodeInfo, crypto.PubKey, error) {
func (_m *Connection) Handshake(_a0 context.Context, _a1 types.NodeInfo, _a2 crypto.PrivKey) (types.NodeInfo, crypto.PubKey, error) {
ret := _m.Called(_a0, _a1, _a2)
var r0 p2p.NodeInfo
if rf, ok := ret.Get(0).(func(context.Context, p2p.NodeInfo, crypto.PrivKey) p2p.NodeInfo); ok {
var r0 types.NodeInfo
if rf, ok := ret.Get(0).(func(context.Context, types.NodeInfo, crypto.PrivKey) types.NodeInfo); ok {
r0 = rf(_a0, _a1, _a2)
} else {
r0 = ret.Get(0).(p2p.NodeInfo)
r0 = ret.Get(0).(types.NodeInfo)
}
var r1 crypto.PubKey
if rf, ok := ret.Get(1).(func(context.Context, p2p.NodeInfo, crypto.PrivKey) crypto.PubKey); ok {
if rf, ok := ret.Get(1).(func(context.Context, types.NodeInfo, crypto.PrivKey) crypto.PubKey); ok {
r1 = rf(_a0, _a1, _a2)
} else {
if ret.Get(1) != nil {
@@ -68,7 +70,7 @@ func (_m *Connection) Handshake(_a0 context.Context, _a1 p2p.NodeInfo, _a2 crypt
}
var r2 error
if rf, ok := ret.Get(2).(func(context.Context, p2p.NodeInfo, crypto.PrivKey) error); ok {
if rf, ok := ret.Get(2).(func(context.Context, types.NodeInfo, crypto.PrivKey) error); ok {
r2 = rf(_a0, _a1, _a2)
} else {
r2 = ret.Error(2)

View File

@@ -5,13 +5,12 @@ package mocks
import (
conn "github.com/tendermint/tendermint/internal/p2p/conn"
log "github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/types"
mock "github.com/stretchr/testify/mock"
net "net"
p2p "github.com/tendermint/tendermint/internal/p2p"
types "github.com/tendermint/tendermint/types"
)
// Peer is an autogenerated mock type for the Peer type
@@ -111,14 +110,14 @@ func (_m *Peer) IsRunning() bool {
}
// NodeInfo provides a mock function with given fields:
func (_m *Peer) NodeInfo() p2p.NodeInfo {
func (_m *Peer) NodeInfo() types.NodeInfo {
ret := _m.Called()
var r0 p2p.NodeInfo
if rf, ok := ret.Get(0).(func() p2p.NodeInfo); ok {
var r0 types.NodeInfo
if rf, ok := ret.Get(0).(func() types.NodeInfo); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(p2p.NodeInfo)
r0 = ret.Get(0).(types.NodeInfo)
}
return r0
@@ -244,15 +243,15 @@ func (_m *Peer) SetLogger(_a0 log.Logger) {
}
// SocketAddr provides a mock function with given fields:
func (_m *Peer) SocketAddr() *p2p.NetAddress {
func (_m *Peer) SocketAddr() *types.NetAddress {
ret := _m.Called()
var r0 *p2p.NetAddress
if rf, ok := ret.Get(0).(func() *p2p.NetAddress); ok {
var r0 *types.NetAddress
if rf, ok := ret.Get(0).(func() *types.NetAddress); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*p2p.NetAddress)
r0 = ret.Get(0).(*types.NetAddress)
}
}

View File

@@ -1,239 +0,0 @@
package p2p
import (
"errors"
"fmt"
"github.com/tendermint/tendermint/libs/bytes"
tmstrings "github.com/tendermint/tendermint/libs/strings"
tmp2p "github.com/tendermint/tendermint/proto/tendermint/p2p"
"github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/version"
)
const (
maxNodeInfoSize = 10240 // 10KB
maxNumChannels = 16 // plenty of room for upgrades, for now
)
// Max size of the NodeInfo struct
func MaxNodeInfoSize() int {
return maxNodeInfoSize
}
// ProtocolVersion contains the protocol versions for the software.
type ProtocolVersion struct {
P2P uint64 `json:"p2p"`
Block uint64 `json:"block"`
App uint64 `json:"app"`
}
// defaultProtocolVersion populates the Block and P2P versions using
// the global values, but not the App.
var defaultProtocolVersion = NewProtocolVersion(
version.P2PProtocol,
version.BlockProtocol,
0,
)
// NewProtocolVersion returns a fully populated ProtocolVersion.
func NewProtocolVersion(p2p, block, app uint64) ProtocolVersion {
return ProtocolVersion{
P2P: p2p,
Block: block,
App: app,
}
}
//-------------------------------------------------------------
// NodeInfo is the basic node information exchanged
// between two peers during the Tendermint P2P handshake.
type NodeInfo struct {
ProtocolVersion ProtocolVersion `json:"protocol_version"`
// Authenticate
NodeID types.NodeID `json:"id"` // authenticated identifier
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 bytes.HexBytes `json:"channels"` // channels this node knows about
// ASCIIText fields
Moniker string `json:"moniker"` // arbitrary moniker
Other NodeInfoOther `json:"other"` // other application specific data
}
// NodeInfoOther is the misc. applcation specific data
type NodeInfoOther struct {
TxIndex string `json:"tx_index"`
RPCAddress string `json:"rpc_address"`
}
// ID returns the node's peer ID.
func (info NodeInfo) ID() types.NodeID {
return info.NodeID
}
// Validate checks the self-reported NodeInfo is safe.
// It returns an error if there
// are too many Channels, if there are any duplicate Channels,
// if the ListenAddr is malformed, or if the ListenAddr is a host name
// that can not be resolved to some IP.
// TODO: constraints for Moniker/Other? Or is that for the UI ?
// JAE: It needs to be done on the client, but to prevent ambiguous
// unicode characters, maybe it's worth sanitizing it here.
// In the future we might want to validate these, once we have a
// name-resolution system up.
// International clients could then use punycode (or we could use
// url-encoding), and we just need to be careful with how we handle that in our
// clients. (e.g. off by default).
func (info NodeInfo) Validate() error {
// ID is already validated.
// Validate ListenAddr.
_, err := types.NewNetAddressString(info.ID().AddressString(info.ListenAddr))
if err != nil {
return err
}
// Network is validated in CompatibleWith.
// Validate Version
if len(info.Version) > 0 &&
(!tmstrings.IsASCIIText(info.Version) || tmstrings.ASCIITrim(info.Version) == "") {
return fmt.Errorf("info.Version must be valid ASCII text without tabs, but got %v", info.Version)
}
// Validate Channels - ensure max and check for duplicates.
if len(info.Channels) > maxNumChannels {
return fmt.Errorf("info.Channels is too long (%v). Max is %v", len(info.Channels), maxNumChannels)
}
channels := make(map[byte]struct{})
for _, ch := range info.Channels {
_, ok := channels[ch]
if ok {
return fmt.Errorf("info.Channels contains duplicate channel id %v", ch)
}
channels[ch] = struct{}{}
}
// Validate Moniker.
if !tmstrings.IsASCIIText(info.Moniker) || tmstrings.ASCIITrim(info.Moniker) == "" {
return fmt.Errorf("info.Moniker must be valid non-empty ASCII text without tabs, but got %v", info.Moniker)
}
// Validate Other.
other := info.Other
txIndex := other.TxIndex
switch txIndex {
case "", "on", "off":
default:
return fmt.Errorf("info.Other.TxIndex should be either 'on', 'off', or empty string, got '%v'", txIndex)
}
// XXX: Should we be more strict about address formats?
rpcAddr := other.RPCAddress
if len(rpcAddr) > 0 && (!tmstrings.IsASCIIText(rpcAddr) || tmstrings.ASCIITrim(rpcAddr) == "") {
return fmt.Errorf("info.Other.RPCAddress=%v must be valid ASCII text without tabs", rpcAddr)
}
return nil
}
// CompatibleWith checks if two NodeInfo are compatible with each other.
// CONTRACT: two nodes are compatible if the Block version and network match
// and they have at least one channel in common.
func (info NodeInfo) CompatibleWith(other NodeInfo) error {
if info.ProtocolVersion.Block != other.ProtocolVersion.Block {
return fmt.Errorf("peer is on a different Block version. Got %v, expected %v",
other.ProtocolVersion.Block, info.ProtocolVersion.Block)
}
// nodes must be on the same network
if info.Network != other.Network {
return fmt.Errorf("peer is on a different network. Got %v, expected %v", other.Network, info.Network)
}
// 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
found := false
OUTER_LOOP:
for _, ch1 := range info.Channels {
for _, ch2 := range other.Channels {
if ch1 == ch2 {
found = true
break OUTER_LOOP // only need one
}
}
}
if !found {
return fmt.Errorf("peer has no common channels. Our channels: %v ; Peer channels: %v", info.Channels, other.Channels)
}
return nil
}
// NetAddress returns a NetAddress derived from the NodeInfo -
// it includes the authenticated peer ID and the self-reported
// ListenAddr. Note that the ListenAddr is not authenticated and
// may not match that address actually dialed if its an outbound peer.
func (info NodeInfo) NetAddress() (*NetAddress, error) {
idAddr := info.ID().AddressString(info.ListenAddr)
return types.NewNetAddressString(idAddr)
}
func (info NodeInfo) ToProto() *tmp2p.NodeInfo {
dni := new(tmp2p.NodeInfo)
dni.ProtocolVersion = tmp2p.ProtocolVersion{
P2P: info.ProtocolVersion.P2P,
Block: info.ProtocolVersion.Block,
App: info.ProtocolVersion.App,
}
dni.NodeID = string(info.NodeID)
dni.ListenAddr = info.ListenAddr
dni.Network = info.Network
dni.Version = info.Version
dni.Channels = info.Channels
dni.Moniker = info.Moniker
dni.Other = tmp2p.NodeInfoOther{
TxIndex: info.Other.TxIndex,
RPCAddress: info.Other.RPCAddress,
}
return dni
}
func NodeInfoFromProto(pb *tmp2p.NodeInfo) (NodeInfo, error) {
if pb == nil {
return NodeInfo{}, errors.New("nil node info")
}
dni := NodeInfo{
ProtocolVersion: ProtocolVersion{
P2P: pb.ProtocolVersion.P2P,
Block: pb.ProtocolVersion.Block,
App: pb.ProtocolVersion.App,
},
NodeID: types.NodeID(pb.NodeID),
ListenAddr: pb.ListenAddr,
Network: pb.Network,
Version: pb.Version,
Channels: pb.Channels,
Moniker: pb.Moniker,
Other: NodeInfoOther{
TxIndex: pb.Other.TxIndex,
RPCAddress: pb.Other.RPCAddress,
},
}
return dni, nil
}

View File

@@ -1,120 +0,0 @@
package p2p
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNodeInfoValidate(t *testing.T) {
// empty fails
ni := NodeInfo{}
assert.Error(t, ni.Validate())
channels := make([]byte, maxNumChannels)
for i := 0; i < maxNumChannels; i++ {
channels[i] = byte(i)
}
dupChannels := make([]byte, 5)
copy(dupChannels, channels[:5])
dupChannels = append(dupChannels, testCh)
nonASCII := "¢§µ"
emptyTab := "\t"
emptySpace := " "
testCases := []struct {
testName string
malleateNodeInfo func(*NodeInfo)
expectErr bool
}{
{
"Too Many Channels",
func(ni *NodeInfo) { ni.Channels = append(channels, byte(maxNumChannels)) }, // nolint: gocritic
true,
},
{"Duplicate Channel", func(ni *NodeInfo) { ni.Channels = dupChannels }, true},
{"Good Channels", func(ni *NodeInfo) { ni.Channels = ni.Channels[:5] }, false},
{"Invalid NetAddress", func(ni *NodeInfo) { ni.ListenAddr = "not-an-address" }, true},
{"Good NetAddress", func(ni *NodeInfo) { ni.ListenAddr = "0.0.0.0:26656" }, false},
{"Non-ASCII Version", func(ni *NodeInfo) { ni.Version = nonASCII }, true},
{"Empty tab Version", func(ni *NodeInfo) { ni.Version = emptyTab }, true},
{"Empty space Version", func(ni *NodeInfo) { ni.Version = emptySpace }, true},
{"Empty Version", func(ni *NodeInfo) { ni.Version = "" }, false},
{"Non-ASCII Moniker", func(ni *NodeInfo) { ni.Moniker = nonASCII }, true},
{"Empty tab Moniker", func(ni *NodeInfo) { ni.Moniker = emptyTab }, true},
{"Empty space Moniker", func(ni *NodeInfo) { ni.Moniker = emptySpace }, true},
{"Empty Moniker", func(ni *NodeInfo) { ni.Moniker = "" }, true},
{"Good Moniker", func(ni *NodeInfo) { ni.Moniker = "hey its me" }, false},
{"Non-ASCII TxIndex", func(ni *NodeInfo) { ni.Other.TxIndex = nonASCII }, true},
{"Empty tab TxIndex", func(ni *NodeInfo) { ni.Other.TxIndex = emptyTab }, true},
{"Empty space TxIndex", func(ni *NodeInfo) { ni.Other.TxIndex = emptySpace }, true},
{"Empty TxIndex", func(ni *NodeInfo) { ni.Other.TxIndex = "" }, false},
{"Off TxIndex", func(ni *NodeInfo) { ni.Other.TxIndex = "off" }, false},
{"Non-ASCII RPCAddress", func(ni *NodeInfo) { ni.Other.RPCAddress = nonASCII }, true},
{"Empty tab RPCAddress", func(ni *NodeInfo) { ni.Other.RPCAddress = emptyTab }, true},
{"Empty space RPCAddress", func(ni *NodeInfo) { ni.Other.RPCAddress = emptySpace }, true},
{"Empty RPCAddress", func(ni *NodeInfo) { ni.Other.RPCAddress = "" }, false},
{"Good RPCAddress", func(ni *NodeInfo) { ni.Other.RPCAddress = "0.0.0.0:26657" }, false},
}
nodeKey := GenNodeKey()
name := "testing"
// test case passes
ni = testNodeInfo(nodeKey.ID, name)
ni.Channels = channels
assert.NoError(t, ni.Validate())
for _, tc := range testCases {
ni := testNodeInfo(nodeKey.ID, name)
ni.Channels = channels
tc.malleateNodeInfo(&ni)
err := ni.Validate()
if tc.expectErr {
assert.Error(t, err, tc.testName)
} else {
assert.NoError(t, err, tc.testName)
}
}
}
func TestNodeInfoCompatible(t *testing.T) {
nodeKey1 := GenNodeKey()
nodeKey2 := GenNodeKey()
name := "testing"
var newTestChannel byte = 0x2
// test NodeInfo is compatible
ni1 := testNodeInfo(nodeKey1.ID, name)
ni2 := testNodeInfo(nodeKey2.ID, name)
assert.NoError(t, ni1.CompatibleWith(ni2))
// add another channel; still compatible
ni2.Channels = []byte{newTestChannel, testCh}
assert.NoError(t, ni1.CompatibleWith(ni2))
testCases := []struct {
testName string
malleateNodeInfo func(*NodeInfo)
}{
{"Wrong block version", func(ni *NodeInfo) { ni.ProtocolVersion.Block++ }},
{"Wrong network", func(ni *NodeInfo) { ni.Network += "-wrong" }},
{"No common channels", func(ni *NodeInfo) { ni.Channels = []byte{newTestChannel} }},
}
for _, tc := range testCases {
ni := testNodeInfo(nodeKey2.ID, name)
tc.malleateNodeInfo(&ni)
assert.Error(t, ni1.CompatibleWith(ni))
}
}

View File

@@ -24,7 +24,7 @@ var (
selfKey crypto.PrivKey = ed25519.GenPrivKeyFromSecret([]byte{0xf9, 0x1b, 0x08, 0xaa, 0x38, 0xee, 0x34, 0xdd})
selfID = types.NodeIDFromPubKey(selfKey.PubKey())
selfInfo = p2p.NodeInfo{
selfInfo = types.NodeInfo{
NodeID: selfID,
ListenAddr: "0.0.0.0:0",
Network: "test",
@@ -33,7 +33,7 @@ var (
peerKey crypto.PrivKey = ed25519.GenPrivKeyFromSecret([]byte{0x84, 0xd7, 0x01, 0xbf, 0x83, 0x20, 0x1c, 0xfe})
peerID = types.NodeIDFromPubKey(peerKey.PubKey())
peerInfo = p2p.NodeInfo{
peerInfo = types.NodeInfo{
NodeID: peerID,
ListenAddr: "0.0.0.0:0",
Network: "test",

View File

@@ -215,7 +215,7 @@ func (n *Network) Remove(t *testing.T, id types.NodeID) {
// Node is a node in a Network, with a Router and a PeerManager.
type Node struct {
NodeID types.NodeID
NodeInfo p2p.NodeInfo
NodeInfo types.NodeInfo
NodeAddress p2p.NodeAddress
PrivKey crypto.PrivKey
Router *p2p.Router
@@ -229,7 +229,7 @@ type Node struct {
func (n *Network) MakeNode(t *testing.T, opts NodeOptions) *Node {
privKey := ed25519.GenPrivKey()
nodeID := types.NodeIDFromPubKey(privKey.PubKey())
nodeInfo := p2p.NodeInfo{
nodeInfo := types.NodeInfo{
NodeID: nodeID,
ListenAddr: "0.0.0.0:0", // FIXME: We have to fake this for now.
Moniker: string(nodeID),

View File

@@ -32,7 +32,7 @@ type Peer interface {
CloseConn() error // close original connection
NodeInfo() NodeInfo // peer's info
NodeInfo() types.NodeInfo // peer's info
Status() tmconn.ConnectionStatus
SocketAddr() *NetAddress // actual address of the socket
@@ -81,7 +81,7 @@ type peer struct {
// peer's node info and the channel it knows about
// channels = nodeInfo.Channels
// cached to avoid copying nodeInfo in hasChannel
nodeInfo NodeInfo
nodeInfo types.NodeInfo
channels []byte
reactors map[byte]Reactor
onPeerError func(Peer, interface{})
@@ -96,7 +96,7 @@ type peer struct {
type PeerOption func(*peer)
func newPeer(
nodeInfo NodeInfo,
nodeInfo types.NodeInfo,
pc peerConn,
reactorsByCh map[byte]Reactor,
onPeerError func(Peer, interface{}),
@@ -218,7 +218,7 @@ func (p *peer) IsPersistent() bool {
}
// NodeInfo returns a copy of the peer's NodeInfo.
func (p *peer) NodeInfo() NodeInfo {
func (p *peer) NodeInfo() types.NodeInfo {
return p.nodeInfo
}

View File

@@ -21,7 +21,7 @@ type mockPeer struct {
func (mp *mockPeer) FlushStop() { mp.Stop() } //nolint:errcheck // ignore error
func (mp *mockPeer) TrySend(chID byte, msgBytes []byte) bool { return true }
func (mp *mockPeer) Send(chID byte, msgBytes []byte) bool { return true }
func (mp *mockPeer) NodeInfo() NodeInfo { return NodeInfo{} }
func (mp *mockPeer) NodeInfo() types.NodeInfo { return types.NodeInfo{} }
func (mp *mockPeer) Status() ConnectionStatus { return ConnectionStatus{} }
func (mp *mockPeer) ID() types.NodeID { return mp.id }
func (mp *mockPeer) IsOutbound() bool { return false }

View File

@@ -221,8 +221,8 @@ func (rp *remotePeer) accept() {
}
}
func (rp *remotePeer) nodeInfo() NodeInfo {
return NodeInfo{
func (rp *remotePeer) nodeInfo() types.NodeInfo {
return types.NodeInfo{
ProtocolVersion: defaultProtocolVersion,
NodeID: rp.Addr().ID,
ListenAddr: rp.listener.Addr().String(),

View File

@@ -248,7 +248,7 @@ type Router struct {
logger log.Logger
metrics *Metrics
options RouterOptions
nodeInfo NodeInfo
nodeInfo types.NodeInfo
privKey crypto.PrivKey
peerManager *PeerManager
chDescs []ChannelDescriptor
@@ -275,7 +275,7 @@ type Router struct {
func NewRouter(
logger log.Logger,
metrics *Metrics,
nodeInfo NodeInfo,
nodeInfo types.NodeInfo,
privKey crypto.PrivKey,
peerManager *PeerManager,
transports []Transport,
@@ -787,7 +787,7 @@ func (r *Router) handshakePeer(
ctx context.Context,
conn Connection,
expectID types.NodeID,
) (NodeInfo, crypto.PubKey, error) {
) (types.NodeInfo, crypto.PubKey, error) {
if r.options.HandshakeTimeout > 0 {
var cancel context.CancelFunc

View File

@@ -6,6 +6,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/types"
)
func TestRouter_ConstructQueueFactory(t *testing.T) {
@@ -17,21 +18,21 @@ func TestRouter_ConstructQueueFactory(t *testing.T) {
t.Run("Default", func(t *testing.T) {
require.Zero(t, os.Getenv("TM_P2P_QUEUE"))
opts := RouterOptions{}
r, err := NewRouter(log.NewNopLogger(), nil, NodeInfo{}, nil, nil, nil, opts)
r, err := NewRouter(log.NewNopLogger(), nil, types.NodeInfo{}, nil, nil, nil, opts)
require.NoError(t, err)
_, ok := r.queueFactory(1).(*fifoQueue)
require.True(t, ok)
})
t.Run("Fifo", func(t *testing.T) {
opts := RouterOptions{QueueType: queueTypeFifo}
r, err := NewRouter(log.NewNopLogger(), nil, NodeInfo{}, nil, nil, nil, opts)
r, err := NewRouter(log.NewNopLogger(), nil, types.NodeInfo{}, nil, nil, nil, opts)
require.NoError(t, err)
_, ok := r.queueFactory(1).(*fifoQueue)
require.True(t, ok)
})
t.Run("Priority", func(t *testing.T) {
opts := RouterOptions{QueueType: queueTypePriority}
r, err := NewRouter(log.NewNopLogger(), nil, NodeInfo{}, nil, nil, nil, opts)
r, err := NewRouter(log.NewNopLogger(), nil, types.NodeInfo{}, nil, nil, nil, opts)
require.NoError(t, err)
q, ok := r.queueFactory(1).(*pqScheduler)
require.True(t, ok)
@@ -39,7 +40,7 @@ func TestRouter_ConstructQueueFactory(t *testing.T) {
})
t.Run("WDRR", func(t *testing.T) {
opts := RouterOptions{QueueType: queueTypeWDRR}
r, err := NewRouter(log.NewNopLogger(), nil, NodeInfo{}, nil, nil, nil, opts)
r, err := NewRouter(log.NewNopLogger(), nil, types.NodeInfo{}, nil, nil, nil, opts)
require.NoError(t, err)
q, ok := r.queueFactory(1).(*wdrrScheduler)
require.True(t, ok)
@@ -47,7 +48,7 @@ func TestRouter_ConstructQueueFactory(t *testing.T) {
})
t.Run("NonExistant", func(t *testing.T) {
opts := RouterOptions{QueueType: "fast"}
_, err := NewRouter(log.NewNopLogger(), nil, NodeInfo{}, nil, nil, nil, opts)
_, err := NewRouter(log.NewNopLogger(), nil, types.NodeInfo{}, nil, nil, nil, opts)
require.Error(t, err)
require.Contains(t, err.Error(), "fast")
})

View File

@@ -319,12 +319,12 @@ func TestRouter_Channel_Error(t *testing.T) {
func TestRouter_AcceptPeers(t *testing.T) {
testcases := map[string]struct {
peerInfo p2p.NodeInfo
peerInfo types.NodeInfo
peerKey crypto.PubKey
ok bool
}{
"valid handshake": {peerInfo, peerKey.PubKey(), true},
"empty handshake": {p2p.NodeInfo{}, nil, false},
"empty handshake": {types.NodeInfo{}, nil, false},
"invalid key": {peerInfo, selfKey.PubKey(), false},
"self handshake": {selfInfo, selfKey.PubKey(), false},
}
@@ -478,7 +478,7 @@ func TestRouter_AcceptPeers_HeadOfLineBlocking(t *testing.T) {
mockConnection := &mocks.Connection{}
mockConnection.On("String").Maybe().Return("mock")
mockConnection.On("Handshake", mock.Anything, selfInfo, selfKey).
WaitUntil(closeCh).Return(p2p.NodeInfo{}, nil, io.EOF)
WaitUntil(closeCh).Return(types.NodeInfo{}, nil, io.EOF)
mockConnection.On("Close").Return(nil)
mockConnection.On("RemoteEndpoint").Return(p2p.Endpoint{})
@@ -522,13 +522,13 @@ func TestRouter_AcceptPeers_HeadOfLineBlocking(t *testing.T) {
func TestRouter_DialPeers(t *testing.T) {
testcases := map[string]struct {
dialID types.NodeID
peerInfo p2p.NodeInfo
peerInfo types.NodeInfo
peerKey crypto.PubKey
dialErr error
ok bool
}{
"valid dial": {peerInfo.NodeID, peerInfo, peerKey.PubKey(), nil, true},
"empty handshake": {peerInfo.NodeID, p2p.NodeInfo{}, nil, nil, false},
"empty handshake": {peerInfo.NodeID, types.NodeInfo{}, nil, nil, false},
"invalid key": {peerInfo.NodeID, peerInfo, selfKey.PubKey(), nil, false},
"unexpected node ID": {peerInfo.NodeID, selfInfo, selfKey.PubKey(), nil, false},
"dial error": {peerInfo.NodeID, peerInfo, peerKey.PubKey(), errors.New("boom"), false},
@@ -634,7 +634,7 @@ func TestRouter_DialPeers_Parallel(t *testing.T) {
mockConnection := &mocks.Connection{}
mockConnection.On("String").Maybe().Return("mock")
mockConnection.On("Handshake", mock.Anything, selfInfo, selfKey).
WaitUntil(closeCh).Return(p2p.NodeInfo{}, nil, io.EOF)
WaitUntil(closeCh).Return(types.NodeInfo{}, nil, io.EOF)
mockConnection.On("Close").Return(nil)
mockTransport := &mocks.Transport{}

View File

@@ -103,8 +103,8 @@ type Switch struct {
peers *PeerSet
dialing *cmap.CMap
reconnecting *cmap.CMap
nodeInfo NodeInfo // our node info
nodeKey NodeKey // our node privkey
nodeInfo types.NodeInfo // our node info
nodeKey NodeKey // our node privkey
addrBook AddrBook
// peers addresses with whom we'll maintain constant connection
persistentPeersAddrs []*NetAddress
@@ -242,13 +242,13 @@ func (sw *Switch) Reactor(name string) Reactor {
// SetNodeInfo sets the switch's NodeInfo for checking compatibility and handshaking with other nodes.
// NOTE: Not goroutine safe.
func (sw *Switch) SetNodeInfo(nodeInfo NodeInfo) {
func (sw *Switch) SetNodeInfo(nodeInfo types.NodeInfo) {
sw.nodeInfo = nodeInfo
}
// NodeInfo returns the switch's NodeInfo.
// NOTE: Not goroutine safe.
func (sw *Switch) NodeInfo() NodeInfo {
func (sw *Switch) NodeInfo() types.NodeInfo {
return sw.nodeInfo
}
@@ -669,7 +669,7 @@ func (sw *Switch) IsPeerPersistent(na *NetAddress) bool {
func (sw *Switch) acceptRoutine() {
for {
var peerNodeInfo NodeInfo
var peerNodeInfo types.NodeInfo
c, err := sw.transport.Accept()
if err == nil {
// NOTE: The legacy MConn transport did handshaking in Accept(),
@@ -800,7 +800,7 @@ func (sw *Switch) addOutboundPeerWithConfig(
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
var peerNodeInfo NodeInfo
var peerNodeInfo types.NodeInfo
c, err := sw.transport.Dial(ctx, Endpoint{
Protocol: MConnProtocol,
IP: addr.IP,
@@ -856,7 +856,10 @@ func (sw *Switch) addOutboundPeerWithConfig(
return nil
}
func (sw *Switch) handshakePeer(c Connection, expectPeerID types.NodeID) (NodeInfo, crypto.PubKey, error) {
func (sw *Switch) handshakePeer(
c Connection,
expectPeerID types.NodeID,
) (types.NodeInfo, crypto.PubKey, error) {
// Moved from transport and hardcoded until legacy P2P stack removal.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

View File

@@ -27,7 +27,7 @@ func CreateRandomPeer(outbound bool) Peer {
addr, netAddr := CreateRoutableAddr()
p := &peer{
peerConn: peerConn{outbound: outbound},
nodeInfo: NodeInfo{
nodeInfo: types.NodeInfo{
NodeID: netAddr.ID,
ListenAddr: netAddr.DialString(),
},
@@ -227,12 +227,12 @@ func testPeerConn(
//----------------------------------------------------------------
// rand node info
func testNodeInfo(id types.NodeID, name string) NodeInfo {
func testNodeInfo(id types.NodeID, name string) types.NodeInfo {
return testNodeInfoWithNetwork(id, name, "testing")
}
func testNodeInfoWithNetwork(id types.NodeID, name, network string) NodeInfo {
return NodeInfo{
func testNodeInfoWithNetwork(id types.NodeID, name, network string) types.NodeInfo {
return types.NodeInfo{
ProtocolVersion: defaultProtocolVersion,
NodeID: id,
ListenAddr: fmt.Sprintf("127.0.0.1:%d", getFreePort()),
@@ -240,7 +240,7 @@ func testNodeInfoWithNetwork(id types.NodeID, name, network string) NodeInfo {
Version: "1.2.3-rc0-deadbeef",
Channels: []byte{testCh},
Moniker: name,
Other: NodeInfoOther{
Other: types.NodeInfoOther{
TxIndex: "on",
RPCAddress: fmt.Sprintf("127.0.0.1:%d", getFreePort()),
},

View File

@@ -9,6 +9,7 @@ import (
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/internal/p2p/conn"
"github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/version"
)
//go:generate mockery --case underscore --name Transport|Connection
@@ -19,6 +20,14 @@ const (
defaultProtocol Protocol = MConnProtocol
)
// defaultProtocolVersion populates the Block and P2P versions using
// the global values, but not the App.
var defaultProtocolVersion = types.ProtocolVersion{
P2P: version.P2PProtocol,
Block: version.BlockProtocol,
App: 0,
}
// Protocol identifies a transport protocol.
type Protocol string
@@ -75,7 +84,7 @@ type Connection interface {
// FIXME: The handshake should really be the Router's responsibility, but
// that requires the connection interface to be byte-oriented rather than
// message-oriented (see comment above).
Handshake(context.Context, NodeInfo, crypto.PrivKey) (NodeInfo, crypto.PubKey, error)
Handshake(context.Context, types.NodeInfo, crypto.PrivKey) (types.NodeInfo, crypto.PubKey, error)
// ReceiveMessage returns the next message received on the connection,
// blocking until one is available. Returns io.EOF if closed.

View File

@@ -17,6 +17,7 @@ import (
"github.com/tendermint/tendermint/internal/p2p/conn"
"github.com/tendermint/tendermint/libs/log"
p2pproto "github.com/tendermint/tendermint/proto/tendermint/p2p"
"github.com/tendermint/tendermint/types"
)
const (
@@ -254,12 +255,12 @@ func newMConnConnection(
// Handshake implements Connection.
func (c *mConnConnection) Handshake(
ctx context.Context,
nodeInfo NodeInfo,
nodeInfo types.NodeInfo,
privKey crypto.PrivKey,
) (NodeInfo, crypto.PubKey, error) {
) (types.NodeInfo, crypto.PubKey, error) {
var (
mconn *conn.MConnection
peerInfo NodeInfo
peerInfo types.NodeInfo
peerKey crypto.PubKey
errCh = make(chan error, 1)
)
@@ -282,16 +283,16 @@ func (c *mConnConnection) Handshake(
select {
case <-ctx.Done():
_ = c.Close()
return NodeInfo{}, nil, ctx.Err()
return types.NodeInfo{}, nil, ctx.Err()
case err := <-errCh:
if err != nil {
return NodeInfo{}, nil, err
return types.NodeInfo{}, nil, err
}
c.mconn = mconn
c.logger = mconn.Logger
if err = c.mconn.Start(); err != nil {
return NodeInfo{}, nil, err
return types.NodeInfo{}, nil, err
}
return peerInfo, peerKey, nil
}
@@ -302,16 +303,16 @@ func (c *mConnConnection) Handshake(
// unstarted but handshaked MConnection, to avoid concurrent field writes.
func (c *mConnConnection) handshake(
ctx context.Context,
nodeInfo NodeInfo,
nodeInfo types.NodeInfo,
privKey crypto.PrivKey,
) (*conn.MConnection, NodeInfo, crypto.PubKey, error) {
) (*conn.MConnection, types.NodeInfo, crypto.PubKey, error) {
if c.mconn != nil {
return nil, NodeInfo{}, nil, errors.New("connection is already handshaked")
return nil, types.NodeInfo{}, nil, errors.New("connection is already handshaked")
}
secretConn, err := conn.MakeSecretConnection(c.conn, privKey)
if err != nil {
return nil, NodeInfo{}, nil, err
return nil, types.NodeInfo{}, nil, err
}
var pbPeerInfo p2pproto.NodeInfo
@@ -321,17 +322,17 @@ func (c *mConnConnection) handshake(
errCh <- err
}()
go func() {
_, err := protoio.NewDelimitedReader(secretConn, MaxNodeInfoSize()).ReadMsg(&pbPeerInfo)
_, err := protoio.NewDelimitedReader(secretConn, types.MaxNodeInfoSize()).ReadMsg(&pbPeerInfo)
errCh <- err
}()
for i := 0; i < cap(errCh); i++ {
if err = <-errCh; err != nil {
return nil, NodeInfo{}, nil, err
return nil, types.NodeInfo{}, nil, err
}
}
peerInfo, err := NodeInfoFromProto(&pbPeerInfo)
peerInfo, err := types.NodeInfoFromProto(&pbPeerInfo)
if err != nil {
return nil, NodeInfo{}, nil, err
return nil, types.NodeInfo{}, nil, err
}
mconn := conn.NewMConnectionWithConfig(

View File

@@ -218,7 +218,7 @@ type memoryMessage struct {
message []byte
// For handshakes.
nodeInfo *NodeInfo
nodeInfo *types.NodeInfo
pubKey crypto.PubKey
}
@@ -270,29 +270,29 @@ func (c *MemoryConnection) Status() conn.ConnectionStatus {
// Handshake implements Connection.
func (c *MemoryConnection) Handshake(
ctx context.Context,
nodeInfo NodeInfo,
nodeInfo types.NodeInfo,
privKey crypto.PrivKey,
) (NodeInfo, crypto.PubKey, error) {
) (types.NodeInfo, crypto.PubKey, error) {
select {
case c.sendCh <- memoryMessage{nodeInfo: &nodeInfo, pubKey: privKey.PubKey()}:
c.logger.Debug("sent handshake", "nodeInfo", nodeInfo)
case <-c.closer.Done():
return NodeInfo{}, nil, io.EOF
return types.NodeInfo{}, nil, io.EOF
case <-ctx.Done():
return NodeInfo{}, nil, ctx.Err()
return types.NodeInfo{}, nil, ctx.Err()
}
select {
case msg := <-c.receiveCh:
if msg.nodeInfo == nil {
return NodeInfo{}, nil, errors.New("no NodeInfo in handshake")
return types.NodeInfo{}, nil, errors.New("no NodeInfo in handshake")
}
c.logger.Debug("received handshake", "peerInfo", msg.nodeInfo)
return *msg.nodeInfo, msg.pubKey, nil
case <-c.closer.Done():
return NodeInfo{}, nil, io.EOF
return types.NodeInfo{}, nil, io.EOF
case <-ctx.Done():
return NodeInfo{}, nil, ctx.Err()
return types.NodeInfo{}, nil, ctx.Err()
}
}

View File

@@ -242,21 +242,25 @@ func TestConnection_Handshake(t *testing.T) {
// A handshake should pass the given keys and NodeInfo.
aKey := ed25519.GenPrivKey()
aInfo := p2p.NodeInfo{
NodeID: types.NodeIDFromPubKey(aKey.PubKey()),
ProtocolVersion: p2p.NewProtocolVersion(1, 2, 3),
ListenAddr: "listenaddr",
Network: "network",
Version: "1.2.3",
Channels: bytes.HexBytes([]byte{0xf0, 0x0f}),
Moniker: "moniker",
Other: p2p.NodeInfoOther{
aInfo := types.NodeInfo{
NodeID: types.NodeIDFromPubKey(aKey.PubKey()),
ProtocolVersion: types.ProtocolVersion{
P2P: 1,
Block: 2,
App: 3,
},
ListenAddr: "listenaddr",
Network: "network",
Version: "1.2.3",
Channels: bytes.HexBytes([]byte{0xf0, 0x0f}),
Moniker: "moniker",
Other: types.NodeInfoOther{
TxIndex: "txindex",
RPCAddress: "rpc.domain.com",
},
}
bKey := ed25519.GenPrivKey()
bInfo := p2p.NodeInfo{NodeID: types.NodeIDFromPubKey(bKey.PubKey())}
bInfo := types.NodeInfo{NodeID: types.NodeIDFromPubKey(bKey.PubKey())}
errCh := make(chan error, 1)
go func() {
@@ -287,7 +291,7 @@ func TestConnection_HandshakeCancel(t *testing.T) {
ab, ba := dialAccept(t, a, b)
timeoutCtx, cancel := context.WithTimeout(ctx, 1*time.Minute)
cancel()
_, _, err := ab.Handshake(timeoutCtx, p2p.NodeInfo{}, ed25519.GenPrivKey())
_, _, err := ab.Handshake(timeoutCtx, types.NodeInfo{}, ed25519.GenPrivKey())
require.Error(t, err)
require.Equal(t, context.Canceled, err)
_ = ab.Close()
@@ -297,7 +301,7 @@ func TestConnection_HandshakeCancel(t *testing.T) {
ab, ba = dialAccept(t, a, b)
timeoutCtx, cancel = context.WithTimeout(ctx, 200*time.Millisecond)
defer cancel()
_, _, err = ab.Handshake(timeoutCtx, p2p.NodeInfo{}, ed25519.GenPrivKey())
_, _, err = ab.Handshake(timeoutCtx, types.NodeInfo{}, ed25519.GenPrivKey())
require.Error(t, err)
require.Equal(t, context.DeadlineExceeded, err)
_ = ab.Close()
@@ -619,13 +623,13 @@ func dialAcceptHandshake(t *testing.T, a, b p2p.Transport) (p2p.Connection, p2p.
errCh := make(chan error, 1)
go func() {
privKey := ed25519.GenPrivKey()
nodeInfo := p2p.NodeInfo{NodeID: types.NodeIDFromPubKey(privKey.PubKey())}
nodeInfo := types.NodeInfo{NodeID: types.NodeIDFromPubKey(privKey.PubKey())}
_, _, err := ba.Handshake(ctx, nodeInfo, privKey)
errCh <- err
}()
privKey := ed25519.GenPrivKey()
nodeInfo := p2p.NodeInfo{NodeID: types.NodeIDFromPubKey(privKey.PubKey())}
nodeInfo := types.NodeInfo{NodeID: types.NodeIDFromPubKey(privKey.PubKey())}
_, _, err := ab.Handshake(ctx, nodeInfo, privKey)
require.NoError(t, err)