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

     1  package stategen
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
     8  	"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
     9  	"github.com/prysmaticlabs/prysm/shared/params"
    10  	"github.com/prysmaticlabs/prysm/shared/testutil"
    11  	"github.com/prysmaticlabs/prysm/shared/testutil/assert"
    12  	"github.com/prysmaticlabs/prysm/shared/testutil/require"
    13  	logTest "github.com/sirupsen/logrus/hooks/test"
    14  )
    15  
    16  func TestSaveState_HotStateCanBeSaved(t *testing.T) {
    17  	ctx := context.Background()
    18  	beaconDB := testDB.SetupDB(t)
    19  
    20  	service := New(beaconDB)
    21  	service.slotsPerArchivedPoint = 1
    22  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
    23  	// This goes to hot section, verify it can save on epoch boundary.
    24  	require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch))
    25  
    26  	r := [32]byte{'a'}
    27  	require.NoError(t, service.SaveState(ctx, r, beaconState))
    28  
    29  	// Should save both state and state summary.
    30  	_, ok, err := service.epochBoundaryStateCache.getByRoot(r)
    31  	require.NoError(t, err)
    32  	assert.Equal(t, true, ok, "Should have saved the state")
    33  	assert.Equal(t, true, service.beaconDB.HasStateSummary(ctx, r), "Should have saved the state summary")
    34  }
    35  
    36  func TestSaveState_HotStateCached(t *testing.T) {
    37  	hook := logTest.NewGlobal()
    38  	ctx := context.Background()
    39  	beaconDB := testDB.SetupDB(t)
    40  
    41  	service := New(beaconDB)
    42  	service.slotsPerArchivedPoint = 1
    43  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
    44  	require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch))
    45  
    46  	// Cache the state prior.
    47  	r := [32]byte{'a'}
    48  	service.hotStateCache.put(r, beaconState)
    49  	require.NoError(t, service.SaveState(ctx, r, beaconState))
    50  
    51  	// Should not save the state and state summary.
    52  	assert.Equal(t, false, service.beaconDB.HasState(ctx, r), "Should not have saved the state")
    53  	assert.Equal(t, false, service.beaconDB.HasStateSummary(ctx, r), "Should have saved the state summary")
    54  	require.LogsDoNotContain(t, hook, "Saved full state on epoch boundary")
    55  }
    56  
    57  func TestState_ForceCheckpoint_SavesStateToDatabase(t *testing.T) {
    58  	ctx := context.Background()
    59  	beaconDB := testDB.SetupDB(t)
    60  
    61  	svc := New(beaconDB)
    62  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
    63  	require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch))
    64  
    65  	r := [32]byte{'a'}
    66  	svc.hotStateCache.put(r, beaconState)
    67  
    68  	require.Equal(t, false, beaconDB.HasState(ctx, r), "Database has state stored already")
    69  	assert.NoError(t, svc.ForceCheckpoint(ctx, r[:]))
    70  	assert.Equal(t, true, beaconDB.HasState(ctx, r), "Did not save checkpoint to database")
    71  
    72  	// Should not panic with genesis finalized root.
    73  	assert.NoError(t, svc.ForceCheckpoint(ctx, params.BeaconConfig().ZeroHash[:]))
    74  }
    75  
    76  func TestSaveState_Alreadyhas(t *testing.T) {
    77  	hook := logTest.NewGlobal()
    78  	ctx := context.Background()
    79  	beaconDB := testDB.SetupDB(t)
    80  	service := New(beaconDB)
    81  
    82  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
    83  	require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch))
    84  	r := [32]byte{'A'}
    85  
    86  	// Pre cache the hot state.
    87  	service.hotStateCache.put(r, beaconState)
    88  	require.NoError(t, service.saveStateByRoot(ctx, r, beaconState))
    89  
    90  	// Should not save the state and state summary.
    91  	assert.Equal(t, false, service.beaconDB.HasState(ctx, r), "Should not have saved the state")
    92  	assert.Equal(t, false, service.beaconDB.HasStateSummary(ctx, r), "Should have saved the state summary")
    93  	require.LogsDoNotContain(t, hook, "Saved full state on epoch boundary")
    94  }
    95  
    96  func TestSaveState_CanSaveOnEpochBoundary(t *testing.T) {
    97  	ctx := context.Background()
    98  	beaconDB := testDB.SetupDB(t)
    99  	service := New(beaconDB)
   100  
   101  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
   102  	require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch))
   103  	r := [32]byte{'A'}
   104  
   105  	require.NoError(t, service.saveStateByRoot(ctx, r, beaconState))
   106  
   107  	// Should save both state and state summary.
   108  	_, ok, err := service.epochBoundaryStateCache.getByRoot(r)
   109  	require.NoError(t, err)
   110  	require.Equal(t, true, ok, "Did not save epoch boundary state")
   111  	assert.Equal(t, true, service.beaconDB.HasStateSummary(ctx, r), "Should have saved the state summary")
   112  	// Should have not been saved in DB.
   113  	require.Equal(t, false, beaconDB.HasState(ctx, r))
   114  }
   115  
   116  func TestSaveState_NoSaveNotEpochBoundary(t *testing.T) {
   117  	hook := logTest.NewGlobal()
   118  	ctx := context.Background()
   119  	beaconDB := testDB.SetupDB(t)
   120  	service := New(beaconDB)
   121  
   122  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
   123  	require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch-1))
   124  	r := [32]byte{'A'}
   125  	b := testutil.NewBeaconBlock()
   126  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
   127  	gRoot, err := b.Block.HashTreeRoot()
   128  	require.NoError(t, err)
   129  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   130  	require.NoError(t, service.SaveState(ctx, r, beaconState))
   131  
   132  	// Should only save state summary.
   133  	assert.Equal(t, false, service.beaconDB.HasState(ctx, r), "Should not have saved the state")
   134  	assert.Equal(t, true, service.beaconDB.HasStateSummary(ctx, r), "Should have saved the state summary")
   135  	require.LogsDoNotContain(t, hook, "Saved full state on epoch boundary")
   136  	// Should have not been saved in DB.
   137  	require.Equal(t, false, beaconDB.HasState(ctx, r))
   138  }
   139  
   140  func TestSaveState_CanSaveHotStateToDB(t *testing.T) {
   141  	hook := logTest.NewGlobal()
   142  	ctx := context.Background()
   143  	beaconDB := testDB.SetupDB(t)
   144  	service := New(beaconDB)
   145  	service.EnableSaveHotStateToDB(ctx)
   146  	beaconState, _ := testutil.DeterministicGenesisState(t, 32)
   147  	require.NoError(t, beaconState.SetSlot(defaultHotStateDBInterval))
   148  
   149  	r := [32]byte{'A'}
   150  	require.NoError(t, service.saveStateByRoot(ctx, r, beaconState))
   151  
   152  	require.LogsContain(t, hook, "Saving hot state to DB")
   153  	// Should have saved in DB.
   154  	require.Equal(t, true, beaconDB.HasState(ctx, r))
   155  }
   156  
   157  func TestEnableSaveHotStateToDB_Enabled(t *testing.T) {
   158  	hook := logTest.NewGlobal()
   159  	ctx := context.Background()
   160  	beaconDB := testDB.SetupDB(t)
   161  	service := New(beaconDB)
   162  
   163  	service.EnableSaveHotStateToDB(ctx)
   164  	require.LogsContain(t, hook, "Entering mode to save hot states in DB")
   165  	require.Equal(t, true, service.saveHotStateDB.enabled)
   166  }
   167  
   168  func TestEnableSaveHotStateToDB_AlreadyEnabled(t *testing.T) {
   169  	hook := logTest.NewGlobal()
   170  	ctx := context.Background()
   171  	beaconDB := testDB.SetupDB(t)
   172  	service := New(beaconDB)
   173  	service.saveHotStateDB.enabled = true
   174  	service.EnableSaveHotStateToDB(ctx)
   175  	require.LogsDoNotContain(t, hook, "Entering mode to save hot states in DB")
   176  	require.Equal(t, true, service.saveHotStateDB.enabled)
   177  }
   178  
   179  func TestEnableSaveHotStateToDB_Disabled(t *testing.T) {
   180  	hook := logTest.NewGlobal()
   181  	ctx := context.Background()
   182  	beaconDB := testDB.SetupDB(t)
   183  	service := New(beaconDB)
   184  	service.saveHotStateDB.enabled = true
   185  	b := testutil.NewBeaconBlock()
   186  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
   187  	r, err := b.Block.HashTreeRoot()
   188  	require.NoError(t, err)
   189  	service.saveHotStateDB.savedStateRoots = [][32]byte{r}
   190  	require.NoError(t, service.DisableSaveHotStateToDB(ctx))
   191  	require.LogsContain(t, hook, "Exiting mode to save hot states in DB")
   192  	require.Equal(t, false, service.saveHotStateDB.enabled)
   193  	require.Equal(t, 0, len(service.saveHotStateDB.savedStateRoots))
   194  }
   195  
   196  func TestEnableSaveHotStateToDB_AlreadyDisabled(t *testing.T) {
   197  	hook := logTest.NewGlobal()
   198  	ctx := context.Background()
   199  	beaconDB := testDB.SetupDB(t)
   200  	service := New(beaconDB)
   201  	require.NoError(t, service.DisableSaveHotStateToDB(ctx))
   202  	require.LogsDoNotContain(t, hook, "Exiting mode to save hot states in DB")
   203  	require.Equal(t, false, service.saveHotStateDB.enabled)
   204  }