Схемы сообщений TL-B
Эта страница переведена сообществом на русский язык, но нуждается в улучшениях. Если вы хотите принять участие в переводе свяжитесь с @alexgton.
В этом разделе подробное объяснение схем TL-B для сообщений.
Сообщение TL-B
TL-B
Основное сообщение Схема TL-B объявлена как комбинация нескольких вложенных структур
message$_ {X:Type} info:CommonMsgInfo
init:(Maybe (Either StateInit ^StateInit))
body:(Either X ^X) = Message X;
message$_ {X:Type} info:CommonMsgInfoRelaxed
init:(Maybe (Either StateInit ^StateInit))
body:(Either X ^X) = MessageRelaxed X;
_ (Message Any) = MessageAny;
Здесь Message X
- это общая структура сообщения, MessageRelaxed X
дополнительный тип с телом CommonMsgInfoRelaxed, а Message Any
- это объединение обоих.
Структура сообщения унифицирована с X:Type, то есть является ячейкой.
Согласно TL-B мы можем объединить все данные в одной ячейке (если она уместится в 1023 бита) или использовать ссылки, объявленные с помощью символа ^
.
Сериализованное Message X
помещается в список действий с помощью метода FunC send_raw_message(), затем смарт-контракт выполняет это действие и отправляет сообщение.
Определение явной сериализации
Для построения допустимых двоичных данных в соответствии со структурой TL-B мы должны выполнить сериализацию, которая определяется для каждого типа рекуррентно. Это значит, что дл я сериализации сообщения X нам нужно знать, как сериализовать
StateInit
, CommonMsgInfo
и т. д.
Каждую вложенную структуру мы должны получать из другой схемы TL-B по ссылке рекуррентно, пока сериализация для верхней структуры не станет явной - каждый бит будет определен булевым или битовым типом (bits, uint, varuint).
Структуры, которые в настоящее время не используются в обычной разработке, будут отмечены *
в столбце Тип, например *Anycast обычно пропускается при сериализации.
message$_
Имеется верхняя схема TL-B для всех сообщений Message X
:
message$_ {X:Type} info:CommonMsgInfo
init:(Maybe (Either StateInit ^StateInit))
body:(Either X ^X) = Message X;
Структура | Тип | Обязательно | Описание | |
---|---|---|---|---|
message$_ | Constructor | Определяется по правилам конструктора. Пустой тег $_ означает, что мы не будем добавлять никаких битов в начало | ||
info | CommonMsgInfo | Обязательно | Подробные свойства сообщения определяют пункт назначения и его значение. Всегда помещаются в корневую ячейку сообщения. | |
init | StateInit | Необязательно | Общая структура, используемая в TON для инициализации новых контрактов. Может быть записана как ссылка на ячейку или корневую ячейку. | |
body | X | Обязательно | Полезная нагрузка сообщения. Может быть записана как ссылка на ячейку или корневую ячейку. |
nothing$0 {X:Type} = Maybe X;
just$1 {X:Type} value:X = Maybe X;
left$0 {X:Type} {Y:Type} value:X = Either X Y;
right$1 {X:Type} {Y:Type} value:Y = Either X Y;
Вспомним, как работают Maybe
и Either
, мы можем сериализовать разные случаи:
[CommonMsgInfo][10][StateInit][0][X]
-Сообщение X
в одной ячейке


[CommonMsgInfo][11][^StateInit][1][^X]
-Сообщение X
со ссылками


CommonMsgInfo TL-B
CommonMsgInfo
CommonMsgInfo
— это список параметров, который определяет, как сообщение будет доставлено в блокчейне TON.
//internal message
int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
src:MsgAddressInt dest:MsgAddressInt
value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams
created_lt:uint64 created_at:uint32 = CommonMsgInfo;
//external incoming message
ext_in_msg_info$10 src:MsgAddressExt dest:MsgAddressInt
import_fee:Grams = CommonMsgInfo;
//external outgoing message
ext_out_msg_info$11 src:MsgAddressInt dest:MsgAddressExt
created_lt:uint64 created_at:uint32 = CommonMsgInfo;
int_msg_info$0
int_msg_info
— это случай внутреннего сообщения. Это означает, что они могут быть отправлены между контрактами и только между контрактами.
Случай использования — обычные сообщения между контрактами.
nanograms$_ amount:(VarUInteger 16) = Grams;
//internal message
int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
src:MsgAddressInt dest:MsgAddressInt
value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams
created_lt:uint64 created_at:uint32 = CommonMsgInfo;
Структура | Тип | Обязательно | Описание |
---|---|---|---|
int_msg_info$0 | Constructor | Обязательно | Значение $0 тега означает, что при сериализации CommonMsgInfo, начинающийся с 0 бита, описывает внутреннее сообщение. |
ihr_disabled | Bool | Обязательно | Флаг маршрутизации гиперкуба. |
bounce | Bool | Обязательно | Сообщение должно быть отклонено, если во время обработки возникли ошибки. Если flat bounce сообщения = 1, оно вызывает bounceable. |
bounced | Bool | Обязательно | Флаг, описывающий, что само сообщение является результатом bounce. |
src | MsgAddressInt | Обязательно | Адрес отправителя сообщения смарт-контракта. |
dest | MsgAddressInt | Обязательно | Адрес получателя сообщения смарт-контракта. |
value | CurrencyCollection | Обязательно | Структура, описывающая информацию о валюте, включая общую сумму средств, переведенных в сообщении. |
ihr_fee | VarUInteger 16 | Обязательно | Комиссии за доставку гипермаршрутизации |
fwd_fee | VarUInteger 16 | Обязательно | Комиссии за пересылку сообщений, назначенные валидаторами |
created_lt | uint64 | Обязательно | Логическое время отправки сообщения, назначенное валидатором. Используется для заказа действий в смарт-контракте. |
created_at | uint32 | Обязательно | Время Unix |
ext_in_msg_info$10
ext_in_msg_info$10
— это случай внешнего входящего сообщения. Означает, что этот тип сообщений отправляется из off-chain-пространства в контракты.
Вариант использования — запрос приложения кошелька в контракт кошелька.
nanograms$_ amount:(VarUInteger 16) = Grams;
//external incoming message
ext_in_msg_info$10 src:MsgAddressExt dest:MsgAddressInt
import_fee:Grams = CommonMsgInfo;
Структура | Тип | Обязательно | Описание |
---|---|---|---|
ext_in_msg_info$10 | Constructor | Обязательно | Тег $10 означает, что в сериализации CommonMsgInfo, начинающийся с 10 бит, описывает внешнее входящее сообщение. |
ihr_disabled | Bool | Обязательно | Флаг гипермаршрутизации. (в настоящее время всегда true) |
src | MsgAddressExt | Обязательно | Адрес внешнего отправителя сообщения. |
dest | MsgAddressInt | Обязательно | Адрес смарт-контракта назначения сообщения. |
import_fee | VarUInteger 16 | Обязательно | Плата за выполнение и доставку сообщения. |
ext_out_msg_info$11
ext_out_msg_info$11
— это случай внешнего исходящего сообщения. Это означает, что они могут быть отправлены из контрактов в off-chain пространство.
Пример использования — логи.
//external outgoing message
ext_out_msg_info$11 src:MsgAddressInt dest:MsgAddressExt
created_lt:uint64 created_at:uint32 = CommonMsgInfo;
Структура | Тип | Обязательно | Описание |
---|---|---|---|
ext_out_msg_info$11 | Constructor | Обязательно | Тег $11 означает, что в сериализации CommonMsgInfo, начинающийся с бита 11 , описывает внешнее исходящее сообщение. |
src | MsgAddressInt | Обязательно | Адрес отправителя сообщения смарт-контракта. |
dest | MsgAddressExt | Обязательно | Адрес внешнего назначения сообщения. |
created_lt | uint64 | Обязательно | Логическое время отправки сообщения, назначенное валидатором. Используется для упорядочивания действий в смарт-контракте. |
created_at | uint32 | Обязательно | Время Unix |
StateInit TL-B
StateInit служит для дос тавки начальных данных в контракт и используется при развертывании контракта.
_ split_depth:(Maybe (## 5)) special:(Maybe TickTock)
code:(Maybe ^Cell) data:(Maybe ^Cell)
library:(HashmapE 256 SimpleLib) = StateInit;
Структура | Тип | Обязательно | Описание |
---|---|---|---|
split_depth | (## 5) | Необязательно | Параметр для highload контрактов определяет поведение разделения на несколько экземпляров в разных шардах. В настоящее время StateInit используется без него. |
special | TickTock* | Необязательно | Используется для вызова смарт-контрактов в каждом новом блоке блокчейна. Доступно только в мастерчейне. Обычные пользовательские контракты используются без него. |
code | Cell | Необязательно | Сериализованный код контракта. |
data | Cell | Необязательно | Начальные данные контракта. |
library | HashmapE 256 SimpleLib* | Необязательно | В настоящее время используется StateInit без библиотек |
Общие подробные пояснения к хэшмапам
MsgAddressExt TL-B
addr_none$00 = MsgAddressExt;
addr_extern$01 len:(## 9) external_address:(bits len)
= MsgAddressExt;
MsgAddress
- это схема различных сериализаций для адресов. В зависимости от того, какой участник (off-chain или смарт-контракт) отправляет сообщения, используются различные структуры.
addr_none$00
addr_none$00
- используется для определения нулевого адреса off-chain участника. Это означает, что мы можем отправлять внешнее сообщение контракту без уникального адреса отправителя.
addr_none$00 = MsgAddressExt;
Структура | Тип | Обязательно | Описание |
---|---|---|---|
addr_none$00 | Constructor | Обязательно | Тег "$00" означает, что при сериализации MsgAddressExt начинается с битов "00". Это означает, что весь внешний адрес равен 00 . |
addr_extern$01
addr_extern$01 len:(## 9) external_address:(bits len)
= MsgAddressExt;
Структура | Тип | Обязательно | Описание |
---|---|---|---|
addr_extern$01 | Constructor | Обязательно | Тег $01 означает, что при сериализации MsgAddressExt, начинающийся с бита 01 , описывает внешний адрес. |
len | ## 9 | Обязательно | То же, что и uintN - означает N-разрядное число без знака |
external_address | (bits len) | Обязательно | Адрес - это битовая строка len, равная предыдущему "len" |
MsgAddressInt TL-B
addr_std$10 anycast:(Maybe Anycast)
workchain_id:int8 address:bits256 = MsgAddressInt;
addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9)
workchain_id:int32 address:(bits addr_len) = MsgAddressInt;
addr_std$10
addr_std$10 anycast:(Maybe Anycast)
workchain_id:int8 address:bits256 = MsgAddressInt;
Структура | Тип | Обязательно | Описание |
---|---|---|---|
addr_std$10 | Constructor | Обязательно | Тег $10 означает, что в сериализации MsgAddressInt, начинающийся с 10 бит, описывает внутренний адрес. |
anycast | Anycast* | Необязательно | Дополнительные данные адреса, в настоящее время не используются в обычных внутренних сообщениях |
workchain_id | int8 | Обязательно | Воркчейн, в котором размещен смарт-контракт адреса назначения. В настоящий момент всегда равен нулю. |
address | (bits256) | Обязательно | Номер идентификатора учетной записи смарт-контракта |
addr_var$11
addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9)
workchain_id:int32 address:(bits addr_len) = MsgAddressInt;
Структура | Тип | Обязательно | Описание |
---|---|---|---|
addr_var$11 | Constructor | Обязательно | Тег $11 означает, что в сериализации MsgAddressInt, начинающийся с 11 бит, описывает внутренний адрес контракта. |
anycast | Anycast* | Необязательно | Дополнительные данные адреса, в настоящее время не используются в обычных внутренних сообщениях |
addr_len | ## 9 | Обязательно | То же, что и uintN - означает N-разрядное число без знака |
workchain_id | int32 | Обязательно | Воркчейн, в котором размещен смарт-контракт адреса назначения. В настоящий момент всегда равен нулю. |
address | (bits256) | Обязательно | Адрес полезной нагрузки (может быть идентификатором учетной записи) |
Основные используемые типы
CurrencyCollection
nanograms$_ amount:(VarUInteger 16) = Grams;
currencies$_ grams:Grams other:ExtraCurrencyCollection
= CurrencyCollection;
Структура | Тип | Обязательно | Описание |
---|---|---|---|
currencies$_ | Constructor | Обязательно | $_ пустой тег означает, что в сериализации CurrencyCollection мы не будем добавлять никаких битов в начало |
grams | (VarUInteger 16) | Обязательно | Значение сообщения в nanoTons |
other | ExtraCurrencyCollection | Необязательно | ExtraCurrencyCollection — это словарь, предназначенный для дополнительных валют, который обычно пустой |
- ExtraCurrencyCollection сложный тип, который обычно пишется как пустой словарь в сообщениях
VarUInteger n
var_uint$_ {n:#} len:(#< n) value:(uint (len * 8))
= VarUInteger n;
var_int$_ {n:#} len:(#< n) value:(int (len * 8))
= VarInteger n;
Структура | Тип | Обязательно | Описание |
---|---|---|---|
var_uint$_ | Constructor | Обязательно | var_uint$_ пустой тег означает, что в сериализации CurrencyCollection мы не будем добавлять никаких битов в начало |
len | uintN | Обязательно | биты параметра len для следующего значения |
value | (uint (len * 8)) | Необязательно | значение uint для целого числа, записанного в (len * 8) бит |
Пример сообщения
Обычное внутреннее сообщение на func
var msg = begin_cell()
.store_uint(0, 1) ;; tag
.store_uint(1, 1) ;; ihr_disabled
.store_uint(1, 1) ;; allow bounces
.store_uint(0, 1) ;; not bounced itself
.store_slice(source)
.store_slice(destination)
;; serialize CurrencyCollection (see below)
.store_coins(amount)
.store_dict(extra_currencies)
.store_coins(0) ;; ihr_fee
.store_coins(fwd_value) ;; fwd_fee
.store_uint(cur_lt(), 64) ;; lt of transaction
.store_uint(now(), 32) ;; unixtime of transaction
.store_uint(0, 1) ;; no init-field flag (Maybe)
.store_uint(0, 1) ;; inplace message body flag (Either)
.store_slice(msg_body)
.end_cell();
Обычное сообщение на func в краткой форме
Части сообщения, которые всегда перезаписываются валидаторами, можно пропустить (заполнить нулевыми битами). Отправитель сообщения здесь также пропущен, сериализован как addr_none$00
.
cell msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(addr)
.store_coins(amount)
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_slice(message_body)
.end_cell();