github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/sync/rpc_ping_test.go (about)

     1  package sync
     2  
     3  import (
     4  	"context"
     5  	"sync"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/ethereum/go-ethereum/p2p/enr"
    10  	"github.com/kevinms/leakybucket-go"
    11  	"github.com/libp2p/go-libp2p-core/network"
    12  	"github.com/libp2p/go-libp2p-core/protocol"
    13  	types "github.com/prysmaticlabs/eth2-types"
    14  	db "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
    15  	p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
    16  	p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
    17  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    18  	"github.com/prysmaticlabs/prysm/shared/interfaces"
    19  	"github.com/prysmaticlabs/prysm/shared/testutil"
    20  	"github.com/prysmaticlabs/prysm/shared/testutil/assert"
    21  	"github.com/prysmaticlabs/prysm/shared/testutil/require"
    22  )
    23  
    24  func TestPingRPCHandler_ReceivesPing(t *testing.T) {
    25  	p1 := p2ptest.NewTestP2P(t)
    26  	p2 := p2ptest.NewTestP2P(t)
    27  	p1.Connect(p2)
    28  	assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected")
    29  	p1.LocalMetadata = interfaces.WrappedMetadataV0(&pb.MetaDataV0{
    30  		SeqNumber: 2,
    31  		Attnets:   []byte{'A', 'B'},
    32  	})
    33  
    34  	p2.LocalMetadata = interfaces.WrappedMetadataV0(&pb.MetaDataV0{
    35  		SeqNumber: 2,
    36  		Attnets:   []byte{'C', 'D'},
    37  	})
    38  
    39  	// Set up a head state in the database with data we expect.
    40  	d := db.SetupDB(t)
    41  	r := &Service{
    42  		cfg: &Config{
    43  			DB:  d,
    44  			P2P: p1,
    45  		},
    46  		rateLimiter: newRateLimiter(p1),
    47  	}
    48  
    49  	p1.Peers().Add(new(enr.Record), p2.BHost.ID(), p2.BHost.Addrs()[0], network.DirUnknown)
    50  	p1.Peers().SetMetadata(p2.BHost.ID(), p2.LocalMetadata)
    51  
    52  	// Setup streams
    53  	pcl := protocol.ID("/testing")
    54  	topic := string(pcl)
    55  	r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(1, 1, false)
    56  	var wg sync.WaitGroup
    57  	wg.Add(1)
    58  	p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) {
    59  		defer wg.Done()
    60  		expectSuccess(t, stream)
    61  		out := new(types.SSZUint64)
    62  		assert.NoError(t, r.cfg.P2P.Encoding().DecodeWithMaxLength(stream, out))
    63  		assert.Equal(t, uint64(2), uint64(*out))
    64  	})
    65  	stream1, err := p1.BHost.NewStream(context.Background(), p2.BHost.ID(), pcl)
    66  	require.NoError(t, err)
    67  	seqNumber := types.SSZUint64(2)
    68  
    69  	assert.NoError(t, r.pingHandler(context.Background(), &seqNumber, stream1))
    70  
    71  	if testutil.WaitTimeout(&wg, 1*time.Second) {
    72  		t.Fatal("Did not receive stream within 1 sec")
    73  	}
    74  
    75  	conns := p1.BHost.Network().ConnsToPeer(p2.BHost.ID())
    76  	if len(conns) == 0 {
    77  		t.Error("Peer is disconnected despite receiving a valid ping")
    78  	}
    79  }
    80  
    81  func TestPingRPCHandler_SendsPing(t *testing.T) {
    82  	p1 := p2ptest.NewTestP2P(t)
    83  	p2 := p2ptest.NewTestP2P(t)
    84  	p1.Connect(p2)
    85  	assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected")
    86  	p1.LocalMetadata = interfaces.WrappedMetadataV0(&pb.MetaDataV0{
    87  		SeqNumber: 2,
    88  		Attnets:   []byte{'A', 'B'},
    89  	})
    90  
    91  	p2.LocalMetadata = interfaces.WrappedMetadataV0(&pb.MetaDataV0{
    92  		SeqNumber: 2,
    93  		Attnets:   []byte{'C', 'D'},
    94  	})
    95  
    96  	// Set up a head state in the database with data we expect.
    97  	d := db.SetupDB(t)
    98  	r := &Service{
    99  		cfg: &Config{
   100  			DB:  d,
   101  			P2P: p1,
   102  		},
   103  		rateLimiter: newRateLimiter(p1),
   104  	}
   105  
   106  	p1.Peers().Add(new(enr.Record), p2.BHost.ID(), p2.BHost.Addrs()[0], network.DirUnknown)
   107  	p1.Peers().SetMetadata(p2.BHost.ID(), p2.LocalMetadata)
   108  
   109  	p2.Peers().Add(new(enr.Record), p1.BHost.ID(), p1.BHost.Addrs()[0], network.DirUnknown)
   110  	p2.Peers().SetMetadata(p1.BHost.ID(), p1.LocalMetadata)
   111  
   112  	r2 := &Service{
   113  		cfg: &Config{
   114  			DB:  d,
   115  			P2P: p2,
   116  		},
   117  		rateLimiter: newRateLimiter(p2),
   118  	}
   119  	// Setup streams
   120  	pcl := protocol.ID("/eth2/beacon_chain/req/ping/1/ssz_snappy")
   121  	topic := string(pcl)
   122  	r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(1, 1, false)
   123  
   124  	var wg sync.WaitGroup
   125  	wg.Add(1)
   126  	p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) {
   127  		defer wg.Done()
   128  		out := new(types.SSZUint64)
   129  		assert.NoError(t, r2.cfg.P2P.Encoding().DecodeWithMaxLength(stream, out))
   130  		assert.Equal(t, uint64(2), uint64(*out))
   131  		assert.NoError(t, r2.pingHandler(context.Background(), out, stream))
   132  	})
   133  
   134  	assert.NoError(t, r.sendPingRequest(context.Background(), p2.BHost.ID()))
   135  
   136  	if testutil.WaitTimeout(&wg, 1*time.Second) {
   137  		t.Fatal("Did not receive stream within 1 sec")
   138  	}
   139  
   140  	conns := p1.BHost.Network().ConnsToPeer(p2.BHost.ID())
   141  	if len(conns) == 0 {
   142  		t.Error("Peer is disconnected despite receiving a valid ping")
   143  	}
   144  }
   145  
   146  func TestPingRPCHandler_BadSequenceNumber(t *testing.T) {
   147  	p1 := p2ptest.NewTestP2P(t)
   148  	p2 := p2ptest.NewTestP2P(t)
   149  	p1.Connect(p2)
   150  	assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected")
   151  	p1.LocalMetadata = interfaces.WrappedMetadataV0(&pb.MetaDataV0{
   152  		SeqNumber: 2,
   153  		Attnets:   []byte{'A', 'B'},
   154  	})
   155  
   156  	p2.LocalMetadata = interfaces.WrappedMetadataV0(&pb.MetaDataV0{
   157  		SeqNumber: 2,
   158  		Attnets:   []byte{'C', 'D'},
   159  	})
   160  
   161  	// Set up a head state in the database with data we expect.
   162  	d := db.SetupDB(t)
   163  	r := &Service{
   164  		cfg: &Config{
   165  			DB:  d,
   166  			P2P: p1,
   167  		},
   168  		rateLimiter: newRateLimiter(p1),
   169  	}
   170  
   171  	badMetadata := &pb.MetaDataV0{
   172  		SeqNumber: 3,
   173  		Attnets:   []byte{'E', 'F'},
   174  	}
   175  
   176  	p1.Peers().Add(new(enr.Record), p2.BHost.ID(), p2.BHost.Addrs()[0], network.DirUnknown)
   177  	p1.Peers().SetMetadata(p2.BHost.ID(), interfaces.WrappedMetadataV0(badMetadata))
   178  
   179  	// Setup streams
   180  	pcl := protocol.ID("/testing")
   181  	topic := string(pcl)
   182  	r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(1, 1, false)
   183  	var wg sync.WaitGroup
   184  	wg.Add(1)
   185  	p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) {
   186  		defer wg.Done()
   187  		expectFailure(t, responseCodeInvalidRequest, p2ptypes.ErrInvalidSequenceNum.Error(), stream)
   188  
   189  	})
   190  	stream1, err := p1.BHost.NewStream(context.Background(), p2.BHost.ID(), pcl)
   191  	require.NoError(t, err)
   192  
   193  	wantedSeq := types.SSZUint64(p2.LocalMetadata.SequenceNumber())
   194  	err = r.pingHandler(context.Background(), &wantedSeq, stream1)
   195  	assert.ErrorContains(t, p2ptypes.ErrInvalidSequenceNum.Error(), err)
   196  
   197  	if testutil.WaitTimeout(&wg, 1*time.Second) {
   198  		t.Fatal("Did not receive stream within 1 sec")
   199  	}
   200  
   201  	res, err := p1.Peers().Scorers().BadResponsesScorer().Count(p2.BHost.ID())
   202  	assert.NoError(t, err)
   203  	assert.Equal(t, 1, res, "Peer wasn't penalised for providing a bad sequence number")
   204  }