diff --git a/sei-cosmos/storev2/rootmulti/store.go b/sei-cosmos/storev2/rootmulti/store.go index 6284d4def7..ff02872b44 100644 --- a/sei-cosmos/storev2/rootmulti/store.go +++ b/sei-cosmos/storev2/rootmulti/store.go @@ -398,11 +398,15 @@ func (rs *Store) CacheMultiStoreFromCommitter(snap sctypes.Committer) (types.Cac // GetStore Implements interface MultiStore func (rs *Store) GetStore(key types.StoreKey) types.Store { + rs.mtx.RLock() + defer rs.mtx.RUnlock() return rs.ckvStores[key] } // GetKVStore Implements interface MultiStore func (rs *Store) GetKVStore(key types.StoreKey) types.KVStore { + rs.mtx.RLock() + defer rs.mtx.RUnlock() return rs.ckvStores[key] } @@ -453,6 +457,8 @@ func (rs *Store) GetCommitStore(key types.StoreKey) types.CommitStore { // GetCommitKVStore Implements interface CommitMultiStore func (rs *Store) GetCommitKVStore(key types.StoreKey) types.CommitKVStore { + rs.mtx.RLock() + defer rs.mtx.RUnlock() return rs.ckvStores[key] } diff --git a/sei-cosmos/storev2/rootmulti/store_test.go b/sei-cosmos/storev2/rootmulti/store_test.go index 4d505aa981..90b7aa98c9 100644 --- a/sei-cosmos/storev2/rootmulti/store_test.go +++ b/sei-cosmos/storev2/rootmulti/store_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/sei-protocol/sei-chain/sei-cosmos/store/mem" "github.com/sei-protocol/sei-chain/sei-cosmos/store/types" "github.com/sei-protocol/sei-chain/sei-cosmos/storev2/state" "github.com/sei-protocol/sei-chain/sei-db/config" @@ -15,6 +16,35 @@ import ( "golang.org/x/time/rate" ) +func TestGetCommitKVStore_ReaderRespectsWriteLock(t *testing.T) { + store := &Store{ + storeKeys: map[string]types.StoreKey{}, + ckvStores: map[types.StoreKey]types.CommitKVStore{}, + } + key := types.NewKVStoreKey("bank") + store.storeKeys[key.Name()] = key + store.ckvStores[key] = mem.NewStore() + + store.mtx.Lock() + + readDone := make(chan types.CommitKVStore, 1) + go func() { + readDone <- store.GetCommitKVStore(key) //GetCommitKVStore is blocked until store.mtx is unlocked + }() + + select { + case <-readDone: + t.Fatal("GetCommitKVStore returned while write lock held — RLock missing") + case <-time.After(50 * time.Millisecond): + } + + newVal := mem.NewStore() + store.ckvStores = map[types.StoreKey]types.CommitKVStore{key: newVal} + store.mtx.Unlock() + + require.Same(t, newVal, <-readDone) +} + func TestLastCommitID(t *testing.T) { store := NewStore(t.TempDir(), config.DefaultStateCommitConfig(), config.StateStoreConfig{}, []string{}) require.Equal(t, types.CommitID{}, store.LastCommitID())