Synopsis Msgs and Queries are the two primary objects handled by modules. Most of the core components defined in a module, like Msg services, keepers and Query services, exist to process messages and queries.

Messages

Msgs are objects whose end-goal is to trigger state-transitions. They are wrapped in transactions, which may contain one or more of them. When a transaction is relayed from the underlying consensus engine to the Cosmos SDK application, it is first decoded by BaseApp. Then, each message contained in the transaction is extracted and routed to the appropriate module via BaseApp’s MsgServiceRouter so that it can be processed by the module’s Msg service. For a more detailed explanation of the lifecycle of a transaction, click here.

Msg Services

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). It must have an RPC service method defined for each message in the module. See an example of a Msg service definition from x/bank module:
/ Reference: https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/tx.proto#L13-L36
Each Msg service method must have exactly one argument, which must implement the sdk.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:
  rpc Send(MsgSend) returns (MsgSendResponse);
sdk.Msg interface is a simplified version of the Amino LegacyMsg interface described below with the GetSigners() method. For backwards compatibility with Amino LegacyMsgs, existing LegacyMsg types should be used as the request parameter for service RPC definitions. Newer sdk.Msg types, which only support service definitions, should use canonical Msg... name. The Cosmos SDK uses Protobuf definitions to generate client and server code:
  • MsgServer interface defines the server API for the Msg service and its implementation is described as part of the Msg services documentation.
  • Structures are generated for all RPC request and response types.
A RegisterMsgServer method is also generated and should be used to register the module’s MsgServer implementation in RegisterServices method from the AppModule interface. 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 method, using the proto-generated &_Msg_serviceDesc as *grpc.ServiceDesc argument.

Legacy Amino LegacyMsgs

The following way of defining messages is deprecated and using Msg services is preferred. Amino LegacyMsgs can be defined as protobuf messages. The messages definition usually includes a list of parameters needed to process the message that will be provided by end-users when they want to create a new transaction containing said message. A LegacyMsg is typically accompanied by a standard constructor function, that is called from one of the module’s interface. messages also need to implement the sdk.Msg interface:
package types

import (
    
	"encoding/json"
	fmt "fmt"
    "github.com/cosmos/gogoproto/proto"
    "github.com/cosmos/cosmos-sdk/codec"
	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
)

type (
	/ Msg defines the interface a transaction message must fulfill.
	Msg interface {
    proto.Message

		/ ValidateBasic does a simple validation check that
		/ doesn't require access to any other information.
		ValidateBasic()

error

		/ GetSigners returns the addrs of signers that must sign.
		/ CONTRACT: All signatures must be present to be valid.
		/ CONTRACT: Returns addrs in some deterministic order.
		GetSigners() []AccAddress
}

	/ Fee defines an interface for an application application-defined concrete
	/ transaction type to be able to set and return the transaction fee.
	Fee interface {
    GetGas()

uint64
		GetAmount()

Coins
}

	/ Signature defines an interface for an application application-defined
	/ concrete transaction type to be able to set and return transaction signatures.
	Signature interface {
    GetPubKey()

cryptotypes.PubKey
		GetSignature() []byte
}

	/ Tx defines the interface a transaction must fulfill.
	Tx interface {
		/ GetMsgs gets the all the transaction's messages.
		GetMsgs() []Msg

		/ ValidateBasic does a simple and lightweight validation check that doesn't
		/ require access to any other information.
		ValidateBasic()

error
}

	/ FeeTx defines the interface to be implemented by Tx to use the FeeDecorators
	FeeTx interface {
    Tx
		GetGas()

uint64
		GetFee()

Coins
		FeePayer()

AccAddress
		FeeGranter()

AccAddress
}

	/ TxWithMemo must have GetMemo()

method to use ValidateMemoDecorator
	TxWithMemo interface {
    Tx
		GetMemo()

string
}

	/ TxWithTimeoutHeight extends the Tx interface by allowing a transaction to
	/ set a height timeout.
	TxWithTimeoutHeight interface {
    Tx

		GetTimeoutHeight()

uint64
}
)

/ TxDecoder unmarshals transaction bytes
type TxDecoder func(txBytes []byte) (Tx, error)

/ TxEncoder marshals transaction to bytes
type TxEncoder func(tx Tx) ([]byte, error)

/ MsgTypeURL returns the TypeURL of a `sdk.Msg`.
func MsgTypeURL(msg Msg)

string {
    return "/" + proto.MessageName(msg)
}

/ GetMsgFromTypeURL returns a `sdk.Msg` message type from a type URL
func GetMsgFromTypeURL(cdc codec.Codec, input string) (Msg, error) {
    var msg Msg
	bz, err := json.Marshal(struct {
    Type string `json:"@type"`
}{
    Type: input,
})
    if err != nil {
    return nil, err
}
    if err := cdc.UnmarshalInterfaceJSON(bz, &msg); err != nil {
    return nil, fmt.Errorf("failed to determine sdk.Msg for %s URL : %w", input, err)
}

return msg, nil
}
It extends proto.Message and contains the following methods:
  • GetSignBytes() []byte: Return the canonical byte representation of the message. Used to generate a signature.
  • GetSigners() []AccAddress: Return the list of signers. The Cosmos SDK will make sure that each message contained in a transaction is signed by all the signers listed in the list returned by this method.
package legacytx

import (
    
	"encoding/json"
    "fmt"
    "sigs.k8s.io/yaml"
    "github.com/cosmos/cosmos-sdk/codec"
    "github.com/cosmos/cosmos-sdk/codec/legacy"
	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
    "github.com/cosmos/cosmos-sdk/crypto/types/multisig"
	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
    "github.com/cosmos/cosmos-sdk/types/tx"
    "github.com/cosmos/cosmos-sdk/types/tx/signing"
)

/ LegacyMsg defines the old interface a message must fulfill, containing
/ Amino signing method and legacy router info.
/ Deprecated: Please use `Msg` instead.
type LegacyMsg interface {
    sdk.Msg

	/ Get the canonical byte representation of the Msg.
	GetSignBytes() []byte

	/ Return the message type.
	/ Must be alphanumeric or empty.
	Route()

string

	/ Returns a human-readable string for the message, intended for utilization
	/ within tags
	Type()

string
}

/ StdSignDoc is replay-prevention structure.
/ It includes the result of msg.GetSignBytes(),
/ as well as the ChainID (prevent cross chain replay)
/ and the Sequence numbers for each signature (prevent
/ inchain replay and enforce tx ordering per account).
type StdSignDoc struct {
    AccountNumber uint64            `json:"account_number" yaml:"account_number"`
	Sequence      uint64            `json:"sequence" yaml:"sequence"`
	TimeoutHeight uint64            `json:"timeout_height,omitempty" yaml:"timeout_height"`
	ChainID       string            `json:"chain_id" yaml:"chain_id"`
	Memo          string            `json:"memo" yaml:"memo"`
	Fee           json.RawMessage   `json:"fee" yaml:"fee"`
	Msgs          []json.RawMessage `json:"msgs" yaml:"msgs"`
	Tip           *StdTip           `json:"tip,omitempty" yaml:"tip"`
}

/ StdSignBytes returns the bytes to sign for a transaction.
func StdSignBytes(chainID string, accnum, sequence, timeout uint64, fee StdFee, msgs []sdk.Msg, memo string, tip *tx.Tip) []byte {
    msgsBytes := make([]json.RawMessage, 0, len(msgs))
    for _, msg := range msgs {
    legacyMsg, ok := msg.(LegacyMsg)
    if !ok {
    panic(fmt.Errorf("expected %T when using amino JSON", (*LegacyMsg)(nil)))
}

msgsBytes = append(msgsBytes, json.RawMessage(legacyMsg.GetSignBytes()))
}

var stdTip *StdTip
    if tip != nil {
    if tip.Tipper == "" {
    panic(fmt.Errorf("tipper cannot be empty"))
}

stdTip = &StdTip{
    Amount: tip.Amount,
    Tipper: tip.Tipper
}
	
}

bz, err := legacy.Cdc.MarshalJSON(StdSignDoc{
    AccountNumber: accnum,
    ChainID:       chainID,
    Fee:           json.RawMessage(fee.Bytes()),
    Memo:          memo,
    Msgs:          msgsBytes,
    Sequence:      sequence,
    TimeoutHeight: timeout,
    Tip:           stdTip,
})
    if err != nil {
    panic(err)
}

return sdk.MustSortJSON(bz)
}

/ Deprecated: StdSignature represents a sig
type StdSignature struct {
    cryptotypes.PubKey `json:"pub_key" yaml:"pub_key"` / optional
	Signature          []byte                          `json:"signature" yaml:"signature"`
}

/ Deprecated
func NewStdSignature(pk cryptotypes.PubKey, sig []byte)

StdSignature {
    return StdSignature{
    PubKey: pk,
    Signature: sig
}
}

/ GetSignature returns the raw signature bytes.
func (ss StdSignature)

GetSignature() []byte {
    return ss.Signature
}

/ GetPubKey returns the public key of a signature as a cryptotypes.PubKey using the
/ Amino codec.
func (ss StdSignature)

GetPubKey()

cryptotypes.PubKey {
    return ss.PubKey
}

/ MarshalYAML returns the YAML representation of the signature.
func (ss StdSignature)

MarshalYAML() (interface{
}, error) {
    pk := ""
    if ss.PubKey != nil {
    pk = ss.PubKey.String()
}

bz, err := yaml.Marshal(struct {
    PubKey    string `json:"pub_key"`
		Signature string `json:"signature"`
}{
    pk,
		fmt.Sprintf("%X", ss.Signature),
})
    if err != nil {
    return nil, err
}

return string(bz), err
}

func (ss StdSignature)

UnpackInterfaces(unpacker codectypes.AnyUnpacker)

error {
    return codectypes.UnpackInterfaces(ss.PubKey, unpacker)
}

/ StdSignatureToSignatureV2 converts a StdSignature to a SignatureV2
func StdSignatureToSignatureV2(cdc *codec.LegacyAmino, sig StdSignature) (signing.SignatureV2, error) {
    pk := sig.GetPubKey()

data, err := pubKeySigToSigData(cdc, pk, sig.Signature)
    if err != nil {
    return signing.SignatureV2{
}, err
}

return signing.SignatureV2{
    PubKey: pk,
    Data:   data,
}, nil
}

func pubKeySigToSigData(cdc *codec.LegacyAmino, key cryptotypes.PubKey, sig []byte) (signing.SignatureData, error) {
    multiPK, ok := key.(multisig.PubKey)
    if !ok {
    return &signing.SingleSignatureData{
    SignMode:  signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
    Signature: sig,
}, nil
}

var multiSig multisig.AminoMultisignature
    err := cdc.Unmarshal(sig, &multiSig)
    if err != nil {
    return nil, err
}
    sigs := multiSig.Sigs
    sigDatas := make([]signing.SignatureData, len(sigs))
    pubKeys := multiPK.GetPubKeys()
    bitArray := multiSig.BitArray
    n := multiSig.BitArray.Count()
    signatures := multisig.NewMultisig(n)
    sigIdx := 0
    for i := 0; i < n; i++ {
    if bitArray.GetIndex(i) {
    data, err := pubKeySigToSigData(cdc, pubKeys[i], multiSig.Sigs[sigIdx])
    if err != nil {
    return nil, sdkerrors.Wrapf(err, "Unable to convert Signature to SigData %d", sigIdx)
}

sigDatas[sigIdx] = data
			multisig.AddSignature(signatures, data, sigIdx)

sigIdx++
}
	
}

return signatures, nil
}
See an example implementation of a message from the gov module:
package v1

import (
    
	"fmt"
    "cosmossdk.io/math"

	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
	sdktx "github.com/cosmos/cosmos-sdk/types/tx"
    "github.com/cosmos/cosmos-sdk/x/gov/codec"
    "github.com/cosmos/cosmos-sdk/x/gov/types"
    "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
)

var (
	_, _, _, _, _, _ sdk.Msg                            = &MsgSubmitProposal{
}, &MsgDeposit{
}, &MsgVote{
}, &MsgVoteWeighted{
}, &MsgExecLegacyContent{
}, &MsgUpdateParams{
}
	_, _             codectypes.UnpackInterfacesMessage = &MsgSubmitProposal{
}, &MsgExecLegacyContent{
}
)

/ NewMsgSubmitProposal creates a new MsgSubmitProposal.
/
/nolint:interfacer
func NewMsgSubmitProposal(messages []sdk.Msg, initialDeposit sdk.Coins, proposer, metadata, title, summary string) (*MsgSubmitProposal, error) {
    m := &MsgSubmitProposal{
    InitialDeposit: initialDeposit,
    Proposer:       proposer,
    Metadata:       metadata,
    Title:          title,
    Summary:        summary,
}

anys, err := sdktx.SetMsgs(messages)
    if err != nil {
    return nil, err
}

m.Messages = anys

	return m, nil
}

/ GetMsgs unpacks m.Messages Any's into sdk.Msg's
func (m *MsgSubmitProposal)

GetMsgs() ([]sdk.Msg, error) {
    return sdktx.GetMsgs(m.Messages, "sdk.MsgProposal")
}

/ Route implements the sdk.Msg interface.
func (m MsgSubmitProposal)

Route()

string {
    return types.RouterKey
}

/ Type implements the sdk.Msg interface.
func (m MsgSubmitProposal)

Type()

string {
    return sdk.MsgTypeURL(&m)
}

/ ValidateBasic implements the sdk.Msg interface.
func (m MsgSubmitProposal)

ValidateBasic()

error {
    if m.Title == "" {
    return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "proposal title cannot be empty")
}
    if m.Summary == "" {
    return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "proposal summary cannot be empty")
}
    if _, err := sdk.AccAddressFromBech32(m.Proposer); err != nil {
    return sdkerrors.ErrInvalidAddress.Wrapf("invalid proposer address: %s", err)
}
    deposit := sdk.NewCoins(m.InitialDeposit...)
    if !deposit.IsValid() {
    return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, deposit.String())
}
    if deposit.IsAnyNegative() {
    return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, deposit.String())
}

	/ Check that either metadata or Msgs length is non nil.
    if len(m.Messages) == 0 && len(m.Metadata) == 0 {
    return sdkerrors.Wrap(types.ErrNoProposalMsgs, "either metadata or Msgs length must be non-nil")
}

msgs, err := m.GetMsgs()
    if err != nil {
    return err
}
    for idx, msg := range msgs {
    if err := msg.ValidateBasic(); err != nil {
    return sdkerrors.Wrap(types.ErrInvalidProposalMsg,
				fmt.Sprintf("msg: %d, err: %s", idx, err.Error()))
}
	
}

return nil
}

/ GetSignBytes returns the message bytes to sign over.
func (m MsgSubmitProposal)

GetSignBytes() []byte {
    bz := codec.ModuleCdc.MustMarshalJSON(&m)

return sdk.MustSortJSON(bz)
}

/ GetSigners returns the expected signers for a MsgSubmitProposal.
func (m MsgSubmitProposal)

GetSigners() []sdk.AccAddress {
    proposer, _ := sdk.AccAddressFromBech32(m.Proposer)

return []sdk.AccAddress{
    proposer
}
}

/ UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (m MsgSubmitProposal)

UnpackInterfaces(unpacker codectypes.AnyUnpacker)

error {
    return sdktx.UnpackInterfaces(unpacker, m.Messages)
}

/ NewMsgDeposit creates a new MsgDeposit instance
/
/nolint:interfacer
func NewMsgDeposit(depositor sdk.AccAddress, proposalID uint64, amount sdk.Coins) *MsgDeposit {
    return &MsgDeposit{
    proposalID, depositor.String(), amount
}
}

/ Route implements the sdk.Msg interface.
func (msg MsgDeposit)

Route()

string {
    return types.RouterKey
}

/ Type implements the sdk.Msg interface.
func (msg MsgDeposit)

Type()

string {
    return sdk.MsgTypeURL(&msg)
}

/ ValidateBasic implements the sdk.Msg interface.
func (msg MsgDeposit)

ValidateBasic()

error {
    if _, err := sdk.AccAddressFromBech32(msg.Depositor); err != nil {
    return sdkerrors.ErrInvalidAddress.Wrapf("invalid depositor address: %s", err)
}
    amount := sdk.NewCoins(msg.Amount...)
    if !amount.IsValid() {
    return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amount.String())
}
    if amount.IsAnyNegative() {
    return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amount.String())
}

return nil
}

/ GetSignBytes returns the message bytes to sign over.
func (msg MsgDeposit)

GetSignBytes() []byte {
    bz := codec.ModuleCdc.MustMarshalJSON(&msg)

return sdk.MustSortJSON(bz)
}

/ GetSigners returns the expected signers for a MsgDeposit.
func (msg MsgDeposit)

GetSigners() []sdk.AccAddress {
    depositor, _ := sdk.AccAddressFromBech32(msg.Depositor)

return []sdk.AccAddress{
    depositor
}
}

/ NewMsgVote creates a message to cast a vote on an active proposal
/
/nolint:interfacer
func NewMsgVote(voter sdk.AccAddress, proposalID uint64, option VoteOption, metadata string) *MsgVote {
    return &MsgVote{
    proposalID, voter.String(), option, metadata
}
}

/ Route implements the sdk.Msg interface.
func (msg MsgVote)

Route()

string {
    return types.RouterKey
}

/ Type implements the sdk.Msg interface.
func (msg MsgVote)

Type()

string {
    return sdk.MsgTypeURL(&msg)
}

/ ValidateBasic implements the sdk.Msg interface.
func (msg MsgVote)

ValidateBasic()

error {
    if _, err := sdk.AccAddressFromBech32(msg.Voter); err != nil {
    return sdkerrors.ErrInvalidAddress.Wrapf("invalid voter address: %s", err)
}
    if !ValidVoteOption(msg.Option) {
    return sdkerrors.Wrap(types.ErrInvalidVote, msg.Option.String())
}

return nil
}

/ GetSignBytes returns the message bytes to sign over.
func (msg MsgVote)

GetSignBytes() []byte {
    bz := codec.ModuleCdc.MustMarshalJSON(&msg)

return sdk.MustSortJSON(bz)
}

/ GetSigners returns the expected signers for a MsgVote.
func (msg MsgVote)

GetSigners() []sdk.AccAddress {
    voter, _ := sdk.AccAddressFromBech32(msg.Voter)

return []sdk.AccAddress{
    voter
}
}

/ NewMsgVoteWeighted creates a message to cast a vote on an active proposal
/
/nolint:interfacer
func NewMsgVoteWeighted(voter sdk.AccAddress, proposalID uint64, options WeightedVoteOptions, metadata string) *MsgVoteWeighted {
    return &MsgVoteWeighted{
    proposalID, voter.String(), options, metadata
}
}

/ Route implements the sdk.Msg interface.
func (msg MsgVoteWeighted)

Route()

string {
    return types.RouterKey
}

/ Type implements the sdk.Msg interface.
func (msg MsgVoteWeighted)

Type()

string {
    return sdk.MsgTypeURL(&msg)
}

/ ValidateBasic implements the sdk.Msg interface.
func (msg MsgVoteWeighted)

ValidateBasic()

error {
    if _, err := sdk.AccAddressFromBech32(msg.Voter); err != nil {
    return sdkerrors.ErrInvalidAddress.Wrapf("invalid voter address: %s", err)
}
    if len(msg.Options) == 0 {
    return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, WeightedVoteOptions(msg.Options).String())
}
    totalWeight := math.LegacyNewDec(0)
    usedOptions := make(map[VoteOption]bool)
    for _, option := range msg.Options {
    if !option.IsValid() {
    return sdkerrors.Wrap(types.ErrInvalidVote, option.String())
}

weight, err := sdk.NewDecFromStr(option.Weight)
    if err != nil {
    return sdkerrors.Wrapf(types.ErrInvalidVote, "Invalid weight: %s", err)
}

totalWeight = totalWeight.Add(weight)
    if usedOptions[option.Option] {
    return sdkerrors.Wrap(types.ErrInvalidVote, "Duplicated vote option")
}

usedOptions[option.Option] = true
}
    if totalWeight.GT(math.LegacyNewDec(1)) {
    return sdkerrors.Wrap(types.ErrInvalidVote, "Total weight overflow 1.00")
}
    if totalWeight.LT(math.LegacyNewDec(1)) {
    return sdkerrors.Wrap(types.ErrInvalidVote, "Total weight lower than 1.00")
}

return nil
}

/ GetSignBytes returns the message bytes to sign over.
func (msg MsgVoteWeighted)

GetSignBytes() []byte {
    bz := codec.ModuleCdc.MustMarshalJSON(&msg)

return sdk.MustSortJSON(bz)
}

/ GetSigners returns the expected signers for a MsgVoteWeighted.
func (msg MsgVoteWeighted)

GetSigners() []sdk.AccAddress {
    voter, _ := sdk.AccAddressFromBech32(msg.Voter)

return []sdk.AccAddress{
    voter
}
}

/ NewMsgExecLegacyContent creates a new MsgExecLegacyContent instance
/
/nolint:interfacer
func NewMsgExecLegacyContent(content *codectypes.Any, authority string) *MsgExecLegacyContent {
    return &MsgExecLegacyContent{
    Content:   content,
    Authority: authority,
}
}

/ GetSigners returns the expected signers for a MsgExecLegacyContent.
func (c MsgExecLegacyContent)

GetSigners() []sdk.AccAddress {
    authority, _ := sdk.AccAddressFromBech32(c.Authority)

return []sdk.AccAddress{
    authority
}
}

/ ValidateBasic implements the sdk.Msg interface.
func (c MsgExecLegacyContent)

ValidateBasic()

error {
	_, err := sdk.AccAddressFromBech32(c.Authority)
    if err != nil {
    return err
}

return nil
}

/ UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (c MsgExecLegacyContent)

UnpackInterfaces(unpacker codectypes.AnyUnpacker)

error {
    var content v1beta1.Content
	return unpacker.UnpackAny(c.Content, &content)
}

/ Route implements the sdk.Msg interface.
func (msg MsgUpdateParams)

Route()

string {
    return types.RouterKey
}

/ Type implements the sdk.Msg interface.
func (msg MsgUpdateParams)

Type()

string {
    return sdk.MsgTypeURL(&msg)
}

/ ValidateBasic implements the sdk.Msg interface.
func (msg MsgUpdateParams)

ValidateBasic()

error {
    if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil {
    return sdkerrors.ErrInvalidAddress.Wrapf("invalid authority address: %s", err)
}

return msg.Params.ValidateBasic()
}

/ GetSignBytes returns the message bytes to sign over.
func (msg MsgUpdateParams)

GetSignBytes() []byte {
    bz := codec.ModuleCdc.MustMarshalJSON(&msg)

return sdk.MustSortJSON(bz)
}

/ GetSigners returns the expected signers for a MsgUpdateParams.
func (msg MsgUpdateParams)

GetSigners() []sdk.AccAddress {
    authority, _ := sdk.AccAddressFromBech32(msg.Authority)

return []sdk.AccAddress{
    authority
}
}

Queries

A query is a request for information made by end-users of applications through an interface and processed by a full-node. A query is received by a full-node through its consensus engine and relayed to the application via the ABCI. It is then routed to the appropriate module via BaseApp’s QueryRouter so that it can be processed by the module’s query service (./04-query-services.md). For a deeper look at the lifecycle of a query, click here.

gRPC Queries

Queries should be defined using Protobuf services. A Query service should be created per module in query.proto. This service lists endpoints starting with rpc. Here’s an example of such a Query service definition:
/ Reference: https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/auth/v1beta1/query.proto#L14-L89
As proto.Messages, generated Response types implement by default String() method of fmt.Stringer. A RegisterQueryServer method is also generated and should be used to register the module’s query server in the RegisterServices method from the AppModule interface.

Legacy Queries

Before the introduction of Protobuf and gRPC in the Cosmos SDK, there was usually no specific query object defined by module developers, contrary to messages. Instead, the Cosmos SDK took the simpler approach of using a simple path to define each query. The path contains the query type and all the arguments needed to process it. For most module queries, the path should look like the following:
queryCategory/queryRoute/queryType/arg1/arg2/...
where:
  • queryCategory is the category of the query, typically custom for module queries. It is used to differentiate between different kinds of queries within BaseApp’s Query method.
  • queryRoute is used by BaseApp’s queryRouter to map the query to its module. Usually, queryRoute should be the name of the module.
  • queryType is used by the module’s querier to map the query to the appropriate querier function within the module.
  • args are the actual arguments needed to process the query. They are filled out by the end-user. Note that for bigger queries, you might prefer passing arguments in the Data field of the request req instead of the path.
The path for each query must be defined by the module developer in the module’s command-line interface file.Overall, there are 3 mains components module developers need to implement in order to make the subset of the state defined by their module queryable:
  • A querier, to process the query once it has been routed to the module.
  • Query commands in the module’s CLI file, where the path for each query is specified.
  • query return types. Typically defined in a file types/querier.go, they specify the result type of each of the module’s queries. These custom types must implement the String() method of fmt.Stringer.

Store Queries

Store queries query directly for store keys. They use clientCtx.QueryABCI(req abci.RequestQuery) to return the full abci.ResponseQuery with inclusion Merkle proofs. See following examples:
package baseapp

import (
    
	"crypto/sha256"
    "errors"
    "fmt"
    "os"
    "sort"
    "strings"
    "syscall"
    "time"
    "github.com/cosmos/gogoproto/proto"
	abci "github.com/tendermint/tendermint/abci/types"
	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
    "google.golang.org/grpc/codes"
	grpcstatus "google.golang.org/grpc/status"
    "github.com/cosmos/cosmos-sdk/codec"
	snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types"
    "github.com/cosmos/cosmos-sdk/telemetry"
	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

/ Supported ABCI Query prefixes
const (
	QueryPathApp    = "app"
	QueryPathCustom = "custom"
	QueryPathP2P    = "p2p"
	QueryPathStore  = "store"
)

/ InitChain implements the ABCI interface. It runs the initialization logic
/ directly on the CommitMultiStore.
func (app *BaseApp)

InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) {
	/ On a new chain, we consider the init chain block height as 0, even though
	/ req.InitialHeight is 1 by default.
    initHeader := tmproto.Header{
    ChainID: req.ChainId,
    Time: req.Time
}

app.logger.Info("InitChain", "initialHeight", req.InitialHeight, "chainID", req.ChainId)

	/ If req.InitialHeight is > 1, then we set the initial version in the
	/ stores.
    if req.InitialHeight > 1 {
    app.initialHeight = req.InitialHeight
		initHeader = tmproto.Header{
    ChainID: req.ChainId,
    Height: req.InitialHeight,
    Time: req.Time
}
    err := app.cms.SetInitialVersion(req.InitialHeight)
    if err != nil {
    panic(err)
}
	
}

	/ initialize states with a correct header
	app.setState(runTxModeDeliver, initHeader)

app.setState(runTxModeCheck, initHeader)

app.setState(runTxPrepareProposal, initHeader)

app.setState(runTxProcessProposal, initHeader)

	/ Store the consensus params in the BaseApp's paramstore. Note, this must be
	/ done after the deliver state and context have been set as it's persisted
	/ to state.
    if req.ConsensusParams != nil {
    app.StoreConsensusParams(app.deliverState.ctx, req.ConsensusParams)
}
    if app.initChainer == nil {
    return
}

	/ add block gas meter for any genesis transactions (allow infinite gas)

app.deliverState.ctx = app.deliverState.ctx.WithBlockGasMeter(sdk.NewInfiniteGasMeter())

res = app.initChainer(app.deliverState.ctx, req)

	/ sanity check
    if len(req.Validators) > 0 {
    if len(req.Validators) != len(res.Validators) {
    panic(
				fmt.Errorf(
					"len(RequestInitChain.Validators) != len(GenesisValidators) (%d != %d)",
					len(req.Validators), len(res.Validators),
				),
			)
}

sort.Sort(abci.ValidatorUpdates(req.Validators))

sort.Sort(abci.ValidatorUpdates(res.Validators))
    for i := range res.Validators {
    if !proto.Equal(&res.Validators[i], &req.Validators[i]) {
    panic(fmt.Errorf("genesisValidators[%d] != req.Validators[%d] ", i, i))
}
	
}
	
}

	/ In the case of a new chain, AppHash will be the hash of an empty string.
	/ During an upgrade, it'll be the hash of the last committed block.
	var appHash []byte
    if !app.LastCommitID().IsZero() {
    appHash = app.LastCommitID().Hash
}

else {
		/ $ echo -n '' | sha256sum
		/ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    emptyHash := sha256.Sum256([]byte{
})

appHash = emptyHash[:]
}

	/ NOTE: We don't commit, but BeginBlock for block `initial_height` starts from this
	/ deliverState.
	return abci.ResponseInitChain{
    ConsensusParams: res.ConsensusParams,
    Validators:      res.Validators,
    AppHash:         appHash,
}
}

/ Info implements the ABCI interface.
func (app *BaseApp)

Info(req abci.RequestInfo)

abci.ResponseInfo {
    lastCommitID := app.cms.LastCommitID()

return abci.ResponseInfo{
    Data:             app.name,
    Version:          app.version,
    AppVersion:       app.appVersion,
    LastBlockHeight:  lastCommitID.Version,
    LastBlockAppHash: lastCommitID.Hash,
}
}

/ FilterPeerByAddrPort filters peers by address/port.
func (app *BaseApp)

FilterPeerByAddrPort(info string)

abci.ResponseQuery {
    if app.addrPeerFilter != nil {
    return app.addrPeerFilter(info)
}

return abci.ResponseQuery{
}
}

/ FilterPeerByID filters peers by node ID.
func (app *BaseApp)

FilterPeerByID(info string)

abci.ResponseQuery {
    if app.idPeerFilter != nil {
    return app.idPeerFilter(info)
}

return abci.ResponseQuery{
}
}

/ BeginBlock implements the ABCI application interface.
func (app *BaseApp)

BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) {
    if app.cms.TracingEnabled() {
    app.cms.SetTracingContext(sdk.TraceContext(
			map[string]interface{
}{"blockHeight": req.Header.Height
},
		))
}
    if err := app.validateHeight(req); err != nil {
    panic(err)
}

	/ Initialize the DeliverTx state. If this is the first block, it should
	/ already be initialized in InitChain. Otherwise app.deliverState will be
	/ nil, since it is reset on Commit.
    if app.deliverState == nil {
    app.setState(runTxModeDeliver, req.Header)
}

else {
		/ In the first block, app.deliverState.ctx will already be initialized
		/ by InitChain. Context is now updated with Header information.
		app.deliverState.ctx = app.deliverState.ctx.
			WithBlockHeader(req.Header).
			WithBlockHeight(req.Header.Height)
}

	/ add block gas meter
	var gasMeter sdk.GasMeter
    if maxGas := app.GetMaximumBlockGas(app.deliverState.ctx); maxGas > 0 {
    gasMeter = sdk.NewGasMeter(maxGas)
}

else {
    gasMeter = sdk.NewInfiniteGasMeter()
}

	/ NOTE: header hash is not set in NewContext, so we manually set it here

	app.deliverState.ctx = app.deliverState.ctx.
		WithBlockGasMeter(gasMeter).
		WithHeaderHash(req.Hash).
		WithConsensusParams(app.GetConsensusParams(app.deliverState.ctx))
    if app.checkState != nil {
    app.checkState.ctx = app.checkState.ctx.
			WithBlockGasMeter(gasMeter).
			WithHeaderHash(req.Hash)
}
    if app.beginBlocker != nil {
    res = app.beginBlocker(app.deliverState.ctx, req)

res.Events = sdk.MarkEventsToIndex(res.Events, app.indexEvents)
}
	/ set the signed validators for addition to context in deliverTx
	app.voteInfos = req.LastCommitInfo.GetVotes()

	/ call the hooks with the BeginBlock messages
    for _, streamingListener := range app.abciListeners {
    if err := streamingListener.ListenBeginBlock(app.deliverState.ctx, req, res); err != nil {
    panic(fmt.Errorf("BeginBlock listening hook failed, height: %d, err: %w", req.Header.Height, err))
}
	
}

return res
}

/ EndBlock implements the ABCI interface.
func (app *BaseApp)

EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) {
    if app.deliverState.ms.TracingEnabled() {
    app.deliverState.ms = app.deliverState.ms.SetTracingContext(nil).(sdk.CacheMultiStore)
}
    if app.endBlocker != nil {
    res = app.endBlocker(app.deliverState.ctx, req)

res.Events = sdk.MarkEventsToIndex(res.Events, app.indexEvents)
}
    if cp := app.GetConsensusParams(app.deliverState.ctx); cp != nil {
    res.ConsensusParamUpdates = cp
}

	/ call the streaming service hooks with the EndBlock messages
    for _, streamingListener := range app.abciListeners {
    if err := streamingListener.ListenEndBlock(app.deliverState.ctx, req, res); err != nil {
    panic(fmt.Errorf("EndBlock listening hook failed, height: %d, err: %w", req.Height, err))
}
	
}

return res
}

/ PrepareProposal implements the PrepareProposal ABCI method and returns a
/ ResponsePrepareProposal object to the client. The PrepareProposal method is
/ responsible for allowing the block proposer to perform application-dependent
/ work in a block before proposing it.
/
/ Transactions can be modified, removed, or added by the application. Since the
/ application maintains its own local mempool, it will ignore the transactions
/ provided to it in RequestPrepareProposal. Instead, it will determine which
/ transactions to return based on the mempool's semantics and the MaxTxBytes
/ provided by the client's request.
/
/ Ref: docs/sdk/next/documentation/legacy/adr-comprehensive
/ Ref: https://github.com/tendermint/tendermint/blob/main/spec/abci/abci%2B%2B_basic_concepts.md
func (app *BaseApp)

PrepareProposal(req abci.RequestPrepareProposal) (resp abci.ResponsePrepareProposal) {
    if app.prepareProposal == nil {
    panic("PrepareProposal method not set")
}

	/ Tendermint must never call PrepareProposal with a height of 0.
	/ Ref: https://github.com/tendermint/tendermint/blob/059798a4f5b0c9f52aa8655fa619054a0154088c/spec/core/state.md?plain=1#L37-L38
    if req.Height < 1 {
    panic("PrepareProposal called with invalid height")
}
    ctx := app.getContextForProposal(app.prepareProposalState.ctx, req.Height)

ctx = ctx.WithVoteInfos(app.voteInfos).
		WithBlockHeight(req.Height).
		WithBlockTime(req.Time).
		WithProposer(req.ProposerAddress).
		WithConsensusParams(app.GetConsensusParams(ctx))

defer func() {
    if err := recover(); err != nil {
    app.logger.Error(
				"panic recovered in PrepareProposal",
				"height", req.Height,
				"time", req.Time,
				"panic", err,
			)

resp = abci.ResponsePrepareProposal{
    Txs: req.Txs
}
	
}
	
}()

resp = app.prepareProposal(ctx, req)

return resp
}

/ ProcessProposal implements the ProcessProposal ABCI method and returns a
/ ResponseProcessProposal object to the client. The ProcessProposal method is
/ responsible for allowing execution of application-dependent work in a proposed
/ block. Note, the application defines the exact implementation details of
/ ProcessProposal. In general, the application must at the very least ensure
/ that all transactions are valid. If all transactions are valid, then we inform
/ Tendermint that the Status is ACCEPT. However, the application is also able
/ to implement optimizations such as executing the entire proposed block
/ immediately.
/
/ If a panic is detected during execution of an application's ProcessProposal
/ handler, it will be recovered and we will reject the proposal.
/
/ Ref: docs/sdk/next/documentation/legacy/adr-comprehensive
/ Ref: https://github.com/tendermint/tendermint/blob/main/spec/abci/abci%2B%2B_basic_concepts.md
func (app *BaseApp)

ProcessProposal(req abci.RequestProcessProposal) (resp abci.ResponseProcessProposal) {
    if app.processProposal == nil {
    panic("app.ProcessProposal is not set")
}
    ctx := app.getContextForProposal(app.processProposalState.ctx, req.Height)

ctx = ctx.
		WithVoteInfos(app.voteInfos).
		WithBlockHeight(req.Height).
		WithBlockTime(req.Time).
		WithHeaderHash(req.Hash).
		WithProposer(req.ProposerAddress).
		WithConsensusParams(app.GetConsensusParams(ctx))

defer func() {
    if err := recover(); err != nil {
    app.logger.Error(
				"panic recovered in ProcessProposal",
				"height", req.Height,
				"time", req.Time,
				"hash", fmt.Sprintf("%X", req.Hash),
				"panic", err,
			)

resp = abci.ResponseProcessProposal{
    Status: abci.ResponseProcessProposal_REJECT
}
	
}
	
}()

resp = app.processProposal(ctx, req)

return resp
}

/ CheckTx implements the ABCI interface and executes a tx in CheckTx mode. In
/ CheckTx mode, messages are not executed. This means messages are only validated
/ and only the AnteHandler is executed. State is persisted to the BaseApp's
/ internal CheckTx state if the AnteHandler passes. Otherwise, the ResponseCheckTx
/ will contain relevant error information. Regardless of tx execution outcome,
/ the ResponseCheckTx will contain relevant gas execution context.
func (app *BaseApp)

CheckTx(req abci.RequestCheckTx)

abci.ResponseCheckTx {
    var mode runTxMode
    switch {
    case req.Type == abci.CheckTxType_New:
		mode = runTxModeCheck
    case req.Type == abci.CheckTxType_Recheck:
		mode = runTxModeReCheck

	default:
		panic(fmt.Sprintf("unknown RequestCheckTx type: %s", req.Type))
}

gInfo, result, anteEvents, priority, err := app.runTx(mode, req.Tx)
    if err != nil {
    return sdkerrors.ResponseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, app.trace)
}

return abci.ResponseCheckTx{
    GasWanted: int64(gInfo.GasWanted), / TODO: Should type accept unsigned ints?
		GasUsed:   int64(gInfo.GasUsed),   / TODO: Should type accept unsigned ints?
		Log:       result.Log,
    Data:      result.Data,
    Events:    sdk.MarkEventsToIndex(result.Events, app.indexEvents),
    Priority:  priority,
}
}

/ DeliverTx implements the ABCI interface and executes a tx in DeliverTx mode.
/ State only gets persisted if all messages are valid and get executed successfully.
/ Otherwise, the ResponseDeliverTx will contain relevant error information.
/ Regardless of tx execution outcome, the ResponseDeliverTx will contain relevant
/ gas execution context.
func (app *BaseApp)

DeliverTx(req abci.RequestDeliverTx) (res abci.ResponseDeliverTx) {
    gInfo := sdk.GasInfo{
}
    resultStr := "successful"

	defer func() {
    for _, streamingListener := range app.abciListeners {
    if err := streamingListener.ListenDeliverTx(app.deliverState.ctx, req, res); err != nil {
    panic(fmt.Errorf("DeliverTx listening hook failed: %w", err))
}
	
}
	
}()

defer func() {
    telemetry.IncrCounter(1, "tx", "count")

telemetry.IncrCounter(1, "tx", resultStr)

telemetry.SetGauge(float32(gInfo.GasUsed), "tx", "gas", "used")

telemetry.SetGauge(float32(gInfo.GasWanted), "tx", "gas", "wanted")
}()

gInfo, result, anteEvents, _, err := app.runTx(runTxModeDeliver, req.Tx)
    if err != nil {
    resultStr = "failed"
		return sdkerrors.ResponseDeliverTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, sdk.MarkEventsToIndex(anteEvents, app.indexEvents), app.trace)
}

return abci.ResponseDeliverTx{
    GasWanted: int64(gInfo.GasWanted), / TODO: Should type accept unsigned ints?
		GasUsed:   int64(gInfo.GasUsed),   / TODO: Should type accept unsigned ints?
		Log:       result.Log,
    Data:      result.Data,
    Events:    sdk.MarkEventsToIndex(result.Events, app.indexEvents),
}
}

/ Commit implements the ABCI interface. It will commit all state that exists in
/ the deliver state's multi-store and includes the resulting commit ID in the
/ returned abci.ResponseCommit. Commit will set the check state based on the
/ latest header and reset the deliver state. Also, if a non-zero halt height is
/ defined in config, Commit will execute a deferred function call to check
/ against that height and gracefully halt if it matches the latest committed
/ height.
func (app *BaseApp)

Commit()

abci.ResponseCommit {
    header := app.deliverState.ctx.BlockHeader()
    retainHeight := app.GetBlockRetentionHeight(header.Height)

	/ Write the DeliverTx state into branched storage and commit the MultiStore.
	/ The write to the DeliverTx state writes all state transitions to the root
	/ MultiStore (app.cms)

so when Commit()

is called is persists those values.
	app.deliverState.ms.Write()
    commitID := app.cms.Commit()
    res := abci.ResponseCommit{
    Data:         commitID.Hash,
    RetainHeight: retainHeight,
}

	/ call the hooks with the Commit message
    for _, streamingListener := range app.abciListeners {
    if err := streamingListener.ListenCommit(app.deliverState.ctx, res); err != nil {
    panic(fmt.Errorf("Commit listening hook failed, height: %d, err: %w", header.Height, err))
}
	
}

app.logger.Info("commit synced", "commit", fmt.Sprintf("%X", commitID))

	/ Reset the Check state to the latest committed.
	/
	/ NOTE: This is safe because Tendermint holds a lock on the mempool for
	/ Commit. Use the header from this latest block.
	app.setState(runTxModeCheck, header)

app.setState(runTxPrepareProposal, header)

app.setState(runTxProcessProposal, header)

	/ empty/reset the deliver state
	app.deliverState = nil

	var halt bool
    switch {
    case app.haltHeight > 0 && uint64(header.Height) >= app.haltHeight:
		halt = true
    case app.haltTime > 0 && header.Time.Unix() >= int64(app.haltTime):
		halt = true
}
    if halt {
		/ Halt the binary and allow Tendermint to receive the ResponseCommit
		/ response with the commit ID hash. This will allow the node to successfully
		/ restart and process blocks assuming the halt configuration has been
		/ reset or moved to a more distant value.
		app.halt()
}

go app.snapshotManager.SnapshotIfApplicable(header.Height)

return res
}

/ halt attempts to gracefully shutdown the node via SIGINT and SIGTERM falling
/ back on os.Exit if both fail.
func (app *BaseApp)

halt() {
    app.logger.Info("halting node per configuration", "height", app.haltHeight, "time", app.haltTime)

p, err := os.FindProcess(os.Getpid())
    if err == nil {
		/ attempt cascading signals in case SIGINT fails (os dependent)
    sigIntErr := p.Signal(syscall.SIGINT)
    sigTermErr := p.Signal(syscall.SIGTERM)
    if sigIntErr == nil || sigTermErr == nil {
    return
}
	
}

	/ Resort to exiting immediately if the process could not be found or killed
	/ via SIGINT/SIGTERM signals.
	app.logger.Info("failed to send SIGINT/SIGTERM; exiting...")

os.Exit(0)
}

/ Query implements the ABCI interface. It delegates to CommitMultiStore if it
/ implements Queryable.
func (app *BaseApp)

Query(req abci.RequestQuery) (res abci.ResponseQuery) {
	/ Add panic recovery for all queries.
	/ ref: https://github.com/cosmos/cosmos-sdk/pull/8039
	defer func() {
    if r := recover(); r != nil {
    res = sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrPanic, "%v", r), app.trace)
}
	
}()

	/ when a client did not provide a query height, manually inject the latest
    if req.Height == 0 {
    req.Height = app.LastBlockHeight()
}

telemetry.IncrCounter(1, "query", "count")

telemetry.IncrCounter(1, "query", req.Path)

defer telemetry.MeasureSince(time.Now(), req.Path)

	/ handle gRPC routes first rather than calling splitPath because '/' characters
	/ are used as part of gRPC paths
    if grpcHandler := app.grpcQueryRouter.Route(req.Path); grpcHandler != nil {
    return app.handleQueryGRPC(grpcHandler, req)
}
    path := SplitABCIQueryPath(req.Path)
    if len(path) == 0 {
    return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "no query path provided"), app.trace)
}
    switch path[0] {
    case QueryPathApp:
		/ "/app" prefix for special application queries
		return handleQueryApp(app, path, req)
    case QueryPathStore:
		return handleQueryStore(app, path, req)
    case QueryPathP2P:
		return handleQueryP2P(app, path)
}

return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown query path"), app.trace)
}

/ ListSnapshots implements the ABCI interface. It delegates to app.snapshotManager if set.
func (app *BaseApp)

ListSnapshots(req abci.RequestListSnapshots)

abci.ResponseListSnapshots {
    resp := abci.ResponseListSnapshots{
    Snapshots: []*abci.Snapshot{
}}
    if app.snapshotManager == nil {
    return resp
}

snapshots, err := app.snapshotManager.List()
    if err != nil {
    app.logger.Error("failed to list snapshots", "err", err)

return resp
}
    for _, snapshot := range snapshots {
    abciSnapshot, err := snapshot.ToABCI()
    if err != nil {
    app.logger.Error("failed to list snapshots", "err", err)

return resp
}

resp.Snapshots = append(resp.Snapshots, &abciSnapshot)
}

return resp
}

/ LoadSnapshotChunk implements the ABCI interface. It delegates to app.snapshotManager if set.
func (app *BaseApp)

LoadSnapshotChunk(req abci.RequestLoadSnapshotChunk)

abci.ResponseLoadSnapshotChunk {
    if app.snapshotManager == nil {
    return abci.ResponseLoadSnapshotChunk{
}
	
}

chunk, err := app.snapshotManager.LoadChunk(req.Height, req.Format, req.Chunk)
    if err != nil {
    app.logger.Error(
			"failed to load snapshot chunk",
			"height", req.Height,
			"format", req.Format,
			"chunk", req.Chunk,
			"err", err,
		)

return abci.ResponseLoadSnapshotChunk{
}
	
}

return abci.ResponseLoadSnapshotChunk{
    Chunk: chunk
}
}

/ OfferSnapshot implements the ABCI interface. It delegates to app.snapshotManager if set.
func (app *BaseApp)

OfferSnapshot(req abci.RequestOfferSnapshot)

abci.ResponseOfferSnapshot {
    if app.snapshotManager == nil {
    app.logger.Error("snapshot manager not configured")

return abci.ResponseOfferSnapshot{
    Result: abci.ResponseOfferSnapshot_ABORT
}
	
}
    if req.Snapshot == nil {
    app.logger.Error("received nil snapshot")

return abci.ResponseOfferSnapshot{
    Result: abci.ResponseOfferSnapshot_REJECT
}
	
}

snapshot, err := snapshottypes.SnapshotFromABCI(req.Snapshot)
    if err != nil {
    app.logger.Error("failed to decode snapshot metadata", "err", err)

return abci.ResponseOfferSnapshot{
    Result: abci.ResponseOfferSnapshot_REJECT
}
	
}

err = app.snapshotManager.Restore(snapshot)
    switch {
    case err == nil:
		return abci.ResponseOfferSnapshot{
    Result: abci.ResponseOfferSnapshot_ACCEPT
}
    case errors.Is(err, snapshottypes.ErrUnknownFormat):
		return abci.ResponseOfferSnapshot{
    Result: abci.ResponseOfferSnapshot_REJECT_FORMAT
}
    case errors.Is(err, snapshottypes.ErrInvalidMetadata):
		app.logger.Error(
			"rejecting invalid snapshot",
			"height", req.Snapshot.Height,
			"format", req.Snapshot.Format,
			"err", err,
		)

return abci.ResponseOfferSnapshot{
    Result: abci.ResponseOfferSnapshot_REJECT
}

default:
		app.logger.Error(
			"failed to restore snapshot",
			"height", req.Snapshot.Height,
			"format", req.Snapshot.Format,
			"err", err,
		)

		/ We currently don't support resetting the IAVL stores and retrying a different snapshot,
		/ so we ask Tendermint to abort all snapshot restoration.
		return abci.ResponseOfferSnapshot{
    Result: abci.ResponseOfferSnapshot_ABORT
}
	
}
}

/ ApplySnapshotChunk implements the ABCI interface. It delegates to app.snapshotManager if set.
func (app *BaseApp)

ApplySnapshotChunk(req abci.RequestApplySnapshotChunk)

abci.ResponseApplySnapshotChunk {
    if app.snapshotManager == nil {
    app.logger.Error("snapshot manager not configured")

return abci.ResponseApplySnapshotChunk{
    Result: abci.ResponseApplySnapshotChunk_ABORT
}
	
}

	_, err := app.snapshotManager.RestoreChunk(req.Chunk)
    switch {
    case err == nil:
		return abci.ResponseApplySnapshotChunk{
    Result: abci.ResponseApplySnapshotChunk_ACCEPT
}
    case errors.Is(err, snapshottypes.ErrChunkHashMismatch):
		app.logger.Error(
			"chunk checksum mismatch; rejecting sender and requesting refetch",
			"chunk", req.Index,
			"sender", req.Sender,
			"err", err,
		)

return abci.ResponseApplySnapshotChunk{
    Result:        abci.ResponseApplySnapshotChunk_RETRY,
    RefetchChunks: []uint32{
    req.Index
},
    RejectSenders: []string{
    req.Sender
},
}

default:
		app.logger.Error("failed to restore snapshot", "err", err)

return abci.ResponseApplySnapshotChunk{
    Result: abci.ResponseApplySnapshotChunk_ABORT
}
	
}
}

func (app *BaseApp)

handleQueryGRPC(handler GRPCQueryHandler, req abci.RequestQuery)

abci.ResponseQuery {
    ctx, err := app.CreateQueryContext(req.Height, req.Prove)
    if err != nil {
    return sdkerrors.QueryResult(err, app.trace)
}

res, err := handler(ctx, req)
    if err != nil {
    res = sdkerrors.QueryResult(gRPCErrorToSDKError(err), app.trace)

res.Height = req.Height
		return res
}

return res
}

func gRPCErrorToSDKError(err error)

error {
    status, ok := grpcstatus.FromError(err)
    if !ok {
    return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())
}
    switch status.Code() {
    case codes.NotFound:
		return sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, err.Error())
    case codes.InvalidArgument:
		return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())
    case codes.FailedPrecondition:
		return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())
    case codes.Unauthenticated:
		return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, err.Error())

default:
		return sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, err.Error())
}
}

func checkNegativeHeight(height int64)

error {
    if height < 0 {
		/ Reject invalid heights.
		return sdkerrors.Wrap(
			sdkerrors.ErrInvalidRequest,
			"cannot query with height < 0; please provide a valid height",
		)
}

return nil
}

/ createQueryContext creates a new sdk.Context for a query, taking as args
/ the block height and whether the query needs a proof or not.
func (app *BaseApp)

CreateQueryContext(height int64, prove bool) (sdk.Context, error) {
    if err := checkNegativeHeight(height); err != nil {
    return sdk.Context{
}, err
}

	/ use custom query multistore if provided
    qms := app.qms
    if qms == nil {
    qms = app.cms.(sdk.MultiStore)
}
    lastBlockHeight := qms.LatestVersion()
    if height > lastBlockHeight {
    return sdk.Context{
},
			sdkerrors.Wrap(
				sdkerrors.ErrInvalidHeight,
				"cannot query with height in the future; please provide a valid height",
			)
}

	/ when a client did not provide a query height, manually inject the latest
    if height == 0 {
    height = lastBlockHeight
}
    if height <= 1 && prove {
    return sdk.Context{
},
			sdkerrors.Wrap(
				sdkerrors.ErrInvalidRequest,
				"cannot query with proof when height <= 1; please provide a valid height",
			)
}

cacheMS, err := qms.CacheMultiStoreWithVersion(height)
    if err != nil {
    return sdk.Context{
},
			sdkerrors.Wrapf(
				sdkerrors.ErrInvalidRequest,
				"failed to load state at height %d; %s (latest height: %d)", height, err, lastBlockHeight,
			)
}

	/ branch the commit-multistore for safety
    ctx := sdk.NewContext(
		cacheMS, app.checkState.ctx.BlockHeader(), true, app.logger,
	).WithMinGasPrices(app.minGasPrices).WithBlockHeight(height)

return ctx, nil
}

/ GetBlockRetentionHeight returns the height for which all blocks below this height
/ are pruned from Tendermint. Given a commitment height and a non-zero local
/ minRetainBlocks configuration, the retentionHeight is the smallest height that
/ satisfies:
/
/ - Unbonding (safety threshold)

time: The block interval in which validators
/ can be economically punished for misbehavior. Blocks in this interval must be
/ auditable e.g. by the light client.
/
/ - Logical store snapshot interval: The block interval at which the underlying
/ logical store database is persisted to disk, e.g. every 10000 heights. Blocks
/ since the last IAVL snapshot must be available for replay on application restart.
/
/ - State sync snapshots: Blocks since the oldest available snapshot must be
/ available for state sync nodes to catch up (oldest because a node may be
/ restoring an old snapshot while a new snapshot was taken).
/
/ - Local (minRetainBlocks)

config: Archive nodes may want to retain more or
/ all blocks, e.g. via a local config option min-retain-blocks. There may also
/ be a need to vary retention for other nodes, e.g. sentry nodes which do not
/ need historical blocks.
func (app *BaseApp)

GetBlockRetentionHeight(commitHeight int64)

int64 {
	/ pruning is disabled if minRetainBlocks is zero
    if app.minRetainBlocks == 0 {
    return 0
}
    minNonZero := func(x, y int64)

int64 {
    switch {
    case x == 0:
			return y
    case y == 0:
			return x
    case x < y:
			return x
		default:
			return y
}
	
}

	/ Define retentionHeight as the minimum value that satisfies all non-zero
	/ constraints. All blocks below (commitHeight-retentionHeight)

are pruned
	/ from Tendermint.
	var retentionHeight int64

	/ Define the number of blocks needed to protect against misbehaving validators
	/ which allows light clients to operate safely. Note, we piggy back of the
	/ evidence parameters instead of computing an estimated nubmer of blocks based
	/ on the unbonding period and block commitment time as the two should be
	/ equivalent.
    cp := app.GetConsensusParams(app.deliverState.ctx)
    if cp != nil && cp.Evidence != nil && cp.Evidence.MaxAgeNumBlocks > 0 {
    retentionHeight = commitHeight - cp.Evidence.MaxAgeNumBlocks
}
    if app.snapshotManager != nil {
    snapshotRetentionHeights := app.snapshotManager.GetSnapshotBlockRetentionHeights()
    if snapshotRetentionHeights > 0 {
    retentionHeight = minNonZero(retentionHeight, commitHeight-snapshotRetentionHeights)
}
	
}
    v := commitHeight - int64(app.minRetainBlocks)

retentionHeight = minNonZero(retentionHeight, v)
    if retentionHeight <= 0 {
		/ prune nothing in the case of a non-positive height
		return 0
}

return retentionHeight
}

func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery)

abci.ResponseQuery {
    if len(path) >= 2 {
    switch path[1] {
    case "simulate":
    txBytes := req.Data

			gInfo, res, err := app.Simulate(txBytes)
    if err != nil {
    return sdkerrors.QueryResult(sdkerrors.Wrap(err, "failed to simulate tx"), app.trace)
}
    simRes := &sdk.SimulationResponse{
    GasInfo: gInfo,
    Result:  res,
}

bz, err := codec.ProtoMarshalJSON(simRes, app.interfaceRegistry)
    if err != nil {
    return sdkerrors.QueryResult(sdkerrors.Wrap(err, "failed to JSON encode simulation response"), app.trace)
}

return abci.ResponseQuery{
    Codespace: sdkerrors.RootCodespace,
    Height:    req.Height,
    Value:     bz,
}
    case "version":
			return abci.ResponseQuery{
    Codespace: sdkerrors.RootCodespace,
    Height:    req.Height,
    Value:     []byte(app.version),
}

default:
			return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown query: %s", path), app.trace)
}
	
}

return sdkerrors.QueryResult(
		sdkerrors.Wrap(
			sdkerrors.ErrUnknownRequest,
			"expected second parameter to be either 'simulate' or 'version', neither was present",
		), app.trace)
}

func handleQueryStore(app *BaseApp, path []string, req abci.RequestQuery)

abci.ResponseQuery {
	/ "/store" prefix for store queries
	queryable, ok := app.cms.(sdk.Queryable)
    if !ok {
    return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "multistore doesn't support queries"), app.trace)
}

req.Path = "/" + strings.Join(path[1:], "/")
    if req.Height <= 1 && req.Prove {
    return sdkerrors.QueryResult(
			sdkerrors.Wrap(
				sdkerrors.ErrInvalidRequest,
				"cannot query with proof when height <= 1; please provide a valid height",
			), app.trace)
}
    resp := queryable.Query(req)

resp.Height = req.Height

	return resp
}

func handleQueryP2P(app *BaseApp, path []string)

abci.ResponseQuery {
	/ "/p2p" prefix for p2p queries
    if len(path) < 4 {
    return sdkerrors.QueryResult(
			sdkerrors.Wrap(
				sdkerrors.ErrUnknownRequest, "path should be p2p filter <addr|id> <parameter>",
			), app.trace)
}

var resp abci.ResponseQuery

	cmd, typ, arg := path[1], path[2], path[3]
    switch cmd {
    case "filter":
    switch typ {
    case "addr":
			resp = app.FilterPeerByAddrPort(arg)
    case "id":
			resp = app.FilterPeerByID(arg)
}

default:
		resp = sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "expected second parameter to be 'filter'"), app.trace)
}

return resp
}

/ SplitABCIQueryPath splits a string path using the delimiter '/'.
/
/ e.g. "this/is/funny" becomes []string{"this", "is", "funny"
}

func SplitABCIQueryPath(requestPath string) (path []string) {
    path = strings.Split(requestPath, "/")

	/ first element is empty string
    if len(path) > 0 && path[0] == "" {
    path = path[1:]
}

return path
}

/ getContextForProposal returns the right context for PrepareProposal and
/ ProcessProposal. We use deliverState on the first block to be able to access
/ any state changes made in InitChain.
func (app *BaseApp)

getContextForProposal(ctx sdk.Context, height int64)

sdk.Context {
    if height == 1 {
    ctx, _ = app.deliverState.ctx.CacheContext()

return ctx
}

return ctx
}