Move GasKVStore to /store

This commit is contained in:
Christopher Goes
2018-05-16 01:14:30 +02:00
parent 702ffafa06
commit 147cf9f897
8 changed files with 74 additions and 84 deletions
+1 -1
View File
@@ -69,7 +69,7 @@ func (c Context) Value(key interface{}) interface{} {
// KVStore fetches a KVStore from the MultiStore.
func (c Context) KVStore(key StoreKey) KVStore {
return NewGasKVStore(c.GasMeter(), c.multiStore().GetKVStore(key))
return c.multiStore().GetKVStoreWithGas(c.GasMeter(), key)
}
//----------------------------------------
-144
View File
@@ -1,144 +0,0 @@
package types
// nolint
const (
HasCost = 10
ReadCostFlat = 10
ReadCostPerByte = 1
WriteCostFlat = 10
WriteCostPerByte = 10
KeyCostFlat = 5
ValueCostFlat = 10
ValueCostPerByte = 1
)
// gasKVStore applies gas tracking to an underlying kvstore
type gasKVStore struct {
gasMeter GasMeter
parent KVStore
}
// nolint
func NewGasKVStore(gasMeter GasMeter, parent KVStore) *gasKVStore {
kvs := &gasKVStore{
gasMeter: gasMeter,
parent: parent,
}
return kvs
}
// Implements Store.
func (gi *gasKVStore) GetStoreType() StoreType {
return gi.parent.GetStoreType()
}
// Implements KVStore.
func (gi *gasKVStore) Get(key []byte) (value []byte) {
gi.gasMeter.ConsumeGas(ReadCostFlat, "GetFlat")
value = gi.parent.Get(key)
// TODO overflow-safe math?
gi.gasMeter.ConsumeGas(ReadCostPerByte*Gas(len(value)), "ReadPerByte")
return value
}
// Implements KVStore.
func (gi *gasKVStore) Set(key []byte, value []byte) {
gi.gasMeter.ConsumeGas(WriteCostFlat, "SetFlat")
// TODO overflow-safe math?
gi.gasMeter.ConsumeGas(WriteCostPerByte*Gas(len(value)), "SetPerByte")
gi.parent.Set(key, value)
}
// Implements KVStore.
func (gi *gasKVStore) Has(key []byte) bool {
gi.gasMeter.ConsumeGas(HasCost, "Has")
return gi.parent.Has(key)
}
// Implements KVStore.
func (gi *gasKVStore) Delete(key []byte) {
// No gas costs for deletion
gi.parent.Delete(key)
}
// Implements KVStore.
func (gi *gasKVStore) Iterator(start, end []byte) Iterator {
return gi.iterator(start, end, true)
}
// Implements KVStore.
func (gi *gasKVStore) ReverseIterator(start, end []byte) Iterator {
return gi.iterator(start, end, false)
}
// Implements KVStore.
func (gi *gasKVStore) SubspaceIterator(prefix []byte) Iterator {
return gi.iterator(prefix, PrefixEndBytes(prefix), true)
}
// Implements KVStore.
func (gi *gasKVStore) ReverseSubspaceIterator(prefix []byte) Iterator {
return gi.iterator(prefix, PrefixEndBytes(prefix), false)
}
// Implements KVStore.
func (gi *gasKVStore) CacheWrap() CacheWrap {
panic("you cannot CacheWrap a GasKVStore")
}
func (gi *gasKVStore) iterator(start, end []byte, ascending bool) Iterator {
var parent Iterator
if ascending {
parent = gi.parent.Iterator(start, end)
} else {
parent = gi.parent.ReverseIterator(start, end)
}
return newGasIterator(gi.gasMeter, parent)
}
type gasIterator struct {
gasMeter GasMeter
parent Iterator
}
func newGasIterator(gasMeter GasMeter, parent Iterator) Iterator {
return &gasIterator{
gasMeter: gasMeter,
parent: parent,
}
}
// Implements Iterator.
func (g *gasIterator) Domain() (start []byte, end []byte) {
return g.parent.Domain()
}
// Implements Iterator.
func (g *gasIterator) Valid() bool {
return g.parent.Valid()
}
// Implements Iterator.
func (g *gasIterator) Next() {
g.parent.Next()
}
// Implements Iterator.
func (g *gasIterator) Key() (key []byte) {
g.gasMeter.ConsumeGas(KeyCostFlat, "KeyFlat")
key = g.parent.Key()
return key
}
// Implements Iterator.
func (g *gasIterator) Value() (value []byte) {
value = g.parent.Value()
g.gasMeter.ConsumeGas(ValueCostFlat, "ValueFlat")
g.gasMeter.ConsumeGas(ValueCostPerByte*Gas(len(value)), "ValuePerByte")
return value
}
// Implements Iterator.
func (g *gasIterator) Close() {
g.parent.Close()
}
-63
View File
@@ -1,63 +0,0 @@
package types
import (
"testing"
"github.com/stretchr/testify/require"
cmn "github.com/tendermint/tmlibs/common"
dbm "github.com/tendermint/tmlibs/db"
)
func newGasKVStore() KVStore {
meter := NewGasMeter(1000)
mem := dbStoreAdapter{dbm.NewMemDB()}
return NewGasKVStore(meter, mem)
}
func TestGasKVStoreBasic(t *testing.T) {
mem := dbStoreAdapter{dbm.NewMemDB()}
meter := NewGasMeter(1000)
st := NewGasKVStore(meter, mem)
require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty")
mem.Set(keyFmt(1), valFmt(1))
st.Set(keyFmt(1), valFmt(1))
require.Equal(t, valFmt(1), st.Get(keyFmt(1)))
}
func TestGasKVStoreOutOfGas(t *testing.T) {
mem := dbStoreAdapter{dbm.NewMemDB()}
meter := NewGasMeter(0)
st := NewGasKVStore(meter, mem)
require.Panics(t, func() { st.Set(keyFmt(1), valFmt(1)) }, "Expected out-of-gas")
}
func keyFmt(i int) []byte { return bz(cmn.Fmt("key%0.8d", i)) }
func valFmt(i int) []byte { return bz(cmn.Fmt("value%0.8d", i)) }
func bz(s string) []byte { return []byte(s) }
type dbStoreAdapter struct {
dbm.DB
}
// Implements Store.
func (dbStoreAdapter) GetStoreType() StoreType {
return StoreTypeDB
}
// Implements KVStore.
func (dsa dbStoreAdapter) CacheWrap() CacheWrap {
panic("unsupported")
}
func (dsa dbStoreAdapter) SubspaceIterator(prefix []byte) Iterator {
return dsa.Iterator(prefix, PrefixEndBytes(prefix))
}
func (dsa dbStoreAdapter) ReverseSubspaceIterator(prefix []byte) Iterator {
return dsa.ReverseIterator(prefix, PrefixEndBytes(prefix))
}
// dbm.DB implements KVStore so we can CacheKVStore it.
var _ KVStore = dbStoreAdapter{dbm.DB(nil)}
+1
View File
@@ -49,6 +49,7 @@ type MultiStore interface { //nolint
// Convenience for fetching substores.
GetStore(StoreKey) Store
GetKVStore(StoreKey) KVStore
GetKVStoreWithGas(GasMeter, StoreKey) KVStore
}
// From MultiStore.CacheMultiStore()....