> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cosmos.network/llms.txt
> Use this file to discover all available pages before exploring further.

# Messages and Queries

<Note>
  **Synopsis**
  `Msg`s and `Queries` are the two primary objects handled by modules. Most of the core components defined in a module, like `Msg` services, `keeper`s and `Query` services, exist to process `message`s and `queries`.
</Note>

<Note>
  ### Pre-requisite Readings

  * [Introduction to Cosmos SDK Modules](/sdk/v0.47/build/building-modules/intro)
</Note>

## Messages

`Msg`s are objects whose end-goal is to trigger state-transitions. They are wrapped in [transactions](/sdk/v0.47/learn/advanced/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`](/sdk/v0.47/learn/advanced/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](/sdk/v0.47/build/building-modules/msg-services). For a more detailed explanation of the lifecycle of a transaction, click [here](/sdk/v0.47/learn/beginner/tx-lifecycle).

### `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](/sdk/v0.47/learn/advanced/encoding#faq)). 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:

```protobuf theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// 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:

```protobuf theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  rpc Send(MsgSend) returns (MsgSendResponse);
```

`sdk.Msg` interface is a simplified version of the Amino `LegacyMsg` interface described [below](#legacy-amino-legacymsg-s) with the `GetSigners()` method. For backwards compatibility with [Amino `LegacyMsg`s](#egacy-amino-legacymsg-s), 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](/sdk/v0.47/build/building-modules/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](/sdk/v0.47/build/building-modules/module-manager#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`](/sdk/v0.47/build/building-modules/module-manager#appmodulebasic) method, using the proto-generated `&_Msg_serviceDesc` as `*grpc.ServiceDesc` argument.

### Legacy Amino `LegacyMsg`s

The following way of defining messages is deprecated and using [`Msg` services](#msg-services) is preferred.

Amino `LegacyMsg`s 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](/sdk/v0.47/build/building-modules/module-interfaces). `message`s also need to implement the `sdk.Msg` interface:

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
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.

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
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:

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
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](/sdk/v0.47/learn/beginner/query-lifecycle).

### gRPC Queries

Queries should be defined using [Protobuf services](https://developers.google.com/protocol-buffers/docs/proto#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:

```protobuf theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// Reference: https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/auth/v1beta1/query.proto#L14-L89
```

As `proto.Message`s, generated `Response` types implement by default `String()` method of [`fmt.Stringer`](https://pkg.go.dev/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](/sdk/v0.47/build/building-modules/module-manager#appmodule).

### 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 `message`s. 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:

```text theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
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](/sdk/v0.47/learn/advanced/baseapp#query).
* `queryRoute` is used by `BaseApp`'s [`queryRouter`](/sdk/v0.47/learn/advanced/baseapp#grpc-query-router) to map the `query` to its module. Usually, `queryRoute` should be the name of the module.
* `queryType` is used by the module's [`querier`](/sdk/v0.47/build/building-modules/query-services#query-services) 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](/sdk/v0.47/build/building-modules/module-interfaces#query-commands).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`](/sdk/v0.47/build/building-modules/query-services#query-services), to process the `query` once it has been [routed to the module](/sdk/v0.47/learn/advanced/baseapp#grpc-query-router).
* [Query commands](/sdk/v0.47/build/building-modules/module-interfaces#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`](https://pkg.go.dev/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:

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
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: https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-060-abci-1.0.md
// 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: https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-060-abci-1.0.md
// 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
}
```
