From 56bbc887f83c86cc2cfa4c8e8dffc04d1c21cf8f Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Fri, 19 Jul 2019 13:20:56 -0400 Subject: [PATCH 01/70] Update BaseApp state type --- baseapp/baseapp.go | 96 +++++++++++++++++++++++----------------------- baseapp/helpers.go | 4 +- 2 files changed, 49 insertions(+), 51 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index d421a4f07663..f5b8ef5a27ea 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -63,14 +63,16 @@ type BaseApp struct { idPeerFilter sdk.PeerFilter // filter peers by node ID fauxMerkleMode bool // if true, IAVL MountStores uses MountStoresDB for simulation speed. - // -------------------- - // Volatile state - // checkState is set on initialization and reset on Commit. - // deliverState is set in InitChain and BeginBlock and cleared on Commit. - // See methods setCheckState and setDeliverState. - checkState *state // for CheckTx - deliverState *state // for DeliverTx - voteInfos []abci.VoteInfo // absent validators from begin block + // volatile state: + // + // checkState is set on initialization and reset on Commit + // deliverState is set in InitChain and BeginBlock and cleared on Commit + // + // see methods setCheckState and setDeliverState + checkState *state // for CheckTx + deliverState *state // for DeliverTx + + voteInfos []abci.VoteInfo // absent validators from begin block // consensus params // TODO: Move this in the future to baseapp param store on main store. @@ -265,27 +267,21 @@ func (app *BaseApp) Seal() { app.sealed = true } // IsSealed returns true if the BaseApp is sealed and false otherwise. func (app *BaseApp) IsSealed() bool { return app.sealed } -// setCheckState sets checkState with the cached multistore and -// the context wrapping it. -// It is called by InitChain() and Commit() +// setCheckState sets the CheckTx state context with a cached multi-store. It is +// called by InitChain and Commit. func (app *BaseApp) setCheckState(header abci.Header) { - ms := app.cms.CacheMultiStore() - app.checkState = &state{ - ms: ms, - ctx: sdk.NewContext(ms, header, true, app.logger).WithMinGasPrices(app.minGasPrices), - } + app.checkState = newState( + sdk.NewContext(app.cms.CacheMultiStore(), header, true, app.logger). + WithMinGasPrices(app.minGasPrices), + ) } -// setCheckState sets checkState with the cached multistore and -// the context wrapping it. -// It is called by InitChain() and BeginBlock(), -// and deliverState is set nil on Commit(). +// setDeliverState sets the DeliverTx state context with a cached multi-store. +// It is called by InitChain and BeginBlock. It is reset (set to nil) on Commit. func (app *BaseApp) setDeliverState(header abci.Header) { - ms := app.cms.CacheMultiStore() - app.deliverState = &state{ - ms: ms, - ctx: sdk.NewContext(ms, header, false, app.logger), - } + app.deliverState = newState( + sdk.NewContext(app.cms.CacheMultiStore(), header, false, app.logger), + ) } // setConsensusParams memoizes the consensus params. @@ -364,11 +360,9 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC } // add block gas meter for any genesis transactions (allow infinite gas) - app.deliverState.ctx = app.deliverState.ctx. - WithBlockGasMeter(sdk.NewInfiniteGasMeter()) - - res = app.initChainer(app.deliverState.ctx, req) + app.deliverState = newState(app.deliverState.WithBlockGasMeter(sdk.NewInfiniteGasMeter())) + res = app.initChainer(app.deliverState.Context, req) // sanity check if len(req.Validators) > 0 { if len(req.Validators) != len(res.Validators) { @@ -376,8 +370,10 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC "len(RequestInitChain.Validators) != len(validators) (%d != %d)", len(req.Validators), len(res.Validators))) } + sort.Sort(abci.ValidatorUpdates(req.Validators)) sort.Sort(abci.ValidatorUpdates(res.Validators)) + for i, val := range res.Validators { if !val.Equal(req.Validators[i]) { panic(fmt.Errorf("validators[%d] != req.Validators[%d] ", i, i)) @@ -533,7 +529,7 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res // cache wrap the commit-multistore for safety ctx := sdk.NewContext( - app.cms.CacheMultiStore(), app.checkState.ctx.BlockHeader(), true, app.logger, + app.cms.CacheMultiStore(), app.checkState.BlockHeader(), true, app.logger, ).WithMinGasPrices(app.minGasPrices) if req.Height > 0 { @@ -595,11 +591,9 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg if app.deliverState == nil { app.setDeliverState(req.Header) } else { - // In the first block, app.deliverState.ctx will already be initialized + // In the first block, app.deliverState will already be initialized // by InitChain. Context is now updated with Header information. - app.deliverState.ctx = app.deliverState.ctx. - WithBlockHeader(req.Header). - WithBlockHeight(req.Header.Height) + app.deliverState = newState(app.deliverState.WithBlockHeader(req.Header).WithBlockHeight(req.Header.Height)) } // add block gas meter @@ -610,10 +604,10 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg gasMeter = sdk.NewInfiniteGasMeter() } - app.deliverState.ctx = app.deliverState.ctx.WithBlockGasMeter(gasMeter) + app.deliverState = newState(app.deliverState.WithBlockGasMeter(gasMeter)) if app.beginBlocker != nil { - res = app.beginBlocker(app.deliverState.ctx, req) + res = app.beginBlocker(app.deliverState.Context, req) } // set the signed validators for addition to context in deliverTx @@ -688,7 +682,7 @@ func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error { // retrieve the context for the tx w/ txBytes and other memoized values. func (app *BaseApp) getContextForTx(mode runTxMode, txBytes []byte) (ctx sdk.Context) { - ctx = app.getState(mode).ctx. + ctx = app.getState(mode). WithTxBytes(txBytes). WithVoteInfos(app.voteInfos). WithConsensusParams(app.consensusParams) @@ -920,12 +914,12 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk // EndBlock implements the ABCI interface. func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) { - if app.deliverState.ms.TracingEnabled() { - app.deliverState.ms = app.deliverState.ms.SetTracingContext(nil).(sdk.CacheMultiStore) + if app.deliverState.MultiStore().TracingEnabled() { + app.deliverState = newState(app.deliverState.WithMultiStore(app.deliverState.MultiStore().SetTracingContext(nil))) } if app.endBlocker != nil { - res = app.endBlocker(app.deliverState.ctx, req) + res = app.endBlocker(app.deliverState.Context, req) } return @@ -939,10 +933,11 @@ func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBloc // against that height and gracefully halt if it matches the latest committed // height. func (app *BaseApp) Commit() (res abci.ResponseCommit) { - header := app.deliverState.ctx.BlockHeader() + header := app.deliverState.BlockHeader() + + // write the DeliverTx state and commit the multi-store + app.deliverState.MultiStore().(store.CacheMultiStore).Write() - // write the Deliver state and commit the MultiStore - app.deliverState.ms.Write() commitID := app.cms.Commit() app.logger.Debug("Commit synced", "commit", fmt.Sprintf("%X", commitID)) @@ -970,15 +965,18 @@ func (app *BaseApp) Commit() (res abci.ResponseCommit) { // ---------------------------------------------------------------------------- // State +// state is a simple wrapper around a Context object. There is a unique state +// for both CheckTx and DeliverTx respectively. type state struct { - ms sdk.CacheMultiStore - ctx sdk.Context + sdk.Context } -func (st *state) CacheMultiStore() sdk.CacheMultiStore { - return st.ms.CacheMultiStore() +func newState(ctx sdk.Context) *state { + return &state{ctx} } -func (st *state) Context() sdk.Context { - return st.ctx +// CacheMultiStore returns a cache-wrapped version of the state context's +// multi-store. +func (st *state) CacheMultiStore() sdk.CacheMultiStore { + return st.MultiStore().CacheMultiStore() } diff --git a/baseapp/helpers.go b/baseapp/helpers.go index 25f59cee5e77..ecb0e72c9d58 100644 --- a/baseapp/helpers.go +++ b/baseapp/helpers.go @@ -29,9 +29,9 @@ func (app *BaseApp) Deliver(tx sdk.Tx) (result sdk.Result) { // used by tests func (app *BaseApp) NewContext(isCheckTx bool, header abci.Header) sdk.Context { if isCheckTx { - return sdk.NewContext(app.checkState.ms, header, true, app.logger). + return sdk.NewContext(app.checkState.MultiStore(), header, true, app.logger). WithMinGasPrices(app.minGasPrices) } - return sdk.NewContext(app.deliverState.ms, header, false, app.logger) + return sdk.NewContext(app.deliverState.MultiStore(), header, false, app.logger) } From 557804362ce0bd8f79be6f18f1fe04627f0aa0d4 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 22 Jul 2019 11:24:23 -0400 Subject: [PATCH 02/70] Implement inter block caching layer --- go.mod | 2 +- go.sum | 2 + store/cachemulti/cache.go | 104 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 store/cachemulti/cache.go diff --git a/go.mod b/go.mod index f20d9f8e5b81..63cb2ace24b2 100644 --- a/go.mod +++ b/go.mod @@ -9,9 +9,9 @@ require ( github.com/fortytw2/leaktest v1.3.0 // indirect github.com/gogo/protobuf v1.2.1 github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129 - github.com/golang/protobuf v1.3.0 github.com/gorilla/mux v1.7.0 github.com/gorilla/websocket v1.4.0 // indirect + github.com/hashicorp/golang-lru v0.5.1 github.com/mattn/go-isatty v0.0.6 github.com/pelletier/go-toml v1.2.0 github.com/pkg/errors v0.8.1 diff --git a/go.sum b/go.sum index 72d7f35eedff..d08330b83bb0 100644 --- a/go.sum +++ b/go.sum @@ -77,6 +77,8 @@ github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= diff --git a/store/cachemulti/cache.go b/store/cachemulti/cache.go new file mode 100644 index 000000000000..40aaa235778b --- /dev/null +++ b/store/cachemulti/cache.go @@ -0,0 +1,104 @@ +package cachemulti + +import ( + "github.com/cosmos/cosmos-sdk/store/types" + + "fmt" + + "github.com/hashicorp/golang-lru" +) + +const ( + defaultCacheSize = 10000 +) + +var ( + _ types.KVStore = (*StoreCache)(nil) + _ types.CacheWrap = (*StoreCache)(nil) + + // The interBlockCache contains an inter-block write-through cache for each + // KVStore. Each underlying KVStore itself may be cache-wrapped, but the + // cache here is persistent through block production. + interBlockCache = NewStoreCacheManager() +) + +type ( + // StoreCache defines a cache that is meant to be used in a persistent + // (inter-block) fashion and which wraps an underlying KVStore. Reads first + // hit the ARC (Adaptive Replacement Cache). During a cache miss, the read + // is delegated to the underlying KVStore. Deletes and writes always happen + // to both the cache and the KVStore in a write-through manner. Caching + // performed in the KVStore is completely irrelevant to this layer. + StoreCache struct { + types.KVStore + cache *lru.ARCCache + } + + // StoreCacheManager defines a manager that handles a mapping of StoreKeys + // to StoreCache references. Each StoreCache reference is meant to be + // persistent between blocks. + StoreCacheManager struct { + caches map[types.StoreKey]*StoreCache + } +) + +func newStoreCache(store types.KVStore) *StoreCache { + cache, err := lru.NewARC(defaultCacheSize) + if err != nil { + panic(fmt.Errorf("failed to create cache: %s", err)) + } + + return &StoreCache{ + KVStore: store, + cache: cache, + } +} + +func NewStoreCacheManager() *StoreCacheManager { + return &StoreCacheManager{ + caches: make(map[types.StoreKey]*StoreCache), + } +} + +// GetOrSetStoreCache attempts to get a CacheWrap store from the StoreCacheManager. +// If the CacheWrap does not exist in the mapping, it is added. Each CacheWrap +// store contains a persistent cache through the StoreCache. +func (cmgr *StoreCacheManager) GetOrSetStoreCache(key types.StoreKey, store types.CacheWrap) types.CacheWrap { + if cmgr.caches[key] == nil { + cmgr.caches[key] = newStoreCache(store.(types.KVStore)) + } + + return cmgr.caches[key] +} + +// Write implements the CacheWrap interface and simply delegates the Write call +// to the underlying KVStore. +func (sc *StoreCache) Write() { + sc.KVStore.(types.CacheWrap).Write() +} + +// Get retrieves a value by key. It will first look in the write-through cache. +// If the value doesn't exist in the write-through cache, the Get call is +// delegated to the underlying KVStore. +func (sc *StoreCache) Get(key []byte) []byte { + val, ok := sc.cache.Get(string(key)) + if ok { + return val.([]byte) + } + + return sc.KVStore.Get(key) +} + +// Set inserts a key/value pair into both the write-through cache and the +// underlying KVStore. +func (sc *StoreCache) Set(key, value []byte) { + sc.cache.Add(string(key), value) + sc.KVStore.Set(key, value) +} + +// Delete removes a key/value pair from both the write-through cache and the +// underlying KVStore. +func (sc *StoreCache) Delete(key []byte) { + sc.cache.Remove(string(key)) + sc.KVStore.Delete(key) +} From 81f7dc18a50e25e529d64922a9fe3ce55b129a74 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 22 Jul 2019 11:29:18 -0400 Subject: [PATCH 03/70] Update the cache multi-store to use new layer --- store/cachekv/store.go | 4 +++- store/cachemulti/cache.go | 10 +++++----- store/cachemulti/store.go | 8 ++++++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/store/cachekv/store.go b/store/cachekv/store.go index 259a888af655..1bc347d4044f 100644 --- a/store/cachekv/store.go +++ b/store/cachekv/store.go @@ -34,7 +34,6 @@ type Store struct { var _ types.CacheKVStore = (*Store)(nil) -// nolint func NewStore(parent types.KVStore) *Store { return &Store{ cache: make(map[string]*cValue), @@ -53,6 +52,7 @@ func (store *Store) GetStoreType() types.StoreType { func (store *Store) Get(key []byte) (value []byte) { store.mtx.Lock() defer store.mtx.Unlock() + types.AssertValidKey(key) cacheValue, ok := store.cache[string(key)] @@ -70,6 +70,7 @@ func (store *Store) Get(key []byte) (value []byte) { func (store *Store) Set(key []byte, value []byte) { store.mtx.Lock() defer store.mtx.Unlock() + types.AssertValidKey(key) types.AssertValidValue(value) @@ -86,6 +87,7 @@ func (store *Store) Has(key []byte) bool { func (store *Store) Delete(key []byte) { store.mtx.Lock() defer store.mtx.Unlock() + types.AssertValidKey(key) store.setCacheValue(key, nil, true, true) diff --git a/store/cachemulti/cache.go b/store/cachemulti/cache.go index 40aaa235778b..db95b4d27421 100644 --- a/store/cachemulti/cache.go +++ b/store/cachemulti/cache.go @@ -8,10 +8,6 @@ import ( "github.com/hashicorp/golang-lru" ) -const ( - defaultCacheSize = 10000 -) - var ( _ types.KVStore = (*StoreCache)(nil) _ types.CacheWrap = (*StoreCache)(nil) @@ -20,6 +16,10 @@ var ( // KVStore. Each underlying KVStore itself may be cache-wrapped, but the // cache here is persistent through block production. interBlockCache = NewStoreCacheManager() + + // PersistentStoreCacheSize defines the persistent ARC cache size for each + // KVStore. + PersistentStoreCacheSize = 1000 ) type ( @@ -43,7 +43,7 @@ type ( ) func newStoreCache(store types.KVStore) *StoreCache { - cache, err := lru.NewARC(defaultCacheSize) + cache, err := lru.NewARC(PersistentStoreCacheSize) if err != nil { panic(fmt.Errorf("failed to create cache: %s", err)) } diff --git a/store/cachemulti/store.go b/store/cachemulti/store.go index 4ac54ce07780..16b5c9c9730f 100644 --- a/store/cachemulti/store.go +++ b/store/cachemulti/store.go @@ -42,11 +42,15 @@ func NewFromKVStore( } for key, store := range stores { + var cacheWrappedStore types.CacheWrap + if cms.TracingEnabled() { - cms.stores[key] = store.CacheWrapWithTrace(cms.traceWriter, cms.traceContext) + cacheWrappedStore = store.CacheWrapWithTrace(cms.traceWriter, cms.traceContext) } else { - cms.stores[key] = store.CacheWrap() + cacheWrappedStore = store.CacheWrap() } + + cms.stores[key] = interBlockCache.GetOrSetStoreCache(key, cacheWrappedStore) } return cms From 2bc2ec246c1248685731b498319605f6e5c51082 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 22 Jul 2019 11:36:09 -0400 Subject: [PATCH 04/70] Fix constructor --- store/cachemulti/cache.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/store/cachemulti/cache.go b/store/cachemulti/cache.go index db95b4d27421..5ee0d3804e20 100644 --- a/store/cachemulti/cache.go +++ b/store/cachemulti/cache.go @@ -42,7 +42,7 @@ type ( } ) -func newStoreCache(store types.KVStore) *StoreCache { +func NewStoreCache(store types.KVStore) *StoreCache { cache, err := lru.NewARC(PersistentStoreCacheSize) if err != nil { panic(fmt.Errorf("failed to create cache: %s", err)) @@ -65,7 +65,7 @@ func NewStoreCacheManager() *StoreCacheManager { // store contains a persistent cache through the StoreCache. func (cmgr *StoreCacheManager) GetOrSetStoreCache(key types.StoreKey, store types.CacheWrap) types.CacheWrap { if cmgr.caches[key] == nil { - cmgr.caches[key] = newStoreCache(store.(types.KVStore)) + cmgr.caches[key] = NewStoreCache(store.(types.KVStore)) } return cmgr.caches[key] From 580119f3829bd5ba9fa6274e0b9e69c890aba97a Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 22 Jul 2019 12:22:50 -0400 Subject: [PATCH 05/70] Add unit tests --- store/cachemulti/cache_test.go | 64 ++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 store/cachemulti/cache_test.go diff --git a/store/cachemulti/cache_test.go b/store/cachemulti/cache_test.go new file mode 100644 index 000000000000..5e2198ffde2b --- /dev/null +++ b/store/cachemulti/cache_test.go @@ -0,0 +1,64 @@ +package cachemulti_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + "github.com/tendermint/iavl" + dbm "github.com/tendermint/tendermint/libs/db" + + "github.com/cosmos/cosmos-sdk/store/cachemulti" + iavlstore "github.com/cosmos/cosmos-sdk/store/iavl" + "github.com/cosmos/cosmos-sdk/store/types" +) + +func TestGetOrSetStoreCache(t *testing.T) { + db := dbm.NewMemDB() + tree := iavl.NewMutableTree(db, 100) + store := iavlstore.UnsafeNewStore(tree, 10, 10) + cwStore := store.CacheWrap() + + mngr := cachemulti.NewStoreCacheManager() + sKey := types.NewKVStoreKey("test") + cwStore2 := mngr.GetOrSetStoreCache(sKey, cwStore) + + require.NotNil(t, cwStore2) + require.Equal(t, cwStore2, mngr.GetOrSetStoreCache(sKey, cwStore)) +} + +func TestStoreCache(t *testing.T) { + db := dbm.NewMemDB() + tree := iavl.NewMutableTree(db, 100) + store := iavlstore.UnsafeNewStore(tree, 10, 10) + cwStore := store.CacheWrap() + + mngr := cachemulti.NewStoreCacheManager() + sKey := types.NewKVStoreKey("test") + kvStore := mngr.GetOrSetStoreCache(sKey, cwStore).(types.KVStore) + + for i := 0; i < cachemulti.PersistentStoreCacheSize*2; i++ { + key := []byte(fmt.Sprintf("key_%d", i)) + value := []byte(fmt.Sprintf("value_%d", i)) + + kvStore.Set(key, value) + + res := kvStore.Get(key) + require.Equal(t, res, value) + + res = cwStore.(types.KVStore).Get(key) + require.Equal(t, res, value) + } + + for i := 0; i < cachemulti.PersistentStoreCacheSize*2; i++ { + key := []byte(fmt.Sprintf("key_%d", i)) + + kvStore.Delete(key) + + res := kvStore.Get(key) + require.Nil(t, res) + + res = cwStore.(types.KVStore).Get(key) + require.Nil(t, res) + } +} From e7fed5035a2a4a242f553e25764504573c8ec620 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 22 Jul 2019 12:30:47 -0400 Subject: [PATCH 06/70] Set cache on read during cache miss --- store/cachemulti/cache.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/store/cachemulti/cache.go b/store/cachemulti/cache.go index 5ee0d3804e20..05085db4cc12 100644 --- a/store/cachemulti/cache.go +++ b/store/cachemulti/cache.go @@ -83,10 +83,15 @@ func (sc *StoreCache) Write() { func (sc *StoreCache) Get(key []byte) []byte { val, ok := sc.cache.Get(string(key)) if ok { + // cache hit return val.([]byte) } - return sc.KVStore.Get(key) + // cache miss; add to cache + bz := sc.KVStore.Get(key) + sc.cache.Add(string(key), bz) + + return bz } // Set inserts a key/value pair into both the write-through cache and the From c2836703418f7190718c5451d9e9587dcda3f7c3 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 22 Jul 2019 13:06:06 -0400 Subject: [PATCH 07/70] Reset BaseApp changes --- baseapp/baseapp.go | 96 +++++++++++++++++++++++----------------------- baseapp/helpers.go | 4 +- 2 files changed, 51 insertions(+), 49 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index f5b8ef5a27ea..d421a4f07663 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -63,16 +63,14 @@ type BaseApp struct { idPeerFilter sdk.PeerFilter // filter peers by node ID fauxMerkleMode bool // if true, IAVL MountStores uses MountStoresDB for simulation speed. - // volatile state: - // - // checkState is set on initialization and reset on Commit - // deliverState is set in InitChain and BeginBlock and cleared on Commit - // - // see methods setCheckState and setDeliverState - checkState *state // for CheckTx - deliverState *state // for DeliverTx - - voteInfos []abci.VoteInfo // absent validators from begin block + // -------------------- + // Volatile state + // checkState is set on initialization and reset on Commit. + // deliverState is set in InitChain and BeginBlock and cleared on Commit. + // See methods setCheckState and setDeliverState. + checkState *state // for CheckTx + deliverState *state // for DeliverTx + voteInfos []abci.VoteInfo // absent validators from begin block // consensus params // TODO: Move this in the future to baseapp param store on main store. @@ -267,21 +265,27 @@ func (app *BaseApp) Seal() { app.sealed = true } // IsSealed returns true if the BaseApp is sealed and false otherwise. func (app *BaseApp) IsSealed() bool { return app.sealed } -// setCheckState sets the CheckTx state context with a cached multi-store. It is -// called by InitChain and Commit. +// setCheckState sets checkState with the cached multistore and +// the context wrapping it. +// It is called by InitChain() and Commit() func (app *BaseApp) setCheckState(header abci.Header) { - app.checkState = newState( - sdk.NewContext(app.cms.CacheMultiStore(), header, true, app.logger). - WithMinGasPrices(app.minGasPrices), - ) + ms := app.cms.CacheMultiStore() + app.checkState = &state{ + ms: ms, + ctx: sdk.NewContext(ms, header, true, app.logger).WithMinGasPrices(app.minGasPrices), + } } -// setDeliverState sets the DeliverTx state context with a cached multi-store. -// It is called by InitChain and BeginBlock. It is reset (set to nil) on Commit. +// setCheckState sets checkState with the cached multistore and +// the context wrapping it. +// It is called by InitChain() and BeginBlock(), +// and deliverState is set nil on Commit(). func (app *BaseApp) setDeliverState(header abci.Header) { - app.deliverState = newState( - sdk.NewContext(app.cms.CacheMultiStore(), header, false, app.logger), - ) + ms := app.cms.CacheMultiStore() + app.deliverState = &state{ + ms: ms, + ctx: sdk.NewContext(ms, header, false, app.logger), + } } // setConsensusParams memoizes the consensus params. @@ -360,9 +364,11 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC } // add block gas meter for any genesis transactions (allow infinite gas) - app.deliverState = newState(app.deliverState.WithBlockGasMeter(sdk.NewInfiniteGasMeter())) + app.deliverState.ctx = app.deliverState.ctx. + WithBlockGasMeter(sdk.NewInfiniteGasMeter()) + + res = app.initChainer(app.deliverState.ctx, req) - res = app.initChainer(app.deliverState.Context, req) // sanity check if len(req.Validators) > 0 { if len(req.Validators) != len(res.Validators) { @@ -370,10 +376,8 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC "len(RequestInitChain.Validators) != len(validators) (%d != %d)", len(req.Validators), len(res.Validators))) } - sort.Sort(abci.ValidatorUpdates(req.Validators)) sort.Sort(abci.ValidatorUpdates(res.Validators)) - for i, val := range res.Validators { if !val.Equal(req.Validators[i]) { panic(fmt.Errorf("validators[%d] != req.Validators[%d] ", i, i)) @@ -529,7 +533,7 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res // cache wrap the commit-multistore for safety ctx := sdk.NewContext( - app.cms.CacheMultiStore(), app.checkState.BlockHeader(), true, app.logger, + app.cms.CacheMultiStore(), app.checkState.ctx.BlockHeader(), true, app.logger, ).WithMinGasPrices(app.minGasPrices) if req.Height > 0 { @@ -591,9 +595,11 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg if app.deliverState == nil { app.setDeliverState(req.Header) } else { - // In the first block, app.deliverState will already be initialized + // In the first block, app.deliverState.ctx will already be initialized // by InitChain. Context is now updated with Header information. - app.deliverState = newState(app.deliverState.WithBlockHeader(req.Header).WithBlockHeight(req.Header.Height)) + app.deliverState.ctx = app.deliverState.ctx. + WithBlockHeader(req.Header). + WithBlockHeight(req.Header.Height) } // add block gas meter @@ -604,10 +610,10 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg gasMeter = sdk.NewInfiniteGasMeter() } - app.deliverState = newState(app.deliverState.WithBlockGasMeter(gasMeter)) + app.deliverState.ctx = app.deliverState.ctx.WithBlockGasMeter(gasMeter) if app.beginBlocker != nil { - res = app.beginBlocker(app.deliverState.Context, req) + res = app.beginBlocker(app.deliverState.ctx, req) } // set the signed validators for addition to context in deliverTx @@ -682,7 +688,7 @@ func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error { // retrieve the context for the tx w/ txBytes and other memoized values. func (app *BaseApp) getContextForTx(mode runTxMode, txBytes []byte) (ctx sdk.Context) { - ctx = app.getState(mode). + ctx = app.getState(mode).ctx. WithTxBytes(txBytes). WithVoteInfos(app.voteInfos). WithConsensusParams(app.consensusParams) @@ -914,12 +920,12 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk // EndBlock implements the ABCI interface. func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) { - if app.deliverState.MultiStore().TracingEnabled() { - app.deliverState = newState(app.deliverState.WithMultiStore(app.deliverState.MultiStore().SetTracingContext(nil))) + if app.deliverState.ms.TracingEnabled() { + app.deliverState.ms = app.deliverState.ms.SetTracingContext(nil).(sdk.CacheMultiStore) } if app.endBlocker != nil { - res = app.endBlocker(app.deliverState.Context, req) + res = app.endBlocker(app.deliverState.ctx, req) } return @@ -933,11 +939,10 @@ func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBloc // against that height and gracefully halt if it matches the latest committed // height. func (app *BaseApp) Commit() (res abci.ResponseCommit) { - header := app.deliverState.BlockHeader() - - // write the DeliverTx state and commit the multi-store - app.deliverState.MultiStore().(store.CacheMultiStore).Write() + header := app.deliverState.ctx.BlockHeader() + // write the Deliver state and commit the MultiStore + app.deliverState.ms.Write() commitID := app.cms.Commit() app.logger.Debug("Commit synced", "commit", fmt.Sprintf("%X", commitID)) @@ -965,18 +970,15 @@ func (app *BaseApp) Commit() (res abci.ResponseCommit) { // ---------------------------------------------------------------------------- // State -// state is a simple wrapper around a Context object. There is a unique state -// for both CheckTx and DeliverTx respectively. type state struct { - sdk.Context + ms sdk.CacheMultiStore + ctx sdk.Context } -func newState(ctx sdk.Context) *state { - return &state{ctx} +func (st *state) CacheMultiStore() sdk.CacheMultiStore { + return st.ms.CacheMultiStore() } -// CacheMultiStore returns a cache-wrapped version of the state context's -// multi-store. -func (st *state) CacheMultiStore() sdk.CacheMultiStore { - return st.MultiStore().CacheMultiStore() +func (st *state) Context() sdk.Context { + return st.ctx } diff --git a/baseapp/helpers.go b/baseapp/helpers.go index ecb0e72c9d58..25f59cee5e77 100644 --- a/baseapp/helpers.go +++ b/baseapp/helpers.go @@ -29,9 +29,9 @@ func (app *BaseApp) Deliver(tx sdk.Tx) (result sdk.Result) { // used by tests func (app *BaseApp) NewContext(isCheckTx bool, header abci.Header) sdk.Context { if isCheckTx { - return sdk.NewContext(app.checkState.MultiStore(), header, true, app.logger). + return sdk.NewContext(app.checkState.ms, header, true, app.logger). WithMinGasPrices(app.minGasPrices) } - return sdk.NewContext(app.deliverState.MultiStore(), header, false, app.logger) + return sdk.NewContext(app.deliverState.ms, header, false, app.logger) } From d4d56052ff97fd7adde3fb67e11cf63fc06bae27 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 22 Jul 2019 15:09:17 -0400 Subject: [PATCH 08/70] gofmt --- store/cachemulti/cache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/cachemulti/cache.go b/store/cachemulti/cache.go index 05085db4cc12..51391e40d1d1 100644 --- a/store/cachemulti/cache.go +++ b/store/cachemulti/cache.go @@ -5,7 +5,7 @@ import ( "fmt" - "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru" ) var ( From 799c585395e56425f47851f681bfd4023181c255 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 23 Jul 2019 11:12:26 -0400 Subject: [PATCH 09/70] Update cache multi-store to use cache mngr as an arg --- store/cachemulti/cache.go | 5 ----- store/cachemulti/store.go | 33 ++++++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/store/cachemulti/cache.go b/store/cachemulti/cache.go index 51391e40d1d1..282ec579368d 100644 --- a/store/cachemulti/cache.go +++ b/store/cachemulti/cache.go @@ -12,11 +12,6 @@ var ( _ types.KVStore = (*StoreCache)(nil) _ types.CacheWrap = (*StoreCache)(nil) - // The interBlockCache contains an inter-block write-through cache for each - // KVStore. Each underlying KVStore itself may be cache-wrapped, but the - // cache here is persistent through block production. - interBlockCache = NewStoreCacheManager() - // PersistentStoreCacheSize defines the persistent ARC cache size for each // KVStore. PersistentStoreCacheSize = 1000 diff --git a/store/cachemulti/store.go b/store/cachemulti/store.go index 16b5c9c9730f..b3b085b92245 100644 --- a/store/cachemulti/store.go +++ b/store/cachemulti/store.go @@ -24,14 +24,20 @@ type Store struct { traceWriter io.Writer traceContext types.TraceContext + + cacheManager *StoreCacheManager } var _ types.CacheMultiStore = Store{} +// NewFromKVStore creates a new Store object from a mapping of store keys to +// CacheWrapper objects and a KVStore as the database. Each CacheWrapper store +// is cache-wrapped. In addition, if a StoreCacheManager is provided, then it'll +// be used to act as a persistent inter-block cache. func NewFromKVStore( - store types.KVStore, - stores map[types.StoreKey]types.CacheWrapper, keys map[string]types.StoreKey, - traceWriter io.Writer, traceContext types.TraceContext, + store types.KVStore, stores map[types.StoreKey]types.CacheWrapper, + keys map[string]types.StoreKey, traceWriter io.Writer, traceContext types.TraceContext, + cacheMngr *StoreCacheManager, ) Store { cms := Store{ db: cachekv.NewStore(store), @@ -39,6 +45,7 @@ func NewFromKVStore( keys: keys, traceWriter: traceWriter, traceContext: traceContext, + cacheManager: cacheMngr, } for key, store := range stores { @@ -50,18 +57,25 @@ func NewFromKVStore( cacheWrappedStore = store.CacheWrap() } - cms.stores[key] = interBlockCache.GetOrSetStoreCache(key, cacheWrappedStore) + if cacheMngr != nil { + cms.stores[key] = cacheMngr.GetOrSetStoreCache(key, cacheWrappedStore) + } else { + cms.stores[key] = cacheWrappedStore + } } return cms } +// NewStore creates a new Store object from a mapping of store keys to +// CacheWrapper objects. Each CacheWrapper store is cache-wrapped. In addition, +// if a StoreCacheManager is provided, then it'll be used to act as a persistent +// inter-block cache. func NewStore( - db dbm.DB, - stores map[types.StoreKey]types.CacheWrapper, keys map[string]types.StoreKey, - traceWriter io.Writer, traceContext types.TraceContext, + db dbm.DB, stores map[types.StoreKey]types.CacheWrapper, keys map[string]types.StoreKey, + traceWriter io.Writer, traceContext types.TraceContext, cacheMngr *StoreCacheManager, ) Store { - return NewFromKVStore(dbadapter.Store{db}, stores, keys, traceWriter, traceContext) + return NewFromKVStore(dbadapter.Store{db}, stores, keys, traceWriter, traceContext, cacheMngr) } func newCacheMultiStoreFromCMS(cms Store) Store { @@ -69,7 +83,8 @@ func newCacheMultiStoreFromCMS(cms Store) Store { for k, v := range cms.stores { stores[k] = v } - return NewFromKVStore(cms.db, stores, nil, cms.traceWriter, cms.traceContext) + + return NewFromKVStore(cms.db, stores, nil, cms.traceWriter, cms.traceContext, cms.cacheManager) } // SetTracer sets the tracer for the MultiStore that the underlying From b1945e408bad6749a34156752020ebf2e34504ae Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 23 Jul 2019 11:15:14 -0400 Subject: [PATCH 10/70] Update multi-store --- store/rootmulti/store.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index e4213a8794fa..c0d77d5b4c38 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -38,6 +38,7 @@ type Store struct { traceWriter io.Writer traceContext types.TraceContext + cacheManager *cachemulti.StoreCacheManager } var _ types.CommitMultiStore = (*Store)(nil) @@ -50,6 +51,7 @@ func NewStore(db dbm.DB) *Store { storesParams: make(map[types.StoreKey]storeParams), stores: make(map[types.StoreKey]types.CommitStore), keysByName: make(map[string]types.StoreKey), + cacheManager: cachemulti.NewStoreCacheManager(), } } @@ -231,20 +233,23 @@ func (rs *Store) CacheWrapWithTrace(_ io.Writer, _ types.TraceContext) types.Cac //---------------------------------------- // +MultiStore -// Implements MultiStore. +// CacheMultiStore cache-wraps the multi-store and returns a CacheMultiStore. +// It implements the MultiStore interface. Note, the multi-store has a persistent +// inter-block cache that will be used by all subsequent KVStores. func (rs *Store) CacheMultiStore() types.CacheMultiStore { stores := make(map[types.StoreKey]types.CacheWrapper) for k, v := range rs.stores { stores[k] = v } - return cachemulti.NewStore(rs.db, stores, rs.keysByName, rs.traceWriter, rs.traceContext) + return cachemulti.NewStore(rs.db, stores, rs.keysByName, rs.traceWriter, rs.traceContext, rs.cacheManager) } // CacheMultiStoreWithVersion is analogous to CacheMultiStore except that it // attempts to load stores at a given version (height). An error is returned if // any store cannot be loaded. This should only be used for querying and -// iterating at past heights. +// iterating at past heights. Note, the multi-store has a persistent inter-block +// cache that will be used by all subsequent KVStores. func (rs *Store) CacheMultiStoreWithVersion(version int64) (types.CacheMultiStore, error) { cachedStores := make(map[types.StoreKey]types.CacheWrapper) for key, store := range rs.stores { @@ -264,7 +269,7 @@ func (rs *Store) CacheMultiStoreWithVersion(version int64) (types.CacheMultiStor } } - return cachemulti.NewStore(rs.db, cachedStores, rs.keysByName, rs.traceWriter, rs.traceContext), nil + return cachemulti.NewStore(rs.db, cachedStores, rs.keysByName, rs.traceWriter, rs.traceContext, rs.cacheManager), nil } // Implements MultiStore. From 04c3bacc6127e4d19fdd87c0aa47e74b49561ddd Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 14 Aug 2019 13:49:44 -0400 Subject: [PATCH 11/70] fmt and godoc cleanup --- store/cachemulti/cache.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/store/cachemulti/cache.go b/store/cachemulti/cache.go index 282ec579368d..945b8d86a607 100644 --- a/store/cachemulti/cache.go +++ b/store/cachemulti/cache.go @@ -1,10 +1,10 @@ package cachemulti import ( - "github.com/cosmos/cosmos-sdk/store/types" - "fmt" + "github.com/cosmos/cosmos-sdk/store/types" + lru "github.com/hashicorp/golang-lru" ) @@ -19,10 +19,10 @@ var ( type ( // StoreCache defines a cache that is meant to be used in a persistent - // (inter-block) fashion and which wraps an underlying KVStore. Reads first - // hit the ARC (Adaptive Replacement Cache). During a cache miss, the read - // is delegated to the underlying KVStore. Deletes and writes always happen - // to both the cache and the KVStore in a write-through manner. Caching + // (inter-block) fashion and in which it wraps an underlying KVStore. Reads + // first hit the ARC (Adaptive Replacement Cache). During a cache miss, the + // read is delegated to the underlying KVStore. Deletes and writes always + // happen to both the cache and the KVStore in a write-through manner. Caching // performed in the KVStore is completely irrelevant to this layer. StoreCache struct { types.KVStore From c1d84fa70d32ecbff36eb0a48a39c660b82c5d46 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Thu, 15 Aug 2019 13:36:14 -0400 Subject: [PATCH 12/70] Restructure baseapp --- baseapp/abci.go | 407 +++++++++++++++++++++++++++++++++++++++ baseapp/baseapp.go | 468 +++------------------------------------------ baseapp/doc.go | 8 - baseapp/state.go | 21 ++ 4 files changed, 457 insertions(+), 447 deletions(-) create mode 100644 baseapp/abci.go delete mode 100644 baseapp/doc.go create mode 100644 baseapp/state.go diff --git a/baseapp/abci.go b/baseapp/abci.go new file mode 100644 index 000000000000..067732b940bf --- /dev/null +++ b/baseapp/abci.go @@ -0,0 +1,407 @@ +package baseapp + +import ( + "fmt" + "os" + "sort" + "strings" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +// InitChain implements the ABCI interface. It runs the initialization logic +// directly on the CommitMultiStore. +func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) { + // stash the consensus params in the cms main store and memoize + if req.ConsensusParams != nil { + app.setConsensusParams(req.ConsensusParams) + app.storeConsensusParams(req.ConsensusParams) + } + + initHeader := abci.Header{ChainID: req.ChainId, Time: req.Time} + + // initialize the deliver state and check state with a correct header + app.setDeliverState(initHeader) + app.setCheckState(initHeader) + + if app.initChainer == nil { + return + } + + // add block gas meter for any genesis transactions (allow infinite gas) + app.deliverState.ctx = app.deliverState.ctx. + WithBlockGasMeter(sdk.NewInfiniteGasMeter()) + + res = app.initChainer(app.deliverState.ctx, req) + + // sanity check + if len(req.Validators) > 0 { + if len(req.Validators) != len(res.Validators) { + panic(fmt.Errorf( + "len(RequestInitChain.Validators) != len(validators) (%d != %d)", + len(req.Validators), len(res.Validators))) + } + sort.Sort(abci.ValidatorUpdates(req.Validators)) + sort.Sort(abci.ValidatorUpdates(res.Validators)) + for i, val := range res.Validators { + if !val.Equal(req.Validators[i]) { + panic(fmt.Errorf("validators[%d] != req.Validators[%d] ", i, i)) + } + } + } + + // NOTE: We don't commit, but BeginBlock for block 1 starts from this + // deliverState. + return +} + +// Info implements the ABCI interface. +func (app *BaseApp) Info(req abci.RequestInfo) abci.ResponseInfo { + lastCommitID := app.cms.LastCommitID() + + return abci.ResponseInfo{ + Data: app.name, + LastBlockHeight: lastCommitID.Version, + LastBlockAppHash: lastCommitID.Hash, + } +} + +// SetOption implements the ABCI interface. +func (app *BaseApp) SetOption(req abci.RequestSetOption) (res abci.ResponseSetOption) { + // TODO: Implement! + return +} + +// FilterPeerByAddrPort filters peers by address/port. +func (app *BaseApp) FilterPeerByAddrPort(info string) abci.ResponseQuery { + if app.addrPeerFilter != nil { + return app.addrPeerFilter(info) + } + return abci.ResponseQuery{} +} + +// FilterPeerByIDfilters peers by node ID. +func (app *BaseApp) FilterPeerByID(info string) abci.ResponseQuery { + if app.idPeerFilter != nil { + return app.idPeerFilter(info) + } + return abci.ResponseQuery{} +} + +// BeginBlock implements the ABCI application interface. +func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { + if app.cms.TracingEnabled() { + app.cms.SetTracingContext(sdk.TraceContext( + map[string]interface{}{"blockHeight": req.Header.Height}, + )) + } + + if err := app.validateHeight(req); err != nil { + panic(err) + } + + // Initialize the DeliverTx state. If this is the first block, it should + // already be initialized in InitChain. Otherwise app.deliverState will be + // nil, since it is reset on Commit. + if app.deliverState == nil { + app.setDeliverState(req.Header) + } else { + // In the first block, app.deliverState.ctx will already be initialized + // by InitChain. Context is now updated with Header information. + app.deliverState.ctx = app.deliverState.ctx. + WithBlockHeader(req.Header). + WithBlockHeight(req.Header.Height) + } + + // add block gas meter + var gasMeter sdk.GasMeter + if maxGas := app.getMaximumBlockGas(); maxGas > 0 { + gasMeter = sdk.NewGasMeter(maxGas) + } else { + gasMeter = sdk.NewInfiniteGasMeter() + } + + app.deliverState.ctx = app.deliverState.ctx.WithBlockGasMeter(gasMeter) + + if app.beginBlocker != nil { + res = app.beginBlocker(app.deliverState.ctx, req) + } + + // set the signed validators for addition to context in deliverTx + app.voteInfos = req.LastCommitInfo.GetVotes() + return +} + +// EndBlock implements the ABCI interface. +func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) { + if app.deliverState.ms.TracingEnabled() { + app.deliverState.ms = app.deliverState.ms.SetTracingContext(nil).(sdk.CacheMultiStore) + } + + if app.endBlocker != nil { + res = app.endBlocker(app.deliverState.ctx, req) + } + + return +} + +// CheckTx implements the ABCI interface. It runs the "basic checks" to see +// whether or not a transaction can possibly be executed, first decoding and then +// the ante handler (which checks signatures/fees/ValidateBasic). +// +// NOTE:CheckTx does not run the actual Msg handler function(s). +func (app *BaseApp) CheckTx(req abci.RequestCheckTx) (res abci.ResponseCheckTx) { + var result sdk.Result + + tx, err := app.txDecoder(req.Tx) + if err != nil { + result = err.Result() + } else { + result = app.runTx(runTxModeCheck, req.Tx, tx) + } + + return abci.ResponseCheckTx{ + Code: uint32(result.Code), + Data: result.Data, + Log: result.Log, + GasWanted: int64(result.GasWanted), // TODO: Should type accept unsigned ints? + GasUsed: int64(result.GasUsed), // TODO: Should type accept unsigned ints? + Events: result.Events.ToABCIEvents(), + } +} + +// DeliverTx implements the ABCI interface. +func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) (res abci.ResponseDeliverTx) { + var result sdk.Result + + tx, err := app.txDecoder(req.Tx) + if err != nil { + result = err.Result() + } else { + result = app.runTx(runTxModeDeliver, req.Tx, tx) + } + + return abci.ResponseDeliverTx{ + Code: uint32(result.Code), + Codespace: string(result.Codespace), + Data: result.Data, + Log: result.Log, + GasWanted: int64(result.GasWanted), // TODO: Should type accept unsigned ints? + GasUsed: int64(result.GasUsed), // TODO: Should type accept unsigned ints? + Events: result.Events.ToABCIEvents(), + } +} + +// Commit implements the ABCI interface. It will commit all state that exists in +// the deliver state's multi-store and includes the resulting commit ID in the +// returned abci.ResponseCommit. Commit will set the check state based on the +// latest header and reset the deliver state. Also, if a non-zero halt height is +// defined in config, Commit will execute a deferred function call to check +// against that height and gracefully halt if it matches the latest committed +// height. +func (app *BaseApp) Commit() (res abci.ResponseCommit) { + header := app.deliverState.ctx.BlockHeader() + + // write the Deliver state and commit the MultiStore + app.deliverState.ms.Write() + commitID := app.cms.Commit() + app.logger.Debug("Commit synced", "commit", fmt.Sprintf("%X", commitID)) + + // Reset the Check state to the latest committed. + // + // NOTE: This is safe because Tendermint holds a lock on the mempool for + // Commit. Use the header from this latest block. + app.setCheckState(header) + + // empty/reset the deliver state + app.deliverState = nil + + defer func() { + if app.haltHeight > 0 && uint64(header.Height) == app.haltHeight { + app.logger.Info("halting node per configuration", "height", app.haltHeight) + os.Exit(0) + } + }() + + return abci.ResponseCommit{ + Data: commitID.Hash, + } +} + +// Query implements the ABCI interface. It delegates to CommitMultiStore if it +// implements Queryable. +func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) { + path := splitPath(req.Path) + if len(path) == 0 { + msg := "no query path provided" + return sdk.ErrUnknownRequest(msg).QueryResult() + } + + switch path[0] { + // "/app" prefix for special application queries + case "app": + return handleQueryApp(app, path, req) + + case "store": + return handleQueryStore(app, path, req) + + case "p2p": + return handleQueryP2P(app, path, req) + + case "custom": + return handleQueryCustom(app, path, req) + } + + msg := "unknown query path" + return sdk.ErrUnknownRequest(msg).QueryResult() +} + +func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { + if len(path) >= 2 { + var result sdk.Result + + switch path[1] { + case "simulate": + txBytes := req.Data + tx, err := app.txDecoder(txBytes) + if err != nil { + result = err.Result() + } else { + result = app.Simulate(txBytes, tx) + } + + case "version": + return abci.ResponseQuery{ + Code: uint32(sdk.CodeOK), + Codespace: string(sdk.CodespaceRoot), + Height: req.Height, + Value: []byte(app.appVersion), + } + + default: + result = sdk.ErrUnknownRequest(fmt.Sprintf("Unknown query: %s", path)).Result() + } + + value := codec.Cdc.MustMarshalBinaryLengthPrefixed(result) + return abci.ResponseQuery{ + Code: uint32(sdk.CodeOK), + Codespace: string(sdk.CodespaceRoot), + Height: req.Height, + Value: value, + } + } + + msg := "Expected second parameter to be either simulate or version, neither was present" + return sdk.ErrUnknownRequest(msg).QueryResult() +} + +func handleQueryStore(app *BaseApp, path []string, req abci.RequestQuery) abci.ResponseQuery { + // "/store" prefix for store queries + queryable, ok := app.cms.(sdk.Queryable) + if !ok { + msg := "multistore doesn't support queries" + return sdk.ErrUnknownRequest(msg).QueryResult() + } + + req.Path = "/" + strings.Join(path[1:], "/") + + // when a client did not provide a query height, manually inject the latest + if req.Height == 0 { + req.Height = app.LastBlockHeight() + } + + if req.Height <= 1 && req.Prove { + return sdk.ErrInternal("cannot query with proof when height <= 1; please provide a valid height").QueryResult() + } + + resp := queryable.Query(req) + resp.Height = req.Height + + return resp +} + +func handleQueryP2P(app *BaseApp, path []string, _ abci.RequestQuery) (res abci.ResponseQuery) { + // "/p2p" prefix for p2p queries + if len(path) >= 4 { + cmd, typ, arg := path[1], path[2], path[3] + switch cmd { + case "filter": + switch typ { + case "addr": + return app.FilterPeerByAddrPort(arg) + + case "id": + return app.FilterPeerByID(arg) + } + + default: + msg := "Expected second parameter to be filter" + return sdk.ErrUnknownRequest(msg).QueryResult() + } + } + + msg := "Expected path is p2p filter " + return sdk.ErrUnknownRequest(msg).QueryResult() +} + +func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { + // path[0] should be "custom" because "/custom" prefix is required for keeper + // queries. + // + // The queryRouter routes using path[1]. For example, in the path + // "custom/gov/proposal", queryRouter routes using "gov". + if len(path) < 2 || path[1] == "" { + return sdk.ErrUnknownRequest("No route for custom query specified").QueryResult() + } + + querier := app.queryRouter.Route(path[1]) + if querier == nil { + return sdk.ErrUnknownRequest(fmt.Sprintf("no custom querier found for route %s", path[1])).QueryResult() + } + + // when a client did not provide a query height, manually inject the latest + if req.Height == 0 { + req.Height = app.LastBlockHeight() + } + + if req.Height <= 1 && req.Prove { + return sdk.ErrInternal("cannot query with proof when height <= 1; please provide a valid height").QueryResult() + } + + cacheMS, err := app.cms.CacheMultiStoreWithVersion(req.Height) + if err != nil { + return sdk.ErrInternal( + fmt.Sprintf( + "failed to load state at height %d; %s (latest height: %d)", + req.Height, err, app.LastBlockHeight(), + ), + ).QueryResult() + } + + // cache wrap the commit-multistore for safety + ctx := sdk.NewContext( + cacheMS, app.checkState.ctx.BlockHeader(), true, app.logger, + ).WithMinGasPrices(app.minGasPrices) + + // Passes the rest of the path as an argument to the querier. + // + // For example, in the path "custom/gov/proposal/test", the gov querier gets + // []string{"proposal", "test"} as the path. + resBytes, queryErr := querier(ctx, path[2:], req) + if queryErr != nil { + return abci.ResponseQuery{ + Code: uint32(queryErr.Code()), + Codespace: string(queryErr.Codespace()), + Height: req.Height, + Log: queryErr.ABCILog(), + } + } + + return abci.ResponseQuery{ + Code: uint32(sdk.CodeOK), + Height: req.Height, + Value: resBytes, + } +} diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index d336e79fca25..f06f7bf4a574 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -2,18 +2,15 @@ package baseapp import ( "encoding/json" + "errors" "fmt" "io/ioutil" "os" "reflect" "runtime/debug" - "sort" "strings" - "errors" - "github.com/gogo/protobuf/proto" - abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/libs/log" @@ -25,12 +22,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// Key to store the consensus params in the main store. -var mainConsensusParamsKey = []byte("consensus_params") - -// Enum mode for app.runTx -type runTxMode uint8 - const ( // Check a transaction runTxModeCheck runTxMode = iota @@ -43,11 +34,24 @@ const ( MainStoreKey = "main" ) -// StoreLoader defines a customizable function to control how we load the CommitMultiStore -// from disk. This is useful for state migration, when loading a datastore written with -// an older version of the software. In particular, if a module changed the substore key name -// (or removed a substore) between two versions of the software. -type StoreLoader func(ms sdk.CommitMultiStore) error +var ( + _ abci.Application = (*BaseApp)(nil) + + // mainConsensusParamsKey defines a key to store the consensus params in the + // main store. + mainConsensusParamsKey = []byte("consensus_params") +) + +type ( + // Enum mode for app.runTx + runTxMode uint8 + + // StoreLoader defines a customizable function to control how we load the CommitMultiStore + // from disk. This is useful for state migration, when loading a datastore written with + // an older version of the software. In particular, if a module changed the substore key name + // (or removed a substore) between two versions of the software. + StoreLoader func(ms sdk.CommitMultiStore) error +) // BaseApp reflects the ABCI application implementation. type BaseApp struct { @@ -99,8 +103,6 @@ type BaseApp struct { appVersion string } -var _ abci.Application = (*BaseApp)(nil) - // NewBaseApp returns a reference to an initialized BaseApp. It accepts a // variadic number of option functions, which act on the BaseApp to set // configuration choices. @@ -156,8 +158,10 @@ func (app *BaseApp) MountStores(keys ...sdk.StoreKey) { // retain history, but it's useful for faster simulation. app.MountStore(key, sdk.StoreTypeDB) } + case *sdk.TransientStoreKey: app.MountStore(key, sdk.StoreTypeTransient) + default: panic("Unrecognized store key type " + reflect.TypeOf(key).Name()) } @@ -411,275 +415,6 @@ func (app *BaseApp) getMaximumBlockGas() uint64 { } } -// ---------------------------------------------------------------------------- -// ABCI - -// Info implements the ABCI interface. -func (app *BaseApp) Info(req abci.RequestInfo) abci.ResponseInfo { - lastCommitID := app.cms.LastCommitID() - - return abci.ResponseInfo{ - Data: app.name, - LastBlockHeight: lastCommitID.Version, - LastBlockAppHash: lastCommitID.Hash, - } -} - -// SetOption implements the ABCI interface. -func (app *BaseApp) SetOption(req abci.RequestSetOption) (res abci.ResponseSetOption) { - // TODO: Implement! - return -} - -// InitChain implements the ABCI interface. It runs the initialization logic -// directly on the CommitMultiStore. -func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) { - // stash the consensus params in the cms main store and memoize - if req.ConsensusParams != nil { - app.setConsensusParams(req.ConsensusParams) - app.storeConsensusParams(req.ConsensusParams) - } - - initHeader := abci.Header{ChainID: req.ChainId, Time: req.Time} - - // initialize the deliver state and check state with a correct header - app.setDeliverState(initHeader) - app.setCheckState(initHeader) - - if app.initChainer == nil { - return - } - - // add block gas meter for any genesis transactions (allow infinite gas) - app.deliverState.ctx = app.deliverState.ctx. - WithBlockGasMeter(sdk.NewInfiniteGasMeter()) - - res = app.initChainer(app.deliverState.ctx, req) - - // sanity check - if len(req.Validators) > 0 { - if len(req.Validators) != len(res.Validators) { - panic(fmt.Errorf( - "len(RequestInitChain.Validators) != len(validators) (%d != %d)", - len(req.Validators), len(res.Validators))) - } - sort.Sort(abci.ValidatorUpdates(req.Validators)) - sort.Sort(abci.ValidatorUpdates(res.Validators)) - for i, val := range res.Validators { - if !val.Equal(req.Validators[i]) { - panic(fmt.Errorf("validators[%d] != req.Validators[%d] ", i, i)) - } - } - } - - // NOTE: We don't commit, but BeginBlock for block 1 starts from this - // deliverState. - return -} - -// FilterPeerByAddrPort filters peers by address/port. -func (app *BaseApp) FilterPeerByAddrPort(info string) abci.ResponseQuery { - if app.addrPeerFilter != nil { - return app.addrPeerFilter(info) - } - return abci.ResponseQuery{} -} - -// FilterPeerByIDfilters peers by node ID. -func (app *BaseApp) FilterPeerByID(info string) abci.ResponseQuery { - if app.idPeerFilter != nil { - return app.idPeerFilter(info) - } - return abci.ResponseQuery{} -} - -// Splits a string path using the delimiter '/'. -// e.g. "this/is/funny" becomes []string{"this", "is", "funny"} -func splitPath(requestPath string) (path []string) { - path = strings.Split(requestPath, "/") - // first element is empty string - if len(path) > 0 && path[0] == "" { - path = path[1:] - } - return path -} - -// Query implements the ABCI interface. It delegates to CommitMultiStore if it -// implements Queryable. -func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) { - path := splitPath(req.Path) - if len(path) == 0 { - msg := "no query path provided" - return sdk.ErrUnknownRequest(msg).QueryResult() - } - - switch path[0] { - // "/app" prefix for special application queries - case "app": - return handleQueryApp(app, path, req) - - case "store": - return handleQueryStore(app, path, req) - - case "p2p": - return handleQueryP2P(app, path, req) - - case "custom": - return handleQueryCustom(app, path, req) - } - - msg := "unknown query path" - return sdk.ErrUnknownRequest(msg).QueryResult() -} - -func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { - if len(path) >= 2 { - var result sdk.Result - - switch path[1] { - case "simulate": - txBytes := req.Data - tx, err := app.txDecoder(txBytes) - if err != nil { - result = err.Result() - } else { - result = app.Simulate(txBytes, tx) - } - - case "version": - return abci.ResponseQuery{ - Code: uint32(sdk.CodeOK), - Codespace: string(sdk.CodespaceRoot), - Height: req.Height, - Value: []byte(app.appVersion), - } - - default: - result = sdk.ErrUnknownRequest(fmt.Sprintf("Unknown query: %s", path)).Result() - } - - value := codec.Cdc.MustMarshalBinaryLengthPrefixed(result) - return abci.ResponseQuery{ - Code: uint32(sdk.CodeOK), - Codespace: string(sdk.CodespaceRoot), - Height: req.Height, - Value: value, - } - } - - msg := "Expected second parameter to be either simulate or version, neither was present" - return sdk.ErrUnknownRequest(msg).QueryResult() -} - -func handleQueryStore(app *BaseApp, path []string, req abci.RequestQuery) abci.ResponseQuery { - // "/store" prefix for store queries - queryable, ok := app.cms.(sdk.Queryable) - if !ok { - msg := "multistore doesn't support queries" - return sdk.ErrUnknownRequest(msg).QueryResult() - } - - req.Path = "/" + strings.Join(path[1:], "/") - - // when a client did not provide a query height, manually inject the latest - if req.Height == 0 { - req.Height = app.LastBlockHeight() - } - - if req.Height <= 1 && req.Prove { - return sdk.ErrInternal("cannot query with proof when height <= 1; please provide a valid height").QueryResult() - } - - resp := queryable.Query(req) - resp.Height = req.Height - - return resp -} - -func handleQueryP2P(app *BaseApp, path []string, _ abci.RequestQuery) (res abci.ResponseQuery) { - // "/p2p" prefix for p2p queries - if len(path) >= 4 { - cmd, typ, arg := path[1], path[2], path[3] - switch cmd { - case "filter": - switch typ { - case "addr": - return app.FilterPeerByAddrPort(arg) - - case "id": - return app.FilterPeerByID(arg) - } - - default: - msg := "Expected second parameter to be filter" - return sdk.ErrUnknownRequest(msg).QueryResult() - } - } - - msg := "Expected path is p2p filter " - return sdk.ErrUnknownRequest(msg).QueryResult() -} - -func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { - // path[0] should be "custom" because "/custom" prefix is required for keeper - // queries. - // - // The queryRouter routes using path[1]. For example, in the path - // "custom/gov/proposal", queryRouter routes using "gov". - if len(path) < 2 || path[1] == "" { - return sdk.ErrUnknownRequest("No route for custom query specified").QueryResult() - } - - querier := app.queryRouter.Route(path[1]) - if querier == nil { - return sdk.ErrUnknownRequest(fmt.Sprintf("no custom querier found for route %s", path[1])).QueryResult() - } - - // when a client did not provide a query height, manually inject the latest - if req.Height == 0 { - req.Height = app.LastBlockHeight() - } - - if req.Height <= 1 && req.Prove { - return sdk.ErrInternal("cannot query with proof when height <= 1; please provide a valid height").QueryResult() - } - - cacheMS, err := app.cms.CacheMultiStoreWithVersion(req.Height) - if err != nil { - return sdk.ErrInternal( - fmt.Sprintf( - "failed to load state at height %d; %s (latest height: %d)", - req.Height, err, app.LastBlockHeight(), - ), - ).QueryResult() - } - - // cache wrap the commit-multistore for safety - ctx := sdk.NewContext( - cacheMS, app.checkState.ctx.BlockHeader(), true, app.logger, - ).WithMinGasPrices(app.minGasPrices) - - // Passes the rest of the path as an argument to the querier. - // - // For example, in the path "custom/gov/proposal/test", the gov querier gets - // []string{"proposal", "test"} as the path. - resBytes, queryErr := querier(ctx, path[2:], req) - if queryErr != nil { - return abci.ResponseQuery{ - Code: uint32(queryErr.Code()), - Codespace: string(queryErr.Codespace()), - Height: req.Height, - Log: queryErr.ABCILog(), - } - } - - return abci.ResponseQuery{ - Code: uint32(sdk.CodeOK), - Height: req.Height, - Value: resBytes, - } -} - func (app *BaseApp) validateHeight(req abci.RequestBeginBlock) error { if req.Header.Height < 1 { return fmt.Errorf("invalid height: %d", req.Header.Height) @@ -693,97 +428,6 @@ func (app *BaseApp) validateHeight(req abci.RequestBeginBlock) error { return nil } -// BeginBlock implements the ABCI application interface. -func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { - if app.cms.TracingEnabled() { - app.cms.SetTracingContext(sdk.TraceContext( - map[string]interface{}{"blockHeight": req.Header.Height}, - )) - } - - if err := app.validateHeight(req); err != nil { - panic(err) - } - - // Initialize the DeliverTx state. If this is the first block, it should - // already be initialized in InitChain. Otherwise app.deliverState will be - // nil, since it is reset on Commit. - if app.deliverState == nil { - app.setDeliverState(req.Header) - } else { - // In the first block, app.deliverState.ctx will already be initialized - // by InitChain. Context is now updated with Header information. - app.deliverState.ctx = app.deliverState.ctx. - WithBlockHeader(req.Header). - WithBlockHeight(req.Header.Height) - } - - // add block gas meter - var gasMeter sdk.GasMeter - if maxGas := app.getMaximumBlockGas(); maxGas > 0 { - gasMeter = sdk.NewGasMeter(maxGas) - } else { - gasMeter = sdk.NewInfiniteGasMeter() - } - - app.deliverState.ctx = app.deliverState.ctx.WithBlockGasMeter(gasMeter) - - if app.beginBlocker != nil { - res = app.beginBlocker(app.deliverState.ctx, req) - } - - // set the signed validators for addition to context in deliverTx - app.voteInfos = req.LastCommitInfo.GetVotes() - return -} - -// CheckTx implements the ABCI interface. It runs the "basic checks" to see -// whether or not a transaction can possibly be executed, first decoding and then -// the ante handler (which checks signatures/fees/ValidateBasic). -// -// NOTE:CheckTx does not run the actual Msg handler function(s). -func (app *BaseApp) CheckTx(req abci.RequestCheckTx) (res abci.ResponseCheckTx) { - var result sdk.Result - - tx, err := app.txDecoder(req.Tx) - if err != nil { - result = err.Result() - } else { - result = app.runTx(runTxModeCheck, req.Tx, tx) - } - - return abci.ResponseCheckTx{ - Code: uint32(result.Code), - Data: result.Data, - Log: result.Log, - GasWanted: int64(result.GasWanted), // TODO: Should type accept unsigned ints? - GasUsed: int64(result.GasUsed), // TODO: Should type accept unsigned ints? - Events: result.Events.ToABCIEvents(), - } -} - -// DeliverTx implements the ABCI interface. -func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) (res abci.ResponseDeliverTx) { - var result sdk.Result - - tx, err := app.txDecoder(req.Tx) - if err != nil { - result = err.Result() - } else { - result = app.runTx(runTxModeDeliver, req.Tx, tx) - } - - return abci.ResponseDeliverTx{ - Code: uint32(result.Code), - Codespace: string(result.Codespace), - Data: result.Data, - Log: result.Log, - GasWanted: int64(result.GasWanted), // TODO: Should type accept unsigned ints? - GasUsed: int64(result.GasUsed), // TODO: Should type accept unsigned ints? - Events: result.Events.ToABCIEvents(), - } -} - // validateBasicTxMsgs executes basic validator calls for messages. func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error { if msgs == nil || len(msgs) == 0 { @@ -1030,67 +674,13 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk return result } -// EndBlock implements the ABCI interface. -func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) { - if app.deliverState.ms.TracingEnabled() { - app.deliverState.ms = app.deliverState.ms.SetTracingContext(nil).(sdk.CacheMultiStore) - } - - if app.endBlocker != nil { - res = app.endBlocker(app.deliverState.ctx, req) - } - - return -} - -// Commit implements the ABCI interface. It will commit all state that exists in -// the deliver state's multi-store and includes the resulting commit ID in the -// returned abci.ResponseCommit. Commit will set the check state based on the -// latest header and reset the deliver state. Also, if a non-zero halt height is -// defined in config, Commit will execute a deferred function call to check -// against that height and gracefully halt if it matches the latest committed -// height. -func (app *BaseApp) Commit() (res abci.ResponseCommit) { - header := app.deliverState.ctx.BlockHeader() - - // write the Deliver state and commit the MultiStore - app.deliverState.ms.Write() - commitID := app.cms.Commit() - app.logger.Debug("Commit synced", "commit", fmt.Sprintf("%X", commitID)) - - // Reset the Check state to the latest committed. - // - // NOTE: This is safe because Tendermint holds a lock on the mempool for - // Commit. Use the header from this latest block. - app.setCheckState(header) - - // empty/reset the deliver state - app.deliverState = nil - - defer func() { - if app.haltHeight > 0 && uint64(header.Height) == app.haltHeight { - app.logger.Info("halting node per configuration", "height", app.haltHeight) - os.Exit(0) - } - }() - - return abci.ResponseCommit{ - Data: commitID.Hash, +// Splits a string path using the delimiter '/'. +// e.g. "this/is/funny" becomes []string{"this", "is", "funny"} +func splitPath(requestPath string) (path []string) { + path = strings.Split(requestPath, "/") + // first element is empty string + if len(path) > 0 && path[0] == "" { + path = path[1:] } -} - -// ---------------------------------------------------------------------------- -// State - -type state struct { - ms sdk.CacheMultiStore - ctx sdk.Context -} - -func (st *state) CacheMultiStore() sdk.CacheMultiStore { - return st.ms.CacheMultiStore() -} - -func (st *state) Context() sdk.Context { - return st.ctx + return path } diff --git a/baseapp/doc.go b/baseapp/doc.go deleted file mode 100644 index d708d08bcd1f..000000000000 --- a/baseapp/doc.go +++ /dev/null @@ -1,8 +0,0 @@ -/* -Package baseapp contains data structures that provide basic data storage -functionality and act as a bridge between the ABCI interface and the SDK -abstractions. - -BaseApp has no state except the CommitMultiStore you provide upon init. -*/ -package baseapp diff --git a/baseapp/state.go b/baseapp/state.go new file mode 100644 index 000000000000..addc89cb342c --- /dev/null +++ b/baseapp/state.go @@ -0,0 +1,21 @@ +package baseapp + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type state struct { + ms sdk.CacheMultiStore + ctx sdk.Context +} + +// CacheMultiStore calls and returns a CacheMultiStore on the state's underling +// CacheMultiStore. +func (st *state) CacheMultiStore() sdk.CacheMultiStore { + return st.ms.CacheMultiStore() +} + +// Context returns the Context of the state. +func (st *state) Context() sdk.Context { + return st.ctx +} From 0d6a3ed4273b6f4d976cbc0b3a5c8e1222386980 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Fri, 16 Aug 2019 10:30:27 -0400 Subject: [PATCH 13/70] More BaseApp cleanup and restructuring --- baseapp/abci.go | 14 ++-- baseapp/baseapp.go | 156 ++++++++++++++++++++++----------------------- 2 files changed, 86 insertions(+), 84 deletions(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index 067732b940bf..dc031197589d 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -31,20 +31,24 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC } // add block gas meter for any genesis transactions (allow infinite gas) - app.deliverState.ctx = app.deliverState.ctx. - WithBlockGasMeter(sdk.NewInfiniteGasMeter()) + app.deliverState.ctx = app.deliverState.ctx.WithBlockGasMeter(sdk.NewInfiniteGasMeter()) res = app.initChainer(app.deliverState.ctx, req) // sanity check if len(req.Validators) > 0 { if len(req.Validators) != len(res.Validators) { - panic(fmt.Errorf( - "len(RequestInitChain.Validators) != len(validators) (%d != %d)", - len(req.Validators), len(res.Validators))) + panic( + fmt.Errorf( + "len(RequestInitChain.Validators) != len(validators) (%d != %d)", + len(req.Validators), len(res.Validators), + ), + ) } + sort.Sort(abci.ValidatorUpdates(req.Validators)) sort.Sort(abci.ValidatorUpdates(res.Validators)) + for i, val := range res.Validators { if !val.Equal(req.Validators[i]) { panic(fmt.Errorf("validators[%d] != req.Validators[%d] ", i, i)) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index f06f7bf4a574..5be819732c07 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -445,6 +445,16 @@ func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error { return nil } +// Returns the applications's deliverState if app is in runTxModeDeliver, +// otherwise it returns the application's checkstate. +func (app *BaseApp) getState(mode runTxMode) *state { + if mode == runTxModeCheck || mode == runTxModeSimulate { + return app.checkState + } + + return app.deliverState +} + // retrieve the context for the tx w/ txBytes and other memoized values. func (app *BaseApp) getContextForTx(mode runTxMode, txBytes []byte) (ctx sdk.Context) { ctx = app.getState(mode).ctx. @@ -459,87 +469,9 @@ func (app *BaseApp) getContextForTx(mode runTxMode, txBytes []byte) (ctx sdk.Con return } -// runMsgs iterates through all the messages and executes them. -// nolint: gocyclo -func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (result sdk.Result) { - idxLogs := make([]sdk.ABCIMessageLog, 0, len(msgs)) // a list of JSON-encoded logs with msg index - - var ( - data []byte - code sdk.CodeType - codespace sdk.CodespaceType - ) - - events := sdk.EmptyEvents() - - // NOTE: GasWanted is determined by ante handler and GasUsed by the GasMeter. - for msgIdx, msg := range msgs { - // match message route - msgRoute := msg.Route() - handler := app.router.Route(msgRoute) - if handler == nil { - return sdk.ErrUnknownRequest("Unrecognized Msg type: " + msgRoute).Result() - } - - var msgResult sdk.Result - - // skip actual execution for CheckTx mode - if mode != runTxModeCheck { - msgResult = handler(ctx, msg) - } - - // Each message result's Data must be length prefixed in order to separate - // each result. - data = append(data, msgResult.Data...) - - // append events from the message's execution and a message action event - events = events.AppendEvent(sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, msg.Type()))) - events = events.AppendEvents(msgResult.Events) - - idxLog := sdk.ABCIMessageLog{MsgIndex: uint16(msgIdx), Log: msgResult.Log} - - // stop execution and return on first failed message - if !msgResult.IsOK() { - idxLog.Success = false - idxLogs = append(idxLogs, idxLog) - - code = msgResult.Code - codespace = msgResult.Codespace - break - } - - idxLog.Success = true - idxLogs = append(idxLogs, idxLog) - } - - logJSON := codec.Cdc.MustMarshalJSON(idxLogs) - result = sdk.Result{ - Code: code, - Codespace: codespace, - Data: data, - Log: strings.TrimSpace(string(logJSON)), - GasUsed: ctx.GasMeter().GasConsumed(), - Events: events, - } - - return result -} - -// Returns the applications's deliverState if app is in runTxModeDeliver, -// otherwise it returns the application's checkstate. -func (app *BaseApp) getState(mode runTxMode) *state { - if mode == runTxModeCheck || mode == runTxModeSimulate { - return app.checkState - } - - return app.deliverState -} - // cacheTxContext returns a new context based off of the provided context with // a cache wrapped multi-store. -func (app *BaseApp) cacheTxContext(ctx sdk.Context, txBytes []byte) ( - sdk.Context, sdk.CacheMultiStore) { - +func (app *BaseApp) cacheTxContext(ctx sdk.Context, txBytes []byte) (sdk.Context, sdk.CacheMultiStore) { ms := ctx.MultiStore() // TODO: https://github.com/cosmos/cosmos-sdk/issues/2824 msCache := ms.CacheMultiStore() @@ -674,6 +606,72 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk return result } +// runMsgs iterates through all the messages and executes them. +// nolint: gocyclo +func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (result sdk.Result) { + idxLogs := make([]sdk.ABCIMessageLog, 0, len(msgs)) // a list of JSON-encoded logs with msg index + + var ( + data []byte + code sdk.CodeType + codespace sdk.CodespaceType + ) + + events := sdk.EmptyEvents() + + // NOTE: GasWanted is determined by ante handler and GasUsed by the GasMeter. + for msgIdx, msg := range msgs { + // match message route + msgRoute := msg.Route() + handler := app.router.Route(msgRoute) + if handler == nil { + return sdk.ErrUnknownRequest("Unrecognized Msg type: " + msgRoute).Result() + } + + var msgResult sdk.Result + + // skip actual execution for CheckTx mode + if mode != runTxModeCheck { + msgResult = handler(ctx, msg) + } + + // Each message result's Data must be length prefixed in order to separate + // each result. + data = append(data, msgResult.Data...) + + // append events from the message's execution and a message action event + events = events.AppendEvent(sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, msg.Type()))) + events = events.AppendEvents(msgResult.Events) + + idxLog := sdk.ABCIMessageLog{MsgIndex: uint16(msgIdx), Log: msgResult.Log} + + // stop execution and return on first failed message + if !msgResult.IsOK() { + idxLog.Success = false + idxLogs = append(idxLogs, idxLog) + + code = msgResult.Code + codespace = msgResult.Codespace + break + } + + idxLog.Success = true + idxLogs = append(idxLogs, idxLog) + } + + logJSON := codec.Cdc.MustMarshalJSON(idxLogs) + result = sdk.Result{ + Code: code, + Codespace: codespace, + Data: data, + Log: strings.TrimSpace(string(logJSON)), + GasUsed: ctx.GasMeter().GasConsumed(), + Events: events, + } + + return result +} + // Splits a string path using the delimiter '/'. // e.g. "this/is/funny" becomes []string{"this", "is", "funny"} func splitPath(requestPath string) (path []string) { From 6430ca0efb294f3fe5c79f89e29c574f33d84357 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 19 Aug 2019 13:53:21 -0400 Subject: [PATCH 14/70] Remove cache manager from multi-store --- store/cachemulti/cache_test.go | 64 ---------------------------- store/cachemulti/store.go | 24 +++-------- store/rootmulti/store.go | 12 ++---- {store/cachemulti => types}/cache.go | 59 +++++++++++-------------- types/cache_test.go | 59 +++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 123 deletions(-) delete mode 100644 store/cachemulti/cache_test.go rename {store/cachemulti => types}/cache.go (52%) create mode 100644 types/cache_test.go diff --git a/store/cachemulti/cache_test.go b/store/cachemulti/cache_test.go deleted file mode 100644 index 5e2198ffde2b..000000000000 --- a/store/cachemulti/cache_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package cachemulti_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - "github.com/tendermint/iavl" - dbm "github.com/tendermint/tendermint/libs/db" - - "github.com/cosmos/cosmos-sdk/store/cachemulti" - iavlstore "github.com/cosmos/cosmos-sdk/store/iavl" - "github.com/cosmos/cosmos-sdk/store/types" -) - -func TestGetOrSetStoreCache(t *testing.T) { - db := dbm.NewMemDB() - tree := iavl.NewMutableTree(db, 100) - store := iavlstore.UnsafeNewStore(tree, 10, 10) - cwStore := store.CacheWrap() - - mngr := cachemulti.NewStoreCacheManager() - sKey := types.NewKVStoreKey("test") - cwStore2 := mngr.GetOrSetStoreCache(sKey, cwStore) - - require.NotNil(t, cwStore2) - require.Equal(t, cwStore2, mngr.GetOrSetStoreCache(sKey, cwStore)) -} - -func TestStoreCache(t *testing.T) { - db := dbm.NewMemDB() - tree := iavl.NewMutableTree(db, 100) - store := iavlstore.UnsafeNewStore(tree, 10, 10) - cwStore := store.CacheWrap() - - mngr := cachemulti.NewStoreCacheManager() - sKey := types.NewKVStoreKey("test") - kvStore := mngr.GetOrSetStoreCache(sKey, cwStore).(types.KVStore) - - for i := 0; i < cachemulti.PersistentStoreCacheSize*2; i++ { - key := []byte(fmt.Sprintf("key_%d", i)) - value := []byte(fmt.Sprintf("value_%d", i)) - - kvStore.Set(key, value) - - res := kvStore.Get(key) - require.Equal(t, res, value) - - res = cwStore.(types.KVStore).Get(key) - require.Equal(t, res, value) - } - - for i := 0; i < cachemulti.PersistentStoreCacheSize*2; i++ { - key := []byte(fmt.Sprintf("key_%d", i)) - - kvStore.Delete(key) - - res := kvStore.Get(key) - require.Nil(t, res) - - res = cwStore.(types.KVStore).Get(key) - require.Nil(t, res) - } -} diff --git a/store/cachemulti/store.go b/store/cachemulti/store.go index 80da73084a00..50b238df9a9d 100644 --- a/store/cachemulti/store.go +++ b/store/cachemulti/store.go @@ -25,20 +25,16 @@ type Store struct { traceWriter io.Writer traceContext types.TraceContext - - cacheManager *StoreCacheManager } var _ types.CacheMultiStore = Store{} // NewFromKVStore creates a new Store object from a mapping of store keys to // CacheWrapper objects and a KVStore as the database. Each CacheWrapper store -// is cache-wrapped. In addition, if a StoreCacheManager is provided, then it'll -// be used to act as a persistent inter-block cache. +// is cache-wrapped. func NewFromKVStore( store types.KVStore, stores map[types.StoreKey]types.CacheWrapper, keys map[string]types.StoreKey, traceWriter io.Writer, traceContext types.TraceContext, - cacheMngr *StoreCacheManager, ) Store { cms := Store{ db: cachekv.NewStore(store), @@ -46,7 +42,6 @@ func NewFromKVStore( keys: keys, traceWriter: traceWriter, traceContext: traceContext, - cacheManager: cacheMngr, } for key, store := range stores { @@ -58,25 +53,20 @@ func NewFromKVStore( cacheWrappedStore = store.CacheWrap() } - if cacheMngr != nil { - cms.stores[key] = cacheMngr.GetOrSetStoreCache(key, cacheWrappedStore) - } else { - cms.stores[key] = cacheWrappedStore - } + cms.stores[key] = cacheWrappedStore } return cms } // NewStore creates a new Store object from a mapping of store keys to -// CacheWrapper objects. Each CacheWrapper store is cache-wrapped. In addition, -// if a StoreCacheManager is provided, then it'll be used to act as a persistent -// inter-block cache. +// CacheWrapper objects. Each CacheWrapper store is cache-wrapped. func NewStore( db dbm.DB, stores map[types.StoreKey]types.CacheWrapper, keys map[string]types.StoreKey, - traceWriter io.Writer, traceContext types.TraceContext, cacheMngr *StoreCacheManager, + traceWriter io.Writer, traceContext types.TraceContext, ) Store { - return NewFromKVStore(dbadapter.Store{db}, stores, keys, traceWriter, traceContext, cacheMngr) + + return NewFromKVStore(dbadapter.Store{DB: db}, stores, keys, traceWriter, traceContext) } func newCacheMultiStoreFromCMS(cms Store) Store { @@ -85,7 +75,7 @@ func newCacheMultiStoreFromCMS(cms Store) Store { stores[k] = v } - return NewFromKVStore(cms.db, stores, nil, cms.traceWriter, cms.traceContext, cms.cacheManager) + return NewFromKVStore(cms.db, stores, nil, cms.traceWriter, cms.traceContext) } // SetTracer sets the tracer for the MultiStore that the underlying diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 3dc1854c7292..87939cd2c3fe 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -38,7 +38,6 @@ type Store struct { traceWriter io.Writer traceContext types.TraceContext - cacheManager *cachemulti.StoreCacheManager } var _ types.CommitMultiStore = (*Store)(nil) @@ -51,7 +50,6 @@ func NewStore(db dbm.DB) *Store { storesParams: make(map[types.StoreKey]storeParams), stores: make(map[types.StoreKey]types.CommitStore), keysByName: make(map[string]types.StoreKey), - cacheManager: cachemulti.NewStoreCacheManager(), } } @@ -295,22 +293,20 @@ func (rs *Store) CacheWrapWithTrace(_ io.Writer, _ types.TraceContext) types.Cac // +MultiStore // CacheMultiStore cache-wraps the multi-store and returns a CacheMultiStore. -// It implements the MultiStore interface. Note, the multi-store has a persistent -// inter-block cache that will be used by all subsequent KVStores. +// It implements the MultiStore interface. func (rs *Store) CacheMultiStore() types.CacheMultiStore { stores := make(map[types.StoreKey]types.CacheWrapper) for k, v := range rs.stores { stores[k] = v } - return cachemulti.NewStore(rs.db, stores, rs.keysByName, rs.traceWriter, rs.traceContext, rs.cacheManager) + return cachemulti.NewStore(rs.db, stores, rs.keysByName, rs.traceWriter, rs.traceContext) } // CacheMultiStoreWithVersion is analogous to CacheMultiStore except that it // attempts to load stores at a given version (height). An error is returned if // any store cannot be loaded. This should only be used for querying and -// iterating at past heights. Note, the multi-store has a persistent inter-block -// cache that will be used by all subsequent KVStores. +// iterating at past heights. func (rs *Store) CacheMultiStoreWithVersion(version int64) (types.CacheMultiStore, error) { cachedStores := make(map[types.StoreKey]types.CacheWrapper) for key, store := range rs.stores { @@ -330,7 +326,7 @@ func (rs *Store) CacheMultiStoreWithVersion(version int64) (types.CacheMultiStor } } - return cachemulti.NewStore(rs.db, cachedStores, rs.keysByName, rs.traceWriter, rs.traceContext, rs.cacheManager), nil + return cachemulti.NewStore(rs.db, cachedStores, rs.keysByName, rs.traceWriter, rs.traceContext), nil } // Implements MultiStore. diff --git a/store/cachemulti/cache.go b/types/cache.go similarity index 52% rename from store/cachemulti/cache.go rename to types/cache.go index 945b8d86a607..182c5b3c7cce 100644 --- a/store/cachemulti/cache.go +++ b/types/cache.go @@ -1,16 +1,13 @@ -package cachemulti +package types import ( "fmt" - "github.com/cosmos/cosmos-sdk/store/types" - lru "github.com/hashicorp/golang-lru" ) var ( - _ types.KVStore = (*StoreCache)(nil) - _ types.CacheWrap = (*StoreCache)(nil) + _ KVStore = (*KVStoreCache)(nil) // PersistentStoreCacheSize defines the persistent ARC cache size for each // KVStore. @@ -18,32 +15,32 @@ var ( ) type ( - // StoreCache defines a cache that is meant to be used in a persistent + // KVStoreCache defines a cache that is meant to be used in a persistent // (inter-block) fashion and in which it wraps an underlying KVStore. Reads // first hit the ARC (Adaptive Replacement Cache). During a cache miss, the // read is delegated to the underlying KVStore. Deletes and writes always // happen to both the cache and the KVStore in a write-through manner. Caching - // performed in the KVStore is completely irrelevant to this layer. - StoreCache struct { - types.KVStore + // performed in the KVStore and below is completely irrelevant to this layer. + KVStoreCache struct { + KVStore cache *lru.ARCCache } - // StoreCacheManager defines a manager that handles a mapping of StoreKeys - // to StoreCache references. Each StoreCache reference is meant to be + // StoreCacheManager defines a manager that stores a mapping of StoreKeys + // to KVStoreCache references. Each KVStoreCache reference is meant to be // persistent between blocks. StoreCacheManager struct { - caches map[types.StoreKey]*StoreCache + caches map[StoreKey]*KVStoreCache } ) -func NewStoreCache(store types.KVStore) *StoreCache { +func NewStoreCache(store KVStore) *KVStoreCache { cache, err := lru.NewARC(PersistentStoreCacheSize) if err != nil { panic(fmt.Errorf("failed to create cache: %s", err)) } - return &StoreCache{ + return &KVStoreCache{ KVStore: store, cache: cache, } @@ -51,54 +48,48 @@ func NewStoreCache(store types.KVStore) *StoreCache { func NewStoreCacheManager() *StoreCacheManager { return &StoreCacheManager{ - caches: make(map[types.StoreKey]*StoreCache), + caches: make(map[StoreKey]*KVStoreCache), } } -// GetOrSetStoreCache attempts to get a CacheWrap store from the StoreCacheManager. +// GetOrSetKVStoreCache attempts to get a CacheWrap store from the StoreCacheManager. // If the CacheWrap does not exist in the mapping, it is added. Each CacheWrap // store contains a persistent cache through the StoreCache. -func (cmgr *StoreCacheManager) GetOrSetStoreCache(key types.StoreKey, store types.CacheWrap) types.CacheWrap { +func (cmgr *StoreCacheManager) GetOrSetKVStoreCache(key StoreKey, store KVStore) KVStore { if cmgr.caches[key] == nil { - cmgr.caches[key] = NewStoreCache(store.(types.KVStore)) + cmgr.caches[key] = NewStoreCache(store) } return cmgr.caches[key] } -// Write implements the CacheWrap interface and simply delegates the Write call -// to the underlying KVStore. -func (sc *StoreCache) Write() { - sc.KVStore.(types.CacheWrap).Write() -} - // Get retrieves a value by key. It will first look in the write-through cache. // If the value doesn't exist in the write-through cache, the Get call is // delegated to the underlying KVStore. -func (sc *StoreCache) Get(key []byte) []byte { - val, ok := sc.cache.Get(string(key)) +func (kvsc *KVStoreCache) Get(key []byte) []byte { + val, ok := kvsc.cache.Get(string(key)) if ok { // cache hit return val.([]byte) } // cache miss; add to cache - bz := sc.KVStore.Get(key) - sc.cache.Add(string(key), bz) + bz := kvsc.KVStore.Get(key) + kvsc.cache.Add(string(key), bz) return bz } // Set inserts a key/value pair into both the write-through cache and the // underlying KVStore. -func (sc *StoreCache) Set(key, value []byte) { - sc.cache.Add(string(key), value) - sc.KVStore.Set(key, value) +func (kvsc *KVStoreCache) Set(key, value []byte) { + kvsc.cache.Add(string(key), value) + kvsc.KVStore.Set(key, value) } // Delete removes a key/value pair from both the write-through cache and the // underlying KVStore. -func (sc *StoreCache) Delete(key []byte) { - sc.cache.Remove(string(key)) - sc.KVStore.Delete(key) +func (kvsc *KVStoreCache) Delete(key []byte) { + kvsc.cache.Remove(string(key)) + kvsc.KVStore.Delete(key) } diff --git a/types/cache_test.go b/types/cache_test.go new file mode 100644 index 000000000000..f235e2f58e99 --- /dev/null +++ b/types/cache_test.go @@ -0,0 +1,59 @@ +package types_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + "github.com/tendermint/iavl" + dbm "github.com/tendermint/tm-db" + + iavlstore "github.com/cosmos/cosmos-sdk/store/iavl" + "github.com/cosmos/cosmos-sdk/types" +) + +func TestGetOrSetStoreCache(t *testing.T) { + db := dbm.NewMemDB() + mngr := types.NewStoreCacheManager() + + sKey := types.NewKVStoreKey("test") + store := iavlstore.UnsafeNewStore(iavl.NewMutableTree(db, 100), 10, 10) + store2 := mngr.GetOrSetKVStoreCache(sKey, store) + + require.NotNil(t, store2) + require.Equal(t, store2, mngr.GetOrSetKVStoreCache(sKey, store)) +} + +func TestStoreCache(t *testing.T) { + db := dbm.NewMemDB() + mngr := types.NewStoreCacheManager() + + sKey := types.NewKVStoreKey("test") + store := iavlstore.UnsafeNewStore(iavl.NewMutableTree(db, 100), 10, 10) + kvStore := mngr.GetOrSetKVStoreCache(sKey, store) + + for i := 0; i < types.PersistentStoreCacheSize*2; i++ { + key := []byte(fmt.Sprintf("key_%d", i)) + value := []byte(fmt.Sprintf("value_%d", i)) + + kvStore.Set(key, value) + + res := kvStore.Get(key) + require.Equal(t, res, value) + + res = store.Get(key) + require.Equal(t, res, value) + } + + for i := 0; i < types.PersistentStoreCacheSize*2; i++ { + key := []byte(fmt.Sprintf("key_%d", i)) + + kvStore.Delete(key) + + res := kvStore.Get(key) + require.Nil(t, res) + + res = store.Get(key) + require.Nil(t, res) + } +} From 0d89c5e39f10b80aa07da66c91c6fec10b4eea25 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 19 Aug 2019 13:54:07 -0400 Subject: [PATCH 15/70] Implement SetInterBlockCache option on BaseApp --- baseapp/options.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/baseapp/options.go b/baseapp/options.go index 15a825ee4a59..8997909107d9 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -8,6 +8,7 @@ import ( dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/store/cachemulti" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -34,6 +35,12 @@ func SetHaltHeight(height uint64) func(*BaseApp) { return func(bap *BaseApp) { bap.setHaltHeight(height) } } +// SetInterBlockCache provides a BaseApp option function that sets the +// inter-block cache. +func SetInterBlockCache(cache *cachemulti.StoreCacheManager) func(*BaseApp) { + return func(app *BaseApp) { app.setInterBlockCache(cache) } +} + func (app *BaseApp) SetName(name string) { if app.sealed { panic("SetName() on sealed BaseApp") From f8fc57f3a44a320933e9b6d789bc963ef7e944ed Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 19 Aug 2019 13:54:31 -0400 Subject: [PATCH 16/70] More BaseApp godoc cleanup and support for inter-block cache --- baseapp/baseapp.go | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 5be819732c07..13090e81dfe4 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -18,6 +18,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/store/cachemulti" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -76,14 +77,18 @@ type BaseApp struct { idPeerFilter sdk.PeerFilter // filter peers by node ID fauxMerkleMode bool // if true, IAVL MountStores uses MountStoresDB for simulation speed. - // -------------------- - // Volatile state - // checkState is set on initialization and reset on Commit. - // deliverState is set in InitChain and BeginBlock and cleared on Commit. - // See methods setCheckState and setDeliverState. - checkState *state // for CheckTx - deliverState *state // for DeliverTx - voteInfos []abci.VoteInfo // absent validators from begin block + // volatile states: + // + // checkState is set on InitChain and reset on Commit + // deliverState is set on InitChain and BeginBlock and set to nil on Commit + checkState *state // for CheckTx + deliverState *state // for DeliverTx + + // an inter-block write-through cache provided to the context during deliverState + interBlockCache *cachemulti.StoreCacheManager + + // absent validators from begin block + voteInfos []abci.VoteInfo // consensus params // TODO: Move this in the future to baseapp param store on main store. @@ -337,6 +342,10 @@ func (app *BaseApp) setHaltHeight(height uint64) { app.haltHeight = height } +func (app *BaseApp) setInterBlockCache(cache *cachemulti.StoreCacheManager) { + app.interBlockCache = cache +} + // Router returns the router of the BaseApp. func (app *BaseApp) Router() sdk.Router { if app.sealed { @@ -356,9 +365,10 @@ func (app *BaseApp) Seal() { app.sealed = true } // IsSealed returns true if the BaseApp is sealed and false otherwise. func (app *BaseApp) IsSealed() bool { return app.sealed } -// setCheckState sets checkState with the cached multistore and -// the context wrapping it. -// It is called by InitChain() and Commit() +// setCheckState sets the BaseApp's checkState with a cache-wrapped multi-store +// (i.e. a CacheMultiStore) and a new Context with the cache-wrapped multi-store, +// provided header, and minimum gas prices set. It is set on InitChain and reset +// on Commit. func (app *BaseApp) setCheckState(header abci.Header) { ms := app.cms.CacheMultiStore() app.checkState = &state{ @@ -367,10 +377,10 @@ func (app *BaseApp) setCheckState(header abci.Header) { } } -// setCheckState sets checkState with the cached multistore and -// the context wrapping it. -// It is called by InitChain() and BeginBlock(), -// and deliverState is set nil on Commit(). +// setDeliverState sets the BaseApp's deliverState with a cache-wrapped multi-store +// (i.e. a CacheMultiStore) and a new Context with the cache-wrapped multi-store, +// and provided header. It is set on InitChain and BeginBlock and set to nil on +// Commit. func (app *BaseApp) setDeliverState(header abci.Header) { ms := app.cms.CacheMultiStore() app.deliverState = &state{ From 5bc9f73e65416646a53107c6551f366dbb448225 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 19 Aug 2019 14:18:03 -0400 Subject: [PATCH 17/70] Revert changes in new cache multi-store --- store/cachemulti/store.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/store/cachemulti/store.go b/store/cachemulti/store.go index 50b238df9a9d..463781656b44 100644 --- a/store/cachemulti/store.go +++ b/store/cachemulti/store.go @@ -45,15 +45,11 @@ func NewFromKVStore( } for key, store := range stores { - var cacheWrappedStore types.CacheWrap - if cms.TracingEnabled() { - cacheWrappedStore = store.CacheWrapWithTrace(cms.traceWriter, cms.traceContext) + cms.stores[key] = store.CacheWrapWithTrace(cms.traceWriter, cms.traceContext) } else { - cacheWrappedStore = store.CacheWrap() + cms.stores[key] = store.CacheWrap() } - - cms.stores[key] = cacheWrappedStore } return cms From cc01e564e2b61b0dc7d2f23173aecac268dfad1d Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 19 Aug 2019 14:25:57 -0400 Subject: [PATCH 18/70] Fix build --- baseapp/baseapp.go | 5 ++--- baseapp/options.go | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 13090e81dfe4..f515570fc8ee 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -18,7 +18,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store" - "github.com/cosmos/cosmos-sdk/store/cachemulti" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -85,7 +84,7 @@ type BaseApp struct { deliverState *state // for DeliverTx // an inter-block write-through cache provided to the context during deliverState - interBlockCache *cachemulti.StoreCacheManager + interBlockCache *sdk.StoreCacheManager // absent validators from begin block voteInfos []abci.VoteInfo @@ -342,7 +341,7 @@ func (app *BaseApp) setHaltHeight(height uint64) { app.haltHeight = height } -func (app *BaseApp) setInterBlockCache(cache *cachemulti.StoreCacheManager) { +func (app *BaseApp) setInterBlockCache(cache *sdk.StoreCacheManager) { app.interBlockCache = cache } diff --git a/baseapp/options.go b/baseapp/options.go index 8997909107d9..14214b4d78ed 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -8,7 +8,6 @@ import ( dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/store" - "github.com/cosmos/cosmos-sdk/store/cachemulti" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -37,7 +36,7 @@ func SetHaltHeight(height uint64) func(*BaseApp) { // SetInterBlockCache provides a BaseApp option function that sets the // inter-block cache. -func SetInterBlockCache(cache *cachemulti.StoreCacheManager) func(*BaseApp) { +func SetInterBlockCache(cache *sdk.StoreCacheManager) func(*BaseApp) { return func(app *BaseApp) { app.setInterBlockCache(cache) } } From 23eecc705fff6a708f451927e8b4f18dcfdea8b6 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 19 Aug 2019 14:26:22 -0400 Subject: [PATCH 19/70] Add KVStore cache manager to Context --- types/context.go | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/types/context.go b/types/context.go index 9fe8f2b67437..5e68e8edf580 100644 --- a/types/context.go +++ b/types/context.go @@ -21,19 +21,20 @@ but please do not over-use it. We try to keep all data structured and standard additions here would be better just to add to the Context struct */ type Context struct { - ctx context.Context - ms MultiStore - header abci.Header - chainID string - txBytes []byte - logger log.Logger - voteInfo []abci.VoteInfo - gasMeter GasMeter - blockGasMeter GasMeter - checkTx bool - minGasPrice DecCoins - consParams *abci.ConsensusParams - eventManager *EventManager + ctx context.Context + ms MultiStore + interBlockCache *StoreCacheManager + header abci.Header + chainID string + txBytes []byte + logger log.Logger + voteInfo []abci.VoteInfo + gasMeter GasMeter + blockGasMeter GasMeter + checkTx bool + minGasPrice DecCoins + consParams *abci.ConsensusParams + eventManager *EventManager } // Proposed rename, not done to avoid API breakage @@ -91,6 +92,11 @@ func (c Context) WithMultiStore(ms MultiStore) Context { return c } +func (c Context) WithInterBlockCache(cacheMngr *StoreCacheManager) Context { + c.interBlockCache = cacheMngr + return c +} + func (c Context) WithBlockHeader(header abci.Header) Context { // https://github.com/gogo/protobuf/issues/519 header.Time = header.Time.UTC() From ce59123e9f5dd99a06a083a46cafbaef610e3c90 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 19 Aug 2019 14:28:05 -0400 Subject: [PATCH 20/70] Update Context KVStore and TransientStore to use KVStore cache manager --- types/context.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/types/context.go b/types/context.go index 5e68e8edf580..640e47e1986e 100644 --- a/types/context.go +++ b/types/context.go @@ -203,12 +203,24 @@ func (c Context) Value(key interface{}) interface{} { // KVStore fetches a KVStore from the MultiStore. func (c Context) KVStore(key StoreKey) KVStore { - return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.KVGasConfig()) + kvStore := c.MultiStore().GetKVStore(key) + if c.interBlockCache != nil { + // wrap the KVStore in an inter-block write-through cache + kvStore = c.interBlockCache.GetOrSetKVStoreCache(key, kvStore) + } + + return gaskv.NewStore(kvStore, c.GasMeter(), stypes.KVGasConfig()) } // TransientStore fetches a TransientStore from the MultiStore. func (c Context) TransientStore(key StoreKey) KVStore { - return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.TransientGasConfig()) + kvStore := c.MultiStore().GetKVStore(key) + if c.interBlockCache != nil { + // wrap the KVStore in an inter-block write-through cache + kvStore = c.interBlockCache.GetOrSetKVStoreCache(key, kvStore) + } + + return gaskv.NewStore(kvStore, c.GasMeter(), stypes.TransientGasConfig()) } // CacheContext returns a new Context with the multi-store cached and a new From 2765b324c5d4a2666e8a0f6aa0cc35a8b91dd34a Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 19 Aug 2019 14:29:33 -0400 Subject: [PATCH 21/70] Update setDeliverState godoc --- baseapp/baseapp.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index f515570fc8ee..ba16518a2eba 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -378,8 +378,10 @@ func (app *BaseApp) setCheckState(header abci.Header) { // setDeliverState sets the BaseApp's deliverState with a cache-wrapped multi-store // (i.e. a CacheMultiStore) and a new Context with the cache-wrapped multi-store, -// and provided header. It is set on InitChain and BeginBlock and set to nil on -// Commit. +// and provided header. If an inter-block cache is set on the BaseApp, it will +// be provided to the context such that whenever a KVStore is retrieived, it'll +// be wrapped with a persistent write-through cache. It is set on InitChain and +// BeginBlock and set to nil on Commit. func (app *BaseApp) setDeliverState(header abci.Header) { ms := app.cms.CacheMultiStore() app.deliverState = &state{ From 24aa18a4d2080bbd7b95e2154688af2bc62e0080 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 19 Aug 2019 19:40:44 -0400 Subject: [PATCH 22/70] Support cache size as uint --- baseapp/abci.go | 3 ++- types/cache.go | 22 ++++++++++++---------- types/cache_test.go | 8 ++++---- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index dc031197589d..6ba592b0c191 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -6,9 +6,10 @@ import ( "sort" "strings" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - abci "github.com/tendermint/tendermint/abci/types" ) // InitChain implements the ABCI interface. It runs the initialization logic diff --git a/types/cache.go b/types/cache.go index 182c5b3c7cce..46d76faf3d96 100644 --- a/types/cache.go +++ b/types/cache.go @@ -9,9 +9,9 @@ import ( var ( _ KVStore = (*KVStoreCache)(nil) - // PersistentStoreCacheSize defines the persistent ARC cache size for each - // KVStore. - PersistentStoreCacheSize = 1000 + // DefaultPersistentKVStoreCacheSize defines the persistent ARC cache size for + // each KVStore. + DefaultPersistentKVStoreCacheSize uint = 1000 ) type ( @@ -30,14 +30,15 @@ type ( // to KVStoreCache references. Each KVStoreCache reference is meant to be // persistent between blocks. StoreCacheManager struct { - caches map[StoreKey]*KVStoreCache + cacheSize uint + caches map[StoreKey]*KVStoreCache } ) -func NewStoreCache(store KVStore) *KVStoreCache { - cache, err := lru.NewARC(PersistentStoreCacheSize) +func NewKVStoreCache(store KVStore, size uint) *KVStoreCache { + cache, err := lru.NewARC(int(size)) if err != nil { - panic(fmt.Errorf("failed to create cache: %s", err)) + panic(fmt.Errorf("failed to create KVStore cache: %s", err)) } return &KVStoreCache{ @@ -46,9 +47,10 @@ func NewStoreCache(store KVStore) *KVStoreCache { } } -func NewStoreCacheManager() *StoreCacheManager { +func NewStoreCacheManager(size uint) *StoreCacheManager { return &StoreCacheManager{ - caches: make(map[StoreKey]*KVStoreCache), + cacheSize: size, + caches: make(map[StoreKey]*KVStoreCache), } } @@ -57,7 +59,7 @@ func NewStoreCacheManager() *StoreCacheManager { // store contains a persistent cache through the StoreCache. func (cmgr *StoreCacheManager) GetOrSetKVStoreCache(key StoreKey, store KVStore) KVStore { if cmgr.caches[key] == nil { - cmgr.caches[key] = NewStoreCache(store) + cmgr.caches[key] = NewKVStoreCache(store, cmgr.cacheSize) } return cmgr.caches[key] diff --git a/types/cache_test.go b/types/cache_test.go index f235e2f58e99..802dff6511e4 100644 --- a/types/cache_test.go +++ b/types/cache_test.go @@ -14,7 +14,7 @@ import ( func TestGetOrSetStoreCache(t *testing.T) { db := dbm.NewMemDB() - mngr := types.NewStoreCacheManager() + mngr := types.NewStoreCacheManager(types.DefaultPersistentKVStoreCacheSize) sKey := types.NewKVStoreKey("test") store := iavlstore.UnsafeNewStore(iavl.NewMutableTree(db, 100), 10, 10) @@ -26,13 +26,13 @@ func TestGetOrSetStoreCache(t *testing.T) { func TestStoreCache(t *testing.T) { db := dbm.NewMemDB() - mngr := types.NewStoreCacheManager() + mngr := types.NewStoreCacheManager(types.DefaultPersistentKVStoreCacheSize) sKey := types.NewKVStoreKey("test") store := iavlstore.UnsafeNewStore(iavl.NewMutableTree(db, 100), 10, 10) kvStore := mngr.GetOrSetKVStoreCache(sKey, store) - for i := 0; i < types.PersistentStoreCacheSize*2; i++ { + for i := uint(0); i < types.DefaultPersistentKVStoreCacheSize*2; i++ { key := []byte(fmt.Sprintf("key_%d", i)) value := []byte(fmt.Sprintf("value_%d", i)) @@ -45,7 +45,7 @@ func TestStoreCache(t *testing.T) { require.Equal(t, res, value) } - for i := 0; i < types.PersistentStoreCacheSize*2; i++ { + for i := uint(0); i < types.DefaultPersistentKVStoreCacheSize*2; i++ { key := []byte(fmt.Sprintf("key_%d", i)) kvStore.Delete(key) From 4793428c6d021f4994688926c8aac13480f6079f Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 21 Aug 2019 10:00:33 -0400 Subject: [PATCH 23/70] Update BaseApp to call WithInterBlockCache --- baseapp/baseapp.go | 2 +- baseapp/helpers.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index ba16518a2eba..6ce605b9cfab 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -386,7 +386,7 @@ func (app *BaseApp) setDeliverState(header abci.Header) { ms := app.cms.CacheMultiStore() app.deliverState = &state{ ms: ms, - ctx: sdk.NewContext(ms, header, false, app.logger), + ctx: sdk.NewContext(ms, header, false, app.logger).WithInterBlockCache(app.interBlockCache), } } diff --git a/baseapp/helpers.go b/baseapp/helpers.go index 25f59cee5e77..c762de82d023 100644 --- a/baseapp/helpers.go +++ b/baseapp/helpers.go @@ -33,5 +33,5 @@ func (app *BaseApp) NewContext(isCheckTx bool, header abci.Header) sdk.Context { WithMinGasPrices(app.minGasPrices) } - return sdk.NewContext(app.deliverState.ms, header, false, app.logger) + return sdk.NewContext(app.deliverState.ms, header, false, app.logger).WithInterBlockCache(app.interBlockCache) } From e8d35f919b66305f34e0f347a2cfd491913e2f41 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 21 Aug 2019 10:03:23 -0400 Subject: [PATCH 24/70] Add godoc to WithInterBlockCache --- types/context.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/types/context.go b/types/context.go index 640e47e1986e..c17f23e56423 100644 --- a/types/context.go +++ b/types/context.go @@ -92,6 +92,10 @@ func (c Context) WithMultiStore(ms MultiStore) Context { return c } +// WithInterBlockCache returns the Context with an inter-block write-through +// cache. +// +// NOTE: This cache is persistent and should only be set on the DeliverTx state. func (c Context) WithInterBlockCache(cacheMngr *StoreCacheManager) Context { c.interBlockCache = cacheMngr return c From d93ab8cbf267f7f92638e74e52100cb45366f0df Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 21 Aug 2019 10:03:54 -0400 Subject: [PATCH 25/70] Linting --- baseapp/helpers.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/baseapp/helpers.go b/baseapp/helpers.go index c762de82d023..fa71cf45e5f8 100644 --- a/baseapp/helpers.go +++ b/baseapp/helpers.go @@ -33,5 +33,6 @@ func (app *BaseApp) NewContext(isCheckTx bool, header abci.Header) sdk.Context { WithMinGasPrices(app.minGasPrices) } - return sdk.NewContext(app.deliverState.ms, header, false, app.logger).WithInterBlockCache(app.interBlockCache) + return sdk.NewContext(app.deliverState.ms, header, false, app.logger). + WithInterBlockCache(app.interBlockCache) } From c5cb001cc0262270d5ab893006d04fbe5d03aed2 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 21 Aug 2019 10:11:25 -0400 Subject: [PATCH 26/70] Update simulation test suite to use inter-block cache --- simapp/sim_test.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/simapp/sim_test.go b/simapp/sim_test.go index 3557432da063..e09482327b12 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -247,6 +247,12 @@ func fauxMerkleModeOpt(bapp *baseapp.BaseApp) { bapp.SetFauxMerkleMode() } +// interBlockCache returns a BaseApp option function that sets the persistent +// inter-block write-through cache. +func interBlockCache() func(*baseapp.BaseApp) { + return baseapp.SetInterBlockCache(sdk.NewStoreCacheManager(sdk.DefaultPersistentKVStoreCacheSize)) +} + // Profile with: // /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/simapp -bench ^BenchmarkFullAppSimulation$ -Commit=true -cpuprofile cpu.out func BenchmarkFullAppSimulation(b *testing.B) { @@ -260,7 +266,8 @@ func BenchmarkFullAppSimulation(b *testing.B) { db.Close() os.RemoveAll(dir) }() - app := NewSimApp(logger, db, nil, true, 0) + + app := NewSimApp(logger, db, nil, true, 0, interBlockCache()) // Run randomized simulation // TODO: parameterize numbers, save for a later PR @@ -335,7 +342,7 @@ func TestFullAppSimulation(t *testing.T) { os.RemoveAll(dir) }() - app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt) + app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt, interBlockCache()) require.Equal(t, "SimApp", app.Name()) // Run randomized simulation @@ -399,7 +406,7 @@ func TestAppImportExport(t *testing.T) { os.RemoveAll(dir) }() - app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt) + app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt, interBlockCache()) require.Equal(t, "SimApp", app.Name()) // Run randomized simulation @@ -452,7 +459,7 @@ func TestAppImportExport(t *testing.T) { _ = os.RemoveAll(newDir) }() - newApp := NewSimApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt) + newApp := NewSimApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt, interBlockCache()) require.Equal(t, "SimApp", newApp.Name()) var genesisState GenesisState @@ -525,7 +532,7 @@ func TestAppSimulationAfterImport(t *testing.T) { os.RemoveAll(dir) }() - app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt) + app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt, interBlockCache()) require.Equal(t, "SimApp", app.Name()) // Run randomized simulation @@ -585,7 +592,7 @@ func TestAppSimulationAfterImport(t *testing.T) { _ = os.RemoveAll(newDir) }() - newApp := NewSimApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt) + newApp := NewSimApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt, interBlockCache()) require.Equal(t, "SimApp", newApp.Name()) newApp.InitChain(abci.RequestInitChain{ AppStateBytes: appState, @@ -624,7 +631,8 @@ func TestAppStateDeterminism(t *testing.T) { for j := 0; j < numTimesToRunPerSeed; j++ { logger := log.NewNopLogger() db := dbm.NewMemDB() - app := NewSimApp(logger, db, nil, true, 0) + + app := NewSimApp(logger, db, nil, true, 0, interBlockCache()) fmt.Printf( "Running non-determinism simulation; seed: %d/%d (%d), attempt: %d/%d\n", @@ -660,7 +668,7 @@ func BenchmarkInvariants(b *testing.B) { os.RemoveAll(dir) }() - app := NewSimApp(logger, db, nil, true, 0) + app := NewSimApp(logger, db, nil, true, 0, interBlockCache()) // 2. Run parameterized simulation (w/o invariants) _, params, simErr := simulation.SimulateFromSeed( From 7cebc1518b6e26a2bf9649bd2e2dc327b9393a9f Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 21 Aug 2019 10:18:48 -0400 Subject: [PATCH 27/70] Rename to KVStoreCacheManager --- baseapp/baseapp.go | 4 ++-- baseapp/options.go | 2 +- types/cache.go | 12 ++++++------ types/cache_test.go | 4 ++-- types/context.go | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 6ce605b9cfab..140a22930817 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -84,7 +84,7 @@ type BaseApp struct { deliverState *state // for DeliverTx // an inter-block write-through cache provided to the context during deliverState - interBlockCache *sdk.StoreCacheManager + interBlockCache *sdk.KVStoreCacheManager // absent validators from begin block voteInfos []abci.VoteInfo @@ -341,7 +341,7 @@ func (app *BaseApp) setHaltHeight(height uint64) { app.haltHeight = height } -func (app *BaseApp) setInterBlockCache(cache *sdk.StoreCacheManager) { +func (app *BaseApp) setInterBlockCache(cache *sdk.KVStoreCacheManager) { app.interBlockCache = cache } diff --git a/baseapp/options.go b/baseapp/options.go index 14214b4d78ed..026156f5c83c 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -36,7 +36,7 @@ func SetHaltHeight(height uint64) func(*BaseApp) { // SetInterBlockCache provides a BaseApp option function that sets the // inter-block cache. -func SetInterBlockCache(cache *sdk.StoreCacheManager) func(*BaseApp) { +func SetInterBlockCache(cache *sdk.KVStoreCacheManager) func(*BaseApp) { return func(app *BaseApp) { app.setInterBlockCache(cache) } } diff --git a/types/cache.go b/types/cache.go index 46d76faf3d96..6de76e3bfde3 100644 --- a/types/cache.go +++ b/types/cache.go @@ -26,10 +26,10 @@ type ( cache *lru.ARCCache } - // StoreCacheManager defines a manager that stores a mapping of StoreKeys + // KVStoreCacheManager defines a manager that stores a mapping of StoreKeys // to KVStoreCache references. Each KVStoreCache reference is meant to be // persistent between blocks. - StoreCacheManager struct { + KVStoreCacheManager struct { cacheSize uint caches map[StoreKey]*KVStoreCache } @@ -47,17 +47,17 @@ func NewKVStoreCache(store KVStore, size uint) *KVStoreCache { } } -func NewStoreCacheManager(size uint) *StoreCacheManager { - return &StoreCacheManager{ +func NewKVStoreCacheManager(size uint) *KVStoreCacheManager { + return &KVStoreCacheManager{ cacheSize: size, caches: make(map[StoreKey]*KVStoreCache), } } -// GetOrSetKVStoreCache attempts to get a CacheWrap store from the StoreCacheManager. +// GetOrSetKVStoreCache attempts to get a CacheWrap store from the KVStoreCacheManager. // If the CacheWrap does not exist in the mapping, it is added. Each CacheWrap // store contains a persistent cache through the StoreCache. -func (cmgr *StoreCacheManager) GetOrSetKVStoreCache(key StoreKey, store KVStore) KVStore { +func (cmgr *KVStoreCacheManager) GetOrSetKVStoreCache(key StoreKey, store KVStore) KVStore { if cmgr.caches[key] == nil { cmgr.caches[key] = NewKVStoreCache(store, cmgr.cacheSize) } diff --git a/types/cache_test.go b/types/cache_test.go index 802dff6511e4..d84e7636a387 100644 --- a/types/cache_test.go +++ b/types/cache_test.go @@ -14,7 +14,7 @@ import ( func TestGetOrSetStoreCache(t *testing.T) { db := dbm.NewMemDB() - mngr := types.NewStoreCacheManager(types.DefaultPersistentKVStoreCacheSize) + mngr := types.NewKVStoreCacheManager(types.DefaultPersistentKVStoreCacheSize) sKey := types.NewKVStoreKey("test") store := iavlstore.UnsafeNewStore(iavl.NewMutableTree(db, 100), 10, 10) @@ -26,7 +26,7 @@ func TestGetOrSetStoreCache(t *testing.T) { func TestStoreCache(t *testing.T) { db := dbm.NewMemDB() - mngr := types.NewStoreCacheManager(types.DefaultPersistentKVStoreCacheSize) + mngr := types.NewKVStoreCacheManager(types.DefaultPersistentKVStoreCacheSize) sKey := types.NewKVStoreKey("test") store := iavlstore.UnsafeNewStore(iavl.NewMutableTree(db, 100), 10, 10) diff --git a/types/context.go b/types/context.go index c17f23e56423..cc4c6a903982 100644 --- a/types/context.go +++ b/types/context.go @@ -23,7 +23,7 @@ and standard additions here would be better just to add to the Context struct type Context struct { ctx context.Context ms MultiStore - interBlockCache *StoreCacheManager + interBlockCache *KVStoreCacheManager header abci.Header chainID string txBytes []byte @@ -96,7 +96,7 @@ func (c Context) WithMultiStore(ms MultiStore) Context { // cache. // // NOTE: This cache is persistent and should only be set on the DeliverTx state. -func (c Context) WithInterBlockCache(cacheMngr *StoreCacheManager) Context { +func (c Context) WithInterBlockCache(cacheMngr *KVStoreCacheManager) Context { c.interBlockCache = cacheMngr return c } From 5d9480109ce5e726f14a893e564499a7a2bc10ce Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 21 Aug 2019 10:31:43 -0400 Subject: [PATCH 28/70] Fix build --- simapp/app_bench_test.go | 1 + simapp/sim_test.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 simapp/app_bench_test.go diff --git a/simapp/app_bench_test.go b/simapp/app_bench_test.go new file mode 100644 index 000000000000..55736c719217 --- /dev/null +++ b/simapp/app_bench_test.go @@ -0,0 +1 @@ +package simapp_test \ No newline at end of file diff --git a/simapp/sim_test.go b/simapp/sim_test.go index e09482327b12..1c09b4c7e3f7 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -250,7 +250,7 @@ func fauxMerkleModeOpt(bapp *baseapp.BaseApp) { // interBlockCache returns a BaseApp option function that sets the persistent // inter-block write-through cache. func interBlockCache() func(*baseapp.BaseApp) { - return baseapp.SetInterBlockCache(sdk.NewStoreCacheManager(sdk.DefaultPersistentKVStoreCacheSize)) + return baseapp.SetInterBlockCache(sdk.NewKVStoreCacheManager(sdk.DefaultPersistentKVStoreCacheSize)) } // Profile with: From 1c09227c54d2ad64ccbe20568debd6cc1623ffeb Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 21 Aug 2019 14:40:29 -0400 Subject: [PATCH 29/70] Implement and call inter-block cache Reset --- baseapp/abci.go | 5 +++++ simapp/sim_test.go | 1 + types/cache.go | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/baseapp/abci.go b/baseapp/abci.go index 6ba592b0c191..11a6a9e3b41c 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -31,6 +31,11 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC return } + // reset the inter-block cache in case successive InitChain calls are made + if app.interBlockCache != nil { + app.interBlockCache.Reset() + } + // add block gas meter for any genesis transactions (allow infinite gas) app.deliverState.ctx = app.deliverState.ctx.WithBlockGasMeter(sdk.NewInfiniteGasMeter()) diff --git a/simapp/sim_test.go b/simapp/sim_test.go index 1c09b4c7e3f7..6bc512803589 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -594,6 +594,7 @@ func TestAppSimulationAfterImport(t *testing.T) { newApp := NewSimApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt, interBlockCache()) require.Equal(t, "SimApp", newApp.Name()) + newApp.InitChain(abci.RequestInitChain{ AppStateBytes: appState, }) diff --git a/types/cache.go b/types/cache.go index 6de76e3bfde3..93a7161c564c 100644 --- a/types/cache.go +++ b/types/cache.go @@ -65,6 +65,11 @@ func (cmgr *KVStoreCacheManager) GetOrSetKVStoreCache(key StoreKey, store KVStor return cmgr.caches[key] } +// Reset resets in the internal caches. +func (cmgr *KVStoreCacheManager) Reset() { + cmgr.caches = make(map[StoreKey]*KVStoreCache) +} + // Get retrieves a value by key. It will first look in the write-through cache. // If the value doesn't exist in the write-through cache, the Get call is // delegated to the underlying KVStore. From dc214197e192e89b5a936e051f2d856c34562a5f Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Fri, 23 Aug 2019 09:21:15 -0400 Subject: [PATCH 30/70] Only generate secp256k1 keys in simulation --- x/simulation/account.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/x/simulation/account.go b/x/simulation/account.go index fb3fdb65d817..386c55acd5bd 100644 --- a/x/simulation/account.go +++ b/x/simulation/account.go @@ -4,7 +4,6 @@ import ( "math/rand" "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" @@ -38,13 +37,8 @@ func RandomAccounts(r *rand.Rand, n int) []Account { // don't need that much entropy for simulation privkeySeed := make([]byte, 15) r.Read(privkeySeed) - useSecp := r.Int63()%2 == 0 - if useSecp { - accs[i].PrivKey = secp256k1.GenPrivKeySecp256k1(privkeySeed) - } else { - accs[i].PrivKey = ed25519.GenPrivKeyFromSecret(privkeySeed) - } + accs[i].PrivKey = secp256k1.GenPrivKeySecp256k1(privkeySeed) accs[i].PubKey = accs[i].PrivKey.PubKey() accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address()) } From 528f67852329f2327b7831b3bff96c0b96b89785 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Fri, 23 Aug 2019 09:21:37 -0400 Subject: [PATCH 31/70] Update bank aliases --- x/bank/alias.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x/bank/alias.go b/x/bank/alias.go index b4885a675837..bcd873e4a261 100644 --- a/x/bank/alias.go +++ b/x/bank/alias.go @@ -29,6 +29,8 @@ var ( NewBaseKeeper = keeper.NewBaseKeeper NewInput = types.NewInput NewOutput = types.NewOutput + NewMsgSend = types.NewMsgSend + NewMsgMultiSend = types.NewMsgMultiSend ParamKeyTable = types.ParamKeyTable // variable aliases From cebb7e7f724fc47072f96704155fa666350afe65 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Fri, 23 Aug 2019 09:25:17 -0400 Subject: [PATCH 32/70] Update inter-block cache APIs --- types/cache.go | 23 +++++++++++++---------- types/cache_test.go | 6 +++--- types/context.go | 4 ++-- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/types/cache.go b/types/cache.go index 93a7161c564c..dbe52fd61e8e 100644 --- a/types/cache.go +++ b/types/cache.go @@ -31,7 +31,7 @@ type ( // persistent between blocks. KVStoreCacheManager struct { cacheSize uint - caches map[StoreKey]*KVStoreCache + caches map[string]*KVStoreCache } ) @@ -50,24 +50,27 @@ func NewKVStoreCache(store KVStore, size uint) *KVStoreCache { func NewKVStoreCacheManager(size uint) *KVStoreCacheManager { return &KVStoreCacheManager{ cacheSize: size, - caches: make(map[StoreKey]*KVStoreCache), + caches: make(map[string]*KVStoreCache), } } -// GetOrSetKVStoreCache attempts to get a CacheWrap store from the KVStoreCacheManager. -// If the CacheWrap does not exist in the mapping, it is added. Each CacheWrap -// store contains a persistent cache through the StoreCache. -func (cmgr *KVStoreCacheManager) GetOrSetKVStoreCache(key StoreKey, store KVStore) KVStore { - if cmgr.caches[key] == nil { - cmgr.caches[key] = NewKVStoreCache(store, cmgr.cacheSize) +// GetKVStoreCache returns a KVStore from the KVStoreCacheManager which is +// deceratored with a persistent inter-block cache particular for that store's +// StoreKey. If the KVStore does not exist in the KVStoreCacheManager, it is +// added. Otherwise, the KVStore is updated to the provided parameter. +func (cmgr *KVStoreCacheManager) GetKVStoreCache(key StoreKey, store KVStore) KVStore { + if cmgr.caches[key.Name()] == nil { + cmgr.caches[key.Name()] = NewKVStoreCache(store, cmgr.cacheSize) + } else { + cmgr.caches[key.Name()].KVStore = store } - return cmgr.caches[key] + return cmgr.caches[key.Name()].KVStore } // Reset resets in the internal caches. func (cmgr *KVStoreCacheManager) Reset() { - cmgr.caches = make(map[StoreKey]*KVStoreCache) + cmgr.caches = make(map[string]*KVStoreCache) } // Get retrieves a value by key. It will first look in the write-through cache. diff --git a/types/cache_test.go b/types/cache_test.go index d84e7636a387..b11137fe85ca 100644 --- a/types/cache_test.go +++ b/types/cache_test.go @@ -18,10 +18,10 @@ func TestGetOrSetStoreCache(t *testing.T) { sKey := types.NewKVStoreKey("test") store := iavlstore.UnsafeNewStore(iavl.NewMutableTree(db, 100), 10, 10) - store2 := mngr.GetOrSetKVStoreCache(sKey, store) + store2 := mngr.GetKVStoreCache(sKey, store) require.NotNil(t, store2) - require.Equal(t, store2, mngr.GetOrSetKVStoreCache(sKey, store)) + require.Equal(t, store2, mngr.GetKVStoreCache(sKey, store)) } func TestStoreCache(t *testing.T) { @@ -30,7 +30,7 @@ func TestStoreCache(t *testing.T) { sKey := types.NewKVStoreKey("test") store := iavlstore.UnsafeNewStore(iavl.NewMutableTree(db, 100), 10, 10) - kvStore := mngr.GetOrSetKVStoreCache(sKey, store) + kvStore := mngr.GetKVStoreCache(sKey, store) for i := uint(0); i < types.DefaultPersistentKVStoreCacheSize*2; i++ { key := []byte(fmt.Sprintf("key_%d", i)) diff --git a/types/context.go b/types/context.go index cc4c6a903982..4e8bd9b36341 100644 --- a/types/context.go +++ b/types/context.go @@ -210,7 +210,7 @@ func (c Context) KVStore(key StoreKey) KVStore { kvStore := c.MultiStore().GetKVStore(key) if c.interBlockCache != nil { // wrap the KVStore in an inter-block write-through cache - kvStore = c.interBlockCache.GetOrSetKVStoreCache(key, kvStore) + kvStore = c.interBlockCache.GetKVStoreCache(key, kvStore) } return gaskv.NewStore(kvStore, c.GasMeter(), stypes.KVGasConfig()) @@ -221,7 +221,7 @@ func (c Context) TransientStore(key StoreKey) KVStore { kvStore := c.MultiStore().GetKVStore(key) if c.interBlockCache != nil { // wrap the KVStore in an inter-block write-through cache - kvStore = c.interBlockCache.GetOrSetKVStoreCache(key, kvStore) + kvStore = c.interBlockCache.GetKVStoreCache(key, kvStore) } return gaskv.NewStore(kvStore, c.GasMeter(), stypes.TransientGasConfig()) From a635ca52621a0a1051f870cd4d0bb925ea6e517e Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Fri, 23 Aug 2019 09:36:11 -0400 Subject: [PATCH 33/70] Don't return KVStore --- types/cache.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/types/cache.go b/types/cache.go index dbe52fd61e8e..0376e7d9597e 100644 --- a/types/cache.go +++ b/types/cache.go @@ -18,9 +18,10 @@ type ( // KVStoreCache defines a cache that is meant to be used in a persistent // (inter-block) fashion and in which it wraps an underlying KVStore. Reads // first hit the ARC (Adaptive Replacement Cache). During a cache miss, the - // read is delegated to the underlying KVStore. Deletes and writes always - // happen to both the cache and the KVStore in a write-through manner. Caching - // performed in the KVStore and below is completely irrelevant to this layer. + // read is delegated to the underlying KVStore and cached. Deletes and writes + // always happen to both the cache and the KVStore in a write-through manner. + // Caching performed in the KVStore and below is completely irrelevant to this + // layer. KVStoreCache struct { KVStore cache *lru.ARCCache @@ -65,7 +66,7 @@ func (cmgr *KVStoreCacheManager) GetKVStoreCache(key StoreKey, store KVStore) KV cmgr.caches[key.Name()].KVStore = store } - return cmgr.caches[key.Name()].KVStore + return cmgr.caches[key.Name()] } // Reset resets in the internal caches. From 4ee169b1ba215522a673777e0a755ed2f2ee331b Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 26 Aug 2019 16:27:15 -0400 Subject: [PATCH 34/70] Remove inter-block cache from Context --- store/types/store.go | 14 ++++++++++ types/context.go | 52 ++++++++++------------------------- types/store.go | 19 +++++++------ x/params/subspace/subspace.go | 2 ++ 4 files changed, 41 insertions(+), 46 deletions(-) diff --git a/store/types/store.go b/store/types/store.go index 021cd36cbbae..b1a08495e9e0 100644 --- a/store/types/store.go +++ b/store/types/store.go @@ -151,6 +151,10 @@ type CommitMultiStore interface { // must be idempotent (return the same commit id). Otherwise the behavior is // undefined. LoadVersion(ver int64) error + + // Set an inter-block (persistent) cache that maintains a mapping from + // StoreKeys to CommitKVStores. + SetInterBlockCache(MultiStorePersistentCache) } //---------subsp------------------------------- @@ -328,3 +332,13 @@ type KVPair cmn.KVPair // TraceContext contains TraceKVStore context data. It will be written with // every trace operation. type TraceContext map[string]interface{} + +// MultiStorePersistentCache defines an interface which provides inter-block +// (persistent) caching capabilities for multiple CommitKVStores based on StoreKeys. +type MultiStorePersistentCache interface { + // Wrap and return the provided CommitKVStore with an inter-block (persistent) + // cache. + GetStoreCache(key StoreKey, store CommitKVStore) CommitKVStore + // Reset the entire set of internal caches. + Reset() +} diff --git a/types/context.go b/types/context.go index 4e8bd9b36341..9fe8f2b67437 100644 --- a/types/context.go +++ b/types/context.go @@ -21,20 +21,19 @@ but please do not over-use it. We try to keep all data structured and standard additions here would be better just to add to the Context struct */ type Context struct { - ctx context.Context - ms MultiStore - interBlockCache *KVStoreCacheManager - header abci.Header - chainID string - txBytes []byte - logger log.Logger - voteInfo []abci.VoteInfo - gasMeter GasMeter - blockGasMeter GasMeter - checkTx bool - minGasPrice DecCoins - consParams *abci.ConsensusParams - eventManager *EventManager + ctx context.Context + ms MultiStore + header abci.Header + chainID string + txBytes []byte + logger log.Logger + voteInfo []abci.VoteInfo + gasMeter GasMeter + blockGasMeter GasMeter + checkTx bool + minGasPrice DecCoins + consParams *abci.ConsensusParams + eventManager *EventManager } // Proposed rename, not done to avoid API breakage @@ -92,15 +91,6 @@ func (c Context) WithMultiStore(ms MultiStore) Context { return c } -// WithInterBlockCache returns the Context with an inter-block write-through -// cache. -// -// NOTE: This cache is persistent and should only be set on the DeliverTx state. -func (c Context) WithInterBlockCache(cacheMngr *KVStoreCacheManager) Context { - c.interBlockCache = cacheMngr - return c -} - func (c Context) WithBlockHeader(header abci.Header) Context { // https://github.com/gogo/protobuf/issues/519 header.Time = header.Time.UTC() @@ -207,24 +197,12 @@ func (c Context) Value(key interface{}) interface{} { // KVStore fetches a KVStore from the MultiStore. func (c Context) KVStore(key StoreKey) KVStore { - kvStore := c.MultiStore().GetKVStore(key) - if c.interBlockCache != nil { - // wrap the KVStore in an inter-block write-through cache - kvStore = c.interBlockCache.GetKVStoreCache(key, kvStore) - } - - return gaskv.NewStore(kvStore, c.GasMeter(), stypes.KVGasConfig()) + return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.KVGasConfig()) } // TransientStore fetches a TransientStore from the MultiStore. func (c Context) TransientStore(key StoreKey) KVStore { - kvStore := c.MultiStore().GetKVStore(key) - if c.interBlockCache != nil { - // wrap the KVStore in an inter-block write-through cache - kvStore = c.interBlockCache.GetKVStoreCache(key, kvStore) - } - - return gaskv.NewStore(kvStore, c.GasMeter(), stypes.TransientGasConfig()) + return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.TransientGasConfig()) } // CacheContext returns a new Context with the multi-store cached and a new diff --git a/types/store.go b/types/store.go index a8772117e0bb..c34b6d437d09 100644 --- a/types/store.go +++ b/types/store.go @@ -14,15 +14,16 @@ type ( // nolint - reexport type ( - Store = types.Store - Committer = types.Committer - CommitStore = types.CommitStore - Queryable = types.Queryable - MultiStore = types.MultiStore - CacheMultiStore = types.CacheMultiStore - CommitMultiStore = types.CommitMultiStore - KVStore = types.KVStore - Iterator = types.Iterator + Store = types.Store + Committer = types.Committer + CommitStore = types.CommitStore + Queryable = types.Queryable + MultiStore = types.MultiStore + CacheMultiStore = types.CacheMultiStore + CommitMultiStore = types.CommitMultiStore + MultiStorePersistentCache = types.MultiStorePersistentCache + KVStore = types.KVStore + Iterator = types.Iterator ) // StoreDecoderRegistry defines each of the modules store decoders. Used for ImportExport diff --git a/x/params/subspace/subspace.go b/x/params/subspace/subspace.go index 457c0133345d..91740b8f6702 100644 --- a/x/params/subspace/subspace.go +++ b/x/params/subspace/subspace.go @@ -195,6 +195,8 @@ func (s Subspace) Update(ctx sdk.Context, key []byte, param []byte) error { } s.Set(ctx, key, dest) + + // TODO: Remove; seems redundant as Set already does this. tStore := s.transientStore(ctx) tStore.Set(key, []byte{}) From a6961c09af7eaee51bd01d67f9bdc2d85e411da8 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 26 Aug 2019 16:28:11 -0400 Subject: [PATCH 35/70] Cleanup IAVL store + return CommitKVStore instead of CommitStore --- store/iavl/store.go | 67 +++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/store/iavl/store.go b/store/iavl/store.go index 01eed572990b..4a9f0957fec9 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -22,8 +22,34 @@ const ( defaultIAVLCacheSize = 10000 ) -// LoadStore loads the iavl store -func LoadStore(db dbm.DB, id types.CommitID, pruning types.PruningOptions, lazyLoading bool) (types.CommitStore, error) { +var ( + _ types.KVStore = (*Store)(nil) + _ types.CommitStore = (*Store)(nil) + _ types.CommitKVStore = (*Store)(nil) + _ types.Queryable = (*Store)(nil) +) + +// Store Implements types.KVStore and CommitKVStore. +type Store struct { + tree Tree + + // How many old versions we hold onto. + // A value of 0 means keep no recent states. + numRecent int64 + + // This is the distance between state-sync waypoint states to be stored. + // See https://github.com/tendermint/tendermint/issues/828 + // A value of 1 means store every state. + // A value of 0 means store no waypoints. (node cannot assist in state-sync) + // By default this value should be set the same across all nodes, + // so that nodes can know the waypoints their peers store. + storeEvery int64 +} + +// LoadStore returns an IAVL Store as a CommitKVStore. Internally it will load the +// store's version (id) from the provided DB. An error is returned if the version +// fails to load. +func LoadStore(db dbm.DB, id types.CommitID, pruning types.PruningOptions, lazyLoading bool) (types.CommitKVStore, error) { tree := iavl.NewMutableTree(db, defaultIAVLCacheSize) var err error @@ -43,38 +69,15 @@ func LoadStore(db dbm.DB, id types.CommitID, pruning types.PruningOptions, lazyL return iavl, nil } -//---------------------------------------- - -var _ types.KVStore = (*Store)(nil) -var _ types.CommitStore = (*Store)(nil) -var _ types.Queryable = (*Store)(nil) - -// Store Implements types.KVStore and CommitStore. -type Store struct { - tree Tree - - // How many old versions we hold onto. - // A value of 0 means keep no recent states. - numRecent int64 - - // This is the distance between state-sync waypoint states to be stored. - // See https://github.com/tendermint/tendermint/issues/828 - // A value of 1 means store every state. - // A value of 0 means store no waypoints. (node cannot assist in state-sync) - // By default this value should be set the same across all nodes, - // so that nodes can know the waypoints their peers store. - storeEvery int64 -} - -// CONTRACT: tree should be fully loaded. -// nolint: unparam +// UnsafeNewStore returns a reference to a new IAVL Store. +// +// CONTRACT: The IAVL tree should be fully loaded. func UnsafeNewStore(tree *iavl.MutableTree, numRecent int64, storeEvery int64) *Store { - st := &Store{ + return &Store{ tree: tree, numRecent: numRecent, storeEvery: storeEvery, } - return st } // GetImmutable returns a reference to a new store backed by an immutable IAVL @@ -167,9 +170,9 @@ func (st *Store) Set(key, value []byte) { } // Implements types.KVStore. -func (st *Store) Get(key []byte) (value []byte) { - _, v := st.tree.Get(key) - return v +func (st *Store) Get(key []byte) []byte { + _, value := st.tree.Get(key) + return value } // Implements types.KVStore. From d49ffa79215c6700b7708b0da95f183637a4e645 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 26 Aug 2019 16:33:21 -0400 Subject: [PATCH 36/70] Update root multi store --- store/rootmulti/store.go | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 87939cd2c3fe..31a34c59eb3d 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -32,12 +32,14 @@ type Store struct { lastCommitID types.CommitID pruningOpts types.PruningOptions storesParams map[types.StoreKey]storeParams - stores map[types.StoreKey]types.CommitStore + stores map[types.StoreKey]types.CommitKVStore keysByName map[string]types.StoreKey lazyLoading bool traceWriter io.Writer traceContext types.TraceContext + + interBlockCache types.MultiStorePersistentCache } var _ types.CommitMultiStore = (*Store)(nil) @@ -48,7 +50,7 @@ func NewStore(db dbm.DB) *Store { return &Store{ db: db, storesParams: make(map[types.StoreKey]storeParams), - stores: make(map[types.StoreKey]types.CommitStore), + stores: make(map[types.StoreKey]types.CommitKVStore), keysByName: make(map[string]types.StoreKey), } } @@ -141,7 +143,7 @@ func (rs *Store) loadVersion(ver int64, upgrades *types.StoreUpgrades) error { } // load each Store (note this doesn't panic on unmounted keys now) - var newStores = make(map[types.StoreKey]types.CommitStore) + var newStores = make(map[types.StoreKey]types.CommitKVStore) for key, storeParams := range rs.storesParams { // Load it @@ -220,6 +222,13 @@ func moveKVStoreData(oldDB types.KVStore, newDB types.KVStore) error { return deleteKVStore(oldDB) } +// SetInterBlockCache sets the Store's internal inter-block (persistent) cache. +// When this is defined, all CommitKVStores will be wrapped with their respective +// inter-block cache. +func (rs *Store) SetInterBlockCache(c types.MultiStorePersistentCache) { + rs.interBlockCache = c +} + // SetTracer sets the tracer for the MultiStore that the underlying // stores will utilize to trace operations. A MultiStore is returned. func (rs *Store) SetTracer(w io.Writer) types.MultiStore { @@ -443,7 +452,7 @@ func parsePath(path string) (storeName string, subpath string, err errors.Error) //---------------------------------------- // Note: why do we use key and params.key in different places. Seems like there should be only one key used. -func (rs *Store) loadCommitStoreFromParams(key types.StoreKey, id types.CommitID, params storeParams) (store types.CommitStore, err error) { +func (rs *Store) loadCommitStoreFromParams(key types.StoreKey, id types.CommitID, params storeParams) (types.CommitKVStore, error) { var db dbm.DB if params.db != nil { @@ -458,7 +467,19 @@ func (rs *Store) loadCommitStoreFromParams(key types.StoreKey, id types.CommitID panic("recursive MultiStores not yet supported") case types.StoreTypeIAVL: - return iavl.LoadStore(db, id, rs.pruningOpts, rs.lazyLoading) + store, err := iavl.LoadStore(db, id, rs.pruningOpts, rs.lazyLoading) + if err != nil { + return nil, err + } + + if rs.interBlockCache != nil { + // Wrap and get a CommitKVStore with inter-block caching. Note, this should + // only wrap the primary CommitKVStore, not any store that is already + // cache-wrapped as that will create unexpected behavior. + store = rs.interBlockCache.GetStoreCache(key, store) + } + + return store, err case types.StoreTypeDB: return commitDBStoreAdapter{dbadapter.Store{db}}, nil @@ -466,7 +487,7 @@ func (rs *Store) loadCommitStoreFromParams(key types.StoreKey, id types.CommitID case types.StoreTypeTransient: _, ok := key.(*types.TransientStoreKey) if !ok { - return store, fmt.Errorf("invalid StoreKey for StoreTypeTransient: %s", key.String()) + return nil, fmt.Errorf("invalid StoreKey for StoreTypeTransient: %s", key.String()) } return transient.NewStore(), nil @@ -574,7 +595,7 @@ func setLatestVersion(batch dbm.Batch, version int64) { } // Commits each store and returns a new commitInfo. -func commitStores(version int64, storeMap map[types.StoreKey]types.CommitStore) commitInfo { +func commitStores(version int64, storeMap map[types.StoreKey]types.CommitKVStore) commitInfo { storeInfos := make([]storeInfo, 0, len(storeMap)) for key, store := range storeMap { From 0f5d816a80c0d06230f712131f7bfe4f6c10a188 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 26 Aug 2019 16:34:06 -0400 Subject: [PATCH 37/70] Remove context call in helpers --- baseapp/helpers.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/baseapp/helpers.go b/baseapp/helpers.go index fa71cf45e5f8..3a1d3abf2ffa 100644 --- a/baseapp/helpers.go +++ b/baseapp/helpers.go @@ -25,14 +25,12 @@ func (app *BaseApp) Deliver(tx sdk.Tx) (result sdk.Result) { return app.runTx(runTxModeDeliver, nil, tx) } -// Context with current {check, deliver}State of the app -// used by tests +// Context with current {check, deliver}State of the app used by tests. func (app *BaseApp) NewContext(isCheckTx bool, header abci.Header) sdk.Context { if isCheckTx { return sdk.NewContext(app.checkState.ms, header, true, app.logger). WithMinGasPrices(app.minGasPrices) } - return sdk.NewContext(app.deliverState.ms, header, false, app.logger). - WithInterBlockCache(app.interBlockCache) + return sdk.NewContext(app.deliverState.ms, header, false, app.logger) } From 00d887505ca7db82bef6dfaae6f344e280ab7cd4 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 26 Aug 2019 16:44:17 -0400 Subject: [PATCH 38/70] Update BaseApp --- baseapp/baseapp.go | 21 ++++++++++++--------- baseapp/options.go | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 140a22930817..5715be03f55d 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -84,7 +84,7 @@ type BaseApp struct { deliverState *state // for DeliverTx // an inter-block write-through cache provided to the context during deliverState - interBlockCache *sdk.KVStoreCacheManager + interBlockCache sdk.MultiStorePersistentCache // absent validators from begin block voteInfos []abci.VoteInfo @@ -131,6 +131,10 @@ func NewBaseApp( option(app) } + if app.interBlockCache != nil { + app.cms.SetInterBlockCache(app.interBlockCache) + } + return app } @@ -341,7 +345,7 @@ func (app *BaseApp) setHaltHeight(height uint64) { app.haltHeight = height } -func (app *BaseApp) setInterBlockCache(cache *sdk.KVStoreCacheManager) { +func (app *BaseApp) setInterBlockCache(cache sdk.MultiStorePersistentCache) { app.interBlockCache = cache } @@ -378,15 +382,13 @@ func (app *BaseApp) setCheckState(header abci.Header) { // setDeliverState sets the BaseApp's deliverState with a cache-wrapped multi-store // (i.e. a CacheMultiStore) and a new Context with the cache-wrapped multi-store, -// and provided header. If an inter-block cache is set on the BaseApp, it will -// be provided to the context such that whenever a KVStore is retrieived, it'll -// be wrapped with a persistent write-through cache. It is set on InitChain and -// BeginBlock and set to nil on Commit. +// and provided header. It is set on InitChain and BeginBlock and set to nil on +// Commit. func (app *BaseApp) setDeliverState(header abci.Header) { ms := app.cms.CacheMultiStore() app.deliverState = &state{ ms: ms, - ctx: sdk.NewContext(ms, header, false, app.logger).WithInterBlockCache(app.interBlockCache), + ctx: sdk.NewContext(ms, header, false, app.logger), } } @@ -598,8 +600,9 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk msCache.Write() } - // Create a new context based off of the existing context with a cache wrapped - // multi-store in case message processing fails. + // Create a new Context based off of the existing Context with a cache-wrapped + // MultiStore in case message processing fails. At this point, the MultiStore + // is doubly cached-wrapped. runMsgCtx, msCache := app.cacheTxContext(ctx, txBytes) result = app.runMsgs(runMsgCtx, msgs, mode) result.GasWanted = gasWanted diff --git a/baseapp/options.go b/baseapp/options.go index 026156f5c83c..db94bac333db 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -36,7 +36,7 @@ func SetHaltHeight(height uint64) func(*BaseApp) { // SetInterBlockCache provides a BaseApp option function that sets the // inter-block cache. -func SetInterBlockCache(cache *sdk.KVStoreCacheManager) func(*BaseApp) { +func SetInterBlockCache(cache sdk.MultiStorePersistentCache) func(*BaseApp) { return func(app *BaseApp) { app.setInterBlockCache(cache) } } From 5ba59103f5ef0c444e800a2731f70e432ad11c71 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 26 Aug 2019 16:45:03 -0400 Subject: [PATCH 39/70] Small godoc update --- baseapp/abci.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index 11a6a9e3b41c..a50ea96975ca 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -214,7 +214,9 @@ func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) (res abci.ResponseDeliv func (app *BaseApp) Commit() (res abci.ResponseCommit) { header := app.deliverState.ctx.BlockHeader() - // write the Deliver state and commit the MultiStore + // Write the DeliverTx state which is cache-wrapped and commit the MultiStore. + // The write to the DeliverTx state writes all state transitions to the root + // MultiStore (app.cms) so when Commit() is called is persists those values. app.deliverState.ms.Write() commitID := app.cms.Commit() app.logger.Debug("Commit synced", "commit", fmt.Sprintf("%X", commitID)) From 8b114bc52804adda6e572c2c32621459841f7378 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 26 Aug 2019 19:24:49 -0400 Subject: [PATCH 40/70] Refactor inter-block caching to use CommitKVStore --- types/cache.go | 102 ++++++++++++++++++++++---------------------- types/cache_test.go | 14 +++--- 2 files changed, 57 insertions(+), 59 deletions(-) diff --git a/types/cache.go b/types/cache.go index 0376e7d9597e..fee96c8d2119 100644 --- a/types/cache.go +++ b/types/cache.go @@ -7,100 +7,98 @@ import ( ) var ( - _ KVStore = (*KVStoreCache)(nil) + _ CommitKVStore = (*CommitKVStoreCache)(nil) + _ MultiStorePersistentCache = (*CommitKVStoreCacheManager)(nil) - // DefaultPersistentKVStoreCacheSize defines the persistent ARC cache size for - // each KVStore. - DefaultPersistentKVStoreCacheSize uint = 1000 + // DefaultCommitKVStoreCacheSize defines the persistent ARC cache size for a + // CommitKVStoreCache. + DefaultCommitKVStoreCacheSize uint = 1000 ) type ( - // KVStoreCache defines a cache that is meant to be used in a persistent - // (inter-block) fashion and in which it wraps an underlying KVStore. Reads - // first hit the ARC (Adaptive Replacement Cache). During a cache miss, the - // read is delegated to the underlying KVStore and cached. Deletes and writes - // always happen to both the cache and the KVStore in a write-through manner. - // Caching performed in the KVStore and below is completely irrelevant to this - // layer. - KVStoreCache struct { - KVStore + // CommitKVStoreCache implements an inter-block (persistent) cache that wraps a + // CommitKVStore. Reads first hit the internal ARC (Adaptive Replacement Cache). + // During a cache miss, the read is delegated to the underlying CommitKVStore + // and cached. Deletes and writes always happen to both the cache and the + // CommitKVStore in a write-through manner. Caching performed in the + // CommitKVStore and below is completely irrelevant to this layer. + CommitKVStoreCache struct { + CommitKVStore cache *lru.ARCCache } - // KVStoreCacheManager defines a manager that stores a mapping of StoreKeys - // to KVStoreCache references. Each KVStoreCache reference is meant to be - // persistent between blocks. - KVStoreCacheManager struct { + // CommitKVStoreCacheManager maintains a mapping from a StoreKey to a + // CommitKVStoreCache. Each CommitKVStore, per StoreKey, is meant to be used + // in an inter-block (persistent) manner and typically provided by a + // CommitMultiStore. + CommitKVStoreCacheManager struct { cacheSize uint - caches map[string]*KVStoreCache + caches map[string]CommitKVStore } ) -func NewKVStoreCache(store KVStore, size uint) *KVStoreCache { +func NewCommitKVStoreCache(store CommitKVStore, size uint) *CommitKVStoreCache { cache, err := lru.NewARC(int(size)) if err != nil { panic(fmt.Errorf("failed to create KVStore cache: %s", err)) } - return &KVStoreCache{ - KVStore: store, - cache: cache, + return &CommitKVStoreCache{ + CommitKVStore: store, + cache: cache, } } -func NewKVStoreCacheManager(size uint) *KVStoreCacheManager { - return &KVStoreCacheManager{ +func NewCommitKVStoreCacheManager(size uint) *CommitKVStoreCacheManager { + return &CommitKVStoreCacheManager{ cacheSize: size, - caches: make(map[string]*KVStoreCache), + caches: make(map[string]CommitKVStore), } } -// GetKVStoreCache returns a KVStore from the KVStoreCacheManager which is -// deceratored with a persistent inter-block cache particular for that store's -// StoreKey. If the KVStore does not exist in the KVStoreCacheManager, it is -// added. Otherwise, the KVStore is updated to the provided parameter. -func (cmgr *KVStoreCacheManager) GetKVStoreCache(key StoreKey, store KVStore) KVStore { +// GetStoreCache returns a Cache from the CommitStoreCacheManager for a given +// StoreKey. If no Cache exists for the StoreKey, then one is created and set. +// The returned Cache is meant to be used in a persistent manner. +func (cmgr *CommitKVStoreCacheManager) GetStoreCache(key StoreKey, store CommitKVStore) CommitKVStore { if cmgr.caches[key.Name()] == nil { - cmgr.caches[key.Name()] = NewKVStoreCache(store, cmgr.cacheSize) - } else { - cmgr.caches[key.Name()].KVStore = store + cmgr.caches[key.Name()] = NewCommitKVStoreCache(store, cmgr.cacheSize) } return cmgr.caches[key.Name()] } // Reset resets in the internal caches. -func (cmgr *KVStoreCacheManager) Reset() { - cmgr.caches = make(map[string]*KVStoreCache) +func (cmgr *CommitKVStoreCacheManager) Reset() { + cmgr.caches = make(map[string]CommitKVStore) } // Get retrieves a value by key. It will first look in the write-through cache. -// If the value doesn't exist in the write-through cache, the Get call is -// delegated to the underlying KVStore. -func (kvsc *KVStoreCache) Get(key []byte) []byte { - val, ok := kvsc.cache.Get(string(key)) +// If the value doesn't exist in the write-through cache, the query is delegated +// to the underlying CommitKVStore. +func (ckv *CommitKVStoreCache) Get(key []byte) []byte { + valueI, ok := ckv.cache.Get(string(key)) if ok { // cache hit - return val.([]byte) + return valueI.([]byte) } - // cache miss; add to cache - bz := kvsc.KVStore.Get(key) - kvsc.cache.Add(string(key), bz) + // cache miss; write to cache + value := ckv.CommitKVStore.Get(key) + ckv.cache.Add(string(key), value) - return bz + return value } // Set inserts a key/value pair into both the write-through cache and the -// underlying KVStore. -func (kvsc *KVStoreCache) Set(key, value []byte) { - kvsc.cache.Add(string(key), value) - kvsc.KVStore.Set(key, value) +// underlying CommitKVStore. +func (ckv *CommitKVStoreCache) Set(key, value []byte) { + ckv.cache.Add(string(key), value) + ckv.CommitKVStore.Set(key, value) } // Delete removes a key/value pair from both the write-through cache and the -// underlying KVStore. -func (kvsc *KVStoreCache) Delete(key []byte) { - kvsc.cache.Remove(string(key)) - kvsc.KVStore.Delete(key) +// underlying CommitKVStore. +func (ckv *CommitKVStoreCache) Delete(key []byte) { + ckv.cache.Remove(string(key)) + ckv.CommitKVStore.Delete(key) } diff --git a/types/cache_test.go b/types/cache_test.go index b11137fe85ca..b572a40ff8ff 100644 --- a/types/cache_test.go +++ b/types/cache_test.go @@ -14,25 +14,25 @@ import ( func TestGetOrSetStoreCache(t *testing.T) { db := dbm.NewMemDB() - mngr := types.NewKVStoreCacheManager(types.DefaultPersistentKVStoreCacheSize) + mngr := types.NewCommitKVStoreCacheManager(types.DefaultCommitKVStoreCacheSize) sKey := types.NewKVStoreKey("test") store := iavlstore.UnsafeNewStore(iavl.NewMutableTree(db, 100), 10, 10) - store2 := mngr.GetKVStoreCache(sKey, store) + store2 := mngr.GetStoreCache(sKey, store) require.NotNil(t, store2) - require.Equal(t, store2, mngr.GetKVStoreCache(sKey, store)) + require.Equal(t, store2, mngr.GetStoreCache(sKey, store)) } func TestStoreCache(t *testing.T) { db := dbm.NewMemDB() - mngr := types.NewKVStoreCacheManager(types.DefaultPersistentKVStoreCacheSize) + mngr := types.NewCommitKVStoreCacheManager(types.DefaultCommitKVStoreCacheSize) sKey := types.NewKVStoreKey("test") store := iavlstore.UnsafeNewStore(iavl.NewMutableTree(db, 100), 10, 10) - kvStore := mngr.GetKVStoreCache(sKey, store) + kvStore := mngr.GetStoreCache(sKey, store) - for i := uint(0); i < types.DefaultPersistentKVStoreCacheSize*2; i++ { + for i := uint(0); i < types.DefaultCommitKVStoreCacheSize*2; i++ { key := []byte(fmt.Sprintf("key_%d", i)) value := []byte(fmt.Sprintf("value_%d", i)) @@ -45,7 +45,7 @@ func TestStoreCache(t *testing.T) { require.Equal(t, res, value) } - for i := uint(0); i < types.DefaultPersistentKVStoreCacheSize*2; i++ { + for i := uint(0); i < types.DefaultCommitKVStoreCacheSize*2; i++ { key := []byte(fmt.Sprintf("key_%d", i)) kvStore.Delete(key) From f6fd73d2bdddef1ff875de1feede24dcfddd248b Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 26 Aug 2019 19:25:00 -0400 Subject: [PATCH 41/70] cleanup --- store/types/store.go | 1 + 1 file changed, 1 insertion(+) diff --git a/store/types/store.go b/store/types/store.go index b1a08495e9e0..8dbc0e31074b 100644 --- a/store/types/store.go +++ b/store/types/store.go @@ -339,6 +339,7 @@ type MultiStorePersistentCache interface { // Wrap and return the provided CommitKVStore with an inter-block (persistent) // cache. GetStoreCache(key StoreKey, store CommitKVStore) CommitKVStore + // Reset the entire set of internal caches. Reset() } From 9723bab0696b1039073e820ef84599319856157e Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 26 Aug 2019 19:28:32 -0400 Subject: [PATCH 42/70] Fix build --- x/mock/app.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/x/mock/app.go b/x/mock/app.go index 3f531d8c7064..9884c4da3018 100644 --- a/x/mock/app.go +++ b/x/mock/app.go @@ -206,9 +206,8 @@ func SetGenesis(app *App, accs []authexported.Account) { app.Commit() } -// GenTx generates a signed mock transaction. -func GenTx(msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKey) auth.StdTx { - // Make the transaction free +func GenTxWithChainID(cid string, msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKey) auth.StdTx { + // make the transaction free fee := auth.StdFee{ Amount: sdk.NewCoins(sdk.NewInt64Coin("foocoin", 0)), Gas: 100000, @@ -218,7 +217,7 @@ func GenTx(msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKe memo := "testmemotestmemo" for i, p := range priv { - sig, err := p.Sign(auth.StdSignBytes(chainID, accnums[i], seq[i], fee, msgs, memo)) + sig, err := p.Sign(auth.StdSignBytes(cid, accnums[i], seq[i], fee, msgs, memo)) if err != nil { panic(err) } @@ -232,6 +231,11 @@ func GenTx(msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKe return auth.NewStdTx(msgs, fee, sigs, memo) } +// GenTx generates a signed mock transaction. +func GenTx(msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKey) auth.StdTx { + return GenTxWithChainID(chainID, msgs, accnums, seq, priv...) +} + // GeneratePrivKeys generates a total n secp256k1 private keys. func GeneratePrivKeys(n int) (keys []crypto.PrivKey) { // TODO: Randomize this between ed25519 and secp256k1 From 8561ef4128c17a949f096a6a1bf520269c0da421 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 27 Aug 2019 11:12:00 -0400 Subject: [PATCH 43/70] Move cache to store package --- {types => store/cache}/cache.go | 26 +++++++++++++++++--------- {types => store/cache}/cache_test.go | 17 +++++++++-------- 2 files changed, 26 insertions(+), 17 deletions(-) rename {types => store/cache}/cache.go (77%) rename {types => store/cache}/cache_test.go (76%) diff --git a/types/cache.go b/store/cache/cache.go similarity index 77% rename from types/cache.go rename to store/cache/cache.go index fee96c8d2119..fe32fa1069fd 100644 --- a/types/cache.go +++ b/store/cache/cache.go @@ -1,14 +1,17 @@ -package types +package cache import ( "fmt" + "github.com/cosmos/cosmos-sdk/store/cachekv" + "github.com/cosmos/cosmos-sdk/store/types" + lru "github.com/hashicorp/golang-lru" ) var ( - _ CommitKVStore = (*CommitKVStoreCache)(nil) - _ MultiStorePersistentCache = (*CommitKVStoreCacheManager)(nil) + _ types.CommitKVStore = (*CommitKVStoreCache)(nil) + _ types.MultiStorePersistentCache = (*CommitKVStoreCacheManager)(nil) // DefaultCommitKVStoreCacheSize defines the persistent ARC cache size for a // CommitKVStoreCache. @@ -23,7 +26,7 @@ type ( // CommitKVStore in a write-through manner. Caching performed in the // CommitKVStore and below is completely irrelevant to this layer. CommitKVStoreCache struct { - CommitKVStore + types.CommitKVStore cache *lru.ARCCache } @@ -33,11 +36,11 @@ type ( // CommitMultiStore. CommitKVStoreCacheManager struct { cacheSize uint - caches map[string]CommitKVStore + caches map[string]types.CommitKVStore } ) -func NewCommitKVStoreCache(store CommitKVStore, size uint) *CommitKVStoreCache { +func NewCommitKVStoreCache(store types.CommitKVStore, size uint) *CommitKVStoreCache { cache, err := lru.NewARC(int(size)) if err != nil { panic(fmt.Errorf("failed to create KVStore cache: %s", err)) @@ -52,14 +55,14 @@ func NewCommitKVStoreCache(store CommitKVStore, size uint) *CommitKVStoreCache { func NewCommitKVStoreCacheManager(size uint) *CommitKVStoreCacheManager { return &CommitKVStoreCacheManager{ cacheSize: size, - caches: make(map[string]CommitKVStore), + caches: make(map[string]types.CommitKVStore), } } // GetStoreCache returns a Cache from the CommitStoreCacheManager for a given // StoreKey. If no Cache exists for the StoreKey, then one is created and set. // The returned Cache is meant to be used in a persistent manner. -func (cmgr *CommitKVStoreCacheManager) GetStoreCache(key StoreKey, store CommitKVStore) CommitKVStore { +func (cmgr *CommitKVStoreCacheManager) GetStoreCache(key types.StoreKey, store types.CommitKVStore) types.CommitKVStore { if cmgr.caches[key.Name()] == nil { cmgr.caches[key.Name()] = NewCommitKVStoreCache(store, cmgr.cacheSize) } @@ -69,7 +72,12 @@ func (cmgr *CommitKVStoreCacheManager) GetStoreCache(key StoreKey, store CommitK // Reset resets in the internal caches. func (cmgr *CommitKVStoreCacheManager) Reset() { - cmgr.caches = make(map[string]CommitKVStore) + cmgr.caches = make(map[string]types.CommitKVStore) +} + +// CacheWrap returns the inter-block cache as a cache-wrapped CommitKVStore. +func (ckv *CommitKVStoreCache) CacheWrap() types.CacheWrap { + return cachekv.NewStore(ckv) } // Get retrieves a value by key. It will first look in the write-through cache. diff --git a/types/cache_test.go b/store/cache/cache_test.go similarity index 76% rename from types/cache_test.go rename to store/cache/cache_test.go index b572a40ff8ff..cc830c0fad78 100644 --- a/types/cache_test.go +++ b/store/cache/cache_test.go @@ -1,20 +1,21 @@ -package types_test +package cache_test import ( "fmt" "testing" + "github.com/cosmos/cosmos-sdk/store/cache" + iavlstore "github.com/cosmos/cosmos-sdk/store/iavl" + "github.com/cosmos/cosmos-sdk/store/types" + "github.com/stretchr/testify/require" "github.com/tendermint/iavl" dbm "github.com/tendermint/tm-db" - - iavlstore "github.com/cosmos/cosmos-sdk/store/iavl" - "github.com/cosmos/cosmos-sdk/types" ) func TestGetOrSetStoreCache(t *testing.T) { db := dbm.NewMemDB() - mngr := types.NewCommitKVStoreCacheManager(types.DefaultCommitKVStoreCacheSize) + mngr := cache.NewCommitKVStoreCacheManager(cache.DefaultCommitKVStoreCacheSize) sKey := types.NewKVStoreKey("test") store := iavlstore.UnsafeNewStore(iavl.NewMutableTree(db, 100), 10, 10) @@ -26,13 +27,13 @@ func TestGetOrSetStoreCache(t *testing.T) { func TestStoreCache(t *testing.T) { db := dbm.NewMemDB() - mngr := types.NewCommitKVStoreCacheManager(types.DefaultCommitKVStoreCacheSize) + mngr := cache.NewCommitKVStoreCacheManager(cache.DefaultCommitKVStoreCacheSize) sKey := types.NewKVStoreKey("test") store := iavlstore.UnsafeNewStore(iavl.NewMutableTree(db, 100), 10, 10) kvStore := mngr.GetStoreCache(sKey, store) - for i := uint(0); i < types.DefaultCommitKVStoreCacheSize*2; i++ { + for i := uint(0); i < cache.DefaultCommitKVStoreCacheSize*2; i++ { key := []byte(fmt.Sprintf("key_%d", i)) value := []byte(fmt.Sprintf("value_%d", i)) @@ -45,7 +46,7 @@ func TestStoreCache(t *testing.T) { require.Equal(t, res, value) } - for i := uint(0); i < types.DefaultCommitKVStoreCacheSize*2; i++ { + for i := uint(0); i < cache.DefaultCommitKVStoreCacheSize*2; i++ { key := []byte(fmt.Sprintf("key_%d", i)) kvStore.Delete(key) From 2488fe535d46444ab41e747615d2bd74414dd49f Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 27 Aug 2019 11:12:28 -0400 Subject: [PATCH 44/70] Update mock --- server/mock/store.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/mock/store.go b/server/mock/store.go index 9f0882023eed..03c01c094073 100644 --- a/server/mock/store.go +++ b/server/mock/store.go @@ -95,6 +95,10 @@ func (ms multiStore) GetStoreType() sdk.StoreType { panic("not implemented") } +func (ms multiStore) SetInterBlockCache(_ sdk.MultiStorePersistentCache) { + panic("not implemented") +} + var _ sdk.KVStore = kvStore{} type kvStore struct { From 44a7443df13b12537212217c4168283f27f27f9b Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 27 Aug 2019 11:20:46 -0400 Subject: [PATCH 45/70] Create NewCommitKVStoreCacheManager alias --- simapp/sim_test.go | 5 +++-- store/store.go | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/simapp/sim_test.go b/simapp/sim_test.go index 6bc512803589..be3e68d0369c 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -15,6 +15,7 @@ import ( dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" authsimops "github.com/cosmos/cosmos-sdk/x/auth/simulation/operations" @@ -250,7 +251,7 @@ func fauxMerkleModeOpt(bapp *baseapp.BaseApp) { // interBlockCache returns a BaseApp option function that sets the persistent // inter-block write-through cache. func interBlockCache() func(*baseapp.BaseApp) { - return baseapp.SetInterBlockCache(sdk.NewKVStoreCacheManager(sdk.DefaultPersistentKVStoreCacheSize)) + return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager()) } // Profile with: @@ -342,7 +343,7 @@ func TestFullAppSimulation(t *testing.T) { os.RemoveAll(dir) }() - app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt, interBlockCache()) + app := NewSimApp(logger, db, nil, true, 0, interBlockCache()) require.Equal(t, "SimApp", app.Name()) // Run randomized simulation diff --git a/store/store.go b/store/store.go index d0deca1f0505..27a0c74165ed 100644 --- a/store/store.go +++ b/store/store.go @@ -3,6 +3,7 @@ package store import ( dbm "github.com/tendermint/tm-db" + "github.com/cosmos/cosmos-sdk/store/cache" "github.com/cosmos/cosmos-sdk/store/rootmulti" "github.com/cosmos/cosmos-sdk/store/types" ) @@ -11,6 +12,10 @@ func NewCommitMultiStore(db dbm.DB) types.CommitMultiStore { return rootmulti.NewStore(db) } +func NewCommitKVStoreCacheManager() types.MultiStorePersistentCache { + return cache.NewCommitKVStoreCacheManager(cache.DefaultCommitKVStoreCacheSize) +} + func NewPruningOptionsFromString(strategy string) (opt PruningOptions) { switch strategy { case "nothing": From a251163cc609c4f3f013e4880cc411a5a35eb0a4 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 27 Aug 2019 12:53:41 -0400 Subject: [PATCH 46/70] Fix store build --- store/rootmulti/store_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index 69fec842ee17..feff6c2761cf 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -410,7 +410,7 @@ func getExpectedCommitID(store *Store, ver int64) types.CommitID { } } -func hashStores(stores map[types.StoreKey]types.CommitStore) []byte { +func hashStores(stores map[types.StoreKey]types.CommitKVStore) []byte { m := make(map[string][]byte, len(stores)) for key, store := range stores { name := key.Name() From 80d1964405f6de892ec0a4ff8ceeaef5b3266190 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 27 Aug 2019 12:58:58 -0400 Subject: [PATCH 47/70] Update sim tests app construction --- simapp/sim_test.go | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/simapp/sim_test.go b/simapp/sim_test.go index be3e68d0369c..f29124e2edb0 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -243,14 +243,15 @@ func invariants(app *SimApp) []sdk.Invariant { return simulation.PeriodicInvariants(app.CrisisKeeper.Invariants(), flagPeriodValue, 0) } -// Pass this in as an option to use a dbStoreAdapter instead of an IAVLStore for simulation speed. +// fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of +// an IAVLStore for faster simulation speed. func fauxMerkleModeOpt(bapp *baseapp.BaseApp) { bapp.SetFauxMerkleMode() } -// interBlockCache returns a BaseApp option function that sets the persistent +// interBlockCacheOpt returns a BaseApp option function that sets the persistent // inter-block write-through cache. -func interBlockCache() func(*baseapp.BaseApp) { +func interBlockCacheOpt() func(*baseapp.BaseApp) { return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager()) } @@ -268,7 +269,7 @@ func BenchmarkFullAppSimulation(b *testing.B) { os.RemoveAll(dir) }() - app := NewSimApp(logger, db, nil, true, 0, interBlockCache()) + app := NewSimApp(logger, db, nil, true, 0, interBlockCacheOpt()) // Run randomized simulation // TODO: parameterize numbers, save for a later PR @@ -343,7 +344,7 @@ func TestFullAppSimulation(t *testing.T) { os.RemoveAll(dir) }() - app := NewSimApp(logger, db, nil, true, 0, interBlockCache()) + app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt) require.Equal(t, "SimApp", app.Name()) // Run randomized simulation @@ -407,7 +408,7 @@ func TestAppImportExport(t *testing.T) { os.RemoveAll(dir) }() - app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt, interBlockCache()) + app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt) require.Equal(t, "SimApp", app.Name()) // Run randomized simulation @@ -460,7 +461,7 @@ func TestAppImportExport(t *testing.T) { _ = os.RemoveAll(newDir) }() - newApp := NewSimApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt, interBlockCache()) + newApp := NewSimApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt) require.Equal(t, "SimApp", newApp.Name()) var genesisState GenesisState @@ -533,7 +534,7 @@ func TestAppSimulationAfterImport(t *testing.T) { os.RemoveAll(dir) }() - app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt, interBlockCache()) + app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt) require.Equal(t, "SimApp", app.Name()) // Run randomized simulation @@ -593,7 +594,7 @@ func TestAppSimulationAfterImport(t *testing.T) { _ = os.RemoveAll(newDir) }() - newApp := NewSimApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt, interBlockCache()) + newApp := NewSimApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt) require.Equal(t, "SimApp", newApp.Name()) newApp.InitChain(abci.RequestInitChain{ @@ -634,7 +635,7 @@ func TestAppStateDeterminism(t *testing.T) { logger := log.NewNopLogger() db := dbm.NewMemDB() - app := NewSimApp(logger, db, nil, true, 0, interBlockCache()) + app := NewSimApp(logger, db, nil, true, 0, interBlockCacheOpt()) fmt.Printf( "Running non-determinism simulation; seed: %d/%d (%d), attempt: %d/%d\n", @@ -670,7 +671,7 @@ func BenchmarkInvariants(b *testing.B) { os.RemoveAll(dir) }() - app := NewSimApp(logger, db, nil, true, 0, interBlockCache()) + app := NewSimApp(logger, db, nil, true, 0, interBlockCacheOpt()) // 2. Run parameterized simulation (w/o invariants) _, params, simErr := simulation.SimulateFromSeed( From fadce2b3986c1220b58487ae332302521f72a552 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 27 Aug 2019 13:07:26 -0400 Subject: [PATCH 48/70] Minor doc updates --- docs/core/baseapp.md | 80 ++++++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/docs/core/baseapp.md b/docs/core/baseapp.md index 5b2203b3f74c..7bfa2a548072 100644 --- a/docs/core/baseapp.md +++ b/docs/core/baseapp.md @@ -7,37 +7,50 @@ ## Synopsis -This document describes `baseapp`, the abstraction that implements most of the common functionalities of an SDK application. - -- [Introduction](#introduction) -- [Type Definition](#type-definition) -- [Constructor](#constructor) -- [States](#states) -- [Routing](#routing) -- [Main ABCI Messages](#abci) - - [CheckTx](#checktx) - - [DeliverTx](#delivertx) -- [RunTx(), AnteHandler and RunMsgs](<#runtx()-,antehandler-and-runmsgs()>) - - [RunTx()](<#runtx()>) - - [AnteHandler](#antehandler) - - [RunMsgs()](<#runmsgs()>) -- [Other ABCI Message](#other-abci-message) - - [InitChain](#initchain) - - [BeginBlock](#beginblock) - - [EndBlock](#endblock) - - [Commit](#commit) - - [Info](#info) - - [Query](#query) +This document describes `baseapp`, the abstraction that implements most of the common +functionalities of an SDK application. + +- [BaseApp](#baseapp) + - [Pre-requisite Reading](#pre-requisite-reading) + - [Synopsis](#synopsis) + - [Introduction](#introduction) + - [Type Definition](#type-definition) + - [Constructor](#constructor) + - [States](#states) + - [Main State](#main-state) + - [Volatile States](#volatile-states) + - [Routing](#routing) + - [Message Routing](#message-routing) + - [Query Routing](#query-routing) + - [Main ABCI Messages](#main-abci-messages) + - [CheckTx](#checktx) + - [DeliverTx](#delivertx) + - [RunTx(), AnteHandler and RunMsgs()](#runtx-antehandler-and-runmsgs) + - [RunTx()](#runtx) + - [AnteHandler](#antehandler) + - [RunMsgs()](#runmsgs) + - [Other ABCI Messages](#other-abci-messages) + - [InitChain](#initchain) + - [BeginBlock](#beginblock) + - [EndBlock](#endblock) + - [Commit](#commit) + - [Info](#info) + - [Query](#query) + - [Next](#next) ## Introduction -`baseapp` is a base class that implements the core of an SDK application, namely: +`BaseApp` is a base type that implements the core of an SDK application, namely: -- The [Application-Blockchain Interface](#abci), for the state-machine to communicate with the underlying consensus engine (e.g. Tendermint). +- The [Application-Blockchain Interface](#abci), for the state-machine to communicate with the +underlying consensus engine (e.g. Tendermint). - A [Router](#routing), to route messages and queries to the appropriate module. -- Different [states](#states), as the state-machine can have different parallel states updated based on the ABCI message received. +- Different [states](#states), as the state-machine can have different parallel states updated +based on the ABCI message received. -The goal of `baseapp` is to provide the fundamental layer of an SDK application that developers can easily extend to build their own custom application. Usually, developers will create a custom type for their application, like so: +The goal of `BaseApp` is to provide the fundamental layer of an SDK application that developers +can easily extend to build their own custom application. Usually, developers will create a custom +type for their application, like so: ```go type app struct { @@ -52,17 +65,26 @@ type app struct { } ``` -Extending the application with `baseapp` gives the former access to all of `baseapp`'s methods. This allows developers to compose their custom application with the modules they want, while not having to concern themselves with the hard work of implementing the ABCI, the routing and state management logic. +Extending the application with `BaseApp` gives the former access to all of `BaseApp`'s methods. +This allows developers to compose their custom application with the modules they want, while not +having to concern themselves with the hard work of implementing the ABCI, the routing and state +management logic. ## Type Definition -The [`baseapp` type](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/baseapp.go#L45-L91) holds many important parameters for any Cosmos SDK based application. Let us go through the most important components. +The [`BaseApp` type](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/baseapp.go#L53) holds +many important parameters for any Cosmos SDK based application. Let us go through the most +important components. -_Note: Not all parameters are described, only the most important ones. Refer to the [type definition](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/baseapp.go#L45-L91) for the full list_ +> __Note__: Not all parameters are described, only the most important ones. Refer to the +[type definition](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/baseapp.go#L53) for the +full list. First, the important parameters that are initialized during the initialization of the application: -- [`CommitMultiStore`](./store.md#commit-multi-store): This is the main store of the application, which holds the canonical state that is committed at the [end of each block](#commit). This store is **not** cached, meaning it is not used to update the application's intermediate (un-committed) states. The `CommitMultiStore` is a multi-store, meaning a store of stores. Each module of the application uses one or multiple `KVStores` in the multi-store to persist their subset of the state. +- [`CommitMultiStore`](./store.md#commit-multi-store): This is the main store of the application, +which holds the canonical state that is committed at the [end of each block](#commit). This store +is **not** cached, meaning it is not used to update the application's intermediate (un-committed) states. The `CommitMultiStore` is a multi-store, meaning a store of stores. Each module of the application uses one or multiple `KVStores` in the multi-store to persist their subset of the state. - Database: The `db` is used by the `CommitMultiStore` to handle data storage. - [Router](#message-routing): The `router` facilitates the routing of `messages` to the appropriate module for it to be processed. Here `message` refers to the transaction components that need to be processed by the application in order to update the state, and not to ABCI messages which implement the interface between the application and the underlying consensus engine. - [Query Router](#query-routing): The `query router` facilitates the routing of queries to the appropriate module for it to be processed. These `queries` are not ABCI messages themselves, but they are relayed to the application from the underlying consensus engine via the ABCI message [`Query`](#query). From 2cebd07f845163d824b8614a3cca0fc8a9e5b2a9 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 27 Aug 2019 13:08:53 -0400 Subject: [PATCH 49/70] Remove app bench test --- simapp/app_bench_test.go | 1 - 1 file changed, 1 deletion(-) delete mode 100644 simapp/app_bench_test.go diff --git a/simapp/app_bench_test.go b/simapp/app_bench_test.go deleted file mode 100644 index 55736c719217..000000000000 --- a/simapp/app_bench_test.go +++ /dev/null @@ -1 +0,0 @@ -package simapp_test \ No newline at end of file From 63b17507be0a244b3e165620f801ff39f6ac6e6d Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 27 Aug 2019 17:10:17 -0400 Subject: [PATCH 50/70] Update state section in baseapp docs --- docs/core/baseapp.md | 224 +++++++++++++----------- docs/core/baseapp_state-begin_block.png | Bin 0 -> 20565 bytes docs/core/baseapp_state-checktx.png | Bin 0 -> 82308 bytes docs/core/baseapp_state-commit.png | Bin 0 -> 47662 bytes docs/core/baseapp_state-deliver_tx.png | Bin 0 -> 59007 bytes docs/core/baseapp_state-initchain.png | Bin 0 -> 32800 bytes docs/core/baseapp_state_types.png | Bin 0 -> 133747 bytes 7 files changed, 121 insertions(+), 103 deletions(-) create mode 100644 docs/core/baseapp_state-begin_block.png create mode 100644 docs/core/baseapp_state-checktx.png create mode 100644 docs/core/baseapp_state-commit.png create mode 100644 docs/core/baseapp_state-deliver_tx.png create mode 100644 docs/core/baseapp_state-initchain.png create mode 100644 docs/core/baseapp_state_types.png diff --git a/docs/core/baseapp.md b/docs/core/baseapp.md index 7bfa2a548072..5ed12da68156 100644 --- a/docs/core/baseapp.md +++ b/docs/core/baseapp.md @@ -7,7 +7,7 @@ ## Synopsis -This document describes `baseapp`, the abstraction that implements most of the common +This document describes `BaseApp`, the abstraction that implements the core functionalities of an SDK application. - [BaseApp](#baseapp) @@ -17,23 +17,26 @@ functionalities of an SDK application. - [Type Definition](#type-definition) - [Constructor](#constructor) - [States](#states) - - [Main State](#main-state) - - [Volatile States](#volatile-states) + - [InitChain](#initchain) + - [CheckTx](#checktx) + - [BeginBlock](#beginblock) + - [DeliverTx](#delivertx) + - [Commit](#commit) - [Routing](#routing) - [Message Routing](#message-routing) - [Query Routing](#query-routing) - [Main ABCI Messages](#main-abci-messages) - - [CheckTx](#checktx) - - [DeliverTx](#delivertx) + - [CheckTx](#checktx-1) + - [DeliverTx](#delivertx-1) - [RunTx(), AnteHandler and RunMsgs()](#runtx-antehandler-and-runmsgs) - [RunTx()](#runtx) - [AnteHandler](#antehandler) - [RunMsgs()](#runmsgs) - [Other ABCI Messages](#other-abci-messages) - - [InitChain](#initchain) - - [BeginBlock](#beginblock) + - [InitChain](#initchain-1) + - [BeginBlock](#beginblock-1) - [EndBlock](#endblock) - - [Commit](#commit) + - [Commit](#commit-1) - [Info](#info) - [Query](#query) - [Next](#next) @@ -42,26 +45,26 @@ functionalities of an SDK application. `BaseApp` is a base type that implements the core of an SDK application, namely: -- The [Application-Blockchain Interface](#abci), for the state-machine to communicate with the +- The [Application Blockchain Interface](#abci), for the state-machine to communicate with the underlying consensus engine (e.g. Tendermint). - A [Router](#routing), to route messages and queries to the appropriate module. -- Different [states](#states), as the state-machine can have different parallel states updated -based on the ABCI message received. +- Different [states](#states), as the state-machine can have different volatile +states updated based on the ABCI message received. -The goal of `BaseApp` is to provide the fundamental layer of an SDK application that developers -can easily extend to build their own custom application. Usually, developers will create a custom -type for their application, like so: +The goal of `BaseApp` is to provide the fundamental layer of an SDK application +that developers can easily extend to build their own custom application. Usually, +developers will create a custom type for their application, like so: ```go -type app struct { - *bam.BaseApp // reference to baseapp - cdc *codec.Codec +type App struct { + // reference to a BaseApp + *bam.BaseApp - // list of application store keys + // list of application store keys - // list of application keepers + // list of application keepers - // module manager + // module manager } ``` @@ -80,116 +83,131 @@ important components. [type definition](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/baseapp.go#L53) for the full list. -First, the important parameters that are initialized during the initialization of the application: +First, the important parameters that are initialized during the bootstrapping of the application: - [`CommitMultiStore`](./store.md#commit-multi-store): This is the main store of the application, -which holds the canonical state that is committed at the [end of each block](#commit). This store -is **not** cached, meaning it is not used to update the application's intermediate (un-committed) states. The `CommitMultiStore` is a multi-store, meaning a store of stores. Each module of the application uses one or multiple `KVStores` in the multi-store to persist their subset of the state. -- Database: The `db` is used by the `CommitMultiStore` to handle data storage. -- [Router](#message-routing): The `router` facilitates the routing of `messages` to the appropriate module for it to be processed. Here `message` refers to the transaction components that need to be processed by the application in order to update the state, and not to ABCI messages which implement the interface between the application and the underlying consensus engine. -- [Query Router](#query-routing): The `query router` facilitates the routing of queries to the appropriate module for it to be processed. These `queries` are not ABCI messages themselves, but they are relayed to the application from the underlying consensus engine via the ABCI message [`Query`](#query). -- [`TxDecoder`](https://godoc.org/github.com/cosmos/cosmos-sdk/types#TxDecoder): It is used to decode transaction `[]byte` relayed by the underlying Tendermint engine. -- [`BaseKey`]: This key is used to access the [main store](./store.md#main-store) in the `CommitMultiStore`. The main store is used to persist data related to the core of the application, like consensus parameters. -- [`AnteHandler`](#antehandler): This handler is used to handle signature verification and fee payment when a transaction is received. -- [`initChainer`](../basics/app-anatomy.md#initchainer), [`beginBlocker` and `endBlocker`](../basics/app-anatomy.md#beginblocker-and-endblocker): These are the functions executed when the application receives the [InitChain], [BeginBlock] and [EndBlock] ABCI messages from the underlying Tendermint engine. +which holds the canonical state that is committed at the [end of each block](#commit-1). This store +is **not** cached, meaning it is not used to update the application's volatile (un-committed) states. +The `CommitMultiStore` is a multi-store, meaning a store of stores. Each module of the application +uses one or multiple `KVStores` in the multi-store to persist their subset of the state. +- Database: The `db` is used by the `CommitMultiStore` to handle data persistence. +- [Router](#message-routing): The `router` facilitates the routing of `messages` to the appropriate +module for it to be processed. Here a `message` refers to the transaction components that need to be +processed by the application in order to update the state, and not to ABCI messages which implement +the interface between the application and the underlying consensus engine. +- [Query Router](#query-routing): The `query router` facilitates the routing of queries to the +appropriate module for it to be processed. These `queries` are not ABCI messages themselves, but they +are relayed to the application from the underlying consensus engine via the ABCI message [`Query`](#query). +- [`TxDecoder`](https://godoc.org/github.com/cosmos/cosmos-sdk/types#TxDecoder): It is used to decode +raw transaction bytes relayed by the underlying Tendermint engine. +- `BaseKey`: This key is used to access the main store in the `CommitMultiStore`. The main store is +used to persist data related to the core of the application, like consensus parameters. +- [`AnteHandler`](#antehandler): This handler is used to handle signature verification, fee payment, +and other pre-message execution checks when a transaction is received. It's executed during +[`CheckTx`](#checktx-1) and [`DeliverTx`](#delivertx-1). +- [`InitChainer`](../basics/app-anatomy.md#initchainer), +[`BeginBlocker` and `EndBlocker`](../basics/app-anatomy.md#beginblocker-and-endblocker): These are +the functions executed when the application receives the `InitChain`, `BeginBlock` and `EndBlock` +ABCI messages from the underlying Tendermint engine. Then, parameters used to define [volatile states](#volatile-states) (i.e. cached states): -- `checkState`: This state is updated during [`CheckTx`](#checktx), and reset on [`Commit`](#commit). -- `deliverState`: This state is updated during [`DeliverTx`](#delivertx), and reset on [`Commit`](#commit). +- `checkState`: This state is updated during [`CheckTx`](#checktx-1), and reset on [`Commit`](#commit-1). +- `deliverState`: This state is updated during [`DeliverTx`](#delivertx-1), and set to `nil` on +[`Commit`](#commit-1). Finally, a few more important parameters: -- `voteInfos`: This parameter carries the list of validators whose precommit is missing, either because they did not vote or because the proposer did not include their vote. This information is carried by the [context](#context) and can be used by the application for various things like punishing absent validators. -- `minGasPrices`: This parameter defines the minimum gas prices accepted by the node. This is a local parameter, meaning each full-node can set a different `minGasPrices`. It is run by the `anteHandler` during `CheckTx`, mainly as a spam protection mechanism. The transaction enters the [mempool](https://tendermint.com/docs/tendermint-core/mempool.html#transaction-ordering) only if the gas prices of the transaction is superior to one of the minimum gas price in `minGasPrices` (i.e. if `minGasPrices == 1uatom, 1upho`, the `gas-price` of the transaction must be superior to `1uatom` OR `1upho`). -- `appVersion`: Version of the application. It is set in the [application's constructor function](../basics/app-anatomy.md#constructor-function). +- `voteInfos`: This parameter carries the list of validators whose precommit is missing, either +because they did not vote or because the proposer did not include their vote. This information is +carried by the [Context](#context) and can be used by the application for various things like +punishing absent validators. +- `minGasPrices`: This parameter defines the minimum gas prices accepted by the node. This is a +**local** parameter, meaning each full-node can set a different `minGasPrices`. It is used in the +`AnteHandler` during [`CheckTx`](#checktx-1), mainly as a spam protection mechanism. The transaction +enters the [mempool](https://tendermint.com/docs/tendermint-core/mempool.html#transaction-ordering) +only if the gas prices of the transaction are greater than one of the minimum gas price in +`minGasPrices` (e.g. if `minGasPrices == 1uatom,1photon`, the `gas-price` of the transaction must be +greater than `1uatom` OR `1photon`). +- `appVersion`: Version of the application. It is set in the +[application's constructor function](../basics/app-anatomy.md#constructor-function). ## Constructor -`NewBaseApp(name string, logger log.Logger, db dbm.DB, txDecoder sdk.TxDecoder, options ...func(*BaseApp),)` is the constructor function for `baseapp`. It is called from the [application's constructor function](../basics/app-anatomy.md#constructor-function) each time the full-node is started. +```go +func NewBaseApp( + name string, logger log.Logger, db dbm.DB, txDecoder sdk.TxDecoder, options ...func(*BaseApp), +) *BaseApp { -`baseapp`'s constructor function is pretty straightforward. The only thing worth noting is the possibility to add additional [`options`](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/options.go) to `baseapp` by passing `options functions` to the constructor function, which will execute them in order. `options` are generally `setter` functions for important parameters, like `SetPruning()` to active pruning or `SetMinGasPrices()` to set the node's `min-gas-prices`. + // ... +} +``` + +The `BaseApp` constructor function is pretty straightforward. The only thing worth noting is the +possibility to provide additional [`options`](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/options.go) +to the `BaseApp`, which will execute them in order. The `options` are generally `setter` functions +for important parameters, like `SetPruning()` to set pruning options or `SetMinGasPrices()` to set +the node's `min-gas-prices`. -A list of `options` examples can be found [here](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/options.go). Naturally, developers can add additional `options` based on their application's needs. +A list of `options` examples can be found +[here](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/options.go). Naturally, developers +can add additional `options` based on their application's needs. ## States -`baseapp` handles various parallel states for different purposes. There is the [main state](#main-state), which is the canonical state of the application, and volatile states like [`checkState`](#checkState) and [`deliverState`](#deliverstate), which are used to handle temporary states in-between updates of the main state made during [`Commit`](#commit). +The `BaseApp` maintains two primary volatile states and a root or main state. The main state +is the canonical state of the application and the volatile states, `checkState` and `deliverState`, +are used to handle state transitions in-between the main state made during [`Commit`](#commit-1). -``` - Updated whenever an unconfirmed Updated whenever a transaction To serve user queries relayed - transaction is received from the is received from the underlying from the underlying consensus - underlying consensus engine via consensus engine (as part of a block) engine via the Query ABCI message - CheckTx proposal via DeliverTx - +----------------------+ +----------------------+ +----------------------+ - | CheckState(t)(0) | | DeliverState(t)(0) | | QueryState(t) | - +----------------------+ | | | | -CheckTx(tx1) | | | | | - v | | | | - +----------------------+ | | | | - | CheckState(t)(1) | | | | | - +----------------------+ | | | | -CheckTx(tx2) | | | | | - v | | | | - +----------------------+ | | | | - | CheckState(t)(2) | | | | | - +----------------------+ | | | | -CheckTx(tx3) | | | | | - v | | | | - +----------------------+ | | | | - | CheckState(t)(3) | | | | | - +----------------------+ +----------------------+ | | -DeliverTx(tx1) | | | | - v v | | - +----------------------+ +----------------------+ | | - | | | DeliverState(t)(1) | | | - | | +----------------------+ | | -DeliverTx(tx2) | | | | | - | | v | | - | | +----------------------+ | | - | | | DeliverState(t)(2) | | | - | | +----------------------+ | | -DeliverTx(tx3) | | | | | - | | v | | - | | +----------------------+ | | - | | | DeliverState(t)(3) | | | - +----------------------+ +----------------------+ +----------------------+ -Commit() | | | - v v v - +----------------------+ +----------------------+ +----------------------+ - | CheckState(t+1)(0) | | DeliverState(t+1)(0) | | QueryState(t+1) | - +----------------------+ | | | | - . . . - . . . - . . . +Internally, there is only a single `CommitMultiStore` which we refer to as the main or root state. +From this root state, we derive two volatile state through a mechanism called cache-wrapping. The +types can be illustrated as follows: -``` +![Types](./baseapp_state_types.png) -### Main State +### InitChain -The main state is the canonical state of the application. It is initialized on [`InitChain`](#initchain) and updated on [`Commit`](#abci-commit) at the end of each block. +During `InitChain`, the two volatile states, `checkState` and `deliverState` are set by cache-wrapping +the root `CommitMultiStore`. Any subsequent reads and writes happen on cached versions of the `CommitMultiStore`. -``` -+--------+ +--------+ -| | | | -| S +----------------------------> | S' | -| | For each T in B: apply(T) | | -+--------+ +--------+ -``` +![InitChain](./baseapp_state-initchain.png) + +### CheckTx + +During `CheckTx`, the `checkState`, which is based off of the last committed state from the root +store, is used for any reads and writes. Here we only execute the `AnteHandler` and verify a router +exists for every message in the transaction. Note, when we execute the `AnteHandler`, we cache-wrap +the already cache-wrapped `checkState`. This has the side effect that if the `AnteHandler` fails, +the state transitions won't be reflected in the `checkState` -- i.e. `checkState` is only updated on +success. -The main state is held by `baseapp` in a structure called the `CommitMultiStore`. This multi-store is used by developers to instantiate all the stores they need for each of their application's modules. +![CheckTx](./baseapp_state-checktx.png) -### Volatile States +### BeginBlock + +During `BeginBlock`, the `deliverState` is set for use in subsequent `DeliverTx` ABCI messages. The +`deliverState` is based off of the last committed state from the root store and is cache-wrapped. +Note, the `deliverState` is set to `nil` on [`Commit`](#commit-1). -Volatile - or cached - states are used in between [`Commit`s](#commit) to manage temporary states. They are reset to the latest version of the main state after it is committed. There are two main volatile states: +![CheckTx](./baseapp_state-begin_block.png) + +### DeliverTx -- `checkState`: This cached state is initialized during [`InitChain`](#initchain), updated during [`CheckTx`](#abci-checktx) when an unconfirmed transaction is received, and reset to the [main state](#main-state) on [`Commit`](#abci-commit). -- `deliverState`: This cached state is initialized during [`BeginBlock`](#beginblock), updated during [`DeliverTx`](#abci-delivertx) when a transaction included in a block is processed, and reset to the [main state](#main-state) on [`Commit`](#abci-commit). +The state flow for `DeliverTx` is nearly identical to `CheckTx` except state transitions occur on +the `deliverState` and messages in a transaction are executed. Similarly to `CheckTx`, state transitions +occur on a doubly cache-wrapped state -- `deliverState`. Successful message execution results in +writes being committed to `deliverState`. + +![DeliverTx](./baseapp_state-deliver_tx.png) + +### Commit -Both `checkState` and `deliverState` are of type [`state`](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/baseapp.go#L973-L976), which includes: +During `Commit` all the state transitions that occurred in the `deliverState` are finally written to +the root `CommitMultiStore` which in turn is committed to disk and results in a new application +root hash. These state transitions are now considered final. Finally, the `checkState` is set to the +newly committed state and `deliverState` is set to `nil` to be reset on `BeginBlock`. -- A [`CacheMultiStore`](https://github.com/cosmos/cosmos-sdk/blob/master/store/cachemulti/store.go), which is a cached version of the main `CommitMultiStore`. A new version of this store is committed at the end of each successful `CheckTx()`/`DeliverTx()` execution. -- A `Context`, which carries general information (like raw transaction size, block height, ...) that might be needed in order to process the transaction during `CheckTx()` and `DeliverTx()`. The `context` also holds a cache-wrapped version of the `CacheMultiStore`, so that the `CacheMultiStore` can maintain the correct version even if an internal step of `CheckTx()` or `DeliverTx()` fails. +![Commit](./baseapp_state-commit.png) ## Routing diff --git a/docs/core/baseapp_state-begin_block.png b/docs/core/baseapp_state-begin_block.png new file mode 100644 index 0000000000000000000000000000000000000000..745d4a5a971292bb0346c35893b42ebfbcdc206e GIT binary patch literal 20565 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 HU84U7#M|-t literal 0 HcmV?d00001 diff --git a/docs/core/baseapp_state-checktx.png b/docs/core/baseapp_state-checktx.png new file mode 100644 index 0000000000000000000000000000000000000000..38b217acdd04fb2430a2332946864de04474ae5a GIT binary patch literal 82308 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 N1zA-Y;BI{L{{e+~Yq9_U literal 0 HcmV?d00001 diff --git a/docs/core/baseapp_state-deliver_tx.png b/docs/core/baseapp_state-deliver_tx.png new file mode 100644 index 0000000000000000000000000000000000000000..f0a54b4ec34bbe282ed6eff81369428d02dec095 GIT binary patch literal 59007 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 E2iU8KRR910 literal 0 HcmV?d00001 diff --git a/docs/core/baseapp_state-initchain.png b/docs/core/baseapp_state-initchain.png new file mode 100644 index 0000000000000000000000000000000000000000..d03e88ef2ae0745aaedc52cf72863080388d7e9c GIT binary patch literal 32800 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 R0ton{s-*d-Lcucl{{yUICl~+# literal 0 HcmV?d00001 diff --git a/docs/core/baseapp_state_types.png b/docs/core/baseapp_state_types.png new file mode 100644 index 0000000000000000000000000000000000000000..a7f91a6093e0099f409101276833e80bdc223f78 GIT binary patch literal 133747 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 T?XrE0gO|T|pjV|w#G(HHz@)&x literal 0 HcmV?d00001 From 118c1dd4843e7e6a508f567a52127e5aaaa1b33a Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 28 Aug 2019 09:03:50 -0400 Subject: [PATCH 51/70] Add chagelog entry --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e09fb97f9b8..a5a358ecdea0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,10 @@ longer panics if the store to load contains substores that we didn't explicitly * (simulation) [\#4906](https://github.com/cosmos/cosmos-sdk/issues/4906) Add simulation `Config` struct that wraps simulation flags * (store) [\#4792](https://github.com/cosmos/cosmos-sdk/issues/4792) panic on non-registered store * (types) [\#4821](https://github.com/cosmos/cosmos-sdk/issues/4821) types/errors package added with support for stacktraces. It is meant as a more feature-rich replacement for sdk.Errors in the mid-term. +* (store) [\#1947](https://github.com/cosmos/cosmos-sdk/issues/1947) Implement inter-block (persistent) +caching through `CommitKVStoreCacheManager`. Any application wishing to utilize an inter-block cache +must set it in their app via a `BaseApp` option. The `BaseApp` docs have been drastically improved +to detail this new feature and how state transitions occur. ### Bug Fixes From 1ef4985f92da1b2ba9b8bdaf254e68154ef67581 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Wed, 28 Aug 2019 09:49:49 -0400 Subject: [PATCH 52/70] Update baseapp/abci.go Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- baseapp/abci.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index a50ea96975ca..040b738e17ce 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -349,7 +349,7 @@ func handleQueryP2P(app *BaseApp, path []string, _ abci.RequestQuery) (res abci. } default: - msg := "Expected second parameter to be filter" + msg := "expected second parameter to be 'filter'" return sdk.ErrUnknownRequest(msg).QueryResult() } } From 5e2ffa14995a5fd5de52a0cca468d48fb8f25c7d Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Wed, 28 Aug 2019 09:51:51 -0400 Subject: [PATCH 53/70] Update baseapp/abci.go Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- baseapp/abci.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index 040b738e17ce..5cc76a0407e6 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -305,7 +305,7 @@ func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abc } } - msg := "Expected second parameter to be either simulate or version, neither was present" + msg := "expected second parameter to be either 'simulate' or 'version', neither was present" return sdk.ErrUnknownRequest(msg).QueryResult() } From 4f3f2455d4e0ff2bda2e534638cff4c0f5bab729 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Wed, 28 Aug 2019 09:53:32 -0400 Subject: [PATCH 54/70] Update baseapp/abci.go Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- baseapp/abci.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index 5cc76a0407e6..4a12d6998042 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -293,7 +293,7 @@ func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abc } default: - result = sdk.ErrUnknownRequest(fmt.Sprintf("Unknown query: %s", path)).Result() + result = sdk.ErrUnknownRequest(fmt.Sprintf("unknown query: %s", path)).Result() } value := codec.Cdc.MustMarshalBinaryLengthPrefixed(result) From 834ba3f24098b29e572a3bae4497537e07e6b001 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Wed, 28 Aug 2019 09:54:12 -0400 Subject: [PATCH 55/70] Update baseapp/baseapp.go Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- baseapp/baseapp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index b58a50a7346d..53bcef8d5ea3 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -639,7 +639,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (re msgRoute := msg.Route() handler := app.router.Route(msgRoute) if handler == nil { - return sdk.ErrUnknownRequest("Unrecognized Msg type: " + msgRoute).Result() + return sdk.ErrUnknownRequest("unrecognized Msg type: " + msgRoute).Result() } var msgResult sdk.Result From 9b7c8f7eec23b0832409253bce07c5d60ef1ab15 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Wed, 28 Aug 2019 10:20:03 -0400 Subject: [PATCH 56/70] Update baseapp/baseapp.go Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- baseapp/baseapp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 53bcef8d5ea3..021bd568f6ad 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -634,7 +634,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (re events := sdk.EmptyEvents() // NOTE: GasWanted is determined by ante handler and GasUsed by the GasMeter. - for msgIdx, msg := range msgs { + for i, msg := range msgs { // match message route msgRoute := msg.Route() handler := app.router.Route(msgRoute) From 74b5e8470558c86dceb3a57493838005a7aaa627 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Wed, 28 Aug 2019 10:20:18 -0400 Subject: [PATCH 57/70] Update baseapp/baseapp.go Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- baseapp/baseapp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 021bd568f6ad..75b8af39c023 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -657,7 +657,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (re events = events.AppendEvent(sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, msg.Type()))) events = events.AppendEvents(msgResult.Events) - idxLog := sdk.ABCIMessageLog{MsgIndex: uint16(msgIdx), Log: msgResult.Log} + idxLog := sdk.ABCIMessageLog{MsgIndex: uint16(i), Log: msgResult.Log} // stop execution and return on first failed message if !msgResult.IsOK() { From c676e64e00d51343e4981cc9d0db433ca4da10f4 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 28 Aug 2019 13:55:13 -0400 Subject: [PATCH 58/70] Revert x/mock/app.go --- x/mock/app.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/x/mock/app.go b/x/mock/app.go index ba6e5679a627..c1595ad79374 100644 --- a/x/mock/app.go +++ b/x/mock/app.go @@ -206,8 +206,9 @@ func SetGenesis(app *App, accs []authexported.Account) { app.Commit() } -func GenTxWithChainID(cid string, msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKey) auth.StdTx { - // make the transaction free +// GenTx generates a signed mock transaction. +func GenTx(msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKey) auth.StdTx { + // Make the transaction free fee := auth.StdFee{ Amount: sdk.NewCoins(sdk.NewInt64Coin("foocoin", 0)), Gas: 100000, @@ -217,7 +218,7 @@ func GenTxWithChainID(cid string, msgs []sdk.Msg, accnums []uint64, seq []uint64 memo := "testmemotestmemo" for i, p := range priv { - sig, err := p.Sign(auth.StdSignBytes(cid, accnums[i], seq[i], fee, msgs, memo)) + sig, err := p.Sign(auth.StdSignBytes(chainID, accnums[i], seq[i], fee, msgs, memo)) if err != nil { panic(err) } @@ -231,11 +232,6 @@ func GenTxWithChainID(cid string, msgs []sdk.Msg, accnums []uint64, seq []uint64 return auth.NewStdTx(msgs, fee, sigs, memo) } -// GenTx generates a signed mock transaction. -func GenTx(msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKey) auth.StdTx { - return GenTxWithChainID(chainID, msgs, accnums, seq, priv...) -} - // GeneratePrivKeys generates a total n secp256k1 private keys. func GeneratePrivKeys(n int) (keys []crypto.PrivKey) { // TODO: Randomize this between ed25519 and secp256k1 From 0035bd3ae1510e6a3c0fb8f579d7718b28d23a94 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 28 Aug 2019 13:57:12 -0400 Subject: [PATCH 59/70] Cleanup TestStoreCache --- store/cache/cache_test.go | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/store/cache/cache_test.go b/store/cache/cache_test.go index cc830c0fad78..e2898a2c83a2 100644 --- a/store/cache/cache_test.go +++ b/store/cache/cache_test.go @@ -41,20 +41,11 @@ func TestStoreCache(t *testing.T) { res := kvStore.Get(key) require.Equal(t, res, value) - - res = store.Get(key) - require.Equal(t, res, value) - } - - for i := uint(0); i < cache.DefaultCommitKVStoreCacheSize*2; i++ { - key := []byte(fmt.Sprintf("key_%d", i)) + require.Equal(t, res, store.Get(key)) kvStore.Delete(key) - res := kvStore.Get(key) - require.Nil(t, res) - - res = store.Get(key) - require.Nil(t, res) + require.Nil(t, kvStore.Get(key)) + require.Nil(t, store.Get(key)) } } From 3d923eff944746b00013f64c820aeac94092a996 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 28 Aug 2019 13:59:40 -0400 Subject: [PATCH 60/70] Move splitPath to abci.go --- baseapp/abci.go | 14 ++++++++++++++ baseapp/baseapp.go | 11 ----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index 4a12d6998042..ebad8a6488f0 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -417,3 +417,17 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res Value: resBytes, } } + +// splitPath splits a string path using the delimiter '/'. +// +// e.g. "this/is/funny" becomes []string{"this", "is", "funny"} +func splitPath(requestPath string) (path []string) { + path = strings.Split(requestPath, "/") + + // first element is empty string + if len(path) > 0 && path[0] == "" { + path = path[1:] + } + + return path +} diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 75b8af39c023..23868f71c98e 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -685,14 +685,3 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (re return result } - -// Splits a string path using the delimiter '/'. -// e.g. "this/is/funny" becomes []string{"this", "is", "funny"} -func splitPath(requestPath string) (path []string) { - path = strings.Split(requestPath, "/") - // first element is empty string - if len(path) > 0 && path[0] == "" { - path = path[1:] - } - return path -} From 83f5973cd845a0c232c65d6bf5b4dcdade01ca2c Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Sun, 1 Sep 2019 20:55:21 -0400 Subject: [PATCH 61/70] Add inter-block-cache flag --- server/start.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/server/start.go b/server/start.go index d3d47df3b827..83142539f62f 100644 --- a/server/start.go +++ b/server/start.go @@ -20,13 +20,14 @@ import ( // Tendermint full-node start flags const ( - flagWithTendermint = "with-tendermint" - flagAddress = "address" - flagTraceStore = "trace-store" - flagPruning = "pruning" - flagCPUProfile = "cpu-profile" - FlagMinGasPrices = "minimum-gas-prices" - FlagHaltHeight = "halt-height" + flagWithTendermint = "with-tendermint" + flagAddress = "address" + flagTraceStore = "trace-store" + flagPruning = "pruning" + flagCPUProfile = "cpu-profile" + FlagMinGasPrices = "minimum-gas-prices" + FlagHaltHeight = "halt-height" + FlagInterBlockCache = "inter-block-cache" ) // StartCmd runs the service passed in, either stand-alone or in-process with @@ -58,6 +59,7 @@ func StartCmd(ctx *Context, appCreator AppCreator) *cobra.Command { "Minimum gas prices to accept for transactions; Any fee in a tx must meet this minimum (e.g. 0.01photino;0.0001stake)", ) cmd.Flags().Uint64(FlagHaltHeight, 0, "Height at which to gracefully halt the chain and shutdown the node") + cmd.Flags().Bool(FlagInterBlockCache, true, "Enable inter-block caching") cmd.Flags().String(flagCPUProfile, "", "Enable CPU profiling and write to the provided file") // add support for all Tendermint-specific command line options From 4ca6f73b3fcc959c72f2144dd05304286ae39bb2 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Sun, 1 Sep 2019 21:08:05 -0400 Subject: [PATCH 62/70] Update baseapp/abci.go Co-Authored-By: Aditya --- baseapp/abci.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index ebad8a6488f0..2a9803266e25 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -46,7 +46,7 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC if len(req.Validators) != len(res.Validators) { panic( fmt.Errorf( - "len(RequestInitChain.Validators) != len(validators) (%d != %d)", + "len(RequestInitChain.Validators) != len(GenesisValidators) (%d != %d)", len(req.Validators), len(res.Validators), ), ) From d09e8ff764c80295ca1ae2d4574525d01b4ccad0 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Sun, 1 Sep 2019 21:08:29 -0400 Subject: [PATCH 63/70] Update baseapp/abci.go Co-Authored-By: Aditya --- baseapp/abci.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index 2a9803266e25..ac24a06a65f2 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -57,7 +57,7 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC for i, val := range res.Validators { if !val.Equal(req.Validators[i]) { - panic(fmt.Errorf("validators[%d] != req.Validators[%d] ", i, i)) + panic(fmt.Errorf("genesisValidators[%d] != req.Validators[%d] ", i, i)) } } } From 0df9ad5f0d6cbf557cb45e8d84695fe7b1c10390 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Sun, 1 Sep 2019 21:09:08 -0400 Subject: [PATCH 64/70] Update docs/core/baseapp.md Co-Authored-By: Aditya --- docs/core/baseapp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/baseapp.md b/docs/core/baseapp.md index 45a51527e072..dde3e2b29440 100644 --- a/docs/core/baseapp.md +++ b/docs/core/baseapp.md @@ -113,7 +113,7 @@ Then, parameters used to define [volatile states](#volatile-states) (i.e. cached - `checkState`: This state is updated during [`CheckTx`](#checktx-1), and reset on [`Commit`](#commit-1). - `deliverState`: This state is updated during [`DeliverTx`](#delivertx-1), and set to `nil` on -[`Commit`](#commit-1). +[`Commit`](#commit-1). `deliverState` gets re-initialized on BeginBlock. Finally, a few more important parameters: From ad08260bf50d836fb098a0f86496ec0e296f99d2 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Sun, 1 Sep 2019 21:09:50 -0400 Subject: [PATCH 65/70] Modify docs --- docs/core/baseapp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/baseapp.md b/docs/core/baseapp.md index dde3e2b29440..e0ba863a2003 100644 --- a/docs/core/baseapp.md +++ b/docs/core/baseapp.md @@ -113,7 +113,7 @@ Then, parameters used to define [volatile states](#volatile-states) (i.e. cached - `checkState`: This state is updated during [`CheckTx`](#checktx-1), and reset on [`Commit`](#commit-1). - `deliverState`: This state is updated during [`DeliverTx`](#delivertx-1), and set to `nil` on -[`Commit`](#commit-1). `deliverState` gets re-initialized on BeginBlock. +[`Commit`](#commit-1) and gets re-initialized on BeginBlock. Finally, a few more important parameters: From 1d22b5341e1257b84df1f60aeb9bba228d8a0445 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Sun, 1 Sep 2019 21:10:11 -0400 Subject: [PATCH 66/70] Update docs/core/baseapp.md Co-Authored-By: Aditya --- docs/core/baseapp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/baseapp.md b/docs/core/baseapp.md index e0ba863a2003..4207e7ef5059 100644 --- a/docs/core/baseapp.md +++ b/docs/core/baseapp.md @@ -188,7 +188,7 @@ During `BeginBlock`, the `deliverState` is set for use in subsequent `DeliverTx` `deliverState` is based off of the last committed state from the root store and is cache-wrapped. Note, the `deliverState` is set to `nil` on [`Commit`](#commit-1). -![CheckTx](./baseapp_state-begin_block.png) +![BeginBlock](./baseapp_state-begin_block.png) ### DeliverTx From 6c0398f44e1b1f4acfeac04ac459979d73dcbee3 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 3 Sep 2019 15:02:01 -0400 Subject: [PATCH 67/70] Add note on message state transitions --- docs/core/baseapp.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/core/baseapp.md b/docs/core/baseapp.md index e0ba863a2003..61c1e87e0b69 100644 --- a/docs/core/baseapp.md +++ b/docs/core/baseapp.md @@ -195,7 +195,8 @@ Note, the `deliverState` is set to `nil` on [`Commit`](#commit-1). The state flow for `DeliverTx` is nearly identical to `CheckTx` except state transitions occur on the `deliverState` and messages in a transaction are executed. Similarly to `CheckTx`, state transitions occur on a doubly cache-wrapped state -- `deliverState`. Successful message execution results in -writes being committed to `deliverState`. +writes being committed to `deliverState`. Note, if message execution fails, state transitions from +the AnteHandler are persisted. ![DeliverTx](./baseapp_state-deliver_tx.png) From 9db0514b5fa21049671012ff6952c52ebf710961 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 3 Sep 2019 15:38:59 -0400 Subject: [PATCH 68/70] Add assertions for key/value in cache layer --- store/cache/cache.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/store/cache/cache.go b/store/cache/cache.go index fe32fa1069fd..91770b788ea2 100644 --- a/store/cache/cache.go +++ b/store/cache/cache.go @@ -84,6 +84,8 @@ func (ckv *CommitKVStoreCache) CacheWrap() types.CacheWrap { // If the value doesn't exist in the write-through cache, the query is delegated // to the underlying CommitKVStore. func (ckv *CommitKVStoreCache) Get(key []byte) []byte { + types.AssertValidKey(key) + valueI, ok := ckv.cache.Get(string(key)) if ok { // cache hit @@ -100,6 +102,9 @@ func (ckv *CommitKVStoreCache) Get(key []byte) []byte { // Set inserts a key/value pair into both the write-through cache and the // underlying CommitKVStore. func (ckv *CommitKVStoreCache) Set(key, value []byte) { + types.AssertValidKey(key) + types.AssertValidValue(value) + ckv.cache.Add(string(key), value) ckv.CommitKVStore.Set(key, value) } From 1b3d2dfeb4160b6c97b8367e82d9f29aebe93320 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 3 Sep 2019 15:44:45 -0400 Subject: [PATCH 69/70] Store string key in a var --- store/cache/cache.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/store/cache/cache.go b/store/cache/cache.go index 91770b788ea2..2293c3bbde3e 100644 --- a/store/cache/cache.go +++ b/store/cache/cache.go @@ -86,7 +86,8 @@ func (ckv *CommitKVStoreCache) CacheWrap() types.CacheWrap { func (ckv *CommitKVStoreCache) Get(key []byte) []byte { types.AssertValidKey(key) - valueI, ok := ckv.cache.Get(string(key)) + keyStr := string(key) + valueI, ok := ckv.cache.Get(keyStr) if ok { // cache hit return valueI.([]byte) @@ -94,7 +95,7 @@ func (ckv *CommitKVStoreCache) Get(key []byte) []byte { // cache miss; write to cache value := ckv.CommitKVStore.Get(key) - ckv.cache.Add(string(key), value) + ckv.cache.Add(keyStr, value) return value } From 09c5cd617c4adc66c6968dfe9269f5173a6f918d Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 4 Sep 2019 13:15:33 -0400 Subject: [PATCH 70/70] Add a API breaking changelog entry --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e8fe3a641f5..71d0b2569c93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,9 +37,11 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] - ### API Breaking Changes +* (store) [\#4748](https://github.com/cosmos/cosmos-sdk/pull/4748) The `CommitMultiStore` interface +now requires a `SetInterBlockCache` method. Applications that do not wish to support this can simply +have this method perform a no-op. * (modules) [\#4665](https://github.com/cosmos/cosmos-sdk/issues/4665) Refactored `x/gov` module structure and dev-UX: * Prepare for module spec integration * Update gov keys to use big endian encoding instead of little endian @@ -48,7 +50,6 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (rest) [\#4783](https://github.com/cosmos/cosmos-sdk/issues/4783) The balance field in the DelegationResponse type is now sdk.Coin instead of sdk.Int - ### Features * (cli) [\#4973](https://github.com/cosmos/cosmos-sdk/pull/4973) Enable application CPU profiling