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

     1  package blockchain
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math/big"
     7  	"strconv"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/pkg/errors"
    12  	types "github.com/prysmaticlabs/eth2-types"
    13  	mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
    14  	"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
    15  	"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
    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  	iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
    21  	"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
    22  	"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
    23  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    24  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    25  	"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
    26  	"github.com/prysmaticlabs/prysm/proto/interfaces"
    27  	"github.com/prysmaticlabs/prysm/shared/attestationutil"
    28  	"github.com/prysmaticlabs/prysm/shared/bytesutil"
    29  	"github.com/prysmaticlabs/prysm/shared/featureconfig"
    30  	"github.com/prysmaticlabs/prysm/shared/params"
    31  	"github.com/prysmaticlabs/prysm/shared/testutil"
    32  	"github.com/prysmaticlabs/prysm/shared/testutil/assert"
    33  	"github.com/prysmaticlabs/prysm/shared/testutil/require"
    34  	"github.com/prysmaticlabs/prysm/shared/timeutils"
    35  )
    36  
    37  func TestStore_OnBlock(t *testing.T) {
    38  	ctx := context.Background()
    39  	beaconDB := testDB.SetupDB(t)
    40  
    41  	cfg := &Config{
    42  		BeaconDB:        beaconDB,
    43  		StateGen:        stategen.New(beaconDB),
    44  		ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
    45  	}
    46  	service, err := NewService(ctx, cfg)
    47  	require.NoError(t, err)
    48  	genesisStateRoot := [32]byte{}
    49  	genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
    50  	assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis)))
    51  	validGenesisRoot, err := genesis.Block.HashTreeRoot()
    52  	require.NoError(t, err)
    53  	st, err := testutil.NewBeaconState()
    54  	require.NoError(t, err)
    55  	require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
    56  	roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
    57  	require.NoError(t, err)
    58  	random := testutil.NewBeaconBlock()
    59  	random.Block.Slot = 1
    60  	random.Block.ParentRoot = validGenesisRoot[:]
    61  	assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(random)))
    62  	randomParentRoot, err := random.Block.HashTreeRoot()
    63  	assert.NoError(t, err)
    64  	require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot[:]}))
    65  	require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), randomParentRoot))
    66  	randomParentRoot2 := roots[1]
    67  	require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot2}))
    68  	require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), bytesutil.ToBytes32(randomParentRoot2)))
    69  
    70  	tests := []struct {
    71  		name          string
    72  		blk           *ethpb.SignedBeaconBlock
    73  		s             iface.BeaconState
    74  		time          uint64
    75  		wantErrString string
    76  	}{
    77  		{
    78  			name:          "parent block root does not have a state",
    79  			blk:           testutil.NewBeaconBlock(),
    80  			s:             st.Copy(),
    81  			wantErrString: "could not reconstruct parent state",
    82  		},
    83  		{
    84  			name: "block is from the future",
    85  			blk: func() *ethpb.SignedBeaconBlock {
    86  				b := testutil.NewBeaconBlock()
    87  				b.Block.ParentRoot = randomParentRoot2
    88  				b.Block.Slot = params.BeaconConfig().FarFutureSlot
    89  				return b
    90  			}(),
    91  			s:             st.Copy(),
    92  			wantErrString: "is in the far distant future",
    93  		},
    94  		{
    95  			name: "could not get finalized block",
    96  			blk: func() *ethpb.SignedBeaconBlock {
    97  				b := testutil.NewBeaconBlock()
    98  				b.Block.ParentRoot = randomParentRoot[:]
    99  				return b
   100  			}(),
   101  			s:             st.Copy(),
   102  			wantErrString: "is not a descendent of the current finalized block",
   103  		},
   104  		{
   105  			name: "same slot as finalized block",
   106  			blk: func() *ethpb.SignedBeaconBlock {
   107  				b := testutil.NewBeaconBlock()
   108  				b.Block.Slot = 0
   109  				b.Block.ParentRoot = randomParentRoot2
   110  				return b
   111  			}(),
   112  			s:             st.Copy(),
   113  			wantErrString: "block is equal or earlier than finalized block, slot 0 < slot 0",
   114  		},
   115  	}
   116  
   117  	for _, tt := range tests {
   118  		t.Run(tt.name, func(t *testing.T) {
   119  			service.justifiedCheckpt = &ethpb.Checkpoint{Root: validGenesisRoot[:]}
   120  			service.bestJustifiedCheckpt = &ethpb.Checkpoint{Root: validGenesisRoot[:]}
   121  			service.finalizedCheckpt = &ethpb.Checkpoint{Root: validGenesisRoot[:]}
   122  			service.prevFinalizedCheckpt = &ethpb.Checkpoint{Root: validGenesisRoot[:]}
   123  			service.finalizedCheckpt.Root = roots[0]
   124  
   125  			root, err := tt.blk.Block.HashTreeRoot()
   126  			assert.NoError(t, err)
   127  			err = service.onBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(tt.blk), root)
   128  			assert.ErrorContains(t, tt.wantErrString, err)
   129  		})
   130  	}
   131  }
   132  
   133  func TestStore_OnBlockBatch(t *testing.T) {
   134  	ctx := context.Background()
   135  	beaconDB := testDB.SetupDB(t)
   136  
   137  	cfg := &Config{
   138  		BeaconDB: beaconDB,
   139  		StateGen: stategen.New(beaconDB),
   140  	}
   141  	service, err := NewService(ctx, cfg)
   142  	require.NoError(t, err)
   143  
   144  	genesisStateRoot := [32]byte{}
   145  	genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
   146  	assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis)))
   147  	gRoot, err := genesis.Block.HashTreeRoot()
   148  	require.NoError(t, err)
   149  	service.finalizedCheckpt = &ethpb.Checkpoint{
   150  		Root: gRoot[:],
   151  	}
   152  	service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
   153  	service.saveInitSyncBlock(gRoot, wrapper.WrappedPhase0SignedBeaconBlock(genesis))
   154  
   155  	st, keys := testutil.DeterministicGenesisState(t, 64)
   156  
   157  	bState := st.Copy()
   158  
   159  	var blks []interfaces.SignedBeaconBlock
   160  	var blkRoots [][32]byte
   161  	var firstState iface.BeaconState
   162  	for i := 1; i < 10; i++ {
   163  		b, err := testutil.GenerateFullBlock(bState, keys, testutil.DefaultBlockGenConfig(), types.Slot(i))
   164  		require.NoError(t, err)
   165  		bState, err = state.ExecuteStateTransition(ctx, bState, wrapper.WrappedPhase0SignedBeaconBlock(b))
   166  		require.NoError(t, err)
   167  		if i == 1 {
   168  			firstState = bState.Copy()
   169  		}
   170  		root, err := b.Block.HashTreeRoot()
   171  		require.NoError(t, err)
   172  		service.saveInitSyncBlock(root, wrapper.WrappedPhase0SignedBeaconBlock(b))
   173  		blks = append(blks, wrapper.WrappedPhase0SignedBeaconBlock(b))
   174  		blkRoots = append(blkRoots, root)
   175  	}
   176  
   177  	rBlock, err := blks[0].PbPhase0Block()
   178  	assert.NoError(t, err)
   179  	rBlock.Block.ParentRoot = gRoot[:]
   180  	require.NoError(t, beaconDB.SaveBlock(context.Background(), blks[0]))
   181  	require.NoError(t, service.cfg.StateGen.SaveState(ctx, blkRoots[0], firstState))
   182  	_, _, err = service.onBlockBatch(ctx, blks[1:], blkRoots[1:])
   183  	require.NoError(t, err)
   184  }
   185  
   186  func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) {
   187  	ctx := context.Background()
   188  	beaconDB := testDB.SetupDB(t)
   189  	params.UseMinimalConfig()
   190  	defer params.UseMainnetConfig()
   191  
   192  	cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
   193  	service, err := NewService(ctx, cfg)
   194  	require.NoError(t, err)
   195  	service.genesisTime = time.Now()
   196  
   197  	update, err := service.shouldUpdateCurrentJustified(ctx, &ethpb.Checkpoint{Root: make([]byte, 32)})
   198  	require.NoError(t, err)
   199  	assert.Equal(t, true, update, "Should be able to update justified")
   200  	lastJustifiedBlk := testutil.NewBeaconBlock()
   201  	lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
   202  	lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot()
   203  	require.NoError(t, err)
   204  	newJustifiedBlk := testutil.NewBeaconBlock()
   205  	newJustifiedBlk.Block.Slot = 1
   206  	newJustifiedBlk.Block.ParentRoot = bytesutil.PadTo(lastJustifiedRoot[:], 32)
   207  	newJustifiedRoot, err := newJustifiedBlk.Block.HashTreeRoot()
   208  	require.NoError(t, err)
   209  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(newJustifiedBlk)))
   210  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(lastJustifiedBlk)))
   211  
   212  	diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot)
   213  	service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0)
   214  	service.justifiedCheckpt = &ethpb.Checkpoint{Root: lastJustifiedRoot[:]}
   215  	update, err = service.shouldUpdateCurrentJustified(ctx, &ethpb.Checkpoint{Root: newJustifiedRoot[:]})
   216  	require.NoError(t, err)
   217  	assert.Equal(t, true, update, "Should be able to update justified")
   218  }
   219  
   220  func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
   221  	ctx := context.Background()
   222  	beaconDB := testDB.SetupDB(t)
   223  	params.UseMinimalConfig()
   224  	defer params.UseMainnetConfig()
   225  
   226  	cfg := &Config{BeaconDB: beaconDB}
   227  	service, err := NewService(ctx, cfg)
   228  	require.NoError(t, err)
   229  	lastJustifiedBlk := testutil.NewBeaconBlock()
   230  	lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
   231  	lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot()
   232  	require.NoError(t, err)
   233  	newJustifiedBlk := testutil.NewBeaconBlock()
   234  	newJustifiedBlk.Block.ParentRoot = bytesutil.PadTo(lastJustifiedRoot[:], 32)
   235  	newJustifiedRoot, err := newJustifiedBlk.Block.HashTreeRoot()
   236  	require.NoError(t, err)
   237  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(newJustifiedBlk)))
   238  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(lastJustifiedBlk)))
   239  
   240  	diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot)
   241  	service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0)
   242  	service.justifiedCheckpt = &ethpb.Checkpoint{Root: lastJustifiedRoot[:]}
   243  
   244  	update, err := service.shouldUpdateCurrentJustified(ctx, &ethpb.Checkpoint{Root: newJustifiedRoot[:]})
   245  	require.NoError(t, err)
   246  	assert.Equal(t, false, update, "Should not be able to update justified, received true")
   247  }
   248  
   249  func TestCachedPreState_CanGetFromStateSummary(t *testing.T) {
   250  	ctx := context.Background()
   251  	beaconDB := testDB.SetupDB(t)
   252  
   253  	cfg := &Config{
   254  		BeaconDB: beaconDB,
   255  		StateGen: stategen.New(beaconDB),
   256  	}
   257  	service, err := NewService(ctx, cfg)
   258  	require.NoError(t, err)
   259  
   260  	s, err := v1.InitializeFromProto(&pb.BeaconState{Slot: 1, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
   261  	require.NoError(t, err)
   262  
   263  	genesisStateRoot := [32]byte{}
   264  	genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
   265  	assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis)))
   266  	gRoot, err := genesis.Block.HashTreeRoot()
   267  	require.NoError(t, err)
   268  	service.finalizedCheckpt = &ethpb.Checkpoint{
   269  		Root: gRoot[:],
   270  	}
   271  	service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
   272  	service.saveInitSyncBlock(gRoot, wrapper.WrappedPhase0SignedBeaconBlock(genesis))
   273  
   274  	b := testutil.NewBeaconBlock()
   275  	b.Block.Slot = 1
   276  	b.Block.ParentRoot = gRoot[:]
   277  	require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: gRoot[:]}))
   278  	require.NoError(t, service.cfg.StateGen.SaveState(ctx, gRoot, s))
   279  	require.NoError(t, service.verifyBlkPreState(ctx, wrapper.WrappedPhase0BeaconBlock(b.Block)))
   280  }
   281  
   282  func TestCachedPreState_CanGetFromDB(t *testing.T) {
   283  	ctx := context.Background()
   284  	beaconDB := testDB.SetupDB(t)
   285  
   286  	cfg := &Config{
   287  		BeaconDB: beaconDB,
   288  		StateGen: stategen.New(beaconDB),
   289  	}
   290  	service, err := NewService(ctx, cfg)
   291  	require.NoError(t, err)
   292  
   293  	genesisStateRoot := [32]byte{}
   294  	genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
   295  	assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis)))
   296  	gRoot, err := genesis.Block.HashTreeRoot()
   297  	require.NoError(t, err)
   298  	service.finalizedCheckpt = &ethpb.Checkpoint{
   299  		Root: gRoot[:],
   300  	}
   301  	service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
   302  	service.saveInitSyncBlock(gRoot, wrapper.WrappedPhase0SignedBeaconBlock(genesis))
   303  
   304  	b := testutil.NewBeaconBlock()
   305  	b.Block.Slot = 1
   306  	service.finalizedCheckpt = &ethpb.Checkpoint{Root: gRoot[:]}
   307  	err = service.verifyBlkPreState(ctx, wrapper.WrappedPhase0BeaconBlock(b.Block))
   308  	wanted := "could not reconstruct parent state"
   309  	assert.ErrorContains(t, wanted, err)
   310  
   311  	b.Block.ParentRoot = gRoot[:]
   312  	s, err := v1.InitializeFromProto(&pb.BeaconState{Slot: 1})
   313  	require.NoError(t, err)
   314  	require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: gRoot[:]}))
   315  	require.NoError(t, service.cfg.StateGen.SaveState(ctx, gRoot, s))
   316  	require.NoError(t, service.verifyBlkPreState(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b).Block()))
   317  }
   318  
   319  func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
   320  	ctx := context.Background()
   321  	beaconDB := testDB.SetupDB(t)
   322  
   323  	cfg := &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)}
   324  	service, err := NewService(ctx, cfg)
   325  	require.NoError(t, err)
   326  
   327  	signedBlock := testutil.NewBeaconBlock()
   328  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(signedBlock)))
   329  	r, err := signedBlock.Block.HashTreeRoot()
   330  	require.NoError(t, err)
   331  	service.justifiedCheckpt = &ethpb.Checkpoint{Root: []byte{'A'}}
   332  	service.bestJustifiedCheckpt = &ethpb.Checkpoint{Root: []byte{'A'}}
   333  	st, err := testutil.NewBeaconState()
   334  	require.NoError(t, err)
   335  	require.NoError(t, beaconDB.SaveState(ctx, st.Copy(), r))
   336  
   337  	// Could update
   338  	s, err := testutil.NewBeaconState()
   339  	require.NoError(t, err)
   340  	require.NoError(t, s.SetCurrentJustifiedCheckpoint(&ethpb.Checkpoint{Epoch: 1, Root: r[:]}))
   341  	require.NoError(t, service.updateJustified(context.Background(), s))
   342  
   343  	assert.Equal(t, s.CurrentJustifiedCheckpoint().Epoch, service.bestJustifiedCheckpt.Epoch, "Incorrect justified epoch in service")
   344  
   345  	// Could not update
   346  	service.bestJustifiedCheckpt.Epoch = 2
   347  	require.NoError(t, service.updateJustified(context.Background(), s))
   348  
   349  	assert.Equal(t, types.Epoch(2), service.bestJustifiedCheckpt.Epoch, "Incorrect justified epoch in service")
   350  }
   351  
   352  func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
   353  	ctx := context.Background()
   354  	beaconDB := testDB.SetupDB(t)
   355  
   356  	cfg := &Config{BeaconDB: beaconDB}
   357  	service, err := NewService(ctx, cfg)
   358  	require.NoError(t, err)
   359  	service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
   360  	service.finalizedCheckpt = &ethpb.Checkpoint{Root: make([]byte, 32)}
   361  
   362  	genesisStateRoot := [32]byte{}
   363  	genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
   364  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis)))
   365  	validGenesisRoot, err := genesis.Block.HashTreeRoot()
   366  	require.NoError(t, err)
   367  	st, err := testutil.NewBeaconState()
   368  	require.NoError(t, err)
   369  
   370  	require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
   371  	roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
   372  	require.NoError(t, err)
   373  
   374  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
   375  	block := testutil.NewBeaconBlock()
   376  	block.Block.Slot = 9
   377  	block.Block.ParentRoot = roots[8]
   378  
   379  	err = service.fillInForkChoiceMissingBlocks(
   380  		context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(block).Block(), beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint())
   381  	require.NoError(t, err)
   382  
   383  	// 5 nodes from the block tree 1. B0 - B3 - B4 - B6 - B8
   384  	assert.Equal(t, 5, len(service.cfg.ForkChoiceStore.Nodes()), "Miss match nodes")
   385  	assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(bytesutil.ToBytes32(roots[4])), "Didn't save node")
   386  	assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(bytesutil.ToBytes32(roots[6])), "Didn't save node")
   387  	assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(bytesutil.ToBytes32(roots[8])), "Didn't save node")
   388  }
   389  
   390  func TestFillForkChoiceMissingBlocks_RootsMatch(t *testing.T) {
   391  	ctx := context.Background()
   392  	beaconDB := testDB.SetupDB(t)
   393  
   394  	cfg := &Config{BeaconDB: beaconDB}
   395  	service, err := NewService(ctx, cfg)
   396  	require.NoError(t, err)
   397  	service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
   398  	service.finalizedCheckpt = &ethpb.Checkpoint{Root: make([]byte, 32)}
   399  
   400  	genesisStateRoot := [32]byte{}
   401  	genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
   402  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis)))
   403  	validGenesisRoot, err := genesis.Block.HashTreeRoot()
   404  	require.NoError(t, err)
   405  	st, err := testutil.NewBeaconState()
   406  	require.NoError(t, err)
   407  
   408  	require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
   409  	roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
   410  	require.NoError(t, err)
   411  
   412  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
   413  	block := testutil.NewBeaconBlock()
   414  	block.Block.Slot = 9
   415  	block.Block.ParentRoot = roots[8]
   416  
   417  	err = service.fillInForkChoiceMissingBlocks(
   418  		context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(block).Block(), beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint())
   419  	require.NoError(t, err)
   420  
   421  	// 5 nodes from the block tree 1. B0 - B3 - B4 - B6 - B8
   422  	assert.Equal(t, 5, len(service.cfg.ForkChoiceStore.Nodes()), "Miss match nodes")
   423  	// Ensure all roots and their respective blocks exist.
   424  	wantedRoots := [][]byte{roots[0], roots[3], roots[4], roots[6], roots[8]}
   425  	for i, rt := range wantedRoots {
   426  		assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(bytesutil.ToBytes32(rt)), fmt.Sprintf("Didn't save node: %d", i))
   427  		assert.Equal(t, true, service.cfg.BeaconDB.HasBlock(context.Background(), bytesutil.ToBytes32(rt)))
   428  	}
   429  }
   430  
   431  func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
   432  	ctx := context.Background()
   433  	beaconDB := testDB.SetupDB(t)
   434  
   435  	cfg := &Config{BeaconDB: beaconDB}
   436  	service, err := NewService(ctx, cfg)
   437  	require.NoError(t, err)
   438  	service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
   439  	// Set finalized epoch to 1.
   440  	service.finalizedCheckpt = &ethpb.Checkpoint{Epoch: 1}
   441  
   442  	genesisStateRoot := [32]byte{}
   443  	genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
   444  	assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis)))
   445  	validGenesisRoot, err := genesis.Block.HashTreeRoot()
   446  	assert.NoError(t, err)
   447  	st, err := testutil.NewBeaconState()
   448  	require.NoError(t, err)
   449  
   450  	require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
   451  
   452  	// Define a tree branch, slot 63 <- 64 <- 65
   453  	b63 := testutil.NewBeaconBlock()
   454  	b63.Block.Slot = 63
   455  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b63)))
   456  	r63, err := b63.Block.HashTreeRoot()
   457  	require.NoError(t, err)
   458  	b64 := testutil.NewBeaconBlock()
   459  	b64.Block.Slot = 64
   460  	b64.Block.ParentRoot = r63[:]
   461  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b64)))
   462  	r64, err := b64.Block.HashTreeRoot()
   463  	require.NoError(t, err)
   464  	b65 := testutil.NewBeaconBlock()
   465  	b65.Block.Slot = 65
   466  	b65.Block.ParentRoot = r64[:]
   467  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b65)))
   468  
   469  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
   470  	err = service.fillInForkChoiceMissingBlocks(
   471  		context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b65).Block(), beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint())
   472  	require.NoError(t, err)
   473  
   474  	// There should be 2 nodes, block 65 and block 64.
   475  	assert.Equal(t, 2, len(service.cfg.ForkChoiceStore.Nodes()), "Miss match nodes")
   476  
   477  	// Block with slot 63 should be in fork choice because it's less than finalized epoch 1.
   478  	assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(r63), "Didn't save node")
   479  }
   480  
   481  // blockTree1 constructs the following tree:
   482  //    /- B1
   483  // B0           /- B5 - B7
   484  //    \- B3 - B4 - B6 - B8
   485  // (B1, and B3 are all from the same slots)
   486  func blockTree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][]byte, error) {
   487  	genesisRoot = bytesutil.PadTo(genesisRoot, 32)
   488  	b0 := testutil.NewBeaconBlock()
   489  	b0.Block.Slot = 0
   490  	b0.Block.ParentRoot = genesisRoot
   491  	r0, err := b0.Block.HashTreeRoot()
   492  	if err != nil {
   493  		return nil, err
   494  	}
   495  	b1 := testutil.NewBeaconBlock()
   496  	b1.Block.Slot = 1
   497  	b1.Block.ParentRoot = r0[:]
   498  	r1, err := b1.Block.HashTreeRoot()
   499  	if err != nil {
   500  		return nil, err
   501  	}
   502  	b3 := testutil.NewBeaconBlock()
   503  	b3.Block.Slot = 3
   504  	b3.Block.ParentRoot = r0[:]
   505  	r3, err := b3.Block.HashTreeRoot()
   506  	if err != nil {
   507  		return nil, err
   508  	}
   509  	b4 := testutil.NewBeaconBlock()
   510  	b4.Block.Slot = 4
   511  	b4.Block.ParentRoot = r3[:]
   512  	r4, err := b4.Block.HashTreeRoot()
   513  	if err != nil {
   514  		return nil, err
   515  	}
   516  	b5 := testutil.NewBeaconBlock()
   517  	b5.Block.Slot = 5
   518  	b5.Block.ParentRoot = r4[:]
   519  	r5, err := b5.Block.HashTreeRoot()
   520  	if err != nil {
   521  		return nil, err
   522  	}
   523  	b6 := testutil.NewBeaconBlock()
   524  	b6.Block.Slot = 6
   525  	b6.Block.ParentRoot = r4[:]
   526  	r6, err := b6.Block.HashTreeRoot()
   527  	if err != nil {
   528  		return nil, err
   529  	}
   530  	b7 := testutil.NewBeaconBlock()
   531  	b7.Block.Slot = 7
   532  	b7.Block.ParentRoot = r5[:]
   533  	r7, err := b7.Block.HashTreeRoot()
   534  	if err != nil {
   535  		return nil, err
   536  	}
   537  	b8 := testutil.NewBeaconBlock()
   538  	b8.Block.Slot = 8
   539  	b8.Block.ParentRoot = r6[:]
   540  	r8, err := b8.Block.HashTreeRoot()
   541  	if err != nil {
   542  		return nil, err
   543  	}
   544  	st, err := testutil.NewBeaconState()
   545  	require.NoError(t, err)
   546  
   547  	for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b3, b4, b5, b6, b7, b8} {
   548  		beaconBlock := testutil.NewBeaconBlock()
   549  		beaconBlock.Block.Slot = b.Block.Slot
   550  		beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
   551  		if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil {
   552  			return nil, err
   553  		}
   554  		if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
   555  			return nil, errors.Wrap(err, "could not save state")
   556  		}
   557  	}
   558  	if err := beaconDB.SaveState(context.Background(), st.Copy(), r1); err != nil {
   559  		return nil, err
   560  	}
   561  	if err := beaconDB.SaveState(context.Background(), st.Copy(), r7); err != nil {
   562  		return nil, err
   563  	}
   564  	if err := beaconDB.SaveState(context.Background(), st.Copy(), r8); err != nil {
   565  		return nil, err
   566  	}
   567  	return [][]byte{r0[:], r1[:], nil, r3[:], r4[:], r5[:], r6[:], r7[:], r8[:]}, nil
   568  }
   569  
   570  func TestCurrentSlot_HandlesOverflow(t *testing.T) {
   571  	svc := Service{genesisTime: timeutils.Now().Add(1 * time.Hour)}
   572  
   573  	slot := svc.CurrentSlot()
   574  	require.Equal(t, types.Slot(0), slot, "Unexpected slot")
   575  }
   576  func TestAncestorByDB_CtxErr(t *testing.T) {
   577  	ctx, cancel := context.WithCancel(context.Background())
   578  	service, err := NewService(ctx, &Config{})
   579  	require.NoError(t, err)
   580  
   581  	cancel()
   582  	_, err = service.ancestorByDB(ctx, [32]byte{}, 0)
   583  	require.ErrorContains(t, "context canceled", err)
   584  }
   585  
   586  func TestAncestor_HandleSkipSlot(t *testing.T) {
   587  	ctx := context.Background()
   588  	beaconDB := testDB.SetupDB(t)
   589  
   590  	cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
   591  	service, err := NewService(ctx, cfg)
   592  	require.NoError(t, err)
   593  
   594  	b1 := testutil.NewBeaconBlock()
   595  	b1.Block.Slot = 1
   596  	b1.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
   597  	r1, err := b1.Block.HashTreeRoot()
   598  	require.NoError(t, err)
   599  	b100 := testutil.NewBeaconBlock()
   600  	b100.Block.Slot = 100
   601  	b100.Block.ParentRoot = r1[:]
   602  	r100, err := b100.Block.HashTreeRoot()
   603  	require.NoError(t, err)
   604  	b200 := testutil.NewBeaconBlock()
   605  	b200.Block.Slot = 200
   606  	b200.Block.ParentRoot = r100[:]
   607  	r200, err := b200.Block.HashTreeRoot()
   608  	require.NoError(t, err)
   609  	for _, b := range []*ethpb.SignedBeaconBlock{b1, b100, b200} {
   610  		beaconBlock := testutil.NewBeaconBlock()
   611  		beaconBlock.Block.Slot = b.Block.Slot
   612  		beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
   613  		require.NoError(t, beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)))
   614  	}
   615  
   616  	// Slots 100 to 200 are skip slots. Requesting root at 150 will yield root at 100. The last physical block.
   617  	r, err := service.ancestor(context.Background(), r200[:], 150)
   618  	require.NoError(t, err)
   619  	if bytesutil.ToBytes32(r) != r100 {
   620  		t.Error("Did not get correct root")
   621  	}
   622  
   623  	// Slots 1 to 100 are skip slots. Requesting root at 50 will yield root at 1. The last physical block.
   624  	r, err = service.ancestor(context.Background(), r200[:], 50)
   625  	require.NoError(t, err)
   626  	if bytesutil.ToBytes32(r) != r1 {
   627  		t.Error("Did not get correct root")
   628  	}
   629  }
   630  
   631  func TestAncestor_CanUseForkchoice(t *testing.T) {
   632  	ctx := context.Background()
   633  	cfg := &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
   634  	service, err := NewService(ctx, cfg)
   635  	require.NoError(t, err)
   636  
   637  	b1 := testutil.NewBeaconBlock()
   638  	b1.Block.Slot = 1
   639  	b1.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
   640  	r1, err := b1.Block.HashTreeRoot()
   641  	require.NoError(t, err)
   642  	b100 := testutil.NewBeaconBlock()
   643  	b100.Block.Slot = 100
   644  	b100.Block.ParentRoot = r1[:]
   645  	r100, err := b100.Block.HashTreeRoot()
   646  	require.NoError(t, err)
   647  	b200 := testutil.NewBeaconBlock()
   648  	b200.Block.Slot = 200
   649  	b200.Block.ParentRoot = r100[:]
   650  	r200, err := b200.Block.HashTreeRoot()
   651  	require.NoError(t, err)
   652  	for _, b := range []*ethpb.SignedBeaconBlock{b1, b100, b200} {
   653  		beaconBlock := testutil.NewBeaconBlock()
   654  		beaconBlock.Block.Slot = b.Block.Slot
   655  		beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
   656  		r, err := b.Block.HashTreeRoot()
   657  		require.NoError(t, err)
   658  		require.NoError(t, service.cfg.ForkChoiceStore.ProcessBlock(context.Background(), b.Block.Slot, r, bytesutil.ToBytes32(b.Block.ParentRoot), [32]byte{}, 0, 0)) // Saves blocks to fork choice store.
   659  	}
   660  
   661  	r, err := service.ancestor(context.Background(), r200[:], 150)
   662  	require.NoError(t, err)
   663  	if bytesutil.ToBytes32(r) != r100 {
   664  		t.Error("Did not get correct root")
   665  	}
   666  }
   667  
   668  func TestAncestor_CanUseDB(t *testing.T) {
   669  	ctx := context.Background()
   670  	beaconDB := testDB.SetupDB(t)
   671  
   672  	cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
   673  	service, err := NewService(ctx, cfg)
   674  	require.NoError(t, err)
   675  
   676  	b1 := testutil.NewBeaconBlock()
   677  	b1.Block.Slot = 1
   678  	b1.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
   679  	r1, err := b1.Block.HashTreeRoot()
   680  	require.NoError(t, err)
   681  	b100 := testutil.NewBeaconBlock()
   682  	b100.Block.Slot = 100
   683  	b100.Block.ParentRoot = r1[:]
   684  	r100, err := b100.Block.HashTreeRoot()
   685  	require.NoError(t, err)
   686  	b200 := testutil.NewBeaconBlock()
   687  	b200.Block.Slot = 200
   688  	b200.Block.ParentRoot = r100[:]
   689  	r200, err := b200.Block.HashTreeRoot()
   690  	require.NoError(t, err)
   691  	for _, b := range []*ethpb.SignedBeaconBlock{b1, b100, b200} {
   692  		beaconBlock := testutil.NewBeaconBlock()
   693  		beaconBlock.Block.Slot = b.Block.Slot
   694  		beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
   695  		require.NoError(t, beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock))) // Saves blocks to DB.
   696  	}
   697  
   698  	require.NoError(t, service.cfg.ForkChoiceStore.ProcessBlock(context.Background(), 200, r200, r200, [32]byte{}, 0, 0))
   699  
   700  	r, err := service.ancestor(context.Background(), r200[:], 150)
   701  	require.NoError(t, err)
   702  	if bytesutil.ToBytes32(r) != r100 {
   703  		t.Error("Did not get correct root")
   704  	}
   705  }
   706  
   707  func TestEnsureRootNotZeroHashes(t *testing.T) {
   708  	ctx := context.Background()
   709  	cfg := &Config{}
   710  	service, err := NewService(ctx, cfg)
   711  	require.NoError(t, err)
   712  	service.genesisRoot = [32]byte{'a'}
   713  
   714  	r := service.ensureRootNotZeros(params.BeaconConfig().ZeroHash)
   715  	assert.Equal(t, service.genesisRoot, r, "Did not get wanted justified root")
   716  	root := [32]byte{'b'}
   717  	r = service.ensureRootNotZeros(root)
   718  	assert.Equal(t, root, r, "Did not get wanted justified root")
   719  }
   720  
   721  func TestFinalizedImpliesNewJustified(t *testing.T) {
   722  	beaconDB := testDB.SetupDB(t)
   723  	ctx := context.Background()
   724  	type args struct {
   725  		cachedCheckPoint        *ethpb.Checkpoint
   726  		stateCheckPoint         *ethpb.Checkpoint
   727  		diffFinalizedCheckPoint bool
   728  	}
   729  	tests := []struct {
   730  		name string
   731  		args args
   732  		want *ethpb.Checkpoint
   733  	}{
   734  		{
   735  			name: "Same justified, do nothing",
   736  			args: args{
   737  				cachedCheckPoint: &ethpb.Checkpoint{Epoch: 1, Root: []byte{'a'}},
   738  				stateCheckPoint:  &ethpb.Checkpoint{Epoch: 1, Root: []byte{'a'}},
   739  			},
   740  			want: &ethpb.Checkpoint{Epoch: 1, Root: []byte{'a'}},
   741  		},
   742  		{
   743  			name: "Different justified, higher epoch, cache new justified",
   744  			args: args{
   745  				cachedCheckPoint: &ethpb.Checkpoint{Epoch: 1, Root: []byte{'a'}},
   746  				stateCheckPoint:  &ethpb.Checkpoint{Epoch: 2, Root: []byte{'b'}},
   747  			},
   748  			want: &ethpb.Checkpoint{Epoch: 2, Root: []byte{'b'}},
   749  		},
   750  		{
   751  			name: "finalized has different justified, cache new justified",
   752  			args: args{
   753  				cachedCheckPoint:        &ethpb.Checkpoint{Epoch: 1, Root: []byte{'a'}},
   754  				stateCheckPoint:         &ethpb.Checkpoint{Epoch: 1, Root: []byte{'b'}},
   755  				diffFinalizedCheckPoint: true,
   756  			},
   757  			want: &ethpb.Checkpoint{Epoch: 1, Root: []byte{'b'}},
   758  		},
   759  	}
   760  	for _, test := range tests {
   761  		beaconState, err := testutil.NewBeaconState()
   762  		require.NoError(t, err)
   763  		require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(test.args.stateCheckPoint))
   764  		service, err := NewService(ctx, &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB), ForkChoiceStore: protoarray.New(0, 0, [32]byte{})})
   765  		require.NoError(t, err)
   766  		service.justifiedCheckpt = test.args.cachedCheckPoint
   767  		require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo(test.want.Root, 32)}))
   768  		genesisState, err := testutil.NewBeaconState()
   769  		require.NoError(t, err)
   770  		require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, genesisState, bytesutil.ToBytes32(test.want.Root)))
   771  
   772  		if test.args.diffFinalizedCheckPoint {
   773  			b1 := testutil.NewBeaconBlock()
   774  			b1.Block.Slot = 1
   775  			b1.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
   776  			r1, err := b1.Block.HashTreeRoot()
   777  			require.NoError(t, err)
   778  			b100 := testutil.NewBeaconBlock()
   779  			b100.Block.Slot = 100
   780  			b100.Block.ParentRoot = r1[:]
   781  			r100, err := b100.Block.HashTreeRoot()
   782  			require.NoError(t, err)
   783  			for _, b := range []*ethpb.SignedBeaconBlock{b1, b100} {
   784  				beaconBlock := testutil.NewBeaconBlock()
   785  				beaconBlock.Block.Slot = b.Block.Slot
   786  				beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
   787  				require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)))
   788  			}
   789  			service.finalizedCheckpt = &ethpb.Checkpoint{Root: []byte{'c'}, Epoch: 1}
   790  			service.justifiedCheckpt.Root = r100[:]
   791  		}
   792  
   793  		require.NoError(t, service.finalizedImpliesNewJustified(ctx, beaconState))
   794  		assert.Equal(t, true, attestationutil.CheckPointIsEqual(test.want, service.justifiedCheckpt), "Did not get wanted check point")
   795  	}
   796  }
   797  
   798  func TestVerifyBlkDescendant(t *testing.T) {
   799  	beaconDB := testDB.SetupDB(t)
   800  	ctx := context.Background()
   801  
   802  	b := testutil.NewBeaconBlock()
   803  	b.Block.Slot = 1
   804  	r, err := b.Block.HashTreeRoot()
   805  	require.NoError(t, err)
   806  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
   807  
   808  	b1 := testutil.NewBeaconBlock()
   809  	b1.Block.Slot = 1
   810  	b1.Block.Body.Graffiti = bytesutil.PadTo([]byte{'a'}, 32)
   811  	r1, err := b1.Block.HashTreeRoot()
   812  	require.NoError(t, err)
   813  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1)))
   814  
   815  	type args struct {
   816  		parentRoot    [32]byte
   817  		finalizedRoot [32]byte
   818  	}
   819  	tests := []struct {
   820  		name      string
   821  		args      args
   822  		wantedErr string
   823  	}{
   824  		{
   825  			name: "could not get finalized block in block service cache",
   826  			args: args{
   827  				finalizedRoot: [32]byte{'a'},
   828  			},
   829  			wantedErr: "nil finalized block",
   830  		},
   831  		{
   832  			name: "could not get finalized block root in DB",
   833  			args: args{
   834  				finalizedRoot: r,
   835  				parentRoot:    [32]byte{'a'},
   836  			},
   837  			wantedErr: "could not get finalized block root",
   838  		},
   839  		{
   840  			name: "is not descendant",
   841  			args: args{
   842  				finalizedRoot: r1,
   843  				parentRoot:    r,
   844  			},
   845  			wantedErr: "is not a descendent of the current finalized block slot",
   846  		},
   847  		{
   848  			name: "is descendant",
   849  			args: args{
   850  				finalizedRoot: r,
   851  				parentRoot:    r,
   852  			},
   853  		},
   854  	}
   855  	for _, tt := range tests {
   856  		service, err := NewService(ctx, &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB), ForkChoiceStore: protoarray.New(0, 0, [32]byte{})})
   857  		require.NoError(t, err)
   858  		service.finalizedCheckpt = &ethpb.Checkpoint{
   859  			Root: tt.args.finalizedRoot[:],
   860  		}
   861  		err = service.VerifyBlkDescendant(ctx, tt.args.parentRoot)
   862  		if tt.wantedErr != "" {
   863  			assert.ErrorContains(t, tt.wantedErr, err)
   864  		} else if err != nil {
   865  			assert.NoError(t, err)
   866  		}
   867  	}
   868  }
   869  
   870  func TestUpdateJustifiedInitSync(t *testing.T) {
   871  	beaconDB := testDB.SetupDB(t)
   872  	ctx := context.Background()
   873  	cfg := &Config{BeaconDB: beaconDB}
   874  	service, err := NewService(ctx, cfg)
   875  	require.NoError(t, err)
   876  
   877  	gBlk := testutil.NewBeaconBlock()
   878  	gRoot, err := gBlk.Block.HashTreeRoot()
   879  	require.NoError(t, err)
   880  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(gBlk)))
   881  	require.NoError(t, service.cfg.BeaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   882  	require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: gRoot[:]}))
   883  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
   884  	require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, beaconState, gRoot))
   885  	service.genesisRoot = gRoot
   886  	currentCp := &ethpb.Checkpoint{Epoch: 1}
   887  	service.justifiedCheckpt = currentCp
   888  	newCp := &ethpb.Checkpoint{Epoch: 2, Root: gRoot[:]}
   889  
   890  	require.NoError(t, service.updateJustifiedInitSync(ctx, newCp))
   891  
   892  	assert.DeepSSZEqual(t, currentCp, service.prevJustifiedCheckpt, "Incorrect previous justified checkpoint")
   893  	assert.DeepSSZEqual(t, newCp, service.CurrentJustifiedCheckpt(), "Incorrect current justified checkpoint in cache")
   894  	cp, err := service.cfg.BeaconDB.JustifiedCheckpoint(ctx)
   895  	require.NoError(t, err)
   896  	assert.DeepSSZEqual(t, newCp, cp, "Incorrect current justified checkpoint in db")
   897  }
   898  
   899  func TestHandleEpochBoundary_BadMetrics(t *testing.T) {
   900  	ctx := context.Background()
   901  	cfg := &Config{}
   902  	service, err := NewService(ctx, cfg)
   903  	require.NoError(t, err)
   904  
   905  	s, err := testutil.NewBeaconState()
   906  	require.NoError(t, err)
   907  	require.NoError(t, s.SetSlot(1))
   908  	service.head = &head{state: (*v1.BeaconState)(nil)}
   909  
   910  	require.ErrorContains(t, "failed to initialize precompute: nil inner state", service.handleEpochBoundary(ctx, s))
   911  }
   912  
   913  func TestHandleEpochBoundary_UpdateFirstSlot(t *testing.T) {
   914  	ctx := context.Background()
   915  	cfg := &Config{}
   916  	service, err := NewService(ctx, cfg)
   917  	require.NoError(t, err)
   918  
   919  	s, _ := testutil.DeterministicGenesisState(t, 1024)
   920  	service.head = &head{state: s}
   921  	require.NoError(t, s.SetSlot(2*params.BeaconConfig().SlotsPerEpoch))
   922  	require.NoError(t, service.handleEpochBoundary(ctx, s))
   923  	require.Equal(t, 3*params.BeaconConfig().SlotsPerEpoch, service.nextEpochBoundarySlot)
   924  }
   925  
   926  func TestOnBlock_CanFinalize(t *testing.T) {
   927  	ctx := context.Background()
   928  	beaconDB := testDB.SetupDB(t)
   929  	depositCache, err := depositcache.New()
   930  	require.NoError(t, err)
   931  	cfg := &Config{
   932  		BeaconDB:        beaconDB,
   933  		StateGen:        stategen.New(beaconDB),
   934  		ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
   935  		DepositCache:    depositCache,
   936  		StateNotifier:   &mock.MockStateNotifier{},
   937  	}
   938  	service, err := NewService(ctx, cfg)
   939  	require.NoError(t, err)
   940  
   941  	gs, keys := testutil.DeterministicGenesisState(t, 32)
   942  	require.NoError(t, service.saveGenesisData(ctx, gs))
   943  	gBlk, err := service.cfg.BeaconDB.GenesisBlock(ctx)
   944  	require.NoError(t, err)
   945  	gRoot, err := gBlk.Block().HashTreeRoot()
   946  	require.NoError(t, err)
   947  	service.finalizedCheckpt = &ethpb.Checkpoint{Root: gRoot[:]}
   948  
   949  	testState := gs.Copy()
   950  	for i := types.Slot(1); i <= 4*params.BeaconConfig().SlotsPerEpoch; i++ {
   951  		blk, err := testutil.GenerateFullBlock(testState, keys, testutil.DefaultBlockGenConfig(), i)
   952  		require.NoError(t, err)
   953  		r, err := blk.Block.HashTreeRoot()
   954  		require.NoError(t, err)
   955  		require.NoError(t, service.onBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(blk), r))
   956  		testState, err = service.cfg.StateGen.StateByRoot(ctx, r)
   957  		require.NoError(t, err)
   958  	}
   959  	require.Equal(t, types.Epoch(3), service.CurrentJustifiedCheckpt().Epoch)
   960  	require.Equal(t, types.Epoch(2), service.FinalizedCheckpt().Epoch)
   961  }
   962  
   963  func TestInsertFinalizedDeposits(t *testing.T) {
   964  	ctx := context.Background()
   965  	beaconDB := testDB.SetupDB(t)
   966  	depositCache, err := depositcache.New()
   967  	require.NoError(t, err)
   968  	cfg := &Config{
   969  		BeaconDB:        beaconDB,
   970  		StateGen:        stategen.New(beaconDB),
   971  		ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
   972  		DepositCache:    depositCache,
   973  	}
   974  	service, err := NewService(ctx, cfg)
   975  	require.NoError(t, err)
   976  
   977  	gs, _ := testutil.DeterministicGenesisState(t, 32)
   978  	require.NoError(t, service.saveGenesisData(ctx, gs))
   979  	gBlk, err := service.cfg.BeaconDB.GenesisBlock(ctx)
   980  	require.NoError(t, err)
   981  	gRoot, err := gBlk.Block().HashTreeRoot()
   982  	require.NoError(t, err)
   983  	service.finalizedCheckpt = &ethpb.Checkpoint{Root: gRoot[:]}
   984  	gs = gs.Copy()
   985  	assert.NoError(t, gs.SetEth1Data(&ethpb.Eth1Data{DepositCount: 10}))
   986  	assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs))
   987  	zeroSig := [96]byte{}
   988  	for i := uint64(0); i < uint64(4*params.BeaconConfig().SlotsPerEpoch); i++ {
   989  		root := []byte(strconv.Itoa(int(i)))
   990  		assert.NoError(t, depositCache.InsertDeposit(ctx, &ethpb.Deposit{Data: &ethpb.Deposit_Data{
   991  			PublicKey:             bytesutil.FromBytes48([48]byte{}),
   992  			WithdrawalCredentials: params.BeaconConfig().ZeroHash[:],
   993  			Amount:                0,
   994  			Signature:             zeroSig[:],
   995  		}, Proof: [][]byte{root}}, 100+i, int64(i), bytesutil.ToBytes32(root)))
   996  	}
   997  	assert.NoError(t, service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k'}))
   998  	fDeposits := depositCache.FinalizedDeposits(ctx)
   999  	assert.Equal(t, 9, int(fDeposits.MerkleTrieIndex), "Finalized deposits not inserted correctly")
  1000  	deps := depositCache.AllDeposits(ctx, big.NewInt(109))
  1001  	for _, d := range deps {
  1002  		assert.DeepEqual(t, [][]byte(nil), d.Proof, "Proofs are not empty")
  1003  	}
  1004  }
  1005  
  1006  func TestRemoveBlockAttestationsInPool_Canonical(t *testing.T) {
  1007  	resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{
  1008  		CorrectlyPruneCanonicalAtts: true,
  1009  	})
  1010  	defer resetCfg()
  1011  
  1012  	genesis, keys := testutil.DeterministicGenesisState(t, 64)
  1013  	b, err := testutil.GenerateFullBlock(genesis, keys, testutil.DefaultBlockGenConfig(), 1)
  1014  	assert.NoError(t, err)
  1015  	r, err := b.Block.HashTreeRoot()
  1016  	require.NoError(t, err)
  1017  
  1018  	ctx := context.Background()
  1019  	beaconDB := testDB.SetupDB(t)
  1020  	service := setupBeaconChain(t, beaconDB)
  1021  	require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: r[:]}))
  1022  	require.NoError(t, service.cfg.BeaconDB.SaveGenesisBlockRoot(ctx, r))
  1023  
  1024  	atts := b.Block.Body.Attestations
  1025  	require.NoError(t, service.cfg.AttPool.SaveAggregatedAttestations(atts))
  1026  	require.NoError(t, service.pruneCanonicalAttsFromPool(ctx, r, wrapper.WrappedPhase0SignedBeaconBlock(b)))
  1027  	require.Equal(t, 0, service.cfg.AttPool.AggregatedAttestationCount())
  1028  }
  1029  
  1030  func TestRemoveBlockAttestationsInPool_NonCanonical(t *testing.T) {
  1031  	resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{
  1032  		CorrectlyPruneCanonicalAtts: true,
  1033  	})
  1034  	defer resetCfg()
  1035  
  1036  	genesis, keys := testutil.DeterministicGenesisState(t, 64)
  1037  	b, err := testutil.GenerateFullBlock(genesis, keys, testutil.DefaultBlockGenConfig(), 1)
  1038  	assert.NoError(t, err)
  1039  	r, err := b.Block.HashTreeRoot()
  1040  	require.NoError(t, err)
  1041  
  1042  	ctx := context.Background()
  1043  	beaconDB := testDB.SetupDB(t)
  1044  	service := setupBeaconChain(t, beaconDB)
  1045  
  1046  	atts := b.Block.Body.Attestations
  1047  	require.NoError(t, service.cfg.AttPool.SaveAggregatedAttestations(atts))
  1048  	require.NoError(t, service.pruneCanonicalAttsFromPool(ctx, r, wrapper.WrappedPhase0SignedBeaconBlock(b)))
  1049  	require.Equal(t, 1, service.cfg.AttPool.AggregatedAttestationCount())
  1050  }