github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/sync/rpc_beacon_blocks_by_root_test.go (about) 1 package sync 2 3 import ( 4 "context" 5 "sync" 6 "testing" 7 "time" 8 9 "github.com/kevinms/leakybucket-go" 10 "github.com/libp2p/go-libp2p-core/network" 11 "github.com/libp2p/go-libp2p-core/protocol" 12 gcache "github.com/patrickmn/go-cache" 13 types "github.com/prysmaticlabs/eth2-types" 14 mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" 15 "github.com/prysmaticlabs/prysm/beacon-chain/core/state" 16 db "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" 17 "github.com/prysmaticlabs/prysm/beacon-chain/p2p" 18 p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" 19 p2pTypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types" 20 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 21 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper" 22 "github.com/prysmaticlabs/prysm/shared/params" 23 "github.com/prysmaticlabs/prysm/shared/testutil" 24 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 25 "github.com/prysmaticlabs/prysm/shared/testutil/require" 26 ) 27 28 func TestRecentBeaconBlocksRPCHandler_ReturnsBlocks(t *testing.T) { 29 p1 := p2ptest.NewTestP2P(t) 30 p2 := p2ptest.NewTestP2P(t) 31 p1.Connect(p2) 32 assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected") 33 d := db.SetupDB(t) 34 35 var blkRoots p2pTypes.BeaconBlockByRootsReq 36 // Populate the database with blocks that would match the request. 37 for i := types.Slot(1); i < 11; i++ { 38 blk := testutil.NewBeaconBlock() 39 blk.Block.Slot = i 40 root, err := blk.Block.HashTreeRoot() 41 require.NoError(t, err) 42 require.NoError(t, d.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(blk))) 43 blkRoots = append(blkRoots, root) 44 } 45 46 r := &Service{cfg: &Config{P2P: p1, DB: d}, rateLimiter: newRateLimiter(p1)} 47 pcl := protocol.ID(p2p.RPCBlocksByRootTopicV1) 48 topic := string(pcl) 49 r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(10000, 10000, false) 50 51 var wg sync.WaitGroup 52 wg.Add(1) 53 p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) { 54 defer wg.Done() 55 for i := range blkRoots { 56 expectSuccess(t, stream) 57 res := testutil.NewBeaconBlock() 58 assert.NoError(t, r.cfg.P2P.Encoding().DecodeWithMaxLength(stream, res)) 59 if uint64(res.Block.Slot) != uint64(i+1) { 60 t.Errorf("Received unexpected block slot %d but wanted %d", res.Block.Slot, i+1) 61 } 62 } 63 }) 64 65 stream1, err := p1.BHost.NewStream(context.Background(), p2.BHost.ID(), pcl) 66 require.NoError(t, err) 67 err = r.beaconBlocksRootRPCHandler(context.Background(), &blkRoots, stream1) 68 assert.NoError(t, err) 69 70 if testutil.WaitTimeout(&wg, 1*time.Second) { 71 t.Fatal("Did not receive stream within 1 sec") 72 } 73 } 74 75 func TestRecentBeaconBlocks_RPCRequestSent(t *testing.T) { 76 p1 := p2ptest.NewTestP2P(t) 77 p2 := p2ptest.NewTestP2P(t) 78 p1.DelaySend = true 79 80 blockA := testutil.NewBeaconBlock() 81 blockA.Block.Slot = 111 82 blockB := testutil.NewBeaconBlock() 83 blockB.Block.Slot = 40 84 // Set up a head state with data we expect. 85 blockARoot, err := blockA.Block.HashTreeRoot() 86 require.NoError(t, err) 87 blockBRoot, err := blockB.Block.HashTreeRoot() 88 require.NoError(t, err) 89 genesisState, err := state.GenesisBeaconState(context.Background(), nil, 0, ðpb.Eth1Data{}) 90 require.NoError(t, err) 91 require.NoError(t, genesisState.SetSlot(111)) 92 require.NoError(t, genesisState.UpdateBlockRootAtIndex(111%uint64(params.BeaconConfig().SlotsPerHistoricalRoot), blockARoot)) 93 finalizedCheckpt := ðpb.Checkpoint{ 94 Epoch: 5, 95 Root: blockBRoot[:], 96 } 97 98 expectedRoots := p2pTypes.BeaconBlockByRootsReq{blockBRoot, blockARoot} 99 100 r := &Service{ 101 cfg: &Config{ 102 P2P: p1, 103 Chain: &mock.ChainService{ 104 State: genesisState, 105 FinalizedCheckPoint: finalizedCheckpt, 106 Root: blockARoot[:], 107 }, 108 }, 109 slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), 110 seenPendingBlocks: make(map[[32]byte]bool), 111 ctx: context.Background(), 112 rateLimiter: newRateLimiter(p1), 113 } 114 115 // Setup streams 116 pcl := protocol.ID("/eth2/beacon_chain/req/beacon_blocks_by_root/1/ssz_snappy") 117 topic := string(pcl) 118 r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(10000, 10000, false) 119 120 var wg sync.WaitGroup 121 wg.Add(1) 122 p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) { 123 defer wg.Done() 124 out := new(p2pTypes.BeaconBlockByRootsReq) 125 assert.NoError(t, p2.Encoding().DecodeWithMaxLength(stream, out)) 126 assert.DeepEqual(t, &expectedRoots, out, "Did not receive expected message") 127 response := []*ethpb.SignedBeaconBlock{blockB, blockA} 128 for _, blk := range response { 129 _, err := stream.Write([]byte{responseCodeSuccess}) 130 assert.NoError(t, err, "Could not write to stream") 131 _, err = p2.Encoding().EncodeWithMaxLength(stream, blk) 132 assert.NoError(t, err, "Could not send response back") 133 } 134 assert.NoError(t, stream.Close()) 135 }) 136 137 p1.Connect(p2) 138 require.NoError(t, r.sendRecentBeaconBlocksRequest(context.Background(), &expectedRoots, p2.PeerID())) 139 140 if testutil.WaitTimeout(&wg, 1*time.Second) { 141 t.Fatal("Did not receive stream within 1 sec") 142 } 143 } 144 145 func TestRecentBeaconBlocksRPCHandler_HandleZeroBlocks(t *testing.T) { 146 p1 := p2ptest.NewTestP2P(t) 147 p2 := p2ptest.NewTestP2P(t) 148 p1.Connect(p2) 149 assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected") 150 d := db.SetupDB(t) 151 152 r := &Service{cfg: &Config{P2P: p1, DB: d}, rateLimiter: newRateLimiter(p1)} 153 pcl := protocol.ID(p2p.RPCBlocksByRootTopicV1) 154 topic := string(pcl) 155 r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(1, 1, false) 156 157 var wg sync.WaitGroup 158 wg.Add(1) 159 p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) { 160 defer wg.Done() 161 expectFailure(t, 1, "no block roots provided in request", stream) 162 }) 163 164 stream1, err := p1.BHost.NewStream(context.Background(), p2.BHost.ID(), pcl) 165 require.NoError(t, err) 166 err = r.beaconBlocksRootRPCHandler(context.Background(), &p2pTypes.BeaconBlockByRootsReq{}, stream1) 167 assert.ErrorContains(t, "no block roots provided", err) 168 if testutil.WaitTimeout(&wg, 1*time.Second) { 169 t.Fatal("Did not receive stream within 1 sec") 170 } 171 172 r.rateLimiter.RLock() // retrieveCollector requires a lock to be held. 173 defer r.rateLimiter.RUnlock() 174 lter, err := r.rateLimiter.retrieveCollector(topic) 175 require.NoError(t, err) 176 assert.Equal(t, 1, int(lter.Count(stream1.Conn().RemotePeer().String()))) 177 }