Pre-requisite Readings
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.
As further described in ADR 031, this approach has the advantage of clearly specifying return types and generating server and client code.
Protobuf generates a MsgServer
interface based on a definition of Msg
service. It is the role of the module developer to implement this interface, by implementing the state transition logic that should happen upon receival of each sdk.Msg
. As an example, here is the generated MsgServer
interface for x/bank
, which exposes two sdk.Msg
s:
x/bank/types/tx.pb.go
Keeper
should implement MsgServer
, otherwise a msgServer
struct that embeds the Keeper
can be created, typically in ./keeper/msg_server.go
:
x/bank/keeper/msg_server.go
msgServer
methods can retrieve the sdk.Context
from the context.Context
parameter method using the sdk.UnwrapSDKContext
:
x/bank/keeper/msg_server.go
sdk.Msg
processing usually follows these 3 steps:
Validation
The message server must perform all validation required (both stateful and stateless) to make sure themessage
is valid. The signer
is charged for the gas cost of this validation.
For example, a msgServer
method for a transfer
message should check that the sending account has enough funds to actually perform the transfer.
It is recommended to implement all validation checks in a separate function that passes state values as arguments. This implementation simplifies testing. As expected, expensive validation functions charge additional gas. Example:
Previously, the
ValidateBasic
method was used to perform simple and stateless validation checks. This way of validating is deprecated, this means the msgServer
must perform all validation checks.State Transition
After the validation is successful, themsgServer
method uses the keeper
functions to access the state and perform a state transition.
Events
Before returning,msgServer
methods generally emit one or more events by using the EventManager
held in the ctx
. Use the new EmitTypedEvent
function that uses protobuf-based event types:
EmitEvent
function:
msgServer
method returns a proto.Message
response and an error
. These return values are then wrapped into an *sdk.Result
or an error
using sdk.WrapServiceResult(ctx sdk.Context, res proto.Message, err error)
:
baseapp/msg_service_router.go
res
parameter to protobuf and attaching any events on the ctx.EventManager()
to the sdk.Result
.
proto/cosmos/base/abci/v1beta1/abci.proto
Msg
service, and how the message propagates through the module.
Telemetry
New telemetry metrics can be created frommsgServer
methods when handling messages.
This is an example from the x/auth/vesting
module:
x/auth/vesting/msg_server.go