-
Notifications
You must be signed in to change notification settings - Fork 3.6k
/
gaskvstore.go
155 lines (129 loc) · 3.69 KB
/
gaskvstore.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package store
import (
"io"
sdk "github.com/cosmos/cosmos-sdk/types"
)
var _ KVStore = &gasKVStore{}
// gasKVStore applies gas tracking to an underlying kvstore
type gasKVStore struct {
gasMeter sdk.GasMeter
gasConfig sdk.GasConfig
parent sdk.KVStore
}
// nolint
func NewGasKVStore(gasMeter sdk.GasMeter, gasConfig sdk.GasConfig, parent sdk.KVStore) *gasKVStore {
kvs := &gasKVStore{
gasMeter: gasMeter,
gasConfig: gasConfig,
parent: parent,
}
return kvs
}
// Implements Store.
func (gi *gasKVStore) GetStoreType() sdk.StoreType {
return gi.parent.GetStoreType()
}
// Implements KVStore.
func (gi *gasKVStore) Get(key []byte) (value []byte) {
gi.gasMeter.ConsumeGas(gi.gasConfig.ReadCostFlat, "ReadFlat")
value = gi.parent.Get(key)
// TODO overflow-safe math?
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(gi.gasConfig.WriteCostFlat, "WriteFlat")
// TODO overflow-safe math?
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(gi.gasConfig.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) Prefix(prefix []byte) KVStore {
// 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.
func (gi *gasKVStore) Iterator(start, end []byte) sdk.Iterator {
return gi.iterator(start, end, true)
}
// Implements KVStore.
func (gi *gasKVStore) ReverseIterator(start, end []byte) sdk.Iterator {
return gi.iterator(start, end, false)
}
// Implements KVStore.
func (gi *gasKVStore) CacheWrap() sdk.CacheWrap {
panic("cannot CacheWrap a GasKVStore")
}
// CacheWrapWithTrace implements the KVStore interface.
func (gi *gasKVStore) CacheWrapWithTrace(_ io.Writer, _ TraceContext) CacheWrap {
panic("cannot CacheWrapWithTrace a GasKVStore")
}
func (gi *gasKVStore) iterator(start, end []byte, ascending bool) sdk.Iterator {
var parent sdk.Iterator
if ascending {
parent = gi.parent.Iterator(start, end)
} else {
parent = gi.parent.ReverseIterator(start, end)
}
return newGasIterator(gi.gasMeter, gi.gasConfig, parent)
}
type gasIterator struct {
gasMeter sdk.GasMeter
gasConfig sdk.GasConfig
parent sdk.Iterator
}
func newGasIterator(gasMeter sdk.GasMeter, gasConfig sdk.GasConfig, parent sdk.Iterator) sdk.Iterator {
return &gasIterator{
gasMeter: gasMeter,
gasConfig: gasConfig,
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(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(g.gasConfig.ValueCostFlat, "ValueFlat")
g.gasMeter.ConsumeGas(g.gasConfig.ValueCostPerByte*sdk.Gas(len(value)), "ValuePerByte")
return value
}
// Implements Iterator.
func (g *gasIterator) Close() {
g.parent.Close()
}