github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/state/stategen/replay_test.go (about)

     1  package stategen
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	types "github.com/prysmaticlabs/eth2-types"
     8  	"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
     9  	"github.com/prysmaticlabs/prysm/beacon-chain/db"
    10  	testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
    11  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    12  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    13  	"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
    14  	"github.com/prysmaticlabs/prysm/proto/interfaces"
    15  	"github.com/prysmaticlabs/prysm/shared/bytesutil"
    16  	"github.com/prysmaticlabs/prysm/shared/params"
    17  	"github.com/prysmaticlabs/prysm/shared/testutil"
    18  	"github.com/prysmaticlabs/prysm/shared/testutil/assert"
    19  	"github.com/prysmaticlabs/prysm/shared/testutil/require"
    20  	"google.golang.org/protobuf/proto"
    21  )
    22  
    23  func TestReplayBlocks_AllSkipSlots(t *testing.T) {
    24  	beaconDB := testDB.SetupDB(t)
    25  
    26  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
    27  	genesisBlock := blocks.NewGenesisBlock([]byte{})
    28  	bodyRoot, err := genesisBlock.Block.HashTreeRoot()
    29  	require.NoError(t, err)
    30  	err = beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
    31  		Slot:       genesisBlock.Block.Slot,
    32  		ParentRoot: genesisBlock.Block.ParentRoot,
    33  		StateRoot:  params.BeaconConfig().ZeroHash[:],
    34  		BodyRoot:   bodyRoot[:],
    35  	})
    36  	require.NoError(t, err)
    37  	require.NoError(t, beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)))
    38  	cp := beaconState.CurrentJustifiedCheckpoint()
    39  	mockRoot := [32]byte{}
    40  	copy(mockRoot[:], "hello-world")
    41  	cp.Root = mockRoot[:]
    42  	require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cp))
    43  	require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
    44  
    45  	service := New(beaconDB)
    46  	targetSlot := params.BeaconConfig().SlotsPerEpoch - 1
    47  	newState, err := service.ReplayBlocks(context.Background(), beaconState, []interfaces.SignedBeaconBlock{}, targetSlot)
    48  	require.NoError(t, err)
    49  	assert.Equal(t, targetSlot, newState.Slot(), "Did not advance slots")
    50  }
    51  
    52  func TestReplayBlocks_SameSlot(t *testing.T) {
    53  	beaconDB := testDB.SetupDB(t)
    54  
    55  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
    56  	genesisBlock := blocks.NewGenesisBlock([]byte{})
    57  	bodyRoot, err := genesisBlock.Block.HashTreeRoot()
    58  	require.NoError(t, err)
    59  	err = beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
    60  		Slot:       genesisBlock.Block.Slot,
    61  		ParentRoot: genesisBlock.Block.ParentRoot,
    62  		StateRoot:  params.BeaconConfig().ZeroHash[:],
    63  		BodyRoot:   bodyRoot[:],
    64  	})
    65  	require.NoError(t, err)
    66  	require.NoError(t, beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)))
    67  	cp := beaconState.CurrentJustifiedCheckpoint()
    68  	mockRoot := [32]byte{}
    69  	copy(mockRoot[:], "hello-world")
    70  	cp.Root = mockRoot[:]
    71  	require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cp))
    72  	require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
    73  
    74  	service := New(beaconDB)
    75  	targetSlot := beaconState.Slot()
    76  	newState, err := service.ReplayBlocks(context.Background(), beaconState, []interfaces.SignedBeaconBlock{}, targetSlot)
    77  	require.NoError(t, err)
    78  	assert.Equal(t, targetSlot, newState.Slot(), "Did not advance slots")
    79  }
    80  
    81  func TestReplayBlocks_LowerSlotBlock(t *testing.T) {
    82  	beaconDB := testDB.SetupDB(t)
    83  
    84  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
    85  	require.NoError(t, beaconState.SetSlot(1))
    86  	genesisBlock := blocks.NewGenesisBlock([]byte{})
    87  	bodyRoot, err := genesisBlock.Block.HashTreeRoot()
    88  	require.NoError(t, err)
    89  	err = beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
    90  		Slot:       genesisBlock.Block.Slot,
    91  		ParentRoot: genesisBlock.Block.ParentRoot,
    92  		StateRoot:  params.BeaconConfig().ZeroHash[:],
    93  		BodyRoot:   bodyRoot[:],
    94  	})
    95  	require.NoError(t, err)
    96  	require.NoError(t, beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)))
    97  	cp := beaconState.CurrentJustifiedCheckpoint()
    98  	mockRoot := [32]byte{}
    99  	copy(mockRoot[:], "hello-world")
   100  	cp.Root = mockRoot[:]
   101  	require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cp))
   102  	require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
   103  
   104  	service := New(beaconDB)
   105  	targetSlot := beaconState.Slot()
   106  	b := testutil.NewBeaconBlock()
   107  	b.Block.Slot = beaconState.Slot() - 1
   108  	newState, err := service.ReplayBlocks(context.Background(), beaconState, []interfaces.SignedBeaconBlock{wrapper.WrappedPhase0SignedBeaconBlock(b)}, targetSlot)
   109  	require.NoError(t, err)
   110  	assert.Equal(t, targetSlot, newState.Slot(), "Did not advance slots")
   111  }
   112  
   113  func TestLoadBlocks_FirstBranch(t *testing.T) {
   114  	beaconDB := testDB.SetupDB(t)
   115  	ctx := context.Background()
   116  	s := &State{
   117  		beaconDB: beaconDB,
   118  	}
   119  
   120  	roots, savedBlocks, err := tree1(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
   121  	require.NoError(t, err)
   122  
   123  	filteredBlocks, err := s.LoadBlocks(ctx, 0, 8, roots[len(roots)-1])
   124  	require.NoError(t, err)
   125  
   126  	wanted := []*ethpb.SignedBeaconBlock{
   127  		savedBlocks[8],
   128  		savedBlocks[6],
   129  		savedBlocks[4],
   130  		savedBlocks[2],
   131  		savedBlocks[1],
   132  		savedBlocks[0],
   133  	}
   134  
   135  	for i, block := range wanted {
   136  		if !proto.Equal(block, filteredBlocks[i].Proto()) {
   137  			t.Error("Did not get wanted blocks")
   138  		}
   139  	}
   140  }
   141  
   142  func TestLoadBlocks_SecondBranch(t *testing.T) {
   143  	beaconDB := testDB.SetupDB(t)
   144  	ctx := context.Background()
   145  	s := &State{
   146  		beaconDB: beaconDB,
   147  	}
   148  
   149  	roots, savedBlocks, err := tree1(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
   150  	require.NoError(t, err)
   151  
   152  	filteredBlocks, err := s.LoadBlocks(ctx, 0, 5, roots[5])
   153  	require.NoError(t, err)
   154  
   155  	wanted := []*ethpb.SignedBeaconBlock{
   156  		savedBlocks[5],
   157  		savedBlocks[3],
   158  		savedBlocks[1],
   159  		savedBlocks[0],
   160  	}
   161  
   162  	for i, block := range wanted {
   163  		if !proto.Equal(block, filteredBlocks[i].Proto()) {
   164  			t.Error("Did not get wanted blocks")
   165  		}
   166  	}
   167  }
   168  
   169  func TestLoadBlocks_ThirdBranch(t *testing.T) {
   170  	beaconDB := testDB.SetupDB(t)
   171  	ctx := context.Background()
   172  	s := &State{
   173  		beaconDB: beaconDB,
   174  	}
   175  
   176  	roots, savedBlocks, err := tree1(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
   177  	require.NoError(t, err)
   178  
   179  	filteredBlocks, err := s.LoadBlocks(ctx, 0, 7, roots[7])
   180  	require.NoError(t, err)
   181  
   182  	wanted := []*ethpb.SignedBeaconBlock{
   183  		savedBlocks[7],
   184  		savedBlocks[6],
   185  		savedBlocks[4],
   186  		savedBlocks[2],
   187  		savedBlocks[1],
   188  		savedBlocks[0],
   189  	}
   190  
   191  	for i, block := range wanted {
   192  		if !proto.Equal(block, filteredBlocks[i].Proto()) {
   193  			t.Error("Did not get wanted blocks")
   194  		}
   195  	}
   196  }
   197  
   198  func TestLoadBlocks_SameSlots(t *testing.T) {
   199  	beaconDB := testDB.SetupDB(t)
   200  	ctx := context.Background()
   201  	s := &State{
   202  		beaconDB: beaconDB,
   203  	}
   204  
   205  	roots, savedBlocks, err := tree2(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
   206  	require.NoError(t, err)
   207  
   208  	filteredBlocks, err := s.LoadBlocks(ctx, 0, 3, roots[6])
   209  	require.NoError(t, err)
   210  
   211  	wanted := []*ethpb.SignedBeaconBlock{
   212  		savedBlocks[6],
   213  		savedBlocks[5],
   214  		savedBlocks[1],
   215  		savedBlocks[0],
   216  	}
   217  
   218  	for i, block := range wanted {
   219  		if !proto.Equal(block, filteredBlocks[i].Proto()) {
   220  			t.Error("Did not get wanted blocks")
   221  		}
   222  	}
   223  }
   224  
   225  func TestLoadBlocks_SameEndSlots(t *testing.T) {
   226  	beaconDB := testDB.SetupDB(t)
   227  	ctx := context.Background()
   228  	s := &State{
   229  		beaconDB: beaconDB,
   230  	}
   231  
   232  	roots, savedBlocks, err := tree3(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
   233  	require.NoError(t, err)
   234  
   235  	filteredBlocks, err := s.LoadBlocks(ctx, 0, 2, roots[2])
   236  	require.NoError(t, err)
   237  
   238  	wanted := []*ethpb.SignedBeaconBlock{
   239  		savedBlocks[2],
   240  		savedBlocks[1],
   241  		savedBlocks[0],
   242  	}
   243  
   244  	for i, block := range wanted {
   245  		if !proto.Equal(block, filteredBlocks[i].Proto()) {
   246  			t.Error("Did not get wanted blocks")
   247  		}
   248  	}
   249  }
   250  
   251  func TestLoadBlocks_SameEndSlotsWith2blocks(t *testing.T) {
   252  	beaconDB := testDB.SetupDB(t)
   253  	ctx := context.Background()
   254  	s := &State{
   255  		beaconDB: beaconDB,
   256  	}
   257  
   258  	roots, savedBlocks, err := tree4(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
   259  	require.NoError(t, err)
   260  
   261  	filteredBlocks, err := s.LoadBlocks(ctx, 0, 2, roots[1])
   262  	require.NoError(t, err)
   263  
   264  	wanted := []*ethpb.SignedBeaconBlock{
   265  		savedBlocks[1],
   266  		savedBlocks[0],
   267  	}
   268  
   269  	for i, block := range wanted {
   270  		if !proto.Equal(block, filteredBlocks[i].Proto()) {
   271  			t.Error("Did not get wanted blocks")
   272  		}
   273  	}
   274  }
   275  
   276  func TestLoadBlocks_BadStart(t *testing.T) {
   277  	beaconDB := testDB.SetupDB(t)
   278  	ctx := context.Background()
   279  	s := &State{
   280  		beaconDB: beaconDB,
   281  	}
   282  
   283  	roots, _, err := tree1(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
   284  	require.NoError(t, err)
   285  	_, err = s.LoadBlocks(ctx, 0, 5, roots[8])
   286  	assert.ErrorContains(t, "end block roots don't match", err)
   287  }
   288  
   289  func TestLastSavedBlock_Genesis(t *testing.T) {
   290  	beaconDB := testDB.SetupDB(t)
   291  	ctx := context.Background()
   292  	s := &State{
   293  		beaconDB:      beaconDB,
   294  		finalizedInfo: &finalizedInfo{slot: 128},
   295  	}
   296  
   297  	gBlk := testutil.NewBeaconBlock()
   298  	gRoot, err := gBlk.Block.HashTreeRoot()
   299  	require.NoError(t, err)
   300  	require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(gBlk)))
   301  	require.NoError(t, s.beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   302  
   303  	savedRoot, savedSlot, err := s.lastSavedBlock(ctx, 0)
   304  	require.NoError(t, err)
   305  	assert.Equal(t, types.Slot(0), savedSlot, "Did not save genesis slot")
   306  	assert.Equal(t, savedRoot, savedRoot, "Did not save genesis root")
   307  }
   308  
   309  func TestLastSavedBlock_CanGet(t *testing.T) {
   310  	beaconDB := testDB.SetupDB(t)
   311  	ctx := context.Background()
   312  	s := &State{
   313  		beaconDB:      beaconDB,
   314  		finalizedInfo: &finalizedInfo{slot: 128},
   315  	}
   316  
   317  	b1 := testutil.NewBeaconBlock()
   318  	b1.Block.Slot = s.finalizedInfo.slot + 5
   319  	require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1)))
   320  	b2 := testutil.NewBeaconBlock()
   321  	b2.Block.Slot = s.finalizedInfo.slot + 10
   322  	require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2)))
   323  	b3 := testutil.NewBeaconBlock()
   324  	b3.Block.Slot = s.finalizedInfo.slot + 20
   325  	require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3)))
   326  
   327  	savedRoot, savedSlot, err := s.lastSavedBlock(ctx, s.finalizedInfo.slot+100)
   328  	require.NoError(t, err)
   329  	assert.Equal(t, s.finalizedInfo.slot+20, savedSlot)
   330  	wantedRoot, err := b3.Block.HashTreeRoot()
   331  	require.NoError(t, err)
   332  	assert.Equal(t, wantedRoot, savedRoot, "Did not save correct root")
   333  }
   334  
   335  func TestLastSavedBlock_NoSavedBlock(t *testing.T) {
   336  	beaconDB := testDB.SetupDB(t)
   337  	ctx := context.Background()
   338  	s := &State{
   339  		beaconDB:      beaconDB,
   340  		finalizedInfo: &finalizedInfo{slot: 128},
   341  	}
   342  
   343  	root, slot, err := s.lastSavedBlock(ctx, s.finalizedInfo.slot+1)
   344  	require.NoError(t, err)
   345  	if slot != 0 && root != [32]byte{} {
   346  		t.Error("Did not get wanted block")
   347  	}
   348  }
   349  
   350  func TestLastSavedState_Genesis(t *testing.T) {
   351  	beaconDB := testDB.SetupDB(t)
   352  	ctx := context.Background()
   353  	s := &State{
   354  		beaconDB:      beaconDB,
   355  		finalizedInfo: &finalizedInfo{slot: 128},
   356  	}
   357  
   358  	gBlk := testutil.NewBeaconBlock()
   359  	gState, err := testutil.NewBeaconState()
   360  	require.NoError(t, err)
   361  	gRoot, err := gBlk.Block.HashTreeRoot()
   362  	require.NoError(t, err)
   363  	require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(gBlk)))
   364  	require.NoError(t, s.beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   365  	require.NoError(t, s.beaconDB.SaveState(ctx, gState, gRoot))
   366  
   367  	savedState, err := s.lastSavedState(ctx, 0)
   368  	require.NoError(t, err)
   369  	require.DeepSSZEqual(t, gState.InnerStateUnsafe(), savedState.InnerStateUnsafe())
   370  }
   371  
   372  func TestLastSavedState_CanGet(t *testing.T) {
   373  	beaconDB := testDB.SetupDB(t)
   374  	ctx := context.Background()
   375  	s := &State{
   376  		beaconDB:      beaconDB,
   377  		finalizedInfo: &finalizedInfo{slot: 128},
   378  	}
   379  
   380  	b1 := testutil.NewBeaconBlock()
   381  	b1.Block.Slot = s.finalizedInfo.slot + 5
   382  	require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1)))
   383  	b2 := testutil.NewBeaconBlock()
   384  	b2.Block.Slot = s.finalizedInfo.slot + 10
   385  	require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2)))
   386  	b2Root, err := b2.Block.HashTreeRoot()
   387  	require.NoError(t, err)
   388  	st, err := testutil.NewBeaconState()
   389  	require.NoError(t, err)
   390  	require.NoError(t, st.SetSlot(s.finalizedInfo.slot+10))
   391  
   392  	require.NoError(t, s.beaconDB.SaveState(ctx, st, b2Root))
   393  	b3 := testutil.NewBeaconBlock()
   394  	b3.Block.Slot = s.finalizedInfo.slot + 20
   395  	require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3)))
   396  
   397  	savedState, err := s.lastSavedState(ctx, s.finalizedInfo.slot+100)
   398  	require.NoError(t, err)
   399  	require.DeepSSZEqual(t, st.InnerStateUnsafe(), savedState.InnerStateUnsafe())
   400  }
   401  
   402  func TestLastSavedState_NoSavedBlockState(t *testing.T) {
   403  	beaconDB := testDB.SetupDB(t)
   404  	ctx := context.Background()
   405  	s := &State{
   406  		beaconDB:      beaconDB,
   407  		finalizedInfo: &finalizedInfo{slot: 128},
   408  	}
   409  
   410  	b1 := testutil.NewBeaconBlock()
   411  	b1.Block.Slot = 127
   412  	require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1)))
   413  
   414  	_, err := s.lastSavedState(ctx, s.finalizedInfo.slot+1)
   415  	assert.ErrorContains(t, errUnknownState.Error(), err)
   416  }
   417  
   418  // tree1 constructs the following tree:
   419  // B0 - B1 - - B3 -- B5
   420  //        \- B2 -- B4 -- B6 ----- B8
   421  //                         \- B7
   422  func tree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
   423  	b0 := testutil.NewBeaconBlock()
   424  	b0.Block.Slot = 0
   425  	b0.Block.ParentRoot = genesisRoot
   426  	r0, err := b0.Block.HashTreeRoot()
   427  	if err != nil {
   428  		return nil, nil, err
   429  	}
   430  	b1 := testutil.NewBeaconBlock()
   431  	b1.Block.Slot = 1
   432  	b1.Block.ParentRoot = r0[:]
   433  	r1, err := b1.Block.HashTreeRoot()
   434  	if err != nil {
   435  		return nil, nil, err
   436  	}
   437  	b2 := testutil.NewBeaconBlock()
   438  	b2.Block.Slot = 2
   439  	b2.Block.ParentRoot = r1[:]
   440  	r2, err := b2.Block.HashTreeRoot()
   441  	if err != nil {
   442  		return nil, nil, err
   443  	}
   444  	b3 := testutil.NewBeaconBlock()
   445  	b3.Block.Slot = 3
   446  	b3.Block.ParentRoot = r1[:]
   447  	r3, err := b3.Block.HashTreeRoot()
   448  	if err != nil {
   449  		return nil, nil, err
   450  	}
   451  	b4 := testutil.NewBeaconBlock()
   452  	b4.Block.Slot = 4
   453  	b4.Block.ParentRoot = r2[:]
   454  	r4, err := b4.Block.HashTreeRoot()
   455  	if err != nil {
   456  		return nil, nil, err
   457  	}
   458  	b5 := testutil.NewBeaconBlock()
   459  	b5.Block.Slot = 5
   460  	b5.Block.ParentRoot = r3[:]
   461  	r5, err := b5.Block.HashTreeRoot()
   462  	if err != nil {
   463  		return nil, nil, err
   464  	}
   465  	b6 := testutil.NewBeaconBlock()
   466  	b6.Block.Slot = 6
   467  	b6.Block.ParentRoot = r4[:]
   468  	r6, err := b6.Block.HashTreeRoot()
   469  	if err != nil {
   470  		return nil, nil, err
   471  	}
   472  	b7 := testutil.NewBeaconBlock()
   473  	b7.Block.Slot = 7
   474  	b7.Block.ParentRoot = r6[:]
   475  	r7, err := b7.Block.HashTreeRoot()
   476  	if err != nil {
   477  		return nil, nil, err
   478  	}
   479  	b8 := testutil.NewBeaconBlock()
   480  	b8.Block.Slot = 8
   481  	b8.Block.ParentRoot = r6[:]
   482  	r8, err := b8.Block.HashTreeRoot()
   483  	if err != nil {
   484  		return nil, nil, err
   485  	}
   486  	st, err := testutil.NewBeaconState()
   487  	require.NoError(t, err)
   488  
   489  	returnedBlocks := make([]*ethpb.SignedBeaconBlock, 0)
   490  	for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b2, b3, b4, b5, b6, b7, b8} {
   491  		beaconBlock := testutil.NewBeaconBlock()
   492  		beaconBlock.Block.Slot = b.Block.Slot
   493  		beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
   494  		if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil {
   495  			return nil, nil, err
   496  		}
   497  		if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
   498  			return nil, nil, err
   499  		}
   500  		returnedBlocks = append(returnedBlocks, beaconBlock)
   501  	}
   502  	return [][32]byte{r0, r1, r2, r3, r4, r5, r6, r7, r8}, returnedBlocks, nil
   503  }
   504  
   505  // tree2 constructs the following tree:
   506  // B0 - B1
   507  //        \- B2
   508  //        \- B2
   509  //        \- B2
   510  //        \- B2 -- B3
   511  func tree2(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
   512  	b0 := testutil.NewBeaconBlock()
   513  	b0.Block.Slot = 0
   514  	b0.Block.ParentRoot = genesisRoot
   515  	r0, err := b0.Block.HashTreeRoot()
   516  	if err != nil {
   517  		return nil, nil, err
   518  	}
   519  	b1 := testutil.NewBeaconBlock()
   520  	b1.Block.Slot = 1
   521  	b1.Block.ParentRoot = r0[:]
   522  	r1, err := b1.Block.HashTreeRoot()
   523  	if err != nil {
   524  		return nil, nil, err
   525  	}
   526  	b21 := testutil.NewBeaconBlock()
   527  	b21.Block.Slot = 2
   528  	b21.Block.ParentRoot = r1[:]
   529  	b21.Block.StateRoot = bytesutil.PadTo([]byte{'A'}, 32)
   530  	r21, err := b21.Block.HashTreeRoot()
   531  	if err != nil {
   532  		return nil, nil, err
   533  	}
   534  	b22 := testutil.NewBeaconBlock()
   535  	b22.Block.Slot = 2
   536  	b22.Block.ParentRoot = r1[:]
   537  	b22.Block.StateRoot = bytesutil.PadTo([]byte{'B'}, 32)
   538  	r22, err := b22.Block.HashTreeRoot()
   539  	if err != nil {
   540  		return nil, nil, err
   541  	}
   542  	b23 := testutil.NewBeaconBlock()
   543  	b23.Block.Slot = 2
   544  	b23.Block.ParentRoot = r1[:]
   545  	b23.Block.StateRoot = bytesutil.PadTo([]byte{'C'}, 32)
   546  	r23, err := b23.Block.HashTreeRoot()
   547  	if err != nil {
   548  		return nil, nil, err
   549  	}
   550  	b24 := testutil.NewBeaconBlock()
   551  	b24.Block.Slot = 2
   552  	b24.Block.ParentRoot = r1[:]
   553  	b24.Block.StateRoot = bytesutil.PadTo([]byte{'D'}, 32)
   554  	r24, err := b24.Block.HashTreeRoot()
   555  	if err != nil {
   556  		return nil, nil, err
   557  	}
   558  	b3 := testutil.NewBeaconBlock()
   559  	b3.Block.Slot = 3
   560  	b3.Block.ParentRoot = r24[:]
   561  	r3, err := b3.Block.HashTreeRoot()
   562  	if err != nil {
   563  		return nil, nil, err
   564  	}
   565  	st, err := testutil.NewBeaconState()
   566  	require.NoError(t, err)
   567  
   568  	returnedBlocks := make([]*ethpb.SignedBeaconBlock, 0)
   569  	for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b21, b22, b23, b24, b3} {
   570  		beaconBlock := testutil.NewBeaconBlock()
   571  		beaconBlock.Block.Slot = b.Block.Slot
   572  		beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
   573  		beaconBlock.Block.StateRoot = bytesutil.PadTo(b.Block.StateRoot, 32)
   574  		if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil {
   575  			return nil, nil, err
   576  		}
   577  		if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
   578  			return nil, nil, err
   579  		}
   580  		returnedBlocks = append(returnedBlocks, beaconBlock)
   581  	}
   582  	return [][32]byte{r0, r1, r21, r22, r23, r24, r3}, returnedBlocks, nil
   583  }
   584  
   585  // tree3 constructs the following tree:
   586  // B0 - B1
   587  //        \- B2
   588  //        \- B2
   589  //        \- B2
   590  //        \- B2
   591  func tree3(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
   592  	b0 := testutil.NewBeaconBlock()
   593  	b0.Block.Slot = 0
   594  	b0.Block.ParentRoot = genesisRoot
   595  	r0, err := b0.Block.HashTreeRoot()
   596  	if err != nil {
   597  		return nil, nil, err
   598  	}
   599  	b1 := testutil.NewBeaconBlock()
   600  	b1.Block.Slot = 1
   601  	b1.Block.ParentRoot = r0[:]
   602  	r1, err := b1.Block.HashTreeRoot()
   603  	if err != nil {
   604  		return nil, nil, err
   605  	}
   606  	b21 := testutil.NewBeaconBlock()
   607  	b21.Block.Slot = 2
   608  	b21.Block.ParentRoot = r1[:]
   609  	b21.Block.StateRoot = bytesutil.PadTo([]byte{'A'}, 32)
   610  	r21, err := b21.Block.HashTreeRoot()
   611  	if err != nil {
   612  		return nil, nil, err
   613  	}
   614  	b22 := testutil.NewBeaconBlock()
   615  	b22.Block.Slot = 2
   616  	b22.Block.ParentRoot = r1[:]
   617  	b22.Block.StateRoot = bytesutil.PadTo([]byte{'B'}, 32)
   618  	r22, err := b22.Block.HashTreeRoot()
   619  	if err != nil {
   620  		return nil, nil, err
   621  	}
   622  	b23 := testutil.NewBeaconBlock()
   623  	b23.Block.Slot = 2
   624  	b23.Block.ParentRoot = r1[:]
   625  	b23.Block.StateRoot = bytesutil.PadTo([]byte{'C'}, 32)
   626  	r23, err := b23.Block.HashTreeRoot()
   627  	if err != nil {
   628  		return nil, nil, err
   629  	}
   630  	b24 := testutil.NewBeaconBlock()
   631  	b24.Block.Slot = 2
   632  	b24.Block.ParentRoot = r1[:]
   633  	b24.Block.StateRoot = bytesutil.PadTo([]byte{'D'}, 32)
   634  	r24, err := b24.Block.HashTreeRoot()
   635  	if err != nil {
   636  		return nil, nil, err
   637  	}
   638  	st, err := testutil.NewBeaconState()
   639  	require.NoError(t, err)
   640  
   641  	returnedBlocks := make([]*ethpb.SignedBeaconBlock, 0)
   642  	for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b21, b22, b23, b24} {
   643  		beaconBlock := testutil.NewBeaconBlock()
   644  		beaconBlock.Block.Slot = b.Block.Slot
   645  		beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
   646  		beaconBlock.Block.StateRoot = bytesutil.PadTo(b.Block.StateRoot, 32)
   647  		if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil {
   648  			return nil, nil, err
   649  		}
   650  		if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
   651  			return nil, nil, err
   652  		}
   653  		returnedBlocks = append(returnedBlocks, beaconBlock)
   654  	}
   655  
   656  	return [][32]byte{r0, r1, r21, r22, r23, r24}, returnedBlocks, nil
   657  }
   658  
   659  // tree4 constructs the following tree:
   660  // B0
   661  //   \- B2
   662  //   \- B2
   663  //   \- B2
   664  //   \- B2
   665  func tree4(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
   666  	b0 := testutil.NewBeaconBlock()
   667  	b0.Block.Slot = 0
   668  	b0.Block.ParentRoot = genesisRoot
   669  	r0, err := b0.Block.HashTreeRoot()
   670  	if err != nil {
   671  		return nil, nil, err
   672  	}
   673  	b21 := testutil.NewBeaconBlock()
   674  	b21.Block.Slot = 2
   675  	b21.Block.ParentRoot = r0[:]
   676  	b21.Block.StateRoot = bytesutil.PadTo([]byte{'A'}, 32)
   677  	r21, err := b21.Block.HashTreeRoot()
   678  	if err != nil {
   679  		return nil, nil, err
   680  	}
   681  	b22 := testutil.NewBeaconBlock()
   682  	b22.Block.Slot = 2
   683  	b22.Block.ParentRoot = r0[:]
   684  	b22.Block.StateRoot = bytesutil.PadTo([]byte{'B'}, 32)
   685  	r22, err := b22.Block.HashTreeRoot()
   686  	if err != nil {
   687  		return nil, nil, err
   688  	}
   689  	b23 := testutil.NewBeaconBlock()
   690  	b23.Block.Slot = 2
   691  	b23.Block.ParentRoot = r0[:]
   692  	b23.Block.StateRoot = bytesutil.PadTo([]byte{'C'}, 32)
   693  	r23, err := b23.Block.HashTreeRoot()
   694  	if err != nil {
   695  		return nil, nil, err
   696  	}
   697  	b24 := testutil.NewBeaconBlock()
   698  	b24.Block.Slot = 2
   699  	b24.Block.ParentRoot = r0[:]
   700  	b24.Block.StateRoot = bytesutil.PadTo([]byte{'D'}, 32)
   701  	r24, err := b24.Block.HashTreeRoot()
   702  	if err != nil {
   703  		return nil, nil, err
   704  	}
   705  	st, err := testutil.NewBeaconState()
   706  	require.NoError(t, err)
   707  
   708  	returnedBlocks := make([]*ethpb.SignedBeaconBlock, 0)
   709  	for _, b := range []*ethpb.SignedBeaconBlock{b0, b21, b22, b23, b24} {
   710  		beaconBlock := testutil.NewBeaconBlock()
   711  		beaconBlock.Block.Slot = b.Block.Slot
   712  		beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
   713  		beaconBlock.Block.StateRoot = bytesutil.PadTo(b.Block.StateRoot, 32)
   714  		if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil {
   715  			return nil, nil, err
   716  		}
   717  		if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
   718  			return nil, nil, err
   719  		}
   720  		returnedBlocks = append(returnedBlocks, beaconBlock)
   721  	}
   722  
   723  	return [][32]byte{r0, r21, r22, r23, r24}, returnedBlocks, nil
   724  }
   725  
   726  func TestLoadFinalizedBlocks(t *testing.T) {
   727  	beaconDB := testDB.SetupDB(t)
   728  	ctx := context.Background()
   729  	s := &State{
   730  		beaconDB: beaconDB,
   731  	}
   732  	gBlock := testutil.NewBeaconBlock()
   733  	gRoot, err := gBlock.Block.HashTreeRoot()
   734  	require.NoError(t, err)
   735  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(gBlock)))
   736  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, [32]byte{}))
   737  	roots, _, err := tree1(t, beaconDB, gRoot[:])
   738  	require.NoError(t, err)
   739  
   740  	filteredBlocks, err := s.loadFinalizedBlocks(ctx, 0, 8)
   741  	require.NoError(t, err)
   742  	require.Equal(t, 0, len(filteredBlocks))
   743  	require.NoError(t, beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: roots[8][:]}))
   744  
   745  	require.NoError(t, s.beaconDB.SaveFinalizedCheckpoint(ctx, &ethpb.Checkpoint{Root: roots[8][:]}))
   746  	filteredBlocks, err = s.loadFinalizedBlocks(ctx, 0, 8)
   747  	require.NoError(t, err)
   748  	require.Equal(t, 10, len(filteredBlocks))
   749  }