github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/p2p/transport_test.go (about)

     1  package p2p
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"net"
     7  	"reflect"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/gnolang/gno/tm2/pkg/amino"
    12  	"github.com/gnolang/gno/tm2/pkg/crypto/ed25519"
    13  	"github.com/gnolang/gno/tm2/pkg/p2p/conn"
    14  	"github.com/gnolang/gno/tm2/pkg/testutils"
    15  )
    16  
    17  var defaultNodeName = "host_peer"
    18  
    19  func emptyNodeInfo() NodeInfo {
    20  	return NodeInfo{}
    21  }
    22  
    23  // newMultiplexTransport returns a tcp connected multiplexed peer
    24  // using the default MConnConfig. It's a convenience function used
    25  // for testing.
    26  func newMultiplexTransport(
    27  	nodeInfo NodeInfo,
    28  	nodeKey NodeKey,
    29  ) *MultiplexTransport {
    30  	return NewMultiplexTransport(
    31  		nodeInfo, nodeKey, conn.DefaultMConnConfig(),
    32  	)
    33  }
    34  
    35  func TestTransportMultiplexConnFilter(t *testing.T) {
    36  	t.Parallel()
    37  
    38  	mt := newMultiplexTransport(
    39  		emptyNodeInfo(),
    40  		NodeKey{
    41  			PrivKey: ed25519.GenPrivKey(),
    42  		},
    43  	)
    44  	id := mt.nodeKey.ID()
    45  
    46  	MultiplexTransportConnFilters(
    47  		func(_ ConnSet, _ net.Conn, _ []net.IP) error { return nil },
    48  		func(_ ConnSet, _ net.Conn, _ []net.IP) error { return nil },
    49  		func(_ ConnSet, _ net.Conn, _ []net.IP) error {
    50  			return fmt.Errorf("rejected")
    51  		},
    52  	)(mt)
    53  
    54  	addr, err := NewNetAddressFromString(NetAddressString(id, "127.0.0.1:0"))
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  
    59  	if err := mt.Listen(*addr); err != nil {
    60  		t.Fatal(err)
    61  	}
    62  
    63  	errc := make(chan error)
    64  
    65  	go func() {
    66  		addr := NewNetAddress(id, mt.listener.Addr())
    67  
    68  		_, err := addr.Dial()
    69  		if err != nil {
    70  			errc <- err
    71  			return
    72  		}
    73  
    74  		close(errc)
    75  	}()
    76  
    77  	if err := <-errc; err != nil {
    78  		t.Errorf("connection failed: %v", err)
    79  	}
    80  
    81  	_, err = mt.Accept(peerConfig{})
    82  	if err, ok := err.(RejectedError); ok {
    83  		if !err.IsFiltered() {
    84  			t.Errorf("expected peer to be filtered")
    85  		}
    86  	} else {
    87  		t.Errorf("expected RejectedError")
    88  	}
    89  }
    90  
    91  func TestTransportMultiplexConnFilterTimeout(t *testing.T) {
    92  	t.Parallel()
    93  
    94  	mt := newMultiplexTransport(
    95  		emptyNodeInfo(),
    96  		NodeKey{
    97  			PrivKey: ed25519.GenPrivKey(),
    98  		},
    99  	)
   100  	id := mt.nodeKey.ID()
   101  
   102  	MultiplexTransportFilterTimeout(5 * time.Millisecond)(mt)
   103  	MultiplexTransportConnFilters(
   104  		func(_ ConnSet, _ net.Conn, _ []net.IP) error {
   105  			time.Sleep(100 * time.Millisecond)
   106  			return nil
   107  		},
   108  	)(mt)
   109  
   110  	addr, err := NewNetAddressFromString(NetAddressString(id, "127.0.0.1:0"))
   111  	if err != nil {
   112  		t.Fatal(err)
   113  	}
   114  
   115  	if err := mt.Listen(*addr); err != nil {
   116  		t.Fatal(err)
   117  	}
   118  
   119  	errc := make(chan error)
   120  
   121  	go func() {
   122  		addr := NewNetAddress(id, mt.listener.Addr())
   123  
   124  		_, err := addr.Dial()
   125  		if err != nil {
   126  			errc <- err
   127  			return
   128  		}
   129  
   130  		close(errc)
   131  	}()
   132  
   133  	if err := <-errc; err != nil {
   134  		t.Errorf("connection failed: %v", err)
   135  	}
   136  
   137  	_, err = mt.Accept(peerConfig{})
   138  	if _, ok := err.(FilterTimeoutError); !ok {
   139  		t.Errorf("expected FilterTimeoutError")
   140  	}
   141  }
   142  
   143  func TestTransportMultiplexAcceptMultiple(t *testing.T) {
   144  	t.Parallel()
   145  
   146  	mt := testSetupMultiplexTransport(t)
   147  	laddr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   148  
   149  	var (
   150  		seed     = rand.New(rand.NewSource(time.Now().UnixNano()))
   151  		nDialers = seed.Intn(64) + 64
   152  		errc     = make(chan error, nDialers)
   153  	)
   154  
   155  	// Setup dialers.
   156  	for i := 0; i < nDialers; i++ {
   157  		go testDialer(*laddr, errc)
   158  	}
   159  
   160  	// Catch connection errors.
   161  	for i := 0; i < nDialers; i++ {
   162  		if err := <-errc; err != nil {
   163  			t.Fatal(err)
   164  		}
   165  	}
   166  
   167  	ps := []Peer{}
   168  
   169  	// Accept all peers.
   170  	for i := 0; i < cap(errc); i++ {
   171  		p, err := mt.Accept(peerConfig{})
   172  		if err != nil {
   173  			t.Fatal(err)
   174  		}
   175  
   176  		if err := p.Start(); err != nil {
   177  			t.Fatal(err)
   178  		}
   179  
   180  		ps = append(ps, p)
   181  	}
   182  
   183  	if have, want := len(ps), cap(errc); have != want {
   184  		t.Errorf("have %v, want %v", have, want)
   185  	}
   186  
   187  	// Stop all peers.
   188  	for _, p := range ps {
   189  		if err := p.Stop(); err != nil {
   190  			t.Fatal(err)
   191  		}
   192  	}
   193  
   194  	if err := mt.Close(); err != nil {
   195  		t.Errorf("close errored: %v", err)
   196  	}
   197  }
   198  
   199  func testDialer(dialAddr NetAddress, errc chan error) {
   200  	var (
   201  		pv     = ed25519.GenPrivKey()
   202  		dialer = newMultiplexTransport(
   203  			testNodeInfo(pv.PubKey().Address().ID(), defaultNodeName),
   204  			NodeKey{
   205  				PrivKey: pv,
   206  			},
   207  		)
   208  	)
   209  
   210  	_, err := dialer.Dial(dialAddr, peerConfig{})
   211  	if err != nil {
   212  		errc <- err
   213  		return
   214  	}
   215  
   216  	// Signal that the connection was established.
   217  	errc <- nil
   218  }
   219  
   220  func TestFlappyTransportMultiplexAcceptNonBlocking(t *testing.T) {
   221  	t.Parallel()
   222  
   223  	testutils.FilterStability(t, testutils.Flappy)
   224  
   225  	mt := testSetupMultiplexTransport(t)
   226  
   227  	var (
   228  		fastNodePV   = ed25519.GenPrivKey()
   229  		fastNodeInfo = testNodeInfo(fastNodePV.PubKey().Address().ID(), "fastnode")
   230  		errc         = make(chan error)
   231  		fastc        = make(chan struct{})
   232  		slowc        = make(chan struct{})
   233  	)
   234  
   235  	// Simulate slow Peer.
   236  	go func() {
   237  		addr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   238  
   239  		c, err := addr.Dial()
   240  		if err != nil {
   241  			errc <- err
   242  			return
   243  		}
   244  
   245  		close(slowc)
   246  
   247  		select {
   248  		case <-fastc:
   249  			// Fast peer connected.
   250  		case <-time.After(100 * time.Millisecond):
   251  			// We error if the fast peer didn't succeed.
   252  			errc <- fmt.Errorf("Fast peer timed out")
   253  		}
   254  
   255  		sc, err := upgradeSecretConn(c, 100*time.Millisecond, ed25519.GenPrivKey())
   256  		if err != nil {
   257  			errc <- err
   258  			return
   259  		}
   260  
   261  		_, err = handshake(sc, 100*time.Millisecond,
   262  			testNodeInfo(
   263  				ed25519.GenPrivKey().PubKey().Address().ID(),
   264  				"slow_peer",
   265  			))
   266  		if err != nil {
   267  			errc <- err
   268  			return
   269  		}
   270  	}()
   271  
   272  	// Simulate fast Peer.
   273  	go func() {
   274  		<-slowc
   275  
   276  		dialer := newMultiplexTransport(
   277  			fastNodeInfo,
   278  			NodeKey{
   279  				PrivKey: fastNodePV,
   280  			},
   281  		)
   282  		addr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   283  
   284  		_, err := dialer.Dial(*addr, peerConfig{})
   285  		if err != nil {
   286  			errc <- err
   287  			return
   288  		}
   289  
   290  		close(errc)
   291  		close(fastc)
   292  	}()
   293  
   294  	if err := <-errc; err != nil {
   295  		t.Errorf("connection failed: %v", err)
   296  	}
   297  
   298  	p, err := mt.Accept(peerConfig{})
   299  	if err != nil {
   300  		t.Fatal(err)
   301  	}
   302  
   303  	if have, want := p.NodeInfo(), fastNodeInfo; !reflect.DeepEqual(have, want) {
   304  		t.Errorf("have %v, want %v", have, want)
   305  	}
   306  }
   307  
   308  func TestTransportMultiplexValidateNodeInfo(t *testing.T) {
   309  	t.Parallel()
   310  
   311  	mt := testSetupMultiplexTransport(t)
   312  
   313  	errc := make(chan error)
   314  
   315  	go func() {
   316  		var (
   317  			pv     = ed25519.GenPrivKey()
   318  			dialer = newMultiplexTransport(
   319  				testNodeInfo(pv.PubKey().Address().ID(), ""), // Should not be empty
   320  				NodeKey{
   321  					PrivKey: pv,
   322  				},
   323  			)
   324  		)
   325  
   326  		addr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   327  
   328  		_, err := dialer.Dial(*addr, peerConfig{})
   329  		if err != nil {
   330  			errc <- err
   331  			return
   332  		}
   333  
   334  		close(errc)
   335  	}()
   336  
   337  	if err := <-errc; err != nil {
   338  		t.Errorf("connection failed: %v", err)
   339  	}
   340  
   341  	_, err := mt.Accept(peerConfig{})
   342  	if err, ok := err.(RejectedError); ok {
   343  		if !err.IsNodeInfoInvalid() {
   344  			t.Errorf("expected NodeInfo to be invalid")
   345  		}
   346  	} else {
   347  		t.Errorf("expected RejectedError")
   348  	}
   349  }
   350  
   351  func TestTransportMultiplexRejectMismatchID(t *testing.T) {
   352  	t.Parallel()
   353  
   354  	mt := testSetupMultiplexTransport(t)
   355  
   356  	errc := make(chan error)
   357  
   358  	go func() {
   359  		dialer := newMultiplexTransport(
   360  			testNodeInfo(
   361  				ed25519.GenPrivKey().PubKey().Address().ID(), "dialer",
   362  			),
   363  			NodeKey{
   364  				PrivKey: ed25519.GenPrivKey(),
   365  			},
   366  		)
   367  		addr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   368  
   369  		_, err := dialer.Dial(*addr, peerConfig{})
   370  		if err != nil {
   371  			errc <- err
   372  			return
   373  		}
   374  
   375  		close(errc)
   376  	}()
   377  
   378  	if err := <-errc; err != nil {
   379  		t.Errorf("connection failed: %v", err)
   380  	}
   381  
   382  	_, err := mt.Accept(peerConfig{})
   383  	if err, ok := err.(RejectedError); ok {
   384  		if !err.IsAuthFailure() {
   385  			t.Errorf("expected auth failure")
   386  		}
   387  	} else {
   388  		t.Errorf("expected RejectedError")
   389  	}
   390  }
   391  
   392  func TestTransportMultiplexDialRejectWrongID(t *testing.T) {
   393  	t.Parallel()
   394  
   395  	mt := testSetupMultiplexTransport(t)
   396  
   397  	var (
   398  		pv     = ed25519.GenPrivKey()
   399  		dialer = newMultiplexTransport(
   400  			testNodeInfo(pv.PubKey().Address().ID(), ""), // Should not be empty
   401  			NodeKey{
   402  				PrivKey: pv,
   403  			},
   404  		)
   405  	)
   406  
   407  	wrongID := ed25519.GenPrivKey().PubKey().Address().ID()
   408  	addr := NewNetAddress(wrongID, mt.listener.Addr())
   409  
   410  	_, err := dialer.Dial(*addr, peerConfig{})
   411  	if err != nil {
   412  		t.Logf("connection failed: %v", err)
   413  		if err, ok := err.(RejectedError); ok {
   414  			if !err.IsAuthFailure() {
   415  				t.Errorf("expected auth failure")
   416  			}
   417  		} else {
   418  			t.Errorf("expected RejectedError")
   419  		}
   420  	}
   421  }
   422  
   423  func TestTransportMultiplexRejectIncompatible(t *testing.T) {
   424  	t.Parallel()
   425  
   426  	mt := testSetupMultiplexTransport(t)
   427  
   428  	errc := make(chan error)
   429  
   430  	go func() {
   431  		var (
   432  			pv     = ed25519.GenPrivKey()
   433  			dialer = newMultiplexTransport(
   434  				testNodeInfoWithNetwork(pv.PubKey().Address().ID(), "dialer", "incompatible-network"),
   435  				NodeKey{
   436  					PrivKey: pv,
   437  				},
   438  			)
   439  		)
   440  		addr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   441  
   442  		_, err := dialer.Dial(*addr, peerConfig{})
   443  		if err != nil {
   444  			errc <- err
   445  			return
   446  		}
   447  
   448  		close(errc)
   449  	}()
   450  
   451  	_, err := mt.Accept(peerConfig{})
   452  	if err, ok := err.(RejectedError); ok {
   453  		if !err.IsIncompatible() {
   454  			t.Errorf("expected to reject incompatible")
   455  		}
   456  	} else {
   457  		t.Errorf("expected RejectedError")
   458  	}
   459  }
   460  
   461  func TestTransportMultiplexRejectSelf(t *testing.T) {
   462  	t.Parallel()
   463  
   464  	mt := testSetupMultiplexTransport(t)
   465  
   466  	errc := make(chan error)
   467  
   468  	go func() {
   469  		addr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   470  
   471  		_, err := mt.Dial(*addr, peerConfig{})
   472  		if err != nil {
   473  			errc <- err
   474  			return
   475  		}
   476  
   477  		close(errc)
   478  	}()
   479  
   480  	if err := <-errc; err != nil {
   481  		if err, ok := err.(RejectedError); ok {
   482  			if !err.IsSelf() {
   483  				t.Errorf("expected to reject self, got: %v", err)
   484  			}
   485  		} else {
   486  			t.Errorf("expected RejectedError")
   487  		}
   488  	} else {
   489  		t.Errorf("expected connection failure")
   490  	}
   491  
   492  	_, err := mt.Accept(peerConfig{})
   493  	if err, ok := err.(RejectedError); ok {
   494  		if !err.IsSelf() {
   495  			t.Errorf("expected to reject self, got: %v", err)
   496  		}
   497  	} else {
   498  		t.Errorf("expected RejectedError")
   499  	}
   500  }
   501  
   502  func TestTransportConnDuplicateIPFilter(t *testing.T) {
   503  	t.Parallel()
   504  
   505  	filter := ConnDuplicateIPFilter()
   506  
   507  	if err := filter(nil, &testTransportConn{}, nil); err != nil {
   508  		t.Fatal(err)
   509  	}
   510  
   511  	var (
   512  		c  = &testTransportConn{}
   513  		cs = NewConnSet()
   514  	)
   515  
   516  	cs.Set(c, []net.IP{
   517  		{10, 0, 10, 1},
   518  		{10, 0, 10, 2},
   519  		{10, 0, 10, 3},
   520  	})
   521  
   522  	if err := filter(cs, c, []net.IP{
   523  		{10, 0, 10, 2},
   524  	}); err == nil {
   525  		t.Errorf("expected Peer to be rejected as duplicate")
   526  	}
   527  }
   528  
   529  func TestTransportHandshake(t *testing.T) {
   530  	t.Parallel()
   531  
   532  	ln, err := net.Listen("tcp", "127.0.0.1:0")
   533  	if err != nil {
   534  		t.Fatal(err)
   535  	}
   536  
   537  	var (
   538  		peerPV       = ed25519.GenPrivKey()
   539  		peerNodeInfo = testNodeInfo(peerPV.PubKey().Address().ID(), defaultNodeName)
   540  	)
   541  
   542  	go func() {
   543  		c, err := net.Dial(ln.Addr().Network(), ln.Addr().String())
   544  		if err != nil {
   545  			t.Error(err)
   546  			return
   547  		}
   548  
   549  		go func(c net.Conn) {
   550  			_, err := amino.MarshalSizedWriter(c, peerNodeInfo)
   551  			if err != nil {
   552  				t.Error(err)
   553  			}
   554  		}(c)
   555  		go func(c net.Conn) {
   556  			var ni NodeInfo
   557  
   558  			_, err := amino.UnmarshalSizedReader(
   559  				c,
   560  				&ni,
   561  				int64(MaxNodeInfoSize()),
   562  			)
   563  			if err != nil {
   564  				t.Error(err)
   565  			}
   566  		}(c)
   567  	}()
   568  
   569  	c, err := ln.Accept()
   570  	if err != nil {
   571  		t.Fatal(err)
   572  	}
   573  
   574  	ni, err := handshake(c, 100*time.Millisecond, emptyNodeInfo())
   575  	if err != nil {
   576  		t.Fatal(err)
   577  	}
   578  
   579  	if have, want := ni, peerNodeInfo; !reflect.DeepEqual(have, want) {
   580  		t.Errorf("have %v, want %v", have, want)
   581  	}
   582  }
   583  
   584  // create listener
   585  func testSetupMultiplexTransport(t *testing.T) *MultiplexTransport {
   586  	t.Helper()
   587  
   588  	var (
   589  		pv = ed25519.GenPrivKey()
   590  		id = pv.PubKey().Address().ID()
   591  		mt = newMultiplexTransport(
   592  			testNodeInfo(
   593  				id, "transport",
   594  			),
   595  			NodeKey{
   596  				PrivKey: pv,
   597  			},
   598  		)
   599  	)
   600  
   601  	addr, err := NewNetAddressFromString(NetAddressString(id, "127.0.0.1:0"))
   602  	if err != nil {
   603  		t.Fatal(err)
   604  	}
   605  
   606  	if err := mt.Listen(*addr); err != nil {
   607  		t.Fatal(err)
   608  	}
   609  
   610  	return mt
   611  }
   612  
   613  type testTransportAddr struct{}
   614  
   615  func (a *testTransportAddr) Network() string { return "tcp" }
   616  func (a *testTransportAddr) String() string  { return "test.local:1234" }
   617  
   618  type testTransportConn struct{}
   619  
   620  func (c *testTransportConn) Close() error {
   621  	return fmt.Errorf("Close() not implemented")
   622  }
   623  
   624  func (c *testTransportConn) LocalAddr() net.Addr {
   625  	return &testTransportAddr{}
   626  }
   627  
   628  func (c *testTransportConn) RemoteAddr() net.Addr {
   629  	return &testTransportAddr{}
   630  }
   631  
   632  func (c *testTransportConn) Read(_ []byte) (int, error) {
   633  	return -1, fmt.Errorf("Read() not implemented")
   634  }
   635  
   636  func (c *testTransportConn) SetDeadline(_ time.Time) error {
   637  	return fmt.Errorf("SetDeadline() not implemented")
   638  }
   639  
   640  func (c *testTransportConn) SetReadDeadline(_ time.Time) error {
   641  	return fmt.Errorf("SetReadDeadline() not implemented")
   642  }
   643  
   644  func (c *testTransportConn) SetWriteDeadline(_ time.Time) error {
   645  	return fmt.Errorf("SetWriteDeadline() not implemented")
   646  }
   647  
   648  func (c *testTransportConn) Write(_ []byte) (int, error) {
   649  	return -1, fmt.Errorf("Write() not implemented")
   650  }