github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/docs/core/store.md (about)

     1  <!--
     2  order: 5
     3  synopsis: A store is a data structure that holds the state of the application. 
     4  -->
     5  
     6  # Store
     7  
     8  ## Pre-requisite Readings {hide}
     9  
    10  - [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq}
    11  
    12  ## Introduction to SDK Stores
    13  
    14  The Cosmos SDK comes with a large set of stores to persist the state of applications. By default, the main store of SDK applications is a `multistore`, i.e. a store of stores. Developers can add any number of key-value stores to the multistore, depending on their application needs. The multistore exists to support the modularity of the Cosmos SDK, as it lets each module declare and manage their own subset of the state. Key-value stores in the multistore can only be accessed with a specific capability `key`, which is typically held in the [`keeper`](../building-modules/keeper.md) of the module that declared the store. 
    15  
    16  ```
    17  +-----------------------------------------------------+
    18  |                                                     |
    19  |    +--------------------------------------------+   |
    20  |    |                                            |   |
    21  |    |  KVStore 1 - Manage by keeper of Module 1  |
    22  |    |                                            |   |
    23  |    +--------------------------------------------+   |
    24  |                                                     |
    25  |    +--------------------------------------------+   |
    26  |    |                                            |   |
    27  |    |  KVStore 2 - Manage by keeper of Module 2  |   |
    28  |    |                                            |   |
    29  |    +--------------------------------------------+   |
    30  |                                                     |
    31  |    +--------------------------------------------+   |
    32  |    |                                            |   |
    33  |    |  KVStore 3 - Manage by keeper of Module 2  |   |
    34  |    |                                            |   |
    35  |    +--------------------------------------------+   |
    36  |                                                     |
    37  |    +--------------------------------------------+   |
    38  |    |                                            |   |
    39  |    |  KVStore 4 - Manage by keeper of Module 3  |   |
    40  |    |                                            |   |
    41  |    +--------------------------------------------+   |
    42  |                                                     |
    43  |    +--------------------------------------------+   |
    44  |    |                                            |   |
    45  |    |  KVStore 5 - Manage by keeper of Module 4  |   |
    46  |    |                                            |   |
    47  |    +--------------------------------------------+   |
    48  |                                                     |
    49  |                    Main Multistore                  |
    50  |                                                     |
    51  +-----------------------------------------------------+
    52  
    53                     Application's State
    54  ```
    55  
    56  ### Store Interface
    57  
    58  At its very core, a Cosmos SDK `store` is an object that holds a `CacheWrapper` and implements a `GetStoreType()` method:
    59  
    60  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L12-L15
    61  
    62  The `GetStoreType` is a simple method that returns the type of store, whereas a `CacheWrapper` is a simple interface that specifies cache-wrapping and `Write` methods:
    63  
    64  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L217-L238
    65  
    66  Cache-wrapping is used ubiquitously in the Cosmos SDK and required to be implemented on every store type. A cache-wrapper creates a light snapshot of a store that can be passed around and updated without affecting the main underlying store. This is used to trigger temporary state-transitions that may be reverted later should an error occur. If a state-transition sequence is performed without issue, the cached store can be comitted to the underlying store at the end of the sequence. 
    67  
    68  ### Commit Store
    69  
    70  A commit store is a store that has the ability to commit changes made to the underlying tree or db. The Cosmos SDK differentiates simple stores from commit stores by extending the basic store interfaces with a `Committer`:
    71  
    72  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L24-L28
    73  
    74  The `Committer` is an interface that defines methods to persist changes to disk:
    75  
    76  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L17-L22
    77  
    78  The `CommitID` is a deterministic commit of the state tree. Its hash is returned to the underlying consensus engine and stored in the block header. Note that commit store interfaces exist for various purposes, one of which is to make sure not every object can commit the store. As part of the [object-capabilities model](./ocap.md) of the Cosmos SDK, only `baseapp` should have the ability to commit stores. For example, this is the reason why the `ctx.KVStore()` method by which modules typically access stores returns a `KVStore` and not a `CommitKVStore`. 
    79  
    80  The Cosmos SDK comes with many types of stores, the most used being [`CommitMultiStore`](#multistore), [`KVStore`](#kvstore) and [`GasKv` store](#gaskv-store). [Other types of stores](#other-stores) include `Transient` and `TraceKV` stores. 
    81  
    82  ## Multistore
    83  
    84  ### Multistore Interface
    85  
    86  Each Cosmos SDK application holds a multistore at its root to persist its state. The multistore is a store of `KVStores` that follows the `Multistore` interface:
    87  
    88  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L83-L112
    89  
    90  If tracing is enabled, then cache-wrapping the multistore will wrap all the underlying `KVStore` in [`TraceKv.Store`](#tracekv-store) before caching them. 
    91  
    92  ### CommitMultiStore
    93  
    94  The main type of `Multistore` used in the Cosmos SDK is `CommitMultiStore`, which is an extension of the `Multistore` interface:
    95  
    96  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L120-L158
    97  
    98  As for concrete implementation, the [`rootMulti.Store`] is the go-to implementation of the `CommitMultiStore` interface. 
    99  
   100  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/rootmulti/store.go#L27-L43
   101  
   102  The `rootMulti.Store` is a base-layer multistore built around a `db` on top of which multiple `KVStores` can be mounted, and is the default multistore store used in [`baseapp`](./baseapp.md). 
   103  
   104  ### CacheMultiStore
   105  
   106  Whenever the `rootMulti.Store` needs to be cached-wrapped, a [`cachemulti.Store`](https://github.com/cosmos/cosmos-sdk/blob/master/store/cachemulti/store.go) is used. 
   107  
   108  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/cachemulti/store.go#L17-L28
   109  
   110  `cachemulti.Store` cache wraps all substores in its constructor and hold them in `Store.stores`. `Store.GetKVStore()` returns the store from `Store.stores`, and `Store.Write()` recursively calls `CacheWrap.Write()` on all the substores.
   111  
   112  ## Base-layer KVStores
   113  
   114  ### `KVStore` and `CommitKVStore` Interfaces
   115  
   116  A `KVStore` is a simple key-value store used to store and retrieve data. A `CommitKVStore` is a `KVStore` that also implements a `Committer`. By default, stores mounted in `baseapp`'s main `CommitMultiStore` are `CommitKVStore`s. The `KVStore` interface is primarily used to restrict modules from accessing  the committer. 
   117  
   118  Individual `KVStore`s are used by modules to manage a subset of the global state. `KVStores` can be accessed by objects that hold a specific key. This `key` should only be exposed to the [`keeper`](../building-modules/keeper.md) of the module that defines the store. 
   119  
   120  `CommitKVStore`s are declared by proxy of their respective `key` and mounted on the application's [multistore](#multistore) in the [main application file](../basics/app-anatomy.md#core-application-file).  In the same file, the `key` is also passed to the module's `keeper` that is responsible for managing the store. 
   121  
   122  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L163-L193
   123  
   124  Apart from the traditional `Get` and `Set` methods, a `KVStore` is expected to implement an `Iterator()` method which returns an `Iterator` object. The `Iterator()` method is used to iterate over a domain of keys, typically keys that share a common prefix. Here is a common pattern of using an `Iterator` that might be found in a module's `keeper`:
   125  
   126  ```go
   127  store := ctx.KVStore(keeper.storeKey)
   128  iterator := sdk.KVStorePrefixIterator(store, prefix) // proxy for store.Iterator
   129  
   130  defer iterator.Close()
   131  for ; iterator.Valid(); iterator.Next() {
   132  	var object types.Object
   133  	keeper.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &object)
   134  
   135  	if cb(object) {
   136          break
   137      }
   138  }
   139  ```
   140  
   141  ### `IAVL` Store
   142  
   143  The default implementation of `KVStore` and `CommitKVStore` used in `baseapp` is the `iavl.Store`.
   144  
   145  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/iavl/store.go#L32-L47
   146  
   147   `iavl` stores are based around an [IAVL Tree](https://github.com/tendermint/iavl), a self-balancing binary tree which guarantees that:
   148  
   149  - `Get` and `Set` operations are O(log n), where n is the number of elements in the tree.
   150  - Iteration efficiently returns the sorted elements within the range.
   151  - Each tree version is immutable and can be retrieved even after a commit (depending on the pruning settings). 
   152  
   153  The documentation on the IAVL Tree is located [here](https://github.com/tendermint/iavl/blob/f9d4b446a226948ed19286354f0d433a887cc4a3/docs/overview.md).
   154  
   155  ### `DbAdapter` Store
   156  
   157  `dbadapter.Store` is a adapter for `dbm.DB` making it fulfilling the `KVStore` interface.
   158  
   159  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/dbadapter/store.go#L13-L16
   160  
   161  `dbadapter.Store` embeds `dbm.DB`, meaning most of the `KVStore` interface functions are implemented. The other functions (mostly miscellaneous) are manually implemented. This store is primarily used within [Transient Stores](#transient-stores)
   162  
   163  ### `Transient` Store
   164  
   165  `Transient.Store` is a base-layer `KVStore` which is automatically discarded at the end of the block.
   166  
   167  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/transient/store.go#L14-L17
   168  
   169  `Transient.Store` is a `dbadapter.Store` with a `dbm.NewMemDB()`. All `KVStore` methods are reused. When `Store.Commit()` is called, a new `dbadapter.Store` is assigned, discarding previous reference and making it garbage collected.
   170  
   171  This type of store is useful to persist information that is only relevant per-block. One example would be to store parameter changes (i.e. a bool set to `true` if a parameter changed in a block). 
   172  
   173  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/params/subspace/subspace.go#L24-L32
   174  
   175  Transient stores are typically accessed via the [`context`](./context.md) via the `TransientStore()` method:
   176  
   177  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/context.go#L215-L218
   178  
   179  ## KVStore Wrappers
   180  
   181  ### CacheKVStore
   182  
   183  `cachekv.Store` is a wrapper `KVStore` which provides buffered writing / cached reading functionalities over the underlying `KVStore`.
   184  
   185  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/cachekv/store.go#L26-L33
   186  
   187  This is the type used whenever an IAVL Store needs to be cache-wrapped (typically when setting value that might be reverted later). 
   188  
   189  #### `Get`
   190  
   191  `Store.Get()` checks `Store.cache` first in order to find if there is any cached value associated with the key. If the value exists, the function returns it. If not, the function calls `Store.parent.Get()`, sets the key-value pair to the `Store.cache`, and returns it.
   192  
   193  #### `Set`
   194  
   195  `Store.Set()` sets the key-value pair to the `Store.cache`. `cValue` has the field dirty bool which indicates whether the cached value is different from the underlying value. When `Store.Set()` cache new pair, the `cValue.dirty` is set `true` so when `Store.Write()` is called it can be written to the underlying store.
   196  
   197  #### `Iterator`
   198  
   199  `Store.Iterator()` have to traverse on both caches items and the original items. In `Store.iterator()`, two iterators are generated for each of them, and merged. `memIterator` is essentially a slice of the `KVPairs`, used for cached items. `mergeIterator` is a combination of two iterators, where traverse happens ordered on both iterators.
   200  
   201  ### `GasKv` Store
   202  
   203  Cosmos SDK applications use [`gas`](../basics/gas-fees.md) to track resources usage and prevent spam. [`GasKv.Store`](https://github.com/cosmos/cosmos-sdk/blob/master/store/gaskv/store.go) is a `KVStore` wrapper that enables automatic gas consumption each time a read or write to the store is made. It is the solution of choice to track storage usage in Cosmos SDK applications.
   204  
   205  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/gaskv/store.go#L11-L17
   206  
   207  When methods of the parent `KVStore` are called, `GasKv.Store` automatically consumes appropriate amount of gas depending on the `Store.gasConfig`:
   208  
   209  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/gas.go#L141-L150
   210  
   211  By default, all `KVStores` are wrapped in `GasKv.Stores` when retrieved. This is done in the `KVStore()` method of the [`context`](./context.md):
   212  
   213  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/context.go#L210-L213
   214  
   215  In this case, the default gas configuration is used:
   216  
   217  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/gas.go#L152-L163
   218  
   219  ### `TraceKv` Store
   220  
   221  `tracekv.Store` is a wrapper `KVStore` which provides operation tracing functionalities over the underlying `KVStore`. It is applied automatically by the Cosmos SDK on all `KVStore` if tracing is enabled on the parent `MultiStore`. 
   222  
   223  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/tracekv/store.go#L20-L43
   224  
   225  When each `KVStore` methods are called, `tracekv.Store` automatically logs `traceOperation` to the `Store.writer`. `traceOperation.Metadata` is filled with `Store.context` when it is not nil. `TraceContext` is a `map[string]interface{}`.
   226  
   227  ### `Prefix` Store
   228  
   229  `prefix.Store` is a wrapper `KVStore` which provides automatic key-prefixing functionalities over the underlying `KVStore`.
   230  
   231  +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/prefix/store.go#L17-L20
   232  
   233  When `Store.{Get, Set}()` is called, the store forwards the call to its parent, with the key prefixed with the `Store.prefix`.
   234  
   235  When `Store.Iterator()` is called, it does not simply prefix the `Store.prefix`, since it does not work as intended. In that case, some of the elements are traversed even they are not starting with the prefix.
   236  
   237  ## Next {hide}
   238  
   239  Learn about [encoding](./encoding.md) {hide}