github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/store/README.md (about)

     1  # Store
     2  
     3  ## CacheKV
     4  
     5  `cachekv.Store` is a wrapper `KVStore` which provides buffered writing / cached reading functionalities over the underlying `KVStore`.
     6  
     7  ```go
     8  type Store struct {
     9      cache map[string]cValue
    10      parent types.KVStore
    11  }
    12  ```
    13  
    14  ### Get
    15  
    16  `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.
    17  
    18  ### Set
    19  
    20  `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.
    21  
    22  ### Iterator
    23  
    24  `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 `KVPair`s, used for cached items. `mergeIterator` is a combination of two iterators, where traverse happens ordered on both iterators.
    25  
    26  ## CacheMulti
    27  
    28  `cachemulti.Store` is a wrapper `MultiStore` which provides buffered writing / cached reading functionalities over the underlying `MultiStore`
    29  
    30  ```go
    31  type Store struct {
    32      db types.CacheKVStore
    33      stores map[types.StoreKey] types.CacheWrap
    34  }
    35  ```
    36  
    37  `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 the substores.
    38  
    39  ## DBAdapter
    40  
    41  `dbadapter.Store` is a adapter for `dbm.DB` making it fulfilling the `KVStore` interface.
    42  
    43  ```go
    44  type Store struct {
    45      dbm.DB
    46  }
    47  ```
    48  
    49  `dbadapter.Store` embeds `dbm.DB`, so most of the `KVStore` interface functions are implemented. The other functions(mostly miscellaneous) are manually implemented.
    50  
    51  ## IAVL
    52  
    53  `iavl.Store` is a base-layer self-balancing merkle tree. It is guaranteed that
    54  
    55  1. Get & set operations are `O(log n)`, where `n` is the number of elements in the tree
    56  2. Iteration efficiently returns the sorted elements within the range
    57  3. Each tree version is immutable and can be retrieved even after a commit(depending on the pruning settings)
    58  
    59  Specification and implementation of IAVL tree can be found in [https://github.com/tendermint/classic/iavl].
    60  
    61  ## GasKV
    62  
    63  `gaskv.Store` is a wrapper `KVStore` which provides gas consuming functionalities over the underlying `KVStore`.
    64  
    65  ```go
    66  type Store struct {
    67      gasMeter types.GasMeter
    68      gasConfig types.GasConfig
    69      parent types.KVStore
    70  }
    71  ```
    72  
    73  When each `KVStore` methods are called, `gaskv.Store` automatically consumes appropriate amount of gas depending on the `Store.gasConfig`.
    74  
    75  
    76  ## Prefix
    77  
    78  `prefix.Store` is a wrapper `KVStore` which provides automatic key-prefixing functionalities over the underlying `KVStore`.
    79  
    80  ```go
    81  type Store struct {
    82      parent types.KVStore
    83      prefix []byte
    84  }
    85  ```
    86  
    87  When `Store.{Get, Set}()` is called, the store forwards the call to its parent, with the key prefixed with the `Store.prefix`.
    88  
    89  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.
    90  
    91  ## RootMulti
    92  
    93  `rootmulti.Store` is a base-layer `MultiStore` where multiple `KVStore` can be mounted on it and retrieved via object-capability keys. The keys are memory addresses, so it is impossible to forge the key unless an object is a valid owner(or a receiver) of the key, according to the object capability principles.
    94  
    95  ## TraceKV
    96  
    97  `tracekv.Store` is a wrapper `KVStore` which provides operation tracing functionalities over the underlying `KVStore`.
    98  
    99  ```go
   100  type Store struct {
   101      parent types.KVStore
   102      writer io.Writer
   103      context types.TraceContext
   104  }
   105  ```
   106  
   107  When each `KVStore` methods are called, `tracekv.Store` automatically logs `traceOperation` to the `Store.writer`.
   108  
   109  ```go
   110  type traceOperation struct {
   111      Operation operation
   112      Key string
   113      Value string
   114      Metadata map[string]interface{}
   115  }
   116  ```
   117  
   118  `traceOperation.Metadata` is filled with `Store.context` when it is not nil. `TraceContext` is a `map[string]interface{}`.
   119  
   120  ## Transient
   121  
   122  `transient.Store` is a base-layer `KVStore` which is automatically discarded at the end of the block.
   123  
   124  ```go
   125  type Store struct {
   126      dbadapter.Store
   127  }
   128  ```
   129  
   130  `Store.Store` is a `dbadapter.Store` with a `memdb.NewMemDB()`. All `KVStore` methods are reused. When `Store.Commit()` is called, new `dbadapter.Store` is assigned, discarding previous reference and making it garbage collected.