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

     1  package blockchain
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"testing"
     7  	"time"
     8  
     9  	types "github.com/prysmaticlabs/eth2-types"
    10  	mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
    11  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    12  	testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
    13  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    14  	ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
    15  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    16  	"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
    17  	"github.com/prysmaticlabs/prysm/shared/featureconfig"
    18  	"github.com/prysmaticlabs/prysm/shared/params"
    19  	"github.com/prysmaticlabs/prysm/shared/testutil"
    20  	"github.com/prysmaticlabs/prysm/shared/testutil/assert"
    21  	"github.com/prysmaticlabs/prysm/shared/testutil/require"
    22  	logTest "github.com/sirupsen/logrus/hooks/test"
    23  )
    24  
    25  func TestSaveHead_Same(t *testing.T) {
    26  	beaconDB := testDB.SetupDB(t)
    27  	service := setupBeaconChain(t, beaconDB)
    28  
    29  	r := [32]byte{'A'}
    30  	service.head = &head{slot: 0, root: r}
    31  
    32  	require.NoError(t, service.saveHead(context.Background(), r))
    33  	assert.Equal(t, types.Slot(0), service.headSlot(), "Head did not stay the same")
    34  	assert.Equal(t, r, service.headRoot(), "Head did not stay the same")
    35  }
    36  
    37  func TestSaveHead_Different(t *testing.T) {
    38  	ctx := context.Background()
    39  	beaconDB := testDB.SetupDB(t)
    40  	service := setupBeaconChain(t, beaconDB)
    41  
    42  	testutil.NewBeaconBlock()
    43  	oldBlock := wrapper.WrappedPhase0SignedBeaconBlock(
    44  		testutil.NewBeaconBlock(),
    45  	)
    46  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), oldBlock))
    47  	oldRoot, err := oldBlock.Block().HashTreeRoot()
    48  	require.NoError(t, err)
    49  	service.head = &head{
    50  		slot:  0,
    51  		root:  oldRoot,
    52  		block: oldBlock,
    53  	}
    54  
    55  	newHeadSignedBlock := testutil.NewBeaconBlock()
    56  	newHeadSignedBlock.Block.Slot = 1
    57  	newHeadBlock := newHeadSignedBlock.Block
    58  
    59  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(newHeadSignedBlock)))
    60  	newRoot, err := newHeadBlock.HashTreeRoot()
    61  	require.NoError(t, err)
    62  	headState, err := testutil.NewBeaconState()
    63  	require.NoError(t, err)
    64  	require.NoError(t, headState.SetSlot(1))
    65  	require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}))
    66  	require.NoError(t, service.cfg.BeaconDB.SaveState(context.Background(), headState, newRoot))
    67  	require.NoError(t, service.saveHead(context.Background(), newRoot))
    68  
    69  	assert.Equal(t, types.Slot(1), service.HeadSlot(), "Head did not change")
    70  
    71  	cachedRoot, err := service.HeadRoot(context.Background())
    72  	require.NoError(t, err)
    73  	assert.DeepEqual(t, cachedRoot, newRoot[:], "Head did not change")
    74  	assert.DeepEqual(t, newHeadSignedBlock, service.headBlock().Proto(), "Head did not change")
    75  	assert.DeepSSZEqual(t, headState.CloneInnerState(), service.headState(ctx).CloneInnerState(), "Head did not change")
    76  }
    77  
    78  func TestSaveHead_Different_Reorg(t *testing.T) {
    79  	ctx := context.Background()
    80  	hook := logTest.NewGlobal()
    81  	beaconDB := testDB.SetupDB(t)
    82  	service := setupBeaconChain(t, beaconDB)
    83  
    84  	oldBlock := wrapper.WrappedPhase0SignedBeaconBlock(
    85  		testutil.NewBeaconBlock(),
    86  	)
    87  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), oldBlock))
    88  	oldRoot, err := oldBlock.Block().HashTreeRoot()
    89  	require.NoError(t, err)
    90  	service.head = &head{
    91  		slot:  0,
    92  		root:  oldRoot,
    93  		block: oldBlock,
    94  	}
    95  
    96  	reorgChainParent := [32]byte{'B'}
    97  	newHeadSignedBlock := testutil.NewBeaconBlock()
    98  	newHeadSignedBlock.Block.Slot = 1
    99  	newHeadSignedBlock.Block.ParentRoot = reorgChainParent[:]
   100  	newHeadBlock := newHeadSignedBlock.Block
   101  
   102  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(newHeadSignedBlock)))
   103  	newRoot, err := newHeadBlock.HashTreeRoot()
   104  	require.NoError(t, err)
   105  	headState, err := testutil.NewBeaconState()
   106  	require.NoError(t, err)
   107  	require.NoError(t, headState.SetSlot(1))
   108  	require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}))
   109  	require.NoError(t, service.cfg.BeaconDB.SaveState(context.Background(), headState, newRoot))
   110  	require.NoError(t, service.saveHead(context.Background(), newRoot))
   111  
   112  	assert.Equal(t, types.Slot(1), service.HeadSlot(), "Head did not change")
   113  
   114  	cachedRoot, err := service.HeadRoot(context.Background())
   115  	require.NoError(t, err)
   116  	if !bytes.Equal(cachedRoot, newRoot[:]) {
   117  		t.Error("Head did not change")
   118  	}
   119  	assert.DeepEqual(t, newHeadSignedBlock, service.headBlock().Proto(), "Head did not change")
   120  	assert.DeepSSZEqual(t, headState.CloneInnerState(), service.headState(ctx).CloneInnerState(), "Head did not change")
   121  	require.LogsContain(t, hook, "Chain reorg occurred")
   122  }
   123  
   124  func TestCacheJustifiedStateBalances_CanCache(t *testing.T) {
   125  	beaconDB := testDB.SetupDB(t)
   126  	service := setupBeaconChain(t, beaconDB)
   127  
   128  	state, _ := testutil.DeterministicGenesisState(t, 100)
   129  	r := [32]byte{'a'}
   130  	require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Root: r[:]}))
   131  	require.NoError(t, service.cfg.BeaconDB.SaveState(context.Background(), state, r))
   132  	require.NoError(t, service.cacheJustifiedStateBalances(context.Background(), r))
   133  	require.DeepEqual(t, service.getJustifiedBalances(), state.Balances(), "Incorrect justified balances")
   134  }
   135  
   136  func TestUpdateHead_MissingJustifiedRoot(t *testing.T) {
   137  	beaconDB := testDB.SetupDB(t)
   138  	service := setupBeaconChain(t, beaconDB)
   139  
   140  	b := testutil.NewBeaconBlock()
   141  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b)))
   142  	r, err := b.Block.HashTreeRoot()
   143  	require.NoError(t, err)
   144  
   145  	service.justifiedCheckpt = &ethpb.Checkpoint{Root: r[:]}
   146  	service.finalizedCheckpt = &ethpb.Checkpoint{}
   147  	service.bestJustifiedCheckpt = &ethpb.Checkpoint{}
   148  
   149  	require.NoError(t, service.updateHead(context.Background(), []uint64{}))
   150  }
   151  
   152  func Test_notifyNewHeadEvent(t *testing.T) {
   153  	t.Run("genesis_state_root", func(t *testing.T) {
   154  		bState, _ := testutil.DeterministicGenesisState(t, 10)
   155  		notifier := &mock.MockStateNotifier{RecordEvents: true}
   156  		srv := &Service{
   157  			cfg: &Config{
   158  				StateNotifier: notifier,
   159  			},
   160  			genesisRoot: [32]byte{1},
   161  		}
   162  		newHeadStateRoot := [32]byte{2}
   163  		newHeadRoot := [32]byte{3}
   164  		err := srv.notifyNewHeadEvent(1, bState, newHeadStateRoot[:], newHeadRoot[:])
   165  		require.NoError(t, err)
   166  		events := notifier.ReceivedEvents()
   167  		require.Equal(t, 1, len(events))
   168  
   169  		eventHead, ok := events[0].Data.(*ethpbv1.EventHead)
   170  		require.Equal(t, true, ok)
   171  		wanted := &ethpbv1.EventHead{
   172  			Slot:                      1,
   173  			Block:                     newHeadRoot[:],
   174  			State:                     newHeadStateRoot[:],
   175  			EpochTransition:           false,
   176  			PreviousDutyDependentRoot: srv.genesisRoot[:],
   177  			CurrentDutyDependentRoot:  srv.genesisRoot[:],
   178  		}
   179  		require.DeepSSZEqual(t, wanted, eventHead)
   180  	})
   181  	t.Run("non_genesis_values", func(t *testing.T) {
   182  		bState, _ := testutil.DeterministicGenesisState(t, 10)
   183  		notifier := &mock.MockStateNotifier{RecordEvents: true}
   184  		genesisRoot := [32]byte{1}
   185  		srv := &Service{
   186  			cfg: &Config{
   187  				StateNotifier: notifier,
   188  			},
   189  			genesisRoot: genesisRoot,
   190  		}
   191  		epoch1Start, err := helpers.StartSlot(1)
   192  		require.NoError(t, err)
   193  		epoch2Start, err := helpers.StartSlot(1)
   194  		require.NoError(t, err)
   195  		require.NoError(t, bState.SetSlot(epoch1Start))
   196  
   197  		newHeadStateRoot := [32]byte{2}
   198  		newHeadRoot := [32]byte{3}
   199  		err = srv.notifyNewHeadEvent(epoch2Start, bState, newHeadStateRoot[:], newHeadRoot[:])
   200  		require.NoError(t, err)
   201  		events := notifier.ReceivedEvents()
   202  		require.Equal(t, 1, len(events))
   203  
   204  		eventHead, ok := events[0].Data.(*ethpbv1.EventHead)
   205  		require.Equal(t, true, ok)
   206  		wanted := &ethpbv1.EventHead{
   207  			Slot:                      epoch2Start,
   208  			Block:                     newHeadRoot[:],
   209  			State:                     newHeadStateRoot[:],
   210  			EpochTransition:           false,
   211  			PreviousDutyDependentRoot: genesisRoot[:],
   212  			CurrentDutyDependentRoot:  make([]byte, 32),
   213  		}
   214  		require.DeepSSZEqual(t, wanted, eventHead)
   215  	})
   216  }
   217  
   218  func TestSaveOrphanedAtts(t *testing.T) {
   219  	resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{
   220  		CorrectlyInsertOrphanedAtts: true,
   221  	})
   222  	defer resetCfg()
   223  
   224  	genesis, keys := testutil.DeterministicGenesisState(t, 64)
   225  	b, err := testutil.GenerateFullBlock(genesis, keys, testutil.DefaultBlockGenConfig(), 1)
   226  	assert.NoError(t, err)
   227  	r, err := b.Block.HashTreeRoot()
   228  	require.NoError(t, err)
   229  
   230  	ctx := context.Background()
   231  	beaconDB := testDB.SetupDB(t)
   232  	service := setupBeaconChain(t, beaconDB)
   233  	service.genesisTime = time.Now()
   234  
   235  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
   236  	require.NoError(t, service.saveOrphanedAtts(ctx, r))
   237  
   238  	require.Equal(t, len(b.Block.Body.Attestations), service.cfg.AttPool.AggregatedAttestationCount())
   239  	savedAtts := service.cfg.AttPool.AggregatedAttestations()
   240  	atts := b.Block.Body.Attestations
   241  	require.DeepSSZEqual(t, atts, savedAtts)
   242  }
   243  
   244  func TestSaveOrphanedAtts_CanFilter(t *testing.T) {
   245  	resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{
   246  		CorrectlyInsertOrphanedAtts: true,
   247  	})
   248  	defer resetCfg()
   249  
   250  	genesis, keys := testutil.DeterministicGenesisState(t, 64)
   251  	b, err := testutil.GenerateFullBlock(genesis, keys, testutil.DefaultBlockGenConfig(), 1)
   252  	assert.NoError(t, err)
   253  	r, err := b.Block.HashTreeRoot()
   254  	require.NoError(t, err)
   255  
   256  	ctx := context.Background()
   257  	beaconDB := testDB.SetupDB(t)
   258  	service := setupBeaconChain(t, beaconDB)
   259  	service.genesisTime = time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SlotsPerEpoch+1)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
   260  
   261  	require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
   262  	require.NoError(t, service.saveOrphanedAtts(ctx, r))
   263  
   264  	require.Equal(t, 0, service.cfg.AttPool.AggregatedAttestationCount())
   265  	savedAtts := service.cfg.AttPool.AggregatedAttestations()
   266  	atts := b.Block.Body.Attestations
   267  	require.DeepNotSSZEqual(t, atts, savedAtts)
   268  }