Msg service processes messages. Protobuf
Msg services are specific to the module in which they are defined, and only process messages defined within the said module. They are called from
# Pre-requisite Readings
# Implementation of a module
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
When possible, the existing module's
Keeper should implement
MsgServer, otherwise a
msgServer struct that embeds the
Keeper can be created, typically in
msgServer methods can retrieve the
sdk.Context from the
context.Context parameter method using the
sdk.Msg processing usually follows these 3 steps:
msgServer method is executed, the message's
ValidateBasic() method has already been called. Since
msg.ValidateBasic() performs only the most basic checks, this stage must perform all other validation (both stateful and stateless) to make sure the
message is valid. Checks performed in the
msgServer method can be more expensive and the signer is charged gas for these operations.
For example, a
msgServer method for a
transfer message might 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:
# State Transition
After the validation is successful, the
msgServer method uses the
keeper functions to access the state and perform a state transition.
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:
or the older
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 to learn more about events.
msgServer method returns a
proto.Message response and an
error. These return values are then wrapped into an
*sdk.Result or an
sdk.WrapServiceResult(ctx sdk.Context, res proto.Message, err error):
This method takes care of marshaling the
res parameter to protobuf and attaching any events on the
ctx.EventManager() to the
This diagram shows a typical structure of a Protobuf
Msg service, and how the message propagates through the module.
handler type defined in the Cosmos SDK will be deprecated in favor of
Here is the typical structure of a
Let us break it down:
LegacyMsgis the actual object being processed.
Contextcontains all the necessary information needed to process the
msg, as well as a branch of the latest state. If the
msgis successfully processed, the branched version of the state contained in the
ctxwill be written to the main state (branch).
BaseAppcontains (among other things) information on the execution of the
handlers are typically implemented in a
./handler.go file inside the module's folder. The module manager is used to add the module's
handlers to the
router via the
Route() method. Typically,
Route() method simply constructs a Route that calls a
NewHandler() method defined in
NewHandler function dispatches a
LegacyMsg to appropriate handler function, usually by using a switch statement:
NewHandler function sets a new
EventManager to the context to isolate events per
Then, a simple switch calls the appropriate
handler based on the
In this regard,
handlers functions need to be implemented for each module
LegacyMsg. This will also involve manual handler registration of
handlers functions should return a
*Result and an
New telemetry metrics can be created from
msgServer methods when handling messages.
This is an example from the
Learn about query services