Merge PR #3395: Store Refactor 2

This commit is contained in:
Joon 2019-02-05 10:39:22 -08:00 committed by Christopher Goes
parent 174ec0c809
commit d50f3ee4fb
7 changed files with 85 additions and 56 deletions

29
store/errors/errors.go Normal file
View File

@ -0,0 +1,29 @@
package errors
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// nolint - reexport
const (
CodeOK = sdk.CodeOK
CodeInternal = sdk.CodeInternal
CodeTxDecode = sdk.CodeTxDecode
CodeUnknownRequest = sdk.CodeUnknownRequest
CodespaceRoot = sdk.CodespaceRoot
)
// nolint - reexport
type Error = sdk.Error
// nolint - reexport
func ErrInternal(msg string) Error {
return sdk.ErrInternal(msg)
}
func ErrTxDecode(msg string) Error {
return sdk.ErrTxDecode(msg)
}
func ErrUnknownRequest(msg string) Error {
return sdk.ErrUnknownRequest(msg)
}

View File

@ -8,15 +8,15 @@ import (
"github.com/cosmos/cosmos-sdk/store/dbadapter" "github.com/cosmos/cosmos-sdk/store/dbadapter"
"github.com/cosmos/cosmos-sdk/store/gaskv" "github.com/cosmos/cosmos-sdk/store/gaskv"
stypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/store/types"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func newGasKVStore() stypes.KVStore { func newGasKVStore() types.KVStore {
meter := stypes.NewGasMeter(10000) meter := types.NewGasMeter(10000)
mem := dbadapter.Store{dbm.NewMemDB()} mem := dbadapter.Store{dbm.NewMemDB()}
return gaskv.NewStore(mem, meter, stypes.KVGasConfig()) return gaskv.NewStore(mem, meter, types.KVGasConfig())
} }
func bz(s string) []byte { return []byte(s) } func bz(s string) []byte { return []byte(s) }
@ -26,20 +26,20 @@ func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) }
func TestGasKVStoreBasic(t *testing.T) { func TestGasKVStoreBasic(t *testing.T) {
mem := dbadapter.Store{dbm.NewMemDB()} mem := dbadapter.Store{dbm.NewMemDB()}
meter := stypes.NewGasMeter(10000) meter := types.NewGasMeter(10000)
st := gaskv.NewStore(mem, meter, stypes.KVGasConfig()) st := gaskv.NewStore(mem, meter, types.KVGasConfig())
require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty")
st.Set(keyFmt(1), valFmt(1)) st.Set(keyFmt(1), valFmt(1))
require.Equal(t, valFmt(1), st.Get(keyFmt(1))) require.Equal(t, valFmt(1), st.Get(keyFmt(1)))
st.Delete(keyFmt(1)) st.Delete(keyFmt(1))
require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty")
require.Equal(t, meter.GasConsumed(), stypes.Gas(6429)) require.Equal(t, meter.GasConsumed(), types.Gas(6429))
} }
func TestGasKVStoreIterator(t *testing.T) { func TestGasKVStoreIterator(t *testing.T) {
mem := dbadapter.Store{dbm.NewMemDB()} mem := dbadapter.Store{dbm.NewMemDB()}
meter := stypes.NewGasMeter(10000) meter := types.NewGasMeter(10000)
st := gaskv.NewStore(mem, meter, stypes.KVGasConfig()) st := gaskv.NewStore(mem, meter, types.KVGasConfig())
require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty")
require.Empty(t, st.Get(keyFmt(2)), "Expected `key2` to be empty") require.Empty(t, st.Get(keyFmt(2)), "Expected `key2` to be empty")
st.Set(keyFmt(1), valFmt(1)) st.Set(keyFmt(1), valFmt(1))
@ -57,20 +57,20 @@ func TestGasKVStoreIterator(t *testing.T) {
iterator.Next() iterator.Next()
require.False(t, iterator.Valid()) require.False(t, iterator.Valid())
require.Panics(t, iterator.Next) require.Panics(t, iterator.Next)
require.Equal(t, meter.GasConsumed(), stypes.Gas(6987)) require.Equal(t, meter.GasConsumed(), types.Gas(6987))
} }
func TestGasKVStoreOutOfGasSet(t *testing.T) { func TestGasKVStoreOutOfGasSet(t *testing.T) {
mem := dbadapter.Store{dbm.NewMemDB()} mem := dbadapter.Store{dbm.NewMemDB()}
meter := stypes.NewGasMeter(0) meter := types.NewGasMeter(0)
st := gaskv.NewStore(mem, meter, stypes.KVGasConfig()) st := gaskv.NewStore(mem, meter, types.KVGasConfig())
require.Panics(t, func() { st.Set(keyFmt(1), valFmt(1)) }, "Expected out-of-gas") require.Panics(t, func() { st.Set(keyFmt(1), valFmt(1)) }, "Expected out-of-gas")
} }
func TestGasKVStoreOutOfGasIterator(t *testing.T) { func TestGasKVStoreOutOfGasIterator(t *testing.T) {
mem := dbadapter.Store{dbm.NewMemDB()} mem := dbadapter.Store{dbm.NewMemDB()}
meter := stypes.NewGasMeter(20000) meter := types.NewGasMeter(20000)
st := gaskv.NewStore(mem, meter, stypes.KVGasConfig()) st := gaskv.NewStore(mem, meter, types.KVGasConfig())
st.Set(keyFmt(1), valFmt(1)) st.Set(keyFmt(1), valFmt(1))
iterator := st.Iterator(nil, nil) iterator := st.Iterator(nil, nil)
iterator.Next() iterator.Next()

View File

@ -11,11 +11,10 @@ import (
cmn "github.com/tendermint/tendermint/libs/common" cmn "github.com/tendermint/tendermint/libs/common"
dbm "github.com/tendermint/tendermint/libs/db" 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" "github.com/cosmos/cosmos-sdk/store/cachekv"
"github.com/cosmos/cosmos-sdk/store/errors"
"github.com/cosmos/cosmos-sdk/store/tracekv" "github.com/cosmos/cosmos-sdk/store/tracekv"
"github.com/cosmos/cosmos-sdk/store/types"
) )
const ( const (
@ -132,7 +131,7 @@ func (st *Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.Ca
// Implements types.KVStore. // Implements types.KVStore.
func (st *Store) Set(key, value []byte) { func (st *Store) Set(key, value []byte) {
stypes.AssertValidValue(value) types.AssertValidValue(value)
st.tree.Set(key, value) st.tree.Set(key, value)
} }
@ -186,7 +185,7 @@ func getHeight(tree *iavl.MutableTree, req abci.RequestQuery) int64 {
func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) { func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
if len(req.Data) == 0 { if len(req.Data) == 0 {
msg := "Query cannot be zero length" msg := "Query cannot be zero length"
return types.ErrTxDecode(msg).QueryResult() return errors.ErrTxDecode(msg).QueryResult()
} }
tree := st.tree tree := st.tree
@ -236,7 +235,7 @@ func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
subspace := req.Data subspace := req.Data
res.Key = subspace res.Key = subspace
iterator := stypes.KVStorePrefixIterator(st, subspace) iterator := types.KVStorePrefixIterator(st, subspace)
for ; iterator.Valid(); iterator.Next() { for ; iterator.Valid(); iterator.Next() {
KVs = append(KVs, types.KVPair{Key: iterator.Key(), Value: iterator.Value()}) KVs = append(KVs, types.KVPair{Key: iterator.Key(), Value: iterator.Value()})
} }
@ -246,7 +245,7 @@ func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
default: default:
msg := fmt.Sprintf("Unexpected Query path: %v", req.Path) msg := fmt.Sprintf("Unexpected Query path: %v", req.Path)
return types.ErrUnknownRequest(msg).QueryResult() return errors.ErrUnknownRequest(msg).QueryResult()
} }
return return
@ -291,8 +290,8 @@ var _ types.Iterator = (*iavlIterator)(nil)
func newIAVLIterator(tree *iavl.ImmutableTree, start, end []byte, ascending bool) *iavlIterator { func newIAVLIterator(tree *iavl.ImmutableTree, start, end []byte, ascending bool) *iavlIterator {
iter := &iavlIterator{ iter := &iavlIterator{
tree: tree, tree: tree,
start: stypes.Cp(start), start: types.Cp(start),
end: stypes.Cp(end), end: types.Cp(end),
ascending: ascending, ascending: ascending,
iterCh: make(chan cmn.KVPair, 0), // Set capacity > 0? iterCh: make(chan cmn.KVPair, 0), // Set capacity > 0?
quitCh: make(chan struct{}), quitCh: make(chan struct{}),

View File

@ -11,7 +11,8 @@ import (
cmn "github.com/tendermint/tendermint/libs/common" cmn "github.com/tendermint/tendermint/libs/common"
dbm "github.com/tendermint/tendermint/libs/db" dbm "github.com/tendermint/tendermint/libs/db"
"github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/store/errors"
"github.com/cosmos/cosmos-sdk/store/types"
) )
var ( var (
@ -443,7 +444,7 @@ func TestIAVLStoreQuery(t *testing.T) {
// query subspace before anything set // query subspace before anything set
qres := iavlStore.Query(querySub) qres := iavlStore.Query(querySub)
require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, valExpSubEmpty, qres.Value) require.Equal(t, valExpSubEmpty, qres.Value)
// set data // set data
@ -452,24 +453,24 @@ func TestIAVLStoreQuery(t *testing.T) {
// set data without commit, doesn't show up // set data without commit, doesn't show up
qres = iavlStore.Query(query) qres = iavlStore.Query(query)
require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Nil(t, qres.Value) require.Nil(t, qres.Value)
// commit it, but still don't see on old version // commit it, but still don't see on old version
cid = iavlStore.Commit() cid = iavlStore.Commit()
qres = iavlStore.Query(query) qres = iavlStore.Query(query)
require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Nil(t, qres.Value) require.Nil(t, qres.Value)
// but yes on the new version // but yes on the new version
query.Height = cid.Version query.Height = cid.Version
qres = iavlStore.Query(query) qres = iavlStore.Query(query)
require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, v1, qres.Value) require.Equal(t, v1, qres.Value)
// and for the subspace // and for the subspace
qres = iavlStore.Query(querySub) qres = iavlStore.Query(querySub)
require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, valExpSub1, qres.Value) require.Equal(t, valExpSub1, qres.Value)
// modify // modify
@ -478,28 +479,28 @@ func TestIAVLStoreQuery(t *testing.T) {
// query will return old values, as height is fixed // query will return old values, as height is fixed
qres = iavlStore.Query(query) qres = iavlStore.Query(query)
require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, v1, qres.Value) require.Equal(t, v1, qres.Value)
// update to latest in the query and we are happy // update to latest in the query and we are happy
query.Height = cid.Version query.Height = cid.Version
qres = iavlStore.Query(query) qres = iavlStore.Query(query)
require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, v3, qres.Value) require.Equal(t, v3, qres.Value)
query2 := abci.RequestQuery{Path: "/key", Data: k2, Height: cid.Version} query2 := abci.RequestQuery{Path: "/key", Data: k2, Height: cid.Version}
qres = iavlStore.Query(query2) qres = iavlStore.Query(query2)
require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, v2, qres.Value) require.Equal(t, v2, qres.Value)
// and for the subspace // and for the subspace
qres = iavlStore.Query(querySub) qres = iavlStore.Query(querySub)
require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, valExpSub2, qres.Value) require.Equal(t, valExpSub2, qres.Value)
// default (height 0) will show latest -1 // default (height 0) will show latest -1
query0 := abci.RequestQuery{Path: "/key", Data: k1} query0 := abci.RequestQuery{Path: "/key", Data: k1}
qres = iavlStore.Query(query0) qres = iavlStore.Query(query0)
require.Equal(t, uint32(types.CodeOK), qres.Code) require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, v1, qres.Value) require.Equal(t, v1, qres.Value)
} }

View File

@ -3,19 +3,18 @@ package rootmulti
import ( import (
"testing" "testing"
"github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
dbm "github.com/tendermint/tendermint/libs/db" dbm "github.com/tendermint/tendermint/libs/db"
"github.com/cosmos/cosmos-sdk/store/iavl" "github.com/cosmos/cosmos-sdk/store/iavl"
stypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/store/types"
) )
func TestVerifyIAVLStoreQueryProof(t *testing.T) { func TestVerifyIAVLStoreQueryProof(t *testing.T) {
// Create main tree for testing. // Create main tree for testing.
db := dbm.NewMemDB() db := dbm.NewMemDB()
iStore, err := iavl.LoadStore(db, types.CommitID{}, stypes.PruneNothing) iStore, err := iavl.LoadStore(db, types.CommitID{}, types.PruneNothing)
store := iStore.(*iavl.Store) store := iStore.(*iavl.Store)
require.Nil(t, err) require.Nil(t, err)
store.Set([]byte("MYKEY"), []byte("MYVALUE")) store.Set([]byte("MYKEY"), []byte("MYVALUE"))

View File

@ -12,10 +12,11 @@ import (
"github.com/cosmos/cosmos-sdk/store/cachemulti" "github.com/cosmos/cosmos-sdk/store/cachemulti"
"github.com/cosmos/cosmos-sdk/store/dbadapter" "github.com/cosmos/cosmos-sdk/store/dbadapter"
"github.com/cosmos/cosmos-sdk/store/errors"
"github.com/cosmos/cosmos-sdk/store/iavl" "github.com/cosmos/cosmos-sdk/store/iavl"
"github.com/cosmos/cosmos-sdk/store/tracekv" "github.com/cosmos/cosmos-sdk/store/tracekv"
"github.com/cosmos/cosmos-sdk/store/transient" "github.com/cosmos/cosmos-sdk/store/transient"
"github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/store/types"
) )
const ( const (
@ -288,12 +289,12 @@ func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery {
store := rs.getStoreByName(storeName) store := rs.getStoreByName(storeName)
if store == nil { if store == nil {
msg := fmt.Sprintf("no such store: %s", storeName) msg := fmt.Sprintf("no such store: %s", storeName)
return types.ErrUnknownRequest(msg).QueryResult() return errors.ErrUnknownRequest(msg).QueryResult()
} }
queryable, ok := store.(types.Queryable) queryable, ok := store.(types.Queryable)
if !ok { if !ok {
msg := fmt.Sprintf("store %s doesn't support queries", storeName) msg := fmt.Sprintf("store %s doesn't support queries", storeName)
return types.ErrUnknownRequest(msg).QueryResult() return errors.ErrUnknownRequest(msg).QueryResult()
} }
// trim the path and make the query // trim the path and make the query
@ -305,12 +306,12 @@ func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery {
} }
if res.Proof == nil || len(res.Proof.Ops) == 0 { if res.Proof == nil || len(res.Proof.Ops) == 0 {
return types.ErrInternal("substore proof was nil/empty when it should never be").QueryResult() return errors.ErrInternal("substore proof was nil/empty when it should never be").QueryResult()
} }
commitInfo, errMsg := getCommitInfo(rs.db, res.Height) commitInfo, errMsg := getCommitInfo(rs.db, res.Height)
if errMsg != nil { if errMsg != nil {
return types.ErrInternal(errMsg.Error()).QueryResult() return errors.ErrInternal(errMsg.Error()).QueryResult()
} }
// Restore origin path and append proof op. // Restore origin path and append proof op.
@ -327,9 +328,9 @@ func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery {
// parsePath expects a format like /<storeName>[/<subpath>] // parsePath expects a format like /<storeName>[/<subpath>]
// Must start with /, subpath may be empty // Must start with /, subpath may be empty
// Returns error if it doesn't start with / // Returns error if it doesn't start with /
func parsePath(path string) (storeName string, subpath string, err types.Error) { func parsePath(path string) (storeName string, subpath string, err errors.Error) {
if !strings.HasPrefix(path, "/") { if !strings.HasPrefix(path, "/") {
err = types.ErrUnknownRequest(fmt.Sprintf("invalid path: %s", path)) err = errors.ErrUnknownRequest(fmt.Sprintf("invalid path: %s", path))
return return
} }

View File

@ -8,8 +8,8 @@ import (
"github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/crypto/merkle"
dbm "github.com/tendermint/tendermint/libs/db" dbm "github.com/tendermint/tendermint/libs/db"
stypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/store/errors"
"github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/store/types"
) )
const useDebugDB = false const useDebugDB = false
@ -157,37 +157,37 @@ func TestMultiStoreQuery(t *testing.T) {
// Test bad path. // Test bad path.
query := abci.RequestQuery{Path: "/key", Data: k, Height: ver} query := abci.RequestQuery{Path: "/key", Data: k, Height: ver}
qres := multi.Query(query) qres := multi.Query(query)
require.EqualValues(t, types.CodeUnknownRequest, qres.Code) require.EqualValues(t, errors.CodeUnknownRequest, qres.Code)
require.EqualValues(t, types.CodespaceRoot, qres.Codespace) require.EqualValues(t, errors.CodespaceRoot, qres.Codespace)
query.Path = "h897fy32890rf63296r92" query.Path = "h897fy32890rf63296r92"
qres = multi.Query(query) qres = multi.Query(query)
require.EqualValues(t, types.CodeUnknownRequest, qres.Code) require.EqualValues(t, errors.CodeUnknownRequest, qres.Code)
require.EqualValues(t, types.CodespaceRoot, qres.Codespace) require.EqualValues(t, errors.CodespaceRoot, qres.Codespace)
// Test invalid store name. // Test invalid store name.
query.Path = "/garbage/key" query.Path = "/garbage/key"
qres = multi.Query(query) qres = multi.Query(query)
require.EqualValues(t, types.CodeUnknownRequest, qres.Code) require.EqualValues(t, errors.CodeUnknownRequest, qres.Code)
require.EqualValues(t, types.CodespaceRoot, qres.Codespace) require.EqualValues(t, errors.CodespaceRoot, qres.Codespace)
// Test valid query with data. // Test valid query with data.
query.Path = "/store1/key" query.Path = "/store1/key"
qres = multi.Query(query) qres = multi.Query(query)
require.EqualValues(t, types.CodeOK, qres.Code) require.EqualValues(t, errors.CodeOK, qres.Code)
require.Equal(t, v, qres.Value) require.Equal(t, v, qres.Value)
// Test valid but empty query. // Test valid but empty query.
query.Path = "/store2/key" query.Path = "/store2/key"
query.Prove = true query.Prove = true
qres = multi.Query(query) qres = multi.Query(query)
require.EqualValues(t, types.CodeOK, qres.Code) require.EqualValues(t, errors.CodeOK, qres.Code)
require.Nil(t, qres.Value) require.Nil(t, qres.Value)
// Test store2 data. // Test store2 data.
query.Data = k2 query.Data = k2
qres = multi.Query(query) qres = multi.Query(query)
require.EqualValues(t, types.CodeOK, qres.Code) require.EqualValues(t, errors.CodeOK, qres.Code)
require.Equal(t, v2, qres.Value) require.Equal(t, v2, qres.Value)
} }
@ -196,7 +196,7 @@ func TestMultiStoreQuery(t *testing.T) {
func newMultiStoreWithMounts(db dbm.DB) *Store { func newMultiStoreWithMounts(db dbm.DB) *Store {
store := NewStore(db) store := NewStore(db)
store.pruningOpts = stypes.PruneSyncable store.pruningOpts = types.PruneSyncable
store.MountStoreWithDB( store.MountStoreWithDB(
types.NewKVStoreKey("store1"), types.StoreTypeIAVL, nil) types.NewKVStoreKey("store1"), types.StoreTypeIAVL, nil)
store.MountStoreWithDB( store.MountStoreWithDB(