Skip to content

Commit

Permalink
Merge pull request #1481: Transient Stores
Browse files Browse the repository at this point in the history
move gasconfig to types, make GetKVStoreWithGas take GasConfig

fix lint

modify transientstore

in progress

add test for transientstore

fix errors

fix test

fix errors and lint

last fix

in progress

move transient to KVStore

fix syntax errors

finalize rebase

remove NewMemDBStoreAdapter for lint

apply requests

apply requests

apply requests

add CHANGELOG

add tests

fix getter

in progress

finalize rebase

fix lint

partially apply requests

assert -> require

apply requests

fix test

Changelog => Pending

add TransientStoreKey

fix lint

fix lint

refactor *Store from context, add ReadKVStore

delete immutablestore

fix KVStore

fix TransientStore

remove StoreGetter

fix errors
  • Loading branch information
mossid committed Jul 24, 2018
1 parent 63f70cb commit 78164f7
Show file tree
Hide file tree
Showing 26 changed files with 369 additions and 136 deletions.
3 changes: 3 additions & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ FEATURES
* [baseapp] Initialize validator set on ResponseInitChain
* [cosmos-sdk-cli] Added support for cosmos-sdk-cli tool under cosmos-sdk/cmd
* This allows SDK users to initialize a new project repository.
* Added support for cosmos-sdk-cli tool under cosmos-sdk/cmd
* This allows SDK users to init a new project repository with a single command.
* [store] Add transient store

IMPROVEMENTS
* [baseapp] Allow any alphanumeric character in route
Expand Down
Binary file added cmd/gaia/cmd/gaiadebug/gaiadebug
Binary file not shown.
30 changes: 13 additions & 17 deletions examples/democoin/x/assoc/validator_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -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
}

Expand All @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion examples/democoin/x/assoc/validator_set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
2 changes: 1 addition & 1 deletion examples/democoin/x/oracle/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
14 changes: 7 additions & 7 deletions examples/democoin/x/oracle/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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")
}
Expand Down Expand Up @@ -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)
Expand All @@ -77,29 +77,29 @@ 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)
store.Set(key, bz)
}

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)

Expand Down
2 changes: 1 addition & 1 deletion examples/democoin/x/oracle/oracle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 8 additions & 4 deletions server/mock/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

var _ sdk.MultiStore = multiStore{}

type multiStore struct {
kv map[sdk.StoreKey]kvStore
}
Expand Down Expand Up @@ -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")
}
Expand All @@ -88,6 +86,8 @@ func (ms multiStore) GetStoreType() sdk.StoreType {
panic("not implemented")
}

var _ sdk.KVStore = kvStore{}

type kvStore struct {
store map[string][]byte
}
Expand Down Expand Up @@ -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")
}
Expand Down
5 changes: 5 additions & 0 deletions store/cachekvstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
4 changes: 2 additions & 2 deletions store/cachemultistore.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
8 changes: 7 additions & 1 deletion store/dbstoreadapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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{}
67 changes: 36 additions & 31 deletions store/gaskvstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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)
}

Expand All @@ -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.
Expand Down Expand Up @@ -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,
}
}

Expand All @@ -131,16 +136,16 @@ 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
}

// 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
}

Expand Down
Loading

0 comments on commit 78164f7

Please sign in to comment.