Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
julienrbrt committed Dec 6, 2024
1 parent d230ee2 commit 1a7d0df
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 19 deletions.
18 changes: 18 additions & 0 deletions docs/build/building-apps/00-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 reponsible 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
```
7 changes: 7 additions & 0 deletions docs/build/building-modules/00-intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
8 changes: 3 additions & 5 deletions docs/build/building-modules/01-module-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`. 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`. The function returns an `abci` which contains the aforementioned events, as well as validator set updates (if any).
* (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.
Expand Down
22 changes: 18 additions & 4 deletions docs/build/building-modules/06-keeper.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -46,15 +46,30 @@ 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.

Of course, it is possible to define different types of internal `keeper`s for the same module (e.g. a read-only `keeper`). Each type of `keeper` comes with its own constructor function, which is called from the [application's constructor function](../../learn/beginner/00-app-anatomy.md). This is where `keeper`s are instantiated, and where developers make sure to pass correct instances of modules' `keeper`s to other modules that require them.

## 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.
Expand All @@ -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.
18 changes: 13 additions & 5 deletions docs/learn/advanced/17-core.md → docs/learn/advanced/02-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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 {
Expand Down
4 changes: 3 additions & 1 deletion docs/learn/advanced/04-store.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading

0 comments on commit 1a7d0df

Please sign in to comment.