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.