A store is a data structure that holds the state of the application.
The Cosmos SDK store package provides interfaces, types, and abstractions for managing Merkleized state storage and commitment within a Cosmos SDK application. The package supplies various primitives for developers to work with, including state storage, state commitment, and wrapper KVStores. This document highlights the key abstractions and their significance.
The main store in Cosmos SDK applications is a multistore, a store of stores, that supports modularity. Developers can add any number of key-value stores to the multistore based on their application needs. Each module can declare and manage its own subset of the state, allowing for a modular approach. Key-value stores within the multistore can only be accessed with a specific capability key, which is typically held in the keeper of the module that declared the store.
KVStore interface defines a key-value store that can be used to store and retrieve data. The default implementation of
KVStore used in
baseapp is the
iavl.Store, which is based on an IAVL Tree. KVStores can be accessed by objects that hold a specific key and can provide an
Iterator method that returns an
Iterator object, used to iterate over a range of keys.
CommitKVStore interface extends the
KVStore interface and adds methods for state commitment. The default implementation of
CommitKVStore used in
baseapp is also the
StoreDB interface defines a database that can be used to persist key-value stores. The default implementation of
StoreDB used in
baseapp is the
dbm.DB, which is a simple persistent key-value store.
DBAdapter interface defines an adapter for
dbm.DB that fulfills the
KVStore interface. This interface is used to provide compatibility between the
dbm.DB implementation and the
TransientStore interface defines a base-layer KVStore which is automatically discarded at the end of the block and is useful for persisting information that is only relevant per-block, like storing parameter changes.
The store package provides a comprehensive set of abstractions for managing state commitment and storage in an SDK application. These abstractions include CacheWrapping, KVStore, and CommitMultiStore, which offer a range of features such as CRUD functionality, prefix-based iteration, and state commitment management.
By utilizing these abstractions, developers can create modular applications with independent state management for each module. This approach allows for a more organized and maintainable application structure.
CacheWrap is a wrapper around a KVStore that provides caching for both read and write operations. The CacheWrap can be used to improve performance by reducing the number of disk reads and writes required for state storage operations. The CacheWrap also includes a Write method that commits the pending writes to the underlying KVStore.
The HistoryStore is an optional feature that can be used to store historical versions of the state. The HistoryStore can be used to track changes to the state over time, allowing developers to analyze changes in the state and roll back to previous versions if necessary.
The IndexStore is a type of KVStore that is used to maintain indexes of data stored in other KVStores. IndexStores can be used to improve query performance by providing a way to quickly search for data based on specific criteria.
The Queryable interface is used to provide a way for applications to query the state stored in a KVStore. The Queryable interface includes methods for retrieving data based on a key or a range of keys, as well as methods for retrieving data based on specific criteria.
The PrefixIterator interface is used to iterate over a range of keys in a KVStore that share a common prefix. PrefixIterators can be used to efficiently retrieve subsets of data from a KVStore based on a specific prefix.
The RootMultiStore is a Multistore that provides the ability to retrieve a snapshot of the state at a specific height. This is useful for implementing light clients.
The GasKVStore is a wrapper around a KVStore that provides gas measurement for read and write operations. The GasKVStore is typically used to measure the cost of executing transactions.
While there are many interfaces that the store package provides, there is typically a core implementation for each main interface that modules and developers interact with that are defined in the Cosmos SDK.
iavl.Store provides the core implementation for state storage and commitment by implementing the following interfaces:
iavl.Store also provides the ability to remove historical state from the state commitment layer.
An overview of the IAVL implementation can be found here.
Other store abstractions include
rootmulti.Store. Each of these stores provide additional functionality and abstractions for developers to work with.
Note that concurrent access to the
iavl.Store tree is not safe, and it is the responsibility of the caller to ensure that concurrent access to the store is not performed.
Store migration is the process of updating the structure of a KVStore to support new features or changes in the data model. Store migration can be a complex process, but it is essential for maintaining the integrity of the state stored in a KVStore.