github.com/Finschia/ostracon@v1.1.5/p2p/peer_test.go (about)

     1  package p2p
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/Finschia/ostracon/libs/service"
     6  	golog "log"
     7  	"net"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/gogo/protobuf/proto"
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/tendermint/tendermint/proto/tendermint/p2p"
    16  
    17  	"github.com/Finschia/ostracon/crypto"
    18  	"github.com/Finschia/ostracon/crypto/ed25519"
    19  	"github.com/Finschia/ostracon/libs/bytes"
    20  	"github.com/Finschia/ostracon/libs/log"
    21  
    22  	"github.com/Finschia/ostracon/config"
    23  	tmconn "github.com/Finschia/ostracon/p2p/conn"
    24  )
    25  
    26  // OldPeer does not implement EnvelopeSender(SendEnvelope/TrySendEnvelope)
    27  type OldPeer struct {
    28  	service.BaseService
    29  }
    30  
    31  func (mp *OldPeer) FlushStop()                        {}
    32  func (mp *OldPeer) TrySend(_ byte, _ []byte) bool     { return true }
    33  func (mp *OldPeer) Send(_ byte, _ []byte) bool        { return true }
    34  func (mp *OldPeer) NodeInfo() NodeInfo                { return DefaultNodeInfo{} }
    35  func (mp *OldPeer) Status() tmconn.ConnectionStatus   { return tmconn.ConnectionStatus{} }
    36  func (mp *OldPeer) ID() ID                            { return "" }
    37  func (mp *OldPeer) IsOutbound() bool                  { return true }
    38  func (mp *OldPeer) IsPersistent() bool                { return true }
    39  func (mp *OldPeer) Get(key string) interface{}        { return nil }
    40  func (mp *OldPeer) Set(key string, value interface{}) {}
    41  func (mp *OldPeer) RemoteIP() net.IP                  { return []byte{0} }
    42  func (mp *OldPeer) SocketAddr() *NetAddress           { return &NetAddress{} }
    43  func (mp *OldPeer) RemoteAddr() net.Addr              { return &net.TCPAddr{} }
    44  func (mp *OldPeer) CloseConn() error                  { return nil }
    45  func (mp *OldPeer) SetRemovalFailed()                 {}
    46  func (mp *OldPeer) GetRemovalFailed() bool            { return false }
    47  
    48  func TestSendWithOldPeer(t *testing.T) {
    49  	logger := log.TestingLogger()
    50  	p := &OldPeer{}
    51  	assert.True(t, SendEnvelopeShim(p, Envelope{ChannelID: testCh, Message: &p2p.Message{}}, logger))
    52  	assert.True(t, TrySendEnvelopeShim(p, Envelope{ChannelID: testCh, Message: &p2p.Message{}}, logger))
    53  }
    54  
    55  func TestPeerBasic(t *testing.T) {
    56  	assert, require := assert.New(t), require.New(t)
    57  
    58  	// simulate remote peer
    59  	rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg}
    60  	rp.Start()
    61  	t.Cleanup(rp.Stop)
    62  
    63  	p, err := createOutboundPeerAndPerformHandshake(rp.Addr(), cfg, tmconn.DefaultMConnConfig())
    64  	require.Nil(err)
    65  
    66  	err = p.Start()
    67  	require.Nil(err)
    68  	t.Cleanup(func() {
    69  		if err := p.Stop(); err != nil {
    70  			t.Error(err)
    71  		}
    72  	})
    73  
    74  	assert.True(p.IsRunning())
    75  	assert.True(p.IsOutbound())
    76  	assert.False(p.IsPersistent())
    77  	p.persistent = true
    78  	assert.True(p.IsPersistent())
    79  	assert.Equal(rp.Addr().DialString(), p.RemoteAddr().String())
    80  	assert.Equal(rp.ID(), p.ID())
    81  }
    82  
    83  func TestPeerSend(t *testing.T) {
    84  	assert, require := assert.New(t), require.New(t)
    85  
    86  	config := cfg
    87  
    88  	// simulate remote peer
    89  	rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: config}
    90  	rp.Start()
    91  	t.Cleanup(rp.Stop)
    92  
    93  	p, err := createOutboundPeerAndPerformHandshake(rp.Addr(), config, tmconn.DefaultMConnConfig())
    94  	require.Nil(err)
    95  
    96  	// False Test: isn't running peer
    97  	require.NoError(err)
    98  	require.False(SendEnvelopeShim(p, Envelope{ChannelID: testCh, Message: &p2p.Message{}}, p.Logger))
    99  
   100  	err = p.Start()
   101  	require.Nil(err)
   102  
   103  	t.Cleanup(func() {
   104  		if err := p.Stop(); err != nil {
   105  			t.Error(err)
   106  		}
   107  	})
   108  
   109  	assert.True(p.CanSend(testCh))
   110  	assert.True(SendEnvelopeShim(p, Envelope{ChannelID: testCh, Message: &p2p.Message{}}, p.Logger))
   111  
   112  	// False Test: hasn't channels
   113  	p.channels = []byte{}
   114  	require.False(SendEnvelopeShim(p, Envelope{ChannelID: testCh, Message: &p2p.Message{}}, p.Logger))
   115  }
   116  
   117  func createOutboundPeerAndPerformHandshake(
   118  	addr *NetAddress,
   119  	config *config.P2PConfig,
   120  	mConfig tmconn.MConnConfig,
   121  ) (*peer, error) {
   122  	chDescs := []*tmconn.ChannelDescriptor{
   123  		{ID: testCh, Priority: 1},
   124  	}
   125  	reactorsByCh := map[byte]Reactor{testCh: NewTestReactor(chDescs, true, 1000, true)}
   126  	msgTypeByChID := map[byte]proto.Message{
   127  		testCh: &p2p.Message{},
   128  	}
   129  	pk := ed25519.GenPrivKey()
   130  	pc, err := testOutboundPeerConn(addr, config, false, pk)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  	timeout := 1 * time.Second
   135  	ourNodeInfo := testNodeInfo(addr.ID, "host_peer")
   136  	peerNodeInfo, err := handshake(pc.conn, timeout, ourNodeInfo)
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	p := newPeer(pc, mConfig, peerNodeInfo, reactorsByCh, msgTypeByChID, chDescs, func(p Peer, r interface{}) {}, newMetricsLabelCache())
   142  	p.SetLogger(log.TestingLogger().With("peer", addr))
   143  	return p, nil
   144  }
   145  
   146  func testDial(addr *NetAddress, cfg *config.P2PConfig) (net.Conn, error) {
   147  	if cfg.TestDialFail {
   148  		return nil, fmt.Errorf("dial err (peerConfig.DialFail == true)")
   149  	}
   150  
   151  	conn, err := addr.DialTimeout(cfg.DialTimeout)
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  	return conn, nil
   156  }
   157  
   158  func testOutboundPeerConn(
   159  	addr *NetAddress,
   160  	config *config.P2PConfig,
   161  	persistent bool,
   162  	ourNodePrivKey crypto.PrivKey,
   163  ) (peerConn, error) {
   164  
   165  	var pc peerConn
   166  	conn, err := testDial(addr, config)
   167  	if err != nil {
   168  		return pc, fmt.Errorf("error creating peer: %w", err)
   169  	}
   170  
   171  	pc, err = testPeerConn(conn, config, true, persistent, ourNodePrivKey, addr)
   172  	if err != nil {
   173  		if cerr := conn.Close(); cerr != nil {
   174  			return pc, fmt.Errorf("%v: %w", cerr.Error(), err)
   175  		}
   176  		return pc, err
   177  	}
   178  
   179  	// ensure dialed ID matches connection ID
   180  	if addr.ID != pc.ID() {
   181  		if cerr := conn.Close(); cerr != nil {
   182  			return pc, fmt.Errorf("%v: %w", cerr.Error(), err)
   183  		}
   184  		return pc, ErrSwitchAuthenticationFailure{addr, pc.ID()}
   185  	}
   186  
   187  	return pc, nil
   188  }
   189  
   190  type remotePeer struct {
   191  	PrivKey    crypto.PrivKey
   192  	Config     *config.P2PConfig
   193  	addr       *NetAddress
   194  	channels   bytes.HexBytes
   195  	listenAddr string
   196  	listener   net.Listener
   197  }
   198  
   199  func (rp *remotePeer) Addr() *NetAddress {
   200  	return rp.addr
   201  }
   202  
   203  func (rp *remotePeer) ID() ID {
   204  	return PubKeyToID(rp.PrivKey.PubKey())
   205  }
   206  
   207  func (rp *remotePeer) Start() {
   208  	if rp.listenAddr == "" {
   209  		rp.listenAddr = "127.0.0.1:0"
   210  	}
   211  
   212  	l, e := net.Listen("tcp", rp.listenAddr) // any available address
   213  	if e != nil {
   214  		golog.Fatalf("net.Listen tcp :0: %+v", e)
   215  	}
   216  	rp.listener = l
   217  	rp.addr = NewNetAddress(PubKeyToID(rp.PrivKey.PubKey()), l.Addr())
   218  	if rp.channels == nil {
   219  		rp.channels = []byte{testCh}
   220  	}
   221  	go rp.accept()
   222  }
   223  
   224  func (rp *remotePeer) Stop() {
   225  	rp.listener.Close()
   226  }
   227  
   228  func (rp *remotePeer) Dial(addr *NetAddress) (net.Conn, error) {
   229  	conn, err := addr.DialTimeout(1 * time.Second)
   230  	if err != nil {
   231  		return nil, err
   232  	}
   233  	pc, err := testInboundPeerConn(conn, rp.Config, rp.PrivKey)
   234  	if err != nil {
   235  		return nil, err
   236  	}
   237  	_, err = handshake(pc.conn, time.Second, rp.nodeInfo())
   238  	if err != nil {
   239  		return nil, err
   240  	}
   241  	return conn, err
   242  }
   243  
   244  func (rp *remotePeer) accept() {
   245  	conns := []net.Conn{}
   246  
   247  	for {
   248  		conn, err := rp.listener.Accept()
   249  		if err != nil {
   250  			golog.Printf("Failed to accept conn: %+v", err)
   251  			for _, conn := range conns {
   252  				_ = conn.Close()
   253  			}
   254  			return
   255  		}
   256  
   257  		pc, err := testInboundPeerConn(conn, rp.Config, rp.PrivKey)
   258  		if err != nil {
   259  			golog.Fatalf("Failed to create a peer: %+v", err)
   260  		}
   261  
   262  		_, err = handshake(pc.conn, time.Second, rp.nodeInfo())
   263  		if err != nil {
   264  			golog.Fatalf("Failed to perform handshake: %+v", err)
   265  		}
   266  
   267  		conns = append(conns, conn)
   268  	}
   269  }
   270  
   271  func (rp *remotePeer) nodeInfo() NodeInfo {
   272  	return DefaultNodeInfo{
   273  		ProtocolVersion: defaultProtocolVersion,
   274  		DefaultNodeID:   rp.Addr().ID,
   275  		ListenAddr:      rp.listener.Addr().String(),
   276  		Network:         "testing",
   277  		Version:         "1.2.3-rc0-deadbeef",
   278  		Channels:        rp.channels,
   279  		Moniker:         "remote_peer",
   280  	}
   281  }