-
Notifications
You must be signed in to change notification settings - Fork 30
/
store.go
441 lines (349 loc) · 12.5 KB
/
store.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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
package types
import (
"fmt"
"io"
oststrings "github.com/Finschia/ostracon/libs/strings"
abci "github.com/tendermint/tendermint/abci/types"
dbm "github.com/tendermint/tm-db"
snapshottypes "github.com/Finschia/finschia-sdk/snapshots/types"
"github.com/Finschia/finschia-sdk/types/kv"
)
type Store interface {
GetStoreType() StoreType
CacheWrapper
}
// something that can persist to disk
type Committer interface {
Commit() CommitID
LastCommitID() CommitID
SetPruning(PruningOptions)
GetPruning() PruningOptions
}
// Stores of MultiStore must implement CommitStore.
type CommitStore interface {
Committer
Store
}
// Queryable allows a Store to expose internal state to the abci.Query
// interface. Multistore can route requests to the proper Store.
//
// This is an optional, but useful extension to any CommitStore
type Queryable interface {
Query(abci.RequestQuery) abci.ResponseQuery
}
//----------------------------------------
// MultiStore
// StoreUpgrades defines a series of transformations to apply the multistore db upon load
type StoreUpgrades struct {
Added []string `json:"added"`
Renamed []StoreRename `json:"renamed"`
Deleted []string `json:"deleted"`
}
// UpgradeInfo defines height and name of the upgrade
// to ensure multistore upgrades happen only at matching height.
type UpgradeInfo struct {
Name string `json:"name"`
Height int64 `json:"height"`
}
// StoreRename defines a name change of a sub-store.
// All data previously under a PrefixStore with OldKey will be copied
// to a PrefixStore with NewKey, then deleted from OldKey store.
type StoreRename struct {
OldKey string `json:"old_key"`
NewKey string `json:"new_key"`
}
// IsDeleted returns true if the given key should be added
func (s *StoreUpgrades) IsAdded(key string) bool {
if s == nil {
return false
}
return oststrings.StringInSlice(key, s.Added)
}
// IsDeleted returns true if the given key should be deleted
func (s *StoreUpgrades) IsDeleted(key string) bool {
if s == nil {
return false
}
for _, d := range s.Deleted {
if d == key {
return true
}
}
return false
}
// RenamedFrom returns the oldKey if it was renamed
// Returns "" if it was not renamed
func (s *StoreUpgrades) RenamedFrom(key string) string {
if s == nil {
return ""
}
for _, re := range s.Renamed {
if re.NewKey == key {
return re.OldKey
}
}
return ""
}
type MultiStore interface {
Store
// Branches MultiStore into a cached storage object.
// NOTE: Caller should probably not call .Write() on each, but
// call CacheMultiStore.Write().
CacheMultiStore() CacheMultiStore
// CacheMultiStoreWithVersion branches the underlying MultiStore where
// each stored is loaded at a specific version (height).
CacheMultiStoreWithVersion(version int64) (CacheMultiStore, error)
// Convenience for fetching substores.
// If the store does not exist, panics.
GetStore(StoreKey) Store
GetKVStore(StoreKey) KVStore
// TracingEnabled returns if tracing is enabled for the MultiStore.
TracingEnabled() bool
// SetTracer sets the tracer for the MultiStore that the underlying
// stores will utilize to trace operations. The modified MultiStore is
// returned.
SetTracer(w io.Writer) MultiStore
// SetTracingContext sets the tracing context for a MultiStore. It is
// implied that the caller should update the context when necessary between
// tracing operations. The modified MultiStore is returned.
SetTracingContext(TraceContext) MultiStore
// ListeningEnabled returns if listening is enabled for the KVStore belonging the provided StoreKey
ListeningEnabled(key StoreKey) bool
// AddListeners adds WriteListeners for the KVStore belonging to the provided StoreKey
// It appends the listeners to a current set, if one already exists
AddListeners(key StoreKey, listeners []WriteListener)
}
// From MultiStore.CacheMultiStore()....
type CacheMultiStore interface {
MultiStore
Write() // Writes operations to underlying KVStore
}
// CommitMultiStore is an interface for a MultiStore without cache capabilities.
type CommitMultiStore interface {
Committer
MultiStore
snapshottypes.Snapshotter
// Mount a store of type using the given db.
// If db == nil, the new store will use the CommitMultiStore db.
MountStoreWithDB(key StoreKey, typ StoreType, db dbm.DB)
// Panics on a nil key.
GetCommitStore(key StoreKey) CommitStore
// Panics on a nil key.
GetCommitKVStore(key StoreKey) CommitKVStore
// Load the latest persisted version. Called once after all calls to
// Mount*Store() are complete.
LoadLatestVersion() error
// LoadLatestVersionAndUpgrade will load the latest version, but also
// rename/delete/create sub-store keys, before registering all the keys
// in order to handle breaking formats in migrations
LoadLatestVersionAndUpgrade(upgrades *StoreUpgrades) error
// LoadVersionAndUpgrade will load the named version, but also
// rename/delete/create sub-store keys, before registering all the keys
// in order to handle breaking formats in migrations
LoadVersionAndUpgrade(ver int64, upgrades *StoreUpgrades) error
// Load a specific persisted version. When you load an old version, or when
// the last commit attempt didn't complete, the next commit after loading
// must be idempotent (return the same commit id). Otherwise the behavior is
// undefined.
LoadVersion(ver int64) error
// Set an inter-block (persistent) cache that maintains a mapping from
// StoreKeys to CommitKVStores.
SetInterBlockCache(MultiStorePersistentCache)
// SetInitialVersion sets the initial version of the IAVL tree. It is used when
// starting a new chain at an arbitrary height.
SetInitialVersion(version int64) error
// SetIAVLCacheSize sets the cache size of the IAVL tree.
SetIAVLCacheSize(size int)
// SetIAVLDisableFastNode enables/disables fastnode feature on iavl.
SetIAVLDisableFastNode(disable bool)
// RollbackToVersion rollback the db to specific version(height).
RollbackToVersion(version int64) error
}
//---------subsp-------------------------------
// KVStore
// KVStore is a simple interface to get/set data
type KVStore interface {
Store
// Get returns nil if key doesn't exist. Panics on nil key.
Get(key []byte) []byte
// Has checks if a key exists. Panics on nil key.
Has(key []byte) bool
// Set sets the key. Panics on nil key or value.
Set(key, value []byte)
// Delete deletes the key. Panics on nil key.
Delete(key []byte)
// 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.
// To iterate over entire domain, use store.Iterator(nil, nil)
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
// Exceptionally allowed for cachekv.Store, safe to write in the modules.
Iterator(start, end []byte) Iterator
// Iterator over a domain of keys in descending order. End is exclusive.
// Start must be less than end, or the Iterator is invalid.
// Iterator must be closed by caller.
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
// Exceptionally allowed for cachekv.Store, safe to write in the modules.
ReverseIterator(start, end []byte) Iterator
}
// Iterator is an alias db's Iterator for convenience.
type Iterator = dbm.Iterator
// CacheKVStore branches a KVStore and provides read cache functionality.
// After calling .Write() on the CacheKVStore, all previously created
// CacheKVStores on the object expire.
type CacheKVStore interface {
KVStore
// Writes operations to underlying KVStore
Write()
}
// CommitKVStore is an interface for MultiStore.
type CommitKVStore interface {
Committer
KVStore
}
//----------------------------------------
// CacheWrap
// CacheWrap is the most appropriate interface for store ephemeral branching and cache.
// For example, IAVLStore.CacheWrap() returns a CacheKVStore. CacheWrap should not return
// a Committer, since Commit ephemeral store make no sense. It can return KVStore,
// HeapStore, SpaceStore, etc.
type CacheWrap interface {
// Write syncs with the underlying store.
Write()
// CacheWrap recursively wraps again.
CacheWrap() CacheWrap
// CacheWrapWithTrace recursively wraps again with tracing enabled.
CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap
// CacheWrapWithListeners recursively wraps again with listening enabled
CacheWrapWithListeners(storeKey StoreKey, listeners []WriteListener) CacheWrap
}
type CacheWrapper interface {
// CacheWrap branches a store.
CacheWrap() CacheWrap
// CacheWrapWithTrace branches a store with tracing enabled.
CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap
// CacheWrapWithListeners recursively wraps again with listening enabled
CacheWrapWithListeners(storeKey StoreKey, listeners []WriteListener) CacheWrap
}
func (cid CommitID) IsZero() bool {
return cid.Version == 0 && len(cid.Hash) == 0
}
func (cid CommitID) String() string {
return fmt.Sprintf("CommitID{%v:%X}", cid.Hash, cid.Version)
}
//----------------------------------------
// Store types
// kind of store
type StoreType int
const (
StoreTypeMulti StoreType = iota
StoreTypeDB
StoreTypeIAVL
StoreTypeTransient
StoreTypeMemory
)
func (st StoreType) String() string {
switch st {
case StoreTypeMulti:
return "StoreTypeMulti"
case StoreTypeDB:
return "StoreTypeDB"
case StoreTypeIAVL:
return "StoreTypeIAVL"
case StoreTypeTransient:
return "StoreTypeTransient"
case StoreTypeMemory:
return "StoreTypeMemory"
}
return "unknown store type"
}
//----------------------------------------
// Keys for accessing substores
// StoreKey is a key used to index stores in a MultiStore.
type StoreKey interface {
Name() string
String() string
}
// CapabilityKey represent the Cosmos SDK keys for object-capability
// generation in the IBC protocol as defined in https://github.com/cosmos/ics/tree/master/spec/ics-005-port-allocation#data-structures
type CapabilityKey StoreKey
// KVStoreKey is used for accessing substores.
// Only the pointer value should ever be used - it functions as a capabilities key.
type KVStoreKey struct {
name string
}
// NewKVStoreKey returns a new pointer to a KVStoreKey.
// Use a pointer so keys don't collide.
func NewKVStoreKey(name string) *KVStoreKey {
if name == "" {
panic("empty key name not allowed")
}
return &KVStoreKey{
name: name,
}
}
func (key *KVStoreKey) Name() string {
return key.name
}
func (key *KVStoreKey) String() string {
return fmt.Sprintf("KVStoreKey{%p, %s}", key, key.name)
}
// TransientStoreKey is used for indexing transient stores in a MultiStore
type TransientStoreKey struct {
name string
}
// Constructs new TransientStoreKey
// Must return a pointer according to the ocap principle
func NewTransientStoreKey(name string) *TransientStoreKey {
return &TransientStoreKey{
name: name,
}
}
// 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)
}
// MemoryStoreKey defines a typed key to be used with an in-memory KVStore.
type MemoryStoreKey struct {
name string
}
func NewMemoryStoreKey(name string) *MemoryStoreKey {
return &MemoryStoreKey{name: name}
}
// Name returns the name of the MemoryStoreKey.
func (key *MemoryStoreKey) Name() string {
return key.name
}
// String returns a stringified representation of the MemoryStoreKey.
func (key *MemoryStoreKey) String() string {
return fmt.Sprintf("MemoryStoreKey{%p, %s}", key, key.name)
}
//----------------------------------------
// key-value result for iterator queries
type KVPair kv.Pair
//----------------------------------------
// TraceContext contains TraceKVStore context data. It will be written with
// every trace operation.
type TraceContext map[string]interface{}
// MultiStorePersistentCache defines an interface which provides inter-block
// (persistent) caching capabilities for multiple CommitKVStores based on StoreKeys.
type MultiStorePersistentCache interface {
// Wrap and return the provided CommitKVStore with an inter-block (persistent)
// cache.
GetStoreCache(key StoreKey, store CommitKVStore) CommitKVStore
// Return the underlying CommitKVStore for a StoreKey.
Unwrap(key StoreKey) CommitKVStore
// Reset the entire set of internal caches.
Reset()
}
// StoreWithInitialVersion is a store that can have an arbitrary initial
// version.
type StoreWithInitialVersion interface {
// SetInitialVersion sets the initial version of the IAVL tree. It is used when
// starting a new chain at an arbitrary height.
SetInitialVersion(version int64)
}