Merge PR #1481: Transient Stores
This commit is contained in:
parent
74e06d8b96
commit
d46140a392
|
@ -35,6 +35,7 @@ FEATURES
|
|||
* [cosmos-sdk-cli] Added support for cosmos-sdk-cli tool under cosmos-sdk/cmd
|
||||
* This allows SDK users to initialize a new project repository.
|
||||
* [tests] Remotenet commands for AWS (awsnet)
|
||||
* [store] Add transient store
|
||||
|
||||
IMPROVEMENTS
|
||||
* [baseapp] Allow any alphanumeric character in route
|
||||
|
|
|
@ -47,6 +47,7 @@ type GaiaApp struct {
|
|||
keyGov *sdk.KVStoreKey
|
||||
keyFeeCollection *sdk.KVStoreKey
|
||||
keyParams *sdk.KVStoreKey
|
||||
tkeyParams *sdk.TransientStoreKey
|
||||
|
||||
// Manage getting and setting accounts
|
||||
accountMapper auth.AccountMapper
|
||||
|
@ -77,6 +78,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
|
|||
keyGov: sdk.NewKVStoreKey("gov"),
|
||||
keyFeeCollection: sdk.NewKVStoreKey("fee"),
|
||||
keyParams: sdk.NewKVStoreKey("params"),
|
||||
tkeyParams: sdk.NewTransientStoreKey("params"),
|
||||
}
|
||||
|
||||
// define the accountMapper
|
||||
|
@ -109,6 +111,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
|
|||
app.SetEndBlocker(app.EndBlocker)
|
||||
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
|
||||
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams)
|
||||
app.MountStore(app.tkeyParams, sdk.StoreTypeTransient)
|
||||
err := app.LoadLatestVersion(app.keyMain)
|
||||
if err != nil {
|
||||
cmn.Exit(err.Error())
|
||||
|
|
Binary file not shown.
|
@ -11,8 +11,8 @@ import (
|
|||
type ValidatorSet struct {
|
||||
sdk.ValidatorSet
|
||||
|
||||
key sdk.KVStoreGetter
|
||||
cdc *wire.Codec
|
||||
store sdk.KVStore
|
||||
cdc *wire.Codec
|
||||
|
||||
maxAssoc int
|
||||
addrLen int
|
||||
|
@ -21,15 +21,15 @@ type ValidatorSet struct {
|
|||
var _ sdk.ValidatorSet = ValidatorSet{}
|
||||
|
||||
// NewValidatorSet returns new ValidatorSet with underlying ValidatorSet
|
||||
func NewValidatorSet(cdc *wire.Codec, key sdk.KVStoreGetter, valset sdk.ValidatorSet, maxAssoc int, addrLen int) ValidatorSet {
|
||||
func NewValidatorSet(cdc *wire.Codec, store sdk.KVStore, valset sdk.ValidatorSet, maxAssoc int, addrLen int) ValidatorSet {
|
||||
if maxAssoc < 0 || addrLen < 0 {
|
||||
panic("Cannot use negative integer for NewValidatorSet")
|
||||
}
|
||||
return ValidatorSet{
|
||||
ValidatorSet: valset,
|
||||
|
||||
key: key,
|
||||
cdc: cdc,
|
||||
store: store,
|
||||
cdc: cdc,
|
||||
|
||||
maxAssoc: maxAssoc,
|
||||
addrLen: addrLen,
|
||||
|
@ -38,8 +38,7 @@ func NewValidatorSet(cdc *wire.Codec, key sdk.KVStoreGetter, valset sdk.Validato
|
|||
|
||||
// Implements sdk.ValidatorSet
|
||||
func (valset ValidatorSet) Validator(ctx sdk.Context, addr sdk.AccAddress) (res sdk.Validator) {
|
||||
store := valset.key.KVStore(ctx)
|
||||
base := store.Get(GetBaseKey(addr))
|
||||
base := valset.store.Get(GetBaseKey(addr))
|
||||
res = valset.ValidatorSet.Validator(ctx, base)
|
||||
if res == nil {
|
||||
res = valset.ValidatorSet.Validator(ctx, addr)
|
||||
|
@ -67,13 +66,12 @@ func (valset ValidatorSet) Associate(ctx sdk.Context, base sdk.AccAddress, assoc
|
|||
if len(base) != valset.addrLen || len(assoc) != valset.addrLen {
|
||||
return false
|
||||
}
|
||||
store := valset.key.KVStore(ctx)
|
||||
// If someone already owns the associated address
|
||||
if store.Get(GetBaseKey(assoc)) != nil {
|
||||
if valset.store.Get(GetBaseKey(assoc)) != nil {
|
||||
return false
|
||||
}
|
||||
store.Set(GetBaseKey(assoc), base)
|
||||
store.Set(GetAssocKey(base, assoc), []byte{0x00})
|
||||
valset.store.Set(GetBaseKey(assoc), base)
|
||||
valset.store.Set(GetAssocKey(base, assoc), []byte{0x00})
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -82,21 +80,19 @@ func (valset ValidatorSet) Dissociate(ctx sdk.Context, base sdk.AccAddress, asso
|
|||
if len(base) != valset.addrLen || len(assoc) != valset.addrLen {
|
||||
return false
|
||||
}
|
||||
store := valset.key.KVStore(ctx)
|
||||
// No associated address found for given validator
|
||||
if !bytes.Equal(store.Get(GetBaseKey(assoc)), base) {
|
||||
if !bytes.Equal(valset.store.Get(GetBaseKey(assoc)), base) {
|
||||
return false
|
||||
}
|
||||
store.Delete(GetBaseKey(assoc))
|
||||
store.Delete(GetAssocKey(base, assoc))
|
||||
valset.store.Delete(GetBaseKey(assoc))
|
||||
valset.store.Delete(GetAssocKey(base, assoc))
|
||||
return true
|
||||
}
|
||||
|
||||
// Associations returns all associated addresses with a validator
|
||||
func (valset ValidatorSet) Associations(ctx sdk.Context, base sdk.AccAddress) (res []sdk.AccAddress) {
|
||||
store := valset.key.KVStore(ctx)
|
||||
res = make([]sdk.AccAddress, valset.maxAssoc)
|
||||
iter := sdk.KVStorePrefixIterator(store, GetAssocPrefix(base))
|
||||
iter := sdk.KVStorePrefixIterator(valset.store, GetAssocPrefix(base))
|
||||
i := 0
|
||||
for ; iter.Valid(); iter.Next() {
|
||||
key := iter.Key()
|
||||
|
|
|
@ -36,7 +36,7 @@ func TestValidatorSet(t *testing.T) {
|
|||
{addr2, sdk.NewRat(2)},
|
||||
}}
|
||||
|
||||
valset := NewValidatorSet(wire.NewCodec(), sdk.NewPrefixStoreGetter(key, []byte("assoc")), base, 1, 5)
|
||||
valset := NewValidatorSet(wire.NewCodec(), ctx.KVStore(key).Prefix([]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))
|
||||
|
|
|
@ -26,7 +26,7 @@ func (keeper Keeper) update(ctx sdk.Context, val sdk.Validator, valset sdk.Valid
|
|||
info.Power = sdk.ZeroRat()
|
||||
info.Hash = hash
|
||||
prefix := GetSignPrefix(p, keeper.cdc)
|
||||
store := keeper.key.KVStore(ctx)
|
||||
store := ctx.KVStore(keeper.key)
|
||||
iter := sdk.KVStorePrefixIterator(store, prefix)
|
||||
for ; iter.Valid(); iter.Next() {
|
||||
if valset.Validator(ctx, iter.Value()) != nil {
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
// Keeper of the oracle store
|
||||
type Keeper struct {
|
||||
key sdk.KVStoreGetter
|
||||
key sdk.StoreKey
|
||||
cdc *wire.Codec
|
||||
|
||||
valset sdk.ValidatorSet
|
||||
|
@ -18,7 +18,7 @@ type Keeper struct {
|
|||
}
|
||||
|
||||
// NewKeeper constructs a new keeper
|
||||
func NewKeeper(key sdk.KVStoreGetter, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Rat, timeout int64) Keeper {
|
||||
func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Rat, timeout int64) Keeper {
|
||||
if timeout < 0 {
|
||||
panic("Timeout should not be negative")
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ func EmptyInfo(ctx sdk.Context) Info {
|
|||
|
||||
// Info returns the information about a payload
|
||||
func (keeper Keeper) Info(ctx sdk.Context, p Payload) (res Info) {
|
||||
store := keeper.key.KVStore(ctx)
|
||||
store := ctx.KVStore(keeper.key)
|
||||
|
||||
key := GetInfoKey(p, keeper.cdc)
|
||||
bz := store.Get(key)
|
||||
|
@ -77,7 +77,7 @@ func (keeper Keeper) Info(ctx sdk.Context, p Payload) (res Info) {
|
|||
}
|
||||
|
||||
func (keeper Keeper) setInfo(ctx sdk.Context, p Payload, info Info) {
|
||||
store := keeper.key.KVStore(ctx)
|
||||
store := ctx.KVStore(keeper.key)
|
||||
|
||||
key := GetInfoKey(p, keeper.cdc)
|
||||
bz := keeper.cdc.MustMarshalBinary(info)
|
||||
|
@ -85,21 +85,21 @@ func (keeper Keeper) setInfo(ctx sdk.Context, p Payload, info Info) {
|
|||
}
|
||||
|
||||
func (keeper Keeper) sign(ctx sdk.Context, p Payload, signer sdk.AccAddress) {
|
||||
store := keeper.key.KVStore(ctx)
|
||||
store := ctx.KVStore(keeper.key)
|
||||
|
||||
key := GetSignKey(p, signer, keeper.cdc)
|
||||
store.Set(key, signer)
|
||||
}
|
||||
|
||||
func (keeper Keeper) signed(ctx sdk.Context, p Payload, signer sdk.AccAddress) bool {
|
||||
store := keeper.key.KVStore(ctx)
|
||||
store := ctx.KVStore(keeper.key)
|
||||
|
||||
key := GetSignKey(p, signer, keeper.cdc)
|
||||
return store.Has(key)
|
||||
}
|
||||
|
||||
func (keeper Keeper) clearSigns(ctx sdk.Context, p Payload) {
|
||||
store := keeper.key.KVStore(ctx)
|
||||
store := ctx.KVStore(keeper.key)
|
||||
|
||||
prefix := GetSignPrefix(p, keeper.cdc)
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ func TestOracle(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz})
|
||||
|
||||
ork := NewKeeper(sdk.NewPrefixStoreGetter(key, []byte("oracle")), cdc, valset, sdk.NewRat(2, 3), 100)
|
||||
ork := NewKeeper(key, cdc, valset, sdk.NewRat(2, 3), 100)
|
||||
h := seqHandler(ork, key, sdk.CodespaceRoot)
|
||||
|
||||
// Nonmock.Validator signed, transaction failed
|
||||
|
|
|
@ -8,6 +8,8 @@ import (
|
|||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
var _ sdk.MultiStore = multiStore{}
|
||||
|
||||
type multiStore struct {
|
||||
kv map[sdk.StoreKey]kvStore
|
||||
}
|
||||
|
@ -76,10 +78,6 @@ func (ms multiStore) GetKVStore(key sdk.StoreKey) sdk.KVStore {
|
|||
return ms.kv[key]
|
||||
}
|
||||
|
||||
func (ms multiStore) GetKVStoreWithGas(meter sdk.GasMeter, key sdk.StoreKey) sdk.KVStore {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (ms multiStore) GetStore(key sdk.StoreKey) sdk.Store {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
@ -88,6 +86,8 @@ func (ms multiStore) GetStoreType() sdk.StoreType {
|
|||
panic("not implemented")
|
||||
}
|
||||
|
||||
var _ sdk.KVStore = kvStore{}
|
||||
|
||||
type kvStore struct {
|
||||
store map[string][]byte
|
||||
}
|
||||
|
@ -129,6 +129,10 @@ func (kv kvStore) Prefix(prefix []byte) sdk.KVStore {
|
|||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (kv kvStore) Gas(meter sdk.GasMeter, config sdk.GasConfig) sdk.KVStore {
|
||||
panic("not implmeneted")
|
||||
}
|
||||
|
||||
func (kv kvStore) Iterator(start, end []byte) sdk.Iterator {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
|
|
@ -85,6 +85,11 @@ func (ci *cacheKVStore) Prefix(prefix []byte) KVStore {
|
|||
return prefixStore{ci, prefix}
|
||||
}
|
||||
|
||||
// Implements KVStore
|
||||
func (ci *cacheKVStore) Gas(meter GasMeter, config GasConfig) KVStore {
|
||||
return NewGasKVStore(meter, config, ci)
|
||||
}
|
||||
|
||||
// Implements CacheKVStore.
|
||||
func (ci *cacheKVStore) Write() {
|
||||
ci.mtx.Lock()
|
||||
|
|
|
@ -134,6 +134,6 @@ func (cms cacheMultiStore) GetKVStore(key StoreKey) KVStore {
|
|||
}
|
||||
|
||||
// Implements MultiStore.
|
||||
func (cms cacheMultiStore) GetKVStoreWithGas(meter sdk.GasMeter, key StoreKey) KVStore {
|
||||
return NewGasKVStore(meter, cms.GetKVStore(key))
|
||||
func (cms cacheMultiStore) GetKVStoreWithGas(meter sdk.GasMeter, config sdk.GasConfig, key StoreKey) KVStore {
|
||||
return NewGasKVStore(meter, config, cms.GetKVStore(key))
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
)
|
||||
|
||||
// Wrapper type for dbm.Db with implementation of KVStore
|
||||
type dbStoreAdapter struct {
|
||||
dbm.DB
|
||||
}
|
||||
|
@ -31,5 +32,10 @@ func (dsa dbStoreAdapter) Prefix(prefix []byte) KVStore {
|
|||
return prefixStore{dsa, prefix}
|
||||
}
|
||||
|
||||
// Implements 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{dbm.DB(nil)}
|
||||
var _ KVStore = dbStoreAdapter{}
|
||||
|
|
|
@ -6,29 +6,21 @@ import (
|
|||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// nolint
|
||||
const (
|
||||
HasCost = 10
|
||||
ReadCostFlat = 10
|
||||
ReadCostPerByte = 1
|
||||
WriteCostFlat = 10
|
||||
WriteCostPerByte = 10
|
||||
KeyCostFlat = 5
|
||||
ValueCostFlat = 10
|
||||
ValueCostPerByte = 1
|
||||
)
|
||||
var _ KVStore = &gasKVStore{}
|
||||
|
||||
// gasKVStore applies gas tracking to an underlying kvstore
|
||||
type gasKVStore struct {
|
||||
gasMeter sdk.GasMeter
|
||||
parent sdk.KVStore
|
||||
gasMeter sdk.GasMeter
|
||||
gasConfig sdk.GasConfig
|
||||
parent sdk.KVStore
|
||||
}
|
||||
|
||||
// nolint
|
||||
func NewGasKVStore(gasMeter sdk.GasMeter, parent sdk.KVStore) *gasKVStore {
|
||||
func NewGasKVStore(gasMeter sdk.GasMeter, gasConfig sdk.GasConfig, parent sdk.KVStore) *gasKVStore {
|
||||
kvs := &gasKVStore{
|
||||
gasMeter: gasMeter,
|
||||
parent: parent,
|
||||
gasMeter: gasMeter,
|
||||
gasConfig: gasConfig,
|
||||
parent: parent,
|
||||
}
|
||||
return kvs
|
||||
}
|
||||
|
@ -40,24 +32,25 @@ func (gi *gasKVStore) GetStoreType() sdk.StoreType {
|
|||
|
||||
// Implements KVStore.
|
||||
func (gi *gasKVStore) Get(key []byte) (value []byte) {
|
||||
gi.gasMeter.ConsumeGas(ReadCostFlat, "GetFlat")
|
||||
gi.gasMeter.ConsumeGas(gi.gasConfig.ReadCostFlat, "ReadFlat")
|
||||
value = gi.parent.Get(key)
|
||||
// TODO overflow-safe math?
|
||||
gi.gasMeter.ConsumeGas(ReadCostPerByte*sdk.Gas(len(value)), "ReadPerByte")
|
||||
gi.gasMeter.ConsumeGas(gi.gasConfig.ReadCostPerByte*sdk.Gas(len(value)), "ReadPerByte")
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// Implements KVStore.
|
||||
func (gi *gasKVStore) Set(key []byte, value []byte) {
|
||||
gi.gasMeter.ConsumeGas(WriteCostFlat, "SetFlat")
|
||||
gi.gasMeter.ConsumeGas(gi.gasConfig.WriteCostFlat, "WriteFlat")
|
||||
// TODO overflow-safe math?
|
||||
gi.gasMeter.ConsumeGas(WriteCostPerByte*sdk.Gas(len(value)), "SetPerByte")
|
||||
gi.gasMeter.ConsumeGas(gi.gasConfig.WriteCostPerByte*sdk.Gas(len(value)), "WritePerByte")
|
||||
gi.parent.Set(key, value)
|
||||
}
|
||||
|
||||
// Implements KVStore.
|
||||
func (gi *gasKVStore) Has(key []byte) bool {
|
||||
gi.gasMeter.ConsumeGas(HasCost, "Has")
|
||||
gi.gasMeter.ConsumeGas(gi.gasConfig.HasCost, "Has")
|
||||
return gi.parent.Has(key)
|
||||
}
|
||||
|
||||
|
@ -69,7 +62,17 @@ func (gi *gasKVStore) Delete(key []byte) {
|
|||
|
||||
// Implements KVStore
|
||||
func (gi *gasKVStore) Prefix(prefix []byte) KVStore {
|
||||
return prefixStore{gi, prefix}
|
||||
// Keep gasstore layer at the top
|
||||
return &gasKVStore{
|
||||
gasMeter: gi.gasMeter,
|
||||
gasConfig: gi.gasConfig,
|
||||
parent: prefixStore{gi.parent, prefix},
|
||||
}
|
||||
}
|
||||
|
||||
// Implements KVStore
|
||||
func (gi *gasKVStore) Gas(meter GasMeter, config GasConfig) KVStore {
|
||||
return NewGasKVStore(meter, config, gi)
|
||||
}
|
||||
|
||||
// Implements KVStore.
|
||||
|
@ -99,18 +102,20 @@ func (gi *gasKVStore) iterator(start, end []byte, ascending bool) sdk.Iterator {
|
|||
} else {
|
||||
parent = gi.parent.ReverseIterator(start, end)
|
||||
}
|
||||
return newGasIterator(gi.gasMeter, parent)
|
||||
return newGasIterator(gi.gasMeter, gi.gasConfig, parent)
|
||||
}
|
||||
|
||||
type gasIterator struct {
|
||||
gasMeter sdk.GasMeter
|
||||
parent sdk.Iterator
|
||||
gasMeter sdk.GasMeter
|
||||
gasConfig sdk.GasConfig
|
||||
parent sdk.Iterator
|
||||
}
|
||||
|
||||
func newGasIterator(gasMeter sdk.GasMeter, parent sdk.Iterator) sdk.Iterator {
|
||||
func newGasIterator(gasMeter sdk.GasMeter, gasConfig sdk.GasConfig, parent sdk.Iterator) sdk.Iterator {
|
||||
return &gasIterator{
|
||||
gasMeter: gasMeter,
|
||||
parent: parent,
|
||||
gasMeter: gasMeter,
|
||||
gasConfig: gasConfig,
|
||||
parent: parent,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,7 +136,7 @@ func (g *gasIterator) Next() {
|
|||
|
||||
// Implements Iterator.
|
||||
func (g *gasIterator) Key() (key []byte) {
|
||||
g.gasMeter.ConsumeGas(KeyCostFlat, "KeyFlat")
|
||||
g.gasMeter.ConsumeGas(g.gasConfig.KeyCostFlat, "KeyFlat")
|
||||
key = g.parent.Key()
|
||||
return key
|
||||
}
|
||||
|
@ -139,8 +144,8 @@ func (g *gasIterator) Key() (key []byte) {
|
|||
// Implements Iterator.
|
||||
func (g *gasIterator) Value() (value []byte) {
|
||||
value = g.parent.Value()
|
||||
g.gasMeter.ConsumeGas(ValueCostFlat, "ValueFlat")
|
||||
g.gasMeter.ConsumeGas(ValueCostPerByte*sdk.Gas(len(value)), "ValuePerByte")
|
||||
g.gasMeter.ConsumeGas(g.gasConfig.ValueCostFlat, "ValueFlat")
|
||||
g.gasMeter.ConsumeGas(g.gasConfig.ValueCostPerByte*sdk.Gas(len(value)), "ValuePerByte")
|
||||
return value
|
||||
}
|
||||
|
||||
|
|
|
@ -3,21 +3,23 @@ package store
|
|||
import (
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
|
||||
sdk "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, mem)
|
||||
return NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
|
||||
}
|
||||
|
||||
func TestGasKVStoreBasic(t *testing.T) {
|
||||
mem := dbStoreAdapter{dbm.NewMemDB()}
|
||||
meter := sdk.NewGasMeter(1000)
|
||||
st := NewGasKVStore(meter, mem)
|
||||
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), 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)))
|
||||
|
@ -29,7 +31,7 @@ func TestGasKVStoreBasic(t *testing.T) {
|
|||
func TestGasKVStoreIterator(t *testing.T) {
|
||||
mem := dbStoreAdapter{dbm.NewMemDB()}
|
||||
meter := sdk.NewGasMeter(1000)
|
||||
st := NewGasKVStore(meter, mem)
|
||||
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), 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))
|
||||
|
@ -53,16 +55,51 @@ func TestGasKVStoreIterator(t *testing.T) {
|
|||
func TestGasKVStoreOutOfGasSet(t *testing.T) {
|
||||
mem := dbStoreAdapter{dbm.NewMemDB()}
|
||||
meter := sdk.NewGasMeter(0)
|
||||
st := NewGasKVStore(meter, mem)
|
||||
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), 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, mem)
|
||||
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), 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)
|
||||
|
||||
store = store.Gas(meter, sdk.GasConfig{HasCost: 10})
|
||||
require.Equal(t, int64(0), meter.GasConsumed())
|
||||
|
||||
store.Has([]byte("key"))
|
||||
require.Equal(t, int64(10), meter.GasConsumed())
|
||||
|
||||
store = store.Gas(meter, sdk.GasConfig{HasCost: 20})
|
||||
|
||||
store.Has([]byte("key"))
|
||||
require.Equal(t, int64(40), meter.GasConsumed())
|
||||
}
|
||||
|
||||
func TestGasKVStoreWrap(t *testing.T) {
|
||||
db := dbm.NewMemDB()
|
||||
tree, _ := newTree(t, db)
|
||||
iavl := newIAVLStore(tree, numRecent, storeEvery)
|
||||
testGasKVStoreWrap(t, iavl)
|
||||
|
||||
st := NewCacheKVStore(iavl)
|
||||
testGasKVStoreWrap(t, st)
|
||||
|
||||
pref := st.Prefix([]byte("prefix"))
|
||||
testGasKVStoreWrap(t, pref)
|
||||
|
||||
dsa := dbStoreAdapter{dbm.NewMemDB()}
|
||||
testGasKVStoreWrap(t, dsa)
|
||||
|
||||
ts := newTransientStore()
|
||||
testGasKVStoreWrap(t, ts)
|
||||
|
||||
}
|
||||
|
|
|
@ -67,7 +67,6 @@ func newIAVLStore(tree *iavl.VersionedTree, numRecent int64, storeEvery int64) *
|
|||
|
||||
// Implements Committer.
|
||||
func (st *iavlStore) Commit() CommitID {
|
||||
|
||||
// Save a new version.
|
||||
hash, version, err := st.tree.SaveVersion()
|
||||
if err != nil {
|
||||
|
@ -161,6 +160,11 @@ func (st *iavlStore) Prefix(prefix []byte) KVStore {
|
|||
return prefixStore{st, prefix}
|
||||
}
|
||||
|
||||
// Implements KVStore
|
||||
func (st *iavlStore) Gas(meter GasMeter, config GasConfig) KVStore {
|
||||
return NewGasKVStore(meter, config, st)
|
||||
}
|
||||
|
||||
// Implements KVStore.
|
||||
func (st *iavlStore) Iterator(start, end []byte) Iterator {
|
||||
return newIAVLIterator(st.tree.Tree(), start, end, true)
|
||||
|
|
|
@ -446,6 +446,7 @@ func TestIAVLStoreQuery(t *testing.T) {
|
|||
require.Equal(t, uint32(sdk.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, v2, qres.Value)
|
||||
|
|
|
@ -6,14 +6,16 @@ import (
|
|||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
var _ KVStore = prefixStore{}
|
||||
|
||||
type prefixStore struct {
|
||||
store KVStore
|
||||
parent KVStore
|
||||
prefix []byte
|
||||
}
|
||||
|
||||
// Implements Store
|
||||
func (s prefixStore) GetStoreType() StoreType {
|
||||
return sdk.StoreTypePrefix
|
||||
return s.parent.GetStoreType()
|
||||
}
|
||||
|
||||
// Implements CacheWrap
|
||||
|
@ -28,22 +30,22 @@ func (s prefixStore) CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap
|
|||
|
||||
// Implements KVStore
|
||||
func (s prefixStore) Get(key []byte) []byte {
|
||||
return s.store.Get(append(s.prefix, key...))
|
||||
return s.parent.Get(append(s.prefix, key...))
|
||||
}
|
||||
|
||||
// Implements KVStore
|
||||
func (s prefixStore) Has(key []byte) bool {
|
||||
return s.store.Has(append(s.prefix, key...))
|
||||
return s.parent.Has(append(s.prefix, key...))
|
||||
}
|
||||
|
||||
// Implements KVStore
|
||||
func (s prefixStore) Set(key, value []byte) {
|
||||
s.store.Set(append(s.prefix, key...), value)
|
||||
s.parent.Set(append(s.prefix, key...), value)
|
||||
}
|
||||
|
||||
// Implements KVStore
|
||||
func (s prefixStore) Delete(key []byte) {
|
||||
s.store.Delete(append(s.prefix, key...))
|
||||
s.parent.Delete(append(s.prefix, key...))
|
||||
}
|
||||
|
||||
// Implements KVStore
|
||||
|
@ -51,6 +53,11 @@ func (s prefixStore) Prefix(prefix []byte) KVStore {
|
|||
return prefixStore{s, prefix}
|
||||
}
|
||||
|
||||
// Implements KVStore
|
||||
func (s prefixStore) Gas(meter GasMeter, config GasConfig) KVStore {
|
||||
return NewGasKVStore(meter, config, s)
|
||||
}
|
||||
|
||||
// Implements KVStore
|
||||
func (s prefixStore) Iterator(start, end []byte) Iterator {
|
||||
if end == nil {
|
||||
|
@ -60,7 +67,7 @@ func (s prefixStore) Iterator(start, end []byte) Iterator {
|
|||
}
|
||||
return prefixIterator{
|
||||
prefix: s.prefix,
|
||||
iter: s.store.Iterator(append(s.prefix, start...), end),
|
||||
iter: s.parent.Iterator(append(s.prefix, start...), end),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,7 +80,7 @@ func (s prefixStore) ReverseIterator(start, end []byte) Iterator {
|
|||
}
|
||||
return prefixIterator{
|
||||
prefix: s.prefix,
|
||||
iter: s.store.ReverseIterator(start, end),
|
||||
iter: s.parent.ReverseIterator(start, end),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/iavl"
|
||||
|
@ -35,32 +34,34 @@ func setRandomKVPairs(t *testing.T, store KVStore) []kvpair {
|
|||
|
||||
func testPrefixStore(t *testing.T, baseStore KVStore, prefix []byte) {
|
||||
prefixStore := baseStore.Prefix(prefix)
|
||||
prefixPrefixStore := prefixStore.Prefix([]byte("prefix"))
|
||||
|
||||
kvps := setRandomKVPairs(t, prefixStore)
|
||||
|
||||
buf := make([]byte, 32)
|
||||
for i := 0; i < 20; i++ {
|
||||
rand.Read(buf)
|
||||
assert.False(t, prefixStore.Has(buf))
|
||||
assert.Nil(t, prefixStore.Get(buf))
|
||||
assert.False(t, baseStore.Has(append(prefix, buf...)))
|
||||
assert.Nil(t, baseStore.Get(append(prefix, buf...)))
|
||||
}
|
||||
kvps := setRandomKVPairs(t, prefixPrefixStore)
|
||||
|
||||
for i := 0; i < 20; i++ {
|
||||
key := kvps[i].key
|
||||
assert.True(t, prefixStore.Has(key))
|
||||
assert.Equal(t, kvps[i].value, prefixStore.Get(key))
|
||||
assert.True(t, baseStore.Has(append(prefix, key...)))
|
||||
assert.Equal(t, kvps[i].value, baseStore.Get(append(prefix, key...)))
|
||||
value := kvps[i].value
|
||||
require.True(t, prefixPrefixStore.Has(key))
|
||||
require.Equal(t, value, prefixPrefixStore.Get(key))
|
||||
|
||||
prefixStore.Delete(key)
|
||||
assert.False(t, prefixStore.Has(key))
|
||||
assert.Nil(t, prefixStore.Get(key))
|
||||
assert.False(t, baseStore.Has(append(prefix, buf...)))
|
||||
assert.Nil(t, baseStore.Get(append(prefix, buf...)))
|
||||
key = append([]byte("prefix"), key...)
|
||||
require.True(t, prefixStore.Has(key))
|
||||
require.Equal(t, value, prefixStore.Get(key))
|
||||
key = append(prefix, key...)
|
||||
require.True(t, baseStore.Has(key))
|
||||
require.Equal(t, value, baseStore.Get(key))
|
||||
|
||||
key = kvps[i].key
|
||||
prefixPrefixStore.Delete(key)
|
||||
require.False(t, prefixPrefixStore.Has(key))
|
||||
require.Nil(t, prefixPrefixStore.Get(key))
|
||||
key = append([]byte("prefix"), key...)
|
||||
require.False(t, prefixStore.Has(key))
|
||||
require.Nil(t, prefixStore.Get(key))
|
||||
key = append(prefix, key...)
|
||||
require.False(t, baseStore.Has(key))
|
||||
require.Nil(t, baseStore.Get(key))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestIAVLStorePrefix(t *testing.T) {
|
||||
|
@ -80,7 +81,7 @@ func TestCacheKVStorePrefix(t *testing.T) {
|
|||
func TestGasKVStorePrefix(t *testing.T) {
|
||||
meter := sdk.NewGasMeter(100000000)
|
||||
mem := dbStoreAdapter{dbm.NewMemDB()}
|
||||
gasStore := NewGasKVStore(meter, mem)
|
||||
gasStore := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
|
||||
|
||||
testPrefixStore(t, gasStore, []byte("test"))
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ func (rs *rootMultiStore) LoadVersion(ver int64) error {
|
|||
if ver == 0 {
|
||||
for key, storeParams := range rs.storesParams {
|
||||
id := CommitID{}
|
||||
store, err := rs.loadCommitStoreFromParams(id, storeParams)
|
||||
store, err := rs.loadCommitStoreFromParams(key, id, storeParams)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load rootMultiStore: %v", err)
|
||||
}
|
||||
|
@ -122,17 +122,20 @@ func (rs *rootMultiStore) LoadVersion(ver int64) error {
|
|||
for _, storeInfo := range cInfo.StoreInfos {
|
||||
key, commitID := rs.nameToKey(storeInfo.Name), storeInfo.Core.CommitID
|
||||
storeParams := rs.storesParams[key]
|
||||
store, err := rs.loadCommitStoreFromParams(commitID, storeParams)
|
||||
store, err := rs.loadCommitStoreFromParams(key, commitID, storeParams)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load rootMultiStore: %v", err)
|
||||
}
|
||||
newStores[key] = store
|
||||
}
|
||||
|
||||
// If any CommitStoreLoaders were not used, return error.
|
||||
for key := range rs.storesParams {
|
||||
if _, ok := newStores[key]; !ok {
|
||||
return fmt.Errorf("unused CommitStoreLoader: %v", key)
|
||||
// TODO: detecting transient is quite adhoc
|
||||
// If any nontransient CommitStoreLoaders were not used, return error.
|
||||
for key, param := range rs.storesParams {
|
||||
if param.typ != sdk.StoreTypeTransient {
|
||||
if _, ok := newStores[key]; !ok {
|
||||
return fmt.Errorf("unused CommitStoreLoader: %v", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,10 +245,7 @@ func (rs *rootMultiStore) GetKVStore(key StoreKey) KVStore {
|
|||
return store
|
||||
}
|
||||
|
||||
// Implements MultiStore.
|
||||
func (rs *rootMultiStore) GetKVStoreWithGas(meter sdk.GasMeter, key StoreKey) KVStore {
|
||||
return NewGasKVStore(meter, rs.GetKVStore(key))
|
||||
}
|
||||
// Implements MultiStore
|
||||
|
||||
// getStoreByName will first convert the original name to
|
||||
// a special key, before looking up the CommitStore.
|
||||
|
@ -309,7 +309,7 @@ func parsePath(path string) (storeName string, subpath string, err sdk.Error) {
|
|||
|
||||
//----------------------------------------
|
||||
|
||||
func (rs *rootMultiStore) loadCommitStoreFromParams(id CommitID, params storeParams) (store CommitStore, err error) {
|
||||
func (rs *rootMultiStore) loadCommitStoreFromParams(key sdk.StoreKey, id CommitID, params storeParams) (store CommitStore, err error) {
|
||||
var db dbm.DB
|
||||
if params.db != nil {
|
||||
db = dbm.NewPrefixDB(params.db, []byte("s/_/"))
|
||||
|
@ -326,6 +326,14 @@ func (rs *rootMultiStore) loadCommitStoreFromParams(id CommitID, params storePar
|
|||
return
|
||||
case sdk.StoreTypeDB:
|
||||
panic("dbm.DB is not a CommitStore")
|
||||
case sdk.StoreTypeTransient:
|
||||
_, ok := key.(*sdk.TransientStoreKey)
|
||||
if !ok {
|
||||
err = fmt.Errorf("invalid StoreKey for StoreTypeTransient: %s", key.String())
|
||||
return
|
||||
}
|
||||
store = newTransientStore()
|
||||
return
|
||||
default:
|
||||
panic(fmt.Sprintf("unrecognized store type %v", params.typ))
|
||||
}
|
||||
|
@ -440,6 +448,10 @@ func commitStores(version int64, storeMap map[StoreKey]CommitStore) commitInfo {
|
|||
// Commit
|
||||
commitID := store.Commit()
|
||||
|
||||
if store.GetStoreType() == sdk.StoreTypeTransient {
|
||||
continue
|
||||
}
|
||||
|
||||
// Record CommitID
|
||||
si := storeInfo{}
|
||||
si.Name = key.Name()
|
||||
|
|
|
@ -13,6 +13,14 @@ import (
|
|||
|
||||
const useDebugDB = false
|
||||
|
||||
func TestStoreType(t *testing.T) {
|
||||
db := dbm.NewMemDB()
|
||||
store := NewCommitMultiStore(db)
|
||||
store.MountStoreWithDB(
|
||||
sdk.NewKVStoreKey("store1"), sdk.StoreTypeIAVL, db)
|
||||
|
||||
}
|
||||
|
||||
func TestMultistoreCommitLoad(t *testing.T) {
|
||||
var db dbm.DB = dbm.NewMemDB()
|
||||
if useDebugDB {
|
||||
|
|
|
@ -82,6 +82,11 @@ func (tkv *TraceKVStore) Prefix(prefix []byte) KVStore {
|
|||
return prefixStore{tkv, prefix}
|
||||
}
|
||||
|
||||
// Gas implements the KVStore interface.
|
||||
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 {
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package store
|
||||
|
||||
import (
|
||||
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)
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package store
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var k, v = []byte("hello"), []byte("world")
|
||||
|
||||
func TestTransientStore(t *testing.T) {
|
||||
tstore := newTransientStore()
|
||||
|
||||
require.Nil(t, tstore.Get(k))
|
||||
|
||||
tstore.Set(k, v)
|
||||
|
||||
require.Equal(t, v, tstore.Get(k))
|
||||
|
||||
tstore.Commit()
|
||||
|
||||
require.Nil(t, tstore.Get(k))
|
||||
}
|
|
@ -7,6 +7,7 @@ import (
|
|||
// Import cosmos-sdk/types/store.go for convenience.
|
||||
// nolint
|
||||
type (
|
||||
PruningStrategy = types.PruningStrategy
|
||||
Store = types.Store
|
||||
Committer = types.Committer
|
||||
CommitStore = types.CommitStore
|
||||
|
@ -25,4 +26,7 @@ type (
|
|||
StoreType = types.StoreType
|
||||
Queryable = types.Queryable
|
||||
TraceContext = types.TraceContext
|
||||
Gas = types.Gas
|
||||
GasMeter = types.GasMeter
|
||||
GasConfig = types.GasConfig
|
||||
)
|
||||
|
|
|
@ -31,7 +31,6 @@ type Context struct {
|
|||
|
||||
// create a new context
|
||||
func NewContext(ms MultiStore, header abci.Header, isCheckTx bool, logger log.Logger) Context {
|
||||
|
||||
c := Context{
|
||||
Context: context.Background(),
|
||||
pst: newThePast(),
|
||||
|
@ -70,7 +69,12 @@ func (c Context) Value(key interface{}) interface{} {
|
|||
|
||||
// KVStore fetches a KVStore from the MultiStore.
|
||||
func (c Context) KVStore(key StoreKey) KVStore {
|
||||
return c.multiStore().GetKVStoreWithGas(c.GasMeter(), key)
|
||||
return c.multiStore().GetKVStore(key).Gas(c.GasMeter(), cachedDefaultGasConfig)
|
||||
}
|
||||
|
||||
// TransientStore fetches a TransientStore from the MultiStore.
|
||||
func (c Context) TransientStore(key StoreKey) KVStore {
|
||||
return c.multiStore().GetKVStore(key).Gas(c.GasMeter(), cachedTransientGasConfig)
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
@ -125,6 +129,7 @@ const (
|
|||
contextKeyMultiStore contextKey = iota
|
||||
contextKeyBlockHeader
|
||||
contextKeyBlockHeight
|
||||
contextKeyConsensusParams
|
||||
contextKeyChainID
|
||||
contextKeyTxBytes
|
||||
contextKeyLogger
|
||||
|
@ -146,6 +151,9 @@ func (c Context) BlockHeader() abci.Header {
|
|||
func (c Context) BlockHeight() int64 {
|
||||
return c.Value(contextKeyBlockHeight).(int64)
|
||||
}
|
||||
func (c Context) ConsensusParams() abci.ConsensusParams {
|
||||
return c.Value(contextKeyConsensusParams).(abci.ConsensusParams)
|
||||
}
|
||||
func (c Context) ChainID() string {
|
||||
return c.Value(contextKeyChainID).(string)
|
||||
}
|
||||
|
@ -171,6 +179,13 @@ func (c Context) WithBlockHeader(header abci.Header) Context {
|
|||
func (c Context) WithBlockHeight(height int64) Context {
|
||||
return c.withValue(contextKeyBlockHeight, height)
|
||||
}
|
||||
func (c Context) WithConsensusParams(params *abci.ConsensusParams) Context {
|
||||
if params == nil {
|
||||
return c
|
||||
}
|
||||
return c.withValue(contextKeyConsensusParams, params).
|
||||
WithGasMeter(NewGasMeter(params.TxSize.MaxGas))
|
||||
}
|
||||
func (c Context) WithChainID(chainID string) Context {
|
||||
return c.withValue(contextKeyChainID, chainID)
|
||||
}
|
||||
|
|
37
types/gas.go
37
types/gas.go
|
@ -54,3 +54,40 @@ func (g *infiniteGasMeter) GasConsumed() Gas {
|
|||
func (g *infiniteGasMeter) ConsumeGas(amount Gas, descriptor string) {
|
||||
g.consumed += amount
|
||||
}
|
||||
|
||||
// GasConfig defines gas cost for each operation on KVStores
|
||||
type GasConfig struct {
|
||||
HasCost Gas
|
||||
ReadCostFlat Gas
|
||||
ReadCostPerByte Gas
|
||||
WriteCostFlat Gas
|
||||
WriteCostPerByte Gas
|
||||
KeyCostFlat Gas
|
||||
ValueCostFlat Gas
|
||||
ValueCostPerByte Gas
|
||||
}
|
||||
|
||||
var (
|
||||
cachedDefaultGasConfig = DefaultGasConfig()
|
||||
cachedTransientGasConfig = TransientGasConfig()
|
||||
)
|
||||
|
||||
// Default gas config for KVStores
|
||||
func DefaultGasConfig() GasConfig {
|
||||
return GasConfig{
|
||||
HasCost: 10,
|
||||
ReadCostFlat: 10,
|
||||
ReadCostPerByte: 1,
|
||||
WriteCostFlat: 10,
|
||||
WriteCostPerByte: 10,
|
||||
KeyCostFlat: 5,
|
||||
ValueCostFlat: 10,
|
||||
ValueCostPerByte: 1,
|
||||
}
|
||||
}
|
||||
|
||||
// Default gas config for TransientStores
|
||||
func TransientGasConfig() GasConfig {
|
||||
// TODO: define gasconfig for transient stores
|
||||
return DefaultGasConfig()
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ type MultiStore interface { //nolint
|
|||
// Convenience for fetching substores.
|
||||
GetStore(StoreKey) Store
|
||||
GetKVStore(StoreKey) KVStore
|
||||
GetKVStoreWithGas(GasMeter, StoreKey) KVStore
|
||||
|
||||
// TracingEnabled returns if tracing is enabled for the MultiStore.
|
||||
TracingEnabled() bool
|
||||
|
@ -134,9 +133,6 @@ type KVStore interface {
|
|||
// Delete deletes the key. Panics on nil key.
|
||||
Delete(key []byte)
|
||||
|
||||
// Prefix applied keys with the argument
|
||||
Prefix(prefix []byte) KVStore
|
||||
|
||||
// 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.
|
||||
|
@ -155,6 +151,16 @@ 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
|
||||
}
|
||||
|
||||
// Alias iterator to db's Iterator for convenience.
|
||||
|
@ -186,11 +192,6 @@ type CommitKVStore interface {
|
|||
KVStore
|
||||
}
|
||||
|
||||
// Wrapper for StoreKeys to get KVStores
|
||||
type KVStoreGetter interface {
|
||||
KVStore(Context) KVStore
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
// CacheWrap
|
||||
|
||||
|
@ -245,7 +246,7 @@ const (
|
|||
StoreTypeMulti StoreType = iota
|
||||
StoreTypeDB
|
||||
StoreTypeIAVL
|
||||
StoreTypePrefix
|
||||
StoreTypeTransient
|
||||
)
|
||||
|
||||
//----------------------------------------
|
||||
|
@ -279,11 +280,6 @@ func (key *KVStoreKey) String() string {
|
|||
return fmt.Sprintf("KVStoreKey{%p, %s}", key, key.name)
|
||||
}
|
||||
|
||||
// Implements KVStoreGetter
|
||||
func (key *KVStoreKey) KVStore(ctx Context) KVStore {
|
||||
return ctx.KVStore(key)
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -310,19 +306,27 @@ func PrefixEndBytes(prefix []byte) []byte {
|
|||
return end
|
||||
}
|
||||
|
||||
// Getter struct for prefixed stores
|
||||
type PrefixStoreGetter struct {
|
||||
key StoreKey
|
||||
prefix []byte
|
||||
// TransientStoreKey is used for indexing transient stores in a MultiStore
|
||||
type TransientStoreKey struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func NewPrefixStoreGetter(key StoreKey, prefix []byte) PrefixStoreGetter {
|
||||
return PrefixStoreGetter{key, prefix}
|
||||
// Constructs new TransientStoreKey
|
||||
// Must return a pointer according to the ocap principle
|
||||
func NewTransientStoreKey(name string) *TransientStoreKey {
|
||||
return &TransientStoreKey{
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
// Implements sdk.KVStoreGetter
|
||||
func (getter PrefixStoreGetter) KVStore(ctx Context) KVStore {
|
||||
return ctx.KVStore(getter.key).Prefix(getter.prefix)
|
||||
// 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)
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
|
Loading…
Reference in New Issue