Message
In Everscale, smart-contracts communicate between each other and with non-blockchain applications by means of an asynchronous message passing.
Technically, a message is a data structure encoding one of the following:
- desired function call at a destination smart-contract, optionally attaching some coins.
- event log record to signal external observers about some significant state being reached
A message consists of: header
and body
. The header contains the information about the sender, receiver, value as well as the information required by the validator to apply the message to the block. The message body, in turn, comprises the payload of VM instructions that are necessary for the execution of the smart contract.
There are three types of messages on Everscale:
Inbound external message - a message sent from outside onto the Everscale blockchain. It can be sent by any actor outside the blockchain. So-called messages from nowhere. Inbound external messages initiate changes to the blockchain’s state. It is important to mention that external messages can not be value-bearing. They can only declare intent to transfer value to another account.
Internal message: a message sent from one contract to another. Like an inbound external message, it updates the blockchain's state. Only internal messages can be value-bearing.
Outbound external message: aka event - a message that can be emitted by a smart contract. Off-chain participants can subscribe to events within the Everscale network and receive them.
pub struct Message {
header: CommonMsgInfo,
init: Option<StateInit>,
body: Option<SliceData>,
body_to_ref: Option<bool>,
init_to_ref: Option<bool>,
}
The last two fields body_to_ref
and init_to_ref
are used only for serialization purpose, hence not considered in this document.
Message Header
Any message has a message header: a data-structure defining, among other things, the message type and source and destination addresses.
The message header defines its type. It is described by the following enumeration:
pub enum CommonMsgInfo {
IntMsgInfo(InternalMessageHeader),
ExtInMsgInfo(ExternalInboundMessageHeader),
ExtOutMsgInfo(ExtOutMessageHeader),
}
Internal Message
Within Everscale blockchain, smart-contracts communicate with each other by exchanging messages. Messages sent by smart-contracts are called internal.
They are opposed to external messages that are sent by off-chain applications to smart-contracts.
The message header of an internal message is defined as follows:
pub struct InternalMessageHeader {
pub ihr_disabled: bool,
pub bounce: bool,
pub bounced: bool,
pub src: MsgAddressIntOrNone,
pub dst: MsgAddressInt,
pub value: CurrencyCollection,
pub ihr_fee: Grams,
pub fwd_fee: Grams,
pub created_lt: u64,
pub created_at: UnixTime32,
}
InternalMessageHeader fields
Field | Description |
---|---|
ihr_disabled | IHR routing protocol disabled, always true |
bounce | Should the answer message be generated in case of an error |
bounced | Is this message was auto-generated by error handling |
src | Message source address |
dst | Message destination address |
value | Amount of coins attached to the message |
ihr_fee | IHR fee amount, always 0 |
fwd_fee | Message delivery fee amount |
created_lt | Message creation logic time |
created_at | Message creation time in Epoch |
Some clarifications:
bounced
flag is set when the message itself was auto-generated as a result of an error. If the message with bounced flag leads to an error itself, the next bounced message will not be generated.value
is measured in Nano Evers ()reated_lt
is a monotonically increasing counter, thanks to this field, each new generated message is unique, even if the message payload is the same. The message creation logic time is also used to guarantee order of delivery. We do not dive deep into this question, because it is protocol-level details.
External Message
External messages are created outside of the blockchain and get sent through specially distinguished validator nodes called DApp Servers2.
External message header is defined as follows:
pub struct ExternalInboundMessageHeader {
pub src: MsgAddressExt,
pub dst: MsgAddressInt,
pub import_fee: Grams,
}
- Fields
src
anddst
are source and destination addresses. - Field
import_fee
should have been the value paid to the validator for processing an external message. But in the current node, this field is not used. Hence, the fee is not paid. We reported this issue to the developers. - The source address for an external message is always set to
AddrNone
.
pub enum MsgAddressExt {
AddrNone,
AddrExtern(MsgAddrExt),
}
The second variant AddrExtern
is not supported currently.
Events
Event can be considered as a log record. It is used to signal external observers of reaching some significant state in a smart-contract.
Usually, observers are external non-blockchain applications that constantly monitor blockchain state3. Other smart-contracts are not able to catch events.
pub struct ExtOutMessageHeader {
pub src: MsgAddressIntOrNone,
pub dst: MsgAddressExt,
pub created_lt: u64,
pub created_at: UnixTime32,
}
pub enum MsgAddressIntOrNone {
None,
Some(MsgAddressInt)
}
- Transaction Executor automatically assigns the source address
src
to be equal to the smart-contract address emitting the event. - The destination address
dst
may contain any identifier. It is included for easier integration with off-chain applications, i.e. applications can monitor emitted events based on their destination address, and consume only those events destined to their custom identifier. - Fields
created_lt
,created_at
defines the logical creation time and epoch creation time.