From 7d669f23ab8071ac7da7ac0a090f91094377dd29 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Mon, 4 Apr 2022 18:46:05 -0700 Subject: [PATCH] Sync: process pending block with optimistic parent (#10480) --- beacon-chain/sync/pending_blocks_queue.go | 8 +- .../sync/pending_blocks_queue_test.go | 78 +++++++++++++++++++ 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/beacon-chain/sync/pending_blocks_queue.go b/beacon-chain/sync/pending_blocks_queue.go index 9dc4c64899..4f8641e7d9 100644 --- a/beacon-chain/sync/pending_blocks_queue.go +++ b/beacon-chain/sync/pending_blocks_queue.go @@ -152,14 +152,16 @@ func (s *Service) processPendingBlocks(ctx context.Context) error { continue } - if err := s.validateBeaconBlock(ctx, b, blkRoot); err != nil { + err = s.validateBeaconBlock(ctx, b, blkRoot) + switch { + case errors.Is(ErrOptimisticParent, err): // Ok to continue process block with parent that is an optimistic candidate. + case err != nil: log.Debugf("Could not validate block from slot %d: %v", b.Block().Slot(), err) s.setBadBlock(ctx, blkRoot) tracing.AnnotateError(span, err) - // In the next iteration of the queue, this block will be removed from - // the pending queue as it has been marked as a 'bad' block. span.End() continue + default: } if err := s.cfg.chain.ReceiveBlock(ctx, b, blkRoot); err != nil { diff --git a/beacon-chain/sync/pending_blocks_queue_test.go b/beacon-chain/sync/pending_blocks_queue_test.go index 0034b7165a..52ba8fff42 100644 --- a/beacon-chain/sync/pending_blocks_queue_test.go +++ b/beacon-chain/sync/pending_blocks_queue_test.go @@ -111,6 +111,84 @@ func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks1(t *testing.T) { assert.Equal(t, 2, len(r.seenPendingBlocks), "Incorrect size for seen pending block") } +func TestRegularSyncBeaconBlockSubscriber_OptimisticStatus(t *testing.T) { + db := dbtest.SetupDB(t) + + p1 := p2ptest.NewTestP2P(t) + r := &Service{ + cfg: &config{ + p2p: p1, + beaconDB: db, + chain: &mock.ChainService{ + Optimistic: true, + FinalizedCheckPoint: ðpb.Checkpoint{ + Epoch: 0, + }, + }, + stateGen: stategen.New(db), + }, + slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), + seenPendingBlocks: make(map[[32]byte]bool), + } + r.initCaches() + + b0 := util.NewBeaconBlock() + wsb, err := wrapper.WrappedSignedBeaconBlock(b0) + require.NoError(t, err) + require.NoError(t, r.cfg.beaconDB.SaveBlock(context.Background(), wsb)) + b0Root, err := b0.Block.HashTreeRoot() + require.NoError(t, err) + b3 := util.NewBeaconBlock() + b3.Block.Slot = 3 + b3.Block.ParentRoot = b0Root[:] + wsb, err = wrapper.WrappedSignedBeaconBlock(b3) + require.NoError(t, err) + require.NoError(t, r.cfg.beaconDB.SaveBlock(context.Background(), wsb)) + // Incomplete block link + b1 := util.NewBeaconBlock() + b1.Block.Slot = 1 + b1.Block.ParentRoot = b0Root[:] + b1Root, err := b1.Block.HashTreeRoot() + require.NoError(t, err) + b2 := util.NewBeaconBlock() + b2.Block.Slot = 2 + b2.Block.ParentRoot = b1Root[:] + b2Root, err := b1.Block.HashTreeRoot() + require.NoError(t, err) + + // Add b2 to the cache + wsb, err = wrapper.WrappedSignedBeaconBlock(b2) + require.NoError(t, err) + require.NoError(t, r.insertBlockToPendingQueue(b2.Block.Slot, wsb, b2Root)) + + require.NoError(t, r.processPendingBlocks(context.Background())) + assert.Equal(t, 1, len(r.slotToPendingBlocks.Items()), "Incorrect size for slot to pending blocks cache") + assert.Equal(t, 1, len(r.seenPendingBlocks), "Incorrect size for seen pending block") + + // Add b1 to the cache + wsb, err = wrapper.WrappedSignedBeaconBlock(b1) + require.NoError(t, err) + require.NoError(t, r.insertBlockToPendingQueue(b1.Block.Slot, wsb, b1Root)) + wsb, err = wrapper.WrappedSignedBeaconBlock(b1) + require.NoError(t, err) + require.NoError(t, r.cfg.beaconDB.SaveBlock(context.Background(), wsb)) + + nBlock := util.NewBeaconBlock() + nBlock.Block.Slot = b1.Block.Slot + nRoot, err := nBlock.Block.HashTreeRoot() + require.NoError(t, err) + + // Insert bad b1 in the cache to verify the good one doesn't get replaced. + wsb, err = wrapper.WrappedSignedBeaconBlock(nBlock) + require.NoError(t, err) + require.NoError(t, r.insertBlockToPendingQueue(nBlock.Block.Slot, wsb, nRoot)) + require.NoError(t, r.processPendingBlocks(context.Background())) // Marks a block as bad + require.NoError(t, r.processPendingBlocks(context.Background())) // Bad block removed on second run + + assert.Equal(t, 1, len(r.slotToPendingBlocks.Items()), "Incorrect size for slot to pending blocks cache") + assert.Equal(t, 2, len(r.seenPendingBlocks), "Incorrect size for seen pending block") +} + func TestRegularSyncBeaconBlockSubscriber_ExecutionEngineTimesOut(t *testing.T) { db := dbtest.SetupDB(t)