diff --git a/CHANGELOG.md b/CHANGELOG.md index 04ec986ce48f..81c216cfe6cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/group) [#14071](https://github.com/cosmos/cosmos-sdk/pull/14071) Don't re-tally proposal after voting period end if they have been marked as ACCEPTED or REJECTED. +### API Breaking Changes + +* (store) [#13529](https://github.com/cosmos/cosmos-sdk/pull/13529) Add method `LatestVersion` to `MultiStore` interface, add method `SetQueryMultiStore` to baesapp to support alternative `MultiStore` implementation for query service. + ### Bug Fixes * (baseapp) [#13983](https://github.com/cosmos/cosmos-sdk/pull/13983) Don't emit duplicate ante-handler events when a post-handler is defined. diff --git a/baseapp/abci.go b/baseapp/abci.go index aa631f177a77..231eb7dcf6d9 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -921,7 +921,13 @@ func (app *BaseApp) ExtendVote(_ context.Context, req *abci.ExtendVoteRequest) ( return nil, errors.New("application ExtendVote handler not set") } - lastBlockHeight := app.LastBlockHeight() + // use custom query multistore if provided + qms := app.qms + if qms == nil { + qms = sdk.MultiStore(app.cms) + } + + lastBlockHeight := qms.LatestVersion() if height > lastBlockHeight { return sdk.Context{}, sdkerrors.Wrap( @@ -961,7 +967,7 @@ func (app *BaseApp) ExtendVote(_ context.Context, req *abci.ExtendVoteRequest) ( } }() - resp, err = app.extendVote(ctx, req) + cacheMS, err := qms.CacheMultiStoreWithVersion(height) if err != nil { return sdk.Context{}, sdkerrors.Wrapf( diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 9116cc389b8f..1f3c7242a252 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -120,6 +120,7 @@ type BaseApp struct { //nolint: maligned type appStore struct { db dbm.DB // common DB backend cms sdk.CommitMultiStore // Main (uncached) state + qms sdk.MultiStore // Optional alternative state provider for query service storeLoader StoreLoader // function to handle store loading, may be overridden with SetStoreLoader() // an inter-block write-through cache provided to the context during deliverState diff --git a/baseapp/options.go b/baseapp/options.go index a828c64a593f..46567944df5c 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -408,3 +408,13 @@ func (app *BaseApp) SetStreamingService(s StreamingService) { // BaseApp will pass BeginBlock, DeliverTx, and EndBlock requests and responses to the streaming services to update their ABCI context app.abciListeners = append(app.abciListeners, s) } + +// SetQueryMultiStore set a alternative MultiStore implementation to support grpc query service. +// +// Ref: https://github.com/cosmos/cosmos-sdk/issues/13317 +func (app *BaseApp) SetQueryMultiStore(ms sdk.MultiStore) { + if app.sealed { + panic("SetQueryMultiStore() on sealed BaseApp") + } + app.qms = ms +} diff --git a/server/mock/store.go b/server/mock/store.go index a176d12a52fb..b10676aac65b 100644 --- a/server/mock/store.go +++ b/server/mock/store.go @@ -159,6 +159,10 @@ func (ms multiStore) RollbackToVersion(version int64) error { panic("not implemented") } +func (ms multiStore) LatestVersion() int64 { + panic("not implemented") +} + var _ sdk.KVStore = kvStore{} type kvStore struct { diff --git a/store/cachemulti/store.go b/store/cachemulti/store.go index 3b0265cb0f22..c65cdd8a39b3 100644 --- a/store/cachemulti/store.go +++ b/store/cachemulti/store.go @@ -113,6 +113,28 @@ func (cms Store) TracingEnabled() bool { return cms.traceWriter != nil } +// AddListeners adds listeners for a specific KVStore +func (cms Store) AddListeners(key types.StoreKey, listeners []types.WriteListener) { + if ls, ok := cms.listeners[key]; ok { + cms.listeners[key] = append(ls, listeners...) + } else { + cms.listeners[key] = listeners + } +} + +// ListeningEnabled returns if listening is enabled for a specific KVStore +func (cms Store) ListeningEnabled(key types.StoreKey) bool { + if ls, ok := cms.listeners[key]; ok { + return len(ls) != 0 + } + return false +} + +// LatestVersion returns the branch version of the store +func (cms Store) LatestVersion() int64 { + panic("cannot get latest version from branch cached multi-store") +} + // GetStoreType returns the type of the store. func (cms Store) GetStoreType() types.StoreType { return types.StoreTypeMulti diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index f21036077530..ef711a0d5e29 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -386,24 +386,6 @@ func (rs *Store) ListeningEnabled(key types.StoreKey) bool { return false } -// PopStateCache returns the accumulated state change messages from the CommitMultiStore -// Calling PopStateCache destroys only the currently accumulated state in each listener -// not the state in the store itself. This is a mutating and destructive operation. -// This method has been synchronized. -func (rs *Store) PopStateCache() []*types.StoreKVPair { - var cache []*types.StoreKVPair - for key := range rs.listeners { - ls := rs.listeners[key] - if ls != nil { - cache = append(cache, ls.PopStateCache()...) - } - } - sort.SliceStable(cache, func(i, j int) bool { - return cache[i].StoreKey < cache[j].StoreKey - }) - return cache -} - // LatestVersion returns the latest version in the store func (rs *Store) LatestVersion() int64 { return rs.LastCommitID().Version diff --git a/store/types/store.go b/store/types/store.go index a0874efa38c0..58ffcba8192e 100644 --- a/store/types/store.go +++ b/store/types/store.go @@ -159,6 +159,16 @@ type MultiStore interface { // implied that the caller should update the context when necessary between // tracing operations. The modified MultiStore is returned. SetTracingContext(TraceContext) MultiStore + + // ListeningEnabled returns if listening is enabled for the KVStore belonging the provided StoreKey + ListeningEnabled(key StoreKey) bool + + // AddListeners adds WriteListeners for the KVStore belonging to the provided StoreKey + // It appends the listeners to a current set, if one already exists + AddListeners(key StoreKey, listeners []WriteListener) + + // LatestVersion returns the latest version in the store + LatestVersion() int64 } // CacheMultiStore is from MultiStore.CacheMultiStore()....