Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem: concurrent map access in multistore #1299

Closed
wants to merge 12 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ jobs:
with:
name: cronos
extraPullNames: dapp
installCommand: "nix-env --quiet -j8 -iA cachix -f https://cachix.org/api/v1/install/1.6.1"
signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
- name: test contracts
if: steps.changed-files.outputs.any_changed == 'true'
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ jobs:
with:
name: cronos
extraPullNames: dapp
installCommand: "nix-env --quiet -j8 -iA cachix -f https://cachix.org/api/v1/install/1.6.1"
# github don't pass secrets for pull request from fork repos,
# in that case the push is disabled naturally.
signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
Expand Down Expand Up @@ -101,6 +102,7 @@ jobs:
with:
name: cronos
extraPullNames: dapp
installCommand: "nix-env --quiet -j8 -iA cachix -f https://cachix.org/api/v1/install/1.6.1"
# github don't pass secrets for pull request from fork repos,
# in that case the push is disabled naturally.
signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## UNRELEASED

- [#1299](https://github.com/crypto-org-chain/cronos/pull/1299) Avoid concurrent map access in multistore on grpc call.


*January 5, 2024*

## v1.1.0-rc2
Expand Down
49 changes: 36 additions & 13 deletions store/rootmulti/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"math"
"sort"
"strings"
"sync"

"cosmossdk.io/errors"
dbm "github.com/cometbft/cometbft-db"
Expand Down Expand Up @@ -50,6 +51,7 @@
sdk46Compact bool
// it's more efficient to export snapshot versions, we can filter out the non-snapshot versions
supportExportNonSnapshotVersion bool
mtx sync.RWMutex
Copy link
Collaborator

@yihuang yihuang Jan 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the error without this change?
what's the difference with the cosmos-sdk's rootmulti.Store, which don't have a mutex.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get trace from testnet

6:39PM INF burned tokens from module account amount=793560000000000000basetcro from=evm module=x/bank 6:39PM INF burned tokens from module account amount=687500000000000000basetcro from=evm module=x/bank 6:39PM INF minted coins from module account amount=687500000000000000basetcro from=evm module=x/bank 6:39PM INF minted coins from module account amount=30155000000000000basetcro from=evm module=x/bank 6:39PM INF Served debug_traceTransaction conn=10.202.3.249:32398 duration=19.023694 err="rpc error: code = Internal desc = TypeError: Assignment to constant variable. at putGas (:449:32(13)) in > 6:39PM INF received proposal module=consensus proposal="Proposal{17469185/0 (04E3A24D45925907C1ECC8771468447CA1803513F8DAFF0F50454B2E888A6C71:1:BB28BAAF84FF, -1) 4911941D6EBB @ 2024-01-17T18:39:58.973407> 6:39PM INF received complete proposal block hash=04E3A24D45925907C1ECC8771468447CA1803513F8DAFF0F50454B2E888A6C71 height=17469185 module=consensus server=node 6:39PM INF finalizing commit of block hash=04E3A24D45925907C1ECC8771468447CA1803513F8DAFF0F50454B2E888A6C71 height=17469185 module=consensus num_txs=0 root=F7E790D6EB8C997D1318E0BA801C53E3CDB1CC09445BFC1> 6:39PM INF executed block height=17469185 module=state num_invalid_txs=0 num_valid_txs=0 server=node fatal error: concurrent map read and map write goroutine 98372662 [running]: github.com/crypto-org-chain/cronos/store/rootmulti.(*Store).GetKVStore(0x40065237d0?, {0x57e3ca0, 0x40002b76f0}) github.com/crypto-org-chain/cronos/store/rootmulti/store.go:235 +0x34 github.com/crypto-org-chain/cronos/versiondb.(*MultiStore).cacheMultiStore(0x40021cd1a0, 0x4028640038) github.com/crypto-org-chain/cronos/versiondb/multistore.go:44 +0xf8 github.com/crypto-org-chain/cronos/versiondb.(*MultiStore).CacheMultiStoreWithVersion(0x0?, 0x10a8f00) github.com/crypto-org-chain/cronos/versiondb/multistore.go:59 +0x40 github.com/cosmos/cosmos-sdk/baseapp.(*BaseApp).CreateQueryContext(_, _, _) github.com/cosmos/cosmos-sdk/baseapp/abci.go:795 +0x174 github.com/cosmos/cosmos-sdk/baseapp.(*BaseApp).RegisterGRPCServer.func1({0x5808dc8, 0x4008044150}, {0x339d240, 0x773b648}, 0x402a978080?, 0x40032da120) github.com/cosmos/cosmos-sdk/baseapp/grpcserver.go:50 +0x11c github.com/grpc-ecosystem/go-grpc-middleware.ChainUnaryServer.func1.1.1({0x5808dc8?, 0x4008044150?}, {0x339d240?, 0x773b648?}) github.com/grpc-ecosystem/go-grpc-middleware/chain.go:25 +0x3c github.com/grpc-ecosystem/go-grpc-middleware/recovery.UnaryServerInterceptor.func1({0x5808dc8?, 0x4008044150?}, {0x339d240?, 0x773b648?}, 0x4008044180?, 0x402a978080?) github.com/grpc-ecosystem/go-grpc-middleware/recovery/interceptors.go:33 +0x98 github.com/grpc-ecosystem/go-grpc-middleware.ChainUnaryServer.func1.1.1({0x5808dc8?, 0x4008044150?}, {0x339d240?, 0x773b648?}) github.com/grpc-ecosystem/go-grpc-middleware/chain.go:25 +0x3c github.com/grpc-ecosystem/go-grpc-middleware.ChainUnaryServer.func1({0x5808dc8, 0x4008044150}, {0x339d240, 0x773b648}, 0x10?, 0x2f8ff60?) github.com/grpc-ecosystem/go-grpc-middleware/chain.go:34 +0xb8 github.com/evmos/ethermint/x/evm/types._Query_Params_Handler({0x3502d80?, 0x40001523c0}, {0x5808dc8, 0x4008044150}, 0x40021e9a28?, 0x4008044180) github.com/evmos/ethermint/x/evm/types/query.pb.go:1975 +0x118 github.com/cosmos/cosmos-sdk/baseapp.(*BaseApp).RegisterGRPCServer.func2({0x3502d80, 0x40001523c0}, {0x5808dc8, 0x4008044150}, 0x349d580?, 0x4005046d80?) github.com/cosmos/cosmos-sdk/baseapp/grpcserver.go:82 +0xcc google.golang.org/grpc.(*Server).processUnaryRPC(0x403f350b40, {0x58201c0, 0x40470d9860}, 0x4005046d80, 0x40470cac60, 0x40470b9490, 0x0) google.golang.org/grpc/server.go:1374 +0xb90 google.golang.org/grpc.(*Server).handleStream(0x403f350b40, {0x58201c0, 0x40470d9860}, 0x4005046d80, 0x0) google.golang.org/grpc/server.go:1751 +0x80c google.golang.org/grpc.(*Server).serveStreams.func1.1() google.golang.org/grpc/server.go:986 +0xb4 created by google.golang.org/grpc.(*Server).serveStreams.func1 google.golang.org/grpc/server.go:997 +0x170 goroutine 1 [semacquire, 3218 minutes]: sync.runtime_Semacquire(0x0?) runtime/sema.go:62 +0x2c sync.(*WaitGroup).Wait(0x40034fee08) sync/waitgroup.go:116 +0x74 golang.org/x/sync/errgroup.(*Group).Wait(0x40034fee00) golang.org/x/sync/errgroup/errgroup.go:53 +0x2c github.com/evmos/ethermint/server.startInProcess(_, {{0x0, 0x0, 0x0}, {0x5825e80, 0x4000c3e020}, 0x4001446400, {0x400124e768, 0x13}, {0x583a020, ...}, ...}, ...) github.com/evmos/ethermint/server/start.go:631 +0x2240 github.com/evmos/ethermint/server.StartCmd.func2.2() github.com/evmos/ethermint/server/start.go:162 +0x54 github.com/evmos/ethermint/server.wrapCPUProfile(0x40015b1720, 0x400149f900) github.com/evmos/ethermint/server/start.go:692 +0x24c github.com/evmos/ethermint/server.StartCmd.func2(0x4001572900?, {0x40015b1840?, 0x0?, 0x2?}) github.com/evmos/ethermint/server/start.go:161 +0x1d8 github.com/spf13/cobra.(*Command).execute(0x4001572900, {0x40015b1820, 0x2, 0x2}) github.com/spf13/cobra/command.go:940 +0x5c4 github.com/spf13/cobra.(*Command).ExecuteC(0x400154c600) github.com/spf13/cobra/command.go:1068 +0x340 github.com/spf13/cobra.(*Command).Execute(...) github.com/spf13/cobra/command.go:992 github.com/spf13/cobra.(*Command).ExecuteContext(...) github.com/spf13/cobra/command.go:985 github.com/cosmos/cosmos-sdk/server/cmd.Execute(0x27af548?, {0x3529fa8, 0x6}, {0x40013b19e0, 0x14}) github.com/cosmos/cosmos-sdk/server/cmd/execute.go:33 +0x164 main.main() github.com/crypto-org-chain/cronos/v2/cmd/cronosd/main.go:13 +0x3c goroutine 12 [select, 3220 minutes]: github.com/desertbit/timer.timerRoutine() github.com/desertbit/timer/timers.go:119 +0xa4 created by github.com/desertbit/timer.init.0 github.com/desertbit/timer/timers.go:15 +0x24 goroutine 13 [select]: go.opencensus.io/stats/view.(*worker).start(0x4000b62680) go.opencensus.io/stats/view/worker.go:292 +0x88 created by go.opencensus.io/stats/view.init.0 go.opencensus.io/stats/view/worker.go:34 +0xa0 goroutine 14 [chan receive, 3220 minutes]: github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache(0x0?) github.com/ethereum/go-ethereum/core/sender_cacher.go:63 +0x34 created by github.com/ethereum/go-ethereum/core.newTxSenderCacher github.com/ethereum/go-ethereum/core/sender_cacher.go:55 +0x78 goroutine 15 [chan receive, 3220 minutes]: github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache(0x4000130240?) github.com/ethereum/go-ethereum/core/sender_cacher.go:63 +0x34 created by github.com/ethereum/go-ethereum/core.newTxSenderCacher github.com/ethereum/go-ethereum/core/sender_cacher.go:55 +0x78 goroutine 16 [chan receive, 3220 minutes]: github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache(0x0?) github.com/ethereum/go-ethereum/core/sender_cacher.go:63 +0x34 created by github.com/ethereum/go-ethereum/core.newTxSenderCacher github.com/ethereum/go-ethereum/core/sender_cacher.go:55 +0x78 goroutine 50 [chan receive, 3220 minutes]: github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache(0x0?) github.com/ethereum/go-ethereum/core/sender_cacher.go:63 +0x34 created by github.com/ethereum/go-ethereum/core.newTxSenderCacher github.com/ethereum/go-ethereum/core/sender_cacher.go:55 +0x78 goroutine 51 [chan receive, 3220 minutes]: github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache(0x0?) github.com/ethereum/go-ethereum/core/sender_cacher.go:63 +0x34 created by github.com/ethereum/go-ethereum/core.newTxSenderCacher github.com/ethereum/go-ethereum/core/sender_cacher.go:55 +0x78 goroutine 52 [chan receive, 3220 minutes]: github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache(0x0?) github.com/ethereum/go-ethereum/core/sender_cacher.go:63 +0x34 created by github.com/ethereum/go-ethereum/core.newTxSenderCacher github.com/ethereum/go-ethereum/core/sender_cacher.go:55 +0x78 goroutine 53 [chan receive, 3220 minutes]: github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache(0x0?) github.com/ethereum/go-ethereum/core/sender_cacher.go:63 +0x34 created by github.com/ethereum/go-ethereum/core.newTxSenderCacher github.com/ethereum/go-ethereum/core/sender_cacher.go:55 +0x78 goroutine 54 [chan receive, 3220 minutes]: github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache(0x0?) github.com/ethereum/go-ethereum/core/sender_cacher.go:63 +0x34 created by github.com/ethereum/go-ethereum/core.newTxSenderCacher github.com/ethereum/go-ethereum/core/sender_cacher.go:55 +0x78 goroutine 55 [chan receive]: github.com/ethereum/go-ethereum/metrics.(*meterArbiter).tick(0x76e32c0) github.com/ethereum/go-ethereum/metrics/meter.go:293 +0x54 created by github.com/ethereum/go-ethereum/metrics.NewMeterForced github.com/ethereum/go-ethereum/metrics/meter.go:71 +0xc0 goroutine 56 [select]: github.com/ethereum/go-ethereum/consensus/ethash.(*remoteSealer).loop(0x4000353e00) github.com/ethereum/go-ethereum/consensus/ethash/sealer.go:279 +0x140 created by github.com/ethereum/go-ethereum/consensus/ethash.startRemoteSealer github.com/ethereum/go-ethereum/consensus/ethash/sealer.go:263 +0x298 goroutine 21 [chan receive, 3220 minutes]: github.com/evmos/ethermint/server.ListenForQuitSignals.func1() github.com/evmos/ethermint/server/util.go:129 +0x44 github.com/evmos/ethermint/server.ListenForQuitSignals.func2() github.com/evmos/ethermint/server/util.go:137 +0x24 golang.org/x/sync/errgroup.(*Group).Go.func1() golang.org/x/sync/errgroup/errgroup.go:75 +0x5c created by golang.org/x/sync/errgroup.(*Group).Go golang.org/x/sync/errgroup/errgroup.go:72 +0x9c goroutine 37 [select]: github.com/alitto/pond.(*WorkerPool).purge(0x40010b8540) github.com/alitto/pond/pond.go:384 +0xe4 created by github.com/alitto/pond.New github.com/alitto/pond/pond.go:144 +0x1e8 goroutine 59 [chan receive]: github.com/rcrowley/go-metrics.(*meterArbiter).tick(0x76e3340) github.com/rcrowley/go-metrics/meter.go:239 +0x30 created by github.com/rcrowley/go-metrics.NewMeter github.com/rcrowley/go-metrics/meter.go:46 +0xcc goroutine 60 [syscall, 3220 minutes]: os/signal.signal_recv() runtime/sigqueue.go:152 +0x30 os/signal.loop() os/signal/signal_unix.go:23 +0x1c created by os/signal.Notify.func1.1 os/signal/signal.go:151 +0x28 goroutine 102 [select, 3220 minutes]: github.com/cometbft/cometbft/proxy.(*multiAppConn).killTMOnClientError(0x4001bd80e0) github.com/cometbft/cometbft/proxy/multi_app_conn.go:140 +0xd0 created by github.com/cometbft/cometbft/proxy.(*multiAppConn).OnStart github.com/cometbft/cometbft/proxy/multi_app_conn.go:120 +0x3c8 goroutine 103 [chan receive]: github.com/cometbft/cometbft/libs/pubsub.(*Server).loop(0x4000e7ccb0, {0x400173a4e0, 0x400173a510}) github.com/cometbft/cometbft/libs/pubsub/pubsub.go:323 +0x5c created by github.com/cometbft/cometbft/libs/pubsub.(*Server).OnStart github.com/cometbft/cometbft/libs/pubsub/pubsub.go:309 +0x94 goroutine 61 [chan receive]: github.com/cometbft/cometbft/state/txindex.(*IndexerService).OnStart.func1() github.com/cometbft/cometbft/state/txindex/indexer_service.go:62 +0x78 created by github.com/cometbft/cometbft/state/txindex.(*IndexerService).OnStart github.com/cometbft/cometbft/state/txindex/indexer_service.go:60 +0x1b0 goroutine 62 [IO wait, 3220 minutes]: internal/poll.runtime_pollWait(0xffff7df11628, 0x72) runtime/netpoll.go:306 +0xa0 internal/poll.(*pollDesc).wait(0x4001f0c100?, 0x325c6a0?, 0x0) internal/poll/fd_poll_runtime.go:84 +0x28 internal/poll.(*pollDesc).waitRead(...) internal/poll/fd_poll_runtime.go:89 internal/poll.(*FD).Accept(0x4001f0c100) internal/poll/fd_unix.go:614 +0x250 net.(*netFD).accept(0x4001f0c100) net/fd_unix.go:172 +0x28 net.(*TCPListener).accept(0x400000f770) net/tcpsock_posix.go:148 +0x28 net.(*TCPListener).Accept(0x400000f770) net/tcpsock.go:297 +0x2c net/http.(*Server).Serve(0x4002189950, {0x5803230, 0x400000f770}) net/http/server.go:3059 +0x2cc net/http.(*Server).ListenAndServe(0x4002189950) net/http/server.go:2988 +0x84 net/http.ListenAndServe(...) net/http/server.go:3242 github.com/cometbft/cometbft/node.NewNodeWithContext.func1() github.com/cometbft/cometbft/node/node.go:1056 +0x128 created by github.com/cometbft/cometbft/node.NewNodeWithContext github.com/cometbft/cometbft/node/node.go:1053 +0xf64 goroutine 63 [IO wait]: internal/poll.runtime_pollWait(0xffff7df11538, 0x72) runtime/netpoll.go:306 +0xa0 internal/poll.(*pollDesc).wait(0x40021fe600?, 0x0?, 0x0) internal/poll/fd_poll_runtime.go:84 +0x28 internal/poll.(*pollDesc).waitRead(...) internal/poll/fd_poll_runtime.go:89 internal/poll.(*FD).Accept(0x40021fe600) internal/poll/fd_unix.go:614 +0x250 net.(*netFD).accept(0x40021fe600) net/fd_unix.go:172 +0x28 net.(*TCPListener).accept(0x400135ed38) net/tcpsock_posix.go:148 +0x28 net.(*TCPListener).Accept(0x400135ed38) net/tcpsock.go:297 +0x2c golang.org/x/net/netutil.(*limitListener).Accept(0x40035c6960) golang.org/x/net/netutil/listen.go:63 +0x74 net/http.(*Server).Serve(0x4000316780, {0x58015b0, 0x40035c6960}) net/http/server.go:3059 +0x2cc github.com/cometbft/cometbft/rpc/jsonrpc/server.Serve({0x58015b0, 0x40035c6960}, {0x57dcf60, 0x40035be500}, {0x580a958, 0x40035c80d0}, 0x40035c2600) github.com/cometbft/cometbft/rpc/jsonrpc/server/http_server.go:62 +0x21c github.com/cometbft/cometbft/node.(*Node).startRPC.func3() github.com/cometbft/cometbft/node/node.go:1339 +0x40 created by github.com/cometbft/cometbft/node.(*Node).startRPC github.com/cometbft/cometbft/node/node.go:1338 +0x824 goroutine 116 [IO wait, 1841 minutes]: internal/poll.runtime_pollWait(0xffff7df11358, 0x72) runtime/netpoll.go:306 +0xa0 internal/poll.(*pollDesc).wait(0x4001f0c180?, 0x0?, 0x0)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, the main difference with sdk version is we modified the stores in Commit(), in the sdk version, I guess the assumption is the Store won't be mutated after loaded, that's why it don't need protection, we can try to fix the mutation itself.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#1302
I have a different solution, WDYT?

}

func NewStore(dir string, logger log.Logger, sdk46Compact bool, supportExportNonSnapshotVersion bool) *Store {
Expand All @@ -69,19 +71,18 @@
// flush writes all the pending change sets to memiavl tree.
func (rs *Store) flush() error {
var changeSets []*memiavl.NamedChangeSet
for key := range rs.stores {
for key, store := range rs.stores {
// it'll unwrap the inter-block cache
store := rs.GetCommitKVStore(key)
if memiavlStore, ok := store.(*memiavlstore.Store); ok {
cs := memiavlStore.PopChangeSet()
if len(cs.Pairs) > 0 {
changeSets = append(changeSets, &memiavl.NamedChangeSet{
Name: key.Name(),
Changeset: cs,
})
}
}
}

Check failure

Code scanning / gosec

the value in the range statement should be _ unless copying a map: want: for key := range m Error

the value in the range statement should be _ unless copying a map: want: for key := range m
sort.SliceStable(changeSets, func(i, j int) bool {
return changeSets[i].Name < changeSets[j].Name
})
Expand All @@ -93,7 +94,10 @@
//
// Implements interface Committer.
func (rs *Store) WorkingHash() []byte {
if err := rs.flush(); err != nil {
rs.mtx.RLock()
err := rs.flush()
rs.mtx.RUnlock()
if err != nil {
panic(err)
}
commitInfo := convertCommitInfo(rs.db.WorkingCommitInfo())
Expand All @@ -105,29 +109,36 @@

// Implements interface Committer
func (rs *Store) Commit() types.CommitID {
if err := rs.flush(); err != nil {
rs.mtx.RLock()
err := rs.flush()
rs.mtx.RUnlock()
if err != nil {
panic(err)
}

for _, store := range rs.stores {
iavlStoreKeys := make([]types.StoreKey, 0)
rs.mtx.RLock()
for key, store := range rs.stores {
if store.GetStoreType() != types.StoreTypeIAVL {
_ = store.Commit()
} else {
iavlStoreKeys = append(iavlStoreKeys, key)
}
}

Check failure

Code scanning / gosec

the value in the range statement should be _ unless copying a map: want: for key := range m Error

the value in the range statement should be _ unless copying a map: want: for key := range m

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
rs.mtx.RUnlock()

_, err := rs.db.Commit()
_, err = rs.db.Commit()
if err != nil {
panic(err)
}

// the underlying memiavl tree might be reloaded, reload the store as well.
for key := range rs.stores {
store := rs.stores[key]
if store.GetStoreType() == types.StoreTypeIAVL {
rs.stores[key], err = rs.loadCommitStoreFromParams(rs.db, key, rs.storesParams[key])
if err != nil {
panic(fmt.Errorf("inconsistent store map, store %s not found", key.Name()))
}
for _, key := range iavlStoreKeys {
rs.mtx.Lock()
rs.stores[key], err = rs.loadCommitStoreFromParams(rs.db, key, rs.storesParams[key])
rs.mtx.Unlock()
if err != nil {
panic(fmt.Errorf("inconsistent store map, store %s not found", key.Name()))
}
}

Expand Down Expand Up @@ -182,6 +193,7 @@
// Implements interface MultiStore
func (rs *Store) CacheMultiStore() types.CacheMultiStore {
stores := make(map[types.StoreKey]types.CacheWrapper)
rs.mtx.RLock()
for k, v := range rs.stores {
store := types.KVStore(v)
// Wire the listenkv.Store to allow listeners to observe the writes from the cache store,
Expand All @@ -191,6 +203,7 @@
}
stores[k] = store
}
rs.mtx.RUnlock()
return cachemulti.NewStore(nil, stores, rs.keysByName, nil, nil, nil)
}

Expand All @@ -211,11 +224,13 @@
stores := make(map[types.StoreKey]types.CacheWrapper)

// add the transient/mem stores registered in current app.
rs.mtx.RLock()
for k, store := range rs.stores {
if store.GetStoreType() != types.StoreTypeIAVL {
stores[k] = store
}
}
rs.mtx.RUnlock()

// add all the iavl stores at the target version.
for _, tree := range db.Trees() {
Expand All @@ -227,11 +242,15 @@

// Implements interface MultiStore
func (rs *Store) GetStore(key types.StoreKey) types.Store {
rs.mtx.RLock()
defer rs.mtx.RUnlock()
return rs.stores[key]
}

// Implements interface MultiStore
func (rs *Store) GetKVStore(key types.StoreKey) types.KVStore {
rs.mtx.RLock()
defer rs.mtx.RUnlock()
return rs.stores[key]
}

Expand Down Expand Up @@ -287,6 +306,8 @@

// Implements interface CommitMultiStore
func (rs *Store) GetCommitKVStore(key types.StoreKey) types.CommitKVStore {
rs.mtx.RLock()
defer rs.mtx.RUnlock()
return rs.stores[key]
}

Expand Down Expand Up @@ -361,7 +382,9 @@
}

rs.db = db
rs.mtx.Lock()
rs.stores = newStores
rs.mtx.Unlock()
// to keep the root hash compatible with cosmos-sdk 0.46
if db.Version() != 0 {
rs.lastCommitInfo = convertCommitInfo(db.LastCommitInfo())
Expand Down
Loading