From a66942855dc2bada75267b63c95ef05bc60ec646 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 3 Dec 2018 11:45:48 +0100 Subject: [PATCH 01/25] in progress --- store/{ => cache}/memiterator.go | 2 +- .../mergeiterator.go} | 12 +-- store/{cachekvstore.go => cache/store.go} | 82 ++++++++++--------- .../store_test.go} | 4 +- store/{ => cachemulti}/cachemultistore.go | 0 .../{dbstoreadapter.go => dbadapter/store.go} | 33 ++++---- store/firstlast.go | 10 +++ store/{ => gas}/gaskvstore.go | 75 +++++++++-------- store/{ => gas}/gaskvstore_test.go | 2 +- store/{ => iavl}/iavlstore.go | 11 --- store/{ => iavl}/iavlstore_test.go | 0 store/{ => list}/list.go | 0 store/{ => list}/list_test.go | 0 store/{ => prefix}/prefixstore.go | 62 +++++++------- store/{ => prefix}/prefixstore_test.go | 2 +- store/{ => queue}/queue.go | 0 store/{ => queue}/queue_test.go | 0 store/{ => rootmulti}/multistoreproof.go | 0 store/{ => rootmulti}/multistoreproof_test.go | 0 store/{ => rootmulti}/rootmultistore.go | 0 store/{ => rootmulti}/rootmultistore_test.go | 0 store/{tracekvstore.go => trace/store.go} | 36 ++++---- .../store_test.go} | 7 +- store/{ => transient}/transientstore.go | 0 store/{ => transient}/transientstore_test.go | 0 types/context.go | 6 +- types/gas.go | 3 +- types/store.go | 21 +++-- 28 files changed, 199 insertions(+), 169 deletions(-) rename store/{ => cache}/memiterator.go (99%) rename store/{cachemergeiterator.go => cache/mergeiterator.go} (95%) rename store/{cachekvstore.go => cache/store.go} (65%) rename store/{cachekvstore_test.go => cache/store_test.go} (99%) rename store/{ => cachemulti}/cachemultistore.go (100%) rename store/{dbstoreadapter.go => dbadapter/store.go} (61%) rename store/{ => gas}/gaskvstore.go (61%) rename store/{ => gas}/gaskvstore_test.go (99%) rename store/{ => iavl}/iavlstore.go (98%) rename store/{ => iavl}/iavlstore_test.go (100%) rename store/{ => list}/list.go (100%) rename store/{ => list}/list_test.go (100%) rename store/{ => prefix}/prefixstore.go (72%) rename store/{ => prefix}/prefixstore_test.go (99%) rename store/{ => queue}/queue.go (100%) rename store/{ => queue}/queue_test.go (100%) rename store/{ => rootmulti}/multistoreproof.go (100%) rename store/{ => rootmulti}/multistoreproof_test.go (100%) rename store/{ => rootmulti}/rootmultistore.go (100%) rename store/{ => rootmulti}/rootmultistore_test.go (100%) rename store/{tracekvstore.go => trace/store.go} (85%) rename store/{tracekvstore_test.go => trace/store_test.go} (98%) rename store/{ => transient}/transientstore.go (100%) rename store/{ => transient}/transientstore_test.go (100%) diff --git a/store/memiterator.go b/store/cache/memiterator.go similarity index 99% rename from store/memiterator.go rename to store/cache/memiterator.go index c9a026cb5ff1..9b8504c77e03 100644 --- a/store/memiterator.go +++ b/store/cache/memiterator.go @@ -1,4 +1,4 @@ -package store +package cache import ( "bytes" diff --git a/store/cachemergeiterator.go b/store/cache/mergeiterator.go similarity index 95% rename from store/cachemergeiterator.go rename to store/cache/mergeiterator.go index cd739500de76..12bfd2caa600 100644 --- a/store/cachemergeiterator.go +++ b/store/cache/mergeiterator.go @@ -1,7 +1,9 @@ -package store +package cache import ( "bytes" + + "github.com/cosmos/cosmos-sdk/types" ) // cacheMergeIterator merges a parent Iterator and a cache Iterator. @@ -12,14 +14,14 @@ import ( // // TODO: Optimize by memoizing. type cacheMergeIterator struct { - parent Iterator - cache Iterator + parent types.Iterator + cache types.Iterator ascending bool } -var _ Iterator = (*cacheMergeIterator)(nil) +var _ types.Iterator = (*cacheMergeIterator)(nil) -func newCacheMergeIterator(parent, cache Iterator, ascending bool) *cacheMergeIterator { +func newCacheMergeIterator(parent, cache types.Iterator, ascending bool) *cacheMergeIterator { iter := &cacheMergeIterator{ parent: parent, cache: cache, diff --git a/store/cachekvstore.go b/store/cache/store.go similarity index 65% rename from store/cachekvstore.go rename to store/cache/store.go index 4860566c4b6d..6768b4110e84 100644 --- a/store/cachekvstore.go +++ b/store/cache/store.go @@ -1,4 +1,4 @@ -package store +package cache import ( "bytes" @@ -8,6 +8,10 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" + + "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/store/trace" ) // If value is nil but deleted is false, it means the parent doesn't have the @@ -18,30 +22,30 @@ type cValue struct { dirty bool } -// cacheKVStore wraps an in-memory cache around an underlying KVStore. -type cacheKVStore struct { +// Store wraps an in-memory cache around an underlying types.KVStore. +type Store struct { mtx sync.Mutex cache map[string]cValue - parent KVStore + parent types.KVStore } -var _ CacheKVStore = (*cacheKVStore)(nil) +var _ types.CacheKVStore = (*Store)(nil) // nolint -func NewCacheKVStore(parent KVStore) *cacheKVStore { - return &cacheKVStore{ +func NewStore(parent types.KVStore) *Store { + return &Store{ cache: make(map[string]cValue), parent: parent, } } // Implements Store. -func (ci *cacheKVStore) GetStoreType() StoreType { +func (ci *Store) GetStoreType() types.StoreType { return ci.parent.GetStoreType() } -// Implements KVStore. -func (ci *cacheKVStore) Get(key []byte) (value []byte) { +// Implements types.KVStore. +func (ci *Store) Get(key []byte) (value []byte) { ci.mtx.Lock() defer ci.mtx.Unlock() ci.assertValidKey(key) @@ -57,8 +61,8 @@ func (ci *cacheKVStore) Get(key []byte) (value []byte) { return value } -// Implements KVStore. -func (ci *cacheKVStore) Set(key []byte, value []byte) { +// Implements types.KVStore. +func (ci *Store) Set(key []byte, value []byte) { ci.mtx.Lock() defer ci.mtx.Unlock() ci.assertValidKey(key) @@ -67,14 +71,14 @@ func (ci *cacheKVStore) Set(key []byte, value []byte) { ci.setCacheValue(key, value, false, true) } -// Implements KVStore. -func (ci *cacheKVStore) Has(key []byte) bool { +// Implements types.KVStore. +func (ci *Store) Has(key []byte) bool { value := ci.Get(key) return value != nil } -// Implements KVStore. -func (ci *cacheKVStore) Delete(key []byte) { +// Implements types.KVStore. +func (ci *Store) Delete(key []byte) { ci.mtx.Lock() defer ci.mtx.Unlock() ci.assertValidKey(key) @@ -82,18 +86,20 @@ func (ci *cacheKVStore) Delete(key []byte) { ci.setCacheValue(key, nil, true, true) } -// Implements KVStore -func (ci *cacheKVStore) Prefix(prefix []byte) KVStore { +// XXX: delete +/* +// Implements types.KVStore +func (ci *Store) Prefix(prefix []byte) types.KVStore { return prefixStore{ci, prefix} } -// Implements KVStore -func (ci *cacheKVStore) Gas(meter GasMeter, config GasConfig) KVStore { +// Implements types.KVStore +func (ci *Store) Gas(meter GasMeter, config GasConfig) types.KVStore { return NewGasKVStore(meter, config, ci) } - -// Implements CacheKVStore. -func (ci *cacheKVStore) Write() { +*/ +// Implements Cachetypes.KVStore. +func (ci *Store) Write() { ci.mtx.Lock() defer ci.mtx.Unlock() @@ -126,33 +132,33 @@ func (ci *cacheKVStore) Write() { } //---------------------------------------- -// To cache-wrap this cacheKVStore further. +// To cache-wrap this Store further. // Implements CacheWrapper. -func (ci *cacheKVStore) CacheWrap() CacheWrap { - return NewCacheKVStore(ci) +func (ci *Store) CacheWrap() types.CacheWrap { + return NewStore(ci) } // CacheWrapWithTrace implements the CacheWrapper interface. -func (ci *cacheKVStore) CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap { - return NewCacheKVStore(NewTraceKVStore(ci, w, tc)) +func (ci *Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { + return NewStore(trace.NewStore(ci, w, tc)) } //---------------------------------------- // Iteration -// Implements KVStore. -func (ci *cacheKVStore) Iterator(start, end []byte) Iterator { +// Implements types.KVStore. +func (ci *Store) Iterator(start, end []byte) types.Iterator { return ci.iterator(start, end, true) } -// Implements KVStore. -func (ci *cacheKVStore) ReverseIterator(start, end []byte) Iterator { +// Implements types.KVStore. +func (ci *Store) ReverseIterator(start, end []byte) types.Iterator { return ci.iterator(start, end, false) } -func (ci *cacheKVStore) iterator(start, end []byte, ascending bool) Iterator { - var parent, cache Iterator +func (ci *Store) iterator(start, end []byte, ascending bool) types.Iterator { + var parent, cache types.Iterator if ascending { parent = ci.parent.Iterator(start, end) @@ -167,7 +173,7 @@ func (ci *cacheKVStore) iterator(start, end []byte, ascending bool) Iterator { } // Constructs a slice of dirty items, to use w/ memIterator. -func (ci *cacheKVStore) dirtyItems(start, end []byte, ascending bool) []cmn.KVPair { +func (ci *Store) dirtyItems(start, end []byte, ascending bool) []cmn.KVPair { items := make([]cmn.KVPair, 0) for key, cacheValue := range ci.cache { @@ -192,20 +198,20 @@ func (ci *cacheKVStore) dirtyItems(start, end []byte, ascending bool) []cmn.KVPa //---------------------------------------- // etc -func (ci *cacheKVStore) assertValidKey(key []byte) { +func (ci *Store) assertValidKey(key []byte) { if key == nil { panic("key is nil") } } -func (ci *cacheKVStore) assertValidValue(value []byte) { +func (ci *Store) assertValidValue(value []byte) { if value == nil { panic("value is nil") } } // Only entrypoint to mutate ci.cache. -func (ci *cacheKVStore) setCacheValue(key, value []byte, deleted bool, dirty bool) { +func (ci *Store) setCacheValue(key, value []byte, deleted bool, dirty bool) { ci.cache[string(key)] = cValue{ value: value, deleted: deleted, diff --git a/store/cachekvstore_test.go b/store/cache/store_test.go similarity index 99% rename from store/cachekvstore_test.go rename to store/cache/store_test.go index 37e0364fb5aa..76c7b328f519 100644 --- a/store/cachekvstore_test.go +++ b/store/cache/store_test.go @@ -1,4 +1,4 @@ -package store +package cache_test import ( "fmt" @@ -7,6 +7,8 @@ import ( "github.com/stretchr/testify/require" cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" + + "github.com/cosmos/cosmos-sdk/store/dbadapter" ) func newCacheKVStore() CacheKVStore { diff --git a/store/cachemultistore.go b/store/cachemulti/cachemultistore.go similarity index 100% rename from store/cachemultistore.go rename to store/cachemulti/cachemultistore.go diff --git a/store/dbstoreadapter.go b/store/dbadapter/store.go similarity index 61% rename from store/dbstoreadapter.go rename to store/dbadapter/store.go index 8f4a1583c6cf..2d654c2394fd 100644 --- a/store/dbstoreadapter.go +++ b/store/dbadapter/store.go @@ -1,10 +1,13 @@ -package store +package dbadapter import ( "io" - sdk "github.com/cosmos/cosmos-sdk/types" dbm "github.com/tendermint/tendermint/libs/db" + + "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/store/cache" ) // Wrapper type for dbm.Db with implementation of KVStore @@ -13,20 +16,22 @@ type dbStoreAdapter struct { } // Implements Store. -func (dbStoreAdapter) GetStoreType() StoreType { - return sdk.StoreTypeDB +func (dbStoreAdapter) GetStoreType() types.StoreType { + return types.StoreTypeDB } // Implements KVStore. -func (dsa dbStoreAdapter) CacheWrap() CacheWrap { - return NewCacheKVStore(dsa) +func (dsa dbStoreAdapter) CacheWrap() types.CacheWrap { + return cache.NewStore(dsa) } // CacheWrapWithTrace implements the KVStore interface. -func (dsa dbStoreAdapter) CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap { +func (dsa dbStoreAdapter) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { return NewCacheKVStore(NewTraceKVStore(dsa, w, tc)) } +// XXX: delete +/* // Implements KVStore func (dsa dbStoreAdapter) Prefix(prefix []byte) KVStore { return prefixStore{dsa, prefix} @@ -36,9 +41,9 @@ func (dsa dbStoreAdapter) Prefix(prefix []byte) KVStore { func (dsa dbStoreAdapter) Gas(meter GasMeter, config GasConfig) KVStore { return NewGasKVStore(meter, config, dsa) } - +*/ // dbm.DB implements KVStore so we can CacheKVStore it. -var _ KVStore = dbStoreAdapter{} +var _ types.KVStore = dbStoreAdapter{} //---------------------------------------- // commitDBStoreWrapper should only be used for simulation/debugging, @@ -49,18 +54,18 @@ type commitDBStoreAdapter struct { dbStoreAdapter } -func (cdsa commitDBStoreAdapter) Commit() CommitID { - return CommitID{ +func (cdsa commitDBStoreAdapter) Commit() types.CommitID { + return types.CommitID{ Version: -1, Hash: []byte("FAKE_HASH"), } } -func (cdsa commitDBStoreAdapter) LastCommitID() CommitID { - return CommitID{ +func (cdsa commitDBStoreAdapter) LastCommitID() types.CommitID { + return types.CommitID{ Version: -1, Hash: []byte("FAKE_HASH"), } } -func (cdsa commitDBStoreAdapter) SetPruning(_ PruningStrategy) {} +func (cdsa commitDBStoreAdapter) SetPruning(_ types.PruningStrategy) {} diff --git a/store/firstlast.go b/store/firstlast.go index a47f1396d158..76d0ae03e361 100644 --- a/store/firstlast.go +++ b/store/firstlast.go @@ -38,3 +38,13 @@ func Last(st KVStore, start, end []byte) (kv cmn.KVPair, ok bool) { return cmn.KVPair{Key: iter.Key(), Value: iter.Value()}, true } + +//---------------------------------------- +func cp(bz []byte) (ret []byte) { + if bz == nil { + return nil + } + ret = make([]byte, len(bz)) + copy(ret, bz) + return ret +} diff --git a/store/gaskvstore.go b/store/gas/gaskvstore.go similarity index 61% rename from store/gaskvstore.go rename to store/gas/gaskvstore.go index 2ce6415e666b..8d3c88f4dfa1 100644 --- a/store/gaskvstore.go +++ b/store/gas/gaskvstore.go @@ -1,25 +1,25 @@ -package store +package gas import ( "io" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types" ) -var _ KVStore = &gasKVStore{} +var _ types.KVStore = &Store{} -// gasKVStore applies gas tracking to an underlying KVStore. It implements the +// Store applies gas tracking to an underlying KVStore. It implements the // KVStore interface. -type gasKVStore struct { - gasMeter sdk.GasMeter - gasConfig sdk.GasConfig - parent sdk.KVStore +type Store struct { + gasMeter types.GasMeter + gasConfig types.GasConfig + parent types.KVStore } // NewGasKVStore returns a reference to a new GasKVStore. // nolint -func NewGasKVStore(gasMeter sdk.GasMeter, gasConfig sdk.GasConfig, parent sdk.KVStore) *gasKVStore { - kvs := &gasKVStore{ +func NewGasKVStore(gasMeter types.GasMeter, gasConfig types.GasConfig, parent types.KVStore) *Store { + kvs := &Store{ gasMeter: gasMeter, gasConfig: gasConfig, parent: parent, @@ -28,46 +28,48 @@ func NewGasKVStore(gasMeter sdk.GasMeter, gasConfig sdk.GasConfig, parent sdk.KV } // Implements Store. -func (gs *gasKVStore) GetStoreType() sdk.StoreType { +func (gs *Store) GetStoreType() types.StoreType { return gs.parent.GetStoreType() } // Implements KVStore. -func (gs *gasKVStore) Get(key []byte) (value []byte) { - gs.gasMeter.ConsumeGas(gs.gasConfig.ReadCostFlat, sdk.GasReadCostFlatDesc) +func (gs *Store) Get(key []byte) (value []byte) { + gs.gasMeter.ConsumeGas(gs.gasConfig.ReadCostFlat, types.GasReadCostFlatDesc) value = gs.parent.Get(key) // TODO overflow-safe math? - gs.gasMeter.ConsumeGas(gs.gasConfig.ReadCostPerByte*sdk.Gas(len(value)), sdk.GasReadPerByteDesc) + gs.gasMeter.ConsumeGas(gs.gasConfig.ReadCostPerByte*types.Gas(len(value)), types.GasReadPerByteDesc) return value } // Implements KVStore. -func (gs *gasKVStore) Set(key []byte, value []byte) { - gs.gasMeter.ConsumeGas(gs.gasConfig.WriteCostFlat, sdk.GasWriteCostFlatDesc) +func (gs *Store) Set(key []byte, value []byte) { + gs.gasMeter.ConsumeGas(gs.gasConfig.WriteCostFlat, types.GasWriteCostFlatDesc) // TODO overflow-safe math? - gs.gasMeter.ConsumeGas(gs.gasConfig.WriteCostPerByte*sdk.Gas(len(value)), sdk.GasWritePerByteDesc) + gs.gasMeter.ConsumeGas(gs.gasConfig.WriteCostPerByte*types.Gas(len(value)), types.GasWritePerByteDesc) gs.parent.Set(key, value) } // Implements KVStore. -func (gs *gasKVStore) Has(key []byte) bool { - gs.gasMeter.ConsumeGas(gs.gasConfig.HasCost, sdk.GasHasDesc) +func (gs *Store) Has(key []byte) bool { + gs.gasMeter.ConsumeGas(gs.gasConfig.HasCost, types.GasHasDesc) return gs.parent.Has(key) } // Implements KVStore. -func (gs *gasKVStore) Delete(key []byte) { +func (gs *Store) Delete(key []byte) { // charge gas to prevent certain attack vectors even though space is being freed - gs.gasMeter.ConsumeGas(gs.gasConfig.DeleteCost, sdk.GasDeleteDesc) + gs.gasMeter.ConsumeGas(gs.gasConfig.DeleteCost, types.GasDeleteDesc) gs.parent.Delete(key) } +// XXX: delete +/* // Implements KVStore -func (gs *gasKVStore) Prefix(prefix []byte) KVStore { +func (gs *Store) Prefix(prefix []byte) types.KVStore { // Keep gasstore layer at the top - return &gasKVStore{ + return &Store{ gasMeter: gs.gasMeter, gasConfig: gs.gasConfig, parent: prefixStore{gs.parent, prefix}, @@ -75,14 +77,15 @@ func (gs *gasKVStore) Prefix(prefix []byte) KVStore { } // Implements KVStore -func (gs *gasKVStore) Gas(meter GasMeter, config GasConfig) KVStore { +func (gs *Store) Gas(meter types.GasMeter, config types.GasConfig) types.KVStore { return NewGasKVStore(meter, config, gs) } +*/ // Iterator implements the KVStore interface. It returns an iterator which // incurs a flat gas cost for seeking to the first key/value pair and a variable // gas cost based on the current value's length if the iterator is valid. -func (gs *gasKVStore) Iterator(start, end []byte) sdk.Iterator { +func (gs *Store) Iterator(start, end []byte) types.Iterator { return gs.iterator(start, end, true) } @@ -90,22 +93,22 @@ func (gs *gasKVStore) Iterator(start, end []byte) sdk.Iterator { // iterator which incurs a flat gas cost for seeking to the first key/value pair // and a variable gas cost based on the current value's length if the iterator // is valid. -func (gs *gasKVStore) ReverseIterator(start, end []byte) sdk.Iterator { +func (gs *Store) ReverseIterator(start, end []byte) types.Iterator { return gs.iterator(start, end, false) } // Implements KVStore. -func (gs *gasKVStore) CacheWrap() sdk.CacheWrap { +func (gs *Store) CacheWrap() types.CacheWrap { panic("cannot CacheWrap a GasKVStore") } // CacheWrapWithTrace implements the KVStore interface. -func (gs *gasKVStore) CacheWrapWithTrace(_ io.Writer, _ TraceContext) CacheWrap { +func (gs *Store) CacheWrapWithTrace(_ io.Writer, _ types.TraceContext) types.CacheWrap { panic("cannot CacheWrapWithTrace a GasKVStore") } -func (gs *gasKVStore) iterator(start, end []byte, ascending bool) sdk.Iterator { - var parent sdk.Iterator +func (gs *Store) iterator(start, end []byte, ascending bool) types.Iterator { + var parent types.Iterator if ascending { parent = gs.parent.Iterator(start, end) } else { @@ -121,12 +124,12 @@ func (gs *gasKVStore) iterator(start, end []byte, ascending bool) sdk.Iterator { } type gasIterator struct { - gasMeter sdk.GasMeter - gasConfig sdk.GasConfig - parent sdk.Iterator + gasMeter types.GasMeter + gasConfig types.GasConfig + parent types.Iterator } -func newGasIterator(gasMeter sdk.GasMeter, gasConfig sdk.GasConfig, parent sdk.Iterator) sdk.Iterator { +func newGasIterator(gasMeter types.GasMeter, gasConfig types.GasConfig, parent types.Iterator) types.Iterator { return &gasIterator{ gasMeter: gasMeter, gasConfig: gasConfig, @@ -179,6 +182,6 @@ func (gi *gasIterator) Close() { func (gi *gasIterator) consumeSeekGas() { value := gi.Value() - gi.gasMeter.ConsumeGas(gi.gasConfig.ValueCostPerByte*sdk.Gas(len(value)), sdk.GasValuePerByteDesc) - gi.gasMeter.ConsumeGas(gi.gasConfig.IterNextCostFlat, sdk.GasIterNextCostFlatDesc) + gi.gasMeter.ConsumeGas(gi.gasConfig.ValueCostPerByte*types.Gas(len(value)), types.GasValuePerByteDesc) + gi.gasMeter.ConsumeGas(gi.gasConfig.IterNextCostFlat, types.GasIterNextCostFlatDesc) } diff --git a/store/gaskvstore_test.go b/store/gas/gaskvstore_test.go similarity index 99% rename from store/gaskvstore_test.go rename to store/gas/gaskvstore_test.go index f059df7f8231..24626952accb 100644 --- a/store/gaskvstore_test.go +++ b/store/gas/gaskvstore_test.go @@ -1,4 +1,4 @@ -package store +package gas import ( "testing" diff --git a/store/iavlstore.go b/store/iavl/iavlstore.go similarity index 98% rename from store/iavlstore.go rename to store/iavl/iavlstore.go index fccde38e27e0..24d676ff105a 100644 --- a/store/iavlstore.go +++ b/store/iavl/iavlstore.go @@ -430,14 +430,3 @@ func (iter *iavlIterator) assertIsValid(unlockMutex bool) { panic("invalid iterator") } } - -//---------------------------------------- - -func cp(bz []byte) (ret []byte) { - if bz == nil { - return nil - } - ret = make([]byte, len(bz)) - copy(ret, bz) - return ret -} diff --git a/store/iavlstore_test.go b/store/iavl/iavlstore_test.go similarity index 100% rename from store/iavlstore_test.go rename to store/iavl/iavlstore_test.go diff --git a/store/list.go b/store/list/list.go similarity index 100% rename from store/list.go rename to store/list/list.go diff --git a/store/list_test.go b/store/list/list_test.go similarity index 100% rename from store/list_test.go rename to store/list/list_test.go diff --git a/store/prefixstore.go b/store/prefix/prefixstore.go similarity index 72% rename from store/prefixstore.go rename to store/prefix/prefixstore.go index 1f52a99fec48..a7881bc7e816 100644 --- a/store/prefixstore.go +++ b/store/prefix/prefixstore.go @@ -1,20 +1,22 @@ -package store +package prefix import ( "bytes" "io" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/store/cache" ) -var _ KVStore = prefixStore{} +var _ types.KVStore = Store{} -// prefixStore is similar with tendermint/tendermint/libs/db/prefix_db +// Store is similar with tendermint/tendermint/libs/db/prefix_db // both gives access only to the limited subset of the store // for convinience or safety -type prefixStore struct { - parent KVStore +type Store struct { + parent types.KVStore prefix []byte } @@ -25,63 +27,65 @@ func cloneAppend(bz []byte, tail []byte) (res []byte) { return } -func (s prefixStore) key(key []byte) (res []byte) { +func (s Store) key(key []byte) (res []byte) { if key == nil { - panic("nil key on prefixStore") + panic("nil key on Store") } res = cloneAppend(s.prefix, key) return } // Implements Store -func (s prefixStore) GetStoreType() StoreType { +func (s Store) GetStoreType() types.StoreType { return s.parent.GetStoreType() } // Implements CacheWrap -func (s prefixStore) CacheWrap() CacheWrap { - return NewCacheKVStore(s) +func (s Store) CacheWrap() types.CacheWrap { + return cache.NewStore(s) } // CacheWrapWithTrace implements the KVStore interface. -func (s prefixStore) CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap { - return NewCacheKVStore(NewTraceKVStore(s, w, tc)) +func (s Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { + return cache.NewStore(NewTraceKVStore(s, w, tc)) } // Implements KVStore -func (s prefixStore) Get(key []byte) []byte { +func (s Store) Get(key []byte) []byte { res := s.parent.Get(s.key(key)) return res } // Implements KVStore -func (s prefixStore) Has(key []byte) bool { +func (s Store) Has(key []byte) bool { return s.parent.Has(s.key(key)) } // Implements KVStore -func (s prefixStore) Set(key, value []byte) { +func (s Store) Set(key, value []byte) { s.parent.Set(s.key(key), value) } // Implements KVStore -func (s prefixStore) Delete(key []byte) { +func (s Store) Delete(key []byte) { s.parent.Delete(s.key(key)) } +// XXX: delete +/* // Implements KVStore -func (s prefixStore) Prefix(prefix []byte) KVStore { - return prefixStore{s, prefix} +func (s Store) Prefix(prefix []byte) types.KVStore { + return Store{s, prefix} } // Implements KVStore -func (s prefixStore) Gas(meter GasMeter, config GasConfig) KVStore { +func (s Store) Gas(meter types.GasMeter, config types.GasConfig) types.KVStore { return NewGasKVStore(meter, config, s) } - +*/ // Implements KVStore // Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L106 -func (s prefixStore) Iterator(start, end []byte) Iterator { +func (s Store) Iterator(start, end []byte) types.Iterator { newstart := cloneAppend(s.prefix, start) var newend []byte @@ -98,7 +102,7 @@ func (s prefixStore) Iterator(start, end []byte) Iterator { // Implements KVStore // Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L129 -func (s prefixStore) ReverseIterator(start, end []byte) Iterator { +func (s Store) ReverseIterator(start, end []byte) types.Iterator { newstart := cloneAppend(s.prefix, start) var newend []byte @@ -113,16 +117,16 @@ func (s prefixStore) ReverseIterator(start, end []byte) Iterator { return newPrefixIterator(s.prefix, start, end, iter) } -var _ sdk.Iterator = (*prefixIterator)(nil) +var _ types.Iterator = (*prefixIterator)(nil) type prefixIterator struct { prefix []byte start, end []byte - iter Iterator + iter types.Iterator valid bool } -func newPrefixIterator(prefix, start, end []byte, parent Iterator) *prefixIterator { +func newPrefixIterator(prefix, start, end []byte, parent types.Iterator) *prefixIterator { return &prefixIterator{ prefix: prefix, start: start, @@ -184,9 +188,9 @@ func stripPrefix(key []byte, prefix []byte) []byte { return key[len(prefix):] } -// wrapping sdk.PrefixEndBytes +// wrapping types.PrefixEndBytes func cpIncr(bz []byte) []byte { - return sdk.PrefixEndBytes(bz) + return types.PrefixEndBytes(bz) } // copied from github.com/tendermint/tendermint/libs/db/util.go @@ -209,7 +213,7 @@ func cpDecr(bz []byte) (ret []byte) { return nil } -func skipOne(iter Iterator, skipKey []byte) { +func skipOne(iter types.Iterator, skipKey []byte) { if iter.Valid() { if bytes.Equal(iter.Key(), skipKey) { iter.Next() diff --git a/store/prefixstore_test.go b/store/prefix/prefixstore_test.go similarity index 99% rename from store/prefixstore_test.go rename to store/prefix/prefixstore_test.go index 48e6cd17f7b9..db3e0ebf2c6f 100644 --- a/store/prefixstore_test.go +++ b/store/prefix/prefixstore_test.go @@ -1,4 +1,4 @@ -package store +package prefix import ( "math/rand" diff --git a/store/queue.go b/store/queue/queue.go similarity index 100% rename from store/queue.go rename to store/queue/queue.go diff --git a/store/queue_test.go b/store/queue/queue_test.go similarity index 100% rename from store/queue_test.go rename to store/queue/queue_test.go diff --git a/store/multistoreproof.go b/store/rootmulti/multistoreproof.go similarity index 100% rename from store/multistoreproof.go rename to store/rootmulti/multistoreproof.go diff --git a/store/multistoreproof_test.go b/store/rootmulti/multistoreproof_test.go similarity index 100% rename from store/multistoreproof_test.go rename to store/rootmulti/multistoreproof_test.go diff --git a/store/rootmultistore.go b/store/rootmulti/rootmultistore.go similarity index 100% rename from store/rootmultistore.go rename to store/rootmulti/rootmultistore.go diff --git a/store/rootmultistore_test.go b/store/rootmulti/rootmultistore_test.go similarity index 100% rename from store/rootmultistore_test.go rename to store/rootmulti/rootmultistore_test.go diff --git a/store/tracekvstore.go b/store/trace/store.go similarity index 85% rename from store/tracekvstore.go rename to store/trace/store.go index d8c34c354542..042d3c087601 100644 --- a/store/tracekvstore.go +++ b/store/trace/store.go @@ -1,4 +1,4 @@ -package store +package trace import ( "encoding/base64" @@ -6,7 +6,7 @@ import ( "fmt" "io" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types" ) const ( @@ -25,9 +25,9 @@ type ( // TODO: Should we use a buffered writer and implement Commit on // TraceKVStore? TraceKVStore struct { - parent sdk.KVStore + parent types.KVStore writer io.Writer - context TraceContext + context types.TraceContext } // operation represents an IO operation @@ -44,7 +44,7 @@ type ( // NewTraceKVStore returns a reference to a new traceKVStore given a parent // KVStore implementation and a buffered writer. -func NewTraceKVStore(parent sdk.KVStore, writer io.Writer, tc TraceContext) *TraceKVStore { +func NewTraceKVStore(parent types.KVStore, writer io.Writer, tc types.TraceContext) *TraceKVStore { return &TraceKVStore{parent: parent, writer: writer, context: tc} } @@ -77,6 +77,8 @@ func (tkv *TraceKVStore) Has(key []byte) bool { return tkv.parent.Has(key) } +// XXX: delete +/* // Prefix implements the KVStore interface. func (tkv *TraceKVStore) Prefix(prefix []byte) KVStore { return prefixStore{tkv, prefix} @@ -86,23 +88,23 @@ func (tkv *TraceKVStore) Prefix(prefix []byte) KVStore { func (tkv *TraceKVStore) Gas(meter GasMeter, config GasConfig) KVStore { return NewGasKVStore(meter, config, tkv.parent) } - +*/ // Iterator implements the KVStore interface. It delegates the Iterator call // the to the parent KVStore. -func (tkv *TraceKVStore) Iterator(start, end []byte) sdk.Iterator { +func (tkv *TraceKVStore) Iterator(start, end []byte) types.Iterator { return tkv.iterator(start, end, true) } // ReverseIterator implements the KVStore interface. It delegates the // ReverseIterator call the to the parent KVStore. -func (tkv *TraceKVStore) ReverseIterator(start, end []byte) sdk.Iterator { +func (tkv *TraceKVStore) ReverseIterator(start, end []byte) types.Iterator { return tkv.iterator(start, end, false) } // iterator facilitates iteration over a KVStore. It delegates the necessary // calls to it's parent KVStore. -func (tkv *TraceKVStore) iterator(start, end []byte, ascending bool) sdk.Iterator { - var parent sdk.Iterator +func (tkv *TraceKVStore) iterator(start, end []byte, ascending bool) types.Iterator { + var parent types.Iterator if ascending { parent = tkv.parent.Iterator(start, end) @@ -114,12 +116,12 @@ func (tkv *TraceKVStore) iterator(start, end []byte, ascending bool) sdk.Iterato } type traceIterator struct { - parent sdk.Iterator + parent types.Iterator writer io.Writer - context TraceContext + context types.TraceContext } -func newTraceIterator(w io.Writer, parent sdk.Iterator, tc TraceContext) sdk.Iterator { +func newTraceIterator(w io.Writer, parent types.Iterator, tc types.TraceContext) types.Iterator { return &traceIterator{writer: w, parent: parent, context: tc} } @@ -161,26 +163,26 @@ func (ti *traceIterator) Close() { // GetStoreType implements the KVStore interface. It returns the underlying // KVStore type. -func (tkv *TraceKVStore) GetStoreType() sdk.StoreType { +func (tkv *TraceKVStore) GetStoreType() types.StoreType { return tkv.parent.GetStoreType() } // CacheWrap implements the KVStore interface. It panics as a TraceKVStore // cannot be cache wrapped. -func (tkv *TraceKVStore) CacheWrap() sdk.CacheWrap { +func (tkv *TraceKVStore) CacheWrap() types.CacheWrap { panic("cannot CacheWrap a TraceKVStore") } // CacheWrapWithTrace implements the KVStore interface. It panics as a // TraceKVStore cannot be cache wrapped. -func (tkv *TraceKVStore) CacheWrapWithTrace(_ io.Writer, _ TraceContext) CacheWrap { +func (tkv *TraceKVStore) CacheWrapWithTrace(_ io.Writer, _ types.TraceContext) types.CacheWrap { panic("cannot CacheWrapWithTrace a TraceKVStore") } // writeOperation writes a KVStore operation to the underlying io.Writer as // JSON-encoded data where the key/value pair is base64 encoded. // nolint: errcheck -func writeOperation(w io.Writer, op operation, tc TraceContext, key, value []byte) { +func writeOperation(w io.Writer, op operation, tc types.TraceContext, key, value []byte) { traceOp := traceOperation{ Operation: op, Key: base64.StdEncoding.EncodeToString(key), diff --git a/store/tracekvstore_test.go b/store/trace/store_test.go similarity index 98% rename from store/tracekvstore_test.go rename to store/trace/store_test.go index 887fcf96e5c9..187ebc2d7f1c 100644 --- a/store/tracekvstore_test.go +++ b/store/trace/store_test.go @@ -1,4 +1,4 @@ -package store +package trace_test import ( "bytes" @@ -8,9 +8,12 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/tendermint/tendermint/libs/db" + + "github.com/cosmos/cosmos-sdk/store/dbadapter" + "github.com/cosmos/cosmos-sdk/types" ) -var kvPairs = []KVPair{ +var kvPairs = []types.KVPair{ {Key: keyFmt(1), Value: valFmt(1)}, {Key: keyFmt(2), Value: valFmt(2)}, {Key: keyFmt(3), Value: valFmt(3)}, diff --git a/store/transientstore.go b/store/transient/transientstore.go similarity index 100% rename from store/transientstore.go rename to store/transient/transientstore.go diff --git a/store/transientstore_test.go b/store/transient/transientstore_test.go similarity index 100% rename from store/transientstore_test.go rename to store/transient/transientstore_test.go diff --git a/types/context.go b/types/context.go index 71e1f5303e64..55af0fb795dd 100644 --- a/types/context.go +++ b/types/context.go @@ -72,14 +72,16 @@ func (c Context) Value(key interface{}) interface{} { return value } +// XXX: temporary breakes gas semantic +// will be solved after the store->types dependency is inverted // KVStore fetches a KVStore from the MultiStore. func (c Context) KVStore(key StoreKey) KVStore { - return c.MultiStore().GetKVStore(key).Gas(c.GasMeter(), cachedKVGasConfig) + return c.MultiStore().GetKVStore(key) //.Gas(c.GasMeter(), cachedKVGasConfig) } // TransientStore fetches a TransientStore from the MultiStore. func (c Context) TransientStore(key StoreKey) KVStore { - return c.MultiStore().GetKVStore(key).Gas(c.GasMeter(), cachedTransientGasConfig) + return c.MultiStore().GetKVStore(key) //.Gas(c.GasMeter(), cachedTransientGasConfig) } //---------------------------------------- diff --git a/types/gas.go b/types/gas.go index 100b004305b8..0f61d27c0235 100644 --- a/types/gas.go +++ b/types/gas.go @@ -71,7 +71,6 @@ func (g *basicGasMeter) GasConsumedToLimit() Gas { func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) { var overflow bool - // TODO: Should we set the consumed field after overflow checking? g.consumed, overflow = AddUint64Overflow(g.consumed, amount) if overflow { @@ -81,6 +80,7 @@ func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) { if g.consumed > g.limit { panic(ErrorOutOfGas{descriptor}) } + } func (g *basicGasMeter) IsPastLimit() bool { @@ -116,7 +116,6 @@ func (g *infiniteGasMeter) Limit() Gas { func (g *infiniteGasMeter) ConsumeGas(amount Gas, descriptor string) { var overflow bool - // TODO: Should we set the consumed field after overflow checking? g.consumed, overflow = AddUint64Overflow(g.consumed, amount) if overflow { diff --git a/types/store.go b/types/store.go index 671a881c28be..94cefaccbd7c 100644 --- a/types/store.go +++ b/types/store.go @@ -154,15 +154,18 @@ type KVStore interface { // TODO Not yet implemented. // GetSubKVStore(key *storeKey) KVStore - // Prefix applied keys with the argument - // CONTRACT: when Prefix is called on a KVStore more than once, - // the concatanation of the prefixes is applied - Prefix(prefix []byte) KVStore - - // Gas consuming store - // CONTRACT: when Gas is called on a KVStore more than once, - // the concatanation of the meters/configs is applied - Gas(GasMeter, GasConfig) KVStore + // XXX: delete + /* + // Prefix applied keys with the argument + // CONTRACT: when Prefix is called on a KVStore more than once, + // the concatanation of the prefixes is applied + Prefix(prefix []byte) KVStore + + // Gas consuming store + // CONTRACT: when Gas is called on a KVStore more than once, + // the concatanation of the meters/configs is applied + Gas(GasMeter, GasConfig) KVStore + */ } // Alias iterator to db's Iterator for convenience. From 83dac5d0a5174ac0c683365398899e9c335a562f Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 3 Dec 2018 14:10:04 +0100 Subject: [PATCH 02/25] store/* now compiles --- client/context/query.go | 6 +- .../democoin/x/assoc/validator_set_test.go | 3 +- store/cache/store_test.go | 38 ++-- store/cachemulti/cachemultistore.go | 141 --------------- store/cachemulti/store.go | 140 ++++++++++++++ store/dbadapter/store.go | 42 +---- store/gas/{gaskvstore.go => store.go} | 4 +- .../gas/{gaskvstore_test.go => store_test.go} | 60 +++--- store/iavl/{iavlstore.go => store.go} | 129 +++++++------ .../iavl/{iavlstore_test.go => store_test.go} | 70 +++---- store/iavl/wire.go | 7 + store/list/list.go | 2 +- store/list/list_test.go | 23 ++- store/prefix/prefixstore.go | 10 +- store/prefix/prefixstore_test.go | 100 +++++----- store/queue/queue.go | 7 +- store/queue/queue_test.go | 2 + store/rootmulti/dbadapter.go | 31 ++++ store/rootmulti/multistoreproof.go | 2 +- store/rootmulti/multistoreproof_test.go | 32 ++-- store/rootmulti/rootmultistore.go | 171 +++++++++--------- store/rootmulti/rootmultistore_test.go | 66 +++---- store/rootmulti/wire.go | 7 + store/store.go | 13 ++ store/trace/store.go | 44 ++--- store/trace/store_test.go | 24 ++- store/transient/store.go | 53 ++++++ .../{transientstore_test.go => store_test.go} | 4 +- store/transient/transientstore.go | 49 ----- x/params/subspace/subspace.go | 6 +- 30 files changed, 707 insertions(+), 579 deletions(-) delete mode 100644 store/cachemulti/cachemultistore.go create mode 100644 store/cachemulti/store.go rename store/gas/{gaskvstore.go => store.go} (96%) rename store/gas/{gaskvstore_test.go => store_test.go} (58%) rename store/iavl/{iavlstore.go => store.go} (74%) rename store/iavl/{iavlstore_test.go => store_test.go} (88%) create mode 100644 store/iavl/wire.go create mode 100644 store/rootmulti/dbadapter.go create mode 100644 store/rootmulti/wire.go create mode 100644 store/store.go create mode 100644 store/transient/store.go rename store/transient/{transientstore_test.go => store_test.go} (86%) delete mode 100644 store/transient/transientstore.go diff --git a/client/context/query.go b/client/context/query.go index 486bd5186e48..e81d6e03b08e 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -10,7 +10,7 @@ import ( "strings" - "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/store/rootmulti" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto/merkle" cmn "github.com/tendermint/tendermint/libs/common" @@ -210,7 +210,7 @@ func (ctx CLIContext) verifyProof(queryPath string, resp abci.ResponseQuery) err } // TODO: Instead of reconstructing, stash on CLIContext field? - prt := store.DefaultProofRuntime() + prt := rootmulti.DefaultProofRuntime() // TODO: Better convention for path? storeName, err := parseQueryStorePath(queryPath) @@ -250,7 +250,7 @@ func isQueryStoreWithProof(path string) bool { return false case paths[0] != "store": return false - case store.RequireProof("/" + paths[2]): + case rootmulti.RequireProof("/" + paths[2]): return true } diff --git a/docs/examples/democoin/x/assoc/validator_set_test.go b/docs/examples/democoin/x/assoc/validator_set_test.go index 66f03c840324..c7bb9e5c0a8f 100644 --- a/docs/examples/democoin/x/assoc/validator_set_test.go +++ b/docs/examples/democoin/x/assoc/validator_set_test.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/docs/examples/democoin/mock" "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -36,7 +37,7 @@ func TestValidatorSet(t *testing.T) { {addr2, sdk.NewDec(2)}, }} - valset := NewValidatorSet(codec.New(), ctx.KVStore(key).Prefix([]byte("assoc")), base, 1, 5) + valset := NewValidatorSet(codec.New(), prefix.NewStore(ctx.KVStore(key), []byte("assoc")), base, 1, 5) require.Equal(t, base.Validator(ctx, addr1), valset.Validator(ctx, addr1)) require.Equal(t, base.Validator(ctx, addr2), valset.Validator(ctx, addr2)) diff --git a/store/cache/store_test.go b/store/cache/store_test.go index 76c7b328f519..7a2638ce66f8 100644 --- a/store/cache/store_test.go +++ b/store/cache/store_test.go @@ -8,20 +8,22 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" + "github.com/cosmos/cosmos-sdk/store/cache" "github.com/cosmos/cosmos-sdk/store/dbadapter" + "github.com/cosmos/cosmos-sdk/types" ) -func newCacheKVStore() CacheKVStore { - mem := dbStoreAdapter{dbm.NewMemDB()} - return NewCacheKVStore(mem) +func newCacheKVStore() types.CacheKVStore { + mem := dbadapter.Store{dbm.NewMemDB()} + return cache.NewStore(mem) } func keyFmt(i int) []byte { return bz(fmt.Sprintf("key%0.8d", i)) } func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } func TestCacheKVStore(t *testing.T) { - mem := dbStoreAdapter{dbm.NewMemDB()} - st := NewCacheKVStore(mem) + mem := dbadapter.Store{dbm.NewMemDB()} + st := cache.NewStore(mem) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") @@ -47,11 +49,11 @@ func TestCacheKVStore(t *testing.T) { require.Equal(t, valFmt(2), st.Get(keyFmt(1))) // make a new one, check it - st = NewCacheKVStore(mem) + st = cache.NewStore(mem) require.Equal(t, valFmt(2), st.Get(keyFmt(1))) // make a new one and delete - should not be removed from mem - st = NewCacheKVStore(mem) + st = cache.NewStore(mem) st.Delete(keyFmt(1)) require.Empty(t, st.Get(keyFmt(1))) require.Equal(t, mem.Get(keyFmt(1)), valFmt(2)) @@ -63,8 +65,8 @@ func TestCacheKVStore(t *testing.T) { } func TestCacheKVStoreNested(t *testing.T) { - mem := dbStoreAdapter{dbm.NewMemDB()} - st := NewCacheKVStore(mem) + mem := dbadapter.Store{dbm.NewMemDB()} + st := cache.NewStore(mem) // set. check its there on st and not on mem. st.Set(keyFmt(1), valFmt(1)) @@ -72,7 +74,7 @@ func TestCacheKVStoreNested(t *testing.T) { require.Equal(t, valFmt(1), st.Get(keyFmt(1))) // make a new from st and check - st2 := NewCacheKVStore(st) + st2 := cache.NewStore(st) require.Equal(t, valFmt(1), st2.Get(keyFmt(1))) // update the value on st2, check it only effects st2 @@ -314,7 +316,7 @@ func randInt(n int) int { } // useful for replaying a error case if we find one -func doOp(st CacheKVStore, truth dbm.DB, op int, args ...int) { +func doOp(st types.CacheKVStore, truth dbm.DB, op int, args ...int) { switch op { case opSet: k := args[0] @@ -337,7 +339,7 @@ func doOp(st CacheKVStore, truth dbm.DB, op int, args ...int) { } } -func doRandomOp(st CacheKVStore, truth dbm.DB, maxKey int) { +func doRandomOp(st types.CacheKVStore, truth dbm.DB, maxKey int) { r := randInt(totalOps) switch r { case opSet: @@ -364,7 +366,7 @@ func doRandomOp(st CacheKVStore, truth dbm.DB, maxKey int) { //------------------------------------------------------------------------------------------- // iterate over whole domain -func assertIterateDomain(t *testing.T, st KVStore, expectedN int) { +func assertIterateDomain(t *testing.T, st types.KVStore, expectedN int) { itr := st.Iterator(nil, nil) var i = 0 for ; itr.Valid(); itr.Next() { @@ -376,7 +378,7 @@ func assertIterateDomain(t *testing.T, st KVStore, expectedN int) { require.Equal(t, expectedN, i) } -func assertIterateDomainCheck(t *testing.T, st KVStore, mem dbm.DB, r []keyRange) { +func assertIterateDomainCheck(t *testing.T, st types.KVStore, mem dbm.DB, r []keyRange) { // iterate over each and check they match the other itr := st.Iterator(nil, nil) itr2 := mem.Iterator(nil, nil) // ground truth @@ -406,7 +408,7 @@ func assertIterateDomainCheck(t *testing.T, st KVStore, mem dbm.DB, r []keyRange require.False(t, itr2.Valid()) } -func assertIterateDomainCompare(t *testing.T, st KVStore, mem dbm.DB) { +func assertIterateDomainCompare(t *testing.T, st types.KVStore, mem dbm.DB) { // iterate over each and check they match the other itr := st.Iterator(nil, nil) itr2 := mem.Iterator(nil, nil) // ground truth @@ -414,7 +416,7 @@ func assertIterateDomainCompare(t *testing.T, st KVStore, mem dbm.DB) { checkIterators(t, itr2, itr) } -func checkIterators(t *testing.T, itr, itr2 Iterator) { +func checkIterators(t *testing.T, itr, itr2 types.Iterator) { for ; itr.Valid(); itr.Next() { require.True(t, itr2.Valid()) k, v := itr.Key(), itr.Value() @@ -429,14 +431,14 @@ func checkIterators(t *testing.T, itr, itr2 Iterator) { //-------------------------------------------------------- -func setRange(st KVStore, mem dbm.DB, start, end int) { +func setRange(st types.KVStore, mem dbm.DB, start, end int) { for i := start; i < end; i++ { st.Set(keyFmt(i), valFmt(i)) mem.Set(keyFmt(i), valFmt(i)) } } -func deleteRange(st KVStore, mem dbm.DB, start, end int) { +func deleteRange(st types.KVStore, mem dbm.DB, start, end int) { for i := start; i < end; i++ { st.Delete(keyFmt(i)) mem.Delete(keyFmt(i)) diff --git a/store/cachemulti/cachemultistore.go b/store/cachemulti/cachemultistore.go deleted file mode 100644 index ee19778559a0..000000000000 --- a/store/cachemulti/cachemultistore.go +++ /dev/null @@ -1,141 +0,0 @@ -package store - -import ( - "io" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -//---------------------------------------- -// cacheMultiStore - -// cacheMultiStore holds many cache-wrapped stores. -// Implements MultiStore. -// NOTE: a cacheMultiStore (and MultiStores in general) should never expose the -// keys for the substores. -type cacheMultiStore struct { - db CacheKVStore - stores map[StoreKey]CacheWrap - keysByName map[string]StoreKey - - traceWriter io.Writer - traceContext TraceContext -} - -var _ CacheMultiStore = cacheMultiStore{} - -func newCacheMultiStoreFromRMS(rms *rootMultiStore) cacheMultiStore { - cms := cacheMultiStore{ - db: NewCacheKVStore(dbStoreAdapter{rms.db}), - stores: make(map[StoreKey]CacheWrap, len(rms.stores)), - keysByName: rms.keysByName, - traceWriter: rms.traceWriter, - traceContext: rms.traceContext, - } - - for key, store := range rms.stores { - if cms.TracingEnabled() { - cms.stores[key] = store.CacheWrapWithTrace(cms.traceWriter, cms.traceContext) - } else { - cms.stores[key] = store.CacheWrap() - } - } - - return cms -} - -func newCacheMultiStoreFromCMS(cms cacheMultiStore) cacheMultiStore { - cms2 := cacheMultiStore{ - db: NewCacheKVStore(cms.db), - stores: make(map[StoreKey]CacheWrap, len(cms.stores)), - traceWriter: cms.traceWriter, - traceContext: cms.traceContext, - } - - for key, store := range cms.stores { - if cms2.TracingEnabled() { - cms2.stores[key] = store.CacheWrapWithTrace(cms2.traceWriter, cms2.traceContext) - } else { - cms2.stores[key] = store.CacheWrap() - } - } - - return cms2 -} - -// WithTracer sets the tracer for the MultiStore that the underlying -// stores will utilize to trace operations. A MultiStore is returned. -func (cms cacheMultiStore) WithTracer(w io.Writer) MultiStore { - cms.traceWriter = w - return cms -} - -// WithTracingContext updates the tracing context for the MultiStore by merging -// the given context with the existing context by key. Any existing keys will -// be overwritten. It is implied that the caller should update the context when -// necessary between tracing operations. It returns a modified MultiStore. -func (cms cacheMultiStore) WithTracingContext(tc TraceContext) MultiStore { - if cms.traceContext != nil { - for k, v := range tc { - cms.traceContext[k] = v - } - } else { - cms.traceContext = tc - } - - return cms -} - -// TracingEnabled returns if tracing is enabled for the MultiStore. -func (cms cacheMultiStore) TracingEnabled() bool { - return cms.traceWriter != nil -} - -// ResetTraceContext resets the current tracing context. -func (cms cacheMultiStore) ResetTraceContext() MultiStore { - cms.traceContext = nil - return cms -} - -// Implements Store. -func (cms cacheMultiStore) GetStoreType() StoreType { - return sdk.StoreTypeMulti -} - -// Implements CacheMultiStore. -func (cms cacheMultiStore) Write() { - cms.db.Write() - for _, store := range cms.stores { - store.Write() - } -} - -// Implements CacheWrapper. -func (cms cacheMultiStore) CacheWrap() CacheWrap { - return cms.CacheMultiStore().(CacheWrap) -} - -// CacheWrapWithTrace implements the CacheWrapper interface. -func (cms cacheMultiStore) CacheWrapWithTrace(_ io.Writer, _ TraceContext) CacheWrap { - return cms.CacheWrap() -} - -// Implements MultiStore. -func (cms cacheMultiStore) CacheMultiStore() CacheMultiStore { - return newCacheMultiStoreFromCMS(cms) -} - -// Implements MultiStore. -func (cms cacheMultiStore) GetStore(key StoreKey) Store { - return cms.stores[key].(Store) -} - -// Implements MultiStore. -func (cms cacheMultiStore) GetKVStore(key StoreKey) KVStore { - return cms.stores[key].(KVStore) -} - -// Implements MultiStore. -func (cms cacheMultiStore) GetKVStoreWithGas(meter sdk.GasMeter, config sdk.GasConfig, key StoreKey) KVStore { - return NewGasKVStore(meter, config, cms.GetKVStore(key)) -} diff --git a/store/cachemulti/store.go b/store/cachemulti/store.go new file mode 100644 index 000000000000..097014dd2ac1 --- /dev/null +++ b/store/cachemulti/store.go @@ -0,0 +1,140 @@ +package cachemulti + +import ( + "io" + + dbm "github.com/tendermint/tendermint/libs/db" + + "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/store/cache" + "github.com/cosmos/cosmos-sdk/store/dbadapter" + "github.com/cosmos/cosmos-sdk/store/gas" +) + +//---------------------------------------- +// Store + +// Store holds many cache-wrapped stores. +// Implements MultiStore. +// NOTE: a Store (and MultiStores in general) should never expose the +// keys for the substores. +type Store struct { + db types.CacheKVStore + stores map[types.StoreKey]types.CacheWrap + keysByName map[string]types.StoreKey + + traceWriter io.Writer + traceContext types.TraceContext +} + +var _ types.CacheMultiStore = Store{} + +func NewFromKVStore(store types.KVStore, stores map[types.StoreKey]types.CacheWrapper, keysByName map[string]types.StoreKey, traceWriter io.Writer, traceContext types.TraceContext) Store { + cms := Store{ + db: cache.NewStore(store), + stores: make(map[types.StoreKey]types.CacheWrap, len(stores)), + keysByName: keysByName, + traceWriter: traceWriter, + traceContext: traceContext, + } + + for key, store := range stores { + if cms.TracingEnabled() { + cms.stores[key] = store.CacheWrapWithTrace(cms.traceWriter, cms.traceContext) + } else { + cms.stores[key] = store.CacheWrap() + } + } + + return cms +} + +func NewStore(db dbm.DB, stores map[types.StoreKey]types.CacheWrapper, keysByName map[string]types.StoreKey, traceWriter io.Writer, traceContext types.TraceContext) Store { + return NewFromKVStore(dbadapter.Store{db}, stores, keysByName, traceWriter, traceContext) +} + +func newCacheMultiStoreFromCMS(cms Store) Store { + stores := make(map[types.StoreKey]types.CacheWrapper) + for k, v := range cms.stores { + stores[k] = v + } + return NewFromKVStore(cms.db, stores, nil, cms.traceWriter, cms.traceContext) +} + +// WithTracer sets the tracer for the MultiStore that the underlying +// stores will utilize to trace operations. A MultiStore is returned. +func (cms Store) WithTracer(w io.Writer) types.MultiStore { + cms.traceWriter = w + return cms +} + +// WithTracingContext updates the tracing context for the MultiStore by merging +// the given context with the existing context by key. Any existing keys will +// be overwritten. It is implied that the caller should update the context when +// necessary between tracing operations. It returns a modified MultiStore. +func (cms Store) WithTracingContext(tc types.TraceContext) types.MultiStore { + if cms.traceContext != nil { + for k, v := range tc { + cms.traceContext[k] = v + } + } else { + cms.traceContext = tc + } + + return cms +} + +// TracingEnabled returns if tracing is enabled for the MultiStore. +func (cms Store) TracingEnabled() bool { + return cms.traceWriter != nil +} + +// ResetTraceContext resets the current tracing context. +func (cms Store) ResetTraceContext() types.MultiStore { + cms.traceContext = nil + return cms +} + +// Implements Store. +func (cms Store) GetStoreType() types.StoreType { + return types.StoreTypeMulti +} + +// Implements CacheMultiStore. +func (cms Store) Write() { + cms.db.Write() + for _, store := range cms.stores { + store.Write() + } +} + +// Implements CacheWrapper. +func (cms Store) CacheWrap() types.CacheWrap { + return cms.CacheMultiStore().(types.CacheWrap) +} + +// CacheWrapWithTrace implements the CacheWrapper interface. +func (cms Store) CacheWrapWithTrace(_ io.Writer, _ types.TraceContext) types.CacheWrap { + return cms.CacheWrap() +} + +// Implements MultiStore. +func (cms Store) CacheMultiStore() types.CacheMultiStore { + return newCacheMultiStoreFromCMS(cms) +} + +// Implements MultiStore. +func (cms Store) GetStore(key types.StoreKey) types.Store { + return cms.stores[key].(types.Store) +} + +// Implements MultiStore. +func (cms Store) GetKVStore(key types.StoreKey) types.KVStore { + return cms.stores[key].(types.KVStore) +} + +// Implements MultiStore. +func (cms Store) GetKVStoreWithGas(meter types.GasMeter, config types.GasConfig, key types.StoreKey) types.KVStore { + return gas.NewStore(meter, config, cms.GetKVStore(key)) +} diff --git a/store/dbadapter/store.go b/store/dbadapter/store.go index 2d654c2394fd..f2edff2d2377 100644 --- a/store/dbadapter/store.go +++ b/store/dbadapter/store.go @@ -8,64 +8,40 @@ import ( "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/store/cache" + "github.com/cosmos/cosmos-sdk/store/trace" ) // Wrapper type for dbm.Db with implementation of KVStore -type dbStoreAdapter struct { +type Store struct { dbm.DB } // Implements Store. -func (dbStoreAdapter) GetStoreType() types.StoreType { +func (Store) GetStoreType() types.StoreType { return types.StoreTypeDB } // Implements KVStore. -func (dsa dbStoreAdapter) CacheWrap() types.CacheWrap { +func (dsa Store) CacheWrap() types.CacheWrap { return cache.NewStore(dsa) } // CacheWrapWithTrace implements the KVStore interface. -func (dsa dbStoreAdapter) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { - return NewCacheKVStore(NewTraceKVStore(dsa, w, tc)) +func (dsa Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { + return cache.NewStore(trace.NewStore(dsa, w, tc)) } // XXX: delete /* // Implements KVStore -func (dsa dbStoreAdapter) Prefix(prefix []byte) KVStore { +func (dsa Store) Prefix(prefix []byte) KVStore { return prefixStore{dsa, prefix} } // Implements KVStore -func (dsa dbStoreAdapter) Gas(meter GasMeter, config GasConfig) KVStore { +func (dsa Store) Gas(meter GasMeter, config GasConfig) KVStore { return NewGasKVStore(meter, config, dsa) } */ // dbm.DB implements KVStore so we can CacheKVStore it. -var _ types.KVStore = dbStoreAdapter{} - -//---------------------------------------- -// commitDBStoreWrapper should only be used for simulation/debugging, -// as it doesn't compute any commit hash, and it cannot load older state. - -// Wrapper type for dbm.Db with implementation of KVStore -type commitDBStoreAdapter struct { - dbStoreAdapter -} - -func (cdsa commitDBStoreAdapter) Commit() types.CommitID { - return types.CommitID{ - Version: -1, - Hash: []byte("FAKE_HASH"), - } -} - -func (cdsa commitDBStoreAdapter) LastCommitID() types.CommitID { - return types.CommitID{ - Version: -1, - Hash: []byte("FAKE_HASH"), - } -} - -func (cdsa commitDBStoreAdapter) SetPruning(_ types.PruningStrategy) {} +var _ types.KVStore = Store{} diff --git a/store/gas/gaskvstore.go b/store/gas/store.go similarity index 96% rename from store/gas/gaskvstore.go rename to store/gas/store.go index 8d3c88f4dfa1..931562ca6de0 100644 --- a/store/gas/gaskvstore.go +++ b/store/gas/store.go @@ -16,9 +16,9 @@ type Store struct { parent types.KVStore } -// NewGasKVStore returns a reference to a new GasKVStore. +// NewStore returns a reference to a new GasKVStore. // nolint -func NewGasKVStore(gasMeter types.GasMeter, gasConfig types.GasConfig, parent types.KVStore) *Store { +func NewStore(gasMeter types.GasMeter, gasConfig types.GasConfig, parent types.KVStore) *Store { kvs := &Store{ gasMeter: gasMeter, gasConfig: gasConfig, diff --git a/store/gas/gaskvstore_test.go b/store/gas/store_test.go similarity index 58% rename from store/gas/gaskvstore_test.go rename to store/gas/store_test.go index 24626952accb..dd86630cefe1 100644 --- a/store/gas/gaskvstore_test.go +++ b/store/gas/store_test.go @@ -1,38 +1,44 @@ package gas import ( + "fmt" "testing" - "github.com/tendermint/iavl" dbm "github.com/tendermint/tendermint/libs/db" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/dbadapter" + "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" ) -func newGasKVStore() KVStore { - meter := sdk.NewGasMeter(1000) - mem := dbStoreAdapter{dbm.NewMemDB()} - return NewGasKVStore(meter, sdk.KVGasConfig(), mem) +func newGasKVStore() types.KVStore { + meter := types.NewGasMeter(1000) + mem := dbadapter.Store{dbm.NewMemDB()} + return NewStore(meter, types.KVGasConfig(), mem) } +func bz(s string) []byte { return []byte(s) } + +func keyFmt(i int) []byte { return bz(fmt.Sprintf("key%0.8d", i)) } +func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } + func TestGasKVStoreBasic(t *testing.T) { - mem := dbStoreAdapter{dbm.NewMemDB()} - meter := sdk.NewGasMeter(1000) - st := NewGasKVStore(meter, sdk.KVGasConfig(), mem) + mem := dbadapter.Store{dbm.NewMemDB()} + meter := types.NewGasMeter(1000) + st := NewStore(meter, types.KVGasConfig(), mem) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") st.Set(keyFmt(1), valFmt(1)) require.Equal(t, valFmt(1), st.Get(keyFmt(1))) st.Delete(keyFmt(1)) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") - require.Equal(t, meter.GasConsumed(), sdk.Gas(193)) + require.Equal(t, meter.GasConsumed(), types.Gas(193)) } func TestGasKVStoreIterator(t *testing.T) { - mem := dbStoreAdapter{dbm.NewMemDB()} - meter := sdk.NewGasMeter(1000) - st := NewGasKVStore(meter, sdk.KVGasConfig(), mem) + mem := dbadapter.Store{dbm.NewMemDB()} + meter := types.NewGasMeter(1000) + st := NewStore(meter, types.KVGasConfig(), mem) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") require.Empty(t, st.Get(keyFmt(2)), "Expected `key2` to be empty") st.Set(keyFmt(1), valFmt(1)) @@ -50,36 +56,39 @@ func TestGasKVStoreIterator(t *testing.T) { iterator.Next() require.False(t, iterator.Valid()) require.Panics(t, iterator.Next) - require.Equal(t, meter.GasConsumed(), sdk.Gas(384)) + require.Equal(t, meter.GasConsumed(), types.Gas(384)) } func TestGasKVStoreOutOfGasSet(t *testing.T) { - mem := dbStoreAdapter{dbm.NewMemDB()} - meter := sdk.NewGasMeter(0) - st := NewGasKVStore(meter, sdk.KVGasConfig(), mem) + mem := dbadapter.Store{dbm.NewMemDB()} + meter := types.NewGasMeter(0) + st := NewStore(meter, types.KVGasConfig(), mem) require.Panics(t, func() { st.Set(keyFmt(1), valFmt(1)) }, "Expected out-of-gas") } func TestGasKVStoreOutOfGasIterator(t *testing.T) { - mem := dbStoreAdapter{dbm.NewMemDB()} - meter := sdk.NewGasMeter(200) - st := NewGasKVStore(meter, sdk.KVGasConfig(), mem) + mem := dbadapter.Store{dbm.NewMemDB()} + meter := types.NewGasMeter(200) + st := NewStore(meter, types.KVGasConfig(), mem) st.Set(keyFmt(1), valFmt(1)) iterator := st.Iterator(nil, nil) iterator.Next() require.Panics(t, func() { iterator.Value() }, "Expected out-of-gas") } -func testGasKVStoreWrap(t *testing.T, store KVStore) { - meter := sdk.NewGasMeter(10000) +// XXX: delete +// Not important since we are not method chaining to wrap stores +/* +func testGasKVStoreWrap(t *testing.T, store types.KVStore) { + meter := types.NewGasMeter(10000) - store = store.Gas(meter, sdk.GasConfig{HasCost: 10}) + store = NewStore(meter, types.GasConfig{HasCost: 10}, store) require.Equal(t, uint64(0), meter.GasConsumed()) store.Has([]byte("key")) require.Equal(t, uint64(10), meter.GasConsumed()) - store = store.Gas(meter, sdk.GasConfig{HasCost: 20}) + store = NewStore(meter, types.GasConfig{HasCost: 20}, store) store.Has([]byte("key")) require.Equal(t, uint64(40), meter.GasConsumed()) @@ -97,10 +106,11 @@ func TestGasKVStoreWrap(t *testing.T) { pref := st.Prefix([]byte("prefix")) testGasKVStoreWrap(t, pref) - dsa := dbStoreAdapter{dbm.NewMemDB()} + dsa := dbadapter.Store{dbm.NewMemDB()} testGasKVStoreWrap(t, dsa) ts := newTransientStore() testGasKVStoreWrap(t, ts) } +*/ diff --git a/store/iavl/iavlstore.go b/store/iavl/store.go similarity index 74% rename from store/iavl/iavlstore.go rename to store/iavl/store.go index 24d676ff105a..f4dd61b1bbe3 100644 --- a/store/iavl/iavlstore.go +++ b/store/iavl/store.go @@ -1,4 +1,4 @@ -package store +package iavl import ( "fmt" @@ -11,7 +11,10 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/store/cache" + "github.com/cosmos/cosmos-sdk/store/trace" ) const ( @@ -19,25 +22,25 @@ const ( ) // load the iavl store -func LoadIAVLStore(db dbm.DB, id CommitID, pruning sdk.PruningStrategy) (CommitStore, error) { +func LoadStore(db dbm.DB, id types.CommitID, pruning types.PruningStrategy) (types.CommitStore, error) { tree := iavl.NewMutableTree(db, defaultIAVLCacheSize) _, err := tree.LoadVersion(id.Version) if err != nil { return nil, err } - iavl := newIAVLStore(tree, int64(0), int64(0)) + iavl := UnsafeNewStore(tree, int64(0), int64(0)) iavl.SetPruning(pruning) return iavl, nil } //---------------------------------------- -var _ KVStore = (*iavlStore)(nil) -var _ CommitStore = (*iavlStore)(nil) -var _ Queryable = (*iavlStore)(nil) +var _ types.KVStore = (*Store)(nil) +var _ types.CommitStore = (*Store)(nil) +var _ types.Queryable = (*Store)(nil) -// iavlStore Implements KVStore and CommitStore. -type iavlStore struct { +// Store Implements types.KVStore and CommitStore. +type Store struct { // The underlying tree. tree *iavl.MutableTree @@ -57,8 +60,8 @@ type iavlStore struct { // CONTRACT: tree should be fully loaded. // nolint: unparam -func newIAVLStore(tree *iavl.MutableTree, numRecent int64, storeEvery int64) *iavlStore { - st := &iavlStore{ +func UnsafeNewStore(tree *iavl.MutableTree, numRecent int64, storeEvery int64) *Store { + st := &Store{ tree: tree, numRecent: numRecent, storeEvery: storeEvery, @@ -67,7 +70,7 @@ func newIAVLStore(tree *iavl.MutableTree, numRecent int64, storeEvery int64) *ia } // Implements Committer. -func (st *iavlStore) Commit() CommitID { +func (st *Store) Commit() types.CommitID { // Save a new version. hash, version, err := st.tree.SaveVersion() if err != nil { @@ -87,92 +90,94 @@ func (st *iavlStore) Commit() CommitID { } } - return CommitID{ + return types.CommitID{ Version: version, Hash: hash, } } // Implements Committer. -func (st *iavlStore) LastCommitID() CommitID { - return CommitID{ +func (st *Store) LastCommitID() types.CommitID { + return types.CommitID{ Version: st.tree.Version(), Hash: st.tree.Hash(), } } // Implements Committer. -func (st *iavlStore) SetPruning(pruning sdk.PruningStrategy) { +func (st *Store) SetPruning(pruning types.PruningStrategy) { switch pruning { - case sdk.PruneEverything: + case types.PruneEverything: st.numRecent = 0 st.storeEvery = 0 - case sdk.PruneNothing: + case types.PruneNothing: st.storeEvery = 1 - case sdk.PruneSyncable: + case types.PruneSyncable: st.numRecent = 100 st.storeEvery = 10000 } } // VersionExists returns whether or not a given version is stored. -func (st *iavlStore) VersionExists(version int64) bool { +func (st *Store) VersionExists(version int64) bool { return st.tree.VersionExists(version) } // Implements Store. -func (st *iavlStore) GetStoreType() StoreType { - return sdk.StoreTypeIAVL +func (st *Store) GetStoreType() types.StoreType { + return types.StoreTypeIAVL } // Implements Store. -func (st *iavlStore) CacheWrap() CacheWrap { - return NewCacheKVStore(st) +func (st *Store) CacheWrap() types.CacheWrap { + return cache.NewStore(st) } // CacheWrapWithTrace implements the Store interface. -func (st *iavlStore) CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap { - return NewCacheKVStore(NewTraceKVStore(st, w, tc)) +func (st *Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { + return cache.NewStore(trace.NewStore(st, w, tc)) } -// Implements KVStore. -func (st *iavlStore) Set(key, value []byte) { +// Implements types.KVStore. +func (st *Store) Set(key, value []byte) { st.tree.Set(key, value) } -// Implements KVStore. -func (st *iavlStore) Get(key []byte) (value []byte) { +// Implements types.KVStore. +func (st *Store) Get(key []byte) (value []byte) { _, v := st.tree.Get(key) return v } -// Implements KVStore. -func (st *iavlStore) Has(key []byte) (exists bool) { +// Implements types.KVStore. +func (st *Store) Has(key []byte) (exists bool) { return st.tree.Has(key) } -// Implements KVStore. -func (st *iavlStore) Delete(key []byte) { +// Implements types.KVStore. +func (st *Store) Delete(key []byte) { st.tree.Remove(key) } -// Implements KVStore -func (st *iavlStore) Prefix(prefix []byte) KVStore { +// XXX: delete +/* +// Implements types.KVStore +func (st *Store) Prefix(prefix []byte) types.KVStore { return prefixStore{st, prefix} } -// Implements KVStore -func (st *iavlStore) Gas(meter GasMeter, config GasConfig) KVStore { +// Implements types.KVStore +func (st *Store) Gas(meter types.GasMeter, config types.GasConfig) types.KVStore { return NewGasKVStore(meter, config, st) } - -// Implements KVStore. -func (st *iavlStore) Iterator(start, end []byte) Iterator { +*/ +// Implements types.KVStore. +func (st *Store) Iterator(start, end []byte) types.Iterator { return newIAVLIterator(st.tree.ImmutableTree, start, end, true) } -// Implements KVStore. -func (st *iavlStore) ReverseIterator(start, end []byte) Iterator { +// Implements types.KVStore. +func (st *Store) ReverseIterator(start, end []byte) types.Iterator { return newIAVLIterator(st.tree.ImmutableTree, start, end, false) } @@ -197,10 +202,10 @@ func getHeight(tree *iavl.MutableTree, req abci.RequestQuery) int64 { // If latest-1 is not present, use latest (which must be present) // if you care to have the latest data to see a tx results, you must // explicitly set the height you want to see -func (st *iavlStore) Query(req abci.RequestQuery) (res abci.ResponseQuery) { +func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) { if len(req.Data) == 0 { msg := "Query cannot be zero length" - return sdk.ErrTxDecode(msg).QueryResult() + return types.ErrTxDecode(msg).QueryResult() } tree := st.tree @@ -245,14 +250,14 @@ func (st *iavlStore) Query(req abci.RequestQuery) (res abci.ResponseQuery) { } case "/subspace": - var KVs []KVPair + var KVs []types.KVPair subspace := req.Data res.Key = subspace - iterator := sdk.KVStorePrefixIterator(st, subspace) + iterator := types.KVStorePrefixIterator(st, subspace) for ; iterator.Valid(); iterator.Next() { - KVs = append(KVs, KVPair{Key: iterator.Key(), Value: iterator.Value()}) + KVs = append(KVs, types.KVPair{Key: iterator.Key(), Value: iterator.Value()}) } iterator.Close() @@ -260,7 +265,7 @@ func (st *iavlStore) Query(req abci.RequestQuery) (res abci.ResponseQuery) { default: msg := fmt.Sprintf("Unexpected Query path: %v", req.Path) - return sdk.ErrUnknownRequest(msg).QueryResult() + return types.ErrUnknownRequest(msg).QueryResult() } return @@ -268,7 +273,7 @@ func (st *iavlStore) Query(req abci.RequestQuery) (res abci.ResponseQuery) { //---------------------------------------- -// Implements Iterator. +// Implements types.Iterator. type iavlIterator struct { // Underlying store tree *iavl.ImmutableTree @@ -297,7 +302,7 @@ type iavlIterator struct { value []byte // The current value } -var _ Iterator = (*iavlIterator)(nil) +var _ types.Iterator = (*iavlIterator)(nil) // newIAVLIterator will create a new iavlIterator. // CONTRACT: Caller must release the iavlIterator, as each one creates a new @@ -339,12 +344,12 @@ func (iter *iavlIterator) initRoutine() { close(iter.initCh) } -// Implements Iterator. +// Implements types.Iterator. func (iter *iavlIterator) Domain() (start, end []byte) { return iter.start, iter.end } -// Implements Iterator. +// Implements types.Iterator. func (iter *iavlIterator) Valid() bool { iter.waitInit() iter.mtx.Lock() @@ -354,7 +359,7 @@ func (iter *iavlIterator) Valid() bool { return validity } -// Implements Iterator. +// Implements types.Iterator. func (iter *iavlIterator) Next() { iter.waitInit() iter.mtx.Lock() @@ -364,7 +369,7 @@ func (iter *iavlIterator) Next() { iter.mtx.Unlock() } -// Implements Iterator. +// Implements types.Iterator. func (iter *iavlIterator) Key() []byte { iter.waitInit() iter.mtx.Lock() @@ -375,7 +380,7 @@ func (iter *iavlIterator) Key() []byte { return key } -// Implements Iterator. +// Implements types.Iterator. func (iter *iavlIterator) Value() []byte { iter.waitInit() iter.mtx.Lock() @@ -386,7 +391,7 @@ func (iter *iavlIterator) Value() []byte { return val } -// Implements Iterator. +// Implements types.Iterator. func (iter *iavlIterator) Close() { close(iter.quitCh) } @@ -430,3 +435,13 @@ func (iter *iavlIterator) assertIsValid(unlockMutex bool) { panic("invalid iterator") } } + +//---------------------------------------- +func cp(bz []byte) (ret []byte) { + if bz == nil { + return nil + } + ret = make([]byte, len(bz)) + copy(ret, bz) + return ret +} diff --git a/store/iavl/iavlstore_test.go b/store/iavl/store_test.go similarity index 88% rename from store/iavl/iavlstore_test.go rename to store/iavl/store_test.go index 4d8605e4e198..f7d7da30794f 100644 --- a/store/iavl/iavlstore_test.go +++ b/store/iavl/store_test.go @@ -1,4 +1,4 @@ -package store +package iavl import ( "fmt" @@ -11,7 +11,7 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types" ) var ( @@ -29,7 +29,7 @@ var ( ) // make a tree with data from above and save it -func newAlohaTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, CommitID) { +func newAlohaTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, types.CommitID) { tree := iavl.NewMutableTree(db, cacheSize) for k, v := range treeData { tree.Set([]byte(k), []byte(v)) @@ -41,13 +41,13 @@ func newAlohaTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, CommitID) { } hash, ver, err := tree.SaveVersion() require.Nil(t, err) - return tree, CommitID{ver, hash} + return tree, types.CommitID{ver, hash} } func TestIAVLStoreGetSetHasDelete(t *testing.T) { db := dbm.NewMemDB() tree, _ := newAlohaTree(t, db) - iavlStore := newIAVLStore(tree, numRecent, storeEvery) + iavlStore := UnsafeNewStore(tree, numRecent, storeEvery) key := "hello" @@ -72,7 +72,7 @@ func TestIAVLStoreGetSetHasDelete(t *testing.T) { func TestIAVLIterator(t *testing.T) { db := dbm.NewMemDB() tree, _ := newAlohaTree(t, db) - iavlStore := newIAVLStore(tree, numRecent, storeEvery) + iavlStore := UnsafeNewStore(tree, numRecent, storeEvery) iter := iavlStore.Iterator([]byte("aloha"), []byte("hellz")) expected := []string{"aloha", "hello"} var i int @@ -145,7 +145,7 @@ func TestIAVLIterator(t *testing.T) { func TestIAVLReverseIterator(t *testing.T) { db := dbm.NewMemDB() tree := iavl.NewMutableTree(db, cacheSize) - iavlStore := newIAVLStore(tree, numRecent, storeEvery) + iavlStore := UnsafeNewStore(tree, numRecent, storeEvery) iavlStore.Set([]byte{0x00}, []byte("0")) iavlStore.Set([]byte{0x00, 0x00}, []byte("0 0")) @@ -176,7 +176,7 @@ func TestIAVLReverseIterator(t *testing.T) { func TestIAVLPrefixIterator(t *testing.T) { db := dbm.NewMemDB() tree := iavl.NewMutableTree(db, cacheSize) - iavlStore := newIAVLStore(tree, numRecent, storeEvery) + iavlStore := UnsafeNewStore(tree, numRecent, storeEvery) iavlStore.Set([]byte("test1"), []byte("test1")) iavlStore.Set([]byte("test2"), []byte("test2")) @@ -190,7 +190,7 @@ func TestIAVLPrefixIterator(t *testing.T) { var i int - iter := sdk.KVStorePrefixIterator(iavlStore, []byte("test")) + iter := types.KVStorePrefixIterator(iavlStore, []byte("test")) expected := []string{"test1", "test2", "test3"} for i = 0; iter.Valid(); iter.Next() { expectedKey := expected[i] @@ -202,7 +202,7 @@ func TestIAVLPrefixIterator(t *testing.T) { iter.Close() require.Equal(t, len(expected), i) - iter = sdk.KVStorePrefixIterator(iavlStore, []byte{byte(55), byte(255), byte(255)}) + iter = types.KVStorePrefixIterator(iavlStore, []byte{byte(55), byte(255), byte(255)}) expected2 := [][]byte{ {byte(55), byte(255), byte(255), byte(0)}, {byte(55), byte(255), byte(255), byte(1)}, @@ -218,7 +218,7 @@ func TestIAVLPrefixIterator(t *testing.T) { iter.Close() require.Equal(t, len(expected), i) - iter = sdk.KVStorePrefixIterator(iavlStore, []byte{byte(255), byte(255)}) + iter = types.KVStorePrefixIterator(iavlStore, []byte{byte(255), byte(255)}) expected2 = [][]byte{ {byte(255), byte(255), byte(0)}, {byte(255), byte(255), byte(1)}, @@ -238,7 +238,7 @@ func TestIAVLPrefixIterator(t *testing.T) { func TestIAVLReversePrefixIterator(t *testing.T) { db := dbm.NewMemDB() tree := iavl.NewMutableTree(db, cacheSize) - iavlStore := newIAVLStore(tree, numRecent, storeEvery) + iavlStore := UnsafeNewStore(tree, numRecent, storeEvery) iavlStore.Set([]byte("test1"), []byte("test1")) iavlStore.Set([]byte("test2"), []byte("test2")) @@ -252,7 +252,7 @@ func TestIAVLReversePrefixIterator(t *testing.T) { var i int - iter := sdk.KVStoreReversePrefixIterator(iavlStore, []byte("test")) + iter := types.KVStoreReversePrefixIterator(iavlStore, []byte("test")) expected := []string{"test3", "test2", "test1"} for i = 0; iter.Valid(); iter.Next() { expectedKey := expected[i] @@ -263,7 +263,7 @@ func TestIAVLReversePrefixIterator(t *testing.T) { } require.Equal(t, len(expected), i) - iter = sdk.KVStoreReversePrefixIterator(iavlStore, []byte{byte(55), byte(255), byte(255)}) + iter = types.KVStoreReversePrefixIterator(iavlStore, []byte{byte(55), byte(255), byte(255)}) expected2 := [][]byte{ {byte(55), byte(255), byte(255), byte(255)}, {byte(55), byte(255), byte(255), byte(1)}, @@ -278,7 +278,7 @@ func TestIAVLReversePrefixIterator(t *testing.T) { } require.Equal(t, len(expected), i) - iter = sdk.KVStoreReversePrefixIterator(iavlStore, []byte{byte(255), byte(255)}) + iter = types.KVStoreReversePrefixIterator(iavlStore, []byte{byte(255), byte(255)}) expected2 = [][]byte{ {byte(255), byte(255), byte(255)}, {byte(255), byte(255), byte(1)}, @@ -294,7 +294,7 @@ func TestIAVLReversePrefixIterator(t *testing.T) { require.Equal(t, len(expected), i) } -func nextVersion(iavl *iavlStore) { +func nextVersion(iavl *Store) { key := []byte(fmt.Sprintf("Key for tree: %d", iavl.LastCommitID().Version)) value := []byte(fmt.Sprintf("Value for tree: %d", iavl.LastCommitID().Version)) iavl.Set(key, value) @@ -357,7 +357,7 @@ type pruneState struct { func testPruning(t *testing.T, numRecent int64, storeEvery int64, states []pruneState) { db := dbm.NewMemDB() tree := iavl.NewMutableTree(db, cacheSize) - iavlStore := newIAVLStore(tree, numRecent, storeEvery) + iavlStore := UnsafeNewStore(tree, numRecent, storeEvery) for step, state := range states { for _, ver := range state.stored { require.True(t, iavlStore.VersionExists(ver), @@ -376,7 +376,7 @@ func testPruning(t *testing.T, numRecent int64, storeEvery int64, states []prune func TestIAVLNoPrune(t *testing.T) { db := dbm.NewMemDB() tree := iavl.NewMutableTree(db, cacheSize) - iavlStore := newIAVLStore(tree, numRecent, int64(1)) + iavlStore := UnsafeNewStore(tree, numRecent, int64(1)) nextVersion(iavlStore) for i := 1; i < 100; i++ { for j := 1; j <= i; j++ { @@ -391,7 +391,7 @@ func TestIAVLNoPrune(t *testing.T) { func TestIAVLPruneEverything(t *testing.T) { db := dbm.NewMemDB() tree := iavl.NewMutableTree(db, cacheSize) - iavlStore := newIAVLStore(tree, int64(0), int64(0)) + iavlStore := UnsafeNewStore(tree, int64(0), int64(0)) nextVersion(iavlStore) for i := 1; i < 100; i++ { for j := 1; j < i; j++ { @@ -409,19 +409,19 @@ func TestIAVLPruneEverything(t *testing.T) { func TestIAVLStoreQuery(t *testing.T) { db := dbm.NewMemDB() tree := iavl.NewMutableTree(db, cacheSize) - iavlStore := newIAVLStore(tree, numRecent, storeEvery) + iavlStore := UnsafeNewStore(tree, numRecent, storeEvery) k1, v1 := []byte("key1"), []byte("val1") k2, v2 := []byte("key2"), []byte("val2") v3 := []byte("val3") ksub := []byte("key") - KVs0 := []KVPair{} - KVs1 := []KVPair{ + KVs0 := []types.KVPair{} + KVs1 := []types.KVPair{ {Key: k1, Value: v1}, {Key: k2, Value: v2}, } - KVs2 := []KVPair{ + KVs2 := []types.KVPair{ {Key: k1, Value: v3}, {Key: k2, Value: v2}, } @@ -436,7 +436,7 @@ func TestIAVLStoreQuery(t *testing.T) { // query subspace before anything set qres := iavlStore.Query(querySub) - require.Equal(t, uint32(sdk.CodeOK), qres.Code) + require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, valExpSubEmpty, qres.Value) // set data @@ -445,24 +445,24 @@ func TestIAVLStoreQuery(t *testing.T) { // set data without commit, doesn't show up qres = iavlStore.Query(query) - require.Equal(t, uint32(sdk.CodeOK), qres.Code) + require.Equal(t, uint32(types.CodeOK), qres.Code) require.Nil(t, qres.Value) // commit it, but still don't see on old version cid = iavlStore.Commit() qres = iavlStore.Query(query) - require.Equal(t, uint32(sdk.CodeOK), qres.Code) + require.Equal(t, uint32(types.CodeOK), qres.Code) require.Nil(t, qres.Value) // but yes on the new version query.Height = cid.Version qres = iavlStore.Query(query) - require.Equal(t, uint32(sdk.CodeOK), qres.Code) + require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, v1, qres.Value) // and for the subspace qres = iavlStore.Query(querySub) - require.Equal(t, uint32(sdk.CodeOK), qres.Code) + require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, valExpSub1, qres.Value) // modify @@ -471,28 +471,28 @@ func TestIAVLStoreQuery(t *testing.T) { // query will return old values, as height is fixed qres = iavlStore.Query(query) - require.Equal(t, uint32(sdk.CodeOK), qres.Code) + require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, v1, qres.Value) // update to latest in the query and we are happy query.Height = cid.Version qres = iavlStore.Query(query) - require.Equal(t, uint32(sdk.CodeOK), qres.Code) + require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, v3, qres.Value) query2 := abci.RequestQuery{Path: "/key", Data: k2, Height: cid.Version} qres = iavlStore.Query(query2) - require.Equal(t, uint32(sdk.CodeOK), qres.Code) + require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, v2, qres.Value) // and for the subspace qres = iavlStore.Query(querySub) - require.Equal(t, uint32(sdk.CodeOK), qres.Code) + require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, valExpSub2, qres.Value) // default (height 0) will show latest -1 query0 := abci.RequestQuery{Path: "/key", Data: k1} qres = iavlStore.Query(query0) - require.Equal(t, uint32(sdk.CodeOK), qres.Code) + require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, v1, qres.Value) } @@ -505,8 +505,8 @@ func BenchmarkIAVLIteratorNext(b *testing.B) { value := cmn.RandBytes(50) tree.Set(key, value) } - iavlStore := newIAVLStore(tree, numRecent, storeEvery) - iterators := make([]Iterator, b.N/treeSize) + iavlStore := UnsafeNewStore(tree, numRecent, storeEvery) + iterators := make([]types.Iterator, b.N/treeSize) for i := 0; i < len(iterators); i++ { iterators[i] = iavlStore.Iterator([]byte{0}, []byte{255, 255, 255, 255, 255}) } diff --git a/store/iavl/wire.go b/store/iavl/wire.go new file mode 100644 index 000000000000..43173f3e7895 --- /dev/null +++ b/store/iavl/wire.go @@ -0,0 +1,7 @@ +package iavl + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +var cdc = codec.New() diff --git a/store/list/list.go b/store/list/list.go index b38f11b803ee..e9770d97c6af 100644 --- a/store/list/list.go +++ b/store/list/list.go @@ -1,4 +1,4 @@ -package store +package list import ( "fmt" diff --git a/store/list/list_test.go b/store/list/list_test.go index 396e2d1a1996..6b1cbf7bf045 100644 --- a/store/list/list_test.go +++ b/store/list/list_test.go @@ -1,13 +1,34 @@ -package store +package list import ( "math/rand" "testing" + dbm "github.com/tendermint/tendermint/libs/db" + "github.com/tendermint/tendermint/libs/log" + + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/rootmulti" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" ) +type S struct { + I uint64 + B bool +} + +func defaultComponents(key sdk.StoreKey) (sdk.Context, *codec.Codec) { + db := dbm.NewMemDB() + cms := rootmulti.NewStore(db) + cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) + cms.LoadLatestVersion() + ctx := sdk.NewContext(cms, abci.Header{}, false, log.NewNopLogger()) + cdc := codec.New() + return ctx, cdc +} func TestList(t *testing.T) { key := sdk.NewKVStoreKey("test") ctx, cdc := defaultComponents(key) diff --git a/store/prefix/prefixstore.go b/store/prefix/prefixstore.go index a7881bc7e816..68b8598bc821 100644 --- a/store/prefix/prefixstore.go +++ b/store/prefix/prefixstore.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/store/cache" + "github.com/cosmos/cosmos-sdk/store/trace" ) var _ types.KVStore = Store{} @@ -20,6 +21,13 @@ type Store struct { prefix []byte } +func NewStore(parent types.KVStore, prefix []byte) Store { + return Store{ + parent: parent, + prefix: prefix, + } +} + func cloneAppend(bz []byte, tail []byte) (res []byte) { res = make([]byte, len(bz)+len(tail)) copy(res, bz) @@ -47,7 +55,7 @@ func (s Store) CacheWrap() types.CacheWrap { // CacheWrapWithTrace implements the KVStore interface. func (s Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { - return cache.NewStore(NewTraceKVStore(s, w, tc)) + return cache.NewStore(trace.NewStore(s, w, tc)) } // Implements KVStore diff --git a/store/prefix/prefixstore_test.go b/store/prefix/prefixstore_test.go index db3e0ebf2c6f..0d014c9a4f1a 100644 --- a/store/prefix/prefixstore_test.go +++ b/store/prefix/prefixstore_test.go @@ -6,12 +6,24 @@ import ( "github.com/stretchr/testify/require" - "github.com/tendermint/iavl" + tiavl "github.com/tendermint/iavl" dbm "github.com/tendermint/tendermint/libs/db" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/dbadapter" + "github.com/cosmos/cosmos-sdk/store/gas" + "github.com/cosmos/cosmos-sdk/store/iavl" + "github.com/cosmos/cosmos-sdk/types" ) +// copied from iavl/store_test.go +var ( + cacheSize = 100 + numRecent int64 = 5 + storeEvery int64 = 3 +) + +func bz(s string) []byte { return []byte(s) } + type kvpair struct { key []byte value []byte @@ -30,7 +42,7 @@ func genRandomKVPairs(t *testing.T) []kvpair { return kvps } -func setRandomKVPairs(t *testing.T, store KVStore) []kvpair { +func setRandomKVPairs(t *testing.T, store types.KVStore) []kvpair { kvps := genRandomKVPairs(t) for _, kvp := range kvps { store.Set(kvp.key, kvp.value) @@ -38,9 +50,9 @@ func setRandomKVPairs(t *testing.T, store KVStore) []kvpair { return kvps } -func testPrefixStore(t *testing.T, baseStore KVStore, prefix []byte) { - prefixStore := baseStore.Prefix(prefix) - prefixPrefixStore := prefixStore.Prefix([]byte("prefix")) +func testPrefixStore(t *testing.T, baseStore types.KVStore, prefix []byte) { + prefixStore := NewStore(baseStore, prefix) + prefixPrefixStore := NewStore(prefixStore, []byte("prefix")) require.Panics(t, func() { prefixStore.Get(nil) }) require.Panics(t, func() { prefixStore.Set(nil, []byte{}) }) @@ -75,36 +87,30 @@ func testPrefixStore(t *testing.T, baseStore KVStore, prefix []byte) { func TestIAVLStorePrefix(t *testing.T) { db := dbm.NewMemDB() - tree := iavl.NewMutableTree(db, cacheSize) - iavlStore := newIAVLStore(tree, numRecent, storeEvery) + tree := tiavl.NewMutableTree(db, cacheSize) + iavlStore := iavl.UnsafeNewStore(tree, numRecent, storeEvery) testPrefixStore(t, iavlStore, []byte("test")) } -func TestCacheKVStorePrefix(t *testing.T) { - cacheStore := newCacheKVStore() - - testPrefixStore(t, cacheStore, []byte("test")) -} - func TestGasKVStorePrefix(t *testing.T) { - meter := sdk.NewGasMeter(100000000) - mem := dbStoreAdapter{dbm.NewMemDB()} - gasStore := NewGasKVStore(meter, sdk.KVGasConfig(), mem) + meter := types.NewGasMeter(100000000) + mem := dbadapter.Store{dbm.NewMemDB()} + gasStore := gas.NewStore(meter, types.KVGasConfig(), mem) testPrefixStore(t, gasStore, []byte("test")) } func TestPrefixStoreIterate(t *testing.T) { db := dbm.NewMemDB() - baseStore := dbStoreAdapter{db} + baseStore := dbadapter.Store{db} prefix := []byte("test") - prefixStore := baseStore.Prefix(prefix) + prefixStore := NewStore(baseStore, prefix) setRandomKVPairs(t, prefixStore) - bIter := sdk.KVStorePrefixIterator(baseStore, prefix) - pIter := sdk.KVStorePrefixIterator(prefixStore, nil) + bIter := types.KVStorePrefixIterator(baseStore, prefix) + pIter := types.KVStorePrefixIterator(prefixStore, nil) for bIter.Valid() && pIter.Valid() { require.Equal(t, bIter.Key(), append(prefix, pIter.Key()...)) @@ -143,11 +149,11 @@ func TestCloneAppend(t *testing.T) { func TestPrefixStoreIteratorEdgeCase(t *testing.T) { db := dbm.NewMemDB() - baseStore := dbStoreAdapter{db} + baseStore := dbadapter.Store{db} // overflow in cpIncr prefix := []byte{0xAA, 0xFF, 0xFF} - prefixStore := baseStore.Prefix(prefix) + prefixStore := NewStore(baseStore, prefix) // ascending order baseStore.Set([]byte{0xAA, 0xFF, 0xFE}, []byte{}) @@ -173,11 +179,11 @@ func TestPrefixStoreIteratorEdgeCase(t *testing.T) { func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { db := dbm.NewMemDB() - baseStore := dbStoreAdapter{db} + baseStore := dbadapter.Store{db} // overflow in cpIncr prefix := []byte{0xAA, 0xFF, 0xFF} - prefixStore := baseStore.Prefix(prefix) + prefixStore := NewStore(baseStore, prefix) // descending order baseStore.Set([]byte{0xAB, 0x00, 0x00}, []byte{}) @@ -201,11 +207,11 @@ func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { iter.Close() db = dbm.NewMemDB() - baseStore = dbStoreAdapter{db} + baseStore = dbadapter.Store{db} // underflow in cpDecr prefix = []byte{0xAA, 0x00, 0x00} - prefixStore = baseStore.Prefix(prefix) + prefixStore = NewStore(baseStore, prefix) baseStore.Set([]byte{0xAB, 0x00, 0x01, 0x00, 0x00}, []byte{}) baseStore.Set([]byte{0xAB, 0x00, 0x01, 0x00}, []byte{}) @@ -230,9 +236,9 @@ func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { // Tests below are ported from https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db_test.go -func mockStoreWithStuff() sdk.KVStore { +func mockStoreWithStuff() types.KVStore { db := dbm.NewMemDB() - store := dbStoreAdapter{db} + store := dbadapter.Store{db} // Under "key" prefix store.Set(bz("key"), bz("value")) store.Set(bz("key1"), bz("value1")) @@ -246,55 +252,55 @@ func mockStoreWithStuff() sdk.KVStore { return store } -func checkValue(t *testing.T, store sdk.KVStore, key []byte, expected []byte) { +func checkValue(t *testing.T, store types.KVStore, key []byte, expected []byte) { bz := store.Get(key) require.Equal(t, expected, bz) } -func checkValid(t *testing.T, itr sdk.Iterator, expected bool) { +func checkValid(t *testing.T, itr types.Iterator, expected bool) { valid := itr.Valid() require.Equal(t, expected, valid) } -func checkNext(t *testing.T, itr sdk.Iterator, expected bool) { +func checkNext(t *testing.T, itr types.Iterator, expected bool) { itr.Next() valid := itr.Valid() require.Equal(t, expected, valid) } -func checkDomain(t *testing.T, itr sdk.Iterator, start, end []byte) { +func checkDomain(t *testing.T, itr types.Iterator, start, end []byte) { ds, de := itr.Domain() require.Equal(t, start, ds) require.Equal(t, end, de) } -func checkItem(t *testing.T, itr sdk.Iterator, key, value []byte) { +func checkItem(t *testing.T, itr types.Iterator, key, value []byte) { require.Exactly(t, key, itr.Key()) require.Exactly(t, value, itr.Value()) } -func checkInvalid(t *testing.T, itr sdk.Iterator) { +func checkInvalid(t *testing.T, itr types.Iterator) { checkValid(t, itr, false) checkKeyPanics(t, itr) checkValuePanics(t, itr) checkNextPanics(t, itr) } -func checkKeyPanics(t *testing.T, itr sdk.Iterator) { +func checkKeyPanics(t *testing.T, itr types.Iterator) { require.Panics(t, func() { itr.Key() }) } -func checkValuePanics(t *testing.T, itr sdk.Iterator) { +func checkValuePanics(t *testing.T, itr types.Iterator) { require.Panics(t, func() { itr.Value() }) } -func checkNextPanics(t *testing.T, itr sdk.Iterator) { +func checkNextPanics(t *testing.T, itr types.Iterator) { require.Panics(t, func() { itr.Next() }) } func TestPrefixDBSimple(t *testing.T) { store := mockStoreWithStuff() - pstore := store.Prefix(bz("key")) + pstore := NewStore(store, bz("key")) checkValue(t, pstore, bz("key"), nil) checkValue(t, pstore, bz(""), bz("value")) @@ -312,7 +318,7 @@ func TestPrefixDBSimple(t *testing.T) { func TestPrefixDBIterator1(t *testing.T) { store := mockStoreWithStuff() - pstore := store.Prefix(bz("key")) + pstore := NewStore(store, bz("key")) itr := pstore.Iterator(nil, nil) checkDomain(t, itr, nil, nil) @@ -330,7 +336,7 @@ func TestPrefixDBIterator1(t *testing.T) { func TestPrefixDBIterator2(t *testing.T) { store := mockStoreWithStuff() - pstore := store.Prefix(bz("key")) + pstore := NewStore(store, bz("key")) itr := pstore.Iterator(nil, bz("")) checkDomain(t, itr, nil, bz("")) @@ -340,7 +346,7 @@ func TestPrefixDBIterator2(t *testing.T) { func TestPrefixDBIterator3(t *testing.T) { store := mockStoreWithStuff() - pstore := store.Prefix(bz("key")) + pstore := NewStore(store, bz("key")) itr := pstore.Iterator(bz(""), nil) checkDomain(t, itr, bz(""), nil) @@ -358,7 +364,7 @@ func TestPrefixDBIterator3(t *testing.T) { func TestPrefixDBIterator4(t *testing.T) { store := mockStoreWithStuff() - pstore := store.Prefix(bz("key")) + pstore := NewStore(store, bz("key")) itr := pstore.Iterator(bz(""), bz("")) checkDomain(t, itr, bz(""), bz("")) @@ -368,7 +374,7 @@ func TestPrefixDBIterator4(t *testing.T) { func TestPrefixDBReverseIterator1(t *testing.T) { store := mockStoreWithStuff() - pstore := store.Prefix(bz("key")) + pstore := NewStore(store, bz("key")) itr := pstore.ReverseIterator(nil, nil) checkDomain(t, itr, nil, nil) @@ -386,7 +392,7 @@ func TestPrefixDBReverseIterator1(t *testing.T) { func TestPrefixDBReverseIterator2(t *testing.T) { store := mockStoreWithStuff() - pstore := store.Prefix(bz("key")) + pstore := NewStore(store, bz("key")) itr := pstore.ReverseIterator(bz(""), nil) checkDomain(t, itr, bz(""), nil) @@ -404,7 +410,7 @@ func TestPrefixDBReverseIterator2(t *testing.T) { func TestPrefixDBReverseIterator3(t *testing.T) { store := mockStoreWithStuff() - pstore := store.Prefix(bz("key")) + pstore := NewStore(store, bz("key")) itr := pstore.ReverseIterator(nil, bz("")) checkDomain(t, itr, nil, bz("")) @@ -414,7 +420,7 @@ func TestPrefixDBReverseIterator3(t *testing.T) { func TestPrefixDBReverseIterator4(t *testing.T) { store := mockStoreWithStuff() - pstore := store.Prefix(bz("key")) + pstore := NewStore(store, bz("key")) itr := pstore.ReverseIterator(bz(""), bz("")) checkInvalid(t, itr) diff --git a/store/queue/queue.go b/store/queue/queue.go index f41ecb7d7a19..0f65d0375ba3 100644 --- a/store/queue/queue.go +++ b/store/queue/queue.go @@ -1,8 +1,12 @@ package store +// TODO: make it independent from list +/* import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/store/list" ) // Key for the top element position in the queue @@ -13,7 +17,7 @@ func TopKey() []byte { // Queue is a List wrapper that provides queue-like functions // It panics when the element type cannot be (un/)marshalled by the codec type Queue struct { - List List + List list.List } // NewQueue constructs new Queue @@ -86,3 +90,4 @@ func (m Queue) Flush(ptr interface{}, fn func() bool) { } m.setTop(i) } +*/ diff --git a/store/queue/queue_test.go b/store/queue/queue_test.go index 58e96f56a19e..a71adbfed29a 100644 --- a/store/queue/queue_test.go +++ b/store/queue/queue_test.go @@ -1,5 +1,6 @@ package store +/* import ( "testing" @@ -100,3 +101,4 @@ func TestKeys(t *testing.T) { require.Nil(t, err) require.Equal(t, top, queue.getTop()) } +*/ diff --git a/store/rootmulti/dbadapter.go b/store/rootmulti/dbadapter.go new file mode 100644 index 000000000000..4a93efc8698d --- /dev/null +++ b/store/rootmulti/dbadapter.go @@ -0,0 +1,31 @@ +package rootmulti + +import ( + "github.com/cosmos/cosmos-sdk/store/dbadapter" + "github.com/cosmos/cosmos-sdk/types" +) + +//---------------------------------------- +// commitDBStoreWrapper should only be used for simulation/debugging, +// as it doesn't compute any commit hash, and it cannot load older state. + +// Wrapper type for dbm.Db with implementation of KVStore +type commitDBStoreAdapter struct { + dbadapter.Store +} + +func (cdsa commitDBStoreAdapter) Commit() types.CommitID { + return types.CommitID{ + Version: -1, + Hash: []byte("FAKE_HASH"), + } +} + +func (cdsa commitDBStoreAdapter) LastCommitID() types.CommitID { + return types.CommitID{ + Version: -1, + Hash: []byte("FAKE_HASH"), + } +} + +func (cdsa commitDBStoreAdapter) SetPruning(_ types.PruningStrategy) {} diff --git a/store/rootmulti/multistoreproof.go b/store/rootmulti/multistoreproof.go index 96f0a48373ea..6657a6007a66 100644 --- a/store/rootmulti/multistoreproof.go +++ b/store/rootmulti/multistoreproof.go @@ -1,4 +1,4 @@ -package store +package rootmulti import ( "bytes" diff --git a/store/rootmulti/multistoreproof_test.go b/store/rootmulti/multistoreproof_test.go index db3b65cad53d..51c974d45554 100644 --- a/store/rootmulti/multistoreproof_test.go +++ b/store/rootmulti/multistoreproof_test.go @@ -1,19 +1,21 @@ -package store +package rootmulti import ( "testing" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" dbm "github.com/tendermint/tendermint/libs/db" + + "github.com/cosmos/cosmos-sdk/store/iavl" ) func TestVerifyIAVLStoreQueryProof(t *testing.T) { // Create main tree for testing. db := dbm.NewMemDB() - iStore, err := LoadIAVLStore(db, CommitID{}, sdk.PruneNothing) - store := iStore.(*iavlStore) + iStore, err := iavl.LoadStore(db, types.CommitID{}, types.PruneNothing) + store := iStore.(*iavl.Store) require.Nil(t, err) store.Set([]byte("MYKEY"), []byte("MYVALUE")) cid := store.Commit() @@ -55,13 +57,13 @@ func TestVerifyIAVLStoreQueryProof(t *testing.T) { func TestVerifyMultiStoreQueryProof(t *testing.T) { // Create main tree for testing. db := dbm.NewMemDB() - store := NewCommitMultiStore(db) - iavlStoreKey := sdk.NewKVStoreKey("iavlStoreKey") + store := NewStore(db) + iavlStoreKey := types.NewKVStoreKey("iavlStoreKey") - store.MountStoreWithDB(iavlStoreKey, sdk.StoreTypeIAVL, nil) + store.MountStoreWithDB(iavlStoreKey, types.StoreTypeIAVL, nil) store.LoadVersion(0) - iavlStore := store.GetCommitStore(iavlStoreKey).(*iavlStore) + iavlStore := store.GetCommitStore(iavlStoreKey).(*iavl.Store) iavlStore.Set([]byte("MYKEY"), []byte("MYVALUE")) cid := store.Commit() @@ -110,10 +112,10 @@ func TestVerifyMultiStoreQueryProof(t *testing.T) { func TestVerifyMultiStoreQueryProofEmptyStore(t *testing.T) { // Create main tree for testing. db := dbm.NewMemDB() - store := NewCommitMultiStore(db) - iavlStoreKey := sdk.NewKVStoreKey("iavlStoreKey") + store := NewStore(db) + iavlStoreKey := types.NewKVStoreKey("iavlStoreKey") - store.MountStoreWithDB(iavlStoreKey, sdk.StoreTypeIAVL, nil) + store.MountStoreWithDB(iavlStoreKey, types.StoreTypeIAVL, nil) store.LoadVersion(0) cid := store.Commit() // Commit with empty iavl store. @@ -139,13 +141,13 @@ func TestVerifyMultiStoreQueryProofEmptyStore(t *testing.T) { func TestVerifyMultiStoreQueryProofAbsence(t *testing.T) { // Create main tree for testing. db := dbm.NewMemDB() - store := NewCommitMultiStore(db) - iavlStoreKey := sdk.NewKVStoreKey("iavlStoreKey") + store := NewStore(db) + iavlStoreKey := types.NewKVStoreKey("iavlStoreKey") - store.MountStoreWithDB(iavlStoreKey, sdk.StoreTypeIAVL, nil) + store.MountStoreWithDB(iavlStoreKey, types.StoreTypeIAVL, nil) store.LoadVersion(0) - iavlStore := store.GetCommitStore(iavlStoreKey).(*iavlStore) + iavlStore := store.GetCommitStore(iavlStoreKey).(*iavl.Store) iavlStore.Set([]byte("MYKEY"), []byte("MYVALUE")) cid := store.Commit() // Commit with empty iavl store. diff --git a/store/rootmulti/rootmultistore.go b/store/rootmulti/rootmultistore.go index c309f9e9b28a..ee252e66d902 100644 --- a/store/rootmulti/rootmultistore.go +++ b/store/rootmulti/rootmultistore.go @@ -1,4 +1,4 @@ -package store +package rootmulti import ( "fmt" @@ -10,7 +10,12 @@ import ( "github.com/tendermint/tendermint/crypto/tmhash" dbm "github.com/tendermint/tendermint/libs/db" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/cachemulti" + "github.com/cosmos/cosmos-sdk/store/dbadapter" + "github.com/cosmos/cosmos-sdk/store/iavl" + "github.com/cosmos/cosmos-sdk/store/trace" + "github.com/cosmos/cosmos-sdk/store/transient" + "github.com/cosmos/cosmos-sdk/types" ) const ( @@ -18,36 +23,36 @@ const ( commitInfoKeyFmt = "s/%d" // s/ ) -// rootMultiStore is composed of many CommitStores. Name contrasts with +// Store is composed of many CommitStores. Name contrasts with // cacheMultiStore which is for cache-wrapping other MultiStores. It implements // the CommitMultiStore interface. -type rootMultiStore struct { +type Store struct { db dbm.DB - lastCommitID CommitID - pruning sdk.PruningStrategy - storesParams map[StoreKey]storeParams - stores map[StoreKey]CommitStore - keysByName map[string]StoreKey + lastCommitID types.CommitID + pruning types.PruningStrategy + storesParams map[types.StoreKey]storeParams + stores map[types.StoreKey]types.CommitStore + keysByName map[string]types.StoreKey traceWriter io.Writer - traceContext TraceContext + traceContext types.TraceContext } -var _ CommitMultiStore = (*rootMultiStore)(nil) -var _ Queryable = (*rootMultiStore)(nil) +var _ types.CommitMultiStore = (*Store)(nil) +var _ types.Queryable = (*Store)(nil) // nolint -func NewCommitMultiStore(db dbm.DB) *rootMultiStore { - return &rootMultiStore{ +func NewStore(db dbm.DB) *Store { + return &Store{ db: db, - storesParams: make(map[StoreKey]storeParams), - stores: make(map[StoreKey]CommitStore), - keysByName: make(map[string]StoreKey), + storesParams: make(map[types.StoreKey]storeParams), + stores: make(map[types.StoreKey]types.CommitStore), + keysByName: make(map[string]types.StoreKey), } } // Implements CommitMultiStore -func (rs *rootMultiStore) SetPruning(pruning sdk.PruningStrategy) { +func (rs *Store) SetPruning(pruning types.PruningStrategy) { rs.pruning = pruning for _, substore := range rs.stores { substore.SetPruning(pruning) @@ -55,20 +60,20 @@ func (rs *rootMultiStore) SetPruning(pruning sdk.PruningStrategy) { } // Implements Store. -func (rs *rootMultiStore) GetStoreType() StoreType { - return sdk.StoreTypeMulti +func (rs *Store) GetStoreType() types.StoreType { + return types.StoreTypeMulti } // Implements CommitMultiStore. -func (rs *rootMultiStore) MountStoreWithDB(key StoreKey, typ StoreType, db dbm.DB) { +func (rs *Store) MountStoreWithDB(key types.StoreKey, typ types.StoreType, db dbm.DB) { if key == nil { panic("MountIAVLStore() key cannot be nil") } if _, ok := rs.storesParams[key]; ok { - panic(fmt.Sprintf("rootMultiStore duplicate store key %v", key)) + panic(fmt.Sprintf("Store duplicate store key %v", key)) } if _, ok := rs.keysByName[key.Name()]; ok { - panic(fmt.Sprintf("rootMultiStore duplicate store key name %v", key)) + panic(fmt.Sprintf("Store duplicate store key name %v", key)) } rs.storesParams[key] = storeParams{ key: key, @@ -79,36 +84,36 @@ func (rs *rootMultiStore) MountStoreWithDB(key StoreKey, typ StoreType, db dbm.D } // Implements CommitMultiStore. -func (rs *rootMultiStore) GetCommitStore(key StoreKey) CommitStore { +func (rs *Store) GetCommitStore(key types.StoreKey) types.CommitStore { return rs.stores[key] } // Implements CommitMultiStore. -func (rs *rootMultiStore) GetCommitKVStore(key StoreKey) CommitKVStore { - return rs.stores[key].(CommitKVStore) +func (rs *Store) GetCommitKVStore(key types.StoreKey) types.CommitKVStore { + return rs.stores[key].(types.CommitKVStore) } // Implements CommitMultiStore. -func (rs *rootMultiStore) LoadLatestVersion() error { +func (rs *Store) LoadLatestVersion() error { ver := getLatestVersion(rs.db) return rs.LoadVersion(ver) } // Implements CommitMultiStore. -func (rs *rootMultiStore) LoadVersion(ver int64) error { +func (rs *Store) LoadVersion(ver int64) error { // Special logic for version 0 if ver == 0 { for key, storeParams := range rs.storesParams { - id := CommitID{} + id := types.CommitID{} store, err := rs.loadCommitStoreFromParams(key, id, storeParams) if err != nil { - return fmt.Errorf("failed to load rootMultiStore: %v", err) + return fmt.Errorf("failed to load Store: %v", err) } rs.stores[key] = store } - rs.lastCommitID = CommitID{} + rs.lastCommitID = types.CommitID{} return nil } // Otherwise, version is 1 or greater @@ -120,15 +125,15 @@ func (rs *rootMultiStore) LoadVersion(ver int64) error { } // Convert StoreInfos slice to map - infos := make(map[StoreKey]storeInfo) + infos := make(map[types.StoreKey]storeInfo) for _, storeInfo := range cInfo.StoreInfos { infos[rs.nameToKey(storeInfo.Name)] = storeInfo } // Load each Store - var newStores = make(map[StoreKey]CommitStore) + var newStores = make(map[types.StoreKey]types.CommitStore) for key, storeParams := range rs.storesParams { - var id CommitID + var id types.CommitID info, ok := infos[key] if ok { id = info.Core.CommitID @@ -136,7 +141,7 @@ func (rs *rootMultiStore) LoadVersion(ver int64) error { store, err := rs.loadCommitStoreFromParams(key, id, storeParams) if err != nil { - return fmt.Errorf("failed to load rootMultiStore: %v", err) + return fmt.Errorf("failed to load Store: %v", err) } newStores[key] = store } @@ -149,7 +154,7 @@ func (rs *rootMultiStore) LoadVersion(ver int64) error { // WithTracer sets the tracer for the MultiStore that the underlying // stores will utilize to trace operations. A MultiStore is returned. -func (rs *rootMultiStore) WithTracer(w io.Writer) MultiStore { +func (rs *Store) WithTracer(w io.Writer) types.MultiStore { rs.traceWriter = w return rs } @@ -158,7 +163,7 @@ func (rs *rootMultiStore) WithTracer(w io.Writer) MultiStore { // the given context with the existing context by key. Any existing keys will // be overwritten. It is implied that the caller should update the context when // necessary between tracing operations. It returns a modified MultiStore. -func (rs *rootMultiStore) WithTracingContext(tc TraceContext) MultiStore { +func (rs *Store) WithTracingContext(tc types.TraceContext) types.MultiStore { if rs.traceContext != nil { for k, v := range tc { rs.traceContext[k] = v @@ -171,12 +176,12 @@ func (rs *rootMultiStore) WithTracingContext(tc TraceContext) MultiStore { } // TracingEnabled returns if tracing is enabled for the MultiStore. -func (rs *rootMultiStore) TracingEnabled() bool { +func (rs *Store) TracingEnabled() bool { return rs.traceWriter != nil } // ResetTraceContext resets the current tracing context. -func (rs *rootMultiStore) ResetTraceContext() MultiStore { +func (rs *Store) ResetTraceContext() types.MultiStore { rs.traceContext = nil return rs } @@ -185,12 +190,12 @@ func (rs *rootMultiStore) ResetTraceContext() MultiStore { // +CommitStore // Implements Committer/CommitStore. -func (rs *rootMultiStore) LastCommitID() CommitID { +func (rs *Store) LastCommitID() types.CommitID { return rs.lastCommitID } // Implements Committer/CommitStore. -func (rs *rootMultiStore) Commit() CommitID { +func (rs *Store) Commit() types.CommitID { // Commit stores. version := rs.lastCommitID.Version + 1 @@ -203,7 +208,7 @@ func (rs *rootMultiStore) Commit() CommitID { batch.Write() // Prepare for next version. - commitID := CommitID{ + commitID := types.CommitID{ Version: version, Hash: commitInfo.Hash(), } @@ -212,12 +217,12 @@ func (rs *rootMultiStore) Commit() CommitID { } // Implements CacheWrapper/Store/CommitStore. -func (rs *rootMultiStore) CacheWrap() CacheWrap { - return rs.CacheMultiStore().(CacheWrap) +func (rs *Store) CacheWrap() types.CacheWrap { + return rs.CacheMultiStore().(types.CacheWrap) } // CacheWrapWithTrace implements the CacheWrapper interface. -func (rs *rootMultiStore) CacheWrapWithTrace(_ io.Writer, _ TraceContext) CacheWrap { +func (rs *Store) CacheWrapWithTrace(_ io.Writer, _ types.TraceContext) types.CacheWrap { return rs.CacheWrap() } @@ -225,13 +230,17 @@ func (rs *rootMultiStore) CacheWrapWithTrace(_ io.Writer, _ TraceContext) CacheW // +MultiStore // Implements MultiStore. -func (rs *rootMultiStore) CacheMultiStore() CacheMultiStore { - return newCacheMultiStoreFromRMS(rs) +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) } // Implements MultiStore. // If the store does not exist, panics. -func (rs *rootMultiStore) GetStore(key StoreKey) Store { +func (rs *Store) GetStore(key types.StoreKey) types.Store { store := rs.stores[key] if store == nil { panic("Could not load store " + key.String()) @@ -240,14 +249,14 @@ func (rs *rootMultiStore) GetStore(key StoreKey) Store { } // GetKVStore implements the MultiStore interface. If tracing is enabled on the -// rootMultiStore, a wrapped TraceKVStore will be returned with the given +// Store, a wrapped TraceKVStore will be returned with the given // tracer, otherwise, the original KVStore will be returned. // If the store does not exist, panics. -func (rs *rootMultiStore) GetKVStore(key StoreKey) KVStore { - store := rs.stores[key].(KVStore) +func (rs *Store) GetKVStore(key types.StoreKey) types.KVStore { + store := rs.stores[key].(types.KVStore) if rs.TracingEnabled() { - store = NewTraceKVStore(store, rs.traceWriter, rs.traceContext) + store = trace.NewStore(store, rs.traceWriter, rs.traceContext) } return store @@ -260,7 +269,7 @@ func (rs *rootMultiStore) GetKVStore(key StoreKey) KVStore { // This is not exposed to the extensions (which will need the // StoreKey), but is useful in main, and particularly app.Query, // in order to convert human strings into CommitStores. -func (rs *rootMultiStore) getStoreByName(name string) Store { +func (rs *Store) getStoreByName(name string) types.Store { key := rs.keysByName[name] if key == nil { return nil @@ -274,7 +283,7 @@ func (rs *rootMultiStore) getStoreByName(name string) Store { // modified to remove the substore prefix. // Ie. `req.Path` here is `//`, and trimmed to `/` for the substore. // TODO: add proof for `multistore -> substore`. -func (rs *rootMultiStore) Query(req abci.RequestQuery) abci.ResponseQuery { +func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery { // Query just routes this to a substore. path := req.Path storeName, subpath, err := parsePath(path) @@ -285,12 +294,12 @@ func (rs *rootMultiStore) Query(req abci.RequestQuery) abci.ResponseQuery { store := rs.getStoreByName(storeName) if store == nil { msg := fmt.Sprintf("no such store: %s", storeName) - return sdk.ErrUnknownRequest(msg).QueryResult() + return types.ErrUnknownRequest(msg).QueryResult() } - queryable, ok := store.(Queryable) + queryable, ok := store.(types.Queryable) if !ok { msg := fmt.Sprintf("store %s doesn't support queries", storeName) - return sdk.ErrUnknownRequest(msg).QueryResult() + return types.ErrUnknownRequest(msg).QueryResult() } // trim the path and make the query @@ -302,12 +311,12 @@ func (rs *rootMultiStore) Query(req abci.RequestQuery) abci.ResponseQuery { } if res.Proof == nil || len(res.Proof.Ops) == 0 { - return sdk.ErrInternal("substore proof was nil/empty when it should never be").QueryResult() + return types.ErrInternal("substore proof was nil/empty when it should never be").QueryResult() } commitInfo, errMsg := getCommitInfo(rs.db, res.Height) if errMsg != nil { - return sdk.ErrInternal(errMsg.Error()).QueryResult() + return types.ErrInternal(errMsg.Error()).QueryResult() } // Restore origin path and append proof op. @@ -324,9 +333,9 @@ func (rs *rootMultiStore) Query(req abci.RequestQuery) abci.ResponseQuery { // parsePath expects a format like /[/] // Must start with /, subpath may be empty // Returns error if it doesn't start with / -func parsePath(path string) (storeName string, subpath string, err sdk.Error) { +func parsePath(path string) (storeName string, subpath string, err types.Error) { if !strings.HasPrefix(path, "/") { - err = sdk.ErrUnknownRequest(fmt.Sprintf("invalid path: %s", path)) + err = types.ErrUnknownRequest(fmt.Sprintf("invalid path: %s", path)) return } @@ -342,7 +351,7 @@ func parsePath(path string) (storeName string, subpath string, err sdk.Error) { //---------------------------------------- -func (rs *rootMultiStore) loadCommitStoreFromParams(key sdk.StoreKey, id CommitID, params storeParams) (store CommitStore, err error) { +func (rs *Store) loadCommitStoreFromParams(key types.StoreKey, id types.CommitID, params storeParams) (store types.CommitStore, err error) { var db dbm.DB if params.db != nil { db = dbm.NewPrefixDB(params.db, []byte("s/_/")) @@ -350,30 +359,30 @@ func (rs *rootMultiStore) loadCommitStoreFromParams(key sdk.StoreKey, id CommitI db = dbm.NewPrefixDB(rs.db, []byte("s/k:"+params.key.Name()+"/")) } switch params.typ { - case sdk.StoreTypeMulti: + case types.StoreTypeMulti: panic("recursive MultiStores not yet supported") // TODO: id? // return NewCommitMultiStore(db, id) - case sdk.StoreTypeIAVL: - store, err = LoadIAVLStore(db, id, rs.pruning) + case types.StoreTypeIAVL: + store, err = iavl.LoadStore(db, id, rs.pruning) return - case sdk.StoreTypeDB: - store = commitDBStoreAdapter{dbStoreAdapter{db}} + case types.StoreTypeDB: + store = commitDBStoreAdapter{dbadapter.Store{db}} return - case sdk.StoreTypeTransient: - _, ok := key.(*sdk.TransientStoreKey) + case types.StoreTypeTransient: + _, ok := key.(*types.TransientStoreKey) if !ok { err = fmt.Errorf("invalid StoreKey for StoreTypeTransient: %s", key.String()) return } - store = newTransientStore() + store = transient.NewStore() return default: panic(fmt.Sprintf("unrecognized store type %v", params.typ)) } } -func (rs *rootMultiStore) nameToKey(name string) StoreKey { +func (rs *Store) nameToKey(name string) types.StoreKey { for key := range rs.storesParams { if key.Name() == name { return key @@ -386,9 +395,9 @@ func (rs *rootMultiStore) nameToKey(name string) StoreKey { // storeParams type storeParams struct { - key StoreKey + key types.StoreKey db dbm.DB - typ StoreType + typ types.StoreType } //---------------------------------------- @@ -415,8 +424,8 @@ func (ci commitInfo) Hash() []byte { return merkle.SimpleHashFromMap(m) } -func (ci commitInfo) CommitID() CommitID { - return CommitID{ +func (ci commitInfo) CommitID() types.CommitID { + return types.CommitID{ Version: ci.Version, Hash: ci.Hash(), } @@ -426,7 +435,7 @@ func (ci commitInfo) CommitID() CommitID { // storeInfo // storeInfo contains the name and core reference for an -// underlying store. It is the leaf of the rootMultiStores top +// underlying store. It is the leaf of the Stores top // level simple merkle tree. type storeInfo struct { Name string @@ -435,7 +444,7 @@ type storeInfo struct { type storeCore struct { // StoreType StoreType - CommitID CommitID + CommitID types.CommitID // ... maybe add more state } @@ -480,14 +489,14 @@ func setLatestVersion(batch dbm.Batch, version int64) { } // Commits each store and returns a new commitInfo. -func commitStores(version int64, storeMap map[StoreKey]CommitStore) commitInfo { +func commitStores(version int64, storeMap map[types.StoreKey]types.CommitStore) commitInfo { storeInfos := make([]storeInfo, 0, len(storeMap)) for key, store := range storeMap { // Commit commitID := store.Commit() - if store.GetStoreType() == sdk.StoreTypeTransient { + if store.GetStoreType() == types.StoreTypeTransient { continue } @@ -513,14 +522,14 @@ func getCommitInfo(db dbm.DB, ver int64) (commitInfo, error) { cInfoKey := fmt.Sprintf(commitInfoKeyFmt, ver) cInfoBytes := db.Get([]byte(cInfoKey)) if cInfoBytes == nil { - return commitInfo{}, fmt.Errorf("failed to get rootMultiStore: no data") + return commitInfo{}, fmt.Errorf("failed to get Store: no data") } var cInfo commitInfo err := cdc.UnmarshalBinaryLengthPrefixed(cInfoBytes, &cInfo) if err != nil { - return commitInfo{}, fmt.Errorf("failed to get rootMultiStore: %v", err) + return commitInfo{}, fmt.Errorf("failed to get Store: %v", err) } return cInfo, nil diff --git a/store/rootmulti/rootmultistore_test.go b/store/rootmulti/rootmultistore_test.go index cd555d6f2d5a..e042e0026f1b 100644 --- a/store/rootmulti/rootmultistore_test.go +++ b/store/rootmulti/rootmultistore_test.go @@ -1,4 +1,4 @@ -package store +package rootmulti import ( "testing" @@ -8,32 +8,32 @@ import ( "github.com/tendermint/tendermint/crypto/merkle" dbm "github.com/tendermint/tendermint/libs/db" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types" ) const useDebugDB = false func TestStoreType(t *testing.T) { db := dbm.NewMemDB() - store := NewCommitMultiStore(db) + store := NewStore(db) store.MountStoreWithDB( - sdk.NewKVStoreKey("store1"), sdk.StoreTypeIAVL, db) + types.NewKVStoreKey("store1"), types.StoreTypeIAVL, db) } func TestStoreMount(t *testing.T) { db := dbm.NewMemDB() - store := NewCommitMultiStore(db) + store := NewStore(db) - key1 := sdk.NewKVStoreKey("store1") - key2 := sdk.NewKVStoreKey("store2") - dup1 := sdk.NewKVStoreKey("store1") + key1 := types.NewKVStoreKey("store1") + key2 := types.NewKVStoreKey("store2") + dup1 := types.NewKVStoreKey("store1") - require.NotPanics(t, func() { store.MountStoreWithDB(key1, sdk.StoreTypeIAVL, db) }) - require.NotPanics(t, func() { store.MountStoreWithDB(key2, sdk.StoreTypeIAVL, db) }) + require.NotPanics(t, func() { store.MountStoreWithDB(key1, types.StoreTypeIAVL, db) }) + require.NotPanics(t, func() { store.MountStoreWithDB(key2, types.StoreTypeIAVL, db) }) - require.Panics(t, func() { store.MountStoreWithDB(key1, sdk.StoreTypeIAVL, db) }) - require.Panics(t, func() { store.MountStoreWithDB(dup1, sdk.StoreTypeIAVL, db) }) + require.Panics(t, func() { store.MountStoreWithDB(key1, types.StoreTypeIAVL, db) }) + require.Panics(t, func() { store.MountStoreWithDB(dup1, types.StoreTypeIAVL, db) }) } func TestMultistoreCommitLoad(t *testing.T) { @@ -46,7 +46,7 @@ func TestMultistoreCommitLoad(t *testing.T) { require.Nil(t, err) // New store has empty last commit. - commitID := CommitID{} + commitID := types.CommitID{} checkStore(t, store, commitID, commitID) // Make sure we can get stores by name. @@ -137,11 +137,11 @@ func TestMultiStoreQuery(t *testing.T) { require.Nil(t, garbage) // Set and commit data in one store. - store1 := multi.getStoreByName("store1").(KVStore) + store1 := multi.getStoreByName("store1").(types.KVStore) store1.Set(k, v) // ... and another. - store2 := multi.getStoreByName("store2").(KVStore) + store2 := multi.getStoreByName("store2").(types.KVStore) store2.Set(k2, v2) // Commit the multistore. @@ -156,68 +156,68 @@ func TestMultiStoreQuery(t *testing.T) { // Test bad path. query := abci.RequestQuery{Path: "/key", Data: k, Height: ver} qres := multi.Query(query) - require.EqualValues(t, sdk.CodeUnknownRequest, qres.Code) - require.EqualValues(t, sdk.CodespaceRoot, qres.Codespace) + require.EqualValues(t, types.CodeUnknownRequest, qres.Code) + require.EqualValues(t, types.CodespaceRoot, qres.Codespace) query.Path = "h897fy32890rf63296r92" qres = multi.Query(query) - require.EqualValues(t, sdk.CodeUnknownRequest, qres.Code) - require.EqualValues(t, sdk.CodespaceRoot, qres.Codespace) + require.EqualValues(t, types.CodeUnknownRequest, qres.Code) + require.EqualValues(t, types.CodespaceRoot, qres.Codespace) // Test invalid store name. query.Path = "/garbage/key" qres = multi.Query(query) - require.EqualValues(t, sdk.CodeUnknownRequest, qres.Code) - require.EqualValues(t, sdk.CodespaceRoot, qres.Codespace) + require.EqualValues(t, types.CodeUnknownRequest, qres.Code) + require.EqualValues(t, types.CodespaceRoot, qres.Codespace) // Test valid query with data. query.Path = "/store1/key" qres = multi.Query(query) - require.EqualValues(t, sdk.CodeOK, qres.Code) + require.EqualValues(t, types.CodeOK, qres.Code) require.Equal(t, v, qres.Value) // Test valid but empty query. query.Path = "/store2/key" query.Prove = true qres = multi.Query(query) - require.EqualValues(t, sdk.CodeOK, qres.Code) + require.EqualValues(t, types.CodeOK, qres.Code) require.Nil(t, qres.Value) // Test store2 data. query.Data = k2 qres = multi.Query(query) - require.EqualValues(t, sdk.CodeOK, qres.Code) + require.EqualValues(t, types.CodeOK, qres.Code) require.Equal(t, v2, qres.Value) } //----------------------------------------------------------------------- // utils -func newMultiStoreWithMounts(db dbm.DB) *rootMultiStore { - store := NewCommitMultiStore(db) +func newMultiStoreWithMounts(db dbm.DB) *Store { + store := NewStore(db) store.MountStoreWithDB( - sdk.NewKVStoreKey("store1"), sdk.StoreTypeIAVL, nil) + types.NewKVStoreKey("store1"), types.StoreTypeIAVL, nil) store.MountStoreWithDB( - sdk.NewKVStoreKey("store2"), sdk.StoreTypeIAVL, nil) + types.NewKVStoreKey("store2"), types.StoreTypeIAVL, nil) store.MountStoreWithDB( - sdk.NewKVStoreKey("store3"), sdk.StoreTypeIAVL, nil) + types.NewKVStoreKey("store3"), types.StoreTypeIAVL, nil) return store } -func checkStore(t *testing.T, store *rootMultiStore, expect, got CommitID) { +func checkStore(t *testing.T, store *Store, expect, got types.CommitID) { require.Equal(t, expect, got) require.Equal(t, expect, store.LastCommitID()) } -func getExpectedCommitID(store *rootMultiStore, ver int64) CommitID { - return CommitID{ +func getExpectedCommitID(store *Store, ver int64) types.CommitID { + return types.CommitID{ Version: ver, Hash: hashStores(store.stores), } } -func hashStores(stores map[StoreKey]CommitStore) []byte { +func hashStores(stores map[types.StoreKey]types.CommitStore) []byte { m := make(map[string][]byte, len(stores)) for key, store := range stores { name := key.Name() diff --git a/store/rootmulti/wire.go b/store/rootmulti/wire.go new file mode 100644 index 000000000000..8d6d936160ff --- /dev/null +++ b/store/rootmulti/wire.go @@ -0,0 +1,7 @@ +package rootmulti + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +var cdc = codec.New() diff --git a/store/store.go b/store/store.go new file mode 100644 index 000000000000..458c3472e402 --- /dev/null +++ b/store/store.go @@ -0,0 +1,13 @@ +package store + +import ( + dbm "github.com/tendermint/tendermint/libs/db" + + "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/store/rootmulti" +) + +func NewCommitMultiStore(db dbm.DB) types.CommitMultiStore { + return rootmulti.NewStore(db) +} diff --git a/store/trace/store.go b/store/trace/store.go index 042d3c087601..c3b6e9ae62b1 100644 --- a/store/trace/store.go +++ b/store/trace/store.go @@ -18,13 +18,13 @@ const ( ) type ( - // TraceKVStore implements the KVStore interface with tracing enabled. + // Store implements the KVStore interface with tracing enabled. // Operations are traced on each core KVStore call and written to the // underlying io.writer. // // TODO: Should we use a buffered writer and implement Commit on - // TraceKVStore? - TraceKVStore struct { + // Store? + Store struct { parent types.KVStore writer io.Writer context types.TraceContext @@ -42,15 +42,15 @@ type ( } ) -// NewTraceKVStore returns a reference to a new traceKVStore given a parent +// NewStore returns a reference to a new traceKVStore given a parent // KVStore implementation and a buffered writer. -func NewTraceKVStore(parent types.KVStore, writer io.Writer, tc types.TraceContext) *TraceKVStore { - return &TraceKVStore{parent: parent, writer: writer, context: tc} +func NewStore(parent types.KVStore, writer io.Writer, tc types.TraceContext) *Store { + return &Store{parent: parent, writer: writer, context: tc} } // Get implements the KVStore interface. It traces a read operation and // delegates a Get call to the parent KVStore. -func (tkv *TraceKVStore) Get(key []byte) []byte { +func (tkv *Store) Get(key []byte) []byte { value := tkv.parent.Get(key) writeOperation(tkv.writer, readOp, tkv.context, key, value) @@ -59,51 +59,51 @@ func (tkv *TraceKVStore) Get(key []byte) []byte { // Set implements the KVStore interface. It traces a write operation and // delegates the Set call to the parent KVStore. -func (tkv *TraceKVStore) Set(key []byte, value []byte) { +func (tkv *Store) Set(key []byte, value []byte) { writeOperation(tkv.writer, writeOp, tkv.context, key, value) tkv.parent.Set(key, value) } // Delete implements the KVStore interface. It traces a write operation and // delegates the Delete call to the parent KVStore. -func (tkv *TraceKVStore) Delete(key []byte) { +func (tkv *Store) Delete(key []byte) { writeOperation(tkv.writer, deleteOp, tkv.context, key, nil) tkv.parent.Delete(key) } // Has implements the KVStore interface. It delegates the Has call to the // parent KVStore. -func (tkv *TraceKVStore) Has(key []byte) bool { +func (tkv *Store) Has(key []byte) bool { return tkv.parent.Has(key) } // XXX: delete /* // Prefix implements the KVStore interface. -func (tkv *TraceKVStore) Prefix(prefix []byte) KVStore { +func (tkv *Store) Prefix(prefix []byte) KVStore { return prefixStore{tkv, prefix} } // Gas implements the KVStore interface. -func (tkv *TraceKVStore) Gas(meter GasMeter, config GasConfig) KVStore { +func (tkv *Store) Gas(meter GasMeter, config GasConfig) KVStore { return NewGasKVStore(meter, config, tkv.parent) } */ // Iterator implements the KVStore interface. It delegates the Iterator call // the to the parent KVStore. -func (tkv *TraceKVStore) Iterator(start, end []byte) types.Iterator { +func (tkv *Store) Iterator(start, end []byte) types.Iterator { return tkv.iterator(start, end, true) } // ReverseIterator implements the KVStore interface. It delegates the // ReverseIterator call the to the parent KVStore. -func (tkv *TraceKVStore) ReverseIterator(start, end []byte) types.Iterator { +func (tkv *Store) ReverseIterator(start, end []byte) types.Iterator { return tkv.iterator(start, end, false) } // iterator facilitates iteration over a KVStore. It delegates the necessary // calls to it's parent KVStore. -func (tkv *TraceKVStore) iterator(start, end []byte, ascending bool) types.Iterator { +func (tkv *Store) iterator(start, end []byte, ascending bool) types.Iterator { var parent types.Iterator if ascending { @@ -163,20 +163,20 @@ func (ti *traceIterator) Close() { // GetStoreType implements the KVStore interface. It returns the underlying // KVStore type. -func (tkv *TraceKVStore) GetStoreType() types.StoreType { +func (tkv *Store) GetStoreType() types.StoreType { return tkv.parent.GetStoreType() } -// CacheWrap implements the KVStore interface. It panics as a TraceKVStore +// CacheWrap implements the KVStore interface. It panics as a Store // cannot be cache wrapped. -func (tkv *TraceKVStore) CacheWrap() types.CacheWrap { - panic("cannot CacheWrap a TraceKVStore") +func (tkv *Store) CacheWrap() types.CacheWrap { + panic("cannot CacheWrap a Store") } // CacheWrapWithTrace implements the KVStore interface. It panics as a -// TraceKVStore cannot be cache wrapped. -func (tkv *TraceKVStore) CacheWrapWithTrace(_ io.Writer, _ types.TraceContext) types.CacheWrap { - panic("cannot CacheWrapWithTrace a TraceKVStore") +// Store cannot be cache wrapped. +func (tkv *Store) CacheWrapWithTrace(_ io.Writer, _ types.TraceContext) types.CacheWrap { + panic("cannot CacheWrapWithTrace a Store") } // writeOperation writes a KVStore operation to the underlying io.Writer as diff --git a/store/trace/store_test.go b/store/trace/store_test.go index 187ebc2d7f1c..e8cbe4f11308 100644 --- a/store/trace/store_test.go +++ b/store/trace/store_test.go @@ -2,6 +2,7 @@ package trace_test import ( "bytes" + "fmt" "io" "testing" @@ -10,16 +11,23 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" "github.com/cosmos/cosmos-sdk/store/dbadapter" + "github.com/cosmos/cosmos-sdk/store/prefix" + "github.com/cosmos/cosmos-sdk/store/trace" "github.com/cosmos/cosmos-sdk/types" ) +func bz(s string) []byte { return []byte(s) } + +func keyFmt(i int) []byte { return bz(fmt.Sprintf("key%0.8d", i)) } +func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } + var kvPairs = []types.KVPair{ {Key: keyFmt(1), Value: valFmt(1)}, {Key: keyFmt(2), Value: valFmt(2)}, {Key: keyFmt(3), Value: valFmt(3)}, } -func newTraceKVStore(w io.Writer) *TraceKVStore { +func newTraceKVStore(w io.Writer) *trace.Store { store := newEmptyTraceKVStore(w) for _, kvPair := range kvPairs { @@ -29,11 +37,11 @@ func newTraceKVStore(w io.Writer) *TraceKVStore { return store } -func newEmptyTraceKVStore(w io.Writer) *TraceKVStore { - memDB := dbStoreAdapter{dbm.NewMemDB()} - tc := TraceContext(map[string]interface{}{"blockHeight": 64}) +func newEmptyTraceKVStore(w io.Writer) *trace.Store { + memDB := dbadapter.Store{dbm.NewMemDB()} + tc := types.TraceContext(map[string]interface{}{"blockHeight": 64}) - return NewTraceKVStore(memDB, w, tc) + return trace.NewStore(memDB, w, tc) } func TestTraceKVStoreGet(t *testing.T) { @@ -266,12 +274,12 @@ func TestTestTraceKVStoreReverseIterator(t *testing.T) { func TestTraceKVStorePrefix(t *testing.T) { store := newEmptyTraceKVStore(nil) - pStore := store.Prefix([]byte("trace_prefix")) - require.IsType(t, prefixStore{}, pStore) + pStore := prefix.NewStore(store, []byte("trace_prefix")) + require.IsType(t, prefix.Store{}, pStore) } func TestTraceKVStoreGetStoreType(t *testing.T) { - memDB := dbStoreAdapter{dbm.NewMemDB()} + memDB := dbadapter.Store{dbm.NewMemDB()} store := newEmptyTraceKVStore(nil) require.Equal(t, memDB.GetStoreType(), store.GetStoreType()) } diff --git a/store/transient/store.go b/store/transient/store.go new file mode 100644 index 000000000000..874840992356 --- /dev/null +++ b/store/transient/store.go @@ -0,0 +1,53 @@ +package transient + +import ( + "github.com/cosmos/cosmos-sdk/types" + dbm "github.com/tendermint/tendermint/libs/db" + + "github.com/cosmos/cosmos-sdk/store/dbadapter" +) + +var _ types.KVStore = (*Store)(nil) + +// Store is a wrapper for a MemDB with Commiter implementation +type Store struct { + dbadapter.Store +} + +// Constructs new MemDB adapter +func NewStore() *Store { + return &Store{dbadapter.Store{dbm.NewMemDB()}} +} + +// Implements CommitStore +// Commit cleans up Store. +func (ts *Store) Commit() (id types.CommitID) { + ts.Store = dbadapter.Store{dbm.NewMemDB()} + return +} + +// Implements CommitStore +func (ts *Store) SetPruning(pruning types.PruningStrategy) { +} + +// Implements CommitStore +func (ts *Store) LastCommitID() (id types.CommitID) { + return +} + +// XXX: delete +/* +// Implements types.KVStore +func (ts *Store) Prefix(prefix []byte) types.KVStore { + return prefixStore{ts, prefix} +} + +// Implements types.KVStore +func (ts *Store) Gas(meter GasMeter, config GasConfig) types.KVStore { + return NewGasKVStore(meter, config, ts) +} +*/ +// Implements Store. +func (ts *Store) GetStoreType() types.StoreType { + return types.StoreTypeTransient +} diff --git a/store/transient/transientstore_test.go b/store/transient/store_test.go similarity index 86% rename from store/transient/transientstore_test.go rename to store/transient/store_test.go index 1c9e98cfaaa1..846c8a3a43ca 100644 --- a/store/transient/transientstore_test.go +++ b/store/transient/store_test.go @@ -1,4 +1,4 @@ -package store +package transient import ( "testing" @@ -9,7 +9,7 @@ import ( var k, v = []byte("hello"), []byte("world") func TestTransientStore(t *testing.T) { - tstore := newTransientStore() + tstore := NewStore() require.Nil(t, tstore.Get(k)) diff --git a/store/transient/transientstore.go b/store/transient/transientstore.go deleted file mode 100644 index a3ce8963171d..000000000000 --- a/store/transient/transientstore.go +++ /dev/null @@ -1,49 +0,0 @@ -package store - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - dbm "github.com/tendermint/tendermint/libs/db" -) - -var _ KVStore = (*transientStore)(nil) - -// transientStore is a wrapper for a MemDB with Commiter implementation -type transientStore struct { - dbStoreAdapter -} - -// Constructs new MemDB adapter -func newTransientStore() *transientStore { - return &transientStore{dbStoreAdapter{dbm.NewMemDB()}} -} - -// Implements CommitStore -// Commit cleans up transientStore. -func (ts *transientStore) Commit() (id CommitID) { - ts.dbStoreAdapter = dbStoreAdapter{dbm.NewMemDB()} - return -} - -// Implements CommitStore -func (ts *transientStore) SetPruning(pruning PruningStrategy) { -} - -// Implements CommitStore -func (ts *transientStore) LastCommitID() (id CommitID) { - return -} - -// Implements KVStore -func (ts *transientStore) Prefix(prefix []byte) KVStore { - return prefixStore{ts, prefix} -} - -// Implements KVStore -func (ts *transientStore) Gas(meter GasMeter, config GasConfig) KVStore { - return NewGasKVStore(meter, config, ts) -} - -// Implements Store. -func (ts *transientStore) GetStoreType() StoreType { - return sdk.StoreTypeTransient -} diff --git a/x/params/subspace/subspace.go b/x/params/subspace/subspace.go index fe5889a908ca..313b41795e7c 100644 --- a/x/params/subspace/subspace.go +++ b/x/params/subspace/subspace.go @@ -5,6 +5,8 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/store/prefix" ) // Individual parameter store for each keeper @@ -61,14 +63,14 @@ func (s Subspace) WithTypeTable(table TypeTable) Subspace { func (s Subspace) kvStore(ctx sdk.Context) sdk.KVStore { // append here is safe, appends within a function won't cause // weird side effects when its singlethreaded - return ctx.KVStore(s.key).Prefix(append(s.name, '/')) + return prefix.NewStore(ctx.KVStore(s.key), append(s.name, '/')) } // Returns a KVStore identical with ctx.TransientStore(s.tkey).Prefix() func (s Subspace) transientStore(ctx sdk.Context) sdk.KVStore { // append here is safe, appends within a function won't cause // weird side effects when its singlethreaded - return ctx.TransientStore(s.tkey).Prefix(append(s.name, '/')) + return prefix.NewStore(ctx.TransientStore(s.tkey), append(s.name, '/')) } // Get parameter from store From fe1209ac8d89ca677085cda4292dcdc61b20bbb1 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 3 Dec 2018 16:00:43 +0100 Subject: [PATCH 03/25] make store/gas independent from types/, now pass ci --- store/cachemulti/store.go | 6 - store/codec.go | 5 +- store/gas/store.go | 20 +- store/gas/store_test.go | 70 ++--- store/prefix/prefixstore_test.go | 9 - store/types/adapter.go | 47 ++++ {types => store/types}/gas.go | 13 + {types => store/types}/gas_test.go | 0 store/types/store.go | 393 ++++++++++++++++++++++++++++ types/context.go | 9 +- types/store.go | 402 +++++------------------------ x/params/keeper_test.go | 5 +- 12 files changed, 551 insertions(+), 428 deletions(-) create mode 100644 store/types/adapter.go rename {types => store/types}/gas.go (91%) rename {types => store/types}/gas_test.go (100%) create mode 100644 store/types/store.go diff --git a/store/cachemulti/store.go b/store/cachemulti/store.go index 097014dd2ac1..f883fd8843cc 100644 --- a/store/cachemulti/store.go +++ b/store/cachemulti/store.go @@ -9,7 +9,6 @@ import ( "github.com/cosmos/cosmos-sdk/store/cache" "github.com/cosmos/cosmos-sdk/store/dbadapter" - "github.com/cosmos/cosmos-sdk/store/gas" ) //---------------------------------------- @@ -133,8 +132,3 @@ func (cms Store) GetStore(key types.StoreKey) types.Store { func (cms Store) GetKVStore(key types.StoreKey) types.KVStore { return cms.stores[key].(types.KVStore) } - -// Implements MultiStore. -func (cms Store) GetKVStoreWithGas(meter types.GasMeter, config types.GasConfig, key types.StoreKey) types.KVStore { - return gas.NewStore(meter, config, cms.GetKVStore(key)) -} diff --git a/store/codec.go b/store/codec.go index 353cd2e3cd77..a5a8132efc2f 100644 --- a/store/codec.go +++ b/store/codec.go @@ -1,6 +1,7 @@ package store import ( + stypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/types" ) @@ -26,7 +27,7 @@ type ( StoreType = types.StoreType Queryable = types.Queryable TraceContext = types.TraceContext - Gas = types.Gas + Gas = stypes.Gas GasMeter = types.GasMeter - GasConfig = types.GasConfig + GasConfig = stypes.GasConfig ) diff --git a/store/gas/store.go b/store/gas/store.go index 931562ca6de0..0b971776b906 100644 --- a/store/gas/store.go +++ b/store/gas/store.go @@ -3,7 +3,7 @@ package gas import ( "io" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" ) var _ types.KVStore = &Store{} @@ -64,24 +64,6 @@ func (gs *Store) Delete(key []byte) { gs.parent.Delete(key) } -// XXX: delete -/* -// Implements KVStore -func (gs *Store) Prefix(prefix []byte) types.KVStore { - // Keep gasstore layer at the top - return &Store{ - gasMeter: gs.gasMeter, - gasConfig: gs.gasConfig, - parent: prefixStore{gs.parent, prefix}, - } -} - -// Implements KVStore -func (gs *Store) Gas(meter types.GasMeter, config types.GasConfig) types.KVStore { - return NewGasKVStore(meter, config, gs) -} -*/ - // Iterator implements the KVStore interface. It returns an iterator which // incurs a flat gas cost for seeking to the first key/value pair and a variable // gas cost based on the current value's length if the iterator is valid. diff --git a/store/gas/store_test.go b/store/gas/store_test.go index dd86630cefe1..c1434f4a46cf 100644 --- a/store/gas/store_test.go +++ b/store/gas/store_test.go @@ -1,4 +1,4 @@ -package gas +package gas_test import ( "fmt" @@ -7,15 +7,16 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" "github.com/cosmos/cosmos-sdk/store/dbadapter" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/gas" + stypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/stretchr/testify/require" ) -func newGasKVStore() types.KVStore { - meter := types.NewGasMeter(1000) +func newGasKVStore() stypes.KVStore { + meter := stypes.NewGasMeter(1000) mem := dbadapter.Store{dbm.NewMemDB()} - return NewStore(meter, types.KVGasConfig(), mem) + return gas.NewStore(meter, stypes.KVGasConfig(), mem) } func bz(s string) []byte { return []byte(s) } @@ -25,20 +26,20 @@ func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } func TestGasKVStoreBasic(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} - meter := types.NewGasMeter(1000) - st := NewStore(meter, types.KVGasConfig(), mem) + meter := stypes.NewGasMeter(1000) + st := gas.NewStore(meter, stypes.KVGasConfig(), mem) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") st.Set(keyFmt(1), valFmt(1)) require.Equal(t, valFmt(1), st.Get(keyFmt(1))) st.Delete(keyFmt(1)) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") - require.Equal(t, meter.GasConsumed(), types.Gas(193)) + require.Equal(t, meter.GasConsumed(), stypes.Gas(193)) } func TestGasKVStoreIterator(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} - meter := types.NewGasMeter(1000) - st := NewStore(meter, types.KVGasConfig(), mem) + meter := stypes.NewGasMeter(1000) + st := gas.NewStore(meter, stypes.KVGasConfig(), mem) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") require.Empty(t, st.Get(keyFmt(2)), "Expected `key2` to be empty") st.Set(keyFmt(1), valFmt(1)) @@ -56,61 +57,22 @@ func TestGasKVStoreIterator(t *testing.T) { iterator.Next() require.False(t, iterator.Valid()) require.Panics(t, iterator.Next) - require.Equal(t, meter.GasConsumed(), types.Gas(384)) + require.Equal(t, meter.GasConsumed(), stypes.Gas(384)) } func TestGasKVStoreOutOfGasSet(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} - meter := types.NewGasMeter(0) - st := NewStore(meter, types.KVGasConfig(), mem) + meter := stypes.NewGasMeter(0) + st := gas.NewStore(meter, stypes.KVGasConfig(), mem) require.Panics(t, func() { st.Set(keyFmt(1), valFmt(1)) }, "Expected out-of-gas") } func TestGasKVStoreOutOfGasIterator(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} - meter := types.NewGasMeter(200) - st := NewStore(meter, types.KVGasConfig(), mem) + meter := stypes.NewGasMeter(200) + st := gas.NewStore(meter, stypes.KVGasConfig(), mem) st.Set(keyFmt(1), valFmt(1)) iterator := st.Iterator(nil, nil) iterator.Next() require.Panics(t, func() { iterator.Value() }, "Expected out-of-gas") } - -// XXX: delete -// Not important since we are not method chaining to wrap stores -/* -func testGasKVStoreWrap(t *testing.T, store types.KVStore) { - meter := types.NewGasMeter(10000) - - store = NewStore(meter, types.GasConfig{HasCost: 10}, store) - require.Equal(t, uint64(0), meter.GasConsumed()) - - store.Has([]byte("key")) - require.Equal(t, uint64(10), meter.GasConsumed()) - - store = NewStore(meter, types.GasConfig{HasCost: 20}, store) - - store.Has([]byte("key")) - require.Equal(t, uint64(40), meter.GasConsumed()) -} - -func TestGasKVStoreWrap(t *testing.T) { - db := dbm.NewMemDB() - tree := iavl.NewMutableTree(db, cacheSize) - iavl := newIAVLStore(tree, numRecent, storeEvery) - testGasKVStoreWrap(t, iavl) - - st := NewCacheKVStore(iavl) - testGasKVStoreWrap(t, st) - - pref := st.Prefix([]byte("prefix")) - testGasKVStoreWrap(t, pref) - - dsa := dbadapter.Store{dbm.NewMemDB()} - testGasKVStoreWrap(t, dsa) - - ts := newTransientStore() - testGasKVStoreWrap(t, ts) - -} -*/ diff --git a/store/prefix/prefixstore_test.go b/store/prefix/prefixstore_test.go index 0d014c9a4f1a..a8ea5e1d31fe 100644 --- a/store/prefix/prefixstore_test.go +++ b/store/prefix/prefixstore_test.go @@ -10,7 +10,6 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" "github.com/cosmos/cosmos-sdk/store/dbadapter" - "github.com/cosmos/cosmos-sdk/store/gas" "github.com/cosmos/cosmos-sdk/store/iavl" "github.com/cosmos/cosmos-sdk/types" ) @@ -93,14 +92,6 @@ func TestIAVLStorePrefix(t *testing.T) { testPrefixStore(t, iavlStore, []byte("test")) } -func TestGasKVStorePrefix(t *testing.T) { - meter := types.NewGasMeter(100000000) - mem := dbadapter.Store{dbm.NewMemDB()} - gasStore := gas.NewStore(meter, types.KVGasConfig(), mem) - - testPrefixStore(t, gasStore, []byte("test")) -} - func TestPrefixStoreIterate(t *testing.T) { db := dbm.NewMemDB() baseStore := dbadapter.Store{db} diff --git a/store/types/adapter.go b/store/types/adapter.go new file mode 100644 index 000000000000..b53af1ce3ac6 --- /dev/null +++ b/store/types/adapter.go @@ -0,0 +1,47 @@ +package types + +/* +// XXX: adapters are temporal solution for managing duplicated store.go types +// will be deleted in the following prs + +import ( + stypes "github.com/cosmos/cosmos-sdk/store/types" + "github.com/cosmos/cosmos-sdk/types" +) + +type CacheWrapAdapter struct { + parent types.CacheWrap +} + +var _ stypes.CacheWrap = CacheWrapAdapter{} + +func (c CacheWrapAdapter) Write() { + c.parent.Write() +} + +func (c CacheWrapAdapter) CacheWrap() stypes.CacheWrap { + return CacheWrapAdapter{c.parent.CacheWrap()} +} + +func (c CacheWrapAdapter) CacheWrapWithTrace(w io.Writer, tc stypes.TraceContext) stypes.CacheWrap { + return CacheWrapAdapter{c.parent.CacheWrapWithTrace(w, types.TraceContext(tc))} +} + +// XXX: temporal type to wrap types.KVStore +type KVStoreAdapter struct { + types.KVStore +} + +var _ stypes.KVStore = KVStoreAdapter{} + +func (store KVStoreAdapter) CacheWrap() stypes.CacheWrap { + return CacheWrapAdapter{store.KVStore.CacheWrap()} +} + +func (store KVStoreAdapter) CacheWrapWithTrace(w io.Writer, tc stypes.TraceContext) stypes.CacheWrap { + return CacheWrapAdapter{store.KVStore.CacheWrapWithTrace(w, types.TraceContext(tc))} +} + +func (store KVStoreAdapter) GetStoreType() stypes.StoreType { + return stypes.StoreType(store.KVStore.GetStoreType()) +}*/ diff --git a/types/gas.go b/store/types/gas.go similarity index 91% rename from types/gas.go rename to store/types/gas.go index 0f61d27c0235..3217f774f089 100644 --- a/types/gas.go +++ b/store/types/gas.go @@ -1,5 +1,7 @@ package types +import "math" + // Gas consumption descriptors. const ( GasIterNextCostFlatDesc = "IterNextFlat" @@ -69,6 +71,17 @@ func (g *basicGasMeter) GasConsumedToLimit() Gas { return g.consumed } +// Copied from types/int.go +// AddUint64Overflow performs the addition operation on two uint64 integers and +// returns a boolean on whether or not the result overflows. +func AddUint64Overflow(a, b uint64) (uint64, bool) { + if math.MaxUint64-a < b { + return 0, true + } + + return a + b, false +} + func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) { var overflow bool // TODO: Should we set the consumed field after overflow checking? diff --git a/types/gas_test.go b/store/types/gas_test.go similarity index 100% rename from types/gas_test.go rename to store/types/gas_test.go diff --git a/store/types/store.go b/store/types/store.go new file mode 100644 index 000000000000..117d4aa9f7f0 --- /dev/null +++ b/store/types/store.go @@ -0,0 +1,393 @@ +package types + +// Copied from types/ + +import ( + "bytes" + "fmt" + "io" + + abci "github.com/tendermint/tendermint/abci/types" + cmn "github.com/tendermint/tendermint/libs/common" + dbm "github.com/tendermint/tendermint/libs/db" +) + +// NOTE: These are implemented in cosmos-sdk/store. + +// PruningStrategy specfies how old states will be deleted over time +type PruningStrategy uint8 + +const ( + // PruneSyncable means only those states not needed for state syncing will be deleted (keeps last 100 + every 10000th) + PruneSyncable PruningStrategy = iota + + // PruneEverything means all saved states will be deleted, storing only the current state + PruneEverything PruningStrategy = iota + + // PruneNothing means all historic states will be saved, nothing will be deleted + PruneNothing PruningStrategy = iota +) + +type Store interface { //nolint + GetStoreType() StoreType + CacheWrapper +} + +// something that can persist to disk +type Committer interface { + Commit() CommitID + LastCommitID() CommitID + SetPruning(PruningStrategy) +} + +// Stores of MultiStore must implement CommitStore. +type CommitStore interface { + Committer + Store +} + +// Queryable allows a Store to expose internal state to the abci.Query +// interface. Multistore can route requests to the proper Store. +// +// This is an optional, but useful extension to any CommitStore +type Queryable interface { + Query(abci.RequestQuery) abci.ResponseQuery +} + +//---------------------------------------- +// MultiStore + +type MultiStore interface { //nolint + Store + + // Cache wrap MultiStore. + // NOTE: Caller should probably not call .Write() on each, but + // call CacheMultiStore.Write(). + CacheMultiStore() CacheMultiStore + + // Convenience for fetching substores. + // If the store does not exist, panics. + GetStore(StoreKey) Store + GetKVStore(StoreKey) KVStore + + // TracingEnabled returns if tracing is enabled for the MultiStore. + TracingEnabled() bool + + // WithTracer sets the tracer for the MultiStore that the underlying + // stores will utilize to trace operations. A MultiStore is returned. + WithTracer(w io.Writer) MultiStore + + // WithTracingContext sets the tracing context for a MultiStore. It is + // implied that the caller should update the context when necessary between + // tracing operations. A MultiStore is returned. + WithTracingContext(TraceContext) MultiStore + + // ResetTraceContext resets the current tracing context. + ResetTraceContext() MultiStore +} + +// From MultiStore.CacheMultiStore().... +type CacheMultiStore interface { + MultiStore + Write() // Writes operations to underlying KVStore +} + +// A non-cache MultiStore. +type CommitMultiStore interface { + Committer + MultiStore + + // Mount a store of type using the given db. + // If db == nil, the new store will use the CommitMultiStore db. + MountStoreWithDB(key StoreKey, typ StoreType, db dbm.DB) + + // Panics on a nil key. + GetCommitStore(key StoreKey) CommitStore + + // Panics on a nil key. + GetCommitKVStore(key StoreKey) CommitKVStore + + // Load the latest persisted version. Called once after all + // calls to Mount*Store() are complete. + LoadLatestVersion() error + + // Load a specific persisted version. When you load an old + // version, or when the last commit attempt didn't complete, + // the next commit after loading must be idempotent (return the + // same commit id). Otherwise the behavior is undefined. + LoadVersion(ver int64) error +} + +//---------subsp------------------------------- +// KVStore + +// KVStore is a simple interface to get/set data +type KVStore interface { + Store + + // Get returns nil iff key doesn't exist. Panics on nil key. + Get(key []byte) []byte + + // Has checks if a key exists. Panics on nil key. + Has(key []byte) bool + + // Set sets the key. Panics on nil key or value. + Set(key, value []byte) + + // Delete deletes the key. Panics on nil key. + Delete(key []byte) + + // Iterator over a domain of keys in ascending order. End is exclusive. + // Start must be less than end, or the Iterator is invalid. + // Iterator must be closed by caller. + // To iterate over entire domain, use store.Iterator(nil, nil) + // CONTRACT: No writes may happen within a domain while an iterator exists over it. + Iterator(start, end []byte) Iterator + + // Iterator over a domain of keys in descending order. End is exclusive. + // Start must be less than end, or the Iterator is invalid. + // Iterator must be closed by caller. + // CONTRACT: No writes may happen within a domain while an iterator exists over it. + ReverseIterator(start, end []byte) Iterator + + // TODO Not yet implemented. + // CreateSubKVStore(key *storeKey) (KVStore, error) + + // TODO Not yet implemented. + // GetSubKVStore(key *storeKey) KVStore + + // XXX: delete + /* + // Prefix applied keys with the argument + // CONTRACT: when Prefix is called on a KVStore more than once, + // the concatanation of the prefixes is applied + Prefix(prefix []byte) KVStore + + // Gas consuming store + // CONTRACT: when Gas is called on a KVStore more than once, + // the concatanation of the meters/configs is applied + Gas(GasMeter, GasConfig) KVStore + */ +} + +// Alias iterator to db's Iterator for convenience. +type Iterator = dbm.Iterator + +// Iterator over all the keys with a certain prefix in ascending order +func KVStorePrefixIterator(kvs KVStore, prefix []byte) Iterator { + return kvs.Iterator(prefix, PrefixEndBytes(prefix)) +} + +// Iterator over all the keys with a certain prefix in descending order. +func KVStoreReversePrefixIterator(kvs KVStore, prefix []byte) Iterator { + return kvs.ReverseIterator(prefix, PrefixEndBytes(prefix)) +} + +// Compare two KVstores, return either the first key/value pair +// at which they differ and whether or not they are equal, skipping +// value comparison for a set of provided prefixes +func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvA cmn.KVPair, kvB cmn.KVPair, count int64, equal bool) { + iterA := a.Iterator(nil, nil) + iterB := b.Iterator(nil, nil) + count = int64(0) + for { + if !iterA.Valid() && !iterB.Valid() { + break + } + var kvA, kvB cmn.KVPair + if iterA.Valid() { + kvA = cmn.KVPair{Key: iterA.Key(), Value: iterA.Value()} + iterA.Next() + } + if iterB.Valid() { + kvB = cmn.KVPair{Key: iterB.Key(), Value: iterB.Value()} + iterB.Next() + } + if !bytes.Equal(kvA.Key, kvB.Key) { + return kvA, kvB, count, false + } + compareValue := true + for _, prefix := range prefixesToSkip { + // Skip value comparison if we matched a prefix + if bytes.Equal(kvA.Key[:len(prefix)], prefix) { + compareValue = false + } + } + if compareValue && !bytes.Equal(kvA.Value, kvB.Value) { + return kvA, kvB, count, false + } + count++ + } + return cmn.KVPair{}, cmn.KVPair{}, count, true +} + +// CacheKVStore cache-wraps a KVStore. After calling .Write() on +// the CacheKVStore, all previously created CacheKVStores on the +// object expire. +type CacheKVStore interface { + KVStore + + // Writes operations to underlying KVStore + Write() +} + +// Stores of MultiStore must implement CommitStore. +type CommitKVStore interface { + Committer + KVStore +} + +//---------------------------------------- +// CacheWrap + +// CacheWrap makes the most appropriate cache-wrap. For example, +// IAVLStore.CacheWrap() returns a CacheKVStore. CacheWrap should not return +// a Committer, since Commit cache-wraps make no sense. It can return KVStore, +// HeapStore, SpaceStore, etc. +type CacheWrap interface { + // Write syncs with the underlying store. + Write() + + // CacheWrap recursively wraps again. + CacheWrap() CacheWrap + + // CacheWrapWithTrace recursively wraps again with tracing enabled. + CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap +} + +type CacheWrapper interface { //nolint + // CacheWrap cache wraps. + CacheWrap() CacheWrap + + // CacheWrapWithTrace cache wraps with tracing enabled. + CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap +} + +//---------------------------------------- +// CommitID + +// CommitID contains the tree version number and its merkle root. +type CommitID struct { + Version int64 + Hash []byte +} + +func (cid CommitID) IsZero() bool { //nolint + return cid.Version == 0 && len(cid.Hash) == 0 +} + +func (cid CommitID) String() string { + return fmt.Sprintf("CommitID{%v:%X}", cid.Hash, cid.Version) +} + +//---------------------------------------- +// Store types + +// kind of store +type StoreType int + +const ( + //nolint + StoreTypeMulti StoreType = iota + StoreTypeDB + StoreTypeIAVL + StoreTypeTransient +) + +//---------------------------------------- +// Keys for accessing substores + +// StoreKey is a key used to index stores in a MultiStore. +type StoreKey interface { + Name() string + String() string +} + +// KVStoreKey is used for accessing substores. +// Only the pointer value should ever be used - it functions as a capabilities key. +type KVStoreKey struct { + name string +} + +// NewKVStoreKey returns a new pointer to a KVStoreKey. +// Use a pointer so keys don't collide. +func NewKVStoreKey(name string) *KVStoreKey { + return &KVStoreKey{ + name: name, + } +} + +func (key *KVStoreKey) Name() string { + return key.name +} + +func (key *KVStoreKey) String() string { + return fmt.Sprintf("KVStoreKey{%p, %s}", key, key.name) +} + +// PrefixEndBytes returns the []byte that would end a +// range query for all []byte with a certain prefix +// Deals with last byte of prefix being FF without overflowing +func PrefixEndBytes(prefix []byte) []byte { + if prefix == nil { + return nil + } + + end := make([]byte, len(prefix)) + copy(end, prefix) + + for { + if end[len(end)-1] != byte(255) { + end[len(end)-1]++ + break + } else { + end = end[:len(end)-1] + if len(end) == 0 { + end = nil + break + } + } + } + return end +} + +// InclusiveEndBytes returns the []byte that would end a +// range query such that the input would be included +func InclusiveEndBytes(inclusiveBytes []byte) (exclusiveBytes []byte) { + exclusiveBytes = append(inclusiveBytes, byte(0x00)) + return exclusiveBytes +} + +// TransientStoreKey is used for indexing transient stores in a MultiStore +type TransientStoreKey struct { + name string +} + +// Constructs new TransientStoreKey +// Must return a pointer according to the ocap principle +func NewTransientStoreKey(name string) *TransientStoreKey { + return &TransientStoreKey{ + name: name, + } +} + +// Implements StoreKey +func (key *TransientStoreKey) Name() string { + return key.name +} + +// Implements StoreKey +func (key *TransientStoreKey) String() string { + return fmt.Sprintf("TransientStoreKey{%p, %s}", key, key.name) +} + +//---------------------------------------- + +// key-value result for iterator queries +type KVPair cmn.KVPair + +//---------------------------------------- + +// TraceContext contains TraceKVStore context data. It will be written with +// every trace operation. +type TraceContext map[string]interface{} diff --git a/types/context.go b/types/context.go index 55af0fb795dd..371d9fe2267f 100644 --- a/types/context.go +++ b/types/context.go @@ -10,6 +10,9 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" + + "github.com/cosmos/cosmos-sdk/store/gas" + stypes "github.com/cosmos/cosmos-sdk/store/types" ) /* @@ -46,7 +49,7 @@ func NewContext(ms MultiStore, header abci.Header, isCheckTx bool, logger log.Lo c = c.WithTxBytes(nil) c = c.WithLogger(logger) c = c.WithVoteInfos(nil) - c = c.WithGasMeter(NewInfiniteGasMeter()) + c = c.WithGasMeter(stypes.NewInfiniteGasMeter()) c = c.WithMinimumFees(Coins{}) c = c.WithConsensusParams(nil) return c @@ -76,12 +79,12 @@ func (c Context) Value(key interface{}) interface{} { // will be solved after the store->types dependency is inverted // KVStore fetches a KVStore from the MultiStore. func (c Context) KVStore(key StoreKey) KVStore { - return c.MultiStore().GetKVStore(key) //.Gas(c.GasMeter(), cachedKVGasConfig) + return gas.NewStore(c.GasMeter(), stypes.KVGasConfig(), c.MultiStore().GetKVStore(key)) } // TransientStore fetches a TransientStore from the MultiStore. func (c Context) TransientStore(key StoreKey) KVStore { - return c.MultiStore().GetKVStore(key) //.Gas(c.GasMeter(), cachedTransientGasConfig) + return gas.NewStore(c.GasMeter(), stypes.TransientGasConfig(), c.MultiStore().GetKVStore(key)) } //---------------------------------------- diff --git a/types/store.go b/types/store.go index 94cefaccbd7c..3fe995d77913 100644 --- a/types/store.go +++ b/types/store.go @@ -1,391 +1,127 @@ package types import ( - "bytes" - "fmt" - "io" - - abci "github.com/tendermint/tendermint/abci/types" cmn "github.com/tendermint/tendermint/libs/common" - dbm "github.com/tendermint/tendermint/libs/db" -) -// NOTE: These are implemented in cosmos-sdk/store. + "github.com/cosmos/cosmos-sdk/store/types" +) -// PruningStrategy specfies how old states will be deleted over time -type PruningStrategy uint8 +type ( + PruningStrategy = types.PruningStrategy +) const ( - // PruneSyncable means only those states not needed for state syncing will be deleted (keeps last 100 + every 10000th) - PruneSyncable PruningStrategy = iota - - // PruneEverything means all saved states will be deleted, storing only the current state - PruneEverything PruningStrategy = iota - - // PruneNothing means all historic states will be saved, nothing will be deleted - PruneNothing PruningStrategy = iota + PruneSyncable = types.PruneSyncable + PruneEverything = types.PruneEverything + PruneNothing = types.PruneNothing ) -type Store interface { //nolint - GetStoreType() StoreType - CacheWrapper -} - -// something that can persist to disk -type Committer interface { - Commit() CommitID - LastCommitID() CommitID - SetPruning(PruningStrategy) -} - -// Stores of MultiStore must implement CommitStore. -type CommitStore interface { - Committer - Store -} - -// Queryable allows a Store to expose internal state to the abci.Query -// interface. Multistore can route requests to the proper Store. -// -// This is an optional, but useful extension to any CommitStore -type Queryable interface { - Query(abci.RequestQuery) abci.ResponseQuery -} - -//---------------------------------------- -// MultiStore - -type MultiStore interface { //nolint - Store - - // Cache wrap MultiStore. - // NOTE: Caller should probably not call .Write() on each, but - // call CacheMultiStore.Write(). - CacheMultiStore() CacheMultiStore - - // Convenience for fetching substores. - // If the store does not exist, panics. - GetStore(StoreKey) Store - GetKVStore(StoreKey) KVStore - - // TracingEnabled returns if tracing is enabled for the MultiStore. - TracingEnabled() bool - - // WithTracer sets the tracer for the MultiStore that the underlying - // stores will utilize to trace operations. A MultiStore is returned. - WithTracer(w io.Writer) MultiStore - - // WithTracingContext sets the tracing context for a MultiStore. It is - // implied that the caller should update the context when necessary between - // tracing operations. A MultiStore is returned. - WithTracingContext(TraceContext) MultiStore - - // ResetTraceContext resets the current tracing context. - ResetTraceContext() MultiStore -} - -// From MultiStore.CacheMultiStore().... -type CacheMultiStore interface { - MultiStore - Write() // Writes operations to underlying KVStore -} - -// A non-cache MultiStore. -type CommitMultiStore interface { - Committer - MultiStore - - // Mount a store of type using the given db. - // If db == nil, the new store will use the CommitMultiStore db. - MountStoreWithDB(key StoreKey, typ StoreType, db dbm.DB) - - // Panics on a nil key. - GetCommitStore(key StoreKey) CommitStore - - // Panics on a nil key. - GetCommitKVStore(key StoreKey) CommitKVStore - - // Load the latest persisted version. Called once after all - // calls to Mount*Store() are complete. - LoadLatestVersion() error - - // Load a specific persisted version. When you load an old - // version, or when the last commit attempt didn't complete, - // the next commit after loading must be idempotent (return the - // same commit id). Otherwise the behavior is undefined. - LoadVersion(ver int64) error -} - -//---------subsp------------------------------- -// KVStore - -// KVStore is a simple interface to get/set data -type KVStore interface { - Store - - // Get returns nil iff key doesn't exist. Panics on nil key. - Get(key []byte) []byte - - // Has checks if a key exists. Panics on nil key. - Has(key []byte) bool - - // Set sets the key. Panics on nil key or value. - Set(key, value []byte) - - // Delete deletes the key. Panics on nil key. - Delete(key []byte) - - // Iterator over a domain of keys in ascending order. End is exclusive. - // Start must be less than end, or the Iterator is invalid. - // Iterator must be closed by caller. - // To iterate over entire domain, use store.Iterator(nil, nil) - // CONTRACT: No writes may happen within a domain while an iterator exists over it. - Iterator(start, end []byte) Iterator - - // Iterator over a domain of keys in descending order. End is exclusive. - // Start must be less than end, or the Iterator is invalid. - // Iterator must be closed by caller. - // CONTRACT: No writes may happen within a domain while an iterator exists over it. - ReverseIterator(start, end []byte) Iterator - - // TODO Not yet implemented. - // CreateSubKVStore(key *storeKey) (KVStore, error) - - // TODO Not yet implemented. - // GetSubKVStore(key *storeKey) KVStore - - // XXX: delete - /* - // Prefix applied keys with the argument - // CONTRACT: when Prefix is called on a KVStore more than once, - // the concatanation of the prefixes is applied - Prefix(prefix []byte) KVStore - - // Gas consuming store - // CONTRACT: when Gas is called on a KVStore more than once, - // the concatanation of the meters/configs is applied - Gas(GasMeter, GasConfig) KVStore - */ -} - -// Alias iterator to db's Iterator for convenience. -type Iterator = dbm.Iterator +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 +) // Iterator over all the keys with a certain prefix in ascending order func KVStorePrefixIterator(kvs KVStore, prefix []byte) Iterator { - return kvs.Iterator(prefix, PrefixEndBytes(prefix)) + return types.KVStorePrefixIterator(kvs, prefix) } // Iterator over all the keys with a certain prefix in descending order. func KVStoreReversePrefixIterator(kvs KVStore, prefix []byte) Iterator { - return kvs.ReverseIterator(prefix, PrefixEndBytes(prefix)) + return types.KVStoreReversePrefixIterator(kvs, prefix) } // Compare two KVstores, return either the first key/value pair // at which they differ and whether or not they are equal, skipping // value comparison for a set of provided prefixes func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvA cmn.KVPair, kvB cmn.KVPair, count int64, equal bool) { - iterA := a.Iterator(nil, nil) - iterB := b.Iterator(nil, nil) - count = int64(0) - for { - if !iterA.Valid() && !iterB.Valid() { - break - } - var kvA, kvB cmn.KVPair - if iterA.Valid() { - kvA = cmn.KVPair{Key: iterA.Key(), Value: iterA.Value()} - iterA.Next() - } - if iterB.Valid() { - kvB = cmn.KVPair{Key: iterB.Key(), Value: iterB.Value()} - iterB.Next() - } - if !bytes.Equal(kvA.Key, kvB.Key) { - return kvA, kvB, count, false - } - compareValue := true - for _, prefix := range prefixesToSkip { - // Skip value comparison if we matched a prefix - if bytes.Equal(kvA.Key[:len(prefix)], prefix) { - compareValue = false - } - } - if compareValue && !bytes.Equal(kvA.Value, kvB.Value) { - return kvA, kvB, count, false - } - count++ - } - return cmn.KVPair{}, cmn.KVPair{}, count, true -} - -// CacheKVStore cache-wraps a KVStore. After calling .Write() on -// the CacheKVStore, all previously created CacheKVStores on the -// object expire. -type CacheKVStore interface { - KVStore - - // Writes operations to underlying KVStore - Write() -} - -// Stores of MultiStore must implement CommitStore. -type CommitKVStore interface { - Committer - KVStore + return types.DiffKVStores(a, b, prefixesToSkip) } -//---------------------------------------- -// CacheWrap - -// CacheWrap makes the most appropriate cache-wrap. For example, -// IAVLStore.CacheWrap() returns a CacheKVStore. CacheWrap should not return -// a Committer, since Commit cache-wraps make no sense. It can return KVStore, -// HeapStore, SpaceStore, etc. -type CacheWrap interface { - // Write syncs with the underlying store. - Write() - - // CacheWrap recursively wraps again. - CacheWrap() CacheWrap - - // CacheWrapWithTrace recursively wraps again with tracing enabled. - CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap -} - -type CacheWrapper interface { //nolint - // CacheWrap cache wraps. - CacheWrap() CacheWrap - - // CacheWrapWithTrace cache wraps with tracing enabled. - CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap -} - -//---------------------------------------- -// CommitID - -// CommitID contains the tree version number and its merkle root. -type CommitID struct { - Version int64 - Hash []byte -} - -func (cid CommitID) IsZero() bool { //nolint - return cid.Version == 0 && len(cid.Hash) == 0 -} - -func (cid CommitID) String() string { - return fmt.Sprintf("CommitID{%v:%X}", cid.Hash, cid.Version) -} - -//---------------------------------------- -// Store types +type ( + CacheKVStore = types.CacheKVStore + CommitKVStore = types.CommitKVStore + CacheWrap = types.CacheWrap + CacheWrapper = types.CacheWrapper + CommitID = types.CommitID +) -// kind of store -type StoreType int +type StoreType = types.StoreType const ( //nolint - StoreTypeMulti StoreType = iota - StoreTypeDB - StoreTypeIAVL - StoreTypeTransient + StoreTypeMulti = types.StoreTypeMulti + StoreTypeDB = types.StoreTypeDB + StoreTypeIAVL = types.StoreTypeIAVL + StoreTypeTransient = types.StoreTypeTransient ) -//---------------------------------------- -// Keys for accessing substores - -// StoreKey is a key used to index stores in a MultiStore. -type StoreKey interface { - Name() string - String() string -} - -// KVStoreKey is used for accessing substores. -// Only the pointer value should ever be used - it functions as a capabilities key. -type KVStoreKey struct { - name string -} +type ( + StoreKey = types.StoreKey + KVStoreKey = types.KVStoreKey + TransientStoreKey = types.TransientStoreKey +) // NewKVStoreKey returns a new pointer to a KVStoreKey. // Use a pointer so keys don't collide. func NewKVStoreKey(name string) *KVStoreKey { - return &KVStoreKey{ - name: name, - } -} - -func (key *KVStoreKey) Name() string { - return key.name + return types.NewKVStoreKey(name) } -func (key *KVStoreKey) String() string { - return fmt.Sprintf("KVStoreKey{%p, %s}", key, key.name) +// Constructs new TransientStoreKey +// Must return a pointer according to the ocap principle +func NewTransientStoreKey(name string) *TransientStoreKey { + return types.NewTransientStoreKey(name) } // PrefixEndBytes returns the []byte that would end a // range query for all []byte with a certain prefix // Deals with last byte of prefix being FF without overflowing func PrefixEndBytes(prefix []byte) []byte { - if prefix == nil { - return nil - } - - end := make([]byte, len(prefix)) - copy(end, prefix) - - for { - if end[len(end)-1] != byte(255) { - end[len(end)-1]++ - break - } else { - end = end[:len(end)-1] - if len(end) == 0 { - end = nil - break - } - } - } - return end + return types.PrefixEndBytes(prefix) } // InclusiveEndBytes returns the []byte that would end a // range query such that the input would be included func InclusiveEndBytes(inclusiveBytes []byte) (exclusiveBytes []byte) { - exclusiveBytes = append(inclusiveBytes, byte(0x00)) - return exclusiveBytes -} - -// TransientStoreKey is used for indexing transient stores in a MultiStore -type TransientStoreKey struct { - name string -} - -// Constructs new TransientStoreKey -// Must return a pointer according to the ocap principle -func NewTransientStoreKey(name string) *TransientStoreKey { - return &TransientStoreKey{ - name: name, - } -} - -// Implements StoreKey -func (key *TransientStoreKey) Name() string { - return key.name -} - -// Implements StoreKey -func (key *TransientStoreKey) String() string { - return fmt.Sprintf("TransientStoreKey{%p, %s}", key, key.name) + return types.InclusiveEndBytes(inclusiveBytes) } //---------------------------------------- // key-value result for iterator queries -type KVPair cmn.KVPair +type KVPair = types.KVPair //---------------------------------------- // TraceContext contains TraceKVStore context data. It will be written with // every trace operation. -type TraceContext map[string]interface{} +type TraceContext = types.TraceContext + +// -------------------------------------- + +type ( + Gas = types.Gas + GasMeter = types.GasMeter + GasConfig = types.GasConfig +) + +func NewGasMeter(limit Gas) GasMeter { + return types.NewGasMeter(limit) +} + +type ( + ErrorOutOfGas = types.ErrorOutOfGas + ErrorGasOverflow = types.ErrorGasOverflow +) + +func NewInfiniteGasMeter() GasMeter { + return types.NewInfiniteGasMeter() +} diff --git a/x/params/keeper_test.go b/x/params/keeper_test.go index 585db3c410e5..cda57de8e887 100644 --- a/x/params/keeper_test.go +++ b/x/params/keeper_test.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -71,7 +72,7 @@ func TestKeeper(t *testing.T) { ctx := defaultContext(skey, tkey) keeper := NewKeeper(cdc, skey, tkey) space := keeper.Subspace("test").WithTypeTable(table) - store := ctx.KVStore(skey).Prefix([]byte("test/")) + store := prefix.NewStore(ctx.KVStore(skey), []byte("test/")) // Set params for i, kv := range kvs { @@ -177,7 +178,7 @@ func TestSubspace(t *testing.T) { []byte("struct"), s{}, ) - store := ctx.KVStore(key).Prefix([]byte("test/")) + store := prefix.NewStore(ctx.KVStore(key), []byte("test/")) space := keeper.Subspace("test").WithTypeTable(table) // Test space.Set, space.Modified From c40055ea87c33e97a0d65a980bb239978c637f06 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 3 Dec 2018 16:06:43 +0100 Subject: [PATCH 04/25] remove residue, rename files to match with convention --- store/cache/store.go | 12 ----- store/dbadapter/store.go | 12 ----- store/iavl/store.go | 12 ----- store/prefix/{prefixstore.go => store.go} | 12 ----- .../{prefixstore_test.go => store_test.go} | 0 .../{multistoreproof.go => proof.go} | 0 ...{multistoreproof_test.go => proof_test.go} | 0 .../rootmulti/{rootmultistore.go => store.go} | 0 .../{rootmultistore_test.go => store_test.go} | 0 store/trace/store.go | 12 ----- store/transient/store.go | 12 ----- store/types/adapter.go | 47 ------------------- store/types/store.go | 12 ----- types/context.go | 2 - 14 files changed, 133 deletions(-) rename store/prefix/{prefixstore.go => store.go} (94%) rename store/prefix/{prefixstore_test.go => store_test.go} (100%) rename store/rootmulti/{multistoreproof.go => proof.go} (100%) rename store/rootmulti/{multistoreproof_test.go => proof_test.go} (100%) rename store/rootmulti/{rootmultistore.go => store.go} (100%) rename store/rootmulti/{rootmultistore_test.go => store_test.go} (100%) delete mode 100644 store/types/adapter.go diff --git a/store/cache/store.go b/store/cache/store.go index 6768b4110e84..2af59e085a5a 100644 --- a/store/cache/store.go +++ b/store/cache/store.go @@ -86,18 +86,6 @@ func (ci *Store) Delete(key []byte) { ci.setCacheValue(key, nil, true, true) } -// XXX: delete -/* -// Implements types.KVStore -func (ci *Store) Prefix(prefix []byte) types.KVStore { - return prefixStore{ci, prefix} -} - -// Implements types.KVStore -func (ci *Store) Gas(meter GasMeter, config GasConfig) types.KVStore { - return NewGasKVStore(meter, config, ci) -} -*/ // Implements Cachetypes.KVStore. func (ci *Store) Write() { ci.mtx.Lock() diff --git a/store/dbadapter/store.go b/store/dbadapter/store.go index f2edff2d2377..98aae8e7d113 100644 --- a/store/dbadapter/store.go +++ b/store/dbadapter/store.go @@ -31,17 +31,5 @@ func (dsa Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.Ca return cache.NewStore(trace.NewStore(dsa, w, tc)) } -// XXX: delete -/* -// Implements KVStore -func (dsa Store) Prefix(prefix []byte) KVStore { - return prefixStore{dsa, prefix} -} - -// Implements KVStore -func (dsa Store) Gas(meter GasMeter, config GasConfig) KVStore { - return NewGasKVStore(meter, config, dsa) -} -*/ // dbm.DB implements KVStore so we can CacheKVStore it. var _ types.KVStore = Store{} diff --git a/store/iavl/store.go b/store/iavl/store.go index f4dd61b1bbe3..89c00378cbfe 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -159,18 +159,6 @@ func (st *Store) Delete(key []byte) { st.tree.Remove(key) } -// XXX: delete -/* -// Implements types.KVStore -func (st *Store) Prefix(prefix []byte) types.KVStore { - return prefixStore{st, prefix} -} - -// Implements types.KVStore -func (st *Store) Gas(meter types.GasMeter, config types.GasConfig) types.KVStore { - return NewGasKVStore(meter, config, st) -} -*/ // Implements types.KVStore. func (st *Store) Iterator(start, end []byte) types.Iterator { return newIAVLIterator(st.tree.ImmutableTree, start, end, true) diff --git a/store/prefix/prefixstore.go b/store/prefix/store.go similarity index 94% rename from store/prefix/prefixstore.go rename to store/prefix/store.go index 68b8598bc821..2b1584ea833b 100644 --- a/store/prefix/prefixstore.go +++ b/store/prefix/store.go @@ -79,18 +79,6 @@ func (s Store) Delete(key []byte) { s.parent.Delete(s.key(key)) } -// XXX: delete -/* -// Implements KVStore -func (s Store) Prefix(prefix []byte) types.KVStore { - return Store{s, prefix} -} - -// Implements KVStore -func (s Store) Gas(meter types.GasMeter, config types.GasConfig) types.KVStore { - return NewGasKVStore(meter, config, s) -} -*/ // Implements KVStore // Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L106 func (s Store) Iterator(start, end []byte) types.Iterator { diff --git a/store/prefix/prefixstore_test.go b/store/prefix/store_test.go similarity index 100% rename from store/prefix/prefixstore_test.go rename to store/prefix/store_test.go diff --git a/store/rootmulti/multistoreproof.go b/store/rootmulti/proof.go similarity index 100% rename from store/rootmulti/multistoreproof.go rename to store/rootmulti/proof.go diff --git a/store/rootmulti/multistoreproof_test.go b/store/rootmulti/proof_test.go similarity index 100% rename from store/rootmulti/multistoreproof_test.go rename to store/rootmulti/proof_test.go diff --git a/store/rootmulti/rootmultistore.go b/store/rootmulti/store.go similarity index 100% rename from store/rootmulti/rootmultistore.go rename to store/rootmulti/store.go diff --git a/store/rootmulti/rootmultistore_test.go b/store/rootmulti/store_test.go similarity index 100% rename from store/rootmulti/rootmultistore_test.go rename to store/rootmulti/store_test.go diff --git a/store/trace/store.go b/store/trace/store.go index c3b6e9ae62b1..9d86730ac950 100644 --- a/store/trace/store.go +++ b/store/trace/store.go @@ -77,18 +77,6 @@ func (tkv *Store) Has(key []byte) bool { return tkv.parent.Has(key) } -// XXX: delete -/* -// Prefix implements the KVStore interface. -func (tkv *Store) Prefix(prefix []byte) KVStore { - return prefixStore{tkv, prefix} -} - -// Gas implements the KVStore interface. -func (tkv *Store) Gas(meter GasMeter, config GasConfig) KVStore { - return NewGasKVStore(meter, config, tkv.parent) -} -*/ // Iterator implements the KVStore interface. It delegates the Iterator call // the to the parent KVStore. func (tkv *Store) Iterator(start, end []byte) types.Iterator { diff --git a/store/transient/store.go b/store/transient/store.go index 874840992356..013f2b0a10e8 100644 --- a/store/transient/store.go +++ b/store/transient/store.go @@ -35,18 +35,6 @@ func (ts *Store) LastCommitID() (id types.CommitID) { return } -// XXX: delete -/* -// Implements types.KVStore -func (ts *Store) Prefix(prefix []byte) types.KVStore { - return prefixStore{ts, prefix} -} - -// Implements types.KVStore -func (ts *Store) Gas(meter GasMeter, config GasConfig) types.KVStore { - return NewGasKVStore(meter, config, ts) -} -*/ // Implements Store. func (ts *Store) GetStoreType() types.StoreType { return types.StoreTypeTransient diff --git a/store/types/adapter.go b/store/types/adapter.go deleted file mode 100644 index b53af1ce3ac6..000000000000 --- a/store/types/adapter.go +++ /dev/null @@ -1,47 +0,0 @@ -package types - -/* -// XXX: adapters are temporal solution for managing duplicated store.go types -// will be deleted in the following prs - -import ( - stypes "github.com/cosmos/cosmos-sdk/store/types" - "github.com/cosmos/cosmos-sdk/types" -) - -type CacheWrapAdapter struct { - parent types.CacheWrap -} - -var _ stypes.CacheWrap = CacheWrapAdapter{} - -func (c CacheWrapAdapter) Write() { - c.parent.Write() -} - -func (c CacheWrapAdapter) CacheWrap() stypes.CacheWrap { - return CacheWrapAdapter{c.parent.CacheWrap()} -} - -func (c CacheWrapAdapter) CacheWrapWithTrace(w io.Writer, tc stypes.TraceContext) stypes.CacheWrap { - return CacheWrapAdapter{c.parent.CacheWrapWithTrace(w, types.TraceContext(tc))} -} - -// XXX: temporal type to wrap types.KVStore -type KVStoreAdapter struct { - types.KVStore -} - -var _ stypes.KVStore = KVStoreAdapter{} - -func (store KVStoreAdapter) CacheWrap() stypes.CacheWrap { - return CacheWrapAdapter{store.KVStore.CacheWrap()} -} - -func (store KVStoreAdapter) CacheWrapWithTrace(w io.Writer, tc stypes.TraceContext) stypes.CacheWrap { - return CacheWrapAdapter{store.KVStore.CacheWrapWithTrace(w, types.TraceContext(tc))} -} - -func (store KVStoreAdapter) GetStoreType() stypes.StoreType { - return stypes.StoreType(store.KVStore.GetStoreType()) -}*/ diff --git a/store/types/store.go b/store/types/store.go index 117d4aa9f7f0..43e33fc705b3 100644 --- a/store/types/store.go +++ b/store/types/store.go @@ -156,18 +156,6 @@ type KVStore interface { // TODO Not yet implemented. // GetSubKVStore(key *storeKey) KVStore - // XXX: delete - /* - // Prefix applied keys with the argument - // CONTRACT: when Prefix is called on a KVStore more than once, - // the concatanation of the prefixes is applied - Prefix(prefix []byte) KVStore - - // Gas consuming store - // CONTRACT: when Gas is called on a KVStore more than once, - // the concatanation of the meters/configs is applied - Gas(GasMeter, GasConfig) KVStore - */ } // Alias iterator to db's Iterator for convenience. diff --git a/types/context.go b/types/context.go index 371d9fe2267f..d404996d874e 100644 --- a/types/context.go +++ b/types/context.go @@ -75,8 +75,6 @@ func (c Context) Value(key interface{}) interface{} { return value } -// XXX: temporary breakes gas semantic -// will be solved after the store->types dependency is inverted // KVStore fetches a KVStore from the MultiStore. func (c Context) KVStore(key StoreKey) KVStore { return gas.NewStore(c.GasMeter(), stypes.KVGasConfig(), c.MultiStore().GetKVStore(key)) From ff0e9dc0a07172be96a343b77232bf349967e6b2 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 3 Dec 2018 16:30:25 +0100 Subject: [PATCH 05/25] fix lint --- store/prefix/store.go | 1 - types/store.go | 12 +++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/store/prefix/store.go b/store/prefix/store.go index 2b1584ea833b..90dc8003c2d9 100644 --- a/store/prefix/store.go +++ b/store/prefix/store.go @@ -15,7 +15,6 @@ var _ types.KVStore = Store{} // Store is similar with tendermint/tendermint/libs/db/prefix_db // both gives access only to the limited subset of the store // for convinience or safety - type Store struct { parent types.KVStore prefix []byte diff --git a/types/store.go b/types/store.go index 3fe995d77913..39108aec4a72 100644 --- a/types/store.go +++ b/types/store.go @@ -6,16 +6,19 @@ import ( "github.com/cosmos/cosmos-sdk/store/types" ) +// nolint - reexport type ( PruningStrategy = types.PruningStrategy ) +// nolint - reexport const ( PruneSyncable = types.PruneSyncable PruneEverything = types.PruneEverything PruneNothing = types.PruneNothing ) +// nolint - reexport type ( Store = types.Store Committer = types.Committer @@ -45,6 +48,7 @@ func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvA cmn.KVPair return types.DiffKVStores(a, b, prefixesToSkip) } +// nolint - reexport type ( CacheKVStore = types.CacheKVStore CommitKVStore = types.CommitKVStore @@ -53,16 +57,18 @@ type ( CommitID = types.CommitID ) +// nolint - reexport type StoreType = types.StoreType +// nolint - reexport const ( - //nolint StoreTypeMulti = types.StoreTypeMulti StoreTypeDB = types.StoreTypeDB StoreTypeIAVL = types.StoreTypeIAVL StoreTypeTransient = types.StoreTypeTransient ) +// nolint - reexport type ( StoreKey = types.StoreKey KVStoreKey = types.KVStoreKey @@ -107,21 +113,25 @@ type TraceContext = types.TraceContext // -------------------------------------- +// nolint - reexport type ( Gas = types.Gas GasMeter = types.GasMeter GasConfig = types.GasConfig ) +// nolint - reexport func NewGasMeter(limit Gas) GasMeter { return types.NewGasMeter(limit) } +// nolint - reexport type ( ErrorOutOfGas = types.ErrorOutOfGas ErrorGasOverflow = types.ErrorGasOverflow ) +// nolint - reexport func NewInfiniteGasMeter() GasMeter { return types.NewInfiniteGasMeter() } From b08044a027d2a947b1d165a5859e666d81e71112 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 3 Dec 2018 20:09:59 +0100 Subject: [PATCH 06/25] replace dependency types/ -> store/types/ --- store/cache/mergeiterator.go | 2 +- store/cache/store.go | 2 +- store/cache/store_test.go | 2 +- store/cachemulti/store.go | 3 +-- store/codec.go | 2 +- store/dbadapter/store.go | 3 +-- store/list/list.go | 9 +++++---- store/prefix/store.go | 3 +-- store/prefix/store_test.go | 2 +- store/rootmulti/dbadapter.go | 2 +- store/store.go | 3 +-- store/trace/store.go | 2 +- store/trace/store_test.go | 2 +- store/transient/store.go | 2 +- 14 files changed, 18 insertions(+), 21 deletions(-) diff --git a/store/cache/mergeiterator.go b/store/cache/mergeiterator.go index 12bfd2caa600..b5d50d2deb48 100644 --- a/store/cache/mergeiterator.go +++ b/store/cache/mergeiterator.go @@ -3,7 +3,7 @@ package cache import ( "bytes" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" ) // cacheMergeIterator merges a parent Iterator and a cache Iterator. diff --git a/store/cache/store.go b/store/cache/store.go index 2af59e085a5a..b6f48fbf2da7 100644 --- a/store/cache/store.go +++ b/store/cache/store.go @@ -9,7 +9,7 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/store/trace" ) diff --git a/store/cache/store_test.go b/store/cache/store_test.go index 7a2638ce66f8..9b81c6f2e365 100644 --- a/store/cache/store_test.go +++ b/store/cache/store_test.go @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/cache" "github.com/cosmos/cosmos-sdk/store/dbadapter" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" ) func newCacheKVStore() types.CacheKVStore { diff --git a/store/cachemulti/store.go b/store/cachemulti/store.go index f883fd8843cc..89294b9175c1 100644 --- a/store/cachemulti/store.go +++ b/store/cachemulti/store.go @@ -5,10 +5,9 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" - "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/store/cache" "github.com/cosmos/cosmos-sdk/store/dbadapter" + "github.com/cosmos/cosmos-sdk/store/types" ) //---------------------------------------- diff --git a/store/codec.go b/store/codec.go index a5a8132efc2f..0fcd58a6e10a 100644 --- a/store/codec.go +++ b/store/codec.go @@ -1,8 +1,8 @@ package store import ( + "github.com/cosmos/cosmos-sdk/store/types" stypes "github.com/cosmos/cosmos-sdk/store/types" - "github.com/cosmos/cosmos-sdk/types" ) // Import cosmos-sdk/types/store.go for convenience. diff --git a/store/dbadapter/store.go b/store/dbadapter/store.go index 98aae8e7d113..b6e6c786502d 100644 --- a/store/dbadapter/store.go +++ b/store/dbadapter/store.go @@ -5,10 +5,9 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" - "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/store/cache" "github.com/cosmos/cosmos-sdk/store/trace" + "github.com/cosmos/cosmos-sdk/store/types" ) // Wrapper type for dbm.Db with implementation of KVStore diff --git a/store/list/list.go b/store/list/list.go index e9770d97c6af..118d275a8ed2 100644 --- a/store/list/list.go +++ b/store/list/list.go @@ -5,7 +5,8 @@ import ( "strconv" "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/store/types" ) // Key for the length of the list @@ -22,11 +23,11 @@ func ElemKey(index uint64) []byte { // It panics when the element type cannot be (un/)marshalled by the codec type List struct { cdc *codec.Codec - store sdk.KVStore + store types.KVStore } // NewList constructs new List -func NewList(cdc *codec.Codec, store sdk.KVStore) List { +func NewList(cdc *codec.Codec, store types.KVStore) List { return List{ cdc: cdc, store: store, @@ -83,7 +84,7 @@ func (m List) Push(value interface{}) { // CONTRACT: No writes may happen within a domain while iterating over it. func (m List) Iterate(ptr interface{}, fn func(uint64) bool) { - iter := sdk.KVStorePrefixIterator(m.store, []byte{0x01}) + iter := types.KVStorePrefixIterator(m.store, []byte{0x01}) for ; iter.Valid(); iter.Next() { v := iter.Value() m.cdc.MustUnmarshalBinaryLengthPrefixed(v, ptr) diff --git a/store/prefix/store.go b/store/prefix/store.go index 90dc8003c2d9..426338480702 100644 --- a/store/prefix/store.go +++ b/store/prefix/store.go @@ -4,10 +4,9 @@ import ( "bytes" "io" - "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/store/cache" "github.com/cosmos/cosmos-sdk/store/trace" + "github.com/cosmos/cosmos-sdk/store/types" ) var _ types.KVStore = Store{} diff --git a/store/prefix/store_test.go b/store/prefix/store_test.go index a8ea5e1d31fe..e9303fc573ff 100644 --- a/store/prefix/store_test.go +++ b/store/prefix/store_test.go @@ -11,7 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/dbadapter" "github.com/cosmos/cosmos-sdk/store/iavl" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" ) // copied from iavl/store_test.go diff --git a/store/rootmulti/dbadapter.go b/store/rootmulti/dbadapter.go index 4a93efc8698d..e631a4919274 100644 --- a/store/rootmulti/dbadapter.go +++ b/store/rootmulti/dbadapter.go @@ -2,7 +2,7 @@ package rootmulti import ( "github.com/cosmos/cosmos-sdk/store/dbadapter" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" ) //---------------------------------------- diff --git a/store/store.go b/store/store.go index 458c3472e402..f358ed292f16 100644 --- a/store/store.go +++ b/store/store.go @@ -3,9 +3,8 @@ package store import ( dbm "github.com/tendermint/tendermint/libs/db" - "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/store/rootmulti" + "github.com/cosmos/cosmos-sdk/store/types" ) func NewCommitMultiStore(db dbm.DB) types.CommitMultiStore { diff --git a/store/trace/store.go b/store/trace/store.go index 9d86730ac950..1df48fef21ae 100644 --- a/store/trace/store.go +++ b/store/trace/store.go @@ -6,7 +6,7 @@ import ( "fmt" "io" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" ) const ( diff --git a/store/trace/store_test.go b/store/trace/store_test.go index e8cbe4f11308..f059e856f3f5 100644 --- a/store/trace/store_test.go +++ b/store/trace/store_test.go @@ -13,7 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/dbadapter" "github.com/cosmos/cosmos-sdk/store/prefix" "github.com/cosmos/cosmos-sdk/store/trace" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" ) func bz(s string) []byte { return []byte(s) } diff --git a/store/transient/store.go b/store/transient/store.go index 013f2b0a10e8..8b5c50a5898f 100644 --- a/store/transient/store.go +++ b/store/transient/store.go @@ -1,7 +1,7 @@ package transient import ( - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" dbm "github.com/tendermint/tendermint/libs/db" "github.com/cosmos/cosmos-sdk/store/dbadapter" From 26e05ae37c4b1cb0eb7693e1005714e0ddf4452c Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 3 Dec 2018 20:12:10 +0100 Subject: [PATCH 07/25] update pending --- PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PENDING.md b/PENDING.md index a905c1939ef6..8e2b9aef60f2 100644 --- a/PENDING.md +++ b/PENDING.md @@ -38,6 +38,7 @@ IMPROVEMENTS * SDK - \#1277 Complete bank module specification + - \#2986 Store Refactor * Tendermint From 324a849b9d4f63946669fd48392a528714627452 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 3 Dec 2018 20:17:51 +0100 Subject: [PATCH 08/25] fix gas.NewStore argument order --- store/gas/store.go | 2 +- store/gas/store_test.go | 10 +++++----- types/context.go | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/store/gas/store.go b/store/gas/store.go index 0b971776b906..ed6e610e9394 100644 --- a/store/gas/store.go +++ b/store/gas/store.go @@ -18,7 +18,7 @@ type Store struct { // NewStore returns a reference to a new GasKVStore. // nolint -func NewStore(gasMeter types.GasMeter, gasConfig types.GasConfig, parent types.KVStore) *Store { +func NewStore(parent types.KVStore, gasMeter types.GasMeter, gasConfig types.GasConfig) *Store { kvs := &Store{ gasMeter: gasMeter, gasConfig: gasConfig, diff --git a/store/gas/store_test.go b/store/gas/store_test.go index c1434f4a46cf..d9fec9e66afd 100644 --- a/store/gas/store_test.go +++ b/store/gas/store_test.go @@ -16,7 +16,7 @@ import ( func newGasKVStore() stypes.KVStore { meter := stypes.NewGasMeter(1000) mem := dbadapter.Store{dbm.NewMemDB()} - return gas.NewStore(meter, stypes.KVGasConfig(), mem) + return gas.NewStore(mem, meter, stypes.KVGasConfig()) } func bz(s string) []byte { return []byte(s) } @@ -27,7 +27,7 @@ func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } func TestGasKVStoreBasic(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} meter := stypes.NewGasMeter(1000) - st := gas.NewStore(meter, stypes.KVGasConfig(), mem) + st := gas.NewStore(mem, meter, stypes.KVGasConfig()) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") st.Set(keyFmt(1), valFmt(1)) require.Equal(t, valFmt(1), st.Get(keyFmt(1))) @@ -39,7 +39,7 @@ func TestGasKVStoreBasic(t *testing.T) { func TestGasKVStoreIterator(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} meter := stypes.NewGasMeter(1000) - st := gas.NewStore(meter, stypes.KVGasConfig(), mem) + st := gas.NewStore(mem, meter, stypes.KVGasConfig()) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") require.Empty(t, st.Get(keyFmt(2)), "Expected `key2` to be empty") st.Set(keyFmt(1), valFmt(1)) @@ -63,14 +63,14 @@ func TestGasKVStoreIterator(t *testing.T) { func TestGasKVStoreOutOfGasSet(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} meter := stypes.NewGasMeter(0) - st := gas.NewStore(meter, stypes.KVGasConfig(), mem) + st := gas.NewStore(mem, meter, stypes.KVGasConfig()) require.Panics(t, func() { st.Set(keyFmt(1), valFmt(1)) }, "Expected out-of-gas") } func TestGasKVStoreOutOfGasIterator(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} meter := stypes.NewGasMeter(200) - st := gas.NewStore(meter, stypes.KVGasConfig(), mem) + st := gas.NewStore(mem, meter, stypes.KVGasConfig()) st.Set(keyFmt(1), valFmt(1)) iterator := st.Iterator(nil, nil) iterator.Next() diff --git a/types/context.go b/types/context.go index d404996d874e..cbea65e51fe2 100644 --- a/types/context.go +++ b/types/context.go @@ -77,12 +77,12 @@ func (c Context) Value(key interface{}) interface{} { // KVStore fetches a KVStore from the MultiStore. func (c Context) KVStore(key StoreKey) KVStore { - return gas.NewStore(c.GasMeter(), stypes.KVGasConfig(), c.MultiStore().GetKVStore(key)) + return gas.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.KVGasConfig()) } // TransientStore fetches a TransientStore from the MultiStore. func (c Context) TransientStore(key StoreKey) KVStore { - return gas.NewStore(c.GasMeter(), stypes.TransientGasConfig(), c.MultiStore().GetKVStore(key)) + return gas.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.TransientGasConfig()) } //---------------------------------------- From 9d806d6182c9d246d6ff3301ffa9447bb27199b9 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 5 Dec 2018 13:46:08 +0100 Subject: [PATCH 09/25] rename {gas, cache, trace} -> {gas, cache, trace}kv --- store/{cache => cachekv}/memiterator.go | 2 +- store/{cache => cachekv}/mergeiterator.go | 2 +- store/{cache => cachekv}/store.go | 6 +++--- store/{cache => cachekv}/store_test.go | 16 ++++++++-------- store/cachemulti/store.go | 4 ++-- store/dbadapter/store.go | 8 ++++---- store/{gas => gaskv}/store.go | 2 +- store/{gas => gaskv}/store_test.go | 14 +++++++------- store/iavl/store.go | 8 ++++---- store/prefix/store.go | 8 ++++---- store/rootmulti/store.go | 4 ++-- store/{trace => tracekv}/store.go | 2 +- store/{trace => tracekv}/store_test.go | 10 +++++----- types/context.go | 6 +++--- 14 files changed, 46 insertions(+), 46 deletions(-) rename store/{cache => cachekv}/memiterator.go (98%) rename store/{cache => cachekv}/mergeiterator.go (99%) rename store/{cache => cachekv}/store.go (97%) rename store/{cache => cachekv}/store_test.go (98%) rename store/{gas => gaskv}/store.go (99%) rename store/{gas => gaskv}/store_test.go (86%) rename store/{trace => tracekv}/store.go (99%) rename store/{trace => tracekv}/store_test.go (97%) diff --git a/store/cache/memiterator.go b/store/cachekv/memiterator.go similarity index 98% rename from store/cache/memiterator.go rename to store/cachekv/memiterator.go index 9b8504c77e03..972280c42a0a 100644 --- a/store/cache/memiterator.go +++ b/store/cachekv/memiterator.go @@ -1,4 +1,4 @@ -package cache +package cachekv import ( "bytes" diff --git a/store/cache/mergeiterator.go b/store/cachekv/mergeiterator.go similarity index 99% rename from store/cache/mergeiterator.go rename to store/cachekv/mergeiterator.go index b5d50d2deb48..d45303e074e0 100644 --- a/store/cache/mergeiterator.go +++ b/store/cachekv/mergeiterator.go @@ -1,4 +1,4 @@ -package cache +package cachekv import ( "bytes" diff --git a/store/cache/store.go b/store/cachekv/store.go similarity index 97% rename from store/cache/store.go rename to store/cachekv/store.go index b6f48fbf2da7..8a719f235443 100644 --- a/store/cache/store.go +++ b/store/cachekv/store.go @@ -1,4 +1,4 @@ -package cache +package cachekv import ( "bytes" @@ -11,7 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/types" - "github.com/cosmos/cosmos-sdk/store/trace" + "github.com/cosmos/cosmos-sdk/store/tracekv" ) // If value is nil but deleted is false, it means the parent doesn't have the @@ -129,7 +129,7 @@ func (ci *Store) CacheWrap() types.CacheWrap { // CacheWrapWithTrace implements the CacheWrapper interface. func (ci *Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { - return NewStore(trace.NewStore(ci, w, tc)) + return NewStore(tracekv.NewStore(ci, w, tc)) } //---------------------------------------- diff --git a/store/cache/store_test.go b/store/cachekv/store_test.go similarity index 98% rename from store/cache/store_test.go rename to store/cachekv/store_test.go index 9b81c6f2e365..a9959b213e5f 100644 --- a/store/cache/store_test.go +++ b/store/cachekv/store_test.go @@ -1,4 +1,4 @@ -package cache_test +package cachekv_test import ( "fmt" @@ -8,14 +8,14 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" - "github.com/cosmos/cosmos-sdk/store/cache" + "github.com/cosmos/cosmos-sdk/store/cachekv" "github.com/cosmos/cosmos-sdk/store/dbadapter" "github.com/cosmos/cosmos-sdk/store/types" ) func newCacheKVStore() types.CacheKVStore { mem := dbadapter.Store{dbm.NewMemDB()} - return cache.NewStore(mem) + return cachekv.NewStore(mem) } func keyFmt(i int) []byte { return bz(fmt.Sprintf("key%0.8d", i)) } @@ -23,7 +23,7 @@ func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } func TestCacheKVStore(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} - st := cache.NewStore(mem) + st := cachekv.NewStore(mem) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") @@ -49,11 +49,11 @@ func TestCacheKVStore(t *testing.T) { require.Equal(t, valFmt(2), st.Get(keyFmt(1))) // make a new one, check it - st = cache.NewStore(mem) + st = cachekv.NewStore(mem) require.Equal(t, valFmt(2), st.Get(keyFmt(1))) // make a new one and delete - should not be removed from mem - st = cache.NewStore(mem) + st = cachekv.NewStore(mem) st.Delete(keyFmt(1)) require.Empty(t, st.Get(keyFmt(1))) require.Equal(t, mem.Get(keyFmt(1)), valFmt(2)) @@ -66,7 +66,7 @@ func TestCacheKVStore(t *testing.T) { func TestCacheKVStoreNested(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} - st := cache.NewStore(mem) + st := cachekv.NewStore(mem) // set. check its there on st and not on mem. st.Set(keyFmt(1), valFmt(1)) @@ -74,7 +74,7 @@ func TestCacheKVStoreNested(t *testing.T) { require.Equal(t, valFmt(1), st.Get(keyFmt(1))) // make a new from st and check - st2 := cache.NewStore(st) + st2 := cachekv.NewStore(st) require.Equal(t, valFmt(1), st2.Get(keyFmt(1))) // update the value on st2, check it only effects st2 diff --git a/store/cachemulti/store.go b/store/cachemulti/store.go index 89294b9175c1..40732521774e 100644 --- a/store/cachemulti/store.go +++ b/store/cachemulti/store.go @@ -5,7 +5,7 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" - "github.com/cosmos/cosmos-sdk/store/cache" + "github.com/cosmos/cosmos-sdk/store/cachekv" "github.com/cosmos/cosmos-sdk/store/dbadapter" "github.com/cosmos/cosmos-sdk/store/types" ) @@ -30,7 +30,7 @@ var _ types.CacheMultiStore = Store{} func NewFromKVStore(store types.KVStore, stores map[types.StoreKey]types.CacheWrapper, keysByName map[string]types.StoreKey, traceWriter io.Writer, traceContext types.TraceContext) Store { cms := Store{ - db: cache.NewStore(store), + db: cachekv.NewStore(store), stores: make(map[types.StoreKey]types.CacheWrap, len(stores)), keysByName: keysByName, traceWriter: traceWriter, diff --git a/store/dbadapter/store.go b/store/dbadapter/store.go index b6e6c786502d..07849ab952fc 100644 --- a/store/dbadapter/store.go +++ b/store/dbadapter/store.go @@ -5,8 +5,8 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" - "github.com/cosmos/cosmos-sdk/store/cache" - "github.com/cosmos/cosmos-sdk/store/trace" + "github.com/cosmos/cosmos-sdk/store/cachekv" + "github.com/cosmos/cosmos-sdk/store/tracekv" "github.com/cosmos/cosmos-sdk/store/types" ) @@ -22,12 +22,12 @@ func (Store) GetStoreType() types.StoreType { // Implements KVStore. func (dsa Store) CacheWrap() types.CacheWrap { - return cache.NewStore(dsa) + return cachekv.NewStore(dsa) } // CacheWrapWithTrace implements the KVStore interface. func (dsa Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { - return cache.NewStore(trace.NewStore(dsa, w, tc)) + return cachekv.NewStore(tracekv.NewStore(dsa, w, tc)) } // dbm.DB implements KVStore so we can CacheKVStore it. diff --git a/store/gas/store.go b/store/gaskv/store.go similarity index 99% rename from store/gas/store.go rename to store/gaskv/store.go index ed6e610e9394..c81e8e4c34c9 100644 --- a/store/gas/store.go +++ b/store/gaskv/store.go @@ -1,4 +1,4 @@ -package gas +package gaskv import ( "io" diff --git a/store/gas/store_test.go b/store/gaskv/store_test.go similarity index 86% rename from store/gas/store_test.go rename to store/gaskv/store_test.go index d9fec9e66afd..a16a3bf32556 100644 --- a/store/gas/store_test.go +++ b/store/gaskv/store_test.go @@ -1,4 +1,4 @@ -package gas_test +package gaskv_test import ( "fmt" @@ -7,7 +7,7 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" "github.com/cosmos/cosmos-sdk/store/dbadapter" - "github.com/cosmos/cosmos-sdk/store/gas" + "github.com/cosmos/cosmos-sdk/store/gaskv" stypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/stretchr/testify/require" @@ -16,7 +16,7 @@ import ( func newGasKVStore() stypes.KVStore { meter := stypes.NewGasMeter(1000) mem := dbadapter.Store{dbm.NewMemDB()} - return gas.NewStore(mem, meter, stypes.KVGasConfig()) + return gaskv.NewStore(mem, meter, stypes.KVGasConfig()) } func bz(s string) []byte { return []byte(s) } @@ -27,7 +27,7 @@ func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } func TestGasKVStoreBasic(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} meter := stypes.NewGasMeter(1000) - st := gas.NewStore(mem, meter, stypes.KVGasConfig()) + st := gaskv.NewStore(mem, meter, stypes.KVGasConfig()) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") st.Set(keyFmt(1), valFmt(1)) require.Equal(t, valFmt(1), st.Get(keyFmt(1))) @@ -39,7 +39,7 @@ func TestGasKVStoreBasic(t *testing.T) { func TestGasKVStoreIterator(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} meter := stypes.NewGasMeter(1000) - st := gas.NewStore(mem, meter, stypes.KVGasConfig()) + st := gaskv.NewStore(mem, meter, stypes.KVGasConfig()) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") require.Empty(t, st.Get(keyFmt(2)), "Expected `key2` to be empty") st.Set(keyFmt(1), valFmt(1)) @@ -63,14 +63,14 @@ func TestGasKVStoreIterator(t *testing.T) { func TestGasKVStoreOutOfGasSet(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} meter := stypes.NewGasMeter(0) - st := gas.NewStore(mem, meter, stypes.KVGasConfig()) + st := gaskv.NewStore(mem, meter, stypes.KVGasConfig()) require.Panics(t, func() { st.Set(keyFmt(1), valFmt(1)) }, "Expected out-of-gas") } func TestGasKVStoreOutOfGasIterator(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} meter := stypes.NewGasMeter(200) - st := gas.NewStore(mem, meter, stypes.KVGasConfig()) + st := gaskv.NewStore(mem, meter, stypes.KVGasConfig()) st.Set(keyFmt(1), valFmt(1)) iterator := st.Iterator(nil, nil) iterator.Next() diff --git a/store/iavl/store.go b/store/iavl/store.go index 89c00378cbfe..282654d1ce1d 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -13,8 +13,8 @@ import ( "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/store/cache" - "github.com/cosmos/cosmos-sdk/store/trace" + "github.com/cosmos/cosmos-sdk/store/cachekv" + "github.com/cosmos/cosmos-sdk/store/tracekv" ) const ( @@ -130,12 +130,12 @@ func (st *Store) GetStoreType() types.StoreType { // Implements Store. func (st *Store) CacheWrap() types.CacheWrap { - return cache.NewStore(st) + return cachekv.NewStore(st) } // CacheWrapWithTrace implements the Store interface. func (st *Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { - return cache.NewStore(trace.NewStore(st, w, tc)) + return cachekv.NewStore(tracekv.NewStore(st, w, tc)) } // Implements types.KVStore. diff --git a/store/prefix/store.go b/store/prefix/store.go index 426338480702..6b8996fdf8f0 100644 --- a/store/prefix/store.go +++ b/store/prefix/store.go @@ -4,8 +4,8 @@ import ( "bytes" "io" - "github.com/cosmos/cosmos-sdk/store/cache" - "github.com/cosmos/cosmos-sdk/store/trace" + "github.com/cosmos/cosmos-sdk/store/cachekv" + "github.com/cosmos/cosmos-sdk/store/tracekv" "github.com/cosmos/cosmos-sdk/store/types" ) @@ -48,12 +48,12 @@ func (s Store) GetStoreType() types.StoreType { // Implements CacheWrap func (s Store) CacheWrap() types.CacheWrap { - return cache.NewStore(s) + return cachekv.NewStore(s) } // CacheWrapWithTrace implements the KVStore interface. func (s Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { - return cache.NewStore(trace.NewStore(s, w, tc)) + return cachekv.NewStore(tracekv.NewStore(s, w, tc)) } // Implements KVStore diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index ee252e66d902..d11d360ce403 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -13,7 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/cachemulti" "github.com/cosmos/cosmos-sdk/store/dbadapter" "github.com/cosmos/cosmos-sdk/store/iavl" - "github.com/cosmos/cosmos-sdk/store/trace" + "github.com/cosmos/cosmos-sdk/store/tracekv" "github.com/cosmos/cosmos-sdk/store/transient" "github.com/cosmos/cosmos-sdk/types" ) @@ -256,7 +256,7 @@ func (rs *Store) GetKVStore(key types.StoreKey) types.KVStore { store := rs.stores[key].(types.KVStore) if rs.TracingEnabled() { - store = trace.NewStore(store, rs.traceWriter, rs.traceContext) + store = tracekv.NewStore(store, rs.traceWriter, rs.traceContext) } return store diff --git a/store/trace/store.go b/store/tracekv/store.go similarity index 99% rename from store/trace/store.go rename to store/tracekv/store.go index 1df48fef21ae..ee9558ecbe5a 100644 --- a/store/trace/store.go +++ b/store/tracekv/store.go @@ -1,4 +1,4 @@ -package trace +package tracekv import ( "encoding/base64" diff --git a/store/trace/store_test.go b/store/tracekv/store_test.go similarity index 97% rename from store/trace/store_test.go rename to store/tracekv/store_test.go index f059e856f3f5..36d101583d05 100644 --- a/store/trace/store_test.go +++ b/store/tracekv/store_test.go @@ -1,4 +1,4 @@ -package trace_test +package tracekv_test import ( "bytes" @@ -12,7 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/dbadapter" "github.com/cosmos/cosmos-sdk/store/prefix" - "github.com/cosmos/cosmos-sdk/store/trace" + "github.com/cosmos/cosmos-sdk/store/tracekv" "github.com/cosmos/cosmos-sdk/store/types" ) @@ -27,7 +27,7 @@ var kvPairs = []types.KVPair{ {Key: keyFmt(3), Value: valFmt(3)}, } -func newTraceKVStore(w io.Writer) *trace.Store { +func newTraceKVStore(w io.Writer) *tracekv.Store { store := newEmptyTraceKVStore(w) for _, kvPair := range kvPairs { @@ -37,11 +37,11 @@ func newTraceKVStore(w io.Writer) *trace.Store { return store } -func newEmptyTraceKVStore(w io.Writer) *trace.Store { +func newEmptyTraceKVStore(w io.Writer) *tracekv.Store { memDB := dbadapter.Store{dbm.NewMemDB()} tc := types.TraceContext(map[string]interface{}{"blockHeight": 64}) - return trace.NewStore(memDB, w, tc) + return tracekv.NewStore(memDB, w, tc) } func TestTraceKVStoreGet(t *testing.T) { diff --git a/types/context.go b/types/context.go index cbea65e51fe2..a403acd1c480 100644 --- a/types/context.go +++ b/types/context.go @@ -11,7 +11,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" - "github.com/cosmos/cosmos-sdk/store/gas" + "github.com/cosmos/cosmos-sdk/store/gaskv" stypes "github.com/cosmos/cosmos-sdk/store/types" ) @@ -77,12 +77,12 @@ func (c Context) Value(key interface{}) interface{} { // KVStore fetches a KVStore from the MultiStore. func (c Context) KVStore(key StoreKey) KVStore { - return gas.NewStore(c.MultiStore().GetKVStore(key), 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 { - return gas.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.TransientGasConfig()) + return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.TransientGasConfig()) } //---------------------------------------- From 9876e302ca8063277452ab169a9b2a6c09efd972 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 14 Dec 2018 12:41:28 +0100 Subject: [PATCH 10/25] adress comments in progress --- store/cachemulti/store.go | 14 ++--- store/firstlast.go | 14 +---- store/iavl/store.go | 15 +---- store/queue/queue_test.go | 104 ----------------------------------- store/rootmulti/dbadapter.go | 6 +- store/rootmulti/store.go | 14 ++--- store/types/store.go | 25 +++------ store/types/utils.go | 11 ++++ 8 files changed, 36 insertions(+), 167 deletions(-) delete mode 100644 store/queue/queue_test.go create mode 100644 store/types/utils.go diff --git a/store/cachemulti/store.go b/store/cachemulti/store.go index 40732521774e..dbd922ce6253 100644 --- a/store/cachemulti/store.go +++ b/store/cachemulti/store.go @@ -60,18 +60,18 @@ func newCacheMultiStoreFromCMS(cms Store) Store { return NewFromKVStore(cms.db, stores, nil, cms.traceWriter, cms.traceContext) } -// WithTracer sets the tracer for the MultiStore that the underlying +// SetTracer sets the tracer for the MultiStore that the underlying // stores will utilize to trace operations. A MultiStore is returned. -func (cms Store) WithTracer(w io.Writer) types.MultiStore { +func (cms Store) SetTracer(w io.Writer) types.MultiStore { cms.traceWriter = w return cms } -// WithTracingContext updates the tracing context for the MultiStore by merging +// SetTracingContext updates the tracing context for the MultiStore by merging // the given context with the existing context by key. Any existing keys will // be overwritten. It is implied that the caller should update the context when // necessary between tracing operations. It returns a modified MultiStore. -func (cms Store) WithTracingContext(tc types.TraceContext) types.MultiStore { +func (cms Store) SetTracingContext(tc types.TraceContext) types.MultiStore { if cms.traceContext != nil { for k, v := range tc { cms.traceContext[k] = v @@ -88,12 +88,6 @@ func (cms Store) TracingEnabled() bool { return cms.traceWriter != nil } -// ResetTraceContext resets the current tracing context. -func (cms Store) ResetTraceContext() types.MultiStore { - cms.traceContext = nil - return cms -} - // Implements Store. func (cms Store) GetStoreType() types.StoreType { return types.StoreTypeMulti diff --git a/store/firstlast.go b/store/firstlast.go index 76d0ae03e361..708a7d0d3dce 100644 --- a/store/firstlast.go +++ b/store/firstlast.go @@ -4,6 +4,8 @@ import ( "bytes" cmn "github.com/tendermint/tendermint/libs/common" + + "github.com/cosmos/cosmos-sdk/store/types" ) // Gets the first item. @@ -22,7 +24,7 @@ func Last(st KVStore, start, end []byte) (kv cmn.KVPair, ok bool) { iter := st.ReverseIterator(end, start) if !iter.Valid() { if v := st.Get(start); v != nil { - return cmn.KVPair{Key: cp(start), Value: cp(v)}, true + return cmn.KVPair{Key: types.Cp(start), Value: types.Cp(v)}, true } return kv, false } @@ -38,13 +40,3 @@ func Last(st KVStore, start, end []byte) (kv cmn.KVPair, ok bool) { return cmn.KVPair{Key: iter.Key(), Value: iter.Value()}, true } - -//---------------------------------------- -func cp(bz []byte) (ret []byte) { - if bz == nil { - return nil - } - ret = make([]byte, len(bz)) - copy(ret, bz) - return ret -} diff --git a/store/iavl/store.go b/store/iavl/store.go index 282654d1ce1d..28a9f8ab6a87 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -11,6 +11,7 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" + stypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/store/cachekv" @@ -298,8 +299,8 @@ var _ types.Iterator = (*iavlIterator)(nil) func newIAVLIterator(tree *iavl.ImmutableTree, start, end []byte, ascending bool) *iavlIterator { iter := &iavlIterator{ tree: tree, - start: cp(start), - end: cp(end), + start: stypes.Cp(start), + end: stypes.Cp(end), ascending: ascending, iterCh: make(chan cmn.KVPair, 0), // Set capacity > 0? quitCh: make(chan struct{}), @@ -423,13 +424,3 @@ func (iter *iavlIterator) assertIsValid(unlockMutex bool) { panic("invalid iterator") } } - -//---------------------------------------- -func cp(bz []byte) (ret []byte) { - if bz == nil { - return nil - } - ret = make([]byte, len(bz)) - copy(ret, bz) - return ret -} diff --git a/store/queue/queue_test.go b/store/queue/queue_test.go deleted file mode 100644 index a71adbfed29a..000000000000 --- a/store/queue/queue_test.go +++ /dev/null @@ -1,104 +0,0 @@ -package store - -/* -import ( - "testing" - - "github.com/stretchr/testify/require" - - dbm "github.com/tendermint/tendermint/libs/db" - "github.com/tendermint/tendermint/libs/log" - - abci "github.com/tendermint/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -type S struct { - I uint64 - B bool -} - -func defaultComponents(key sdk.StoreKey) (sdk.Context, *codec.Codec) { - db := dbm.NewMemDB() - cms := NewCommitMultiStore(db) - cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) - cms.LoadLatestVersion() - ctx := sdk.NewContext(cms, abci.Header{}, false, log.NewNopLogger()) - cdc := codec.New() - return ctx, cdc -} - -func TestQueue(t *testing.T) { - key := sdk.NewKVStoreKey("test") - ctx, cdc := defaultComponents(key) - store := ctx.KVStore(key) - - qm := NewQueue(cdc, store) - - val := S{1, true} - var res S - - qm.Push(val) - qm.Peek(&res) - require.Equal(t, val, res) - - qm.Pop() - empty := qm.IsEmpty() - - require.True(t, empty) - require.NotNil(t, qm.Peek(&res)) - - qm.Push(S{1, true}) - qm.Push(S{2, true}) - qm.Push(S{3, true}) - qm.Flush(&res, func() (brk bool) { - if res.I == 3 { - brk = true - } - return - }) - - require.False(t, qm.IsEmpty()) - - qm.Pop() - require.True(t, qm.IsEmpty()) -} - -func TestKeys(t *testing.T) { - key := sdk.NewKVStoreKey("test") - ctx, cdc := defaultComponents(key) - store := ctx.KVStore(key) - queue := NewQueue(cdc, store) - - for i := 0; i < 10; i++ { - queue.Push(i) - } - - var len uint64 - var top uint64 - var expected int - var actual int - - // Checking keys.LengthKey - err := cdc.UnmarshalBinaryLengthPrefixed(store.Get(LengthKey()), &len) - require.Nil(t, err) - require.Equal(t, len, queue.List.Len()) - - // Checking keys.ElemKey - for i := 0; i < 10; i++ { - queue.List.Get(uint64(i), &expected) - bz := store.Get(ElemKey(uint64(i))) - err = cdc.UnmarshalBinaryLengthPrefixed(bz, &actual) - require.Nil(t, err) - require.Equal(t, expected, actual) - } - - queue.Pop() - - err = cdc.UnmarshalBinaryLengthPrefixed(store.Get(TopKey()), &top) - require.Nil(t, err) - require.Equal(t, top, queue.getTop()) -} -*/ diff --git a/store/rootmulti/dbadapter.go b/store/rootmulti/dbadapter.go index e631a4919274..11255da2847e 100644 --- a/store/rootmulti/dbadapter.go +++ b/store/rootmulti/dbadapter.go @@ -5,6 +5,8 @@ import ( "github.com/cosmos/cosmos-sdk/store/types" ) +var commithash = []byte("FAKE_HASH") + //---------------------------------------- // commitDBStoreWrapper should only be used for simulation/debugging, // as it doesn't compute any commit hash, and it cannot load older state. @@ -17,14 +19,14 @@ type commitDBStoreAdapter struct { func (cdsa commitDBStoreAdapter) Commit() types.CommitID { return types.CommitID{ Version: -1, - Hash: []byte("FAKE_HASH"), + Hash: commithash, } } func (cdsa commitDBStoreAdapter) LastCommitID() types.CommitID { return types.CommitID{ Version: -1, - Hash: []byte("FAKE_HASH"), + Hash: commithash, } } diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index d11d360ce403..c087956da6bd 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -152,18 +152,18 @@ func (rs *Store) LoadVersion(ver int64) error { return nil } -// WithTracer sets the tracer for the MultiStore that the underlying +// SetTracer sets the tracer for the MultiStore that the underlying // stores will utilize to trace operations. A MultiStore is returned. -func (rs *Store) WithTracer(w io.Writer) types.MultiStore { +func (rs *Store) SetTracer(w io.Writer) types.MultiStore { rs.traceWriter = w return rs } -// WithTracingContext updates the tracing context for the MultiStore by merging +// SetTracingContext updates the tracing context for the MultiStore by merging // the given context with the existing context by key. Any existing keys will // be overwritten. It is implied that the caller should update the context when // necessary between tracing operations. It returns a modified MultiStore. -func (rs *Store) WithTracingContext(tc types.TraceContext) types.MultiStore { +func (rs *Store) SetTracingContext(tc types.TraceContext) types.MultiStore { if rs.traceContext != nil { for k, v := range tc { rs.traceContext[k] = v @@ -180,12 +180,6 @@ func (rs *Store) TracingEnabled() bool { return rs.traceWriter != nil } -// ResetTraceContext resets the current tracing context. -func (rs *Store) ResetTraceContext() types.MultiStore { - rs.traceContext = nil - return rs -} - //---------------------------------------- // +CommitStore diff --git a/store/types/store.go b/store/types/store.go index 43e33fc705b3..3be892984d8e 100644 --- a/store/types/store.go +++ b/store/types/store.go @@ -1,7 +1,5 @@ package types -// Copied from types/ - import ( "bytes" "fmt" @@ -73,17 +71,15 @@ type MultiStore interface { //nolint // TracingEnabled returns if tracing is enabled for the MultiStore. TracingEnabled() bool - // WithTracer sets the tracer for the MultiStore that the underlying - // stores will utilize to trace operations. A MultiStore is returned. - WithTracer(w io.Writer) MultiStore + // SetTracer sets the tracer for the MultiStore that the underlying + // stores will utilize to trace operations. The modified MultiStore is + // returned. + SetTracer(w io.Writer) MultiStore - // WithTracingContext sets the tracing context for a MultiStore. It is + // SetTracingContext sets the tracing context for a MultiStore. It is // implied that the caller should update the context when necessary between - // tracing operations. A MultiStore is returned. - WithTracingContext(TraceContext) MultiStore - - // ResetTraceContext resets the current tracing context. - ResetTraceContext() MultiStore + // tracing operations. The modified MultiStore is returned. + SetTracingContext(TraceContext) MultiStore } // From MultiStore.CacheMultiStore().... @@ -149,13 +145,6 @@ type KVStore interface { // Iterator must be closed by caller. // CONTRACT: No writes may happen within a domain while an iterator exists over it. ReverseIterator(start, end []byte) Iterator - - // TODO Not yet implemented. - // CreateSubKVStore(key *storeKey) (KVStore, error) - - // TODO Not yet implemented. - // GetSubKVStore(key *storeKey) KVStore - } // Alias iterator to db's Iterator for convenience. diff --git a/store/types/utils.go b/store/types/utils.go new file mode 100644 index 000000000000..b1bd81e88d0e --- /dev/null +++ b/store/types/utils.go @@ -0,0 +1,11 @@ +package types + +//---------------------------------------- +func Cp(bz []byte) (ret []byte) { + if bz == nil { + return nil + } + ret = make([]byte, len(bz)) + copy(ret, bz) + return ret +} From 86b19d487ff6547bf664994ab7a85687c8816a67 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 14 Dec 2018 14:48:41 +0100 Subject: [PATCH 11/25] fix server --- server/mock/store.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/server/mock/store.go b/server/mock/store.go index ec963a1bc22c..8eab5841dd12 100644 --- a/server/mock/store.go +++ b/server/mock/store.go @@ -26,19 +26,15 @@ func (ms multiStore) CacheWrapWithTrace(_ io.Writer, _ sdk.TraceContext) sdk.Cac panic("not implemented") } -func (ms multiStore) ResetTraceContext() sdk.MultiStore { - panic("not implemented") -} - func (ms multiStore) TracingEnabled() bool { panic("not implemented") } -func (ms multiStore) WithTracingContext(tc sdk.TraceContext) sdk.MultiStore { +func (ms multiStore) SetTracingContext(tc sdk.TraceContext) sdk.MultiStore { panic("not implemented") } -func (ms multiStore) WithTracer(w io.Writer) sdk.MultiStore { +func (ms multiStore) SetTracer(w io.Writer) sdk.MultiStore { panic("not implemented") } From 2c316e3dc911fd9cf453324419c1e1f7300b577b Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 14 Dec 2018 15:17:50 +0100 Subject: [PATCH 12/25] address comments in progress --- store/types/store.go | 84 +----------------------------------------- store/types/utils.go | 87 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 82 deletions(-) diff --git a/store/types/store.go b/store/types/store.go index 3be892984d8e..f859d873a2bd 100644 --- a/store/types/store.go +++ b/store/types/store.go @@ -1,7 +1,6 @@ package types import ( - "bytes" "fmt" "io" @@ -138,66 +137,20 @@ type KVStore interface { // Iterator must be closed by caller. // To iterate over entire domain, use store.Iterator(nil, nil) // CONTRACT: No writes may happen within a domain while an iterator exists over it. + // Exceptionally allowed for cachekv.Store Iterator(start, end []byte) Iterator // Iterator over a domain of keys in descending order. End is exclusive. // Start must be less than end, or the Iterator is invalid. // Iterator must be closed by caller. // CONTRACT: No writes may happen within a domain while an iterator exists over it. + // Exceptionally allowed for cachekv.Store ReverseIterator(start, end []byte) Iterator } // Alias iterator to db's Iterator for convenience. type Iterator = dbm.Iterator -// Iterator over all the keys with a certain prefix in ascending order -func KVStorePrefixIterator(kvs KVStore, prefix []byte) Iterator { - return kvs.Iterator(prefix, PrefixEndBytes(prefix)) -} - -// Iterator over all the keys with a certain prefix in descending order. -func KVStoreReversePrefixIterator(kvs KVStore, prefix []byte) Iterator { - return kvs.ReverseIterator(prefix, PrefixEndBytes(prefix)) -} - -// Compare two KVstores, return either the first key/value pair -// at which they differ and whether or not they are equal, skipping -// value comparison for a set of provided prefixes -func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvA cmn.KVPair, kvB cmn.KVPair, count int64, equal bool) { - iterA := a.Iterator(nil, nil) - iterB := b.Iterator(nil, nil) - count = int64(0) - for { - if !iterA.Valid() && !iterB.Valid() { - break - } - var kvA, kvB cmn.KVPair - if iterA.Valid() { - kvA = cmn.KVPair{Key: iterA.Key(), Value: iterA.Value()} - iterA.Next() - } - if iterB.Valid() { - kvB = cmn.KVPair{Key: iterB.Key(), Value: iterB.Value()} - iterB.Next() - } - if !bytes.Equal(kvA.Key, kvB.Key) { - return kvA, kvB, count, false - } - compareValue := true - for _, prefix := range prefixesToSkip { - // Skip value comparison if we matched a prefix - if bytes.Equal(kvA.Key[:len(prefix)], prefix) { - compareValue = false - } - } - if compareValue && !bytes.Equal(kvA.Value, kvB.Value) { - return kvA, kvB, count, false - } - count++ - } - return cmn.KVPair{}, cmn.KVPair{}, count, true -} - // CacheKVStore cache-wraps a KVStore. After calling .Write() on // the CacheKVStore, all previously created CacheKVStores on the // object expire. @@ -302,39 +255,6 @@ func (key *KVStoreKey) String() string { return fmt.Sprintf("KVStoreKey{%p, %s}", key, key.name) } -// PrefixEndBytes returns the []byte that would end a -// range query for all []byte with a certain prefix -// Deals with last byte of prefix being FF without overflowing -func PrefixEndBytes(prefix []byte) []byte { - if prefix == nil { - return nil - } - - end := make([]byte, len(prefix)) - copy(end, prefix) - - for { - if end[len(end)-1] != byte(255) { - end[len(end)-1]++ - break - } else { - end = end[:len(end)-1] - if len(end) == 0 { - end = nil - break - } - } - } - return end -} - -// InclusiveEndBytes returns the []byte that would end a -// range query such that the input would be included -func InclusiveEndBytes(inclusiveBytes []byte) (exclusiveBytes []byte) { - exclusiveBytes = append(inclusiveBytes, byte(0x00)) - return exclusiveBytes -} - // TransientStoreKey is used for indexing transient stores in a MultiStore type TransientStoreKey struct { name string diff --git a/store/types/utils.go b/store/types/utils.go index b1bd81e88d0e..a86efdb8c82f 100644 --- a/store/types/utils.go +++ b/store/types/utils.go @@ -1,5 +1,92 @@ package types +import ( + "bytes" + + cmn "github.com/tendermint/tendermint/libs/common" +) + +// Iterator over all the keys with a certain prefix in ascending order +func KVStorePrefixIterator(kvs KVStore, prefix []byte) Iterator { + return kvs.Iterator(prefix, PrefixEndBytes(prefix)) +} + +// Iterator over all the keys with a certain prefix in descending order. +func KVStoreReversePrefixIterator(kvs KVStore, prefix []byte) Iterator { + return kvs.ReverseIterator(prefix, PrefixEndBytes(prefix)) +} + +// Compare two KVstores, return either the first key/value pair +// at which they differ and whether or not they are equal, skipping +// value comparison for a set of provided prefixes +func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvA cmn.KVPair, kvB cmn.KVPair, count int64, equal bool) { + iterA := a.Iterator(nil, nil) + iterB := b.Iterator(nil, nil) + count = int64(0) + for { + if !iterA.Valid() && !iterB.Valid() { + break + } + var kvA, kvB cmn.KVPair + if iterA.Valid() { + kvA = cmn.KVPair{Key: iterA.Key(), Value: iterA.Value()} + iterA.Next() + } + if iterB.Valid() { + kvB = cmn.KVPair{Key: iterB.Key(), Value: iterB.Value()} + iterB.Next() + } + if !bytes.Equal(kvA.Key, kvB.Key) { + return kvA, kvB, count, false + } + compareValue := true + for _, prefix := range prefixesToSkip { + // Skip value comparison if we matched a prefix + if bytes.Equal(kvA.Key[:len(prefix)], prefix) { + compareValue = false + } + } + if compareValue && !bytes.Equal(kvA.Value, kvB.Value) { + return kvA, kvB, count, false + } + count++ + } + return cmn.KVPair{}, cmn.KVPair{}, count, true +} + +// PrefixEndBytes returns the []byte that would end a +// range query for all []byte with a certain prefix +// Deals with last byte of prefix being FF without overflowing +func PrefixEndBytes(prefix []byte) []byte { + if prefix == nil { + return nil + } + + end := make([]byte, len(prefix)) + copy(end, prefix) + + for { + if end[len(end)-1] != byte(255) { + end[len(end)-1]++ + break + } else { + end = end[:len(end)-1] + if len(end) == 0 { + end = nil + break + } + } + } + return end +} + +// InclusiveEndBytes returns the []byte that would end a +// range query such that the input would be included +func InclusiveEndBytes(inclusiveBytes []byte) (exclusiveBytes []byte) { + exclusiveBytes = append(inclusiveBytes, byte(0x00)) + return exclusiveBytes +} + //---------------------------------------- func Cp(bz []byte) (ret []byte) { if bz == nil { From 30a4a58d208eb2ea3eeea4329df25f470602861b Mon Sep 17 00:00:00 2001 From: mossid Date: Sat, 29 Dec 2018 20:51:16 +0100 Subject: [PATCH 13/25] addressing comments --- store/cachemulti/store.go | 30 +++++++++++++++++++----------- store/dbadapter/store.go | 4 ++-- store/types/gas_test.go | 26 ++++++++++++++++++++++++++ types/int.go | 11 ----------- types/int_test.go | 25 ------------------------- 5 files changed, 47 insertions(+), 49 deletions(-) diff --git a/store/cachemulti/store.go b/store/cachemulti/store.go index dbd922ce6253..69e14494d89a 100644 --- a/store/cachemulti/store.go +++ b/store/cachemulti/store.go @@ -18,9 +18,9 @@ import ( // NOTE: a Store (and MultiStores in general) should never expose the // keys for the substores. type Store struct { - db types.CacheKVStore - stores map[types.StoreKey]types.CacheWrap - keysByName map[string]types.StoreKey + db types.CacheKVStore + stores map[types.StoreKey]types.CacheWrap + keys map[string]types.StoreKey traceWriter io.Writer traceContext types.TraceContext @@ -28,11 +28,15 @@ type Store struct { var _ types.CacheMultiStore = Store{} -func NewFromKVStore(store types.KVStore, stores map[types.StoreKey]types.CacheWrapper, keysByName map[string]types.StoreKey, traceWriter io.Writer, traceContext types.TraceContext) Store { +func NewFromKVStore( + store types.KVStore, + stores map[types.StoreKey]types.CacheWrapper, keys map[string]types.StoreKey, + traceWriter io.Writer, traceContext types.TraceContext, +) Store { cms := Store{ db: cachekv.NewStore(store), stores: make(map[types.StoreKey]types.CacheWrap, len(stores)), - keysByName: keysByName, + keys: keys, traceWriter: traceWriter, traceContext: traceContext, } @@ -48,8 +52,12 @@ func NewFromKVStore(store types.KVStore, stores map[types.StoreKey]types.CacheWr return cms } -func NewStore(db dbm.DB, stores map[types.StoreKey]types.CacheWrapper, keysByName map[string]types.StoreKey, traceWriter io.Writer, traceContext types.TraceContext) Store { - return NewFromKVStore(dbadapter.Store{db}, stores, keysByName, traceWriter, traceContext) +func NewStore( + db dbm.DB, + stores map[types.StoreKey]types.CacheWrapper, keys map[string]types.StoreKey, + traceWriter io.Writer, traceContext types.TraceContext, +) Store { + return NewFromKVStore(dbadapter.Store{db}, stores, keys, traceWriter, traceContext) } func newCacheMultiStoreFromCMS(cms Store) Store { @@ -88,12 +96,12 @@ func (cms Store) TracingEnabled() bool { return cms.traceWriter != nil } -// Implements Store. +// GetStoreType returns the type of the store. func (cms Store) GetStoreType() types.StoreType { return types.StoreTypeMulti } -// Implements CacheMultiStore. +// Write writes each underlying store. func (cms Store) Write() { cms.db.Write() for _, store := range cms.stores { @@ -116,12 +124,12 @@ func (cms Store) CacheMultiStore() types.CacheMultiStore { return newCacheMultiStoreFromCMS(cms) } -// Implements MultiStore. +// GetStore returns an underlying Store by key. func (cms Store) GetStore(key types.StoreKey) types.Store { return cms.stores[key].(types.Store) } -// Implements MultiStore. +// GetKVStore returns an underlying KVStore by key. func (cms Store) GetKVStore(key types.StoreKey) types.KVStore { return cms.stores[key].(types.KVStore) } diff --git a/store/dbadapter/store.go b/store/dbadapter/store.go index 07849ab952fc..accf9189ba11 100644 --- a/store/dbadapter/store.go +++ b/store/dbadapter/store.go @@ -15,12 +15,12 @@ type Store struct { dbm.DB } -// Implements Store. +// GetStoreType returns the type of the store. func (Store) GetStoreType() types.StoreType { return types.StoreTypeDB } -// Implements KVStore. +// CacheWrap cache wraps the underlying store. func (dsa Store) CacheWrap() types.CacheWrap { return cachekv.NewStore(dsa) } diff --git a/store/types/gas_test.go b/store/types/gas_test.go index 5f862dccdb67..352d931134ec 100644 --- a/store/types/gas_test.go +++ b/store/types/gas_test.go @@ -1,6 +1,7 @@ package types import ( + "math" "testing" "github.com/stretchr/testify/require" @@ -43,3 +44,28 @@ func TestGasMeter(t *testing.T) { } } + +func TestAddUint64Overflow(t *testing.T) { + testCases := []struct { + a, b uint64 + result uint64 + overflow bool + }{ + {0, 0, 0, false}, + {100, 100, 200, false}, + {math.MaxUint64 / 2, math.MaxUint64/2 + 1, math.MaxUint64, false}, + {math.MaxUint64 / 2, math.MaxUint64/2 + 2, 0, true}, + } + + for i, tc := range testCases { + res, overflow := AddUint64Overflow(tc.a, tc.b) + require.Equal( + t, tc.overflow, overflow, + "invalid overflow result; tc: #%d, a: %d, b: %d", i, tc.a, tc.b, + ) + require.Equal( + t, tc.result, res, + "invalid uint64 result; tc: #%d, a: %d, b: %d", i, tc.a, tc.b, + ) + } +} diff --git a/types/int.go b/types/int.go index 417a1763d431..1f59ad9e38f8 100644 --- a/types/int.go +++ b/types/int.go @@ -2,7 +2,6 @@ package types import ( "encoding/json" - "math" "testing" "math/big" @@ -546,16 +545,6 @@ func UintOverflow(x Uint) bool { return x.i.Sign() == -1 || x.i.Sign() == 1 && x.i.BitLen() > 256 } -// AddUint64Overflow performs the addition operation on two uint64 integers and -// returns a boolean on whether or not the result overflows. -func AddUint64Overflow(a, b uint64) (uint64, bool) { - if math.MaxUint64-a < b { - return 0, true - } - - return a + b, false -} - // intended to be used with require/assert: require.True(IntEq(...)) func IntEq(t *testing.T, exp, got Int) (*testing.T, bool, string, string, string) { return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp.String(), got.String() diff --git a/types/int_test.go b/types/int_test.go index 9e189858c702..6ac0d6516239 100644 --- a/types/int_test.go +++ b/types/int_test.go @@ -615,28 +615,3 @@ func TestSafeSub(t *testing.T) { ) } } - -func TestAddUint64Overflow(t *testing.T) { - testCases := []struct { - a, b uint64 - result uint64 - overflow bool - }{ - {0, 0, 0, false}, - {100, 100, 200, false}, - {math.MaxUint64 / 2, math.MaxUint64/2 + 1, math.MaxUint64, false}, - {math.MaxUint64 / 2, math.MaxUint64/2 + 2, 0, true}, - } - - for i, tc := range testCases { - res, overflow := AddUint64Overflow(tc.a, tc.b) - require.Equal( - t, tc.overflow, overflow, - "invalid overflow result; tc: #%d, a: %d, b: %d", i, tc.a, tc.b, - ) - require.Equal( - t, tc.result, res, - "invalid uint64 result; tc: #%d, a: %d, b: %d", i, tc.a, tc.b, - ) - } -} From 4eda02b065ec2f10dc9df8ca44ee1a29623f2ab5 Mon Sep 17 00:00:00 2001 From: mossid Date: Sat, 5 Jan 2019 05:53:08 +0100 Subject: [PATCH 14/25] address comments --- store/types/gas.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/store/types/gas.go b/store/types/gas.go index 7800f40a9c95..0acbcd7e2293 100644 --- a/store/types/gas.go +++ b/store/types/gas.go @@ -71,10 +71,9 @@ func (g *basicGasMeter) GasConsumedToLimit() Gas { return g.consumed } -// Copied from types/int.go -// AddUint64Overflow performs the addition operation on two uint64 integers and +// addUint64Overflow performs the addition operation on two uint64 integers and // returns a boolean on whether or not the result overflows. -func AddUint64Overflow(a, b uint64) (uint64, bool) { +func addUint64Overflow(a, b uint64) (uint64, bool) { if math.MaxUint64-a < b { return 0, true } @@ -85,7 +84,7 @@ func AddUint64Overflow(a, b uint64) (uint64, bool) { func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) { var overflow bool // TODO: Should we set the consumed field after overflow checking? - g.consumed, overflow = AddUint64Overflow(g.consumed, amount) + g.consumed, overflow = addUint64Overflow(g.consumed, amount) if overflow { panic(ErrorGasOverflow{descriptor}) } @@ -130,7 +129,7 @@ func (g *infiniteGasMeter) Limit() Gas { func (g *infiniteGasMeter) ConsumeGas(amount Gas, descriptor string) { var overflow bool // TODO: Should we set the consumed field after overflow checking? - g.consumed, overflow = AddUint64Overflow(g.consumed, amount) + g.consumed, overflow = addUint64Overflow(g.consumed, amount) if overflow { panic(ErrorGasOverflow{descriptor}) } From 04631ad6fcc295faa81ac15de6c6f85a0312faa1 Mon Sep 17 00:00:00 2001 From: mossid Date: Sat, 5 Jan 2019 08:24:10 +0100 Subject: [PATCH 15/25] fix test --- store/types/gas_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/store/types/gas_test.go b/store/types/gas_test.go index 352d931134ec..3b2866e458fd 100644 --- a/store/types/gas_test.go +++ b/store/types/gas_test.go @@ -45,7 +45,7 @@ func TestGasMeter(t *testing.T) { } } -func TestAddUint64Overflow(t *testing.T) { +func TestaddUint64Overflow(t *testing.T) { testCases := []struct { a, b uint64 result uint64 @@ -58,7 +58,7 @@ func TestAddUint64Overflow(t *testing.T) { } for i, tc := range testCases { - res, overflow := AddUint64Overflow(tc.a, tc.b) + res, overflow := addUint64Overflow(tc.a, tc.b) require.Equal( t, tc.overflow, overflow, "invalid overflow result; tc: #%d, a: %d, b: %d", i, tc.a, tc.b, From cad00ca9345225cef9a578b81edfd7fac239d807 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 25 Jan 2019 11:55:57 +0100 Subject: [PATCH 16/25] address comments --- store/firstlast.go | 2 +- store/iavl/store.go | 6 +++--- store/list/list_test.go | 16 ++++++++-------- store/types/store.go | 4 ++-- store/types/utils.go | 10 ---------- types/utils.go | 10 ++++++++++ 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/store/firstlast.go b/store/firstlast.go index 708a7d0d3dce..7c94356a6430 100644 --- a/store/firstlast.go +++ b/store/firstlast.go @@ -5,7 +5,7 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" - "github.com/cosmos/cosmos-sdk/store/types" + "github.com/cosmos/cosmos-sdk/types" ) // Gets the first item. diff --git a/store/iavl/store.go b/store/iavl/store.go index 7263e234e550..481a6781a60a 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -235,7 +235,7 @@ func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) { subspace := req.Data res.Key = subspace - iterator := types.KVStorePrefixIterator(st, subspace) + iterator := stypes.KVStorePrefixIterator(st, subspace) for ; iterator.Valid(); iterator.Next() { KVs = append(KVs, types.KVPair{Key: iterator.Key(), Value: iterator.Value()}) } @@ -290,8 +290,8 @@ var _ types.Iterator = (*iavlIterator)(nil) func newIAVLIterator(tree *iavl.ImmutableTree, start, end []byte, ascending bool) *iavlIterator { iter := &iavlIterator{ tree: tree, - start: stypes.Cp(start), - end: stypes.Cp(end), + start: types.Cp(start), + end: types.Cp(end), ascending: ascending, iterCh: make(chan cmn.KVPair, 0), // Set capacity > 0? quitCh: make(chan struct{}), diff --git a/store/list/list_test.go b/store/list/list_test.go index 6b1cbf7bf045..970c836bc3eb 100644 --- a/store/list/list_test.go +++ b/store/list/list_test.go @@ -15,7 +15,7 @@ import ( "github.com/stretchr/testify/require" ) -type S struct { +type TestStruct struct { I uint64 B bool } @@ -35,20 +35,20 @@ func TestList(t *testing.T) { store := ctx.KVStore(key) lm := NewList(cdc, store) - val := S{1, true} - var res S + val := TestStruct{1, true} + var res TestStruct lm.Push(val) require.Equal(t, uint64(1), lm.Len()) lm.Get(uint64(0), &res) require.Equal(t, val, res) - val = S{2, false} + val = TestStruct{2, false} lm.Set(uint64(0), val) lm.Get(uint64(0), &res) require.Equal(t, val, res) - val = S{100, false} + val = TestStruct{100, false} lm.Push(val) require.Equal(t, uint64(2), lm.Len()) lm.Get(uint64(1), &res) @@ -58,7 +58,7 @@ func TestList(t *testing.T) { require.Equal(t, uint64(2), lm.Len()) lm.Iterate(&res, func(index uint64) (brk bool) { - var temp S + var temp TestStruct lm.Get(index, &temp) require.Equal(t, temp, res) @@ -67,12 +67,12 @@ func TestList(t *testing.T) { }) lm.Iterate(&res, func(index uint64) (brk bool) { - lm.Set(index, S{res.I + 1, !res.B}) + lm.Set(index, TestStruct{res.I + 1, !res.B}) return }) lm.Get(uint64(0), &res) - require.Equal(t, S{3, true}, res) + require.Equal(t, TestStruct{3, true}, res) } func TestListRandom(t *testing.T) { diff --git a/store/types/store.go b/store/types/store.go index ee52afb19fda..db696f688787 100644 --- a/store/types/store.go +++ b/store/types/store.go @@ -121,14 +121,14 @@ type KVStore interface { // Iterator must be closed by caller. // To iterate over entire domain, use store.Iterator(nil, nil) // CONTRACT: No writes may happen within a domain while an iterator exists over it. - // Exceptionally allowed for cachekv.Store + // Exceptionally allowed for cachekv.Store, safe to write in the modules. Iterator(start, end []byte) Iterator // Iterator over a domain of keys in descending order. End is exclusive. // Start must be less than end, or the Iterator is invalid. // Iterator must be closed by caller. // CONTRACT: No writes may happen within a domain while an iterator exists over it. - // Exceptionally allowed for cachekv.Store + // Exceptionally allowed for cachekv.Store, safe to write in the modules. ReverseIterator(start, end []byte) Iterator } diff --git a/store/types/utils.go b/store/types/utils.go index a86efdb8c82f..e57075b062b9 100644 --- a/store/types/utils.go +++ b/store/types/utils.go @@ -86,13 +86,3 @@ func InclusiveEndBytes(inclusiveBytes []byte) (exclusiveBytes []byte) { exclusiveBytes = append(inclusiveBytes, byte(0x00)) return exclusiveBytes } - -//---------------------------------------- -func Cp(bz []byte) (ret []byte) { - if bz == nil { - return nil - } - ret = make([]byte, len(bz)) - copy(ret, bz) - return ret -} diff --git a/types/utils.go b/types/utils.go index f5b244d74591..a0d23a04e467 100644 --- a/types/utils.go +++ b/types/utils.go @@ -58,3 +58,13 @@ func ParseTimeBytes(bz []byte) (time.Time, error) { } return t.UTC().Round(0), nil } + +//---------------------------------------- +func Cp(bz []byte) (ret []byte) { + if bz == nil { + return nil + } + ret = make([]byte, len(bz)) + copy(ret, bz) + return ret +} From fe063b37761c659ba47cc47ebd28783a528e8d98 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 25 Jan 2019 13:39:22 +0100 Subject: [PATCH 17/25] mv Cp() back to store --- store/firstlast.go | 2 +- store/iavl/store.go | 4 ++-- store/types/utils.go | 10 ++++++++++ types/utils.go | 10 ---------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/store/firstlast.go b/store/firstlast.go index 7c94356a6430..708a7d0d3dce 100644 --- a/store/firstlast.go +++ b/store/firstlast.go @@ -5,7 +5,7 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" ) // Gets the first item. diff --git a/store/iavl/store.go b/store/iavl/store.go index 481a6781a60a..40adba8352b4 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -290,8 +290,8 @@ var _ types.Iterator = (*iavlIterator)(nil) func newIAVLIterator(tree *iavl.ImmutableTree, start, end []byte, ascending bool) *iavlIterator { iter := &iavlIterator{ tree: tree, - start: types.Cp(start), - end: types.Cp(end), + start: stypes.Cp(start), + end: stypes.Cp(end), ascending: ascending, iterCh: make(chan cmn.KVPair, 0), // Set capacity > 0? quitCh: make(chan struct{}), diff --git a/store/types/utils.go b/store/types/utils.go index e57075b062b9..a86efdb8c82f 100644 --- a/store/types/utils.go +++ b/store/types/utils.go @@ -86,3 +86,13 @@ func InclusiveEndBytes(inclusiveBytes []byte) (exclusiveBytes []byte) { exclusiveBytes = append(inclusiveBytes, byte(0x00)) return exclusiveBytes } + +//---------------------------------------- +func Cp(bz []byte) (ret []byte) { + if bz == nil { + return nil + } + ret = make([]byte, len(bz)) + copy(ret, bz) + return ret +} diff --git a/types/utils.go b/types/utils.go index a0d23a04e467..f5b244d74591 100644 --- a/types/utils.go +++ b/types/utils.go @@ -58,13 +58,3 @@ func ParseTimeBytes(bz []byte) (time.Time, error) { } return t.UTC().Round(0), nil } - -//---------------------------------------- -func Cp(bz []byte) (ret []byte) { - if bz == nil { - return nil - } - ret = make([]byte, len(bz)) - copy(ret, bz) - return ret -} From 20e02f77a1729bedd1812e685d9a06ac7adcdcef Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 30 Jan 2019 07:50:25 +0900 Subject: [PATCH 18/25] Update store/cachemulti/store.go Co-Authored-By: mossid --- store/cachemulti/store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/cachemulti/store.go b/store/cachemulti/store.go index 69e14494d89a..e1257a3385b2 100644 --- a/store/cachemulti/store.go +++ b/store/cachemulti/store.go @@ -101,7 +101,7 @@ func (cms Store) GetStoreType() types.StoreType { return types.StoreTypeMulti } -// Write writes each underlying store. +// Write calls Write on each underlying store. func (cms Store) Write() { cms.db.Write() for _, store := range cms.stores { From 67c5541490b850a5053a65f497d35f3a91ff3e9c Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 30 Jan 2019 07:51:07 +0900 Subject: [PATCH 19/25] Update store/dbadapter/store.go Co-Authored-By: mossid --- store/dbadapter/store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/dbadapter/store.go b/store/dbadapter/store.go index accf9189ba11..b96c6f5ccc08 100644 --- a/store/dbadapter/store.go +++ b/store/dbadapter/store.go @@ -25,7 +25,7 @@ func (dsa Store) CacheWrap() types.CacheWrap { return cachekv.NewStore(dsa) } -// CacheWrapWithTrace implements the KVStore interface. +// CacheWrapWithTrace implements KVStore. func (dsa Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { return cachekv.NewStore(tracekv.NewStore(dsa, w, tc)) } From e1f3feceed45ddeca00d960677a8180afe324b75 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 30 Jan 2019 00:12:14 +0100 Subject: [PATCH 20/25] address comments --- baseapp/baseapp.go | 1 - 1 file changed, 1 deletion(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 33a69dbfd40b..ef5c692b9bb6 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -483,7 +483,6 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res // BeginBlock implements the ABCI application interface. func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { if app.cms.TracingEnabled() { - app.cms.SetTracingContext(nil) app.cms.SetTracingContext(sdk.TraceContext( map[string]interface{}{"blockHeight": req.Header.Height}, )) From 13470c31edb20a1e0504b22c1d6f6030724c7f82 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 30 Jan 2019 20:55:12 +0100 Subject: [PATCH 21/25] add README, fix lint, add AssertValidKey in prefix.Store --- store/README.md | 98 +++++++++++++++++++++++++++++++++++++++++ store/prefix/store.go | 1 + store/types/validity.go | 2 + 3 files changed, 101 insertions(+) create mode 100644 store/README.md diff --git a/store/README.md b/store/README.md new file mode 100644 index 000000000000..9c493b0dbedd --- /dev/null +++ b/store/README.md @@ -0,0 +1,98 @@ +# Store + +## CacheKV + +`cachekv.Store` is a wrapper `KVStore` which provides buffered writing / cached reading functionalities over the underlying `KVStore`. + +```go +type Store struct { + cache map[string]cValue + parent types.KVStore +} +``` + +### Get + +`Store.Get()` checks `Store.cache` first in order to find if there is any cached value associated with the key. If the value exists, the function returns it. If not, the function calls `Store.parent.Get()`, sets the key-value pair to the `Store.cache`, and returns it. + +### Set + +`Store.Set()` sets the key-value pair to the `Store.cache`. `cValue` has the field `dirty bool` which indicates whether the cached value is different from the underlying value. When `Store.Set()` cache new pair, the `cValue.dirty` is set true so when `Store.Write()` is called it can be written to the underlying store. + +### Iterator + +`Store.Iterator()` have to traverse on both caches items and the original items. In `Store.iterator()`, two iterators are generated for each of them, and merged. `memIterator` is essentially a slice of the `KVPair`s, used for cached items. `mergeIterator` is a combination of two iterators, + +## CacheMulti + +`cachemulti.Store` is a wrapper `MultiStore` which provides buffered writing / cached reading functionalities over the underlying `MutliStore` + +```go +type Store struct { + db types.CacheKVStore + stores map[types.StoreKey] types.CacheWrap +} +``` + +`cachemulti.Store` cache wraps all substores in its constructor and hold them in `Store.stores`. `Store.GetKVStore()` returns the store from `Store.stores`, and `Store.Write()` recursively calls `CacheWrap.Write()` on the substores. + +## DBAdapter + +`dbadapter.Store` is a adapter for `dbm.DB` making it fulfilling the `KVStore` interface. + +```go +type Store struct { + dbm.DB +} +``` + +`dbadapter.Store` embeds `dbm.DB`, so most of the `KVStore` interface functions are implemented. The other functions(mostly miscellaneous) are manually implemented. + +## IAVL + +`iavl.Store` is a base-layer self-balancing merkle tree. + +### Get + +### Set + +### Iterator + +## GasKV + +`gaskv.Store` is a wrapper `KVStore` which provides gas consuming functionalities over the underlying `KVStore`. + +## Prefix + +`prefix.Store` is a wrapper `KVStore` which provides automatic key-prefixing functionalities over the underlying `KVStore`. + +```go +type Store struct { + parent types.KVStore + prefix []byte +} +``` + +When `Store.{Get, Set}()` is called, the store forwards the call to its parent, with the key prefixed with the `Store.prefix`. + +When `Store.Iterator()` is called, it does not simply prefix the `Store.prefix`, since it does not work as intended. + +## RootMulti + +`rootmulti.Store` is a base-layer `MultiStore` where multiple `KVStore` can be mounted on it and retrieved via object-capability keys + +## TraceKV + +`tracekv.Store` is a wrapper `KVStore` which provides operation tracing functionalities over the underlying `KVStore`. + +## Transient + +`transient.Store` is a base-layer `KVStore` which is automatically discarded at the end of the block. + +```go +type Store struct { + dbadapter.Store +} +``` + +`Store.Store` is a `dbadapter.Store` with a `dbm.NewMemDB()`. All `KVStore` methods are reused. When `Store.Commit()` is called, new `dbadapter.Store` is assigned, discarding previous reference and making it garbage collected. diff --git a/store/prefix/store.go b/store/prefix/store.go index 93545a1aac08..a04995273baf 100644 --- a/store/prefix/store.go +++ b/store/prefix/store.go @@ -69,6 +69,7 @@ func (s Store) Has(key []byte) bool { // Implements KVStore func (s Store) Set(key, value []byte) { + types.AssertValidKey(key) types.AssertValidValue(value) s.parent.Set(s.key(key), value) } diff --git a/store/types/validity.go b/store/types/validity.go index 13897d7a2e20..59dbd0c032bd 100644 --- a/store/types/validity.go +++ b/store/types/validity.go @@ -1,11 +1,13 @@ package types +// Check if the key is valid(key is not nil) func AssertValidKey(key []byte) { if key == nil { panic("key is nil") } } +// Check if the value is valid(value is not nil) func AssertValidValue(value []byte) { if value == nil { panic("value is nil") From af69aeb4269a1c2ca55fa853667145c031d76e7f Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 31 Jan 2019 00:58:33 +0100 Subject: [PATCH 22/25] modify README --- store/README.md | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/store/README.md b/store/README.md index 9c493b0dbedd..7b43e9a1b753 100644 --- a/store/README.md +++ b/store/README.md @@ -21,7 +21,7 @@ type Store struct { ### Iterator -`Store.Iterator()` have to traverse on both caches items and the original items. In `Store.iterator()`, two iterators are generated for each of them, and merged. `memIterator` is essentially a slice of the `KVPair`s, used for cached items. `mergeIterator` is a combination of two iterators, +`Store.Iterator()` have to traverse on both caches items and the original items. In `Store.iterator()`, two iterators are generated for each of them, and merged. `memIterator` is essentially a slice of the `KVPair`s, used for cached items. `mergeIterator` is a combination of two iterators, where traverse happens ordered on both iterators. ## CacheMulti @@ -50,18 +50,29 @@ type Store struct { ## IAVL -`iavl.Store` is a base-layer self-balancing merkle tree. +`iavl.Store` is a base-layer self-balancing merkle tree. It is guaranteed that -### Get - -### Set +1. get/set operation is done within `O(log n)` +2. iteration efficiently returns the sorted elements within the range +3. each version is immutable, can be retrieved even after a commit -### Iterator +Specification and implementation of IAVL tree can be found in [https://github.com/tendermint/iavl]. ## GasKV `gaskv.Store` is a wrapper `KVStore` which provides gas consuming functionalities over the underlying `KVStore`. +```go +type Store struct { + gasMeter types.GasMeter + gasConfig types.GasConfig + parent types.KVStore +} +``` + +When each `KVStore` methods are called, `gaskv.Store` automatically consumes appropriate amount of gas depending on the `Store.gasConfig`. + + ## Prefix `prefix.Store` is a wrapper `KVStore` which provides automatic key-prefixing functionalities over the underlying `KVStore`. @@ -85,6 +96,27 @@ When `Store.Iterator()` is called, it does not simply prefix the `Store.prefix`, `tracekv.Store` is a wrapper `KVStore` which provides operation tracing functionalities over the underlying `KVStore`. +```go +type Store struct { + parent types.KVStore + writer io.Writer + context types.TraceContext +} +``` + +When each `KVStore` methods are called, `tracekv.Store` automatically logs `traceOperation` to the `Store.writer`. + +```go +type traceOperation struct { + Operation operation + Key string + Value string + Metadata map[string]interface{} +} +``` + +`traceOperation.Metadata` is filled with `Store.context` when it is not nil. `TraceContext` is a `map[string]interface{}`. + ## Transient `transient.Store` is a base-layer `KVStore` which is automatically discarded at the end of the block. From 7cd7880cef62990d2bcb049b928ce15e99cad4d3 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 30 Jan 2019 16:25:15 -0800 Subject: [PATCH 23/25] Update store/README.md Co-Authored-By: mossid --- store/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/README.md b/store/README.md index 7b43e9a1b753..bede6e55cc33 100644 --- a/store/README.md +++ b/store/README.md @@ -52,7 +52,7 @@ type Store struct { `iavl.Store` is a base-layer self-balancing merkle tree. It is guaranteed that -1. get/set operation is done within `O(log n)` +1. Get & set operations are `O(log n)`, where `n` is the number of elements in the tree 2. iteration efficiently returns the sorted elements within the range 3. each version is immutable, can be retrieved even after a commit From ab824548c12b80d5c3e87b7ff36a92da7db72019 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 30 Jan 2019 16:25:28 -0800 Subject: [PATCH 24/25] Update store/README.md Co-Authored-By: mossid --- store/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/README.md b/store/README.md index bede6e55cc33..5894eadc6859 100644 --- a/store/README.md +++ b/store/README.md @@ -53,7 +53,7 @@ type Store struct { `iavl.Store` is a base-layer self-balancing merkle tree. It is guaranteed that 1. Get & set operations are `O(log n)`, where `n` is the number of elements in the tree -2. iteration efficiently returns the sorted elements within the range +2. Iteration efficiently returns the sorted elements within the range 3. each version is immutable, can be retrieved even after a commit Specification and implementation of IAVL tree can be found in [https://github.com/tendermint/iavl]. From ae9eeb9dd89c13621aab812bbf2e40a23ebf92c4 Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 31 Jan 2019 01:30:46 +0100 Subject: [PATCH 25/25] address comments --- store/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/store/README.md b/store/README.md index 5894eadc6859..54994374bcd6 100644 --- a/store/README.md +++ b/store/README.md @@ -54,7 +54,7 @@ type Store struct { 1. Get & set operations are `O(log n)`, where `n` is the number of elements in the tree 2. Iteration efficiently returns the sorted elements within the range -3. each version is immutable, can be retrieved even after a commit +3. Each tree version is immutable and can be retrieved even after a commit(depending on the pruning settings) Specification and implementation of IAVL tree can be found in [https://github.com/tendermint/iavl]. @@ -86,11 +86,11 @@ type Store struct { When `Store.{Get, Set}()` is called, the store forwards the call to its parent, with the key prefixed with the `Store.prefix`. -When `Store.Iterator()` is called, it does not simply prefix the `Store.prefix`, since it does not work as intended. +When `Store.Iterator()` is called, it does not simply prefix the `Store.prefix`, since it does not work as intended. In that case, some of the elements are traversed even they are not starting with the prefix. ## RootMulti -`rootmulti.Store` is a base-layer `MultiStore` where multiple `KVStore` can be mounted on it and retrieved via object-capability keys +`rootmulti.Store` is a base-layer `MultiStore` where multiple `KVStore` can be mounted on it and retrieved via object-capability keys. The keys are memory addresses, so it is impossible to forge the key unless an object is a valid owner(or a receiver) of the key, according to the object capability principles. ## TraceKV