diff --git a/docs/architecture/adr-065-store-v2.md b/docs/architecture/adr-065-store-v2.md index b1377555e02..a6b054d68ed 100644 --- a/docs/architecture/adr-065-store-v2.md +++ b/docs/architecture/adr-065-store-v2.md @@ -79,13 +79,11 @@ We propose to build upon some of the great ideas introduced in [ADR-040](./adr-0 while being a bit more flexible with the underlying implementations and overall less intrusive. Specifically, we propose to: -* Separate the concerns of state commitment (**SC**), needed for consensus, and - state storage (**SS**), needed for state machine and clients. * Reduce layers of abstractions necessary between the RMS and underlying stores. * Remove unnecessary store types and implementations such as `CacheKVStore`. -* Simplify the branching logic. +* Remove the branching logic from the store package. * Ensure the `RootStore` interface remains as lightweight as possible. -* Allow application developers to easily swap out SS and SC backends. +* Allow application developers to easily swap out SC backends. Furthermore, we will keep IAVL as the default [SC](https://cryptography.fandom.com/wiki/Commitment_scheme) backend for the time being. While we might not fully settle on the use of IAVL in @@ -95,18 +93,12 @@ to change the backing commitment store in the future should evidence arise to warrant a better alternative. However there is promising work being done to IAVL that should result in significant performance improvement [1,2]. -Note, we will provide applications with the ability to use IAVL v1 and IAVL v2 as +Note, we will provide applications with the ability to use IAVL v1, IAVL v2 and MemIAVL as either SC backend, with the latter showing extremely promising performance improvements over IAVL v0 and v1, at the cost of a state migration. -### Separating SS and SC -By separating SS and SC, it will allow for us to optimize against primary use cases -and access patterns to state. Specifically, The SS layer will be responsible for -direct access to data in the form of (key, value) pairs, whereas the SC layer (e.g. IAVL) -will be responsible for committing to data and providing Merkle proofs. - -#### State Commitment (SC) +### State Commitment (SC) A foremost design goal is that SC backends should be easily swappable, i.e. not necessarily IAVL. To this end, the scope of SC has been reduced, it must only: @@ -121,45 +113,6 @@ due to the time and space constraints, but since store v2 defines an API for his proofs there should be at least one configuration of a given SC backend which supports this. -#### State Storage (SS) - -The goal of SS is to provide a modular storage backend, i.e. multiple implementations, -to facilitate storing versioned raw key/value pairs in a fast embedded database. -The responsibility and functions of SS include the following: - -* Provided fast and efficient queries for versioned raw key/value pairs -* Provide versioned CRUD operations -* Provide versioned batching functionality -* Provide versioned iteration (forward and reverse) functionality -* Provide pruning functionality - -All of the functionality provided by an SS backend should work under a versioned -scheme, i.e. a user should be able to get, store, and iterate over keys for the latest -and historical versions efficiently and a store key, which is used for name-spacing -purposes. - -We propose to have three defaulting SS backends for applications to choose from: - -* RocksDB - * CGO based - * Usage of User-Defined Timestamps as a built-in versioning mechanism -* PebbleDB - * Native - * Manual implementation of MVCC keys for versioning -* SQLite - * CGO based - * Single table for all state - -Since operators might want pruning strategies to differ in SS compared to SC, -e.g. having a very tight pruning strategy in SC while having a looser pruning -strategy for SS, we propose to introduce an additional pruning configuration, -with parameters that are identical to what exists in the SDK today, and allow -operators to control the pruning strategy of the SS layer independently of the -SC layer. - -Note, the SC pruning strategy must be congruent with the operator's state sync -configuration. This is so as to allow state sync snapshots to execute successfully, -otherwise, a snapshot could be triggered on a height that is not available in SC. #### State Sync @@ -179,7 +132,7 @@ the primary interface for the application to interact with. The `RootStore` will be responsible for housing SS and SC backends. Specifically, a `RootStore` will provide the following functionality: -* Manage commitment of state (both SS and SC) +* Manage commitment of state * Provide modules access to state * Query delegation (i.e. get a value for a tuple) * Providing commitment proofs @@ -197,12 +150,7 @@ solely provide key prefixing/namespacing functionality for modules. #### Proofs -Since the SS layer is naturally a storage layer only, without any commitments -to (key, value) pairs, it cannot provide Merkle proofs to clients during queries. - -So providing inclusion and exclusion proofs, via a `CommitmentOp` type, will be -the responsibility of the SC backend. Retrieving proofs will be done through the -a `RootStore`, which will internally route the request to the SC backend. +Providing a `CommitmentOp` type, will be the responsibility of the SC backend. Retrieving proofs will be done through the a `RootStore`, which will internally route the request to the SC backend. #### Commitment @@ -231,9 +179,6 @@ and storage backends for further performance, in addition to a reduced amount of abstraction around KVStores making operations such as caching and state branching more intuitive. -However, due to the proposed design, there are drawbacks around providing state -proofs for historical queries. - ### Backwards Compatibility This ADR proposes changes to the storage implementation in the Cosmos SDK through @@ -243,17 +188,14 @@ be broken or modified. ### Positive -* Improved performance of independent SS and SC layers +* Improved performance of SC layers * Reduced layers of abstraction making storage primitives easier to understand -* Atomic commitments for SC * Redesign of storage types and interfaces will allow for greater experimentation such as different physical storage backends and different commitment schemes for different application modules ### Negative -* Providing proofs for historical state is challenging - ### Neutral * Removal of OCAP-based store keys in favor of simple strings for state retrieval diff --git a/docs/build/building-apps/00-runtime.md b/docs/build/building-apps/00-runtime.md index a962019e299..5f9ab6f9287 100644 --- a/docs/build/building-apps/00-runtime.md +++ b/docs/build/building-apps/00-runtime.md @@ -5,5 +5,23 @@ sidebar_position: 1 # What is `runtime`? The `runtime` package is the Cosmos SDK package that combines the building blocks of your blockchain together. It wires together the modules, the applications, the codecs, and the stores. +It is a layer of abstraction between `baseapp` and the application modules that simplifies the process of building a Cosmos SDK application. +## Modules wiring + +Runtime is responsible for wiring the modules together. It uses `depinject` to inject the dependencies of the modules. + +## App wiring + +Runtime is the base boilerplate of a Cosmos SDK application. A user only needs to import `runtime` in their `app.go` and instantiate a `runtime.App`. + +## Services + +Modules have access to a multitude of services that are provided by the runtime. +These services include the `store`, the `event manager`, the `context`, and the `logger`. +As runtime is doing the wiring of modules, it can ensure that the services are scoped to their respective modules. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/runtime/module.go#L250-L279 +``` diff --git a/docs/build/building-modules/00-intro.md b/docs/build/building-modules/00-intro.md index 6618a44caa6..bd8e78a4238 100644 --- a/docs/build/building-modules/00-intro.md +++ b/docs/build/building-modules/00-intro.md @@ -58,6 +58,13 @@ While there are no definitive guidelines for writing modules, here are some impo * **Specialization**: A direct consequence of the **composability** feature is that modules should be **specialized**. Developers should carefully establish the scope of their module and not batch multiple functionalities into the same module. This separation of concerns enables modules to be re-used in other projects and improves the upgradability of the application. **Specialization** also plays an important role in the [object-capabilities model](https://docs.cosmos.network/main/learn/advanced/ocap#ocaps-in-practice) of the Cosmos SDK. * **Capabilities**: Most modules need to read and/or write to the store(s) of other modules. However, in an open-source environment, it is possible for some modules to be malicious. That is why module developers need to carefully think not only about how their module interacts with other modules, but also about how to give access to the module's store(s). The Cosmos SDK takes a capabilities-oriented approach to inter-module security. This means that each store defined by a module is accessed by a `key`, which is held by the module's [`keeper`](./06-keeper.md). This `keeper` defines how to access the store(s) and under what conditions. Access to the module's store(s) is done by passing a reference to the module's `keeper`. +## Core APIs for Modules + +The SDK provides a set of APIs that a module can implement, and a set of services that a module can use. +Those APIs are defined in the `cosmossdk.io/core/appmodule` package, and are used to defined the module capabilities, which is used by `runtime` during the wiring of the application. + +Learn more about the core APIs for modules [here](../../learn/advanced/02-core.md). + ## Main Components of Cosmos SDK Modules Modules are by convention defined in the `./x/` subfolder (e.g. the `bank` module will be defined in the `./x/bank` folder). They generally share the same core components: diff --git a/docs/build/building-modules/01-module-manager.md b/docs/build/building-modules/01-module-manager.md index 1e3bf38aa95..9e6694ec332 100644 --- a/docs/build/building-modules/01-module-manager.md +++ b/docs/build/building-modules/01-module-manager.md @@ -217,11 +217,9 @@ The module manager is used throughout the application whenever an action on a co * `InitGenesis(ctx context.Context, genesisData map[string]json.RawMessage)`: Calls the [`InitGenesis`](./08-genesis.md#initgenesis) function of each module when the application is first started, in the order defined in `OrderInitGenesis`. Returns an `abci.InitChainResponse` to the underlying consensus engine, which can contain validator updates. * `ExportGenesis(ctx context.Context)`: Calls the [`ExportGenesis`](./08-genesis.md#exportgenesis) function of each module, in the order defined in `OrderExportGenesis`. The export constructs a genesis file from a previously existing state, and is mainly used when a hard-fork upgrade of the chain is required. * `ExportGenesisForModules(ctx context.Context, modulesToExport []string)`: Behaves the same as `ExportGenesis`, except takes a list of modules to export. -* `BeginBlock(ctx context.Context) error`: At the beginning of each block, this function is called from [`BaseApp`](../../learn/advanced/00-baseapp.md#beginblock) and, in turn, calls the [`BeginBlock`](./06-preblock-beginblock-endblock.md) function of each modules implementing the `appmodule.HasBeginBlocker` interface, in the order defined in `OrderBeginBlockers`. It creates a child [context](../../learn/advanced/02-context.md) with an event manager to aggregate [events](../../learn/advanced/08-events.md) emitted from each modules. -* `EndBlock(ctx context.Context) error`: At the end of each block, this function is called from [`BaseApp`](../../learn/advanced/00-baseapp.md#endblock) and, in turn, calls the [`EndBlock`](./06-preblock-beginblock-endblock.md) function of each modules implementing the `appmodule.HasEndBlocker` interface, in the order defined in `OrderEndBlockers`. It creates a child [context](../../learn/advanced/02-context.md) with an event manager to aggregate [events](../../learn/advanced/08-events.md) emitted from all modules. The function returns an `abci` which contains the aforementioned events, as well as validator set updates (if any). -* `EndBlock(context.Context) ([]abci.ValidatorUpdate, error)`: At the end of each block, this function is called from [`BaseApp`](../../learn/advanced/00-baseapp.md#endblock) and, in turn, calls the [`EndBlock`](./06-preblock-beginblock-endblock.md) function of each modules implementing the `module.HasABCIEndBlock` interface, in the order defined in `OrderEndBlockers`. It creates a child [context](../../learn/advanced/02-context.md) with an event manager to aggregate [events](../../learn/advanced/08-events.md) emitted from all modules. The function returns an `abci` which contains the aforementioned events, as well as validator set updates (if any). -* `Precommit(ctx context.Context)`: During [`Commit`](../../learn/advanced/00-baseapp.md#commit), this function is called from `BaseApp` immediately before the [`deliverState`](../../learn/advanced/00-baseapp.md#state-updates) is written to the underlying [`rootMultiStore`](../../learn/advanced/04-store.md#commitmultistore) and, in turn calls the `Precommit` function of each modules implementing the `HasPrecommit` interface, in the order defined in `OrderPrecommiters`. It creates a child [context](../../learn/advanced/02-context.md) where the underlying `CacheMultiStore` is that of the newly committed block's [`finalizeblockstate`](../../learn/advanced/00-baseapp.md#state-updates). -* `PrepareCheckState(ctx context.Context)`: During [`Commit`](../../learn/advanced/00-baseapp.md#commit), this function is called from `BaseApp` immediately after the [`deliverState`](../../learn/advanced/00-baseapp.md#state-updates) is written to the underlying [`rootMultiStore`](../../learn/advanced/04-store.md#commitmultistore) and, in turn calls the `PrepareCheckState` function of each module implementing the `HasPrepareCheckState` interface, in the order defined in `OrderPrepareCheckStaters`. It creates a child [context](../../learn/advanced/02-context.md) where the underlying `CacheMultiStore` is that of the next block's [`checkState`](../../learn/advanced/00-baseapp.md#state-updates). Writes to this state will be present in the [`checkState`](../../learn/advanced/00-baseapp.md#state-updates) of the next block, and therefore this method can be used to prepare the `checkState` for the next block. +* `BeginBlock(ctx context.Context) error`: At the beginning of each block, this function is called from [`BaseApp`](../../learn/advanced/00-baseapp.md#beginblock) and, in turn, calls the [`BeginBlock`](./06-preblock-beginblock-endblock.md) function of each modules implementing the `appmodule.HasBeginBlocker` interface, in the order defined in `OrderBeginBlockers`. +* `EndBlock(ctx context.Context) error`: At the end of each block, this function is called from [`BaseApp`](../../learn/advanced/00-baseapp.md#endblock) and, in turn, calls the [`EndBlock`](./06-preblock-beginblock-endblock.md) function of each modules implementing the `appmodule.HasEndBlocker` interface, in the order defined in `OrderEndBlockers`. +* `EndBlock(context.Context) ([]abci.ValidatorUpdate, error)`: At the end of each block, this function is called from [`BaseApp`](../../learn/advanced/00-baseapp.md#endblock) and, in turn, calls the [`EndBlock`](./06-preblock-beginblock-endblock.md) function of each modules implementing the `appmodule.HasABCIEndBlock` interface, in the order defined in `OrderEndBlockers`. Extended implementation for modules that need to update the validator set (typically used by the staking module). * (Optional) `RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)`: Registers the [`codec.LegacyAmino`s](../../learn/advanced/05-encoding.md#amino) of each of the application module. This function is usually called early on in the [application's construction](../../learn/beginner/00-app-anatomy.md#constructor). * `RegisterInterfaces(registry codectypes.InterfaceRegistry)`: Registers interface types and implementations of each of the application's `AppModule`. * (Optional) `RegisterGRPCGatewayRoutes(clientCtx client.Context, rtr *runtime.ServeMux)`: Registers gRPC routes for modules. diff --git a/docs/build/building-modules/05-protobuf-annotations.md b/docs/build/building-modules/05-protobuf-annotations.md index 9843a63398f..29dfe19d5f9 100644 --- a/docs/build/building-modules/05-protobuf-annotations.md +++ b/docs/build/building-modules/05-protobuf-annotations.md @@ -2,9 +2,9 @@ sidebar_position: 1 --- -# ProtocolBuffer Annotations +# Protocol buffer Annotations -This document explains the various protobuf scalars that have been added to make working with protobuf easier for Cosmos SDK application developers +This document explains the various protobuf scalars that have been added to make working with protobuf easier for Cosmos SDK application developers. ## Signer @@ -85,7 +85,7 @@ option (cosmos_proto.method_added_in) = "simapp v24.0.0"; The amino codec was removed in `v0.50+`, this means there is not a need register `legacyAminoCodec`. To replace the amino codec, Amino protobuf annotations are used to provide information to the amino codec on how to encode and decode protobuf messages. :::note -Amino annotations are only used for backwards compatibility with amino. New modules are not required use amino annotations. +Amino annotations are only used for backwards compatibility with amino. ::: The below annotations are used to provide information to the amino codec on how to encode and decode protobuf messages in a backwards compatible manner. diff --git a/docs/build/building-modules/06-keeper.md b/docs/build/building-modules/06-keeper.md index 59180170cfd..deb6727842a 100644 --- a/docs/build/building-modules/06-keeper.md +++ b/docs/build/building-modules/06-keeper.md @@ -5,7 +5,7 @@ sidebar_position: 1 # Keepers :::note Synopsis -`Keeper`s refer to a Cosmos SDK abstraction whose role is to manage access to the subset of the state defined by various modules. `Keeper`s are module-specific, i.e. the subset of state defined by a module can only be accessed by a `keeper` defined in said module. If a module needs to access the subset of state defined by another module, a reference to the second module's internal `keeper` needs to be passed to the first one. This is done in `app.go` during the instantiation of module keepers. +`Keeper`s refer to a Cosmos SDK abstraction whose role is to manage access to the subset of the state defined by various modules. `Keeper`s are module-specific, i.e. the subset of state defined by a module can only be accessed by a `keeper` defined in said module. If a module needs to access the subset of state defined by another module, a reference to the second module's internal `keeper` needs to be passed to the first one. This is done by specifying the module inputs in the `depinject` config; `runtime` will ensure that the correct `keeper` is passed to the module. ::: :::note Pre-requisite Readings @@ -28,9 +28,9 @@ The core idea behind the object-capabilities approach is to only reveal what is ```go type Keeper struct { - // External keepers, if any + appmodule.Environment - // Store key(s) + // External keepers, if any // codec @@ -46,8 +46,8 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/staking/keeper/keeper Let us go through the different parameters: +* Environment is a struct that holds the necessary references to services available to the modules. This includes the [store services](../../advanced/04-store.md#store-services), the [event manager](../../learn/advanced/06-events.md) and more. * An expected `keeper` is a `keeper` external to a module that is required by the internal `keeper` of said module. External `keeper`s are listed in the internal `keeper`'s type definition as interfaces. These interfaces are themselves defined in an `expected_keepers.go` file in the root of the module's folder. In this context, interfaces are used to reduce the number of dependencies, as well as to facilitate the maintenance of the module itself. -* `KVStoreService`s grant access to the store(s) of the [multistore](../../learn/advanced/04-store.md) managed by the module. They should always remain unexposed to external modules. * `cdc` is the [codec](../../learn/advanced/05-encoding.md) used to marshal and unmarshal structs to/from `[]byte`. The `cdc` can be any of `codec.BinaryCodec`, `codec.JSONCodec` or `codec.Codec` based on your requirements. It can be either a proto or amino codec as long as they implement these interfaces. * The authority listed is a module account or user account that has the right to change module level parameters. Previously this was handled by the param module, which has been deprecated. @@ -55,6 +55,21 @@ Of course, it is possible to define different types of internal `keeper`s for th ## Environment +Environment is a struct, part of the module Core APIs (`cosmossdk.io/core/appmodule`). +A keeper should embed the `environment` struct to get access to the necessary references to services available to the modules. [Runtime](../../build/building-apps/00-runtime.md) ensures that the `Environment` struct is scoped to the module. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/v2/environment.go#L14-L29 +``` + +All services are then easily available to the module wherever the `keeper` is used: + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/x/gov/keeper/proposal.go#L110-L112 +``` + +Learn more about those services in the [core api](../../learn/advanced/02-core.md) documentation. + ## Implementing Methods `Keeper`s primarily expose methods for business logic, as validity checks should have already been performed by the [`Msg` server](./03-msg-services.md) when `keeper`s' methods are called. @@ -67,5 +82,4 @@ State management is recommended to be done via [Collections](../packages/collect In the Cosmos SDK, it is crucial to be methodical and selective when managing state within a module, as improper state management can lead to inefficiency, security risks, and scalability issues. Not all data belongs in the on-chain state; it's important to store only essential blockchain data that needs to be verified by consensus. Storing unnecessary information, especially client-side data, can bloat the state and slow down performance. Instead, developers should focus on using an off-chain database to handle supplementary data, extending the API as needed. This approach minimizes on-chain complexity, optimizes resource usage, and keeps the blockchain state lean and efficient, ensuring scalability and smooth operations. - The Cosmos SDK leverages Protocol Buffers (protobuf) for efficient state management, providing a well-structured, binary encoding format that ensures compatibility and performance across different modules. The SDK’s recommended approach for managing state is through the [collections package](../pacakges/02-collections.md), which simplifies state handling by offering predefined data structures like maps and indexed sets, reducing the complexity of managing raw state data. While users can opt for custom encoding schemes if they need more flexibility or have specialized requirements, they should be aware that such custom implementations may not integrate seamlessly with indexers that decode state data on the fly. This could lead to challenges in data retrieval, querying, and interoperability, making protobuf a safer and more future-proof choice for most use cases. diff --git a/docs/learn/advanced/00-baseapp.md b/docs/learn/advanced/00-baseapp.md index e30bb4a9a0e..8fea13d4fd3 100644 --- a/docs/learn/advanced/00-baseapp.md +++ b/docs/learn/advanced/00-baseapp.md @@ -92,7 +92,7 @@ Finally, a few more important parameters: * `voteInfos`: This parameter carries the list of validators whose precommit is missing, either because they did not vote or because the proposer did not include their vote. This information is - carried by the [Context](./02-context.md) and can be used by the application for various things like + carried by the [Context](./17-context.md) and can be used by the application for various things like punishing absent validators. * `minGasPrices`: This parameter defines the minimum gas prices accepted by the node. This is a **local** parameter, meaning each full-node can set a different `minGasPrices`. It is used in the @@ -474,7 +474,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/baseapp/abci.go#L894 * Initialize the [block gas meter](../beginner/04-gas-fees.md#block-gas-meter) with the `maxGas` limit. The `gas` consumed within the block cannot go above `maxGas`. This parameter is defined in the application's consensus parameters. * Run the application's [`beginBlocker()`](../beginner/00-app-anatomy.md#beginblocker-and-endblocker), which mainly runs the [`BeginBlocker()`](../../build/building-modules/06-preblock-beginblock-endblock.md#beginblocker-and-endblocker) method of each of the modules. -* Set the [`VoteInfos`](https://docs.cometbft.com/v1.0/spec/abci/abci++_methods#voteinfo) of the application, i.e. the list of validators whose _precommit_ for the previous block was included by the proposer of the current block. This information is carried into the [`Context`](./02-context.md) so that it can be used during transaction execution and EndBlock. +* Set the [`VoteInfos`](https://docs.cometbft.com/v1.0/spec/abci/abci++_methods#voteinfo) of the application, i.e. the list of validators whose _precommit_ for the previous block was included by the proposer of the current block. This information is carried into the [`Context`](./17-context.md) so that it can be used during transaction execution and EndBlock. #### Transaction Execution diff --git a/docs/learn/advanced/01-transactions.md b/docs/learn/advanced/01-transactions.md index 5eba0acc175..35d319f19b0 100644 --- a/docs/learn/advanced/01-transactions.md +++ b/docs/learn/advanced/01-transactions.md @@ -16,7 +16,7 @@ sidebar_position: 1 ## Transactions -Transactions are comprised of metadata held in [contexts](./02-context.md) and [`sdk.Msg`s](../../build/building-modules/02-messages-and-queries.md) that trigger state changes within a module through the module's Protobuf [`Msg` service](../../build/building-modules/03-msg-services.md). +Transactions are comprised of metadata held in [contexts](./17-context.md) and [`sdk.Msg`s](../../build/building-modules/02-messages-and-queries.md) that trigger state changes within a module through the module's Protobuf [`Msg` service](../../build/building-modules/03-msg-services.md). When users want to interact with an application and make state changes (e.g. sending coins), they create transactions. Each of a transaction's `sdk.Msg` must be signed using the private key associated with the appropriate account(s), before the transaction is broadcasted to the network. A transaction must then be included in a block, validated, and approved by the network through the consensus process. To read more about the lifecycle of a transaction, click [here](../beginner/01-tx-lifecycle.md). diff --git a/docs/learn/advanced/17-core.md b/docs/learn/advanced/02-core.md similarity index 85% rename from docs/learn/advanced/17-core.md rename to docs/learn/advanced/02-core.md index b6a453fbb13..b1b93235e40 100644 --- a/docs/learn/advanced/17-core.md +++ b/docs/learn/advanced/02-core.md @@ -4,8 +4,7 @@ sidebar_position: 1 # Core -Core is package which specifies the interfaces for core components of the Cosmos SDK. Other -packages in the SDK implement these interfaces to provide the core functionality. This design +Core (`cosmossdk.io/core`) is package which specifies the interfaces for core components of the Cosmos SDK. Other packages in the SDK implement these interfaces to provide the core functionality. This design provides modularity and flexibility to the SDK, allowing developers to swap out implementations of core components as needed. As such it is often referred to as the Core API. @@ -16,19 +15,28 @@ services of the SDK, such as the KVStore, EventManager, and Logger. The `Enviro passed to modules and other components of the SDK to provide access to these services. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.4/core/appmodule/v2/environment.go#L16-L29 +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/v2/environment.go#L16-L29 ``` -Historically the SDK has used an [sdk.Context](02-context.md) to pass around services and data. +Historically the SDK has used an [sdk.Context](https://docs.cosmos.network/v0.50/learn/advanced/context) to pass around services and data. `Environment` is a newer construct that is intended to replace an `sdk.Context` in many cases. `sdk.Context` will be deprecated in the future on the same timeline as [Baseapp](00-baseapp.md). +## Logger + +The [Logger](https://pkg.go.dev/cosmossdk.io/log) provides a structured logging interface to the SDK. It is used throughout the SDK to log messages at various levels of severity. The Logger service is a thin wrapper around the [zerolog](https://github.com/rs/zerolog) logging library. +When used via environment, the logger is scoped to the module that is using it. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/runtime/module.go#L274 +``` + ## Branch Service The [BranchService](https://pkg.go.dev/cosmossdk.io/core/branch#Service.Execute) provides an interface to execute arbitrary code in a branched store. This is useful for executing code that needs to make changes to the store, but may need to be rolled back if an error occurs. -Below is a contrived example based on the `x/epoch` module's BeginBlocker logic. +Below is a contrived example based on the `x/epochs` module's BeginBlocker logic. ```go func (k Keeper) BeginBlocker(ctx context.Context) error { diff --git a/docs/learn/advanced/04-store.md b/docs/learn/advanced/04-store.md index 9c5b7dd9913..d1b20d20ef6 100644 --- a/docs/learn/advanced/04-store.md +++ b/docs/learn/advanced/04-store.md @@ -45,7 +45,9 @@ The `GetStoreType` is a simple method that returns the type of store, whereas a https://github.com/cosmos/cosmos-sdk/blob/store/v1.1.1/store/types/store.go#L287-L303 ``` -Branching and cache is used ubiquitously in the Cosmos SDK and required to be implemented on every store type. A storage branch creates an isolated, ephemeral branch 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. Read more about it in [context](./02-context.md#store-branching) +Branching and cache is used ubiquitously in the Cosmos SDK and required to be implemented on every store type. A storage branch creates an isolated, ephemeral branch 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. + +Branching is available as a service for modules. Read more about it in the [core](./02-core.md#branch-service) documentation. ### Commit Store @@ -147,29 +149,7 @@ The documentation on the IAVL Tree is located [here](https://github.com/cosmos/i https://github.com/cosmos/cosmos-sdk/blob/store/v1.1.1/store/dbadapter/store.go#L13-L16 ``` -`dbadapter.Store` embeds `corestore.KVStoreWithBatch`, 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-store) - -### `Transient` Store - -`Transient.Store` is a base-layer `KVStore` which is automatically discarded at the end of the block. - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/store/v1.1.1/store/transient/store.go#L16-L19 -``` - -`Transient.Store` is a `dbadapter.Store` with a `coretesting.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. - -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). - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/x/params/types/subspace.go#L23-L33 -``` - -Transient stores are typically accessed via the [`context`](./02-context.md) via the `TransientStore()` method: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/types/context.go#L344-L347 -``` +`dbadapter.Store` embeds `corestore.KVStoreWithBatch`, meaning most of the `KVStore` interface functions are implemented. The other functions (mostly miscellaneous) are manually implemented. ## KVStore Wrappers @@ -215,12 +195,7 @@ By default, all `KVStores` are wrapped in `GasKv.Stores` when retrieved. This is https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/types/context.go#L339-L342 ``` -In this case, the gas configuration set in the `context` is used. The gas configuration can be set using the `WithKVGasConfig` method of the `context`. -Otherwise it uses the following default: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/store/v1.1.1/store/types/gas.go#L231-L242 -``` +`KVStores` can be accessed in their corresponding modules by using the [`kvStoreService` and `memStoreService`](./02-core.md#kvstore-service). ### `TraceKv` Store diff --git a/docs/learn/advanced/08-events.md b/docs/learn/advanced/08-events.md index cea128dac93..64d2baa1c97 100644 --- a/docs/learn/advanced/08-events.md +++ b/docs/learn/advanced/08-events.md @@ -77,10 +77,11 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/types/events.go#L62-L86 ``` Module developers should handle Event emission via the `EventManager#EmitTypedEvent` or `EventManager#EmitEvent` in each -message `Handler` and in each `BeginBlock`/`EndBlock` handler. The `EventManager` is accessed via -the [`Context`](./02-context.md), where Event should be already registered, and emitted like this: +message `Handler` and in each `BeginBlock`/`EndBlock` handler. +The `EventManager` is accessible via the event service, present in the `Environment` struct. +This event service is a [core service](./02-core.md) available to all modules. -Note: it is preferred to use `EmitTypedEvent` over `EmitEvent` as the latter has been deprecated. +Events can be emitted like this using the `EventService`: **Typed events:** @@ -90,18 +91,28 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/x/group/keeper/msg_serv **Legacy events:** -```go -ctx.EventManager().EmitEvent( - sdk.NewEvent(eventType, sdk.NewAttribute(attributeKey, attributeValue)), -) +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/x/gov/keeper/vote.go#L91-L95 ``` -Where the `EventManager` is accessed via the [`Context`](./02-context.md). - See the [`Msg` services](../../build/building-modules/03-msg-services.md) concept doc for a more detailed view on how to typically implement Events and use the `EventManager` in modules. -## Subscribing to Events +## Default Events + +There are a few events that are automatically emitted for all messages, directly from `baseapp`. + +* `message.action`: The name of the message type. +* `message.sender`: The address of the message signer. +* `message.module`: The name of the module that emitted the message. + +:::tip +The module name is assumed by `baseapp` to be the second element of the message route: `"cosmos.bank.v1beta1.MsgSend" -> "bank"`. +In case a module does not follow the standard message path, (e.g. IBC), it is advised to keep emitting the module name event. +`Baseapp` only emits that event if the module have not already done so. +::: + +## Subscribing to CometBFT Events You can use CometBFT's [Websocket](https://docs.cometbft.com/v1.0/explanation/core/subscription) to subscribe to Events by calling the `subscribe` RPC method: @@ -143,17 +154,3 @@ Subscribing to this Event would be done like so: where `ownerAddress` is an address following the [`AccAddress`](../beginner/03-accounts.md#addresses) format. The same way can be used to subscribe to [legacy events](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/bank/types/events.go). - -## Default Events - -There are a few events that are automatically emitted for all messages, directly from `baseapp`. - -* `message.action`: The name of the message type. -* `message.sender`: The address of the message signer. -* `message.module`: The name of the module that emitted the message. - -:::tip -The module name is assumed by `baseapp` to be the second element of the message route: `"cosmos.bank.v1beta1.MsgSend" -> "bank"`. -In case a module does not follow the standard message path, (e.g. IBC), it is advised to keep emitting the module name event. -`Baseapp` only emits that event if the module have not already done so. -::: diff --git a/docs/learn/advanced/02-context.md b/docs/learn/advanced/17-context.md similarity index 95% rename from docs/learn/advanced/02-context.md rename to docs/learn/advanced/17-context.md index eb0405df3fa..77b1a628514 100644 --- a/docs/learn/advanced/02-context.md +++ b/docs/learn/advanced/17-context.md @@ -5,7 +5,7 @@ sidebar_position: 1 # Context :::note Synopsis -The `context` is a data structure intended to be passed from function to function that carries information about the current state of the application. It provides access to a branched storage (a safe branch of the entire state) as well as useful objects and information like `gasMeter`, `block height`, `consensus parameters` and more. +The `context` is a data structure that carries information about the current state of the application. It provides access to a branched storage (a safe branch of the entire state) as well as useful objects and information like `gasMeter`, `block height`, `consensus parameters` and more. ::: :::note Pre-requisite Readings @@ -15,6 +15,10 @@ The `context` is a data structure intended to be passed from function to functio ::: +:::warning +The `sdk.Context` should not be used directly. `Runtime` is implementing the [core services](./02-core.md), which are using directly the `sdk.Context`. +::: + ## Context Definition The Cosmos SDK `Context` is a custom data structure that contains Go's stdlib [`context`](https://pkg.go.dev/context) as its base, and has many additional types within its definition that are specific to the Cosmos SDK. The `Context` is integral to transaction processing in that it allows modules to easily access their respective [store](./04-store.md#base-layer-kvstores) in the [`multistore`](./04-store.md#multistore) and retrieve transactional context such as the block header and gas meter. diff --git a/docs/learn/beginner/04-gas-fees.md b/docs/learn/beginner/04-gas-fees.md index ea9af2e492b..de9a308f91c 100644 --- a/docs/learn/beginner/04-gas-fees.md +++ b/docs/learn/beginner/04-gas-fees.md @@ -26,7 +26,7 @@ In the Cosmos SDK, `gas` is a special unit that is used to track the consumption In the Cosmos SDK, `gas` is a simple alias for `uint64`, and is managed by an object called a _gas meter_. Gas meters implement the `GasMeter` interface ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/store/types/gas.go#L40-L51 +https://github.com/cosmos/cosmos-sdk/blob/b795646/store/types/gas.go#L40-L51 ``` where: @@ -40,17 +40,21 @@ where: * `IsPastLimit()` returns `true` if the amount of gas consumed by the gas meter instance is strictly above the limit, `false` otherwise. * `IsOutOfGas()` returns `true` if the amount of gas consumed by the gas meter instance is above or equal to the limit, `false` otherwise. -The gas meter is generally held in [`ctx`](../advanced/02-context.md), and consuming gas is done with the following pattern: +The gas meter is held under the `GasMeterService` in [`Environment`](../advanced/02-core.md), and consuming gas is done with the following pattern: + +:::note +The gas.Service does not give access to all the methods of the gas meter. +::: ```go -ctx.GasMeter().ConsumeGas(amount, "description") +environment.GasMeter(ctx).Consume(amount, "description") ``` By default, the Cosmos SDK makes use of two different gas meters, the [main gas meter](#main-gas-meter) and the [block gas meter](#block-gas-meter). ### Main Gas Meter -`ctx.GasMeter()` is the main gas meter of the application. The main gas meter is initialized in `FinalizeBlock` via `setFinalizeBlockState`, and then tracks gas consumption during execution sequences that lead to state-transitions, i.e. those originally triggered by [`FinalizeBlock`](../advanced/00-baseapp.md#finalizeblock). At the beginning of each transaction execution, the main gas meter **must be set to 0** in the [`AnteHandler`](#antehandler), so that it can track gas consumption per-transaction. +The main gas meter is initialized in `FinalizeBlock` via `setFinalizeBlockState`, and then tracks gas consumption during execution sequences that lead to state-transitions, i.e. those originally triggered by [`FinalizeBlock`](../advanced/00-baseapp.md#finalizeblock). At the beginning of each transaction execution, the main gas meter **must be set to 0** in the [`AnteHandler`](#antehandler), so that it can track gas consumption per-transaction. Gas consumption can be done manually, generally by the module developer in the [`BeginBlocker`, `EndBlocker`](../../build/building-modules/06-preblock-beginblock-endblock.md) or [`Msg` service](../../build/building-modules/03-msg-services.md), but most of the time it is done automatically whenever there is a read or write to the store. This automatic gas consumption logic is implemented in a special store called [`GasKv`](../advanced/04-store.md#gaskv-store). diff --git a/store/v2/README.md b/store/v2/README.md index eb8495c9adc..1d5dd811f2f 100644 --- a/store/v2/README.md +++ b/store/v2/README.md @@ -7,8 +7,7 @@ and [Store v2 Design](https://docs.google.com/document/d/1l6uXIjTPHOOWM5N4sUUmUf ## Usage The `store` package contains a `root.Store` type which is intended to act as an -abstraction layer around it's two primary constituent components - state storage (SS) -and state commitment (SC). It acts as the main entry point into storage for an +abstraction layer around it's primary constituent components - state commitment (SC). It acts as the main entry point into storage for an application to use in server/v2. Through `root.Store`, an application can query and iterate over both current and historical data, commit new state, perform state sync, and fetch commitment proofs. @@ -16,8 +15,7 @@ sync, and fetch commitment proofs. A `root.Store` is intended to be initialized with already constructed SS and SC backends (see relevant package documentation for instantiation details). Note, from the perspective of `root.Store`, there is no notion of multi or single tree/store, -rather these are implementation details of SS and SC. For SS, we utilize store keys -to namespace raw key/value pairs. For SC, we utilize an abstraction, `commitment.CommitStore`, +rather these are implementation details of SC. For SC, we utilize an abstraction, `commitment.CommitStore`, to map store keys to a commitment trees. ## Upgrades @@ -29,7 +27,6 @@ old ones. The `Rename` feature is not supported in store/v2. ```mermaid sequenceDiagram participant S as Store - participant SS as StateStorage participant SC as StateCommitment alt SC is a UpgradeableStore S->>SC: LoadVersionAndUpgrade @@ -37,14 +34,11 @@ sequenceDiagram SC->>SC: Prune removed store keys end SC->>S: LoadVersion Result - alt SS is a UpgradableDatabase - S->>SS: PruneStoreKeys - end ``` -`PruneStoreKeys` does not remove the data from the SC and SS instantly. It only +`PruneStoreKeys` does not remove the data from the SC instantly. It only marks the store keys as pruned. The actual data removal is done by the pruning -process of the underlying SS and SC. +process of the underlying SC. ## Migration @@ -54,7 +48,7 @@ the `migration` package. See [Migration Manager](./migration/README.md) for more ## Pruning The `root.Store` is NOT responsible for pruning. Rather, pruning is the responsibility -of the underlying SS and SC layers. This means pruning can be implementation specific, +of the underlying commitment layer. This means pruning can be implementation specific, such as being synchronous or asynchronous. See [Pruning Manager](./pruning/README.md) for more details. @@ -65,4 +59,4 @@ for more details. ## Test Coverage -The test coverage of the following logical components should be over 60%: \ No newline at end of file +The test coverage of the following logical components should be over 60%: diff --git a/store/v2/pruning/README.md b/store/v2/pruning/README.md index fbf24130c6b..9ab41af80cd 100644 --- a/store/v2/pruning/README.md +++ b/store/v2/pruning/README.md @@ -1,9 +1,7 @@ # Pruning Manager The `pruning` package defines the `PruningManager` struct which is responsible for -pruning the state storage (SS) and the state commitment (SC) based on the current -height of the chain. The `PruningOption` struct defines the configuration for pruning -and is passed to the `PruningManager` during initialization. +pruning the state commitment (SC) based on the current height of the chain. The `PruningOption` struct defines the configuration for pruning and is passed to the `PruningManager` during initialization. ## Prune Options @@ -29,24 +27,17 @@ sequenceDiagram participant A as RootStore participant B as PruningManager participant C as CommitmentStore - participant D as StorageStore loop Commit A->>B: SignalCommit(true, height) alt SC is PausablePruner B->>C: PausePruning(true) - else SS is PausablePruner - B->>D: PausePruing(true) end A->>C: Commit Changeset - A->>D: Write Changeset A->>B: SignalCommit(false, height) alt SC is PausablePruner B->>C: PausePruning(false) - else SS is PausablePruner - B->>D: PausePruing(false) end B->>C: Prune(height) - B->>D: Prune(height) end ```