github.com/prysmaticlabs/prysm@v1.4.4/slasher/db/kv/spanner_new_test.go (about)

     1  package kv
     2  
     3  import (
     4  	"context"
     5  	"encoding/hex"
     6  	"testing"
     7  
     8  	types "github.com/prysmaticlabs/eth2-types"
     9  	"github.com/prysmaticlabs/prysm/shared/params"
    10  	"github.com/prysmaticlabs/prysm/shared/testutil/require"
    11  	dbtypes "github.com/prysmaticlabs/prysm/slasher/db/types"
    12  	slashertypes "github.com/prysmaticlabs/prysm/slasher/detection/attestations/types"
    13  )
    14  
    15  type spansTestStruct struct {
    16  	name           string
    17  	epoch          types.Epoch
    18  	spansHex       string
    19  	spansResultHex string
    20  	validator1Span slashertypes.Span
    21  	err            error
    22  }
    23  
    24  var spanNewTests []spansTestStruct
    25  
    26  func init() {
    27  	spanNewTests = []spansTestStruct{
    28  		{
    29  			name:           "span too small",
    30  			epoch:          1,
    31  			spansHex:       "00000000",
    32  			spansResultHex: "",
    33  			validator1Span: slashertypes.Span{},
    34  			err:            slashertypes.ErrWrongSize,
    35  		},
    36  		{
    37  			name:           "no validator 1 in spans",
    38  			epoch:          2,
    39  			spansHex:       "00000000000000",
    40  			spansResultHex: "00000000000000",
    41  			validator1Span: slashertypes.Span{},
    42  			err:            nil,
    43  		},
    44  		{
    45  			name:           "validator 1 in spans",
    46  			epoch:          3,
    47  			spansHex:       "0000000000000001000000000000",
    48  			spansResultHex: "0000000000000001000000000000",
    49  			validator1Span: slashertypes.Span{MinSpan: 1},
    50  			err:            nil,
    51  		},
    52  	}
    53  
    54  }
    55  
    56  func TestValidatorSpans_NilDB(t *testing.T) {
    57  
    58  	db := setupDB(t)
    59  	ctx := context.Background()
    60  
    61  	validatorIndex := uint64(1)
    62  	es, err := db.EpochSpans(ctx, types.Epoch(validatorIndex), false)
    63  	require.NoError(t, err, "Nil EpochSpansMap should not return error")
    64  	cleanStore, err := slashertypes.NewEpochStore([]byte{})
    65  	require.NoError(t, err)
    66  	require.DeepEqual(t, es, cleanStore, "EpochSpans should return empty byte array if no record exists in the db")
    67  }
    68  
    69  func TestStore_SaveReadEpochSpans(t *testing.T) {
    70  
    71  	db := setupDB(t)
    72  	ctx := context.Background()
    73  
    74  	for _, tt := range spanNewTests {
    75  		t.Run(tt.name, func(t *testing.T) {
    76  			spans, err := hex.DecodeString(tt.spansHex)
    77  			require.NoError(t, err)
    78  			es, err := slashertypes.NewEpochStore(spans)
    79  			if tt.err != nil {
    80  				require.ErrorContains(t, tt.err.Error(), err)
    81  			} else {
    82  				require.NoError(t, err)
    83  			}
    84  			require.NoError(t, db.SaveEpochSpans(ctx, tt.epoch, es, false))
    85  			sm, err := db.EpochSpans(ctx, tt.epoch, false)
    86  			require.NoError(t, err, "Failed to get validator spans")
    87  			spansResult, err := hex.DecodeString(tt.spansResultHex)
    88  			require.NoError(t, err)
    89  			esr, err := slashertypes.NewEpochStore(spansResult)
    90  			require.NoError(t, err)
    91  			require.DeepEqual(t, sm, esr, "Get should return validator spans: %v", spansResult)
    92  
    93  			s, err := es.GetValidatorSpan(1)
    94  			require.NoError(t, err, "Failed to get validator 1 span")
    95  			require.DeepEqual(t, tt.validator1Span, s, "Get should return validator span for validator 2: %v", tt.validator1Span)
    96  		})
    97  	}
    98  }
    99  
   100  func TestStore_SaveEpochSpans_ToCache(t *testing.T) {
   101  
   102  	db := setupDB(t)
   103  	ctx := context.Background()
   104  
   105  	spansToSave := map[uint64]slashertypes.Span{
   106  		0:     {MinSpan: 5, MaxSpan: 69, SigBytes: [2]byte{40, 219}, HasAttested: false},
   107  		10:    {MinSpan: 43, MaxSpan: 32, SigBytes: [2]byte{10, 13}, HasAttested: true},
   108  		1000:  {MinSpan: 40, MaxSpan: 36, SigBytes: [2]byte{61, 151}, HasAttested: false},
   109  		10000: {MinSpan: 40, MaxSpan: 64, SigBytes: [2]byte{190, 215}, HasAttested: true},
   110  		50000: {MinSpan: 40, MaxSpan: 64, SigBytes: [2]byte{190, 215}, HasAttested: true},
   111  		100:   {MinSpan: 49, MaxSpan: 96, SigBytes: [2]byte{11, 98}, HasAttested: true},
   112  	}
   113  	epochStore, err := slashertypes.EpochStoreFromMap(spansToSave)
   114  	require.NoError(t, err)
   115  
   116  	epoch := types.Epoch(9)
   117  	require.NoError(t, db.SaveEpochSpans(ctx, epoch, epochStore, dbtypes.UseCache))
   118  
   119  	esFromCache, err := db.EpochSpans(ctx, epoch, dbtypes.UseCache)
   120  	require.NoError(t, err)
   121  	require.DeepEqual(t, epochStore.Bytes(), esFromCache.Bytes())
   122  
   123  	esFromDB, err := db.EpochSpans(ctx, epoch, dbtypes.UseDB)
   124  	require.NoError(t, err)
   125  	require.DeepEqual(t, esFromDB.Bytes(), esFromCache.Bytes())
   126  }
   127  
   128  func TestStore_SaveEpochSpans_ToDB(t *testing.T) {
   129  
   130  	db := setupDB(t)
   131  	ctx := context.Background()
   132  
   133  	spansToSave := map[uint64]slashertypes.Span{
   134  		0:      {MinSpan: 5, MaxSpan: 69, SigBytes: [2]byte{40, 219}, HasAttested: false},
   135  		10:     {MinSpan: 43, MaxSpan: 32, SigBytes: [2]byte{10, 13}, HasAttested: true},
   136  		1000:   {MinSpan: 40, MaxSpan: 36, SigBytes: [2]byte{61, 151}, HasAttested: false},
   137  		10000:  {MinSpan: 40, MaxSpan: 64, SigBytes: [2]byte{190, 215}, HasAttested: true},
   138  		100000: {MinSpan: 20, MaxSpan: 64, SigBytes: [2]byte{170, 215}, HasAttested: false},
   139  		100:    {MinSpan: 49, MaxSpan: 96, SigBytes: [2]byte{11, 98}, HasAttested: true},
   140  	}
   141  	epochStore, err := slashertypes.EpochStoreFromMap(spansToSave)
   142  	require.NoError(t, err)
   143  
   144  	epoch := types.Epoch(9)
   145  	require.NoError(t, db.SaveEpochSpans(ctx, epoch, epochStore, dbtypes.UseDB))
   146  
   147  	// Expect cache to retrieve from DB if its not in cache.
   148  	esFromCache, err := db.EpochSpans(ctx, epoch, dbtypes.UseCache)
   149  	require.NoError(t, err)
   150  	require.DeepEqual(t, esFromCache.Bytes(), epochStore.Bytes())
   151  
   152  	esFromDB, err := db.EpochSpans(ctx, epoch, dbtypes.UseDB)
   153  	require.NoError(t, err)
   154  	require.DeepEqual(t, epochStore.Bytes(), esFromDB.Bytes())
   155  }
   156  
   157  func TestStore_SlasherObservedEpoch(t *testing.T) {
   158  	db := setupDB(t)
   159  	ctx := context.Background()
   160  
   161  	prevConfig := params.BeaconConfig().Copy()
   162  
   163  	defer params.OverrideBeaconConfig(prevConfig)
   164  
   165  	for _, tt := range tests {
   166  		require.NoError(t, db.SaveIndexedAttestation(ctx, tt.idxAtt), "Save indexed attestation failed")
   167  
   168  		found, err := db.HasIndexedAttestation(ctx, tt.idxAtt)
   169  		require.NoError(t, err, "Failed to get indexed attestation")
   170  		require.Equal(t, true, found, "Expected to find attestation in DB")
   171  	}
   172  	// Don't prune when not multiple of PruneSlasherStoragePeriod.
   173  	params.BeaconConfig().PruneSlasherStoragePeriod = 2
   174  	highestObservedEpoch = params.BeaconConfig().WeakSubjectivityPeriod
   175  	require.NoError(t, db.setObservedEpochs(ctx, highestObservedEpoch+1))
   176  	for _, tt := range tests {
   177  		exists, err := db.HasIndexedAttestation(ctx, tt.idxAtt)
   178  		require.NoError(t, err)
   179  		require.Equal(t, true, exists, "Expected to find attestation newer than prune age in DB")
   180  
   181  	}
   182  	// Prune on PruneSlasherStoragePeriod.
   183  	params.BeaconConfig().PruneSlasherStoragePeriod = 1
   184  	highestObservedEpoch = params.BeaconConfig().WeakSubjectivityPeriod
   185  	currentEpoch := highestObservedEpoch + 1
   186  	historyToKeep := highestObservedEpoch
   187  	require.NoError(t, db.setObservedEpochs(ctx, highestObservedEpoch+1))
   188  
   189  	for _, tt := range tests {
   190  		exists, err := db.HasIndexedAttestation(ctx, tt.idxAtt)
   191  		require.NoError(t, err)
   192  
   193  		if tt.idxAtt.Data.Target.Epoch > currentEpoch-historyToKeep {
   194  			require.Equal(t, true, exists, "Expected to find attestation newer than prune age in DB")
   195  		} else {
   196  			require.Equal(t, false, exists, "Expected to not find attestation older than prune age in DB")
   197  		}
   198  	}
   199  }