Synopsis

While encoding in the Cosmos SDK used to be mainly handled by go-amino codec, the Cosmos SDK is moving towards using gogoprotobuf for both state and client-side encoding.

Encoding

The Cosmos SDK utilizes two binary wire encoding protocols, Amino which is an object encoding specification and Protocol Buffers, a subset of Proto3 with an extension for interface support. See the Proto3 spec for more information on Proto3, which Amino is largely compatible with (but not with Proto2). Due to Amino having significant performance drawbacks, being reflection-based, and not having any meaningful cross-language/client support, Protocol Buffers, specifically gogoprotobuf, is being used in place of Amino. Note, this process of using Protocol Buffers over Amino is still an ongoing process. Binary wire encoding of types in the Cosmos SDK can be broken down into two main categories, client encoding and store encoding. Client encoding mainly revolves around transaction processing and signing, whereas store encoding revolves around types used in state-machine transitions and what is ultimately stored in the Merkle tree. For store encoding, protobuf definitions can exist for any type and will typically have an Amino-based “intermediary” type. Specifically, the protobuf-based type definition is used for serialization and persistence, whereas the Amino-based type is used for business logic in the state-machine where they may convert back-n-forth. Note, the Amino-based types may slowly be phased-out in the future, so developers should take note to use the protobuf message definitions where possible. In the codec package, there exists two core interfaces, BinaryCodec and JSONCodec, where the former encapsulates the current Amino interface except it operates on types implementing the latter instead of generic interface{} types. In addition, there exists two implementations of Codec. The first being AminoCodec, where both binary and JSON serialization is handled via Amino. The second being ProtoCodec, where both binary and JSON serialization is handled via Protobuf. This means that modules may use Amino or Protobuf encoding, but the types must implement ProtoMarshaler. If modules wish to avoid implementing this interface for their types, they may use an Amino codec directly.

Amino

Every module uses an Amino codec to serialize types and interfaces. This codec typically has types and interfaces registered in that module’s domain only (e.g. messages), but there are exceptions like x/gov. Each module exposes a RegisterLegacyAminoCodec function that allows a user to provide a codec and have all the types registered. An application will call this method for each necessary module. Where there is no protobuf-based type definition for a module (see below), Amino is used to encode and decode raw wire bytes to the concrete type or interface:
bz := keeper.cdc.MustMarshal(typeOrInterface)

keeper.cdc.MustUnmarshal(bz, &typeOrInterface)
Note, there are length-prefixed variants of the above functionality and this is typically used for when the data needs to be streamed or grouped together (e.g. ResponseDeliverTx.Data)

Authz authorizations and Gov/Group proposals

Since authz’s MsgExec and MsgGrant message types, as well as gov’s and group’s MsgSubmitProposal, can contain different messages instances, it is important that developers add the following code inside the init method of their module’s codec.go file:
import (

  authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec"
  govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec"
  groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec"
)

init() {
    / Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be
    / used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances
    RegisterLegacyAminoCodec(authzcodec.Amino)

RegisterLegacyAminoCodec(govcodec.Amino)

RegisterLegacyAminoCodec(groupcodec.Amino)
}
This will allow the x/authz module to properly serialize and de-serializes MsgExec instances using Amino, which is required when signing this kind of messages using a Ledger.

Gogoproto

Modules are encouraged to utilize Protobuf encoding for their respective types. In the Cosmos SDK, we use the Gogoproto specific implementation of the Protobuf spec that offers speed and DX improvements compared to the official Google protobuf implementation.

Guidelines for protobuf message definitions

In addition to following official Protocol Buffer guidelines, we recommend using these annotations in .proto files when dealing with interfaces:
  • use cosmos_proto.accepts_interface to annote Any fields that accept interfaces
    • pass the same fully qualified name as protoName to InterfaceRegistry.RegisterInterface
    • example: (cosmos_proto.accepts_interface) = "cosmos.gov.v1beta1.Content" (and not just Content)
  • annotate interface implementations with cosmos_proto.implements_interface
    • pass the same fully qualified name as protoName to InterfaceRegistry.RegisterInterface
    • example: (cosmos_proto.implements_interface) = "cosmos.authz.v1beta1.Authorization" (and not just Authorization)
Code generators can then match the accepts_interface and implements_interface annotations to know whether some Protobuf messages are allowed to be packed in a given Any field or not.

Transaction Encoding

Another important use of Protobuf is the encoding and decoding of transactions. Transactions are defined by the application or the Cosmos SDK but are then passed to the underlying consensus engine to be relayed to other peers. Since the underlying consensus engine is agnostic to the application, the consensus engine accepts only transactions in the form of raw bytes.
  • The TxEncoder object performs the encoding.
  • The TxDecoder object performs the decoding.
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
}
A standard implementation of both these objects can be found in the auth/tx module:
package tx

import (

	"fmt"
    "google.golang.org/protobuf/encoding/protowire"
    "github.com/cosmos/cosmos-sdk/codec"
    "github.com/cosmos/cosmos-sdk/codec/unknownproto"
	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
    "github.com/cosmos/cosmos-sdk/types/tx"
)

/ DefaultTxDecoder returns a default protobuf TxDecoder using the provided Marshaler.
func DefaultTxDecoder(cdc codec.ProtoCodecMarshaler)

sdk.TxDecoder {
    return func(txBytes []byte) (sdk.Tx, error) {
		/ Make sure txBytes follow ADR-027.
    err := rejectNonADR027TxRaw(txBytes)
    if err != nil {
    return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error())
}

var raw tx.TxRaw

		/ reject all unknown proto fields in the root TxRaw
		err = unknownproto.RejectUnknownFieldsStrict(txBytes, &raw, cdc.InterfaceRegistry())
    if err != nil {
    return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error())
}

err = cdc.Unmarshal(txBytes, &raw)
    if err != nil {
    return nil, err
}

var body tx.TxBody

		/ allow non-critical unknown fields in TxBody
		txBodyHasUnknownNonCriticals, err := unknownproto.RejectUnknownFields(raw.BodyBytes, &body, true, cdc.InterfaceRegistry())
    if err != nil {
    return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error())
}

err = cdc.Unmarshal(raw.BodyBytes, &body)
    if err != nil {
    return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error())
}

var authInfo tx.AuthInfo

		/ reject all unknown proto fields in AuthInfo
		err = unknownproto.RejectUnknownFieldsStrict(raw.AuthInfoBytes, &authInfo, cdc.InterfaceRegistry())
    if err != nil {
    return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error())
}

err = cdc.Unmarshal(raw.AuthInfoBytes, &authInfo)
    if err != nil {
    return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error())
}
    theTx := &tx.Tx{
    Body:       &body,
    AuthInfo:   &authInfo,
    Signatures: raw.Signatures,
}

return &wrapper{
    tx:                           theTx,
			bodyBz:                       raw.BodyBytes,
			authInfoBz:                   raw.AuthInfoBytes,
			txBodyHasUnknownNonCriticals: txBodyHasUnknownNonCriticals,
}, nil
}
}

/ DefaultJSONTxDecoder returns a default protobuf JSON TxDecoder using the provided Marshaler.
func DefaultJSONTxDecoder(cdc codec.ProtoCodecMarshaler)

sdk.TxDecoder {
    return func(txBytes []byte) (sdk.Tx, error) {
    var theTx tx.Tx
    err := cdc.UnmarshalJSON(txBytes, &theTx)
    if err != nil {
    return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error())
}

return &wrapper{
    tx: &theTx,
}, nil
}
}

/ rejectNonADR027TxRaw rejects txBytes that do not follow ADR-027. This is NOT
/ a generic ADR-027 checker, it only applies decoding TxRaw. Specifically, it
/ only checks that:
/ - field numbers are in ascending order (1, 2, and potentially multiple 3s),
/ - and varints are as short as possible.
/ All other ADR-027 edge cases (e.g. default values)

are not applicable with
/ TxRaw.
func rejectNonADR027TxRaw(txBytes []byte)

error {
	/ Make sure all fields are ordered in ascending order with this variable.
    prevTagNum := protowire.Number(0)
    for len(txBytes) > 0 {
    tagNum, wireType, m := protowire.ConsumeTag(txBytes)
    if m < 0 {
    return fmt.Errorf("invalid length; %w", protowire.ParseError(m))
}
		/ TxRaw only has bytes fields.
    if wireType != protowire.BytesType {
    return fmt.Errorf("expected %d wire type, got %d", protowire.BytesType, wireType)
}
		/ Make sure fields are ordered in ascending order.
    if tagNum < prevTagNum {
    return fmt.Errorf("txRaw must follow ADR-027, got tagNum %d after tagNum %d", tagNum, prevTagNum)
}

prevTagNum = tagNum

		/ All 3 fields of TxRaw have wireType == 2, so their next component
		/ is a varint, so we can safely call ConsumeVarint here.
		/ Byte structure: <varint of bytes length><bytes sequence>
		/ Inner  fields are verified in `DefaultTxDecoder`
		lengthPrefix, m := protowire.ConsumeVarint(txBytes[m:])
    if m < 0 {
    return fmt.Errorf("invalid length; %w", protowire.ParseError(m))
}
		/ We make sure that this varint is as short as possible.
    n := varintMinLength(lengthPrefix)
    if n != m {
    return fmt.Errorf("length prefix varint for tagNum %d is not as short as possible, read %d, only need %d", tagNum, m, n)
}

		/ Skip over the bytes that store fieldNumber and wireType bytes.
		_, _, m = protowire.ConsumeField(txBytes)
    if m < 0 {
    return fmt.Errorf("invalid length; %w", protowire.ParseError(m))
}

txBytes = txBytes[m:]
}

return nil
}

/ varintMinLength returns the minimum number of bytes necessary to encode an
/ uint using varint encoding.
func varintMinLength(n uint64)

int {
    switch {
	/ Note: 1<<N == 2**N.
    case n < 1<<(7):
		return 1
    case n < 1<<(7*2):
		return 2
    case n < 1<<(7*3):
		return 3
    case n < 1<<(7*4):
		return 4
    case n < 1<<(7*5):
		return 5
    case n < 1<<(7*6):
		return 6
    case n < 1<<(7*7):
		return 7
    case n < 1<<(7*8):
		return 8
    case n < 1<<(7*9):
		return 9
	default:
		return 10
}
}
package tx

import (

	"fmt"
    "github.com/cosmos/gogoproto/proto"
    "github.com/cosmos/cosmos-sdk/codec"
	sdk "github.com/cosmos/cosmos-sdk/types"
	txtypes "github.com/cosmos/cosmos-sdk/types/tx"
)

/ DefaultTxEncoder returns a default protobuf TxEncoder using the provided Marshaler
func DefaultTxEncoder()

sdk.TxEncoder {
    return func(tx sdk.Tx) ([]byte, error) {
    txWrapper, ok := tx.(*wrapper)
    if !ok {
    return nil, fmt.Errorf("expected %T, got %T", &wrapper{
}, tx)
}
    raw := &txtypes.TxRaw{
    BodyBytes:     txWrapper.getBodyBytes(),
    AuthInfoBytes: txWrapper.getAuthInfoBytes(),
    Signatures:    txWrapper.tx.Signatures,
}

return proto.Marshal(raw)
}
}

/ DefaultJSONTxEncoder returns a default protobuf JSON TxEncoder using the provided Marshaler.
func DefaultJSONTxEncoder(cdc codec.ProtoCodecMarshaler)

sdk.TxEncoder {
    return func(tx sdk.Tx) ([]byte, error) {
    txWrapper, ok := tx.(*wrapper)
    if ok {
    return cdc.MarshalJSON(txWrapper.tx)
}

protoTx, ok := tx.(*txtypes.Tx)
    if ok {
    return cdc.MarshalJSON(protoTx)
}

return nil, fmt.Errorf("expected %T, got %T", &wrapper{
}, tx)
}
}
See ADR-020 for details of how a transaction is encoded.

Interface Encoding and Usage of Any

The Protobuf DSL is strongly typed, which can make inserting variable-typed fields difficult. Imagine we want to create a Profile protobuf message that serves as a wrapper over an account:
message Profile {
  / account is the account associated to a profile.
  cosmos.auth.v1beta1.BaseAccount account = 1;
  / bio is a short description of the account.
  string bio = 4;
}
In this Profile example, we hardcoded account as a BaseAccount. However, there are several other types of user accounts related to vesting, such as BaseVestingAccount or ContinuousVestingAccount. All of these accounts are different, but they all implement the AccountI interface. How would you create a Profile that allows all these types of accounts with an account field that accepts an AccountI interface?
package types

import (

	"bytes"
    "encoding/json"
    "errors"
    "fmt"
    "strings"
    "github.com/cosmos/gogoproto/proto"
    "github.com/tendermint/tendermint/crypto"
    "sigs.k8s.io/yaml"
    "github.com/cosmos/cosmos-sdk/codec"
	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
	cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
	sdk "github.com/cosmos/cosmos-sdk/types"
)

var (
	_ AccountI                           = (*BaseAccount)(nil)
	_ GenesisAccount                     = (*BaseAccount)(nil)
	_ codectypes.UnpackInterfacesMessage = (*BaseAccount)(nil)
	_ GenesisAccount                     = (*ModuleAccount)(nil)
	_ ModuleAccountI                     = (*ModuleAccount)(nil)
)

/ NewBaseAccount creates a new BaseAccount object
/
/nolint:interfacer
func NewBaseAccount(address sdk.AccAddress, pubKey cryptotypes.PubKey, accountNumber, sequence uint64) *BaseAccount {
    acc := &BaseAccount{
    Address:       address.String(),
    AccountNumber: accountNumber,
    Sequence:      sequence,
}
    err := acc.SetPubKey(pubKey)
    if err != nil {
    panic(err)
}

return acc
}

/ ProtoBaseAccount - a prototype function for BaseAccount
func ProtoBaseAccount()

AccountI {
    return &BaseAccount{
}
}

/ NewBaseAccountWithAddress - returns a new base account with a given address
/ leaving AccountNumber and Sequence to zero.
func NewBaseAccountWithAddress(addr sdk.AccAddress) *BaseAccount {
    return &BaseAccount{
    Address: addr.String(),
}
}

/ GetAddress - Implements sdk.AccountI.
func (acc BaseAccount)

GetAddress()

sdk.AccAddress {
    addr, _ := sdk.AccAddressFromBech32(acc.Address)

return addr
}

/ SetAddress - Implements sdk.AccountI.
func (acc *BaseAccount)

SetAddress(addr sdk.AccAddress)

error {
    if len(acc.Address) != 0 {
    return errors.New("cannot override BaseAccount address")
}

acc.Address = addr.String()

return nil
}

/ GetPubKey - Implements sdk.AccountI.
func (acc BaseAccount)

GetPubKey() (pk cryptotypes.PubKey) {
    if acc.PubKey == nil {
    return nil
}

content, ok := acc.PubKey.GetCachedValue().(cryptotypes.PubKey)
    if !ok {
    return nil
}

return content
}

/ SetPubKey - Implements sdk.AccountI.
func (acc *BaseAccount)

SetPubKey(pubKey cryptotypes.PubKey)

error {
    if pubKey == nil {
    acc.PubKey = nil
		return nil
}

any, err := codectypes.NewAnyWithValue(pubKey)
    if err == nil {
    acc.PubKey = any
}

return err
}

/ GetAccountNumber - Implements AccountI
func (acc BaseAccount)

GetAccountNumber()

uint64 {
    return acc.AccountNumber
}

/ SetAccountNumber - Implements AccountI
func (acc *BaseAccount)

SetAccountNumber(accNumber uint64)

error {
    acc.AccountNumber = accNumber
	return nil
}

/ GetSequence - Implements sdk.AccountI.
func (acc BaseAccount)

GetSequence()

uint64 {
    return acc.Sequence
}

/ SetSequence - Implements sdk.AccountI.
func (acc *BaseAccount)

SetSequence(seq uint64)

error {
    acc.Sequence = seq
	return nil
}

/ Validate checks for errors on the account fields
func (acc BaseAccount)

Validate()

error {
    if acc.Address == "" || acc.PubKey == nil {
    return nil
}

accAddr, err := sdk.AccAddressFromBech32(acc.Address)
    if err != nil {
    return err
}
    if !bytes.Equal(acc.GetPubKey().Address().Bytes(), accAddr.Bytes()) {
    return errors.New("account address and pubkey address do not match")
}

return nil
}

/ MarshalYAML returns the YAML representation of an account.
func (acc BaseAccount)

MarshalYAML() (interface{
}, error) {
    registry := codectypes.NewInterfaceRegistry()

cryptocodec.RegisterInterfaces(registry)

bz, err := codec.MarshalYAML(codec.NewProtoCodec(registry), &acc)
    if err != nil {
    return nil, err
}

return string(bz), err
}

/ UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (acc BaseAccount)

UnpackInterfaces(unpacker codectypes.AnyUnpacker)

error {
    if acc.PubKey == nil {
    return nil
}

var pubKey cryptotypes.PubKey
	return unpacker.UnpackAny(acc.PubKey, &pubKey)
}

/ NewModuleAddressOrAddress gets an input string and returns an AccAddress.
/ If the input is a valid address, it returns the address.
/ If the input is a module name, it returns the module address.
func NewModuleAddressOrBech32Address(input string)

sdk.AccAddress {
    if addr, err := sdk.AccAddressFromBech32(input); err == nil {
    return addr
}

return NewModuleAddress(input)
}

/ NewModuleAddress creates an AccAddress from the hash of the module's name
func NewModuleAddress(name string)

sdk.AccAddress {
    return sdk.AccAddress(crypto.AddressHash([]byte(name)))
}

/ NewEmptyModuleAccount creates a empty ModuleAccount from a string
func NewEmptyModuleAccount(name string, permissions ...string) *ModuleAccount {
    moduleAddress := NewModuleAddress(name)
    baseAcc := NewBaseAccountWithAddress(moduleAddress)
    if err := validatePermissions(permissions...); err != nil {
    panic(err)
}

return &ModuleAccount{
    BaseAccount: baseAcc,
    Name:        name,
    Permissions: permissions,
}
}

/ NewModuleAccount creates a new ModuleAccount instance
func NewModuleAccount(ba *BaseAccount, name string, permissions ...string) *ModuleAccount {
    if err := validatePermissions(permissions...); err != nil {
    panic(err)
}

return &ModuleAccount{
    BaseAccount: ba,
    Name:        name,
    Permissions: permissions,
}
}

/ HasPermission returns whether or not the module account has permission.
func (ma ModuleAccount)

HasPermission(permission string)

bool {
    for _, perm := range ma.Permissions {
    if perm == permission {
    return true
}

}

return false
}

/ GetName returns the name of the holder's module
func (ma ModuleAccount)

GetName()

string {
    return ma.Name
}

/ GetPermissions returns permissions granted to the module account
func (ma ModuleAccount)

GetPermissions() []string {
    return ma.Permissions
}

/ SetPubKey - Implements AccountI
func (ma ModuleAccount)

SetPubKey(pubKey cryptotypes.PubKey)

error {
    return fmt.Errorf("not supported for module accounts")
}

/ Validate checks for errors on the account fields
func (ma ModuleAccount)

Validate()

error {
    if strings.TrimSpace(ma.Name) == "" {
    return errors.New("module account name cannot be blank")
}
    if ma.Address != sdk.AccAddress(crypto.AddressHash([]byte(ma.Name))).String() {
    return fmt.Errorf("address %s cannot be derived from the module name '%s'", ma.Address, ma.Name)
}

return ma.BaseAccount.Validate()
}

type moduleAccountPretty struct {
    Address       sdk.AccAddress `json:"address"`
	PubKey        string         `json:"public_key"`
	AccountNumber uint64         `json:"account_number"`
	Sequence      uint64         `json:"sequence"`
	Name          string         `json:"name"`
	Permissions   []string       `json:"permissions"`
}

/ MarshalYAML returns the YAML representation of a ModuleAccount.
func (ma ModuleAccount)

MarshalYAML() (interface{
}, error) {
    accAddr, err := sdk.AccAddressFromBech32(ma.Address)
    if err != nil {
    return nil, err
}

bs, err := yaml.Marshal(moduleAccountPretty{
    Address:       accAddr,
    PubKey:        "",
    AccountNumber: ma.AccountNumber,
    Sequence:      ma.Sequence,
    Name:          ma.Name,
    Permissions:   ma.Permissions,
})
    if err != nil {
    return nil, err
}

return string(bs), nil
}

/ MarshalJSON returns the JSON representation of a ModuleAccount.
func (ma ModuleAccount)

MarshalJSON() ([]byte, error) {
    accAddr, err := sdk.AccAddressFromBech32(ma.Address)
    if err != nil {
    return nil, err
}

return json.Marshal(moduleAccountPretty{
    Address:       accAddr,
    PubKey:        "",
    AccountNumber: ma.AccountNumber,
    Sequence:      ma.Sequence,
    Name:          ma.Name,
    Permissions:   ma.Permissions,
})
}

/ UnmarshalJSON unmarshals raw JSON bytes into a ModuleAccount.
func (ma *ModuleAccount)

UnmarshalJSON(bz []byte)

error {
    var alias moduleAccountPretty
    if err := json.Unmarshal(bz, &alias); err != nil {
    return err
}

ma.BaseAccount = NewBaseAccount(alias.Address, nil, alias.AccountNumber, alias.Sequence)

ma.Name = alias.Name
	ma.Permissions = alias.Permissions

	return nil
}

/ AccountI is an interface used to store coins at a given address within state.
/ It presumes a notion of sequence numbers for replay protection,
/ a notion of account numbers for replay protection for previously pruned accounts,
/ and a pubkey for authentication purposes.
/
/ Many complex conditions can be used in the concrete struct which implements AccountI.
type AccountI interface {
    proto.Message

	GetAddress()

sdk.AccAddress
	SetAddress(sdk.AccAddress)

error / errors if already set.

	GetPubKey()

cryptotypes.PubKey / can return nil.
	SetPubKey(cryptotypes.PubKey)

error

	GetAccountNumber()

uint64
	SetAccountNumber(uint64)

error

	GetSequence()

uint64
	SetSequence(uint64)

error

	/ Ensure that account implements stringer
	String()

string
}

/ ModuleAccountI defines an account interface for modules that hold tokens in
/ an escrow.
type ModuleAccountI interface {
    AccountI

	GetName()

string
	GetPermissions() []string
	HasPermission(string)

bool
}

/ GenesisAccounts defines a slice of GenesisAccount objects
type GenesisAccounts []GenesisAccount

/ Contains returns true if the given address exists in a slice of GenesisAccount
/ objects.
func (ga GenesisAccounts)

Contains(addr sdk.Address)

bool {
    for _, acc := range ga {
    if acc.GetAddress().Equals(addr) {
    return true
}

}

return false
}

/ GenesisAccount defines a genesis account that embeds an AccountI with validation capabilities.
type GenesisAccount interface {
    AccountI

	Validate()

error
}
In ADR-019, it has been decided to use Anys to encode interfaces in protobuf. An Any contains an arbitrary serialized message as bytes, along with a URL that acts as a globally unique identifier for and resolves to that message’s type. This strategy allows us to pack arbitrary Go types inside protobuf messages. Our new Profile then looks like:
message Profile {
  / account is the account associated to a profile.
  google.protobuf.Any account = 1 [
    (cosmos_proto.accepts_interface) = "cosmos.auth.v1beta1.AccountI"; / Asserts that this field only accepts Go types implementing `AccountI`. It is purely informational for now.
  ];
  / bio is a short description of the account.
  string bio = 4;
}
To add an account inside a profile, we need to “pack” it inside an Any first, using codectypes.NewAnyWithValue:
var myAccount AccountI
myAccount = ... / Can be a BaseAccount, a ContinuousVestingAccount or any struct implementing `AccountI`

/ Pack the account into an Any
accAny, err := codectypes.NewAnyWithValue(myAccount)
    if err != nil {
    return nil, err
}

/ Create a new Profile with the any.
    profile := Profile {
    Account: accAny,
    Bio: "some bio",
}

/ We can then marshal the profile as usual.
bz, err := cdc.Marshal(profile)

jsonBz, err := cdc.MarshalJSON(profile)
To summarize, to encode an interface, you must 1/ pack the interface into an Any and 2/ marshal the Any. For convenience, the Cosmos SDK provides a MarshalInterface method to bundle these two steps. Have a look at a real-life example in the x/auth module. The reverse operation of retrieving the concrete Go type from inside an Any, called “unpacking”, is done with the GetCachedValue() on Any.
profileBz := ... / The proto-encoded bytes of a Profile, e.g. retrieved through gRPC.
var myProfile Profile
/ Unmarshal the bytes into the myProfile struct.
    err := cdc.Unmarshal(profilebz, &myProfile)

/ Let's see the types of the Account field.
fmt.Printf("%T\n", myProfile.Account)                  / Prints "Any"
fmt.Printf("%T\n", myProfile.Account.GetCachedValue()) / Prints "BaseAccount", "ContinuousVestingAccount" or whatever was initially packed in the Any.

/ Get the address of the accountt.
    accAddr := myProfile.Account.GetCachedValue().(AccountI).GetAddress()
It is important to note that for GetCachedValue() to work, Profile (and any other structs embedding Profile) must implement the UnpackInterfaces method:
func (p *Profile)

UnpackInterfaces(unpacker codectypes.AnyUnpacker)

error {
    if p.Account != nil {
    var account AccountI
    return unpacker.UnpackAny(p.Account, &account)
}

return nil
}
The UnpackInterfaces gets called recursively on all structs implementing this method, to allow all Anys to have their GetCachedValue() correctly populated. For more information about interface encoding, and especially on UnpackInterfaces and how the Any’s type_url gets resolved using the InterfaceRegistry, please refer to ADR-019.

Any Encoding in the Cosmos SDK

The above Profile example is a fictive example used for educational purposes. In the Cosmos SDK, we use Any encoding in several places (non-exhaustive list):
  • the cryptotypes.PubKey interface for encoding different types of public keys,
  • the sdk.Msg interface for encoding different Msgs in a transaction,
  • the AccountI interface for encodinig different types of accounts (similar to the above example) in the x/auth query responses,
  • the Evidencei interface for encoding different types of evidences in the x/evidence module,
  • the AuthorizationI interface for encoding different types of x/authz authorizations,
  • the Validator struct that contains information about a validator.
A real-life example of encoding the pubkey as Any inside the Validator struct in x/staking is shown in the following example:
package types

import (

	"bytes"
    "fmt"
    "sort"
    "strings"
    "time"
    "cosmossdk.io/math"
	abci "github.com/tendermint/tendermint/abci/types"
	tmprotocrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"
    "sigs.k8s.io/yaml"
    "github.com/cosmos/cosmos-sdk/codec"
	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
	cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

const (
	/ TODO: Why can't we just have one string description which can be JSON by convention
	MaxMonikerLength         = 70
	MaxIdentityLength        = 3000
	MaxWebsiteLength         = 140
	MaxSecurityContactLength = 140
	MaxDetailsLength         = 280
)

var (
	BondStatusUnspecified = BondStatus_name[int32(Unspecified)]
	BondStatusUnbonded    = BondStatus_name[int32(Unbonded)]
	BondStatusUnbonding   = BondStatus_name[int32(Unbonding)]
	BondStatusBonded      = BondStatus_name[int32(Bonded)]
)

var _ ValidatorI = Validator{
}

/ NewValidator constructs a new Validator
/
/nolint:interfacer
func NewValidator(operator sdk.ValAddress, pubKey cryptotypes.PubKey, description Description) (Validator, error) {
    pkAny, err := codectypes.NewAnyWithValue(pubKey)
    if err != nil {
    return Validator{
}, err
}

return Validator{
    OperatorAddress:         operator.String(),
    ConsensusPubkey:         pkAny,
    Jailed:                  false,
    Status:                  Unbonded,
    Tokens:                  math.ZeroInt(),
    DelegatorShares:         math.LegacyZeroDec(),
    Description:             description,
    UnbondingHeight:         int64(0),
    UnbondingTime:           time.Unix(0, 0).UTC(),
    Commission:              NewCommission(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()),
    MinSelfDelegation:       math.OneInt(),
    UnbondingOnHoldRefCount: 0,
}, nil
}

/ String implements the Stringer interface for a Validator object.
func (v Validator)

String()

string {
    bz, err := codec.ProtoMarshalJSON(&v, nil)
    if err != nil {
    panic(err)
}

out, err := yaml.JSONToYAML(bz)
    if err != nil {
    panic(err)
}

return string(out)
}

/ Validators is a collection of Validator
type Validators []Validator

func (v Validators)

String() (out string) {
    for _, val := range v {
    out += val.String() + "\n"
}

return strings.TrimSpace(out)
}

/ ToSDKValidators -  convenience function convert []Validator to []sdk.ValidatorI
func (v Validators)

ToSDKValidators() (validators []ValidatorI) {
    for _, val := range v {
    validators = append(validators, val)
}

return validators
}

/ Sort Validators sorts validator array in ascending operator address order
func (v Validators)

Sort() {
    sort.Sort(v)
}

/ Implements sort interface
func (v Validators)

Len()

int {
    return len(v)
}

/ Implements sort interface
func (v Validators)

Less(i, j int)

bool {
    return bytes.Compare(v[i].GetOperator().Bytes(), v[j].GetOperator().Bytes()) == -1
}

/ Implements sort interface
func (v Validators)

Swap(i, j int) {
    v[i], v[j] = v[j], v[i]
}

/ ValidatorsByVotingPower implements sort.Interface for []Validator based on
/ the VotingPower and Address fields.
/ The validators are sorted first by their voting power (descending). Secondary index - Address (ascending).
/ Copied from tendermint/types/validator_set.go
type ValidatorsByVotingPower []Validator

func (valz ValidatorsByVotingPower)

Len()

int {
    return len(valz)
}

func (valz ValidatorsByVotingPower)

Less(i, j int, r math.Int)

bool {
    if valz[i].ConsensusPower(r) == valz[j].ConsensusPower(r) {
    addrI, errI := valz[i].GetConsAddr()

addrJ, errJ := valz[j].GetConsAddr()
		/ If either returns error, then return false
    if errI != nil || errJ != nil {
    return false
}

return bytes.Compare(addrI, addrJ) == -1
}

return valz[i].ConsensusPower(r) > valz[j].ConsensusPower(r)
}

func (valz ValidatorsByVotingPower)

Swap(i, j int) {
    valz[i], valz[j] = valz[j], valz[i]
}

/ UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (v Validators)

UnpackInterfaces(c codectypes.AnyUnpacker)

error {
    for i := range v {
    if err := v[i].UnpackInterfaces(c); err != nil {
    return err
}

}

return nil
}

/ return the redelegation
func MustMarshalValidator(cdc codec.BinaryCodec, validator *Validator) []byte {
    return cdc.MustMarshal(validator)
}

/ unmarshal a redelegation from a store value
func MustUnmarshalValidator(cdc codec.BinaryCodec, value []byte)

Validator {
    validator, err := UnmarshalValidator(cdc, value)
    if err != nil {
    panic(err)
}

return validator
}

/ unmarshal a redelegation from a store value
func UnmarshalValidator(cdc codec.BinaryCodec, value []byte) (v Validator, err error) {
    err = cdc.Unmarshal(value, &v)

return v, err
}

/ IsBonded checks if the validator status equals Bonded
func (v Validator)

IsBonded()

bool {
    return v.GetStatus() == Bonded
}

/ IsUnbonded checks if the validator status equals Unbonded
func (v Validator)

IsUnbonded()

bool {
    return v.GetStatus() == Unbonded
}

/ IsUnbonding checks if the validator status equals Unbonding
func (v Validator)

IsUnbonding()

bool {
    return v.GetStatus() == Unbonding
}

/ constant used in flags to indicate that description field should not be updated
const DoNotModifyDesc = "[do-not-modify]"

func NewDescription(moniker, identity, website, securityContact, details string)

Description {
    return Description{
    Moniker:         moniker,
    Identity:        identity,
    Website:         website,
    SecurityContact: securityContact,
    Details:         details,
}
}

/ String implements the Stringer interface for a Description object.
func (d Description)

String()

string {
    out, _ := yaml.Marshal(d)

return string(out)
}

/ UpdateDescription updates the fields of a given description. An error is
/ returned if the resulting description contains an invalid length.
func (d Description)

UpdateDescription(d2 Description) (Description, error) {
    if d2.Moniker == DoNotModifyDesc {
    d2.Moniker = d.Moniker
}
    if d2.Identity == DoNotModifyDesc {
    d2.Identity = d.Identity
}
    if d2.Website == DoNotModifyDesc {
    d2.Website = d.Website
}
    if d2.SecurityContact == DoNotModifyDesc {
    d2.SecurityContact = d.SecurityContact
}
    if d2.Details == DoNotModifyDesc {
    d2.Details = d.Details
}

return NewDescription(
		d2.Moniker,
		d2.Identity,
		d2.Website,
		d2.SecurityContact,
		d2.Details,
	).EnsureLength()
}

/ EnsureLength ensures the length of a validator's description.
func (d Description)

EnsureLength() (Description, error) {
    if len(d.Moniker) > MaxMonikerLength {
    return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid moniker length; got: %d, max: %d", len(d.Moniker), MaxMonikerLength)
}
    if len(d.Identity) > MaxIdentityLength {
    return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid identity length; got: %d, max: %d", len(d.Identity), MaxIdentityLength)
}
    if len(d.Website) > MaxWebsiteLength {
    return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid website length; got: %d, max: %d", len(d.Website), MaxWebsiteLength)
}
    if len(d.SecurityContact) > MaxSecurityContactLength {
    return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid security contact length; got: %d, max: %d", len(d.SecurityContact), MaxSecurityContactLength)
}
    if len(d.Details) > MaxDetailsLength {
    return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid details length; got: %d, max: %d", len(d.Details), MaxDetailsLength)
}

return d, nil
}

/ ABCIValidatorUpdate returns an abci.ValidatorUpdate from a staking validator type
/ with the full validator power
func (v Validator)

ABCIValidatorUpdate(r math.Int)

abci.ValidatorUpdate {
    tmProtoPk, err := v.TmConsPublicKey()
    if err != nil {
    panic(err)
}

return abci.ValidatorUpdate{
    PubKey: tmProtoPk,
    Power:  v.ConsensusPower(r),
}
}

/ ABCIValidatorUpdateZero returns an abci.ValidatorUpdate from a staking validator type
/ with zero power used for validator updates.
func (v Validator)

ABCIValidatorUpdateZero()

abci.ValidatorUpdate {
    tmProtoPk, err := v.TmConsPublicKey()
    if err != nil {
    panic(err)
}

return abci.ValidatorUpdate{
    PubKey: tmProtoPk,
    Power:  0,
}
}

/ SetInitialCommission attempts to set a validator's initial commission. An
/ error is returned if the commission is invalid.
func (v Validator)

SetInitialCommission(commission Commission) (Validator, error) {
    if err := commission.Validate(); err != nil {
    return v, err
}

v.Commission = commission

	return v, nil
}

/ In some situations, the exchange rate becomes invalid, e.g. if
/ Validator loses all tokens due to slashing. In this case,
/ make all future delegations invalid.
func (v Validator)

InvalidExRate()

bool {
    return v.Tokens.IsZero() && v.DelegatorShares.IsPositive()
}

/ calculate the token worth of provided shares
func (v Validator)

TokensFromShares(shares sdk.Dec)

math.LegacyDec {
    return (shares.MulInt(v.Tokens)).Quo(v.DelegatorShares)
}

/ calculate the token worth of provided shares, truncated
func (v Validator)

TokensFromSharesTruncated(shares sdk.Dec)

math.LegacyDec {
    return (shares.MulInt(v.Tokens)).QuoTruncate(v.DelegatorShares)
}

/ TokensFromSharesRoundUp returns the token worth of provided shares, rounded
/ up.
func (v Validator)

TokensFromSharesRoundUp(shares sdk.Dec)

math.LegacyDec {
    return (shares.MulInt(v.Tokens)).QuoRoundUp(v.DelegatorShares)
}

/ SharesFromTokens returns the shares of a delegation given a bond amount. It
/ returns an error if the validator has no tokens.
func (v Validator)

SharesFromTokens(amt math.Int) (sdk.Dec, error) {
    if v.Tokens.IsZero() {
    return math.LegacyZeroDec(), ErrInsufficientShares
}

return v.GetDelegatorShares().MulInt(amt).QuoInt(v.GetTokens()), nil
}

/ SharesFromTokensTruncated returns the truncated shares of a delegation given
/ a bond amount. It returns an error if the validator has no tokens.
func (v Validator)

SharesFromTokensTruncated(amt math.Int) (sdk.Dec, error) {
    if v.Tokens.IsZero() {
    return math.LegacyZeroDec(), ErrInsufficientShares
}

return v.GetDelegatorShares().MulInt(amt).QuoTruncate(sdk.NewDecFromInt(v.GetTokens())), nil
}

/ get the bonded tokens which the validator holds
func (v Validator)

BondedTokens()

math.Int {
    if v.IsBonded() {
    return v.Tokens
}

return math.ZeroInt()
}

/ ConsensusPower gets the consensus-engine power. Aa reduction of 10^6 from
/ validator tokens is applied
func (v Validator)

ConsensusPower(r math.Int)

int64 {
    if v.IsBonded() {
    return v.PotentialConsensusPower(r)
}

return 0
}

/ PotentialConsensusPower returns the potential consensus-engine power.
func (v Validator)

PotentialConsensusPower(r math.Int)

int64 {
    return sdk.TokensToConsensusPower(v.Tokens, r)
}

/ UpdateStatus updates the location of the shares within a validator
/ to reflect the new status
func (v Validator)

UpdateStatus(newStatus BondStatus)

Validator {
    v.Status = newStatus
	return v
}

/ AddTokensFromDel adds tokens to a validator
func (v Validator)

AddTokensFromDel(amount math.Int) (Validator, sdk.Dec) {
	/ calculate the shares to issue
	var issuedShares sdk.Dec
    if v.DelegatorShares.IsZero() {
		/ the first delegation to a validator sets the exchange rate to one
		issuedShares = sdk.NewDecFromInt(amount)
}

else {
    shares, err := v.SharesFromTokens(amount)
    if err != nil {
    panic(err)
}

issuedShares = shares
}

v.Tokens = v.Tokens.Add(amount)

v.DelegatorShares = v.DelegatorShares.Add(issuedShares)

return v, issuedShares
}

/ RemoveTokens removes tokens from a validator
func (v Validator)

RemoveTokens(tokens math.Int)

Validator {
    if tokens.IsNegative() {
    panic(fmt.Sprintf("should not happen: trying to remove negative tokens %v", tokens))
}
    if v.Tokens.LT(tokens) {
    panic(fmt.Sprintf("should not happen: only have %v tokens, trying to remove %v", v.Tokens, tokens))
}

v.Tokens = v.Tokens.Sub(tokens)

return v
}

/ RemoveDelShares removes delegator shares from a validator.
/ NOTE: because token fractions are left in the valiadator,
/
/	the exchange rate of future shares of this validator can increase.
func (v Validator)

RemoveDelShares(delShares sdk.Dec) (Validator, math.Int) {
    remainingShares := v.DelegatorShares.Sub(delShares)

var issuedTokens math.Int
    if remainingShares.IsZero() {
		/ last delegation share gets any trimmings
		issuedTokens = v.Tokens
		v.Tokens = math.ZeroInt()
}

else {
		/ leave excess tokens in the validator
		/ however fully use all the delegator shares
		issuedTokens = v.TokensFromShares(delShares).TruncateInt()

v.Tokens = v.Tokens.Sub(issuedTokens)
    if v.Tokens.IsNegative() {
    panic("attempting to remove more tokens than available in validator")
}

}

v.DelegatorShares = remainingShares

	return v, issuedTokens
}

/ MinEqual defines a more minimum set of equality conditions when comparing two
/ validators.
func (v *Validator)

MinEqual(other *Validator)

bool {
    return v.OperatorAddress == other.OperatorAddress &&
		v.Status == other.Status &&
		v.Tokens.Equal(other.Tokens) &&
		v.DelegatorShares.Equal(other.DelegatorShares) &&
		v.Description.Equal(other.Description) &&
		v.Commission.Equal(other.Commission) &&
		v.Jailed == other.Jailed &&
		v.MinSelfDelegation.Equal(other.MinSelfDelegation) &&
		v.ConsensusPubkey.Equal(other.ConsensusPubkey)
}

/ Equal checks if the receiver equals the parameter
func (v *Validator)

Equal(v2 *Validator)

bool {
    return v.MinEqual(v2) &&
		v.UnbondingHeight == v2.UnbondingHeight &&
		v.UnbondingTime.Equal(v2.UnbondingTime)
}

func (v Validator)

IsJailed()

bool        {
    return v.Jailed
}

func (v Validator)

GetMoniker()

string    {
    return v.Description.Moniker
}

func (v Validator)

GetStatus()

BondStatus {
    return v.Status
}

func (v Validator)

GetOperator()

sdk.ValAddress {
    if v.OperatorAddress == "" {
    return nil
}

addr, err := sdk.ValAddressFromBech32(v.OperatorAddress)
    if err != nil {
    panic(err)
}

return addr
}

/ ConsPubKey returns the validator PubKey as a cryptotypes.PubKey.
func (v Validator)

ConsPubKey() (cryptotypes.PubKey, error) {
    pk, ok := v.ConsensusPubkey.GetCachedValue().(cryptotypes.PubKey)
    if !ok {
    return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expecting cryptotypes.PubKey, got %T", pk)
}

return pk, nil
}

/ TmConsPublicKey casts Validator.ConsensusPubkey to tmprotocrypto.PubKey.
func (v Validator)

TmConsPublicKey() (tmprotocrypto.PublicKey, error) {
    pk, err := v.ConsPubKey()
    if err != nil {
    return tmprotocrypto.PublicKey{
}, err
}

tmPk, err := cryptocodec.ToTmProtoPublicKey(pk)
    if err != nil {
    return tmprotocrypto.PublicKey{
}, err
}

return tmPk, nil
}

/ GetConsAddr extracts Consensus key address
func (v Validator)

GetConsAddr() (sdk.ConsAddress, error) {
    pk, ok := v.ConsensusPubkey.GetCachedValue().(cryptotypes.PubKey)
    if !ok {
    return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expecting cryptotypes.PubKey, got %T", pk)
}

return sdk.ConsAddress(pk.Address()), nil
}

func (v Validator)

GetTokens()

math.Int       {
    return v.Tokens
}

func (v Validator)

GetBondedTokens()

math.Int {
    return v.BondedTokens()
}

func (v Validator)

GetConsensusPower(r math.Int)

int64 {
    return v.ConsensusPower(r)
}

func (v Validator)

GetCommission()

math.LegacyDec      {
    return v.Commission.Rate
}

func (v Validator)

GetMinSelfDelegation()

math.Int     {
    return v.MinSelfDelegation
}

func (v Validator)

GetDelegatorShares()

math.LegacyDec {
    return v.DelegatorShares
}

/ UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (v Validator)

UnpackInterfaces(unpacker codectypes.AnyUnpacker)

error {
    var pk cryptotypes.PubKey
	return unpacker.UnpackAny(v.ConsensusPubkey, &pk)
}

Any’s TypeURL

When packing a protobuf message inside an Any, the message’s type is uniquely defined by its type URL, which is the message’s fully qualified name prefixed by a / (slash) character. In some implementations of Any, like the gogoproto one, there’s generally a resolvable prefix, e.g. type.googleapis.com. However, in the Cosmos SDK, we made the decision to not include such prefix, to have shorter type URLs. The Cosmos SDK’s own Any implementation can be found in github.com/cosmos/cosmos-sdk/codec/types. The Cosmos SDK is also switching away from gogoproto to the official google.golang.org/protobuf (known as the Protobuf API v2). Its default Any implementation also contains the type.googleapis.com prefix. To maintain compatibility with the SDK, the following methods from "google.golang.org/protobuf/types/known/anypb" should not be used:
  • anypb.New
  • anypb.MarshalFrom
  • anypb.Any#MarshalFrom
Instead, the Cosmos SDK provides helper functions in "github.com/cosmos/cosmos-proto/anyutil", which create an official anypb.Any without inserting the prefixes:
  • anyutil.New
  • anyutil.MarshalFrom
For example, to pack a sdk.Msg called internalMsg, use:
import (
- 	"google.golang.org/protobuf/types/known/anypb"
+	"github.com/cosmos/cosmos-proto/anyutil"
)

- anyMsg, err := anypb.New(internalMsg.Message().Interface())
+ anyMsg, err := anyutil.New(internalMsg.Message().Interface())

- fmt.Println(anyMsg.TypeURL) / type.googleapis.com/cosmos.bank.v1beta1.MsgSend
+ fmt.Println(anyMsg.TypeURL) / /cosmos.bank.v1beta1.MsgSend

FAQ

How to create modules using protobuf encoding

Defining module types

Protobuf types can be defined to encode:

Naming and conventions

We encourage developers to follow industry guidelines: Protocol Buffers style guide and Buf, see more details in ADR 023

How to update modules to protobuf encoding

If modules do not contain any interfaces (e.g. Account or Content), then they may simply migrate any existing types that are encoded and persisted via their concrete Amino codec to Protobuf (see 1. for further guidelines) and accept a Marshaler as the codec which is implemented via the ProtoCodec without any further customization. However, if a module type composes an interface, it must wrap it in the sdk.Any (from /types package) type. To do that, a module-level .proto file must use google.protobuf.Any for respective message type interface types. For example, in the x/evidence module defines an Evidence interface, which is used by the MsgSubmitEvidence. The structure definition must use sdk.Any to wrap the evidence file. In the proto file we define it as follows:
/ proto/cosmos/evidence/v1beta1/tx.proto

message MsgSubmitEvidence {
  string              submitter = 1;
  google.protobuf.Any evidence  = 2 [(cosmos_proto.accepts_interface) = "cosmos.evidence.v1beta1.Evidence"];
}
The Cosmos SDK codec.Codec interface provides support methods MarshalInterface and UnmarshalInterface to easy encoding of state to Any. Module should register interfaces using InterfaceRegistry which provides a mechanism for registering interfaces: RegisterInterface(protoName string, iface interface{}, impls ...proto.Message) and implementations: RegisterImplementations(iface interface{}, impls ...proto.Message) that can be safely unpacked from Any, similarly to type registration with Amino:
package types

import (

	"fmt"
    "reflect"
    "github.com/cosmos/gogoproto/jsonpb"
    "github.com/cosmos/gogoproto/proto"
)

/ AnyUnpacker is an interface which allows safely unpacking types packed
/ in Any's against a whitelist of registered types
type AnyUnpacker interface {
	/ UnpackAny unpacks the value in any to the interface pointer passed in as
	/ iface. Note that the type in any must have been registered in the
	/ underlying whitelist registry as a concrete type for that interface
	/ Ex:
	/    var msg sdk.Msg
	/    err := cdc.UnpackAny(any, &msg)
	/    ...
	UnpackAny(any *Any, iface interface{
})

error
}

/ InterfaceRegistry provides a mechanism for registering interfaces and
/ implementations that can be safely unpacked from Any
type InterfaceRegistry interface {
    AnyUnpacker
	jsonpb.AnyResolver

	/ RegisterInterface associates protoName as the public name for the
	/ interface passed in as iface. This is to be used primarily to create
	/ a public facing registry of interface implementations for clients.
	/ protoName should be a well-chosen public facing name that remains stable.
	/ RegisterInterface takes an optional list of impls to be registered
	/ as implementations of iface.
	/
	/ Ex:
	/   registry.RegisterInterface("cosmos.base.v1beta1.Msg", (*sdk.Msg)(nil))

RegisterInterface(protoName string, iface interface{
}, impls ...proto.Message)

	/ RegisterImplementations registers impls as concrete implementations of
	/ the interface iface.
	/
	/ Ex:
	/  registry.RegisterImplementations((*sdk.Msg)(nil), &MsgSend{
}, &MsgMultiSend{
})

RegisterImplementations(iface interface{
}, impls ...proto.Message)

	/ ListAllInterfaces list the type URLs of all registered interfaces.
	ListAllInterfaces() []string

	/ ListImplementations lists the valid type URLs for the given interface name that can be used
	/ for the provided interface type URL.
	ListImplementations(ifaceTypeURL string) []string

	/ EnsureRegistered ensures there is a registered interface for the given concrete type.
	EnsureRegistered(iface interface{
})

error
}

/ UnpackInterfacesMessage is meant to extend protobuf types (which implement
/ proto.Message)

to support a post-deserialization phase which unpacks
/ types packed within Any's using the whitelist provided by AnyUnpacker
type UnpackInterfacesMessage interface {
	/ UnpackInterfaces is implemented in order to unpack values packed within
	/ Any's using the AnyUnpacker. It should generally be implemented as
	/ follows:
	/   func (s *MyStruct)

UnpackInterfaces(unpacker AnyUnpacker)

error {
	/		var x AnyInterface
	/		/ where X is an Any field on MyStruct
	/		err := unpacker.UnpackAny(s.X, &x)
	/		if err != nil {
	/			return nil
	/
}
	/		/ where Y is a field on MyStruct that implements UnpackInterfacesMessage itself
	/		err = s.Y.UnpackInterfaces(unpacker)
	/		if err != nil {
	/			return nil
	/
}
	/		return nil
	/
}

UnpackInterfaces(unpacker AnyUnpacker)

error
}

type interfaceRegistry struct {
    interfaceNames map[string]reflect.Type
	interfaceImpls map[reflect.Type]interfaceMap
	implInterfaces map[reflect.Type]reflect.Type
	typeURLMap     map[string]reflect.Type
}

type interfaceMap = map[string]reflect.Type

/ NewInterfaceRegistry returns a new InterfaceRegistry
func NewInterfaceRegistry()

InterfaceRegistry {
    return &interfaceRegistry{
    interfaceNames: map[string]reflect.Type{
},
		interfaceImpls: map[reflect.Type]interfaceMap{
},
		implInterfaces: map[reflect.Type]reflect.Type{
},
		typeURLMap:     map[string]reflect.Type{
},
}
}

func (registry *interfaceRegistry)

RegisterInterface(protoName string, iface interface{
}, impls ...proto.Message) {
    typ := reflect.TypeOf(iface)
    if typ.Elem().Kind() != reflect.Interface {
    panic(fmt.Errorf("%T is not an interface type", iface))
}

registry.interfaceNames[protoName] = typ
	registry.RegisterImplementations(iface, impls...)
}

/ EnsureRegistered ensures there is a registered interface for the given concrete type.
/
/ Returns an error if not, and nil if so.
func (registry *interfaceRegistry)

EnsureRegistered(impl interface{
})

error {
    if reflect.ValueOf(impl).Kind() != reflect.Ptr {
    return fmt.Errorf("%T is not a pointer", impl)
}
    if _, found := registry.implInterfaces[reflect.TypeOf(impl)]; !found {
    return fmt.Errorf("%T does not have a registered interface", impl)
}

return nil
}

/ RegisterImplementations registers a concrete proto Message which implements
/ the given interface.
/
/ This function PANICs if different concrete types are registered under the
/ same typeURL.
func (registry *interfaceRegistry)

RegisterImplementations(iface interface{
}, impls ...proto.Message) {
    for _, impl := range impls {
    typeURL := "/" + proto.MessageName(impl)

registry.registerImpl(iface, typeURL, impl)
}
}

/ RegisterCustomTypeURL registers a concrete type which implements the given
/ interface under `typeURL`.
/
/ This function PANICs if different concrete types are registered under the
/ same typeURL.
func (registry *interfaceRegistry)

RegisterCustomTypeURL(iface interface{
}, typeURL string, impl proto.Message) {
    registry.registerImpl(iface, typeURL, impl)
}

/ registerImpl registers a concrete type which implements the given
/ interface under `typeURL`.
/
/ This function PANICs if different concrete types are registered under the
/ same typeURL.
func (registry *interfaceRegistry)

registerImpl(iface interface{
}, typeURL string, impl proto.Message) {
    ityp := reflect.TypeOf(iface).Elem()

imap, found := registry.interfaceImpls[ityp]
    if !found {
    imap = map[string]reflect.Type{
}

}
    implType := reflect.TypeOf(impl)
    if !implType.AssignableTo(ityp) {
    panic(fmt.Errorf("type %T doesn't actually implement interface %+v", impl, ityp))
}

	/ Check if we already registered something under the given typeURL. It's
	/ okay to register the same concrete type again, but if we are registering
	/ a new concrete type under the same typeURL, then we throw an error (here,
	/ we panic).
	foundImplType, found := imap[typeURL]
    if found && foundImplType != implType {
    panic(
			fmt.Errorf(
				"concrete type %s has already been registered under typeURL %s, cannot register %s under same typeURL. "+
					"This usually means that there are conflicting modules registering different concrete types "+
					"for a same interface implementation",
				foundImplType,
				typeURL,
				implType,
			),
		)
}

imap[typeURL] = implType
	registry.typeURLMap[typeURL] = implType
	registry.implInterfaces[implType] = ityp
	registry.interfaceImpls[ityp] = imap
}

func (registry *interfaceRegistry)

ListAllInterfaces() []string {
    interfaceNames := registry.interfaceNames
    keys := make([]string, 0, len(interfaceNames))
    for key := range interfaceNames {
    keys = append(keys, key)
}

return keys
}

func (registry *interfaceRegistry)

ListImplementations(ifaceName string) []string {
    typ, ok := registry.interfaceNames[ifaceName]
    if !ok {
    return []string{
}

}

impls, ok := registry.interfaceImpls[typ.Elem()]
    if !ok {
    return []string{
}

}
    keys := make([]string, 0, len(impls))
    for key := range impls {
    keys = append(keys, key)
}

return keys
}

func (registry *interfaceRegistry)

UnpackAny(any *Any, iface interface{
})

error {
	/ here we gracefully handle the case in which `any` itself is `nil`, which may occur in message decoding
    if any == nil {
    return nil
}
    if any.TypeUrl == "" {
		/ if TypeUrl is empty return nil because without it we can't actually unpack anything
		return nil
}
    rv := reflect.ValueOf(iface)
    if rv.Kind() != reflect.Ptr {
    return fmt.Errorf("UnpackAny expects a pointer")
}
    rt := rv.Elem().Type()
    cachedValue := any.cachedValue
    if cachedValue != nil {
    if reflect.TypeOf(cachedValue).AssignableTo(rt) {
    rv.Elem().Set(reflect.ValueOf(cachedValue))

return nil
}

}

imap, found := registry.interfaceImpls[rt]
    if !found {
    return fmt.Errorf("no registered implementations of type %+v", rt)
}

typ, found := imap[any.TypeUrl]
    if !found {
    return fmt.Errorf("no concrete type registered for type URL %s against interface %T", any.TypeUrl, iface)
}

msg, ok := reflect.New(typ.Elem()).Interface().(proto.Message)
    if !ok {
    return fmt.Errorf("can't proto unmarshal %T", msg)
}
    err := proto.Unmarshal(any.Value, msg)
    if err != nil {
    return err
}

err = UnpackInterfaces(msg, registry)
    if err != nil {
    return err
}

rv.Elem().Set(reflect.ValueOf(msg))

any.cachedValue = msg

	return nil
}

/ Resolve returns the proto message given its typeURL. It works with types
/ registered with RegisterInterface/RegisterImplementations, as well as those
/ registered with RegisterWithCustomTypeURL.
func (registry *interfaceRegistry)

Resolve(typeURL string) (proto.Message, error) {
    typ, found := registry.typeURLMap[typeURL]
    if !found {
    return nil, fmt.Errorf("unable to resolve type URL %s", typeURL)
}

msg, ok := reflect.New(typ.Elem()).Interface().(proto.Message)
    if !ok {
    return nil, fmt.Errorf("can't resolve type URL %s", typeURL)
}

return msg, nil
}

/ UnpackInterfaces is a convenience function that calls UnpackInterfaces
/ on x if x implements UnpackInterfacesMessage
func UnpackInterfaces(x interface{
}, unpacker AnyUnpacker)

error {
    if msg, ok := x.(UnpackInterfacesMessage); ok {
    return msg.UnpackInterfaces(unpacker)
}

return nil
}
In addition, an UnpackInterfaces phase should be introduced to deserialization to unpack interfaces before they’re needed. Protobuf types that contain a protobuf Any either directly or via one of their members should implement the UnpackInterfacesMessage interface:
type UnpackInterfacesMessage interface {
    UnpackInterfaces(InterfaceUnpacker)

error
}

Custom Stringer

Using option (gogoproto.goproto_stringer) = false; in a proto message definition leads to unexpected behaviour, like returning wrong output or having missing fields in the output. For that reason a proto Message’s String() must not be customized, and the goproto_stringer option must be avoided. A correct YAML output can be obtained through ProtoJSON, using the JSONToYAML function:
package codec

import (

	"github.com/cosmos/gogoproto/proto"
    "sigs.k8s.io/yaml"
)

/ MarshalYAML marshals toPrint using JSONCodec to leverage specialized MarshalJSON methods
/ (usually related to serialize data with protobuf or amin depending on a configuration).
/ This involves additional roundtrip through JSON.
func MarshalYAML(cdc JSONCodec, toPrint proto.Message) ([]byte, error) {
	/ We are OK with the performance hit of the additional JSON roundtip. MarshalYAML is not
	/ used in any critical parts of the system.
	bz, err := cdc.MarshalJSON(toPrint)
    if err != nil {
    return nil, err
}

return yaml.JSONToYAML(bz)
}
For example:
package types

import (

	"bytes"
    "encoding/json"
    "errors"
    "fmt"
    "strings"
    "github.com/cosmos/gogoproto/proto"
    "github.com/tendermint/tendermint/crypto"
    "sigs.k8s.io/yaml"
    "github.com/cosmos/cosmos-sdk/codec"
	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
	cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
	sdk "github.com/cosmos/cosmos-sdk/types"
)

var (
	_ AccountI                           = (*BaseAccount)(nil)
	_ GenesisAccount                     = (*BaseAccount)(nil)
	_ codectypes.UnpackInterfacesMessage = (*BaseAccount)(nil)
	_ GenesisAccount                     = (*ModuleAccount)(nil)
	_ ModuleAccountI                     = (*ModuleAccount)(nil)
)

/ NewBaseAccount creates a new BaseAccount object
/
/nolint:interfacer
func NewBaseAccount(address sdk.AccAddress, pubKey cryptotypes.PubKey, accountNumber, sequence uint64) *BaseAccount {
    acc := &BaseAccount{
    Address:       address.String(),
    AccountNumber: accountNumber,
    Sequence:      sequence,
}
    err := acc.SetPubKey(pubKey)
    if err != nil {
    panic(err)
}

return acc
}

/ ProtoBaseAccount - a prototype function for BaseAccount
func ProtoBaseAccount()

AccountI {
    return &BaseAccount{
}
}

/ NewBaseAccountWithAddress - returns a new base account with a given address
/ leaving AccountNumber and Sequence to zero.
func NewBaseAccountWithAddress(addr sdk.AccAddress) *BaseAccount {
    return &BaseAccount{
    Address: addr.String(),
}
}

/ GetAddress - Implements sdk.AccountI.
func (acc BaseAccount)

GetAddress()

sdk.AccAddress {
    addr, _ := sdk.AccAddressFromBech32(acc.Address)

return addr
}

/ SetAddress - Implements sdk.AccountI.
func (acc *BaseAccount)

SetAddress(addr sdk.AccAddress)

error {
    if len(acc.Address) != 0 {
    return errors.New("cannot override BaseAccount address")
}

acc.Address = addr.String()

return nil
}

/ GetPubKey - Implements sdk.AccountI.
func (acc BaseAccount)

GetPubKey() (pk cryptotypes.PubKey) {
    if acc.PubKey == nil {
    return nil
}

content, ok := acc.PubKey.GetCachedValue().(cryptotypes.PubKey)
    if !ok {
    return nil
}

return content
}

/ SetPubKey - Implements sdk.AccountI.
func (acc *BaseAccount)

SetPubKey(pubKey cryptotypes.PubKey)

error {
    if pubKey == nil {
    acc.PubKey = nil
		return nil
}

any, err := codectypes.NewAnyWithValue(pubKey)
    if err == nil {
    acc.PubKey = any
}

return err
}

/ GetAccountNumber - Implements AccountI
func (acc BaseAccount)

GetAccountNumber()

uint64 {
    return acc.AccountNumber
}

/ SetAccountNumber - Implements AccountI
func (acc *BaseAccount)

SetAccountNumber(accNumber uint64)

error {
    acc.AccountNumber = accNumber
	return nil
}

/ GetSequence - Implements sdk.AccountI.
func (acc BaseAccount)

GetSequence()

uint64 {
    return acc.Sequence
}

/ SetSequence - Implements sdk.AccountI.
func (acc *BaseAccount)

SetSequence(seq uint64)

error {
    acc.Sequence = seq
	return nil
}

/ Validate checks for errors on the account fields
func (acc BaseAccount)

Validate()

error {
    if acc.Address == "" || acc.PubKey == nil {
    return nil
}

accAddr, err := sdk.AccAddressFromBech32(acc.Address)
    if err != nil {
    return err
}
    if !bytes.Equal(acc.GetPubKey().Address().Bytes(), accAddr.Bytes()) {
    return errors.New("account address and pubkey address do not match")
}

return nil
}

/ MarshalYAML returns the YAML representation of an account.
func (acc BaseAccount)

MarshalYAML() (interface{
}, error) {
    registry := codectypes.NewInterfaceRegistry()

cryptocodec.RegisterInterfaces(registry)

bz, err := codec.MarshalYAML(codec.NewProtoCodec(registry), &acc)
    if err != nil {
    return nil, err
}

return string(bz), err
}

/ UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (acc BaseAccount)

UnpackInterfaces(unpacker codectypes.AnyUnpacker)

error {
    if acc.PubKey == nil {
    return nil
}

var pubKey cryptotypes.PubKey
	return unpacker.UnpackAny(acc.PubKey, &pubKey)
}

/ NewModuleAddressOrAddress gets an input string and returns an AccAddress.
/ If the input is a valid address, it returns the address.
/ If the input is a module name, it returns the module address.
func NewModuleAddressOrBech32Address(input string)

sdk.AccAddress {
    if addr, err := sdk.AccAddressFromBech32(input); err == nil {
    return addr
}

return NewModuleAddress(input)
}

/ NewModuleAddress creates an AccAddress from the hash of the module's name
func NewModuleAddress(name string)

sdk.AccAddress {
    return sdk.AccAddress(crypto.AddressHash([]byte(name)))
}

/ NewEmptyModuleAccount creates a empty ModuleAccount from a string
func NewEmptyModuleAccount(name string, permissions ...string) *ModuleAccount {
    moduleAddress := NewModuleAddress(name)
    baseAcc := NewBaseAccountWithAddress(moduleAddress)
    if err := validatePermissions(permissions...); err != nil {
    panic(err)
}

return &ModuleAccount{
    BaseAccount: baseAcc,
    Name:        name,
    Permissions: permissions,
}
}

/ NewModuleAccount creates a new ModuleAccount instance
func NewModuleAccount(ba *BaseAccount, name string, permissions ...string) *ModuleAccount {
    if err := validatePermissions(permissions...); err != nil {
    panic(err)
}

return &ModuleAccount{
    BaseAccount: ba,
    Name:        name,
    Permissions: permissions,
}
}

/ HasPermission returns whether or not the module account has permission.
func (ma ModuleAccount)

HasPermission(permission string)

bool {
    for _, perm := range ma.Permissions {
    if perm == permission {
    return true
}

}

return false
}

/ GetName returns the name of the holder's module
func (ma ModuleAccount)

GetName()

string {
    return ma.Name
}

/ GetPermissions returns permissions granted to the module account
func (ma ModuleAccount)

GetPermissions() []string {
    return ma.Permissions
}

/ SetPubKey - Implements AccountI
func (ma ModuleAccount)

SetPubKey(pubKey cryptotypes.PubKey)

error {
    return fmt.Errorf("not supported for module accounts")
}

/ Validate checks for errors on the account fields
func (ma ModuleAccount)

Validate()

error {
    if strings.TrimSpace(ma.Name) == "" {
    return errors.New("module account name cannot be blank")
}
    if ma.Address != sdk.AccAddress(crypto.AddressHash([]byte(ma.Name))).String() {
    return fmt.Errorf("address %s cannot be derived from the module name '%s'", ma.Address, ma.Name)
}

return ma.BaseAccount.Validate()
}

type moduleAccountPretty struct {
    Address       sdk.AccAddress `json:"address"`
	PubKey        string         `json:"public_key"`
	AccountNumber uint64         `json:"account_number"`
	Sequence      uint64         `json:"sequence"`
	Name          string         `json:"name"`
	Permissions   []string       `json:"permissions"`
}

/ MarshalYAML returns the YAML representation of a ModuleAccount.
func (ma ModuleAccount)

MarshalYAML() (interface{
}, error) {
    accAddr, err := sdk.AccAddressFromBech32(ma.Address)
    if err != nil {
    return nil, err
}

bs, err := yaml.Marshal(moduleAccountPretty{
    Address:       accAddr,
    PubKey:        "",
    AccountNumber: ma.AccountNumber,
    Sequence:      ma.Sequence,
    Name:          ma.Name,
    Permissions:   ma.Permissions,
})
    if err != nil {
    return nil, err
}

return string(bs), nil
}

/ MarshalJSON returns the JSON representation of a ModuleAccount.
func (ma ModuleAccount)

MarshalJSON() ([]byte, error) {
    accAddr, err := sdk.AccAddressFromBech32(ma.Address)
    if err != nil {
    return nil, err
}

return json.Marshal(moduleAccountPretty{
    Address:       accAddr,
    PubKey:        "",
    AccountNumber: ma.AccountNumber,
    Sequence:      ma.Sequence,
    Name:          ma.Name,
    Permissions:   ma.Permissions,
})
}

/ UnmarshalJSON unmarshals raw JSON bytes into a ModuleAccount.
func (ma *ModuleAccount)

UnmarshalJSON(bz []byte)

error {
    var alias moduleAccountPretty
    if err := json.Unmarshal(bz, &alias); err != nil {
    return err
}

ma.BaseAccount = NewBaseAccount(alias.Address, nil, alias.AccountNumber, alias.Sequence)

ma.Name = alias.Name
	ma.Permissions = alias.Permissions

	return nil
}

/ AccountI is an interface used to store coins at a given address within state.
/ It presumes a notion of sequence numbers for replay protection,
/ a notion of account numbers for replay protection for previously pruned accounts,
/ and a pubkey for authentication purposes.
/
/ Many complex conditions can be used in the concrete struct which implements AccountI.
type AccountI interface {
    proto.Message

	GetAddress()

sdk.AccAddress
	SetAddress(sdk.AccAddress)

error / errors if already set.

	GetPubKey()

cryptotypes.PubKey / can return nil.
	SetPubKey(cryptotypes.PubKey)

error

	GetAccountNumber()

uint64
	SetAccountNumber(uint64)

error

	GetSequence()

uint64
	SetSequence(uint64)

error

	/ Ensure that account implements stringer
	String()

string
}

/ ModuleAccountI defines an account interface for modules that hold tokens in
/ an escrow.
type ModuleAccountI interface {
    AccountI

	GetName()

string
	GetPermissions() []string
	HasPermission(string)

bool
}

/ GenesisAccounts defines a slice of GenesisAccount objects
type GenesisAccounts []GenesisAccount

/ Contains returns true if the given address exists in a slice of GenesisAccount
/ objects.
func (ga GenesisAccounts)

Contains(addr sdk.Address)

bool {
    for _, acc := range ga {
    if acc.GetAddress().Equals(addr) {
    return true
}

}

return false
}

/ GenesisAccount defines a genesis account that embeds an AccountI with validation capabilities.
type GenesisAccount interface {
    AccountI

	Validate()

error
}