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 }