Skip to content

Commit bff248e

Browse files
committed
Merge pull request #1481: Transient Stores
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
1 parent f3a1290 commit bff248e

21 files changed

+342
-89
lines changed

PENDING.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ FEATURES
2525
* [baseapp] Initialize validator set on ResponseInitChain
2626
* Added support for cosmos-sdk-cli tool under cosmos-sdk/cmd
2727
* This allows SDK users to init a new project repository with a single command.
28+
* [store] Add transient store
2829

2930
IMPROVEMENTS
3031
* [baseapp] Allow any alphanumeric character in route

cmd/gaia/cmd/gaiadebug/gaiadebug

27.3 MB
Binary file not shown.

server/mock/store.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
sdk "github.com/cosmos/cosmos-sdk/types"
99
)
1010

11+
var _ sdk.MultiStore = multiStore{}
12+
1113
type multiStore struct {
1214
kv map[sdk.StoreKey]kvStore
1315
}
@@ -76,10 +78,6 @@ func (ms multiStore) GetKVStore(key sdk.StoreKey) sdk.KVStore {
7678
return ms.kv[key]
7779
}
7880

79-
func (ms multiStore) GetKVStoreWithGas(meter sdk.GasMeter, key sdk.StoreKey) sdk.KVStore {
80-
panic("not implemented")
81-
}
82-
8381
func (ms multiStore) GetStore(key sdk.StoreKey) sdk.Store {
8482
panic("not implemented")
8583
}
@@ -88,6 +86,8 @@ func (ms multiStore) GetStoreType() sdk.StoreType {
8886
panic("not implemented")
8987
}
9088

89+
var _ sdk.KVStore = kvStore{}
90+
9191
type kvStore struct {
9292
store map[string][]byte
9393
}
@@ -129,6 +129,10 @@ func (kv kvStore) Prefix(prefix []byte) sdk.KVStore {
129129
panic("not implemented")
130130
}
131131

132+
func (kv kvStore) Gas(meter sdk.GasMeter, config sdk.GasConfig) sdk.KVStore {
133+
panic("not implmeneted")
134+
}
135+
132136
func (kv kvStore) Iterator(start, end []byte) sdk.Iterator {
133137
panic("not implemented")
134138
}

store/cachekvstore.go

+5
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ func (ci *cacheKVStore) Prefix(prefix []byte) KVStore {
8585
return prefixStore{ci, prefix}
8686
}
8787

88+
// Implements KVStore
89+
func (ci *cacheKVStore) Gas(meter GasMeter, config GasConfig) KVStore {
90+
return NewGasKVStore(meter, config, ci)
91+
}
92+
8893
// Implements CacheKVStore.
8994
func (ci *cacheKVStore) Write() {
9095
ci.mtx.Lock()

store/cachemultistore.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,6 @@ func (cms cacheMultiStore) GetKVStore(key StoreKey) KVStore {
134134
}
135135

136136
// Implements MultiStore.
137-
func (cms cacheMultiStore) GetKVStoreWithGas(meter sdk.GasMeter, key StoreKey) KVStore {
138-
return NewGasKVStore(meter, cms.GetKVStore(key))
137+
func (cms cacheMultiStore) GetKVStoreWithGas(meter sdk.GasMeter, config sdk.GasConfig, key StoreKey) KVStore {
138+
return NewGasKVStore(meter, config, cms.GetKVStore(key))
139139
}

store/dbstoreadapter.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
dbm "github.com/tendermint/tendermint/libs/db"
88
)
99

10+
// Wrapper type for dbm.Db with implementation of KVStore
1011
type dbStoreAdapter struct {
1112
dbm.DB
1213
}
@@ -31,5 +32,10 @@ func (dsa dbStoreAdapter) Prefix(prefix []byte) KVStore {
3132
return prefixStore{dsa, prefix}
3233
}
3334

35+
// Implements KVStore
36+
func (dsa dbStoreAdapter) Gas(meter GasMeter, config GasConfig) KVStore {
37+
return NewGasKVStore(meter, config, dsa)
38+
}
39+
3440
// dbm.DB implements KVStore so we can CacheKVStore it.
35-
var _ KVStore = dbStoreAdapter{dbm.DB(nil)}
41+
var _ KVStore = dbStoreAdapter{}

store/gaskvstore.go

+36-31
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,21 @@ import (
66
sdk "github.com/cosmos/cosmos-sdk/types"
77
)
88

9-
// nolint
10-
const (
11-
HasCost = 10
12-
ReadCostFlat = 10
13-
ReadCostPerByte = 1
14-
WriteCostFlat = 10
15-
WriteCostPerByte = 10
16-
KeyCostFlat = 5
17-
ValueCostFlat = 10
18-
ValueCostPerByte = 1
19-
)
9+
var _ KVStore = &gasKVStore{}
2010

2111
// gasKVStore applies gas tracking to an underlying kvstore
2212
type gasKVStore struct {
23-
gasMeter sdk.GasMeter
24-
parent sdk.KVStore
13+
gasMeter sdk.GasMeter
14+
gasConfig sdk.GasConfig
15+
parent sdk.KVStore
2516
}
2617

2718
// nolint
28-
func NewGasKVStore(gasMeter sdk.GasMeter, parent sdk.KVStore) *gasKVStore {
19+
func NewGasKVStore(gasMeter sdk.GasMeter, gasConfig sdk.GasConfig, parent sdk.KVStore) *gasKVStore {
2920
kvs := &gasKVStore{
30-
gasMeter: gasMeter,
31-
parent: parent,
21+
gasMeter: gasMeter,
22+
gasConfig: gasConfig,
23+
parent: parent,
3224
}
3325
return kvs
3426
}
@@ -40,24 +32,25 @@ func (gi *gasKVStore) GetStoreType() sdk.StoreType {
4032

4133
// Implements KVStore.
4234
func (gi *gasKVStore) Get(key []byte) (value []byte) {
43-
gi.gasMeter.ConsumeGas(ReadCostFlat, "GetFlat")
35+
gi.gasMeter.ConsumeGas(gi.gasConfig.ReadCostFlat, "ReadFlat")
4436
value = gi.parent.Get(key)
4537
// TODO overflow-safe math?
46-
gi.gasMeter.ConsumeGas(ReadCostPerByte*sdk.Gas(len(value)), "ReadPerByte")
38+
gi.gasMeter.ConsumeGas(gi.gasConfig.ReadCostPerByte*sdk.Gas(len(value)), "ReadPerByte")
39+
4740
return value
4841
}
4942

5043
// Implements KVStore.
5144
func (gi *gasKVStore) Set(key []byte, value []byte) {
52-
gi.gasMeter.ConsumeGas(WriteCostFlat, "SetFlat")
45+
gi.gasMeter.ConsumeGas(gi.gasConfig.WriteCostFlat, "WriteFlat")
5346
// TODO overflow-safe math?
54-
gi.gasMeter.ConsumeGas(WriteCostPerByte*sdk.Gas(len(value)), "SetPerByte")
47+
gi.gasMeter.ConsumeGas(gi.gasConfig.WriteCostPerByte*sdk.Gas(len(value)), "WritePerByte")
5548
gi.parent.Set(key, value)
5649
}
5750

5851
// Implements KVStore.
5952
func (gi *gasKVStore) Has(key []byte) bool {
60-
gi.gasMeter.ConsumeGas(HasCost, "Has")
53+
gi.gasMeter.ConsumeGas(gi.gasConfig.HasCost, "Has")
6154
return gi.parent.Has(key)
6255
}
6356

@@ -69,7 +62,17 @@ func (gi *gasKVStore) Delete(key []byte) {
6962

7063
// Implements KVStore
7164
func (gi *gasKVStore) Prefix(prefix []byte) KVStore {
72-
return prefixStore{gi, prefix}
65+
// Keep gasstore layer at the top
66+
return &gasKVStore{
67+
gasMeter: gi.gasMeter,
68+
gasConfig: gi.gasConfig,
69+
parent: prefixStore{gi.parent, prefix},
70+
}
71+
}
72+
73+
// Implements KVStore
74+
func (gi *gasKVStore) Gas(meter GasMeter, config GasConfig) KVStore {
75+
return NewGasKVStore(meter, config, gi)
7376
}
7477

7578
// Implements KVStore.
@@ -99,18 +102,20 @@ func (gi *gasKVStore) iterator(start, end []byte, ascending bool) sdk.Iterator {
99102
} else {
100103
parent = gi.parent.ReverseIterator(start, end)
101104
}
102-
return newGasIterator(gi.gasMeter, parent)
105+
return newGasIterator(gi.gasMeter, gi.gasConfig, parent)
103106
}
104107

105108
type gasIterator struct {
106-
gasMeter sdk.GasMeter
107-
parent sdk.Iterator
109+
gasMeter sdk.GasMeter
110+
gasConfig sdk.GasConfig
111+
parent sdk.Iterator
108112
}
109113

110-
func newGasIterator(gasMeter sdk.GasMeter, parent sdk.Iterator) sdk.Iterator {
114+
func newGasIterator(gasMeter sdk.GasMeter, gasConfig sdk.GasConfig, parent sdk.Iterator) sdk.Iterator {
111115
return &gasIterator{
112-
gasMeter: gasMeter,
113-
parent: parent,
116+
gasMeter: gasMeter,
117+
gasConfig: gasConfig,
118+
parent: parent,
114119
}
115120
}
116121

@@ -131,16 +136,16 @@ func (g *gasIterator) Next() {
131136

132137
// Implements Iterator.
133138
func (g *gasIterator) Key() (key []byte) {
134-
g.gasMeter.ConsumeGas(KeyCostFlat, "KeyFlat")
139+
g.gasMeter.ConsumeGas(g.gasConfig.KeyCostFlat, "KeyFlat")
135140
key = g.parent.Key()
136141
return key
137142
}
138143

139144
// Implements Iterator.
140145
func (g *gasIterator) Value() (value []byte) {
141146
value = g.parent.Value()
142-
g.gasMeter.ConsumeGas(ValueCostFlat, "ValueFlat")
143-
g.gasMeter.ConsumeGas(ValueCostPerByte*sdk.Gas(len(value)), "ValuePerByte")
147+
g.gasMeter.ConsumeGas(g.gasConfig.ValueCostFlat, "ValueFlat")
148+
g.gasMeter.ConsumeGas(g.gasConfig.ValueCostPerByte*sdk.Gas(len(value)), "ValuePerByte")
144149
return value
145150
}
146151

store/gaskvstore_test.go

+43-6
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,23 @@ package store
33
import (
44
"testing"
55

6+
dbm "github.com/tendermint/tendermint/libs/db"
7+
68
sdk "github.com/cosmos/cosmos-sdk/types"
9+
710
"github.com/stretchr/testify/require"
8-
dbm "github.com/tendermint/tendermint/libs/db"
911
)
1012

1113
func newGasKVStore() KVStore {
1214
meter := sdk.NewGasMeter(1000)
1315
mem := dbStoreAdapter{dbm.NewMemDB()}
14-
return NewGasKVStore(meter, mem)
16+
return NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
1517
}
1618

1719
func TestGasKVStoreBasic(t *testing.T) {
1820
mem := dbStoreAdapter{dbm.NewMemDB()}
1921
meter := sdk.NewGasMeter(1000)
20-
st := NewGasKVStore(meter, mem)
22+
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
2123
require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty")
2224
st.Set(keyFmt(1), valFmt(1))
2325
require.Equal(t, valFmt(1), st.Get(keyFmt(1)))
@@ -29,7 +31,7 @@ func TestGasKVStoreBasic(t *testing.T) {
2931
func TestGasKVStoreIterator(t *testing.T) {
3032
mem := dbStoreAdapter{dbm.NewMemDB()}
3133
meter := sdk.NewGasMeter(1000)
32-
st := NewGasKVStore(meter, mem)
34+
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
3335
require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty")
3436
require.Empty(t, st.Get(keyFmt(2)), "Expected `key2` to be empty")
3537
st.Set(keyFmt(1), valFmt(1))
@@ -53,16 +55,51 @@ func TestGasKVStoreIterator(t *testing.T) {
5355
func TestGasKVStoreOutOfGasSet(t *testing.T) {
5456
mem := dbStoreAdapter{dbm.NewMemDB()}
5557
meter := sdk.NewGasMeter(0)
56-
st := NewGasKVStore(meter, mem)
58+
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
5759
require.Panics(t, func() { st.Set(keyFmt(1), valFmt(1)) }, "Expected out-of-gas")
5860
}
5961

6062
func TestGasKVStoreOutOfGasIterator(t *testing.T) {
6163
mem := dbStoreAdapter{dbm.NewMemDB()}
6264
meter := sdk.NewGasMeter(200)
63-
st := NewGasKVStore(meter, mem)
65+
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
6466
st.Set(keyFmt(1), valFmt(1))
6567
iterator := st.Iterator(nil, nil)
6668
iterator.Next()
6769
require.Panics(t, func() { iterator.Value() }, "Expected out-of-gas")
6870
}
71+
72+
func testGasKVStoreWrap(t *testing.T, store KVStore) {
73+
meter := sdk.NewGasMeter(10000)
74+
75+
store = store.Gas(meter, sdk.GasConfig{HasCost: 10})
76+
require.Equal(t, int64(0), meter.GasConsumed())
77+
78+
store.Has([]byte("key"))
79+
require.Equal(t, int64(10), meter.GasConsumed())
80+
81+
store = store.Gas(meter, sdk.GasConfig{HasCost: 20})
82+
83+
store.Has([]byte("key"))
84+
require.Equal(t, int64(40), meter.GasConsumed())
85+
}
86+
87+
func TestGasKVStoreWrap(t *testing.T) {
88+
db := dbm.NewMemDB()
89+
tree, _ := newTree(t, db)
90+
iavl := newIAVLStore(tree, numRecent, storeEvery)
91+
testGasKVStoreWrap(t, iavl)
92+
93+
st := NewCacheKVStore(iavl)
94+
testGasKVStoreWrap(t, st)
95+
96+
pref := st.Prefix([]byte("prefix"))
97+
testGasKVStoreWrap(t, pref)
98+
99+
dsa := dbStoreAdapter{dbm.NewMemDB()}
100+
testGasKVStoreWrap(t, dsa)
101+
102+
ts := newTransientStore()
103+
testGasKVStoreWrap(t, ts)
104+
105+
}

store/iavlstore.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ func newIAVLStore(tree *iavl.VersionedTree, numRecent int64, storeEvery int64) *
6767

6868
// Implements Committer.
6969
func (st *iavlStore) Commit() CommitID {
70-
7170
// Save a new version.
7271
hash, version, err := st.tree.SaveVersion()
7372
if err != nil {
@@ -161,6 +160,11 @@ func (st *iavlStore) Prefix(prefix []byte) KVStore {
161160
return prefixStore{st, prefix}
162161
}
163162

163+
// Implements KVStore
164+
func (st *iavlStore) Gas(meter GasMeter, config GasConfig) KVStore {
165+
return NewGasKVStore(meter, config, st)
166+
}
167+
164168
// Implements KVStore.
165169
func (st *iavlStore) Iterator(start, end []byte) Iterator {
166170
return newIAVLIterator(st.tree.Tree(), start, end, true)

store/iavlstore_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ func TestIAVLStoreQuery(t *testing.T) {
446446
require.Equal(t, uint32(sdk.CodeOK), qres.Code)
447447
require.Equal(t, v3, qres.Value)
448448
query2 := abci.RequestQuery{Path: "/key", Data: k2, Height: cid.Version}
449+
449450
qres = iavlStore.Query(query2)
450451
require.Equal(t, uint32(sdk.CodeOK), qres.Code)
451452
require.Equal(t, v2, qres.Value)

0 commit comments

Comments
 (0)