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 }