From 5426cd8f345d337bd30b1e8bd2ea6eb44cf6abd0 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Tue, 3 Dec 2024 15:39:55 +0100 Subject: [PATCH] docs: rewrite building module section (1/n) - mm (#22724) --- UPGRADING.md | 2 + docs/build/building-apps/00-app-go.md | 14 -- docs/build/building-apps/00-runtime.md | 9 + docs/build/building-modules/00-intro.md | 7 +- .../building-modules/01-module-manager.md | 186 ++++++++---------- .../02-messages-and-queries.md | 39 ++-- .../build/building-modules/03-msg-services.md | 71 +++---- .../building-modules/04-query-services.md | 12 +- docs/build/building-modules/06-keeper.md | 2 + docs/learn/beginner/00-app-anatomy.md | 6 +- 10 files changed, 152 insertions(+), 196 deletions(-) delete mode 100644 docs/build/building-apps/00-app-go.md create mode 100644 docs/build/building-apps/00-runtime.md diff --git a/UPGRADING.md b/UPGRADING.md index 86d7b41d71b4..1f9ae2647d02 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -415,6 +415,8 @@ been added to avoid the use of the Accounts.String() method. +type MsgSimulatorFn func(r *rand.Rand, accs []Account, cdc address.Codec) (sdk.Msg, error) ``` +The interface `HasProposalMsgs` has been renamed to `HasLegacyProposalMsgs`, as we've introduced a new simulation framework, simpler and easier to use, named [simsx](https://github.com/cosmos/cosmos-sdk/blob/main/simsx/README.md). + ##### Depinject Previously `cosmossdk.io/core` held functions `Invoke`, `Provide` and `Register` were moved to `cosmossdk.io/depinject/appconfig`. diff --git a/docs/build/building-apps/00-app-go.md b/docs/build/building-apps/00-app-go.md deleted file mode 100644 index 5a0524f3bbf7..000000000000 --- a/docs/build/building-apps/00-app-go.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -sidebar_position: 1 ---- - -# Overview of `app.go` - -This section is intended to provide an overview of the `SimApp` `app.go` file and is still a work in progress. -For now please instead read the [tutorials](https://tutorials.cosmos.network) for a deep dive on how to build a chain. - -## Complete `app.go` - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/simapp/app.go -``` diff --git a/docs/build/building-apps/00-runtime.md b/docs/build/building-apps/00-runtime.md new file mode 100644 index 000000000000..a962019e2993 --- /dev/null +++ b/docs/build/building-apps/00-runtime.md @@ -0,0 +1,9 @@ +--- +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. + +A user only needs to import `runtime` in their `app.go` and instantiate a `runtime.App`. diff --git a/docs/build/building-modules/00-intro.md b/docs/build/building-modules/00-intro.md index 4eda49125a7b..6618a44caa61 100644 --- a/docs/build/building-modules/00-intro.md +++ b/docs/build/building-modules/00-intro.md @@ -17,9 +17,9 @@ Modules define most of the logic of Cosmos SDK applications. Developers compose ## Role of Modules in a Cosmos SDK Application -The Cosmos SDK can be thought of as the Ruby-on-Rails of blockchain development. It comes with a core that provides the basic functionalities every blockchain application needs, like a [boilerplate implementation of the ABCI](../../learn/advanced/00-baseapp.md) to communicate with the underlying consensus engine, a [`multistore`](../../learn/advanced/04-store.md#multistore) to persist state, a [server](../../learn/advanced/03-node.md) to form a full-node and [interfaces](./09-module-interfaces.md) to handle queries. +The Cosmos SDK can be thought of as the Next.js or Ruby-on-Rails of blockchain development. It comes with a core that provides the basic functionalities every blockchain application needs, like a [boilerplate implementation of the ABCI](../../learn/advanced/00-baseapp.md) to communicate with the underlying consensus engine, a [`multistore`](../../learn/advanced/04-store.md#multistore) to persist state, a [server](../../learn/advanced/03-node.md) to form a full-node and [interfaces](./09-module-interfaces.md) to handle queries. -On top of this core, the Cosmos SDK enables developers to build modules that implement the business logic of their application. In other words, SDK modules implement the bulk of the logic of applications, while the core does the wiring and enables modules to be composed together. The end goal is to build a robust ecosystem of open-source Cosmos SDK modules, making it increasingly easier to build complex blockchain applications. +On top of this core, the Cosmos SDK enables developers to build modules that implement the business logic of their application. In other words, SDK modules implement the bulk of the logic of applications, while the core does the wiring (via [runtime](../building-apps/00-runtime.md)) and enables modules to be composed together. The end goal is to build a robust ecosystem of open-source Cosmos SDK modules, making it increasingly easier to build complex blockchain applications. Cosmos SDK modules can be seen as little state-machines within the state-machine. They generally define a subset of the state using one or more `KVStore`s in the [main multistore](../../learn/advanced/04-store.md), as well as a subset of [message types](./02-messages-and-queries.md#messages). These messages are routed by one of the main components of Cosmos SDK core, [`BaseApp`](../../learn/advanced/00-baseapp.md), to a module Protobuf [`Msg` service](./03-msg-services.md) that defines them. @@ -42,8 +42,7 @@ flowchart TD As a result of this architecture, building a Cosmos SDK application usually revolves around writing modules to implement the specialized logic of the application and composing them with existing modules to complete the application. Developers will generally work on modules that implement logic needed for their specific use case that do not exist yet, and will use existing modules for more generic functionalities like staking, accounts, or token management. - -### Modules as Sudo +### Modules as super-users Modules have the ability to perform actions that are not available to regular users. This is because modules are given sudo permissions by the state machine. Modules can reject another modules desire to execute a function but this logic must be explicit. Examples of this can be seen when modules create functions to modify parameters: diff --git a/docs/build/building-modules/01-module-manager.md b/docs/build/building-modules/01-module-manager.md index 9742454320ec..1e3bf38aa95e 100644 --- a/docs/build/building-modules/01-module-manager.md +++ b/docs/build/building-modules/01-module-manager.md @@ -5,7 +5,7 @@ sidebar_position: 1 # Module Manager :::note Synopsis -Cosmos SDK modules need to implement the [`AppModule` interfaces](#application-module-interfaces), in order to be managed by the application's [module manager](#module-manager). The module manager plays an important role in [`message` and `query` routing](../../learn/advanced/00-baseapp.md#routing), and allows application developers to set the order of execution of a variety of functions like [`PreBlocker`](https://docs.cosmos.network/main/learn/beginner/app-anatomy) and [`BeginBlocker` and `EndBlocker`](https://docs.cosmos.network/main/learn/beginner/app-anatomy). +Cosmos SDK modules need to implement the [`AppModule` interfaces](#application-module-interfaces), in order to be managed by the application's [module manager](#module-manager). The module manager plays an important role in [`message` and `query` routing](../../learn/advanced/00-baseapp.md#routing), and allows application developers to set the order of execution of a variety of functions like [`PreBlocker`, `BeginBlocker` and `EndBlocker`](https://docs.cosmos.network/main/learn/beginner/app-anatomy). ::: :::note Pre-requisite Readings @@ -18,203 +18,189 @@ Cosmos SDK modules need to implement the [`AppModule` interfaces](#application-m Application module interfaces exist to facilitate the composition of modules together to form a functional Cosmos SDK application. -:::note +Those interface are defined in the `cosmossdk.io/core/appmodule` and `cosmossdk.io/core/appmodule/v2` packages. -It is recommended to implement interfaces from the [Core API](https://docs.cosmos.network/main/architecture/adr-063-core-module-api) `appmodule` package. This makes modules less dependent on the SDK. -For legacy reason modules can still implement interfaces from the SDK `module` package. +:::note +The difference between appmodule and appmodule v2 is mainly the introduction of handlers from Cosmos SDK (server) v2. The rest of the API remains the same, and are simply aliases between the two packages. ::: -There are 2 main application module interfaces: - -* [`appmodule.AppModule` / `module.AppModule`](#appmodule) for inter-dependent module functionalities (except genesis-related functionalities). - -The above interfaces are mostly embedding smaller interfaces (extension interfaces), that defines specific functionalities: - - +Following a list of all interfaces a module can implement: -* (legacy) [`module.HasGenesisBasics`](#modulehasgenesisbasics): The legacy interface for stateless genesis methods. -* (legacy) [`module.HasGenesis`](#modulehasgenesis) for inter-dependent genesis-related module functionalities. -* (legacy) [`module.HasABCIGenesis`](#modulehasabcigenesis) for inter-dependent genesis-related module functionalities. +* [`appmodule.AppModule`](#appmodule) is the main interface that defines a module. By default, a module does nothing. To add functionalities, a module can implement extension interfaces. * [`appmodule.HasPreBlocker`](#haspreblocker): The extension interface that contains information about the `AppModule` and `PreBlock`. * [`appmodule.HasBeginBlocker`](#hasbeginblocker): The extension interface that contains information about the `AppModule` and `BeginBlock`. * [`appmodule.HasEndBlocker`](#hasendblocker): The extension interface that contains information about the `AppModule` and `EndBlock`. -* [`appmodule.HasService` / `module.HasServices`](#hasservices): The extension interface for modules to register services. -* [`module.HasABCIEndBlock`](#hasabciendblock): The extension interface that contains information about the `AppModule`, `EndBlock` and returns an updated validator set. -* (legacy) [`module.HasConsensusVersion`](#hasconsensusversion): The extension interface for declaring a module consensus version. +* [`module.HasABCIEndBlock`](#hasendblocker): The extension interface that contains information about the `AppModule`, `EndBlock` and returns an updated validator set (Usually only needed by staking). +* [`appmodule.HasRegisterInterfaces`](#hasregisterinterfaces): The extension interface for modules to register their message types. +* [`appmodule.HasService`](#hasservices): The extension interface for modules to register services. Note, this interface is not exposed in core to avoid a gRPC dependency. However it is usable in an application. +* [`appmodule.HasAminoCodec`](#hasaminocodec): The extension interface for modules to support JSON encoding and decoding via `amino`. +* [`appmodule.HasMigrations`](#hasmigrations): The extension interface for registering module migrations. + * [`appmodule.HasConsensusVersion`](#hasconsensusversion): The extension interface for declaring a module consensus version. It is usually not used alone, but in conjunction with `HasMigrations`. +* [`appmodule.HasGenesis`](#hasgenesis) for inter-dependent genesis-related module functionalities. +* [`appmodule.HasABCIGenesis`](#hasabcigenesis) for inter-dependent genesis-related module functionalities, with validator set updates (Usually only needed by staking). The `AppModule` interface exists to define inter-dependent module methods. Many modules need to interact with other modules, typically through [`keeper`s](./06-keeper.md), which means there is a need for an interface where modules list their `keeper`s and other methods that require a reference to another module's object. `AppModule` interface extension, such as `HasBeginBlocker` and `HasEndBlocker`, also enables the module manager to set the order of execution between module's methods like `BeginBlock` and `EndBlock`, which is important in cases where the order of execution between modules matters in the context of the application. The usage of extension interfaces allows modules to define only the functionalities they need. For example, a module that does not need an `EndBlock` does not need to define the `HasEndBlocker` interface and thus the `EndBlock` method. `AppModule` and `AppModuleGenesis` are voluntarily small interfaces, that can take advantage of the `Module` patterns without having to define many placeholder functions. -### `HasAminoCodec` +:::note legacy +Prior to the introduction of the `cosmossdk.io/core` package the interfaces were defined in the `types/module` package of the Cosmos SDK. Not all interfaces have been migrated to core. Those legacy interfaces are still supported for backward compatability, but aren't described in this document and should not be used in new modules. +::: -```go reference -https://github.com/cosmos/cosmos-sdk/blob/eee5e21e1c8d0995b6d4f83b7f55ec0b58d27ba7/core/appmodule/module.go#L74-L78 -``` -* `RegisterLegacyAminoCodec(registry.AminoRegistrar)`: Registers the `amino` codec for the module, which is used to marshal and unmarshal structs to/from `[]byte` in order to persist them in the module's `KVStore`. +### `AppModule` -### `HasRegisterInterfaces` +The `AppModule` interface defines a module. Modules can declare their functionalities by implementing extensions interfaces. +`AppModule`s are managed by the [module manager](#manager), which checks which extension interfaces are implemented by the module. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/eee5e21e1c8d0995b6d4f83b7f55ec0b58d27ba7/core/appmodule/v2/module.go#L103-L106 +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/v2/module.go#L10-L20 ``` -* `RegisterInterfaces(codectypes.InterfaceRegistry)`: Registers a module's interface types and their concrete implementations as `proto.Message`. +### `HasPreBlocker` -### `HasGRPCGateway` +The `HasPreBlocker` is an extension interface from `appmodule.AppModule`. All modules that have an `PreBlock` method implement this interface. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/eee5e21e1c8d0995b6d4f83b7f55ec0b58d27ba7/types/module/module.go#L84-L87 +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/v2/module.go#L22-L28 ``` -* `RegisterGRPCGatewayRoutes(client.Context, *runtime.ServeMux)`: Registers gRPC routes for the module. - -### Genesis - -:::tip -For easily creating an `AppModule` that only has genesis functionalities, implement `module.HasGenesis/HasABCIGenesis`. -::: +### `HasBeginBlocker` -#### `module.HasGenesisBasics` +The `HasBeginBlocker` is an extension interface from `appmodule.AppModule`. All modules that have an `BeginBlock` method implement this interface. +It gives module developers the option to implement logic that is automatically triggered at the beginning of each block. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/types/module/module.go#L76-L79 +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/v2/module.go#L30-L38 ``` -Let us go through the methods: - -* `DefaultGenesis(codec.JSONCodec)`: Returns a default [`GenesisState`](./08-genesis.md#genesisstate) for the module, marshalled to `json.RawMessage`. The default `GenesisState` need to be defined by the module developer and is primarily used for testing. -* `ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`: Used to validate the `GenesisState` defined by a module, given in its `json.RawMessage` form. It will usually unmarshall the `json` before running a custom [`ValidateGenesis`](./08-genesis.md#validategenesis) function defined by the module developer. - -#### `module.HasGenesis` +### `HasEndBlocker` -`HasGenesis` is an extension interface for allowing modules to implement genesis functionalities. +The `HasEndBlocker` is an extension interface from `appmodule.AppModule`. All modules that have an `EndBlock` method implement this interface. It gives module developers the option to implement logic that is automatically triggered at the end of each block. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/28fa3b8/types/module/module.go#L184-L189 +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/v2/module.go#L40-L48 ``` -#### `module.HasABCIGenesis` - -`HasABCIGenesis` is an extension interface for allowing modules to implement genesis functionalities and returns validator set updates. +If a module needs to return validator set updates (staking), they can use `HasABCIEndBlock` (in v1). ```go reference -https://github.com/cosmos/cosmos-sdk/blob/28fa3b8/types/module/module.go#L94-L98 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/types/module/module.go#L115-L119 ``` -### `AppModule` - -The `AppModule` interface defines a module. Modules can declare their functionalities by implementing extensions interfaces. -`AppModule`s are managed by the [module manager](#manager), which checks which extension interfaces are implemented by the module. +Or, alternatively, `HasUpdateValidators` in v2: -#### `appmodule.AppModule` ```go reference -https://github.com/cosmos/cosmos-sdk/blob/28fa3b8/core/appmodule/module.go#L11-L20 +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/v2/module.go#L87-L94 ``` -#### `module.AppModule` +### `HasRegisterInterfaces` -:::note -Previously the `module.AppModule` interface was containing all the methods that are defined in the extensions interfaces. This was leading to much boilerplate for modules that did not need all the functionalities. -::: +The `HasRegisterInterfaces` is an extension interface from `appmodule.AppModule`. All modules that have a `RegisterInterfaces` method implement this interface. It allows modules to register their message types with their concrete implementations as `proto.Message`. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/28fa3b8/core/appmodule/v2/module.go#L14-L20 +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/v2/module.go#L103-L106 ``` ### `HasServices` -This interface defines one method. It allows to checks if a module can register invariants. - -#### `appmodule.HasService` +This interface defines one method. It allows to register and let module expose gRPC services. +This interface is not part of the `core` package to avoid a gRPC dependency, but is recognized by the module manager and [runtime](../building-apps/00-runtime.md). ```go reference -https://github.com/cosmos/cosmos-sdk/blob/28fa3b8/core/appmodule/module.go#L22-L40 +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/module.go#L34-L53 ``` -#### `module.HasServices` +### `HasAminoCodec` + +The `HasAminoCodec` allows to register the `amino` codec for the module, which is used to marshal and unmarshal structs to/from `[]byte` in order to persist them in the module's `KVStore`. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/types/module/module.go#L208-L211 +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/module.go#L68-L72 ``` -* `RegisterServices(Configurator)`: Allows a module to register services. - -### `HasConsensusVersion` +### `module.HasGRPCGateway` -This interface defines one method for checking a module consensus version. +This interface is not part of the `core` package to avoid a gRPC dependency. It is used to register gRPC routes gateway routes for the module. [In v2, this will be done differently, and totally abstracted from modules and module manager](https://github.com/cosmos/cosmos-sdk/issues/22715) ```go reference -https://github.com/cosmos/cosmos-sdk/blob/28fa3b8/core/appmodule/v2/migrations.go#L6-L12 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/types/module/module.go#L74-L77 ``` -* `ConsensusVersion() uint64`: Returns the consensus version of the module. +### `HasMigrations` -### `HasPreBlocker` +The `HasMigrations` interface is used to register module migrations. Learn more about [module migrations](./13-upgrade.md). -The `HasPreBlocker` is an extension interface from `appmodule.AppModule`. All modules that have an `PreBlock` method implement this interface. +```go reference +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/v2/migrations.go#L14-L21 +``` -### `HasBeginBlocker` +### `HasConsensusVersion` -The `HasBeginBlocker` is an extension interface from `appmodule.AppModule`. All modules that have an `BeginBlock` method implement this interface. +This interface defines one method for checking a module consensus version. It is mainly used in conjunction with `HasMigrations`. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/28fa3b8dfcb3208d3b1cfbae08eda519e4cc1560/core/appmodule/v2/module.go#L30-L38 +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/v2/migrations.go#L5-L12 ``` -* `BeginBlock(context.Context) error`: This method gives module developers the option to implement logic that is automatically triggered at the beginning of each block. +### Genesis -### `HasEndBlocker` +#### `HasGenesis` -The `HasEndBlocker` is an extension interface from `appmodule.AppModule`. All modules that have an `EndBlock` method implement this interface. If a module needs to return validator set updates (staking), they can use `HasABCIEndBlock` +`HasGenesis` is an extension interface for allowing modules to implement genesis functionalities. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/28fa3b8dfcb3208d3b1cfbae08eda519e4cc1560/core/appmodule/v2/module.go#L40-L48 +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/v2/genesis.go#L8-L19 ``` -* `EndBlock(context.Context) error`: This method gives module developers the option to implement logic that is automatically triggered at the end of each block. +Let us go through some of the methods: -### `HasABCIEndBlock` +* `DefaultGenesis()`: Returns a default [`GenesisState`](./08-genesis.md#genesisstate) for the module, marshalled to `json.RawMessage`. The default `GenesisState` need to be defined by the module developer and is primarily used for testing. +* `ValidateGenesis(data json.RawMessage) error`: Used to validate the `GenesisState` defined by a module, given in its `json.RawMessage` form. It will usually unmarshall the `json` before running a custom [`ValidateGenesis`](./08-genesis.md#validategenesis) function defined by the module developer. -The `HasUpdateValidators` is an extension interface from `module.AppModule`. All modules that have an `EndBlock` which return validator set updates implement this interface. +In the same vein than `HasABCIEndBlock`, `HasABCIGenesis` is used to return validator set updates. -```go reference -https://github.com/cosmos/cosmos-sdk/blob/28fa3b8dfcb3208d3b1cfbae08eda519e4cc1560/core/appmodule/v2/module.go#L87-L94 -``` +#### `HasABCIGenesis` -* `UpdateValidators(context.Context) ([]abci.ValidatorUpdate, error)`: This method gives module developers the option to inform the underlying consensus engine of validator set changes (e.g. the `staking` module). +`HasABCIGenesis` is an extension interface for allowing modules to implement genesis functionalities and returns validator set updates. +```go reference +https://github.com/cosmos/cosmos-sdk/blob/core/v1.0.0-alpha.6/core/appmodule/v2/genesis.go#L21-L31 +``` ### Implementing the Application Module Interfaces - Typically, the various application module interfaces are implemented in a file called `module.go`, located in the module's folder (e.g. `./x/module/module.go`). -Almost every module needs to implement the `AppModule` interfaces. If the module is only used for genesis, it will implement `AppModuleGenesis` instead of `AppModule`. The concrete type that implements the interface can add parameters that are required for the implementation of the various methods of the interface. +Every module must implement the `AppModule` interface. If the module is only used for genesis, it will implement `HasGenesis` in addition of `AppModule`. The concrete type that implements the interface can add parameters that are required for the implementation of the various methods of the interface. ```go // example type AppModule struct { keeper Keeper } -``` -In the example above, you can see that the `AppModule` concrete type references an `AppModuleBasic`, and not an `AppModuleGenesis`. That is because `AppModuleGenesis` only needs to be implemented in modules that focus on genesis-related functionalities. In most modules, the concrete `AppModule` type will have a reference to an `AppModuleBasic` and implement the two added methods of `AppModuleGenesis` directly in the `AppModule` type. +func (AppModule) IsAppModule() {} +func (AppModule) IsOnePerModuleType() {} +``` ## Module Manager -The module manager is used to manage collections of `appmodule.AppModule` and `AppModule` and all the extensions interfaces. +The module manager is used to manage collections of `AppModule` and all the extensions interfaces. ### `Manager` The `Manager` is a structure that holds all the `AppModule` of an application, and defines the order of execution between several key components of these modules: ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/types/module/module.go#L267-L276 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/types/module/module.go#L121-L133 ``` +:::tip +Thanks to `runtime`, a user does not need to interact directly with the `Manager`. The `Manager` is used internally by the `runtime` to manage the modules of the application. +::: + The module manager is used throughout the application whenever an action on a collection of modules is required. It implements the following methods: * `NewManager(modules ...AppModule)`: Constructor function. It takes a list of the application's `AppModule`s and builds a new `Manager`. It is generally called from the application's main [constructor function](../../learn/beginner/00-app-anatomy.md#constructor-function). @@ -242,18 +228,8 @@ The module manager is used throughout the application whenever an action on a co * `DefaultGenesis(cdc codec.JSONCodec)`: Provides default genesis information for modules in the application by calling the [`DefaultGenesis(cdc codec.JSONCodec)`](./08-genesis.md#defaultgenesis) function of each module. It only calls the modules that implements the `HasGenesisBasics` interfaces. * `ValidateGenesis(cdc codec.JSONCodec, txEncCfg client.TxEncodingConfig, genesis map[string]json.RawMessage)`: Validates the genesis information modules by calling the [`ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`](./08-genesis.md#validategenesis) function of modules implementing the `HasGenesisBasics` interface. -Here's an example of a concrete integration within an `simapp`: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/simapp/app.go#L411-L434 -``` - -This is the same example from `runtime` (the package that powers app di): - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/runtime/module.go#L61 -``` +Here's an example of a concrete integration within [`runtime`](../building-apps/00-runtime.md) ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/runtime/module.go#L82 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/runtime/module.go#L242-L244 ``` diff --git a/docs/build/building-modules/02-messages-and-queries.md b/docs/build/building-modules/02-messages-and-queries.md index 5ec1c7a707e9..fc7c6e29a126 100644 --- a/docs/build/building-modules/02-messages-and-queries.md +++ b/docs/build/building-modules/02-messages-and-queries.md @@ -24,11 +24,10 @@ When a transaction is relayed from the underlying consensus engine to the Cosmos Defining Protobuf `Msg` services is the recommended way to handle messages. A Protobuf `Msg` service should be created for each module, typically in `tx.proto` (see more info about [conventions and naming](../../learn/advanced/05-encoding.md#faq)). It must have an RPC service method defined for each message in the module. - -Each `Msg` service method must have exactly one argument, which must implement the `transaction.Msg` interface, and a Protobuf response. The naming convention is to call the RPC argument `Msg` and the RPC response `MsgResponse`. For example: +Each `Msg` service method must have exactly one argument, which must implement the [`transaction.Msg`](https://pkg.go.dev/cosmossdk.io/core@v1.0.0-alpha.6/transaction#Msg) interface, and a Protobuf response. The naming convention is to call the RPC argument `Msg` and the RPC response `MsgResponse`. For example: ```protobuf - rpc Send(MsgSend) returns (MsgSendResponse); +rpc Send(MsgSend) returns (MsgSendResponse); ``` See an example of a `Msg` service definition from `x/bank` module: @@ -45,37 +44,29 @@ https://github.com/cosmos/cosmos-sdk/blob/28fa3b8/x/bank/proto/cosmos/bank/v1bet https://github.com/cosmos/cosmos-sdk/blob/main/core/transaction/transaction.go#L8 ``` -To attach a `ValidateBasic()` method to a message, then you must add methods to the type adhereing to the `HasValidateBasic`. - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/9c1e8b247cd47b5d3decda6e86fbc3bc996ee5d7/types/tx_msg.go#L84-L88 -``` - -In 0.50+ signers from the `GetSigners()` call is automated via a protobuf annotation. - +Signers from the `GetSigners()` call is automated via a protobuf annotation. Read more about the signer field [here](./05-protobuf-annotations.md). ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/e6848d99b55a65d014375b295bdd7f9641aac95e/proto/cosmos/bank/v1beta1/tx.proto#L40 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/x/bank/proto/cosmos/bank/v1beta1/tx.proto#L45 ``` If there is a need for custom signers then there is an alternative path which can be taken. A function which returns `signing.CustomGetSigner` for a specific message can be defined. ```go func ProvideBankSendTransactionGetSigners() signing.CustomGetSigner { - - // Extract the signer from the signature. - signer, err := coretypes.LatestSigner(Tx).Sender(ethTx) - if err != nil { - return nil, err - } - - // Return the signer in the required format. - return [][]byte{signer.Bytes()}, nil + // Extract the signer from the signature. + signer, err := coretypes.LatestSigner(Tx).Sender(ethTx) + if err != nil { + return nil, err + } + + // Return the signer in the required format. + return [][]byte{signer.Bytes()}, nil } ``` -When using dependency injection (depinject) this can be provided to the application via the provide method. +This can be provided to the application using depinject's `Provide` method in the application's `app.go`: ```go depinject.Provide(banktypes.ProvideBankSendTransactionGetSigners) @@ -88,7 +79,7 @@ The Cosmos SDK uses Protobuf definitions to generate client and server code: A `RegisterMsgServer` method is also generated and should be used to register the module's `MsgServer` implementation in `RegisterServices` method from the [`AppModule` interface](./01-module-manager.md#appmodule). -In order for clients (CLI and grpc-gateway) to have these URLs registered, the Cosmos SDK provides the function `RegisterMsgServiceDesc(registry codectypes.InterfaceRegistry, sd *grpc.ServiceDesc)` that should be called inside module's [`RegisterInterfaces`](01-module-manager.md#hasregisterinterfaces) method, using the proto-generated `&_Msg_serviceDesc` as `*grpc.ServiceDesc` argument. +In order for clients (CLI and gRPC-gateway) to have these URLs registered, the Cosmos SDK provides the function `RegisterMsgServiceDesc(registry codectypes.InterfaceRegistry, sd *grpc.ServiceDesc)` that should be called inside module's [`RegisterInterfaces`](01-module-manager.md#hasregisterinterfaces) method, using the proto-generated `&_Msg_serviceDesc` as `*grpc.ServiceDesc` argument. ## Queries @@ -102,7 +93,7 @@ Queries should be defined using [Protobuf services](https://protobuf.dev/program Here's an example of such a `Query` service definition: ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/proto/cosmos/auth/v1beta1/query.proto#L14-L89 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/proto/cosmos/auth/v1beta1/query.proto#L15-L81 ``` As `proto.Message`s, generated `Response` types implement by default `String()` method of [`fmt.Stringer`](https://pkg.go.dev/fmt#Stringer). diff --git a/docs/build/building-modules/03-msg-services.md b/docs/build/building-modules/03-msg-services.md index 14f906119015..1a06925b70e4 100644 --- a/docs/build/building-modules/03-msg-services.md +++ b/docs/build/building-modules/03-msg-services.md @@ -17,7 +17,7 @@ A Protobuf `Msg` service processes [messages](./02-messages-and-queries.md#messa ## Implementation of a module `Msg` service -Each module should define a Protobuf `Msg` service, which will be responsible for processing requests (implementing `sdk.Msg`) and returning responses. +Each module should define a Protobuf `Msg` service, which will be responsible for processing requests (implementing `transaction.Msg`) and returning responses. As further described in [ADR 031](../architecture/adr-031-msg-service.md), this approach has the advantage of clearly specifying return types and generating server and client code. @@ -30,24 +30,12 @@ https://github.com/cosmos/cosmos-sdk/blob/28fa3b8/x/bank/types/tx.pb.go#L564-L57 When possible, the existing module's [`Keeper`](./06-keeper.md) should implement `MsgServer`, otherwise a `msgServer` struct that embeds the `Keeper` can be created, typically in `./keeper/msg_server.go`: ```go reference -https://github.com/cosmos/cosmos-sdk/blob/28fa3b8/x/bank/keeper/msg_server.go#L16-L19 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/x/bank/keeper/msg_server.go#L13-L15 ``` -`msgServer` methods can retrieve the auxiliary information or services using the environment variable, it is always located in the keeper: +`msgServer` methods can retrieve the auxiliary information or services using the environment variable, it is should always be located in the [keeper](./06-keeper.md). -Environment: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/07151304e2ec6a185243d083f59a2d543253cb15/core/appmodule/v2/environment.go#L14-L29 -``` - -Keeper Example: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/07151304e2ec6a185243d083f59a2d543253cb15/x/bank/keeper/keeper.go#L56-L58 -``` - -`transaction.Msg` processing usually follows these 3 steps: +A `transaction.Msg` processing usually follows these 3 steps: ### Validation @@ -79,31 +67,48 @@ After the validation is successful, the `msgServer` method uses the [`keeper`](. ### Events -Before returning, `msgServer` methods generally emit one or more [events](../../learn/advanced/08-events.md) by using the `EventManager` held in `environment`. +Before returning, `msgServer` methods generally emit one or more [events](../../learn/advanced/08-events.md) by using the `EventService` held in `environment`. There are two ways to emit events, typed events using protobuf or arbitrary key & values. -Typed Events: +For typed events: ```go -ctx.EventManager().EmitTypedEvent( - &group.EventABC{Key1: Value1, Key2, Value2}) +environment.EventService.EventManager(ctx).Emit(&group.EventABC{Key1: Value1, Key2, Value2}) ``` -Arbitrary Events: +Or using simple KV events: ```go -ctx.EventManager().EmitEvent( - sdk.NewEvent( +environment.EventService.EventManager(ctx).EmitKV( eventType, // e.g. sdk.EventTypeMessage for a message, types.CustomEventType for a custom event defined in the module - sdk.NewAttribute(key1, value1), - sdk.NewAttribute(key2, value2), - ), + event.Attribute{Key: key1, Value: value1}, + event.Attribute{Key: key2, Value: value2}, ) ``` These events are relayed back to the underlying consensus engine and can be used by service providers to implement services around the application. Click [here](../../learn/advanced/08-events.md) to learn more about events. +### Telemetry + +:::Warning +Telemetry adds a performance overhead to the chain. It is recommended to only use this in critical paths +::: + +New [telemetry metrics](../../learn/advanced/09-telemetry.md) can be created from `msgServer` methods when handling messages. + +This is an example from the `x/auth/vesting` module: + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/auth/vesting/msg_server.go#L76-L88 +``` + +## How it works + +:::warning +This flow concerns only a Cosmos SDK *baseapp*, and not Cosmos SDK v2. +::: + The invoked `msgServer` method returns a `proto.Message` response and an `error`. These return values are then wrapped into an `*sdk.Result` or an `error`: ```go reference @@ -149,17 +154,3 @@ sequenceDiagram baseApp->>User: result, error code ``` - -## Telemetry - -New [telemetry metrics](../../learn/advanced/09-telemetry.md) can be created from `msgServer` methods when handling messages. - -This is an example from the `x/auth/vesting` module: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/auth/vesting/msg_server.go#L76-L88 -``` - -:::Warning -Telemetry adds a performance overhead to the chain. It is recommended to only use this in critical paths -::: diff --git a/docs/build/building-modules/04-query-services.md b/docs/build/building-modules/04-query-services.md index a787a0c22b6f..9486482ea6cd 100644 --- a/docs/build/building-modules/04-query-services.md +++ b/docs/build/building-modules/04-query-services.md @@ -5,7 +5,7 @@ sidebar_position: 1 # Query Services :::note Synopsis -A Protobuf Query service processes [`queries`](./02-messages-and-queries.md#queries). Query services are specific to the module in which they are defined, and only process `queries` defined within said module. They are called from `BaseApp`'s [`Query` method](../../learn/advanced/00-baseapp.md#query). +A Protobuf Query service processes [`queries`](./02-messages-and-queries.md#queries). Query services are specific to the module in which they are defined, and only process `queries` defined within said module. ::: :::note Pre-requisite Readings @@ -28,18 +28,17 @@ type QueryServer interface { } ``` -These custom queries methods should be implemented by a module's keeper, typically in `./keeper/grpc_query.go`. The first parameter of these methods is a generic `context.Context`. Therefore, the Cosmos SDK provides a function `sdk.UnwrapSDKContext` to retrieve the `context.Context` from the provided -`context.Context`. +These custom queries methods should be implemented by a module's keeper, typically in `./keeper/grpc_query.go`. Here's an example implementation for the bank module: ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/bank/keeper/grpc_query.go +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/x/bank/keeper/grpc_query.go#L20-L48 ``` ### Calling queries from the State Machine -The Cosmos SDK v0.47 introduces a new `cosmos.query.v1.module_query_safe` Protobuf annotation which is used to state that a query that is safe to be called from within the state machine, for example: +The `cosmos.query.v1.module_query_safe` protobuf annotation is used to state that a query that is safe to be called from within the state machine, for example: * a Keeper's query function can be called from another module's Keeper, * ADR-033 intermodule query calls, @@ -53,5 +52,4 @@ If the `module_query_safe` annotation set to `true`, it means: If you are a module developer and want to use `module_query_safe` annotation for your own query, you have to ensure the following things: * the query is deterministic and won't introduce state-machine-breaking changes without coordinated upgrades -* it has its gas tracked, to avoid the attack vector where no gas is accounted for - on potentially high-computation queries. +* it has its gas tracked, to avoid the attack vector where no gas is accounted for on potentially high-computation queries. diff --git a/docs/build/building-modules/06-keeper.md b/docs/build/building-modules/06-keeper.md index 0bd776ff9b9d..59180170cfd7 100644 --- a/docs/build/building-modules/06-keeper.md +++ b/docs/build/building-modules/06-keeper.md @@ -53,6 +53,8 @@ Let us go through the different parameters: 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 + ## 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. diff --git a/docs/learn/beginner/00-app-anatomy.md b/docs/learn/beginner/00-app-anatomy.md index edd8611c3e46..88e54fbf7975 100644 --- a/docs/learn/beginner/00-app-anatomy.md +++ b/docs/learn/beginner/00-app-anatomy.md @@ -57,7 +57,9 @@ In general, the core of the state-machine is defined in a file called `app.go`. ### Type Definition of the Application -The first thing defined in `app.go` is the `type` of the application. It is generally comprised of the following parts: + + + ### Constructor Function