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

     1  package blockchain
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"reflect"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/ethereum/go-ethereum/common"
    11  	"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
    12  	b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
    13  	"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
    14  	statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
    15  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    16  	"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
    17  	"github.com/prysmaticlabs/prysm/beacon-chain/db"
    18  	testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
    19  	"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
    20  	"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
    21  	"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
    22  	"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
    23  	"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
    24  	"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
    25  	"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
    26  	protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
    27  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    28  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    29  	"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
    30  	"github.com/prysmaticlabs/prysm/proto/interfaces"
    31  	"github.com/prysmaticlabs/prysm/shared/bytesutil"
    32  	"github.com/prysmaticlabs/prysm/shared/event"
    33  	"github.com/prysmaticlabs/prysm/shared/params"
    34  	"github.com/prysmaticlabs/prysm/shared/testutil"
    35  	"github.com/prysmaticlabs/prysm/shared/testutil/assert"
    36  	"github.com/prysmaticlabs/prysm/shared/testutil/require"
    37  	logTest "github.com/sirupsen/logrus/hooks/test"
    38  	"google.golang.org/protobuf/proto"
    39  )
    40  
    41  type mockBeaconNode struct {
    42  	stateFeed *event.Feed
    43  }
    44  
    45  // StateFeed mocks the same method in the beacon node.
    46  func (mbn *mockBeaconNode) StateFeed() *event.Feed {
    47  	if mbn.stateFeed == nil {
    48  		mbn.stateFeed = new(event.Feed)
    49  	}
    50  	return mbn.stateFeed
    51  }
    52  
    53  type mockBroadcaster struct {
    54  	broadcastCalled bool
    55  }
    56  
    57  func (mb *mockBroadcaster) Broadcast(_ context.Context, _ proto.Message) error {
    58  	mb.broadcastCalled = true
    59  	return nil
    60  }
    61  
    62  func (mb *mockBroadcaster) BroadcastAttestation(_ context.Context, _ uint64, _ *ethpb.Attestation) error {
    63  	mb.broadcastCalled = true
    64  	return nil
    65  }
    66  
    67  var _ p2p.Broadcaster = (*mockBroadcaster)(nil)
    68  
    69  func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
    70  	endpoint := "http://127.0.0.1"
    71  	ctx := context.Background()
    72  	var web3Service *powchain.Service
    73  	var err error
    74  	bState, _ := testutil.DeterministicGenesisState(t, 10)
    75  	pbState, err := v1.ProtobufBeaconState(bState.InnerStateUnsafe())
    76  	require.NoError(t, err)
    77  	err = beaconDB.SavePowchainData(ctx, &protodb.ETH1ChainData{
    78  		BeaconState: pbState,
    79  		Trie:        &protodb.SparseMerkleTrie{},
    80  		CurrentEth1Data: &protodb.LatestETH1Data{
    81  			BlockHash: make([]byte, 32),
    82  		},
    83  		ChainstartData: &protodb.ChainStartData{
    84  			Eth1Data: &ethpb.Eth1Data{
    85  				DepositRoot:  make([]byte, 32),
    86  				DepositCount: 0,
    87  				BlockHash:    make([]byte, 32),
    88  			},
    89  		},
    90  		DepositContainers: []*protodb.DepositContainer{},
    91  	})
    92  	require.NoError(t, err)
    93  	web3Service, err = powchain.NewService(ctx, &powchain.Web3ServiceConfig{
    94  		BeaconDB:        beaconDB,
    95  		HttpEndpoints:   []string{endpoint},
    96  		DepositContract: common.Address{},
    97  	})
    98  	require.NoError(t, err, "Unable to set up web3 service")
    99  
   100  	attService, err := attestations.NewService(ctx, &attestations.Config{Pool: attestations.NewPool()})
   101  	require.NoError(t, err)
   102  
   103  	depositCache, err := depositcache.New()
   104  	require.NoError(t, err)
   105  
   106  	cfg := &Config{
   107  		BeaconBlockBuf:    0,
   108  		BeaconDB:          beaconDB,
   109  		DepositCache:      depositCache,
   110  		ChainStartFetcher: web3Service,
   111  		P2p:               &mockBroadcaster{},
   112  		StateNotifier:     &mockBeaconNode{},
   113  		AttPool:           attestations.NewPool(),
   114  		StateGen:          stategen.New(beaconDB),
   115  		ForkChoiceStore:   protoarray.New(0, 0, params.BeaconConfig().ZeroHash),
   116  		AttService:        attService,
   117  	}
   118  
   119  	// Safe a state in stategen to purposes of testing a service stop / shutdown.
   120  	require.NoError(t, cfg.StateGen.SaveState(ctx, bytesutil.ToBytes32(bState.FinalizedCheckpoint().Root), bState))
   121  
   122  	chainService, err := NewService(ctx, cfg)
   123  	require.NoError(t, err, "Unable to setup chain service")
   124  	chainService.genesisTime = time.Unix(1, 0) // non-zero time
   125  
   126  	return chainService
   127  }
   128  
   129  func TestChainStartStop_Initialized(t *testing.T) {
   130  	hook := logTest.NewGlobal()
   131  	ctx := context.Background()
   132  	beaconDB := testDB.SetupDB(t)
   133  
   134  	chainService := setupBeaconChain(t, beaconDB)
   135  
   136  	genesisBlk := testutil.NewBeaconBlock()
   137  	blkRoot, err := genesisBlk.Block.HashTreeRoot()
   138  	require.NoError(t, err)
   139  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesisBlk)))
   140  	s, err := testutil.NewBeaconState()
   141  	require.NoError(t, err)
   142  	require.NoError(t, s.SetSlot(1))
   143  	require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
   144  	require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, blkRoot))
   145  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, blkRoot))
   146  	require.NoError(t, beaconDB.SaveJustifiedCheckpoint(ctx, &ethpb.Checkpoint{Root: blkRoot[:]}))
   147  	require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, &ethpb.Checkpoint{Root: blkRoot[:]}))
   148  
   149  	// Test the start function.
   150  	chainService.Start()
   151  
   152  	require.NoError(t, chainService.Stop(), "Unable to stop chain service")
   153  
   154  	// The context should have been canceled.
   155  	assert.Equal(t, context.Canceled, chainService.ctx.Err(), "Context was not canceled")
   156  	require.LogsContain(t, hook, "data already exists")
   157  }
   158  
   159  func TestChainStartStop_GenesisZeroHashes(t *testing.T) {
   160  	hook := logTest.NewGlobal()
   161  	ctx := context.Background()
   162  	beaconDB := testDB.SetupDB(t)
   163  
   164  	chainService := setupBeaconChain(t, beaconDB)
   165  
   166  	genesisBlk := testutil.NewBeaconBlock()
   167  	blkRoot, err := genesisBlk.Block.HashTreeRoot()
   168  	require.NoError(t, err)
   169  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesisBlk)))
   170  	s, err := testutil.NewBeaconState()
   171  	require.NoError(t, err)
   172  	require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
   173  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, blkRoot))
   174  	require.NoError(t, beaconDB.SaveJustifiedCheckpoint(ctx, &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}))
   175  
   176  	// Test the start function.
   177  	chainService.Start()
   178  
   179  	require.NoError(t, chainService.Stop(), "Unable to stop chain service")
   180  
   181  	// The context should have been canceled.
   182  	assert.Equal(t, context.Canceled, chainService.ctx.Err(), "Context was not canceled")
   183  	require.LogsContain(t, hook, "data already exists")
   184  }
   185  
   186  func TestChainService_InitializeBeaconChain(t *testing.T) {
   187  	helpers.ClearCache()
   188  	beaconDB := testDB.SetupDB(t)
   189  	ctx := context.Background()
   190  
   191  	bc := setupBeaconChain(t, beaconDB)
   192  	var err error
   193  
   194  	// Set up 10 deposits pre chain start for validators to register
   195  	count := uint64(10)
   196  	deposits, _, err := testutil.DeterministicDepositsAndKeys(count)
   197  	require.NoError(t, err)
   198  	trie, _, err := testutil.DepositTrieFromDeposits(deposits)
   199  	require.NoError(t, err)
   200  	hashTreeRoot := trie.HashTreeRoot()
   201  	genState, err := state.EmptyGenesisState()
   202  	require.NoError(t, err)
   203  	err = genState.SetEth1Data(&ethpb.Eth1Data{
   204  		DepositRoot:  hashTreeRoot[:],
   205  		DepositCount: uint64(len(deposits)),
   206  		BlockHash:    make([]byte, 32),
   207  	})
   208  	require.NoError(t, err)
   209  	genState, err = b.ProcessPreGenesisDeposits(ctx, genState, deposits)
   210  	require.NoError(t, err)
   211  
   212  	_, err = bc.initializeBeaconChain(ctx, time.Unix(0, 0), genState, &ethpb.Eth1Data{DepositRoot: hashTreeRoot[:], BlockHash: make([]byte, 32)})
   213  	require.NoError(t, err)
   214  
   215  	_, err = bc.HeadState(ctx)
   216  	assert.NoError(t, err)
   217  	headBlk, err := bc.HeadBlock(ctx)
   218  	require.NoError(t, err)
   219  	if headBlk == nil {
   220  		t.Error("Head state can't be nil after initialize beacon chain")
   221  	}
   222  	r, err := bc.HeadRoot(ctx)
   223  	require.NoError(t, err)
   224  	if bytesutil.ToBytes32(r) == params.BeaconConfig().ZeroHash {
   225  		t.Error("Canonical root for slot 0 can't be zeros after initialize beacon chain")
   226  	}
   227  }
   228  
   229  func TestChainService_CorrectGenesisRoots(t *testing.T) {
   230  	ctx := context.Background()
   231  	beaconDB := testDB.SetupDB(t)
   232  
   233  	chainService := setupBeaconChain(t, beaconDB)
   234  
   235  	genesisBlk := testutil.NewBeaconBlock()
   236  	blkRoot, err := genesisBlk.Block.HashTreeRoot()
   237  	require.NoError(t, err)
   238  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesisBlk)))
   239  	s, err := testutil.NewBeaconState()
   240  	require.NoError(t, err)
   241  	require.NoError(t, s.SetSlot(0))
   242  	require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
   243  	require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, blkRoot))
   244  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, blkRoot))
   245  	require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, &ethpb.Checkpoint{Root: blkRoot[:]}))
   246  
   247  	// Test the start function.
   248  	chainService.Start()
   249  
   250  	require.DeepEqual(t, blkRoot[:], chainService.finalizedCheckpt.Root, "Finalize Checkpoint root is incorrect")
   251  	require.DeepEqual(t, params.BeaconConfig().ZeroHash[:], chainService.justifiedCheckpt.Root, "Justified Checkpoint root is incorrect")
   252  
   253  	require.NoError(t, chainService.Stop(), "Unable to stop chain service")
   254  
   255  }
   256  
   257  func TestChainService_InitializeChainInfo(t *testing.T) {
   258  	beaconDB := testDB.SetupDB(t)
   259  	ctx := context.Background()
   260  
   261  	genesis := testutil.NewBeaconBlock()
   262  	genesisRoot, err := genesis.Block.HashTreeRoot()
   263  	require.NoError(t, err)
   264  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, genesisRoot))
   265  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis)))
   266  
   267  	finalizedSlot := params.BeaconConfig().SlotsPerEpoch*2 + 1
   268  	headBlock := testutil.NewBeaconBlock()
   269  	headBlock.Block.Slot = finalizedSlot
   270  	headBlock.Block.ParentRoot = bytesutil.PadTo(genesisRoot[:], 32)
   271  	headState, err := testutil.NewBeaconState()
   272  	require.NoError(t, err)
   273  	require.NoError(t, headState.SetSlot(finalizedSlot))
   274  	require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
   275  	headRoot, err := headBlock.Block.HashTreeRoot()
   276  	require.NoError(t, err)
   277  	require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot))
   278  	require.NoError(t, beaconDB.SaveState(ctx, headState, genesisRoot))
   279  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(headBlock)))
   280  	require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, &ethpb.Checkpoint{Epoch: helpers.SlotToEpoch(finalizedSlot), Root: headRoot[:]}))
   281  	c := &Service{cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)}}
   282  	require.NoError(t, c.initializeChainInfo(ctx))
   283  	headBlk, err := c.HeadBlock(ctx)
   284  	require.NoError(t, err)
   285  	assert.DeepEqual(t, headBlock, headBlk.Proto(), "Head block incorrect")
   286  	s, err := c.HeadState(ctx)
   287  	require.NoError(t, err)
   288  	assert.DeepSSZEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
   289  	assert.Equal(t, c.HeadSlot(), headBlock.Block.Slot, "Head slot incorrect")
   290  	r, err := c.HeadRoot(context.Background())
   291  	require.NoError(t, err)
   292  	if !bytes.Equal(headRoot[:], r) {
   293  		t.Error("head slot incorrect")
   294  	}
   295  	assert.Equal(t, genesisRoot, c.genesisRoot, "Genesis block root incorrect")
   296  }
   297  
   298  func TestChainService_InitializeChainInfo_SetHeadAtGenesis(t *testing.T) {
   299  	beaconDB := testDB.SetupDB(t)
   300  	ctx := context.Background()
   301  
   302  	genesis := testutil.NewBeaconBlock()
   303  	genesisRoot, err := genesis.Block.HashTreeRoot()
   304  	require.NoError(t, err)
   305  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, genesisRoot))
   306  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis)))
   307  
   308  	finalizedSlot := params.BeaconConfig().SlotsPerEpoch*2 + 1
   309  	headBlock := testutil.NewBeaconBlock()
   310  	headBlock.Block.Slot = finalizedSlot
   311  	headBlock.Block.ParentRoot = bytesutil.PadTo(genesisRoot[:], 32)
   312  	headState, err := testutil.NewBeaconState()
   313  	require.NoError(t, err)
   314  	require.NoError(t, headState.SetSlot(finalizedSlot))
   315  	require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
   316  	headRoot, err := headBlock.Block.HashTreeRoot()
   317  	require.NoError(t, err)
   318  	require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot))
   319  	require.NoError(t, beaconDB.SaveState(ctx, headState, genesisRoot))
   320  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(headBlock)))
   321  	c := &Service{cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)}}
   322  	require.NoError(t, c.initializeChainInfo(ctx))
   323  	s, err := c.HeadState(ctx)
   324  	require.NoError(t, err)
   325  	assert.DeepSSZEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
   326  	assert.Equal(t, genesisRoot, c.genesisRoot, "Genesis block root incorrect")
   327  	assert.DeepEqual(t, genesis, c.head.block.Proto())
   328  }
   329  
   330  func TestChainService_InitializeChainInfo_HeadSync(t *testing.T) {
   331  	resetFlags := flags.Get()
   332  	flags.Init(&flags.GlobalFlags{
   333  		HeadSync: true,
   334  	})
   335  	defer func() {
   336  		flags.Init(resetFlags)
   337  	}()
   338  
   339  	hook := logTest.NewGlobal()
   340  	finalizedSlot := params.BeaconConfig().SlotsPerEpoch*2 + 1
   341  	beaconDB := testDB.SetupDB(t)
   342  	ctx := context.Background()
   343  
   344  	genesisBlock := testutil.NewBeaconBlock()
   345  	genesisRoot, err := genesisBlock.Block.HashTreeRoot()
   346  	require.NoError(t, err)
   347  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, genesisRoot))
   348  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesisBlock)))
   349  
   350  	finalizedBlock := testutil.NewBeaconBlock()
   351  	finalizedBlock.Block.Slot = finalizedSlot
   352  	finalizedBlock.Block.ParentRoot = genesisRoot[:]
   353  	finalizedRoot, err := finalizedBlock.Block.HashTreeRoot()
   354  	require.NoError(t, err)
   355  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(finalizedBlock)))
   356  
   357  	// Set head slot close to the finalization point, no head sync is triggered.
   358  	headBlock := testutil.NewBeaconBlock()
   359  	headBlock.Block.Slot = finalizedSlot + params.BeaconConfig().SlotsPerEpoch*5
   360  	headBlock.Block.ParentRoot = finalizedRoot[:]
   361  	headRoot, err := headBlock.Block.HashTreeRoot()
   362  	require.NoError(t, err)
   363  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(headBlock)))
   364  
   365  	headState, err := testutil.NewBeaconState()
   366  	require.NoError(t, err)
   367  	require.NoError(t, headState.SetSlot(headBlock.Block.Slot))
   368  	require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
   369  	require.NoError(t, beaconDB.SaveState(ctx, headState, genesisRoot))
   370  	require.NoError(t, beaconDB.SaveState(ctx, headState, finalizedRoot))
   371  	require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot))
   372  	require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, headRoot))
   373  	require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, &ethpb.Checkpoint{
   374  		Epoch: helpers.SlotToEpoch(finalizedBlock.Block.Slot),
   375  		Root:  finalizedRoot[:],
   376  	}))
   377  
   378  	c := &Service{cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)}}
   379  
   380  	require.NoError(t, c.initializeChainInfo(ctx))
   381  	s, err := c.HeadState(ctx)
   382  	require.NoError(t, err)
   383  	assert.DeepSSZEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
   384  	assert.Equal(t, genesisRoot, c.genesisRoot, "Genesis block root incorrect")
   385  	// Since head sync is not triggered, chain is initialized to the last finalization checkpoint.
   386  	assert.DeepEqual(t, finalizedBlock, c.head.block.Proto())
   387  	assert.LogsContain(t, hook, "resetting head from the checkpoint ('--head-sync' flag is ignored)")
   388  	assert.LogsDoNotContain(t, hook, "Regenerating state from the last checkpoint at slot")
   389  
   390  	// Set head slot far beyond the finalization point, head sync should be triggered.
   391  	headBlock = testutil.NewBeaconBlock()
   392  	headBlock.Block.Slot = finalizedSlot + params.BeaconConfig().SlotsPerEpoch*headSyncMinEpochsAfterCheckpoint
   393  	headBlock.Block.ParentRoot = finalizedRoot[:]
   394  	headRoot, err = headBlock.Block.HashTreeRoot()
   395  	require.NoError(t, err)
   396  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(headBlock)))
   397  	require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot))
   398  	require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, headRoot))
   399  
   400  	hook.Reset()
   401  	require.NoError(t, c.initializeChainInfo(ctx))
   402  	s, err = c.HeadState(ctx)
   403  	require.NoError(t, err)
   404  	assert.DeepSSZEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
   405  	assert.Equal(t, genesisRoot, c.genesisRoot, "Genesis block root incorrect")
   406  	// Head slot is far beyond the latest finalized checkpoint, head sync is triggered.
   407  	assert.DeepEqual(t, headBlock, c.head.block.Proto())
   408  	assert.LogsContain(t, hook, "Regenerating state from the last checkpoint at slot 225")
   409  	assert.LogsDoNotContain(t, hook, "resetting head from the checkpoint ('--head-sync' flag is ignored)")
   410  }
   411  
   412  func TestChainService_SaveHeadNoDB(t *testing.T) {
   413  	beaconDB := testDB.SetupDB(t)
   414  	ctx := context.Background()
   415  	s := &Service{
   416  		cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
   417  	}
   418  	blk := testutil.NewBeaconBlock()
   419  	blk.Block.Slot = 1
   420  	r, err := blk.HashTreeRoot()
   421  	require.NoError(t, err)
   422  	newState, err := testutil.NewBeaconState()
   423  	require.NoError(t, err)
   424  	require.NoError(t, s.cfg.StateGen.SaveState(ctx, r, newState))
   425  	require.NoError(t, s.saveHeadNoDB(ctx, wrapper.WrappedPhase0SignedBeaconBlock(blk), r, newState))
   426  
   427  	newB, err := s.cfg.BeaconDB.HeadBlock(ctx)
   428  	require.NoError(t, err)
   429  	if reflect.DeepEqual(newB, blk) {
   430  		t.Error("head block should not be equal")
   431  	}
   432  }
   433  
   434  func TestHasBlock_ForkChoiceAndDB(t *testing.T) {
   435  	ctx := context.Background()
   436  	beaconDB := testDB.SetupDB(t)
   437  	s := &Service{
   438  		cfg:              &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB},
   439  		finalizedCheckpt: &ethpb.Checkpoint{Root: make([]byte, 32)},
   440  	}
   441  	block := testutil.NewBeaconBlock()
   442  	r, err := block.Block.HashTreeRoot()
   443  	require.NoError(t, err)
   444  	beaconState, err := testutil.NewBeaconState()
   445  	require.NoError(t, err)
   446  	require.NoError(t, s.insertBlockAndAttestationsToForkChoiceStore(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block).Block(), r, beaconState))
   447  
   448  	assert.Equal(t, false, s.hasBlock(ctx, [32]byte{}), "Should not have block")
   449  	assert.Equal(t, true, s.hasBlock(ctx, r), "Should have block")
   450  }
   451  
   452  func TestServiceStop_SaveCachedBlocks(t *testing.T) {
   453  	ctx, cancel := context.WithCancel(context.Background())
   454  	beaconDB := testDB.SetupDB(t)
   455  	s := &Service{
   456  		cfg:            &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
   457  		ctx:            ctx,
   458  		cancel:         cancel,
   459  		initSyncBlocks: make(map[[32]byte]interfaces.SignedBeaconBlock),
   460  	}
   461  	block := testutil.NewBeaconBlock()
   462  	r, err := block.Block.HashTreeRoot()
   463  	require.NoError(t, err)
   464  	s.saveInitSyncBlock(r, wrapper.WrappedPhase0SignedBeaconBlock(block))
   465  	require.NoError(t, s.Stop())
   466  	require.Equal(t, true, s.cfg.BeaconDB.HasBlock(ctx, r))
   467  }
   468  
   469  func TestProcessChainStartTime_ReceivedFeed(t *testing.T) {
   470  	beaconDB := testDB.SetupDB(t)
   471  	service := setupBeaconChain(t, beaconDB)
   472  	stateChannel := make(chan *feed.Event, 1)
   473  	stateSub := service.cfg.StateNotifier.StateFeed().Subscribe(stateChannel)
   474  	defer stateSub.Unsubscribe()
   475  	service.processChainStartTime(context.Background(), time.Now())
   476  
   477  	stateEvent := <-stateChannel
   478  	require.Equal(t, int(stateEvent.Type), statefeed.Initialized)
   479  	_, ok := stateEvent.Data.(*statefeed.InitializedData)
   480  	require.Equal(t, true, ok)
   481  }
   482  
   483  func BenchmarkHasBlockDB(b *testing.B) {
   484  	beaconDB := testDB.SetupDB(b)
   485  	ctx := context.Background()
   486  	s := &Service{
   487  		cfg: &Config{BeaconDB: beaconDB},
   488  	}
   489  	block := testutil.NewBeaconBlock()
   490  	require.NoError(b, s.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block)))
   491  	r, err := block.Block.HashTreeRoot()
   492  	require.NoError(b, err)
   493  
   494  	b.ResetTimer()
   495  	for i := 0; i < b.N; i++ {
   496  		require.Equal(b, true, s.cfg.BeaconDB.HasBlock(ctx, r), "Block is not in DB")
   497  	}
   498  }
   499  
   500  func BenchmarkHasBlockForkChoiceStore(b *testing.B) {
   501  	ctx := context.Background()
   502  	beaconDB := testDB.SetupDB(b)
   503  	s := &Service{
   504  		cfg:              &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB},
   505  		finalizedCheckpt: &ethpb.Checkpoint{Root: make([]byte, 32)},
   506  	}
   507  	block := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Body: &ethpb.BeaconBlockBody{}}}
   508  	r, err := block.Block.HashTreeRoot()
   509  	require.NoError(b, err)
   510  	bs := &pb.BeaconState{FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)}, CurrentJustifiedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)}}
   511  	beaconState, err := v1.InitializeFromProto(bs)
   512  	require.NoError(b, err)
   513  	require.NoError(b, s.insertBlockAndAttestationsToForkChoiceStore(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block).Block(), r, beaconState))
   514  
   515  	b.ResetTimer()
   516  	for i := 0; i < b.N; i++ {
   517  		require.Equal(b, true, s.cfg.ForkChoiceStore.HasNode(r), "Block is not in fork choice store")
   518  	}
   519  }