github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/sync/pending_blocks_queue_test.go (about) 1 package sync 2 3 import ( 4 "context" 5 "math" 6 "sync" 7 "testing" 8 "time" 9 10 "github.com/ethereum/go-ethereum/p2p/enr" 11 "github.com/libp2p/go-libp2p-core/network" 12 "github.com/libp2p/go-libp2p-core/protocol" 13 gcache "github.com/patrickmn/go-cache" 14 types "github.com/prysmaticlabs/eth2-types" 15 mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" 16 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 17 dbtest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" 18 "github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers" 19 p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" 20 p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types" 21 "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" 22 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 23 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 24 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper" 25 "github.com/prysmaticlabs/prysm/shared/copyutil" 26 "github.com/prysmaticlabs/prysm/shared/params" 27 "github.com/prysmaticlabs/prysm/shared/rand" 28 "github.com/prysmaticlabs/prysm/shared/testutil" 29 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 30 "github.com/prysmaticlabs/prysm/shared/testutil/require" 31 ) 32 33 // /- b1 - b2 34 // b0 35 // \- b3 36 // Test b1 was missing then received and we can process b0 -> b1 -> b2 37 func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks1(t *testing.T) { 38 db := dbtest.SetupDB(t) 39 40 p1 := p2ptest.NewTestP2P(t) 41 r := &Service{ 42 cfg: &Config{ 43 P2P: p1, 44 DB: db, 45 Chain: &mock.ChainService{ 46 FinalizedCheckPoint: ðpb.Checkpoint{ 47 Epoch: 0, 48 }, 49 }, 50 StateGen: stategen.New(db), 51 }, 52 slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), 53 seenPendingBlocks: make(map[[32]byte]bool), 54 } 55 err := r.initCaches() 56 require.NoError(t, err) 57 58 b0 := testutil.NewBeaconBlock() 59 require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b0))) 60 b0Root, err := b0.Block.HashTreeRoot() 61 require.NoError(t, err) 62 b3 := testutil.NewBeaconBlock() 63 b3.Block.Slot = 3 64 b3.Block.ParentRoot = b0Root[:] 65 require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b3))) 66 // Incomplete block link 67 b1 := testutil.NewBeaconBlock() 68 b1.Block.Slot = 1 69 b1.Block.ParentRoot = b0Root[:] 70 b1Root, err := b1.Block.HashTreeRoot() 71 require.NoError(t, err) 72 b2 := testutil.NewBeaconBlock() 73 b2.Block.Slot = 2 74 b2.Block.ParentRoot = b1Root[:] 75 b2Root, err := b1.Block.HashTreeRoot() 76 require.NoError(t, err) 77 78 // Add b2 to the cache 79 require.NoError(t, r.insertBlockToPendingQueue(b2.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b2), b2Root)) 80 81 require.NoError(t, r.processPendingBlocks(context.Background())) 82 assert.Equal(t, 1, len(r.slotToPendingBlocks.Items()), "Incorrect size for slot to pending blocks cache") 83 assert.Equal(t, 1, len(r.seenPendingBlocks), "Incorrect size for seen pending block") 84 85 // Add b1 to the cache 86 require.NoError(t, r.insertBlockToPendingQueue(b1.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b1), b1Root)) 87 require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b1))) 88 89 // Insert bad b1 in the cache to verify the good one doesn't get replaced. 90 require.NoError(t, r.insertBlockToPendingQueue(b1.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(testutil.NewBeaconBlock()), [32]byte{})) 91 92 require.NoError(t, r.processPendingBlocks(context.Background())) // Marks a block as bad 93 require.NoError(t, r.processPendingBlocks(context.Background())) // Bad block removed on second run 94 95 assert.Equal(t, 1, len(r.slotToPendingBlocks.Items()), "Incorrect size for slot to pending blocks cache") 96 assert.Equal(t, 2, len(r.seenPendingBlocks), "Incorrect size for seen pending block") 97 } 98 99 func TestRegularSync_InsertDuplicateBlocks(t *testing.T) { 100 db := dbtest.SetupDB(t) 101 102 p1 := p2ptest.NewTestP2P(t) 103 r := &Service{ 104 cfg: &Config{ 105 P2P: p1, 106 DB: db, 107 Chain: &mock.ChainService{ 108 FinalizedCheckPoint: ðpb.Checkpoint{ 109 Epoch: 0, 110 Root: make([]byte, 32), 111 }, 112 }, 113 }, 114 slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), 115 seenPendingBlocks: make(map[[32]byte]bool), 116 } 117 err := r.initCaches() 118 require.NoError(t, err) 119 120 b0 := testutil.NewBeaconBlock() 121 b0r := [32]byte{'a'} 122 require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b0))) 123 b0Root, err := b0.Block.HashTreeRoot() 124 require.NoError(t, err) 125 b1 := testutil.NewBeaconBlock() 126 b1.Block.Slot = 1 127 b1.Block.ParentRoot = b0Root[:] 128 b1r := [32]byte{'b'} 129 130 require.NoError(t, r.insertBlockToPendingQueue(b0.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b0), b0r)) 131 require.Equal(t, 1, len(r.pendingBlocksInCache(b0.Block.Slot)), "Block was not added to map") 132 133 require.NoError(t, r.insertBlockToPendingQueue(b1.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b1), b1r)) 134 require.Equal(t, 1, len(r.pendingBlocksInCache(b1.Block.Slot)), "Block was not added to map") 135 136 // Add duplicate block which should not be saved. 137 require.NoError(t, r.insertBlockToPendingQueue(b0.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b0), b0r)) 138 require.Equal(t, 1, len(r.pendingBlocksInCache(b0.Block.Slot)), "Block was added to map") 139 140 // Add duplicate block which should not be saved. 141 require.NoError(t, r.insertBlockToPendingQueue(b1.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b1), b1r)) 142 require.Equal(t, 1, len(r.pendingBlocksInCache(b1.Block.Slot)), "Block was added to map") 143 144 } 145 146 // /- b1 - b2 - b5 147 // b0 148 // \- b3 - b4 149 // Test b2 and b3 were missed, after receiving them we can process 2 chains. 150 func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks_2Chains(t *testing.T) { 151 db := dbtest.SetupDB(t) 152 p1 := p2ptest.NewTestP2P(t) 153 p2 := p2ptest.NewTestP2P(t) 154 p1.Connect(p2) 155 assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected") 156 pcl := protocol.ID("/eth2/beacon_chain/req/hello/1/ssz_snappy") 157 var wg sync.WaitGroup 158 wg.Add(1) 159 p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) { 160 defer wg.Done() 161 code, errMsg, err := ReadStatusCode(stream, p1.Encoding()) 162 assert.NoError(t, err) 163 if code == 0 { 164 t.Error("Expected a non-zero code") 165 } 166 if errMsg != p2ptypes.ErrWrongForkDigestVersion.Error() { 167 t.Logf("Received error string len %d, wanted error string len %d", len(errMsg), len(p2ptypes.ErrWrongForkDigestVersion.Error())) 168 t.Errorf("Received unexpected message response in the stream: %s. Wanted %s.", errMsg, p2ptypes.ErrWrongForkDigestVersion.Error()) 169 } 170 }) 171 172 r := &Service{ 173 cfg: &Config{ 174 P2P: p1, 175 DB: db, 176 Chain: &mock.ChainService{ 177 FinalizedCheckPoint: ðpb.Checkpoint{ 178 Epoch: 0, 179 Root: make([]byte, 32), 180 }, 181 }, 182 StateGen: stategen.New(db), 183 }, 184 slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), 185 seenPendingBlocks: make(map[[32]byte]bool), 186 } 187 err := r.initCaches() 188 require.NoError(t, err) 189 p1.Peers().Add(new(enr.Record), p2.PeerID(), nil, network.DirOutbound) 190 p1.Peers().SetConnectionState(p2.PeerID(), peers.PeerConnected) 191 p1.Peers().SetChainState(p2.PeerID(), &pb.Status{}) 192 193 b0 := testutil.NewBeaconBlock() 194 require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b0))) 195 b0Root, err := b0.Block.HashTreeRoot() 196 require.NoError(t, err) 197 b1 := testutil.NewBeaconBlock() 198 b1.Block.Slot = 1 199 b1.Block.ParentRoot = b0Root[:] 200 require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b1))) 201 b1Root, err := b1.Block.HashTreeRoot() 202 require.NoError(t, err) 203 204 // Incomplete block links 205 b2 := testutil.NewBeaconBlock() 206 b2.Block.Slot = 2 207 b2.Block.ParentRoot = b1Root[:] 208 b2Root, err := b2.Block.HashTreeRoot() 209 require.NoError(t, err) 210 b5 := testutil.NewBeaconBlock() 211 b5.Block.Slot = 5 212 b5.Block.ParentRoot = b2Root[:] 213 b5Root, err := b5.Block.HashTreeRoot() 214 require.NoError(t, err) 215 b3 := testutil.NewBeaconBlock() 216 b3.Block.Slot = 3 217 b3.Block.ParentRoot = b0Root[:] 218 b3Root, err := b3.Block.HashTreeRoot() 219 require.NoError(t, err) 220 b4 := testutil.NewBeaconBlock() 221 b4.Block.Slot = 4 222 b4.Block.ParentRoot = b3Root[:] 223 b4Root, err := b4.Block.HashTreeRoot() 224 require.NoError(t, err) 225 226 require.NoError(t, r.insertBlockToPendingQueue(b4.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b4), b4Root)) 227 require.NoError(t, r.insertBlockToPendingQueue(b5.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b5), b5Root)) 228 229 require.NoError(t, r.processPendingBlocks(context.Background())) // Marks a block as bad 230 require.NoError(t, r.processPendingBlocks(context.Background())) // Bad block removed on second run 231 232 assert.Equal(t, 2, len(r.slotToPendingBlocks.Items()), "Incorrect size for slot to pending blocks cache") 233 assert.Equal(t, 2, len(r.seenPendingBlocks), "Incorrect size for seen pending block") 234 235 // Add b3 to the cache 236 require.NoError(t, r.insertBlockToPendingQueue(b3.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b3), b3Root)) 237 require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b3))) 238 239 require.NoError(t, r.processPendingBlocks(context.Background())) // Marks a block as bad 240 require.NoError(t, r.processPendingBlocks(context.Background())) // Bad block removed on second run 241 242 assert.Equal(t, 1, len(r.slotToPendingBlocks.Items()), "Incorrect size for slot to pending blocks cache") 243 assert.Equal(t, 3, len(r.seenPendingBlocks), "Incorrect size for seen pending block") 244 245 // Add b2 to the cache 246 require.NoError(t, r.insertBlockToPendingQueue(b2.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b2), b2Root)) 247 248 require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b2))) 249 250 require.NoError(t, r.processPendingBlocks(context.Background())) // Marks a block as bad 251 require.NoError(t, r.processPendingBlocks(context.Background())) // Bad block removed on second run 252 253 assert.Equal(t, 0, len(r.slotToPendingBlocks.Items()), "Incorrect size for slot to pending blocks cache") 254 assert.Equal(t, 4, len(r.seenPendingBlocks), "Incorrect size for seen pending block") 255 } 256 257 func TestRegularSyncBeaconBlockSubscriber_PruneOldPendingBlocks(t *testing.T) { 258 db := dbtest.SetupDB(t) 259 p1 := p2ptest.NewTestP2P(t) 260 p2 := p2ptest.NewTestP2P(t) 261 p1.Connect(p2) 262 assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected") 263 264 r := &Service{ 265 cfg: &Config{ 266 P2P: p1, 267 DB: db, 268 Chain: &mock.ChainService{ 269 FinalizedCheckPoint: ðpb.Checkpoint{ 270 Epoch: 1, 271 Root: make([]byte, 32), 272 }, 273 }, 274 }, 275 slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), 276 seenPendingBlocks: make(map[[32]byte]bool), 277 } 278 err := r.initCaches() 279 require.NoError(t, err) 280 p1.Peers().Add(new(enr.Record), p1.PeerID(), nil, network.DirOutbound) 281 p1.Peers().SetConnectionState(p1.PeerID(), peers.PeerConnected) 282 p1.Peers().SetChainState(p1.PeerID(), &pb.Status{}) 283 284 b0 := testutil.NewBeaconBlock() 285 require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b0))) 286 b0Root, err := b0.Block.HashTreeRoot() 287 require.NoError(t, err) 288 b1 := testutil.NewBeaconBlock() 289 b1.Block.Slot = 1 290 b1.Block.ParentRoot = b0Root[:] 291 require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b1))) 292 b1Root, err := b1.Block.HashTreeRoot() 293 require.NoError(t, err) 294 295 // Incomplete block links 296 b2 := testutil.NewBeaconBlock() 297 b2.Block.Slot = 2 298 b2.Block.ParentRoot = b1Root[:] 299 b2Root, err := b2.Block.HashTreeRoot() 300 require.NoError(t, err) 301 b5 := testutil.NewBeaconBlock() 302 b5.Block.Slot = 5 303 b5.Block.ParentRoot = b2Root[:] 304 b5Root, err := b5.Block.HashTreeRoot() 305 require.NoError(t, err) 306 b3 := testutil.NewBeaconBlock() 307 b3.Block.Slot = 3 308 b3.Block.ParentRoot = b0Root[:] 309 b3Root, err := b3.Block.HashTreeRoot() 310 require.NoError(t, err) 311 b4 := testutil.NewBeaconBlock() 312 b4.Block.Slot = 4 313 b4.Block.ParentRoot = b3Root[:] 314 b4Root, err := b4.Block.HashTreeRoot() 315 require.NoError(t, err) 316 317 require.NoError(t, r.insertBlockToPendingQueue(b2.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b2), b2Root)) 318 require.NoError(t, r.insertBlockToPendingQueue(b3.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b3), b3Root)) 319 require.NoError(t, r.insertBlockToPendingQueue(b4.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b4), b4Root)) 320 require.NoError(t, r.insertBlockToPendingQueue(b5.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b5), b5Root)) 321 322 require.NoError(t, r.processPendingBlocks(context.Background())) 323 assert.Equal(t, 0, len(r.slotToPendingBlocks.Items()), "Incorrect size for slot to pending blocks cache") 324 assert.Equal(t, 4, len(r.seenPendingBlocks), "Incorrect size for seen pending block") 325 } 326 327 func TestService_sortedPendingSlots(t *testing.T) { 328 r := &Service{ 329 slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), 330 seenPendingBlocks: make(map[[32]byte]bool), 331 } 332 333 var lastSlot types.Slot = math.MaxUint64 334 require.NoError(t, r.insertBlockToPendingQueue(lastSlot, wrapper.WrappedPhase0SignedBeaconBlock(testutil.HydrateSignedBeaconBlock(ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: lastSlot}})), [32]byte{1})) 335 require.NoError(t, r.insertBlockToPendingQueue(lastSlot-3, wrapper.WrappedPhase0SignedBeaconBlock(testutil.HydrateSignedBeaconBlock(ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: lastSlot - 3}})), [32]byte{2})) 336 require.NoError(t, r.insertBlockToPendingQueue(lastSlot-5, wrapper.WrappedPhase0SignedBeaconBlock(testutil.HydrateSignedBeaconBlock(ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: lastSlot - 5}})), [32]byte{3})) 337 require.NoError(t, r.insertBlockToPendingQueue(lastSlot-2, wrapper.WrappedPhase0SignedBeaconBlock(testutil.HydrateSignedBeaconBlock(ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: lastSlot - 2}})), [32]byte{4})) 338 339 want := []types.Slot{lastSlot - 5, lastSlot - 3, lastSlot - 2, lastSlot} 340 assert.DeepEqual(t, want, r.sortedPendingSlots(), "Unexpected pending slots list") 341 } 342 343 func TestService_BatchRootRequest(t *testing.T) { 344 db := dbtest.SetupDB(t) 345 p1 := p2ptest.NewTestP2P(t) 346 p2 := p2ptest.NewTestP2P(t) 347 p1.Connect(p2) 348 assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected") 349 350 r := &Service{ 351 cfg: &Config{ 352 P2P: p1, 353 DB: db, 354 Chain: &mock.ChainService{ 355 FinalizedCheckPoint: ðpb.Checkpoint{ 356 Epoch: 1, 357 Root: make([]byte, 32), 358 }, 359 }, 360 }, 361 slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), 362 seenPendingBlocks: make(map[[32]byte]bool), 363 } 364 365 err := r.initCaches() 366 require.NoError(t, err) 367 p1.Peers().Add(new(enr.Record), p2.PeerID(), nil, network.DirOutbound) 368 p1.Peers().SetConnectionState(p2.PeerID(), peers.PeerConnected) 369 p1.Peers().SetChainState(p2.PeerID(), &pb.Status{FinalizedEpoch: 2}) 370 371 b0 := testutil.NewBeaconBlock() 372 require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b0))) 373 b0Root, err := b0.Block.HashTreeRoot() 374 require.NoError(t, err) 375 b1 := testutil.NewBeaconBlock() 376 b1.Block.Slot = 1 377 b1.Block.ParentRoot = b0Root[:] 378 require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b1))) 379 b1Root, err := b1.Block.HashTreeRoot() 380 require.NoError(t, err) 381 382 b2 := testutil.NewBeaconBlock() 383 b2.Block.Slot = 2 384 b2.Block.ParentRoot = b1Root[:] 385 b2Root, err := b2.Block.HashTreeRoot() 386 require.NoError(t, err) 387 b5 := testutil.NewBeaconBlock() 388 b5.Block.Slot = 5 389 b5.Block.ParentRoot = b2Root[:] 390 b5Root, err := b5.Block.HashTreeRoot() 391 require.NoError(t, err) 392 b3 := testutil.NewBeaconBlock() 393 b3.Block.Slot = 3 394 b3.Block.ParentRoot = b0Root[:] 395 b3Root, err := b3.Block.HashTreeRoot() 396 require.NoError(t, err) 397 b4 := testutil.NewBeaconBlock() 398 b4.Block.Slot = 4 399 b4.Block.ParentRoot = b3Root[:] 400 b4Root, err := b4.Block.HashTreeRoot() 401 require.NoError(t, err) 402 403 // Send in duplicated roots to also test deduplicaton. 404 sentRoots := p2ptypes.BeaconBlockByRootsReq{b2Root, b2Root, b3Root, b3Root, b4Root, b5Root} 405 expectedRoots := p2ptypes.BeaconBlockByRootsReq{b2Root, b3Root, b4Root, b5Root} 406 407 pcl := protocol.ID("/eth2/beacon_chain/req/beacon_blocks_by_root/1/ssz_snappy") 408 var wg sync.WaitGroup 409 wg.Add(1) 410 p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) { 411 defer wg.Done() 412 var out p2ptypes.BeaconBlockByRootsReq 413 assert.NoError(t, p2.Encoding().DecodeWithMaxLength(stream, &out)) 414 assert.DeepEqual(t, expectedRoots, out, "Did not receive expected message") 415 response := []*ethpb.SignedBeaconBlock{b2, b3, b4, b5} 416 for _, blk := range response { 417 _, err := stream.Write([]byte{responseCodeSuccess}) 418 assert.NoError(t, err, "Could not write to stream") 419 _, err = p2.Encoding().EncodeWithMaxLength(stream, blk) 420 assert.NoError(t, err, "Could not send response back") 421 } 422 assert.NoError(t, stream.Close()) 423 }) 424 425 require.NoError(t, r.sendBatchRootRequest(context.Background(), sentRoots, rand.NewGenerator())) 426 427 if testutil.WaitTimeout(&wg, 1*time.Second) { 428 t.Fatal("Did not receive stream within 1 sec") 429 } 430 assert.Equal(t, 4, len(r.slotToPendingBlocks.Items()), "Incorrect size for slot to pending blocks cache") 431 assert.Equal(t, 4, len(r.seenPendingBlocks), "Incorrect size for seen pending block") 432 } 433 434 func TestService_AddPeningBlockToQueueOverMax(t *testing.T) { 435 r := &Service{ 436 slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), 437 seenPendingBlocks: make(map[[32]byte]bool), 438 } 439 440 b := testutil.NewBeaconBlock() 441 b1 := copyutil.CopySignedBeaconBlock(b) 442 b1.Block.StateRoot = []byte{'a'} 443 b2 := copyutil.CopySignedBeaconBlock(b) 444 b2.Block.StateRoot = []byte{'b'} 445 require.NoError(t, r.insertBlockToPendingQueue(0, wrapper.WrappedPhase0SignedBeaconBlock(b), [32]byte{})) 446 require.NoError(t, r.insertBlockToPendingQueue(0, wrapper.WrappedPhase0SignedBeaconBlock(b1), [32]byte{1})) 447 require.NoError(t, r.insertBlockToPendingQueue(0, wrapper.WrappedPhase0SignedBeaconBlock(b2), [32]byte{2})) 448 449 b3 := copyutil.CopySignedBeaconBlock(b) 450 b3.Block.StateRoot = []byte{'c'} 451 require.NoError(t, r.insertBlockToPendingQueue(0, wrapper.WrappedPhase0SignedBeaconBlock(b2), [32]byte{3})) 452 require.Equal(t, maxBlocksPerSlot, len(r.pendingBlocksInCache(0))) 453 } 454 455 func TestService_ProcessPendingBlockOnCorrectSlot(t *testing.T) { 456 ctx := context.Background() 457 db := dbtest.SetupDB(t) 458 459 p1 := p2ptest.NewTestP2P(t) 460 mockChain := mock.ChainService{Genesis: time.Unix(time.Now().Unix()-int64(params.BeaconConfig().SecondsPerSlot), 0), 461 FinalizedCheckPoint: ðpb.Checkpoint{ 462 Epoch: 0, 463 }} 464 r := &Service{ 465 cfg: &Config{ 466 P2P: p1, 467 DB: db, 468 Chain: &mockChain, 469 StateGen: stategen.New(db), 470 }, 471 slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), 472 seenPendingBlocks: make(map[[32]byte]bool), 473 } 474 err := r.initCaches() 475 require.NoError(t, err) 476 477 beaconState, privKeys := testutil.DeterministicGenesisState(t, 100) 478 parentBlock := testutil.NewBeaconBlock() 479 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(parentBlock))) 480 bRoot, err := parentBlock.Block.HashTreeRoot() 481 require.NoError(t, err) 482 require.NoError(t, db.SaveState(ctx, beaconState, bRoot)) 483 require.NoError(t, db.SaveStateSummary(ctx, &pb.StateSummary{Root: bRoot[:]})) 484 copied := beaconState.Copy() 485 require.NoError(t, copied.SetSlot(1)) 486 proposerIdx, err := helpers.BeaconProposerIndex(copied) 487 require.NoError(t, err) 488 489 st, err := testutil.NewBeaconState() 490 require.NoError(t, err) 491 mockChain.Root = bRoot[:] 492 mockChain.State = st 493 494 b1 := testutil.NewBeaconBlock() 495 b1.Block.ParentRoot = bRoot[:] 496 b1.Block.Slot = 1 497 b1Root, err := b1.Block.HashTreeRoot() 498 require.NoError(t, err) 499 b1.Block.ProposerIndex = proposerIdx 500 b1.Signature, err = helpers.ComputeDomainAndSign(beaconState, 0, b1.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx]) 501 require.NoError(t, err) 502 503 b2 := testutil.NewBeaconBlock() 504 b2.Block.Slot = 2 505 b2.Block.ParentRoot = bRoot[:] 506 b2Root, err := b2.Block.HashTreeRoot() 507 require.NoError(t, err) 508 509 b3 := testutil.NewBeaconBlock() 510 b3.Block.Slot = 3 511 b3.Block.ParentRoot = b2Root[:] 512 b3Root, err := b3.Block.HashTreeRoot() 513 require.NoError(t, err) 514 515 // Add block1 for slot1 516 require.NoError(t, r.insertBlockToPendingQueue(b1.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b1), b1Root)) 517 // Add block2 for slot2 518 require.NoError(t, r.insertBlockToPendingQueue(b2.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b2), b2Root)) 519 // Add block3 for slot3 520 require.NoError(t, r.insertBlockToPendingQueue(b3.Block.Slot, wrapper.WrappedPhase0SignedBeaconBlock(b3), b3Root)) 521 522 // processPendingBlocks should process only blocks of the current slot. i.e. slot 1. 523 // Then check if the other two blocks are still in the pendingQueue. 524 require.NoError(t, r.processPendingBlocks(context.Background())) 525 assert.Equal(t, 2, len(r.slotToPendingBlocks.Items()), "Incorrect size for slot to pending blocks cache") 526 } 527 528 func TestService_ProcessBadPendingBlocks(t *testing.T) { 529 ctx := context.Background() 530 db := dbtest.SetupDB(t) 531 532 p1 := p2ptest.NewTestP2P(t) 533 mockChain := mock.ChainService{Genesis: time.Unix(time.Now().Unix()-int64(params.BeaconConfig().SecondsPerSlot), 0), 534 FinalizedCheckPoint: ðpb.Checkpoint{ 535 Epoch: 0, 536 }} 537 r := &Service{ 538 cfg: &Config{ 539 P2P: p1, 540 DB: db, 541 Chain: &mockChain, 542 StateGen: stategen.New(db), 543 }, 544 slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), 545 seenPendingBlocks: make(map[[32]byte]bool), 546 } 547 err := r.initCaches() 548 require.NoError(t, err) 549 550 beaconState, privKeys := testutil.DeterministicGenesisState(t, 100) 551 parentBlock := testutil.NewBeaconBlock() 552 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(parentBlock))) 553 bRoot, err := parentBlock.Block.HashTreeRoot() 554 require.NoError(t, err) 555 require.NoError(t, db.SaveState(ctx, beaconState, bRoot)) 556 require.NoError(t, db.SaveStateSummary(ctx, &pb.StateSummary{Root: bRoot[:]})) 557 copied := beaconState.Copy() 558 require.NoError(t, copied.SetSlot(1)) 559 proposerIdx, err := helpers.BeaconProposerIndex(copied) 560 require.NoError(t, err) 561 562 st, err := testutil.NewBeaconState() 563 require.NoError(t, err) 564 mockChain.Root = bRoot[:] 565 mockChain.State = st 566 567 b1 := testutil.NewBeaconBlock() 568 b1.Block.ParentRoot = bRoot[:] 569 b1.Block.Slot = 1 570 b1Root, err := b1.Block.HashTreeRoot() 571 require.NoError(t, err) 572 b1.Block.ProposerIndex = proposerIdx 573 b1.Signature, err = helpers.ComputeDomainAndSign(beaconState, 0, b1.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx]) 574 require.NoError(t, err) 575 576 b := testutil.NewBeaconBlock() 577 b.Block.Slot = 55 578 b.Block.ParentRoot = []byte{'A', 'B', 'C'} 579 bA := wrapper.WrappedPhase0SignedBeaconBlock(b) 580 assert.NoError(t, err) 581 582 // Add block1 for slot 55 583 require.NoError(t, r.insertBlockToPendingQueue(b.Block.Slot, bA, b1Root)) 584 bB := wrapper.WrappedPhase0SignedBeaconBlock(testutil.NewBeaconBlock()) 585 assert.NoError(t, err) 586 // remove with a different block from the same slot. 587 require.NoError(t, r.deleteBlockFromPendingQueue(b.Block.Slot, bB, b1Root)) 588 }