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