2.0 KiB
Messages
Messages are the primary inputs to application state machines.
Developers can create messages containing arbitrary information by
implementing the Msg
interface:
type Msg interface {
// Return the message type.
// Must be alphanumeric or empty.
Type() string
// Get the canonical byte representation of the Msg.
GetSignBytes() []byte
// ValidateBasic does a simple validation check that
// doesn't require access to any other information.
ValidateBasic() error
// Signers 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() []Address
}
Messages must specify their type via the Type()
method. The type should
correspond to the messages handler, so there can be many messages with the same
type.
Messages must also specify how they are to be authenticated. The GetSigners()
method return a list of SDK addresses that must sign the message, while the
GetSignBytes()
method returns the bytes that must be signed for a signature
to be valid.
Addresses in the SDK are arbitrary byte arrays that are hex-encoded when displayed as a string or rendered in JSON.
Messages can specify basic self-consistency checks using the ValidateBasic()
method to enforce that message contents are well formed before any actual logic
begins.
For instance, the Basecoin
message types are defined in x/bank/tx.go
:
// Send coins from many inputs to many outputs.
type MsgSend struct {
Inputs []Input `json:"inputs"`
Outputs []Output `json:"outputs"`
}
// Issue new coins to many outputs.
type MsgIssue struct {
Banker sdk.Address `json:"banker"`
Outputs []Output `json:"outputs"`
}
Each specifies the addresses that must sign the message:
func (msg MsgSend) GetSigners() []sdk.Address {
addrs := make([]sdk.Address, len(msg.Inputs))
for i, in := range msg.Inputs {
addrs[i] = in.Address
}
return addrs
}
func (msg MsgIssue) GetSigners() []sdk.Address {
return []sdk.Address{msg.Banker}
}