feat(store/v2): Fallback to SC on queries (#19090)

This commit is contained in:
Aleksandr Bezobchuk
2024-01-19 15:11:15 +00:00
committed by GitHub
parent 2587e756c1
commit 8d0696326b
7 changed files with 107 additions and 12 deletions
+24 -9
View File
@@ -105,13 +105,13 @@ func (s *Store) StateLatest() (uint64, store.ReadOnlyRootStore, error) {
}
func (s *Store) StateAt(v uint64) (store.ReadOnlyRootStore, error) {
// TODO(bez): Ensure the version <v> exists. We can utilize the GetCommitInfo()
// SC method once available.
// 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/pull/18736
// if err := s.stateCommitment.GetCommitInfo(v); err != nil {
// return nil, fmt.Errorf("failed to get commit info for version %d: %w", v, err)
// }
// 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)
}
return NewReadOnlyAdapter(v, s), nil
}
@@ -174,8 +174,23 @@ func (s *Store) Query(storeKey string, version uint64, key []byte, prove bool) (
}
val, err := s.stateStore.Get(storeKey, version, key)
if err != nil {
return store.QueryResult{}, err
if err != nil || val == nil {
// fallback to querying SC backend if not found in SS backend
//
// Note, this should only used during migration, i.e. while SS and IAVL v2
// are being asynchronously synced.
if val == nil {
bz, scErr := s.stateCommitment.Get(storeKey, version, key)
if scErr != nil {
return store.QueryResult{}, fmt.Errorf("failed to query SC store: %w", scErr)
}
val = bz
}
if err != nil {
return store.QueryResult{}, fmt.Errorf("failed to query SS store: %w", err)
}
}
result := store.QueryResult{
@@ -187,7 +202,7 @@ func (s *Store) Query(storeKey string, version uint64, key []byte, prove bool) (
if prove {
result.ProofOps, err = s.stateCommitment.GetProof(storeKey, version, key)
if err != nil {
return store.QueryResult{}, err
return store.QueryResult{}, fmt.Errorf("failed to get SC store proof: %w", err)
}
}
+25
View File
@@ -104,6 +104,31 @@ func (s *RootStoreTestSuite) TestQuery() {
s.Require().Equal([]byte("foo"), result.ProofOps[0].Key)
}
func (s *RootStoreTestSuite) TestGetFallback() {
sc := s.rootStore.GetStateCommitment()
// create a changeset and commit it to SC ONLY
cs := store.NewChangeset()
cs.Add(testStoreKey, []byte("foo"), []byte("bar"))
err := sc.WriteBatch(cs)
s.Require().NoError(err)
ci := sc.WorkingCommitInfo(1)
_, err = sc.Commit(ci.Version)
s.Require().NoError(err)
// ensure we can query for the key, which should fallback to SC
qResult, err := s.rootStore.Query(testStoreKey, 1, []byte("foo"), false)
s.Require().NoError(err)
s.Require().Equal([]byte("bar"), qResult.Value)
// non-existent key
qResult, err = s.rootStore.Query(testStoreKey, 1, []byte("non_existent_key"), false)
s.Require().NoError(err)
s.Require().Nil(qResult.Value)
}
func (s *RootStoreTestSuite) TestQueryProof() {
cs := store.NewChangeset()
// testStoreKey