Skip to content

Commit

Permalink
more updates. the rest will be in another PR
Browse files Browse the repository at this point in the history
  • Loading branch information
julienrbrt committed Dec 3, 2024
1 parent 1767a9e commit 13d82f6
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 71 deletions.
39 changes: 15 additions & 24 deletions docs/build/building-modules/02-messages-and-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<service-rpc-name>` and the RPC response `Msg<service-rpc-name>Response`. For example:
Each `Msg` service method must have exactly one argument, which must implement the [`transaction.Msg`](https://pkg.go.dev/cosmossdk.io/[email protected]/transaction#Msg) interface, and a Protobuf response. The naming convention is to call the RPC argument `Msg<service-rpc-name>` and the RPC response `Msg<service-rpc-name>Response`. 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:
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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).
Expand Down
71 changes: 31 additions & 40 deletions docs/build/building-modules/03-msg-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
:::
12 changes: 5 additions & 7 deletions docs/build/building-modules/04-query-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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.
2 changes: 2 additions & 0 deletions docs/build/building-modules/06-keeper.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 13d82f6

Please sign in to comment.