diff --git a/mod/da/pkg/store/types.go b/mod/da/pkg/store/types.go index 244c02e674..b02a5b3de4 100644 --- a/mod/da/pkg/store/types.go +++ b/mod/da/pkg/store/types.go @@ -40,6 +40,8 @@ type BlockEvent[BeaconBlockT BeaconBlock] interface { type IndexDB interface { Has(index uint64, key []byte) (bool, error) Set(index uint64, key []byte, value []byte) error + + // Prune returns error if start > end Prune(start uint64, end uint64) error } diff --git a/mod/storage/pkg/deposit/store.go b/mod/storage/pkg/deposit/store.go index 18218eea9e..a58e9e8357 100644 --- a/mod/storage/pkg/deposit/store.go +++ b/mod/storage/pkg/deposit/store.go @@ -28,6 +28,7 @@ import ( sdkcollections "cosmossdk.io/collections" "cosmossdk.io/core/store" "github.com/berachain/beacon-kit/mod/storage/pkg/encoding" + "github.com/berachain/beacon-kit/mod/storage/pkg/pruner" ) const KeyDepositPrefix = "deposit" @@ -104,6 +105,10 @@ func (kv *KVStore[DepositT]) setDeposit(deposit DepositT) error { // Prune removes the [start, end) deposits from the store. func (kv *KVStore[DepositT]) Prune(start, end uint64) error { + if start > end { + return pruner.ErrInvalidRange + } + var ctx = context.TODO() kv.mu.Lock() defer kv.mu.Unlock() diff --git a/mod/storage/pkg/filedb/range_db.go b/mod/storage/pkg/filedb/range_db.go index c418cc8ce5..3ac665f96d 100644 --- a/mod/storage/pkg/filedb/range_db.go +++ b/mod/storage/pkg/filedb/range_db.go @@ -93,6 +93,9 @@ func (db *RangeDB) DeleteRange(from, to uint64) error { if !ok { return errors.New("rangedb: delete range not supported for this db") } + if from > to { + return pruner.ErrInvalidRange + } for ; from < to; from++ { path := strconv.FormatUint(from, 10) + "/" if err := f.fs.RemoveAll(path); err != nil { @@ -105,6 +108,10 @@ func (db *RangeDB) DeleteRange(from, to uint64) error { // Prune removes all values in the given range [start, end) from the db. func (db *RangeDB) Prune(start, end uint64) error { start = max(start, db.firstNonNilIndex) + if start > end { + return pruner.ErrInvalidRange + } + if err := db.DeleteRange(start, end); err != nil { // Resets last pruned index in case Delete somehow populates indices on // err. This will cause the next prune operation is O(n), but next diff --git a/mod/storage/pkg/filedb/range_db_test.go b/mod/storage/pkg/filedb/range_db_test.go index 51334ce806..23de7c5c17 100644 --- a/mod/storage/pkg/filedb/range_db_test.go +++ b/mod/storage/pkg/filedb/range_db_test.go @@ -246,6 +246,15 @@ func TestRangeDB_Prune(t *testing.T) { requireExist(t, rdb, 0, 1) }, }, + { + name: "PruneWithDeleteRange-InvalidRange", + setupFunc: func(rdb *file.RangeDB) error { + return populateTestDB(rdb, 0, 50) + }, + start: 7, + end: 2, + expectedError: true, + }, } for _, tt := range tests { @@ -253,7 +262,7 @@ func TestRangeDB_Prune(t *testing.T) { rdb := file.NewRangeDB(newTestFDB("/tmp/testdb-2")) if tt.setupFunc != nil { - if err := tt.setupFunc(rdb); (err != nil) != tt.expectedError { + if err := tt.setupFunc(rdb); err != nil { t.Fatalf( "setupFunc() error = %v, expectedError %v", err, diff --git a/mod/storage/pkg/pruner/types.go b/mod/storage/pkg/pruner/types.go index 1080a79116..b07e3d0633 100644 --- a/mod/storage/pkg/pruner/types.go +++ b/mod/storage/pkg/pruner/types.go @@ -27,11 +27,14 @@ package pruner import ( "context" + "errors" "github.com/berachain/beacon-kit/mod/primitives/pkg/async" "github.com/berachain/beacon-kit/mod/primitives/pkg/math" ) +var ErrInvalidRange = errors.New("range start greater than end") + // BeaconBlock is an interface for beacon blocks. type BeaconBlock interface { GetSlot() math.U64 @@ -48,6 +51,7 @@ type BlockEvent[BeaconBlockT BeaconBlock] interface { // Prunable is an interface representing a store that can be pruned. type Prunable interface { // Prune prunes the store from [start, end). + // Returns ErrInvalidRange if start > end Prune(start, end uint64) error }