From 59b785bd375e07772c7b78057151d81f6260fcc4 Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Fri, 11 Oct 2024 14:53:56 +0200 Subject: [PATCH 1/7] add version exists --- runtime/v2/store.go | 2 +- server/v2/appmanager/appmanager.go | 1 + store/v2/commitment/store.go | 1 + store/v2/database.go | 28 ++++++++++++++++---------- store/v2/mock/types.go | 2 +- store/v2/root/store.go | 16 +++++++-------- store/v2/root/store_mock_test.go | 2 +- store/v2/root/store_test.go | 2 +- store/v2/storage/database.go | 1 + store/v2/storage/pebbledb/db.go | 9 +++++++++ store/v2/storage/rocksdb/db.go | 9 +++++++++ store/v2/storage/rocksdb/db_noflag.go | 4 ++++ store/v2/storage/sqlite/db.go | 16 +++++++++++++++ store/v2/storage/storage_test_suite.go | 2 +- store/v2/storage/store.go | 7 ++++++- store/v2/store.go | 2 +- 16 files changed, 77 insertions(+), 27 deletions(-) diff --git a/runtime/v2/store.go b/runtime/v2/store.go index 40912ea41f48..5d37c321c1fe 100644 --- a/runtime/v2/store.go +++ b/runtime/v2/store.go @@ -43,7 +43,7 @@ type Store interface { Query(storeKey []byte, version uint64, key []byte, prove bool) (storev2.QueryResult, error) // GetStateStorage returns the SS backend. - GetStateStorage() storev2.VersionedDatabase + GetStateStorage() storev2.VersionedWriter // GetStateCommitment returns the SC backend. GetStateCommitment() storev2.Committer diff --git a/server/v2/appmanager/appmanager.go b/server/v2/appmanager/appmanager.go index 6a5f96ec5fa9..f558ab953b55 100644 --- a/server/v2/appmanager/appmanager.go +++ b/server/v2/appmanager/appmanager.go @@ -138,6 +138,7 @@ func (a AppManager[T]) Simulate(ctx context.Context, tx T) (server.TxResult, cor func (a AppManager[T]) Query(ctx context.Context, version uint64, request transaction.Msg) (transaction.Msg, error) { // if version is provided attempt to do a height query. if version != 0 { + // TODO: if proof is set to true we will be checking ss for the version and not sc queryState, err := a.db.StateAt(version) if err != nil { return nil, err diff --git a/store/v2/commitment/store.go b/store/v2/commitment/store.go index da0440987524..e1f6df9d2024 100644 --- a/store/v2/commitment/store.go +++ b/store/v2/commitment/store.go @@ -275,6 +275,7 @@ func (c *CommitStore) GetProof(storeKey []byte, version uint64, key []byte) ([]p return []proof.CommitmentOp{commitOp, *storeCommitmentOp}, nil } +// Get implements store.VersionedReader. func (c *CommitStore) Get(storeKey []byte, version uint64, key []byte) ([]byte, error) { tree, ok := c.multiTrees[conv.UnsafeBytesToStr(storeKey)] if !ok { diff --git a/store/v2/database.go b/store/v2/database.go index 58a3ee7ef65c..c4f00defe81a 100644 --- a/store/v2/database.go +++ b/store/v2/database.go @@ -7,19 +7,29 @@ import ( "cosmossdk.io/store/v2/proof" ) -// VersionedDatabase defines an API for a versioned database that allows reads, +// VersionedWriter defines an API for a versioned database that allows reads, // writes, iteration and commitment over a series of versions. -type VersionedDatabase interface { +type VersionedWriter interface { + VersionedReader + + SetLatestVersion(version uint64) error + ApplyChangeset(version uint64, cs *corestore.Changeset) error + + // Close releases associated resources. It should NOT be idempotent. It must + // only be called once and any call after may panic. + io.Closer +} + +type VersionedReader interface { Has(storeKey []byte, version uint64, key []byte) (bool, error) Get(storeKey []byte, version uint64, key []byte) ([]byte, error) + GetLatestVersion() (uint64, error) - SetLatestVersion(version uint64) error + VersionExists(v uint64) (bool, error) Iterator(storeKey []byte, version uint64, start, end []byte) (corestore.Iterator, error) ReverseIterator(storeKey []byte, version uint64, start, end []byte) (corestore.Iterator, error) - ApplyChangeset(version uint64, cs *corestore.Changeset) error - // Close releases associated resources. It should NOT be idempotent. It must // only be called once and any call after may panic. io.Closer @@ -53,18 +63,14 @@ type Committer interface { // GetProof returns the proof of existence or non-existence for the given key. GetProof(storeKey []byte, version uint64, key []byte) ([]proof.CommitmentOp, error) - // Get returns the value for the given key at the given version. - // - // NOTE: This method only exists to support migration from IAVL v0/v1 to v2. - // Once migration is complete, this method should be removed and/or not used. - Get(storeKey []byte, version uint64, key []byte) ([]byte, error) - // SetInitialVersion sets the initial version of the committer. SetInitialVersion(version uint64) error // GetCommitInfo returns the CommitInfo for the given version. GetCommitInfo(version uint64) (*proof.CommitInfo, error) + Get(storeKey []byte, version uint64, key []byte) ([]byte, error) + // Close releases associated resources. It should NOT be idempotent. It must // only be called once and any call after may panic. io.Closer diff --git a/store/v2/mock/types.go b/store/v2/mock/types.go index 95d623c8396f..a8c2a196d5bb 100644 --- a/store/v2/mock/types.go +++ b/store/v2/mock/types.go @@ -12,7 +12,7 @@ type StateCommitter interface { // StateStorage is a mock of store.VersionedDatabase type StateStorage interface { - store.VersionedDatabase + store.VersionedWriter store.UpgradableDatabase store.Pruner store.PausablePruner diff --git a/store/v2/root/store.go b/store/v2/root/store.go index c39119a9aaf3..8ed2a912bad8 100644 --- a/store/v2/root/store.go +++ b/store/v2/root/store.go @@ -34,7 +34,7 @@ type Store struct { initialVersion uint64 // stateStorage reflects the state storage backend - stateStorage store.VersionedDatabase + stateStorage store.VersionedWriter // stateCommitment reflects the state commitment (SC) backend stateCommitment store.Committer @@ -69,7 +69,7 @@ type Store struct { // NOTE: The migration manager is optional and can be nil if no migration is required. func New( logger corelog.Logger, - ss store.VersionedDatabase, + ss store.VersionedWriter, sc store.Committer, pm *pruning.Manager, mm *migration.Manager, @@ -120,19 +120,17 @@ func (s *Store) StateLatest() (uint64, corestore.ReaderMap, error) { return v, NewReaderMap(v, s), nil } +// StateAt checks if the requested version is present in the state storage and the commitment store. func (s *Store) StateAt(v uint64) (corestore.ReaderMap, error) { - // TODO(bez): We may want to avoid relying on the SC metadata here. Instead, - // we should add a VersionExists() method to the VersionedDatabase interface. - // - // Ref: https://github.com/cosmos/cosmos-sdk/issues/19091 - if cInfo, err := s.stateCommitment.GetCommitInfo(v); err != nil || cInfo == nil { - return nil, fmt.Errorf("failed to get commit info for version %d: %w", v, err) + // check if version is present in state storage + if _, err := s.stateStorage.VersionExists(v); err != nil { + return nil, err } return NewReaderMap(v, s), nil } -func (s *Store) GetStateStorage() store.VersionedDatabase { +func (s *Store) GetStateStorage() store.VersionedWriter { return s.stateStorage } diff --git a/store/v2/root/store_mock_test.go b/store/v2/root/store_mock_test.go index 68956ab47922..3a14054cd7e4 100644 --- a/store/v2/root/store_mock_test.go +++ b/store/v2/root/store_mock_test.go @@ -16,7 +16,7 @@ import ( "cosmossdk.io/store/v2/pruning" ) -func newTestRootStore(ss store.VersionedDatabase, sc store.Committer) *Store { +func newTestRootStore(ss store.VersionedWriter, sc store.Committer) *Store { noopLog := coretesting.NewNopLogger() pm := pruning.NewManager(sc.(store.Pruner), ss.(store.Pruner), nil, nil) return &Store{ diff --git a/store/v2/root/store_test.go b/store/v2/root/store_test.go index e8cf34e014e0..7e0edf4f3abc 100644 --- a/store/v2/root/store_test.go +++ b/store/v2/root/store_test.go @@ -90,7 +90,7 @@ func (s *RootStoreTestSuite) newStoreWithPruneConfig(config *store.PruningOption s.rootStore = rs } -func (s *RootStoreTestSuite) newStoreWithBackendMount(ss store.VersionedDatabase, sc store.Committer, pm *pruning.Manager) { +func (s *RootStoreTestSuite) newStoreWithBackendMount(ss store.VersionedWriter, sc store.Committer, pm *pruning.Manager) { noopLog := coretesting.NewNopLogger() rs, err := New(noopLog, ss, sc, pm, nil, nil) diff --git a/store/v2/storage/database.go b/store/v2/storage/database.go index fba599839594..e969a9ee6338 100644 --- a/store/v2/storage/database.go +++ b/store/v2/storage/database.go @@ -16,6 +16,7 @@ type Database interface { Get(storeKey []byte, version uint64, key []byte) ([]byte, error) GetLatestVersion() (uint64, error) SetLatestVersion(version uint64) error + VersionExists(version uint64) (bool, error) Iterator(storeKey []byte, version uint64, start, end []byte) (corestore.Iterator, error) ReverseIterator(storeKey []byte, version uint64, start, end []byte) (corestore.Iterator, error) diff --git a/store/v2/storage/pebbledb/db.go b/store/v2/storage/pebbledb/db.go index e5fd49ca3e5d..349f00675788 100644 --- a/store/v2/storage/pebbledb/db.go +++ b/store/v2/storage/pebbledb/db.go @@ -137,6 +137,15 @@ func (db *Database) GetLatestVersion() (uint64, error) { return binary.LittleEndian.Uint64(bz), closer.Close() } +func (db *Database) VersionExists(version uint64) (bool, error) { + _, err := db.GetLatestVersion() + if err != nil { + return false, err + } + + return version >= db.earliestVersion, nil +} + func (db *Database) setPruneHeight(pruneVersion uint64) error { db.earliestVersion = pruneVersion + 1 diff --git a/store/v2/storage/rocksdb/db.go b/store/v2/storage/rocksdb/db.go index afac4cc9ff22..0bcc7d047f48 100644 --- a/store/v2/storage/rocksdb/db.go +++ b/store/v2/storage/rocksdb/db.go @@ -131,6 +131,15 @@ func (db *Database) GetLatestVersion() (uint64, error) { return binary.LittleEndian.Uint64(bz), nil } +func (db *Database) VersionExists(version uint64) (bool, error) { + _, err := db.GetLatestVersion() + if err != nil { + return false, err + } + + return version >= db.earliestVersion, nil +} + func (db *Database) Has(storeKey []byte, version uint64, key []byte) (bool, error) { slice, err := db.getSlice(storeKey, version, key) if err != nil { diff --git a/store/v2/storage/rocksdb/db_noflag.go b/store/v2/storage/rocksdb/db_noflag.go index def31e437a44..93bc3090f284 100644 --- a/store/v2/storage/rocksdb/db_noflag.go +++ b/store/v2/storage/rocksdb/db_noflag.go @@ -36,6 +36,10 @@ func (db *Database) GetLatestVersion() (uint64, error) { panic("rocksdb requires a build flag") } +func (db *Database) VersionExists(version uint64) (bool, error) { + panic("rocksdb requires a build flag") +} + func (db *Database) Has(storeKey []byte, version uint64, key []byte) (bool, error) { panic("rocksdb requires a build flag") } diff --git a/store/v2/storage/sqlite/db.go b/store/v2/storage/sqlite/db.go index 38750a0ac9a5..62f907c5ed25 100644 --- a/store/v2/storage/sqlite/db.go +++ b/store/v2/storage/sqlite/db.go @@ -123,6 +123,22 @@ func (db *Database) GetLatestVersion() (uint64, error) { return latestHeight, nil } +func (db *Database) VersionExists(v uint64) (bool, error) { + stmt, err := db.storage.Prepare("SELECT COUNT(*) FROM state_storage WHERE store_key != ? AND version = ? AND tombstone = 0") + if err != nil { + return false, fmt.Errorf("failed to prepare SQL statement: %w", err) + } + + defer stmt.Close() + + var count uint64 + if err := stmt.QueryRow(reservedStoreKey, v).Scan(&count); err != nil { + return false, fmt.Errorf("failed to query row: %w", err) + } + + return count > 0, nil +} + func (db *Database) SetLatestVersion(version uint64) error { _, err := db.storage.Exec(reservedUpsertStmt, reservedStoreKey, keyLatestHeight, version, 0, version) if err != nil { diff --git a/store/v2/storage/storage_test_suite.go b/store/v2/storage/storage_test_suite.go index 08f455ca12ca..af68102a62cd 100644 --- a/store/v2/storage/storage_test_suite.go +++ b/store/v2/storage/storage_test_suite.go @@ -882,7 +882,7 @@ func (s *StorageTestSuite) TestRemovingOldStoreKey() { func dbApplyChangeset( t *testing.T, - db store.VersionedDatabase, + db store.VersionedWriter, version uint64, storeKey string, keys, vals [][]byte, diff --git a/store/v2/storage/store.go b/store/v2/storage/store.go index 9ea839562847..b16ee9e7eae4 100644 --- a/store/v2/storage/store.go +++ b/store/v2/storage/store.go @@ -16,7 +16,7 @@ const ( ) var ( - _ store.VersionedDatabase = (*StorageStore)(nil) + _ store.VersionedWriter = (*StorageStore)(nil) _ snapshots.StorageSnapshotter = (*StorageStore)(nil) _ store.Pruner = (*StorageStore)(nil) _ store.UpgradableDatabase = (*StorageStore)(nil) @@ -84,6 +84,11 @@ func (ss *StorageStore) SetLatestVersion(version uint64) error { return ss.db.SetLatestVersion(version) } +// VersionExists returns true if the given version exists in the store. +func (ss *StorageStore) VersionExists(version uint64) (bool, error) { + return ss.db.VersionExists(version) +} + // Iterator returns an iterator over the specified domain and prefix. func (ss *StorageStore) Iterator(storeKey []byte, version uint64, start, end []byte) (corestore.Iterator, error) { return ss.db.Iterator(storeKey, version, start, end) diff --git a/store/v2/store.go b/store/v2/store.go index 1adf44f0b89b..24ba636e10aa 100644 --- a/store/v2/store.go +++ b/store/v2/store.go @@ -70,7 +70,7 @@ type RootStore interface { // Backend defines the interface for the RootStore backends. type Backend interface { // GetStateStorage returns the SS backend. - GetStateStorage() VersionedDatabase + GetStateStorage() VersionedWriter // GetStateCommitment returns the SC backend. GetStateCommitment() Committer From a3168cc9962fdf9fad934378067c163e78be2ac4 Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Fri, 11 Oct 2024 15:07:43 +0200 Subject: [PATCH 2/7] cleanup --- server/v2/appmanager/appmanager.go | 1 - store/v2/root/store.go | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/server/v2/appmanager/appmanager.go b/server/v2/appmanager/appmanager.go index f558ab953b55..6a5f96ec5fa9 100644 --- a/server/v2/appmanager/appmanager.go +++ b/server/v2/appmanager/appmanager.go @@ -138,7 +138,6 @@ func (a AppManager[T]) Simulate(ctx context.Context, tx T) (server.TxResult, cor func (a AppManager[T]) Query(ctx context.Context, version uint64, request transaction.Msg) (transaction.Msg, error) { // if version is provided attempt to do a height query. if version != 0 { - // TODO: if proof is set to true we will be checking ss for the version and not sc queryState, err := a.db.StateAt(version) if err != nil { return nil, err diff --git a/store/v2/root/store.go b/store/v2/root/store.go index 8ed2a912bad8..414e902e0194 100644 --- a/store/v2/root/store.go +++ b/store/v2/root/store.go @@ -120,7 +120,7 @@ func (s *Store) StateLatest() (uint64, corestore.ReaderMap, error) { return v, NewReaderMap(v, s), nil } -// StateAt checks if the requested version is present in the state storage and the commitment store. +// StateAt checks if the requested version is present in the state storage. func (s *Store) StateAt(v uint64) (corestore.ReaderMap, error) { // check if version is present in state storage if _, err := s.stateStorage.VersionExists(v); err != nil { From dffb45dd1c06fec8079ad69e16a4ccbe3a8f0b7e Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Sun, 13 Oct 2024 12:29:33 +0200 Subject: [PATCH 3/7] add test cases --- store/v2/mock/db_mock.go | 15 ++ store/v2/root/store.go | 2 +- store/v2/storage/pebbledb/db_test.go | 168 ++++++++++++++++++++++ store/v2/storage/sqlite/db.go | 6 +- store/v2/storage/sqlite/db_test.go | 201 +++++++++++++++++++++++++++ 5 files changed, 390 insertions(+), 2 deletions(-) diff --git a/store/v2/mock/db_mock.go b/store/v2/mock/db_mock.go index 8014e48514fe..60f660607929 100644 --- a/store/v2/mock/db_mock.go +++ b/store/v2/mock/db_mock.go @@ -404,3 +404,18 @@ func (mr *MockStateStorageMockRecorder) SetLatestVersion(version any) *gomock.Ca mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLatestVersion", reflect.TypeOf((*MockStateStorage)(nil).SetLatestVersion), version) } + +// VersionExists mocks base method. +func (m *MockStateStorage) VersionExists(v uint64) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "VersionExists", v) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// VersionExists indicates an expected call of VersionExists. +func (mr *MockStateStorageMockRecorder) VersionExists(v any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VersionExists", reflect.TypeOf((*MockStateStorage)(nil).VersionExists), v) +} diff --git a/store/v2/root/store.go b/store/v2/root/store.go index 414e902e0194..8443aa08198a 100644 --- a/store/v2/root/store.go +++ b/store/v2/root/store.go @@ -120,7 +120,7 @@ func (s *Store) StateLatest() (uint64, corestore.ReaderMap, error) { return v, NewReaderMap(v, s), nil } -// StateAt checks if the requested version is present in the state storage. +// StateAt checks if the requested version is present in ss. func (s *Store) StateAt(v uint64) (corestore.ReaderMap, error) { // check if version is present in state storage if _, err := s.stateStorage.VersionExists(v); err != nil { diff --git a/store/v2/storage/pebbledb/db_test.go b/store/v2/storage/pebbledb/db_test.go index 0ef4c8ca9f25..8c9bbfdfca3f 100644 --- a/store/v2/storage/pebbledb/db_test.go +++ b/store/v2/storage/pebbledb/db_test.go @@ -26,3 +26,171 @@ func TestStorageTestSuite(t *testing.T) { suite.Run(t, s) } + +// TestVersionExists tests the VersionExists method of the Database struct. +func TestVersionExists(t *testing.T) { + // Define test cases + testCases := []struct { + name string + setup func(t *testing.T, db *Database) + version uint64 + expectedExists bool + expectError bool + }{ + { + name: "Fresh database: version 0 exists", + setup: func(t *testing.T, db *Database) { + t.Helper() + // No setup needed for fresh database + }, + version: 0, + expectedExists: true, + expectError: false, + }, + { + name: "Fresh database: version 1 exists", + setup: func(t *testing.T, db *Database) { + t.Helper() + // No setup needed for fresh database + }, + version: 1, + expectedExists: true, + expectError: false, + }, + { + name: "After setting latest version to 10, version 5 exists", + setup: func(t *testing.T, db *Database) { + t.Helper() + err := db.SetLatestVersion(10) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + }, + version: 5, + expectedExists: true, // Since pruning hasn't occurred, earliestVersion is still 0 + expectError: false, + }, + { + name: "After setting latest version to 10 and pruning to 5, version 4 does not exist", + setup: func(t *testing.T, db *Database) { + t.Helper() + err := db.SetLatestVersion(10) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + + err = db.Prune(5) + if err != nil { + t.Fatalf("Pruning to version 5 should not error: %v", err) + } + }, + version: 4, + expectedExists: false, + expectError: false, + }, + { + name: "After setting latest version to 10 and pruning to 5, version 5 does not exist", + setup: func(t *testing.T, db *Database) { + t.Helper() + err := db.SetLatestVersion(10) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + + err = db.Prune(5) + if err != nil { + t.Fatalf("Pruning to version 5 should not error: %v", err) + } + }, + version: 5, + expectedExists: false, + expectError: false, + }, + { + name: "After setting latest version to 10 and pruning to 5, version 6 exists", + setup: func(t *testing.T, db *Database) { + t.Helper() + err := db.SetLatestVersion(10) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + + err = db.Prune(5) + if err != nil { + t.Fatalf("Pruning to version 5 should not error: %v", err) + } + }, + version: 6, + expectedExists: true, + expectError: false, + }, + { + name: "After pruning to 0, all versions >=1 exist", + setup: func(t *testing.T, db *Database) { + t.Helper() + // Prune to version 0 + err := db.Prune(0) + if err != nil { + t.Fatalf("Pruning to version 0 should not error: %v", err) + } + }, + version: 0, + expectedExists: false, + expectError: false, + }, + { + name: "After pruning to 0, version 1 exists", + setup: func(t *testing.T, db *Database) { + t.Helper() + // Prune to version 0 + err := db.Prune(0) + if err != nil { + t.Fatalf("Pruning to version 0 should not error: %v", err) + } + }, + version: 1, + expectedExists: true, + expectError: false, + }, + } + + // Iterate over each test case + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // Create a temporary directory for the test database + tempDir := t.TempDir() + + // Initialize the database + db, err := New(tempDir) + if err != nil { + t.Fatalf("Initializing the database should not error: %v", err) + } + defer func() { + err := db.Close() + if err != nil { + t.Fatalf("Closing the database should not error: %v", err) + } + }() + + // Setup the database state as per the test case + tc.setup(t, db) + + // Call VersionExists with the specified version + exists, err := db.VersionExists(tc.version) + + // Assert based on expectation + if tc.expectError { + if err == nil { + t.Errorf("Expected an error but got none") + } + } else { + if err != nil { + t.Errorf("Did not expect an error but got one: %v", err) + } + if exists != tc.expectedExists { + t.Errorf("Version existence mismatch: expected %v, got %v", tc.expectedExists, exists) + } + } + }) + } +} diff --git a/store/v2/storage/sqlite/db.go b/store/v2/storage/sqlite/db.go index 62f907c5ed25..51da723561e5 100644 --- a/store/v2/storage/sqlite/db.go +++ b/store/v2/storage/sqlite/db.go @@ -124,7 +124,11 @@ func (db *Database) GetLatestVersion() (uint64, error) { } func (db *Database) VersionExists(v uint64) (bool, error) { - stmt, err := db.storage.Prepare("SELECT COUNT(*) FROM state_storage WHERE store_key != ? AND version = ? AND tombstone = 0") + stmt, err := db.storage.Prepare(` + SELECT COUNT(*) + FROM state_storage + WHERE store_key != ? AND version = ? AND tombstone = 0 + `) if err != nil { return false, fmt.Errorf("failed to prepare SQL statement: %w", err) } diff --git a/store/v2/storage/sqlite/db_test.go b/store/v2/storage/sqlite/db_test.go index fc4c27e6bfd9..1961cb918695 100644 --- a/store/v2/storage/sqlite/db_test.go +++ b/store/v2/storage/sqlite/db_test.go @@ -198,3 +198,204 @@ func TestParallelWriteAndPruning(t *testing.T) { require.NoError(t, err) require.Equal(t, []byte(fmt.Sprintf("val-%d-%03d", version-1, 0)), val) } + +// TestDatabase_VersionExists tests the VersionExists method of the Database struct. +func TestDatabase_VersionExists(t *testing.T) { + // Define test cases + testCases := []struct { + name string + setup func(t *testing.T, db *Database) + version uint64 + expectedExists bool + expectError bool + }{ + { + name: "Fresh database: version 0 does not exist", + setup: func(t *testing.T, db *Database) { + t.Helper() + // No setup needed for fresh database + }, + version: 0, + expectedExists: false, + expectError: false, + }, + { + name: "Fresh database: version 1 does not exist", + setup: func(t *testing.T, db *Database) { + t.Helper() + // No setup needed for fresh database + }, + version: 1, + expectedExists: false, + expectError: false, + }, + { + name: "After setting latest version to 5, version 5 exists", + setup: func(t *testing.T, db *Database) { + t.Helper() + err := db.SetLatestVersion(5) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + }, + version: 5, + expectedExists: true, + expectError: false, + }, + { + name: "After setting latest version to 5, version 3 does not exist", + setup: func(t *testing.T, db *Database) { + t.Helper() + err := db.SetLatestVersion(5) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + }, + version: 3, + expectedExists: false, // Since tombstone is not set, it's just existence + expectError: false, + }, + { + name: "After setting latest version to 10 and pruning to 5, version 5 does not exist", + setup: func(t *testing.T, db *Database) { + t.Helper() + err := db.SetLatestVersion(10) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + + err = db.Prune(5) + if err != nil { + t.Fatalf("Pruning to version 5 should not error: %v", err) + } + }, + version: 5, + expectedExists: false, + expectError: false, + }, + // { + // name: "After setting latest version to 10 and pruning to 5, version 7 exists", + // setup: func(t *testing.T, db *Database) { + // t.Helper() + // err := db.SetLatestVersion(10) + // if err != nil { + // t.Fatalf("Setting latest version should not error: %v", err) + // } + + // err = db.Prune(5) + // if err != nil { + // t.Fatalf("Pruning to version 5 should not error: %v", err) + // } + // }, + // version: 7, + // expectedExists: true, + // expectError: false, + // }, + { + name: "After pruning to version 0, version 0 does not exist", + setup: func(t *testing.T, db *Database) { + t.Helper() + // Prune to version 0 + err := db.Prune(0) + if err != nil { + t.Fatalf("Pruning to version 0 should not error: %v", err) + } + }, + version: 0, + expectedExists: false, + expectError: false, + }, + { + name: "After pruning to version 0, version 1 exists", + setup: func(t *testing.T, db *Database) { + t.Helper() + // Prune to version 0 + err := db.Prune(0) + if err != nil { + t.Fatalf("Pruning to version 0 should not error: %v", err) + } + + // Set latest version to 1 + err = db.SetLatestVersion(1) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + }, + version: 1, + expectedExists: true, + expectError: false, + }, + { + name: "After setting and pruning, version does not exist due to tombstone", + setup: func(t *testing.T, db *Database) { + t.Helper() + // Set latest version to 5 + err := db.SetLatestVersion(5) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + + // Insert a key with version 3 and tombstone + _, err = db.storage.Exec(upsertStmt, "store1", "key1", "value1", 3, "value1") + if err != nil { + t.Fatalf("Inserting key1 at version 3 should not error: %v", err) + } + + // Mark version 3 as tombstoned + _, err = db.storage.Exec(delStmt, 3, "store1", "key1") + if err != nil { + t.Fatalf("Tombstoning key1 at version 3 should not error: %v", err) + } + + // Prune to version 2 + err = db.Prune(2) + if err != nil { + t.Fatalf("Pruning to version 2 should not error: %v", err) + } + }, + version: 3, + expectedExists: false, + expectError: false, + }, + } + + // Iterate over each test case + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // Create a temporary directory for the test database + tempDir := t.TempDir() + + // Initialize the database + db, err := New(tempDir) + if err != nil { + t.Fatalf("Initializing the database should not error: %v", err) + } + defer func() { + err := db.Close() + if err != nil { + t.Fatalf("Closing the database should not error: %v", err) + } + }() + + // Setup the database state as per the test case + tc.setup(t, db) + + // Call VersionExists with the specified version + exists, err := db.VersionExists(tc.version) + + // Assert based on expectation + if tc.expectError { + if err == nil { + t.Errorf("Expected an error but got none") + } + } else { + if err != nil { + t.Errorf("Did not expect an error but got one: %v", err) + } + if exists != tc.expectedExists { + t.Errorf("Version existence mismatch: expected %v, got %v", tc.expectedExists, exists) + } + } + }) + } +} From 64ae24d691d7a4722d34039d423dd460177cb1b4 Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Tue, 15 Oct 2024 15:54:19 +0200 Subject: [PATCH 4/7] changes --- store/v2/storage/sqlite/db.go | 19 ++++++++++++++----- store/v2/storage/sqlite/db_test.go | 2 +- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/store/v2/storage/sqlite/db.go b/store/v2/storage/sqlite/db.go index 51da723561e5..f648e5ed6cbf 100644 --- a/store/v2/storage/sqlite/db.go +++ b/store/v2/storage/sqlite/db.go @@ -103,7 +103,11 @@ func (db *Database) NewBatch(version uint64) (store.Batch, error) { } func (db *Database) GetLatestVersion() (uint64, error) { - stmt, err := db.storage.Prepare("SELECT value FROM state_storage WHERE store_key = ? AND key = ?") + stmt, err := db.storage.Prepare(` + SELECT value + FROM state_storage + WHERE store_key = ? AND key = ? + `) if err != nil { return 0, fmt.Errorf("failed to prepare SQL statement: %w", err) } @@ -127,7 +131,7 @@ func (db *Database) VersionExists(v uint64) (bool, error) { stmt, err := db.storage.Prepare(` SELECT COUNT(*) FROM state_storage - WHERE store_key != ? AND version = ? AND tombstone = 0 + WHERE store_key != ? AND version = ? `) if err != nil { return false, fmt.Errorf("failed to prepare SQL statement: %w", err) @@ -135,12 +139,17 @@ func (db *Database) VersionExists(v uint64) (bool, error) { defer stmt.Close() - var count uint64 - if err := stmt.QueryRow(reservedStoreKey, v).Scan(&count); err != nil { + var latestHeight uint64 + if err := stmt.QueryRow(reservedStoreKey, keyLatestHeight).Scan(&latestHeight); err != nil { + if errors.Is(err, sql.ErrNoRows) { + // in case of a fresh database + return false, nil + } + return false, fmt.Errorf("failed to query row: %w", err) } - return count > 0, nil + return latestHeight >= v && db.earliestVersion <= v, nil } func (db *Database) SetLatestVersion(version uint64) error { diff --git a/store/v2/storage/sqlite/db_test.go b/store/v2/storage/sqlite/db_test.go index 1961cb918695..85d99c582826 100644 --- a/store/v2/storage/sqlite/db_test.go +++ b/store/v2/storage/sqlite/db_test.go @@ -216,7 +216,7 @@ func TestDatabase_VersionExists(t *testing.T) { // No setup needed for fresh database }, version: 0, - expectedExists: false, + expectedExists: true, expectError: false, }, { From cbd465c293685a0f7592333f66cfdc708387766c Mon Sep 17 00:00:00 2001 From: Cool Developer Date: Tue, 15 Oct 2024 18:06:43 -0400 Subject: [PATCH 5/7] fix tests --- store/v2/root/store.go | 6 +- store/v2/storage/pebbledb/db.go | 4 +- store/v2/storage/pebbledb/db_test.go | 168 --------------------- store/v2/storage/rocksdb/db.go | 4 +- store/v2/storage/sqlite/db.go | 22 +-- store/v2/storage/sqlite/db_test.go | 201 ------------------------- store/v2/storage/storage_test_suite.go | 140 +++++++++++++++++ 7 files changed, 152 insertions(+), 393 deletions(-) diff --git a/store/v2/root/store.go b/store/v2/root/store.go index 8443aa08198a..3ca1cfa38387 100644 --- a/store/v2/root/store.go +++ b/store/v2/root/store.go @@ -123,9 +123,13 @@ func (s *Store) StateLatest() (uint64, corestore.ReaderMap, error) { // StateAt checks if the requested version is present in ss. func (s *Store) StateAt(v uint64) (corestore.ReaderMap, error) { // check if version is present in state storage - if _, err := s.stateStorage.VersionExists(v); err != nil { + isExist, err := s.stateStorage.VersionExists(v) + if err != nil { return nil, err } + if !isExist { + return nil, fmt.Errorf("version %d does not exist", v) + } return NewReaderMap(v, s), nil } diff --git a/store/v2/storage/pebbledb/db.go b/store/v2/storage/pebbledb/db.go index 349f00675788..1547dba102d9 100644 --- a/store/v2/storage/pebbledb/db.go +++ b/store/v2/storage/pebbledb/db.go @@ -138,12 +138,12 @@ func (db *Database) GetLatestVersion() (uint64, error) { } func (db *Database) VersionExists(version uint64) (bool, error) { - _, err := db.GetLatestVersion() + latestVersion, err := db.GetLatestVersion() if err != nil { return false, err } - return version >= db.earliestVersion, nil + return latestVersion >= version && version >= db.earliestVersion, nil } func (db *Database) setPruneHeight(pruneVersion uint64) error { diff --git a/store/v2/storage/pebbledb/db_test.go b/store/v2/storage/pebbledb/db_test.go index 8c9bbfdfca3f..0ef4c8ca9f25 100644 --- a/store/v2/storage/pebbledb/db_test.go +++ b/store/v2/storage/pebbledb/db_test.go @@ -26,171 +26,3 @@ func TestStorageTestSuite(t *testing.T) { suite.Run(t, s) } - -// TestVersionExists tests the VersionExists method of the Database struct. -func TestVersionExists(t *testing.T) { - // Define test cases - testCases := []struct { - name string - setup func(t *testing.T, db *Database) - version uint64 - expectedExists bool - expectError bool - }{ - { - name: "Fresh database: version 0 exists", - setup: func(t *testing.T, db *Database) { - t.Helper() - // No setup needed for fresh database - }, - version: 0, - expectedExists: true, - expectError: false, - }, - { - name: "Fresh database: version 1 exists", - setup: func(t *testing.T, db *Database) { - t.Helper() - // No setup needed for fresh database - }, - version: 1, - expectedExists: true, - expectError: false, - }, - { - name: "After setting latest version to 10, version 5 exists", - setup: func(t *testing.T, db *Database) { - t.Helper() - err := db.SetLatestVersion(10) - if err != nil { - t.Fatalf("Setting latest version should not error: %v", err) - } - }, - version: 5, - expectedExists: true, // Since pruning hasn't occurred, earliestVersion is still 0 - expectError: false, - }, - { - name: "After setting latest version to 10 and pruning to 5, version 4 does not exist", - setup: func(t *testing.T, db *Database) { - t.Helper() - err := db.SetLatestVersion(10) - if err != nil { - t.Fatalf("Setting latest version should not error: %v", err) - } - - err = db.Prune(5) - if err != nil { - t.Fatalf("Pruning to version 5 should not error: %v", err) - } - }, - version: 4, - expectedExists: false, - expectError: false, - }, - { - name: "After setting latest version to 10 and pruning to 5, version 5 does not exist", - setup: func(t *testing.T, db *Database) { - t.Helper() - err := db.SetLatestVersion(10) - if err != nil { - t.Fatalf("Setting latest version should not error: %v", err) - } - - err = db.Prune(5) - if err != nil { - t.Fatalf("Pruning to version 5 should not error: %v", err) - } - }, - version: 5, - expectedExists: false, - expectError: false, - }, - { - name: "After setting latest version to 10 and pruning to 5, version 6 exists", - setup: func(t *testing.T, db *Database) { - t.Helper() - err := db.SetLatestVersion(10) - if err != nil { - t.Fatalf("Setting latest version should not error: %v", err) - } - - err = db.Prune(5) - if err != nil { - t.Fatalf("Pruning to version 5 should not error: %v", err) - } - }, - version: 6, - expectedExists: true, - expectError: false, - }, - { - name: "After pruning to 0, all versions >=1 exist", - setup: func(t *testing.T, db *Database) { - t.Helper() - // Prune to version 0 - err := db.Prune(0) - if err != nil { - t.Fatalf("Pruning to version 0 should not error: %v", err) - } - }, - version: 0, - expectedExists: false, - expectError: false, - }, - { - name: "After pruning to 0, version 1 exists", - setup: func(t *testing.T, db *Database) { - t.Helper() - // Prune to version 0 - err := db.Prune(0) - if err != nil { - t.Fatalf("Pruning to version 0 should not error: %v", err) - } - }, - version: 1, - expectedExists: true, - expectError: false, - }, - } - - // Iterate over each test case - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - // Create a temporary directory for the test database - tempDir := t.TempDir() - - // Initialize the database - db, err := New(tempDir) - if err != nil { - t.Fatalf("Initializing the database should not error: %v", err) - } - defer func() { - err := db.Close() - if err != nil { - t.Fatalf("Closing the database should not error: %v", err) - } - }() - - // Setup the database state as per the test case - tc.setup(t, db) - - // Call VersionExists with the specified version - exists, err := db.VersionExists(tc.version) - - // Assert based on expectation - if tc.expectError { - if err == nil { - t.Errorf("Expected an error but got none") - } - } else { - if err != nil { - t.Errorf("Did not expect an error but got one: %v", err) - } - if exists != tc.expectedExists { - t.Errorf("Version existence mismatch: expected %v, got %v", tc.expectedExists, exists) - } - } - }) - } -} diff --git a/store/v2/storage/rocksdb/db.go b/store/v2/storage/rocksdb/db.go index 0bcc7d047f48..7fce1792a783 100644 --- a/store/v2/storage/rocksdb/db.go +++ b/store/v2/storage/rocksdb/db.go @@ -132,12 +132,12 @@ func (db *Database) GetLatestVersion() (uint64, error) { } func (db *Database) VersionExists(version uint64) (bool, error) { - _, err := db.GetLatestVersion() + latestVersion, err := db.GetLatestVersion() if err != nil { return false, err } - return version >= db.earliestVersion, nil + return latestVersion >= version && version >= db.earliestVersion, nil } func (db *Database) Has(storeKey []byte, version uint64, key []byte) (bool, error) { diff --git a/store/v2/storage/sqlite/db.go b/store/v2/storage/sqlite/db.go index f648e5ed6cbf..925648928601 100644 --- a/store/v2/storage/sqlite/db.go +++ b/store/v2/storage/sqlite/db.go @@ -128,28 +128,12 @@ func (db *Database) GetLatestVersion() (uint64, error) { } func (db *Database) VersionExists(v uint64) (bool, error) { - stmt, err := db.storage.Prepare(` - SELECT COUNT(*) - FROM state_storage - WHERE store_key != ? AND version = ? - `) + latestVersion, err := db.GetLatestVersion() if err != nil { - return false, fmt.Errorf("failed to prepare SQL statement: %w", err) - } - - defer stmt.Close() - - var latestHeight uint64 - if err := stmt.QueryRow(reservedStoreKey, keyLatestHeight).Scan(&latestHeight); err != nil { - if errors.Is(err, sql.ErrNoRows) { - // in case of a fresh database - return false, nil - } - - return false, fmt.Errorf("failed to query row: %w", err) + return false, err } - return latestHeight >= v && db.earliestVersion <= v, nil + return latestVersion >= v && v >= db.earliestVersion, nil } func (db *Database) SetLatestVersion(version uint64) error { diff --git a/store/v2/storage/sqlite/db_test.go b/store/v2/storage/sqlite/db_test.go index 85d99c582826..fc4c27e6bfd9 100644 --- a/store/v2/storage/sqlite/db_test.go +++ b/store/v2/storage/sqlite/db_test.go @@ -198,204 +198,3 @@ func TestParallelWriteAndPruning(t *testing.T) { require.NoError(t, err) require.Equal(t, []byte(fmt.Sprintf("val-%d-%03d", version-1, 0)), val) } - -// TestDatabase_VersionExists tests the VersionExists method of the Database struct. -func TestDatabase_VersionExists(t *testing.T) { - // Define test cases - testCases := []struct { - name string - setup func(t *testing.T, db *Database) - version uint64 - expectedExists bool - expectError bool - }{ - { - name: "Fresh database: version 0 does not exist", - setup: func(t *testing.T, db *Database) { - t.Helper() - // No setup needed for fresh database - }, - version: 0, - expectedExists: true, - expectError: false, - }, - { - name: "Fresh database: version 1 does not exist", - setup: func(t *testing.T, db *Database) { - t.Helper() - // No setup needed for fresh database - }, - version: 1, - expectedExists: false, - expectError: false, - }, - { - name: "After setting latest version to 5, version 5 exists", - setup: func(t *testing.T, db *Database) { - t.Helper() - err := db.SetLatestVersion(5) - if err != nil { - t.Fatalf("Setting latest version should not error: %v", err) - } - }, - version: 5, - expectedExists: true, - expectError: false, - }, - { - name: "After setting latest version to 5, version 3 does not exist", - setup: func(t *testing.T, db *Database) { - t.Helper() - err := db.SetLatestVersion(5) - if err != nil { - t.Fatalf("Setting latest version should not error: %v", err) - } - }, - version: 3, - expectedExists: false, // Since tombstone is not set, it's just existence - expectError: false, - }, - { - name: "After setting latest version to 10 and pruning to 5, version 5 does not exist", - setup: func(t *testing.T, db *Database) { - t.Helper() - err := db.SetLatestVersion(10) - if err != nil { - t.Fatalf("Setting latest version should not error: %v", err) - } - - err = db.Prune(5) - if err != nil { - t.Fatalf("Pruning to version 5 should not error: %v", err) - } - }, - version: 5, - expectedExists: false, - expectError: false, - }, - // { - // name: "After setting latest version to 10 and pruning to 5, version 7 exists", - // setup: func(t *testing.T, db *Database) { - // t.Helper() - // err := db.SetLatestVersion(10) - // if err != nil { - // t.Fatalf("Setting latest version should not error: %v", err) - // } - - // err = db.Prune(5) - // if err != nil { - // t.Fatalf("Pruning to version 5 should not error: %v", err) - // } - // }, - // version: 7, - // expectedExists: true, - // expectError: false, - // }, - { - name: "After pruning to version 0, version 0 does not exist", - setup: func(t *testing.T, db *Database) { - t.Helper() - // Prune to version 0 - err := db.Prune(0) - if err != nil { - t.Fatalf("Pruning to version 0 should not error: %v", err) - } - }, - version: 0, - expectedExists: false, - expectError: false, - }, - { - name: "After pruning to version 0, version 1 exists", - setup: func(t *testing.T, db *Database) { - t.Helper() - // Prune to version 0 - err := db.Prune(0) - if err != nil { - t.Fatalf("Pruning to version 0 should not error: %v", err) - } - - // Set latest version to 1 - err = db.SetLatestVersion(1) - if err != nil { - t.Fatalf("Setting latest version should not error: %v", err) - } - }, - version: 1, - expectedExists: true, - expectError: false, - }, - { - name: "After setting and pruning, version does not exist due to tombstone", - setup: func(t *testing.T, db *Database) { - t.Helper() - // Set latest version to 5 - err := db.SetLatestVersion(5) - if err != nil { - t.Fatalf("Setting latest version should not error: %v", err) - } - - // Insert a key with version 3 and tombstone - _, err = db.storage.Exec(upsertStmt, "store1", "key1", "value1", 3, "value1") - if err != nil { - t.Fatalf("Inserting key1 at version 3 should not error: %v", err) - } - - // Mark version 3 as tombstoned - _, err = db.storage.Exec(delStmt, 3, "store1", "key1") - if err != nil { - t.Fatalf("Tombstoning key1 at version 3 should not error: %v", err) - } - - // Prune to version 2 - err = db.Prune(2) - if err != nil { - t.Fatalf("Pruning to version 2 should not error: %v", err) - } - }, - version: 3, - expectedExists: false, - expectError: false, - }, - } - - // Iterate over each test case - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - // Create a temporary directory for the test database - tempDir := t.TempDir() - - // Initialize the database - db, err := New(tempDir) - if err != nil { - t.Fatalf("Initializing the database should not error: %v", err) - } - defer func() { - err := db.Close() - if err != nil { - t.Fatalf("Closing the database should not error: %v", err) - } - }() - - // Setup the database state as per the test case - tc.setup(t, db) - - // Call VersionExists with the specified version - exists, err := db.VersionExists(tc.version) - - // Assert based on expectation - if tc.expectError { - if err == nil { - t.Errorf("Expected an error but got none") - } - } else { - if err != nil { - t.Errorf("Did not expect an error but got one: %v", err) - } - if exists != tc.expectedExists { - t.Errorf("Version existence mismatch: expected %v, got %v", tc.expectedExists, exists) - } - } - }) - } -} diff --git a/store/v2/storage/storage_test_suite.go b/store/v2/storage/storage_test_suite.go index af68102a62cd..fb5ff24a0c90 100644 --- a/store/v2/storage/storage_test_suite.go +++ b/store/v2/storage/storage_test_suite.go @@ -880,6 +880,146 @@ func (s *StorageTestSuite) TestRemovingOldStoreKey() { } } +// TestVersionExists tests the VersionExists method of the Database struct. +func (s *StorageTestSuite) TestVersionExists() { + // Define test cases + testCases := []struct { + name string + setup func(t *testing.T, db *StorageStore) + version uint64 + expectedExists bool + expectError bool + }{ + { + name: "Fresh database: version 0 exists", + setup: func(t *testing.T, db *StorageStore) { + t.Helper() + // No setup needed for fresh database + }, + version: 0, + expectedExists: true, + expectError: false, + }, + { + name: "Fresh database: version 1 exists", + setup: func(t *testing.T, db *StorageStore) { + t.Helper() + // No setup needed for fresh database + }, + version: 1, + expectedExists: false, + expectError: false, + }, + { + name: "After setting latest version to 10, version 5 exists", + setup: func(t *testing.T, db *StorageStore) { + t.Helper() + err := db.SetLatestVersion(10) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + }, + version: 5, + expectedExists: true, // Since pruning hasn't occurred, earliestVersion is still 0 + expectError: false, + }, + { + name: "After setting latest version to 10 and pruning to 5, version 4 does not exist", + setup: func(t *testing.T, db *StorageStore) { + t.Helper() + err := db.SetLatestVersion(10) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + + err = db.Prune(5) + if err != nil { + t.Fatalf("Pruning to version 5 should not error: %v", err) + } + }, + version: 4, + expectedExists: false, + expectError: false, + }, + { + name: "After setting latest version to 10 and pruning to 5, version 5 does not exist", + setup: func(t *testing.T, db *StorageStore) { + t.Helper() + err := db.SetLatestVersion(10) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + + err = db.Prune(5) + if err != nil { + t.Fatalf("Pruning to version 5 should not error: %v", err) + } + }, + version: 5, + expectedExists: false, + expectError: false, + }, + { + name: "After setting latest version to 10 and pruning to 5, version 6 exists", + setup: func(t *testing.T, db *StorageStore) { + t.Helper() + err := db.SetLatestVersion(10) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + + err = db.Prune(5) + if err != nil { + t.Fatalf("Pruning to version 5 should not error: %v", err) + } + }, + version: 6, + expectedExists: true, + expectError: false, + }, + { + name: "After pruning to 0, all versions >=1 exist", + setup: func(t *testing.T, db *StorageStore) { + t.Helper() + err := db.SetLatestVersion(10) + if err != nil { + t.Fatalf("Setting latest version should not error: %v", err) + } + // Prune to version 0 + err = db.Prune(0) + if err != nil { + t.Fatalf("Pruning to version 0 should not error: %v", err) + } + }, + version: 1, + expectedExists: true, + expectError: false, + }, + } + + // Iterate over each test case + for _, tc := range testCases { + s.T().Run(tc.name, func(t *testing.T) { + // Initialize the database for each test + db, err := s.NewDB(t.TempDir()) + require.NoError(t, err, "Failed to initialize the database") + defer db.Close() + + // Setup test environment + tc.setup(t, db) + + // Call VersionExists and check the result + exists, err := db.VersionExists(tc.version) + if tc.expectError { + require.Error(t, err, "Expected error but got none") + } else { + require.NoError(t, err, "Did not expect an error but got one") + require.Equal(t, tc.expectedExists, exists, "Version existence mismatch") + } + }) + } +} + func dbApplyChangeset( t *testing.T, db store.VersionedWriter, From 72feb124cd6521ad07dabfeeb1d616dd65d63e95 Mon Sep 17 00:00:00 2001 From: Cool Developer Date: Tue, 15 Oct 2024 18:10:32 -0400 Subject: [PATCH 6/7] rocksdb fix --- store/v2/storage/rocksdb/db.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/v2/storage/rocksdb/db.go b/store/v2/storage/rocksdb/db.go index 7fce1792a783..248b014f7b4e 100644 --- a/store/v2/storage/rocksdb/db.go +++ b/store/v2/storage/rocksdb/db.go @@ -137,7 +137,7 @@ func (db *Database) VersionExists(version uint64) (bool, error) { return false, err } - return latestVersion >= version && version >= db.earliestVersion, nil + return latestVersion >= version && version >= db.tsLow, nil } func (db *Database) Has(storeKey []byte, version uint64, key []byte) (bool, error) { From fd3909cc08b09b58f57d7cdb060a2819af811dde Mon Sep 17 00:00:00 2001 From: Cool Developer Date: Tue, 15 Oct 2024 18:13:33 -0400 Subject: [PATCH 7/7] bench test fix --- store/v2/storage/storage_bench_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/store/v2/storage/storage_bench_test.go b/store/v2/storage/storage_bench_test.go index 960c144782a9..35ffbbf5f8ae 100644 --- a/store/v2/storage/storage_bench_test.go +++ b/store/v2/storage/storage_bench_test.go @@ -24,12 +24,12 @@ import ( var storeKey1 = []byte("store1") var ( - backends = map[string]func(dataDir string) (store.VersionedDatabase, error){ - "rocksdb_versiondb_opts": func(dataDir string) (store.VersionedDatabase, error) { + backends = map[string]func(dataDir string) (store.VersionedWriter, error){ + "rocksdb_versiondb_opts": func(dataDir string) (store.VersionedWriter, error) { db, err := rocksdb.New(dataDir) return storage.NewStorageStore(db, coretesting.NewNopLogger()), err }, - "pebbledb_default_opts": func(dataDir string) (store.VersionedDatabase, error) { + "pebbledb_default_opts": func(dataDir string) (store.VersionedWriter, error) { db, err := pebbledb.New(dataDir) if err == nil && db != nil { db.SetSync(false) @@ -37,7 +37,7 @@ var ( return storage.NewStorageStore(db, coretesting.NewNopLogger()), err }, - "btree_sqlite": func(dataDir string) (store.VersionedDatabase, error) { + "btree_sqlite": func(dataDir string) (store.VersionedWriter, error) { db, err := sqlite.New(dataDir) return storage.NewStorageStore(db, coretesting.NewNopLogger()), err },