github.com/evdatsion/aphelion-dpos-bft@v0.32.1/p2p/peer_test.go (about)

     1  package p2p
     2  
     3  import (
     4  	"fmt"
     5  	golog "log"
     6  	"net"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  
    13  	"github.com/evdatsion/aphelion-dpos-bft/crypto"
    14  	"github.com/evdatsion/aphelion-dpos-bft/crypto/ed25519"
    15  	cmn "github.com/evdatsion/aphelion-dpos-bft/libs/common"
    16  	"github.com/evdatsion/aphelion-dpos-bft/libs/log"
    17  
    18  	"github.com/evdatsion/aphelion-dpos-bft/config"
    19  	tmconn "github.com/evdatsion/aphelion-dpos-bft/p2p/conn"
    20  )
    21  
    22  func TestPeerBasic(t *testing.T) {
    23  	assert, require := assert.New(t), require.New(t)
    24  
    25  	// simulate remote peer
    26  	rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg}
    27  	rp.Start()
    28  	defer rp.Stop()
    29  
    30  	p, err := createOutboundPeerAndPerformHandshake(rp.Addr(), cfg, tmconn.DefaultMConnConfig())
    31  	require.Nil(err)
    32  
    33  	err = p.Start()
    34  	require.Nil(err)
    35  	defer p.Stop()
    36  
    37  	assert.True(p.IsRunning())
    38  	assert.True(p.IsOutbound())
    39  	assert.False(p.IsPersistent())
    40  	p.persistent = true
    41  	assert.True(p.IsPersistent())
    42  	assert.Equal(rp.Addr().DialString(), p.RemoteAddr().String())
    43  	assert.Equal(rp.ID(), p.ID())
    44  }
    45  
    46  func TestPeerSend(t *testing.T) {
    47  	assert, require := assert.New(t), require.New(t)
    48  
    49  	config := cfg
    50  
    51  	// simulate remote peer
    52  	rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: config}
    53  	rp.Start()
    54  	defer rp.Stop()
    55  
    56  	p, err := createOutboundPeerAndPerformHandshake(rp.Addr(), config, tmconn.DefaultMConnConfig())
    57  	require.Nil(err)
    58  
    59  	err = p.Start()
    60  	require.Nil(err)
    61  
    62  	defer p.Stop()
    63  
    64  	assert.True(p.CanSend(testCh))
    65  	assert.True(p.Send(testCh, []byte("Asylum")))
    66  }
    67  
    68  func createOutboundPeerAndPerformHandshake(
    69  	addr *NetAddress,
    70  	config *config.P2PConfig,
    71  	mConfig tmconn.MConnConfig,
    72  ) (*peer, error) {
    73  	chDescs := []*tmconn.ChannelDescriptor{
    74  		{ID: testCh, Priority: 1},
    75  	}
    76  	reactorsByCh := map[byte]Reactor{testCh: NewTestReactor(chDescs, true)}
    77  	pk := ed25519.GenPrivKey()
    78  	pc, err := testOutboundPeerConn(addr, config, false, pk)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  	timeout := 1 * time.Second
    83  	ourNodeInfo := testNodeInfo(addr.ID, "host_peer")
    84  	peerNodeInfo, err := handshake(pc.conn, timeout, ourNodeInfo)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	p := newPeer(pc, mConfig, peerNodeInfo, reactorsByCh, chDescs, func(p Peer, r interface{}) {})
    90  	p.SetLogger(log.TestingLogger().With("peer", addr))
    91  	return p, nil
    92  }
    93  
    94  func testDial(addr *NetAddress, cfg *config.P2PConfig) (net.Conn, error) {
    95  	if cfg.TestDialFail {
    96  		return nil, fmt.Errorf("dial err (peerConfig.DialFail == true)")
    97  	}
    98  
    99  	conn, err := addr.DialTimeout(cfg.DialTimeout)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	return conn, nil
   104  }
   105  
   106  func testOutboundPeerConn(
   107  	addr *NetAddress,
   108  	config *config.P2PConfig,
   109  	persistent bool,
   110  	ourNodePrivKey crypto.PrivKey,
   111  ) (peerConn, error) {
   112  
   113  	var pc peerConn
   114  	conn, err := testDial(addr, config)
   115  	if err != nil {
   116  		return pc, cmn.ErrorWrap(err, "Error creating peer")
   117  	}
   118  
   119  	pc, err = testPeerConn(conn, config, true, persistent, ourNodePrivKey, addr)
   120  	if err != nil {
   121  		if cerr := conn.Close(); cerr != nil {
   122  			return pc, cmn.ErrorWrap(err, cerr.Error())
   123  		}
   124  		return pc, err
   125  	}
   126  
   127  	// ensure dialed ID matches connection ID
   128  	if addr.ID != pc.ID() {
   129  		if cerr := conn.Close(); cerr != nil {
   130  			return pc, cmn.ErrorWrap(err, cerr.Error())
   131  		}
   132  		return pc, ErrSwitchAuthenticationFailure{addr, pc.ID()}
   133  	}
   134  
   135  	return pc, nil
   136  }
   137  
   138  type remotePeer struct {
   139  	PrivKey    crypto.PrivKey
   140  	Config     *config.P2PConfig
   141  	addr       *NetAddress
   142  	channels   cmn.HexBytes
   143  	listenAddr string
   144  	listener   net.Listener
   145  }
   146  
   147  func (rp *remotePeer) Addr() *NetAddress {
   148  	return rp.addr
   149  }
   150  
   151  func (rp *remotePeer) ID() ID {
   152  	return PubKeyToID(rp.PrivKey.PubKey())
   153  }
   154  
   155  func (rp *remotePeer) Start() {
   156  	if rp.listenAddr == "" {
   157  		rp.listenAddr = "127.0.0.1:0"
   158  	}
   159  
   160  	l, e := net.Listen("tcp", rp.listenAddr) // any available address
   161  	if e != nil {
   162  		golog.Fatalf("net.Listen tcp :0: %+v", e)
   163  	}
   164  	rp.listener = l
   165  	rp.addr = NewNetAddress(PubKeyToID(rp.PrivKey.PubKey()), l.Addr())
   166  	if rp.channels == nil {
   167  		rp.channels = []byte{testCh}
   168  	}
   169  	go rp.accept()
   170  }
   171  
   172  func (rp *remotePeer) Stop() {
   173  	rp.listener.Close()
   174  }
   175  
   176  func (rp *remotePeer) Dial(addr *NetAddress) (net.Conn, error) {
   177  	conn, err := addr.DialTimeout(1 * time.Second)
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  	pc, err := testInboundPeerConn(conn, rp.Config, rp.PrivKey)
   182  	if err != nil {
   183  		return nil, err
   184  	}
   185  	_, err = handshake(pc.conn, time.Second, rp.nodeInfo())
   186  	if err != nil {
   187  		return nil, err
   188  	}
   189  	return conn, err
   190  }
   191  
   192  func (rp *remotePeer) accept() {
   193  	conns := []net.Conn{}
   194  
   195  	for {
   196  		conn, err := rp.listener.Accept()
   197  		if err != nil {
   198  			golog.Printf("Failed to accept conn: %+v", err)
   199  			for _, conn := range conns {
   200  				_ = conn.Close()
   201  			}
   202  			return
   203  		}
   204  
   205  		pc, err := testInboundPeerConn(conn, rp.Config, rp.PrivKey)
   206  		if err != nil {
   207  			golog.Fatalf("Failed to create a peer: %+v", err)
   208  		}
   209  
   210  		_, err = handshake(pc.conn, time.Second, rp.nodeInfo())
   211  		if err != nil {
   212  			golog.Fatalf("Failed to perform handshake: %+v", err)
   213  		}
   214  
   215  		conns = append(conns, conn)
   216  	}
   217  }
   218  
   219  func (rp *remotePeer) nodeInfo() NodeInfo {
   220  	return DefaultNodeInfo{
   221  		ProtocolVersion: defaultProtocolVersion,
   222  		ID_:             rp.Addr().ID,
   223  		ListenAddr:      rp.listener.Addr().String(),
   224  		Network:         "testing",
   225  		Version:         "1.2.3-rc0-deadbeef",
   226  		Channels:        rp.channels,
   227  		Moniker:         "remote_peer",
   228  	}
   229  }