Сообщения между шардчейнами

Важным компонентом блокчейна TON является система обмена сообщениями между блокчейнами. Эти блокчейны могут быть шардчейнами одного или разных воркчейнов.

Сообщения, счета и транзакции: общая структура системы

Сообщения отправляются из одной учетной записи в другую. Каждая транзакция включает следующие этапы: учетная запись получает одно сообщение, меняет свое состояние в соответствии с определенными правилами и генерирует несколько (возможно, одно или ноль) новых сообщений для других учетных записей. Каждое сообщение создается и принимается (доставляется) ровно один раз.

Это означает, что сообщения играют в системе фундаментальную роль, сравнимую с ролью учетных записей (смарт-контрактов). С точки зрения парадигмы бесконечного шардинга , каждая учетная запись находится в своей отдельной «цепочке учетных записей», и единственный способ повлиять на состояние какой-либо другой учетной записи — это отправить сообщение.

Более дорогая альтернатива — опубликовать такой «глобальный» смарт-контракт в мастерчейне.
Это своего рода «широковещательная» функция для всех шардов, и поэтому она должна быть довольно дорогой

Учетные записи как процессы или субъекты; модель акторов

Можно воспринимать учетные записи (и смарт-контракты) как «процессы» или «акторы», которые могут обрабатывать входящие сообщения, изменять свое внутреннее состояние и в результате генерировать некоторые исходящие сообщения. Это тесно связано с так называемыми моделями акторов, которые используются в таких языках, как Erlang (однако акторы в Erlang обычно называются «процессами»). Поскольку новые акторы (то есть смарт-контракты) также могут быть созданы существующими акторами в результате обработки входящего сообщения, наблюдается практически полное соответствие с моделью акторов.

Получатель сообщения. У любого сообщения есть получатель, который характеризуется идентификатором целевого воркчейна w (предполагается, что по умолчанию он такой же, как идентификатор исходного шардчейна) и учетной записью получателя account_id. Точный формат (т. е. количество битов) account_id зависит от w; однако шард всегда определяется его первыми (наиболее значимыми) 64 битами.

Отправитель сообщения. В большинстве случаев у сообщения есть отправитель, который характеризуется парой (w’, account_id’). При наличии такого идентификатора он находится после получателя сообщения и ценности сообщения. Иногда отправитель не важен, либо это кто-то за пределами блокчейна (то есть не смарт-контракт), поэтому это поле отсутствует.

Обратите внимание, что в модели акторов не требуется, чтобы сообщения имели неявного отправителя. Вместо этого сообщения могут содержать ссылку на актора, которому должен быть отправлен ответ на запрос (обычно совпадает с отправителем). Однако полезно иметь поле явного не поддающегося подделке отправителя в сообщении в криптовалютной среде, в которой применяется задача византийских генералов.

Стоимость сообщения

Другой важной характеристикой сообщения является его прикрепленная стоимость в одной или нескольких криптовалютах, поддерживаемых как исходным, так и целевой воркчейном. Стоимость указывается в самом начале сообщения сразу после получателя сообщения; по сути, это список пар (currency_id, value).

Обратите внимание, что «простые» транзакции стоимости между «простыми» учетными записями — это пустые сообщения с некоторой прикрепленной к ним стоимостью. С другой стороны, немного более сложное тело сообщения может содержать простой текст или двоичный комментарий (например, о цели платежа).

Внешние сообщения или «сообщения из ниоткуда»

Некоторые сообщения поступают в систему «из ниоткуда», то есть они не генерируются учетной записью (смарт-контрактом), находящейся в блокчейне. Наиболее типичный пример — когда пользователь хочет перевести часть средств с контролируемой им учетной записи на другую учетную запись. В этом случае пользователь отправляет «сообщение из ниоткуда» в свою учетную запись, запрашивая создание сообщения для принимающей учетной записи, содержащего указанное значение. Если это сообщение правильно подписано, учетная запись получает его и генерирует необходимые исходящие сообщения.

Фактически, можно рассматривать «простую» учетную запись как частный случай смарт-контракта с предопределенным кодом. Этот смарт-контракт получает только один тип сообщения. Такое входящее сообщение должно содержать список исходящих сообщений, которые должны быть сгенерированы в результате доставки (обработки) входящего сообщения, вместе с подписью. Смарт-контракт проверяет подпись и, если она верна, генерирует необходимые сообщения.

Конечно, есть разница между «сообщениями из ниоткуда» и обычными сообщениями, поскольку «сообщения из ниоткуда» не могут иметь стоимости, и соответственно не могут сами платить за «газ» (то есть за их обработку). Вместо этого они предварительно выполняются с небольшим лимитом газа, прежде чем будет предложено их включение в новый блок шардчейна; если выполнение не удается (подпись неверна), «сообщение из ниоткуда» считается неверным и отбрасывается. Если выполнение будет завершено в пределах небольшого лимита газа, сообщение может быть включено в новый блок шардчейна и полностью обработано, при этом оплата за потребленный газ (мощность обработки) будет взиматься со счета получателя. Для «сообщений из ниоткуда» также может быть определена некоторая комиссия за транзакцию, которая снимается со счета получателя сверх платы за газ и перераспределяется между валидаторами.

В этом смысле «сообщения из ниоткуда» или «внешние сообщения» выступают в роли кандидатов на транзакции, используемых в других системах блокчейнов (например, Биткоин и Эфириум).

Сообщения журнала или «сообщения в никуда»

Точно так же иногда может быть сгенерировано специальное сообщение, которое направляется в конкретный шардчейн не для доставки его получателю, а для регистрации в журнале, чтобы это сообщение мог легко заметить любой пользователь, который получает обновления о рассматриваемом шарде. Такие зарегистрированные сообщения могут выводиться на консоль пользователя или запускать выполнение некоторого сценария на сервере вне сети. В этом смысле они представляют собой внешний «выход» «суперкомпьютера с блокчейном», так же как «сообщения из ниоткуда» представляют собой внешний «вход» «суперкомпьютера с блокчейном».

Взаимодействие с сервисами вне блокчейна и внешними блокчейнами
Эти внешние входные и выходные сообщения могут использоваться для взаимодействия с сервисами вне блокчейна и другими (внешними) блокчейнами, такими как Биткоин или Эфириум.

В блокчейне TON можно создавать токены или криптовалюты, привязанные к биткойну, эфиру или любым токенам ERC-20, определенным в блокчейне Ethereum, и использовать «сообщения из ниоткуда» и «сообщения в никуда», генерируемые и обрабатываемые скриптами, находящимися на сторонних серверах вне блокчейна, чтобы реализовать необходимое взаимодействие между блокчейном TON и этими внешними блокчейнами.

Тело сообщения

Тело сообщения — это просто последовательность байтов, значение которой определяется только принимающим воркчейном и/или смарт-контрактом. Для блокчейнов, в которых используется виртуальная машина TON, это может быть сериализация любой ячейки TVM, автоматически сгенерированная с помощью операции Send О. Такая сериализация достигается путем простой рекурсивной замены всех ссылок в ячейке ВМ TON на указанные ячейки. В конечном итоге появляется строка необработанных байтов, перед которой обычно идет 4-байтовый «тип сообщения» или «конструктор сообщения», используемый для выбора правильного метода принимающего смарт-контракта.

Другим вариантом может быть использование объектов, сериализированных с помощью языка TL, в качестве тел сообщения. Это может быть особенно полезно для связи между различными воркчейнами, в одном из которых или во всех не обязательно используется виртуальная машина TON.

Лимит газа и другие параметры, специфичные для воркчейна/VM
Иногда сообщение должно нести информацию о лимите газа, цене на газ, комиссии за транзакции и аналогичных значениях, которые зависят от принимающего воркчейна и актуальны только для него, но не обязательно для исходного воркчейна. Такие параметры включаются в тело сообщения или перед ним, иногда (в зависимости от воркчейна) со специальными 4-байтовыми префиксами, указывающими на их присутствие (которые могут быть определены с помощью TL-схемы).

Создание сообщений: смарт-контракты и транзакции
Существуют два источника новых сообщений. Большинство сообщений создается во время выполнения смарт-контракта (посредством операции Send() в VM TON), когда для обработки входящего сообщения вызывается какой-либо смарт-контракт. Как вариант, сообщения могут приходить извне как «внешние сообщения» или «сообщения из ниоткуда».

Доставка сообщений

Когда сообщение достигает шардчейна, содержащего целевую учетную запись, оно «доставляется» в целевую учетную запись. Дальнейшие процессы зависят от воркчейна; со стороны важно, чтобы такое сообщение никогда не могло быть переадресовано дальше этого шардчейна.

Для шардчейнов основного воркчейна доставка заключается в добавлении стоимости сообщения (за вычетом любых платежей за газ) к балансу принимающей учетной записи и, возможно, в последующем вызове зависимого от сообщения метода получающего смарт-контракта, если получающая учетная запись является смарт-контрактом. Фактически, смарт-контракт имеет только одну точку входа для обработки всех входящих сообщений, поэтому он должен различать разные типы сообщений путем анализа первых нескольких байтов (например, первые четыре байта, содержащие конструктор TL).

Доставка сообщения как транзакция

Поскольку доставка сообщения изменяет состояние учетной записи или смарт-контракта, этот процесс является особой транзакцией в принимающем шардчейне, которая явно регистрируется как таковая. По сути, без учета некоторых незначительных технических деталей, все транзакции в блокчейне TON представляют собой доставку одного входящего сообщения в принимающую учетную запись (смарт-контракт).

Сообщения между экземплярами одного и того же смарт-контракта
Напомним, что смарт-контракт может быть локальным (т. е. может находиться в одной шардчейне, как и любая обычная учетная запись) или глобальным (т. е. иметь экземпляры во всех шардах или, по крайней мере, во всех шардах до некоторой известной глубины d). При необходимости экземпляры глобального смарт-контракта могут обмениваться специальными сообщениями между собой для передачи информации и стоимости. В этом случае особенно важным становится (не поддающийся подделке) идентификатор account_id.

Сообщения на любой экземпляр смарт-контракта; адреса с подстановочными знаками. Иногда сообщение (например, запрос клиента) необходимо доставить в любой экземпляр глобального смарт-контракта, обычно ближайший (если он находится в том же шардчейне, что и отправитель, это очевидный кандидат). 13 Вышеупомянутое должно быть верным только для исходного воркчейна и соответствующих шардчейнов. Другие воркчейны могут предоставлять другие способы создания сообщений.

Один из способов сделать это — использовать «адрес получателя с подстановочными знаками», при этом первым d битам целевого идентификатора account_id разрешено принимать произвольные значения. На практике для этих битов d обычно устанавливаются те же значения, что и в идентификаторе отправителя account_id.

Отсутствие очереди ввода
Все сообщения, полученные блокчейном (обычно шардчейном, иногда мастерчейном) — или, по сути, «цепочкой учетных записей», находящейся внутри определенного шардчейна, — немедленно доставляются (т. е. обрабатываются принимающей учетной записью). Следовательно, «очередь ввода» как таковая отсутствует. Вместо этого, если из-за ограничений на общий размер блоков и использование газа могут быть обработаны не все сообщения, предназначенные для определенного шардчейна, некоторые сообщения просто накапливаются в очередях вывода исходных шардчейнов.

Очереди вывода
С точки зрения парадигмы бесконечного шардинга, каждая цепочка учетных записей (т. е. каждая учетная запись) имеет свою собственную очередь вывода, состоящую из всех сообщений, которые были в ней сгенерированы, но еще не доставлены получателям. Конечно, цепочки учетных записей существуют только виртуально; они сгруппированы в шардчейны, а шардчейн имеет выходную «очередь», состоящую из очередей вывода всех учетных записей, относящихся к шардчейну.

Эта выходная «очередь» шардчейна обеспечивает только частичный порядок в сообщениях участников шардчейна. А именно, сообщение, сгенерированное в предыдущем блоке, должно быть доставлено до любого сообщения, сгенерированного в последующем блоке, а любые сообщения, сгенерированные той же учетной записью и имеющие то же место назначения, должны быть доставлены в порядке их генерации.

Надежный и быстрый обмен сообщениями между цепями
В масштабируемом проекте с несколькими блокчейнами (таком как TON) чрезвычайно важно иметь возможность пересылать и доставлять сообщения между разными шардчейнами, даже если в системе их миллионы. Необходимо обеспечить надежную (т. е. сообщения не должны теряться или доставляться более одного раза) и быструю доставку сообщений. В блокчейне TON эта цель достигается путем использования комбинации двух механизмов «маршрутизации сообщений».

Маршрутизация в гиперкубе: «медленный путь» для сообщений с гарантированной доставкой

В блокчейне TON применяется технология «маршрутизации в гиперкубе» в качестве медленного и одновременно безопасного и надежного способа доставки сообщений из одного шардчейна в другой, причем при необходимости для передачи используется несколько промежуточных шардчейнов. В противном случае валидаторам любого данного шардчейна потребуется отслеживать состояние (очередей вывода) всех других шардчейнов, что потребует непомерно больших вычислительных мощностей и пропускной способности сети по мере роста общего количества шардчейнов и приведет к ограничению масштабируемости. системы. Следовательно, возможность доставлять сообщения напрямую из одного шарда в другой отсутствует. Вместо этого каждый шард «подключен» только к шардам, которые отличаются ровно одной шестнадцатеричной цифрой в идентификаторах (w, s). В качестве вырожденного случая этот шардчейн может совпадать с исходным шардчейном, например, если операция выполняется внутри воркчейна, который еще не была разделен.

Таким образом, все шардчейны составляют граф типа «гиперкуб», а сообщения перемещаются по краям этого гиперкуба.

Если сообщение отправляется на шард, отличный от текущего шарда, одна из детерминировано выбранных шестнадцатеричных цифр текущего идентификатора шарда заменяется соответствующей цифрой целевого шарда, а полученный идентификатор используется в качестве ближайшей цели для пересылки сообщения. Основное преимущество маршрутизации в гиперкубе заключается в том, что условия допустимости блока подразумевают, что валидаторы, создающие блоки шардчейна, должны собирать и обрабатывать сообщения из выходных очередей «соседних» шардчейнов, опасаясь потери своих долей. Таким образом, можно ожидать, что любое сообщение рано или поздно достигнет своего конечного пункта назначения; при этом сообщение не может быть потеряно в пути или доставлено дважды.

Обратите внимание, что маршрутизация в гиперкубе приводит к некоторым дополнительным задержкам и расходам из-за необходимости пересылать сообщения через несколько промежуточных шардчейнов. Однако количество этих промежуточных шардчейнов увеличивается очень медленно по мере роста логарифма log N (точнее, [log16N] — 1) от общего количества шардчейнов N.

Например, если N = 250, то будет наблюдаться максимум один промежуточный переход; а для N = 4000 шардчейнов — максимум два. С четырьмя промежуточными переходами мы можем поддерживать до одного миллиона шардчейнов. Мы считаем, что это очень небольшая цена за практически неограниченную масштабируемость системы (фактически, не обязательно платить даже ее).

Мгновенная маршрутизация в гиперкубе (Instant Hypercube Routing): «быстрый путь» для сообщений
Новой особенностью блокчейна TON является то, что в нем используется «быстрый путь» для пересылки сообщений от одного шардчейна к любому другому шардчейну, что позволяет в большинстве случаев полностью обойти «медленную» маршрутизацию в гиперкубе и доставлять сообщение в следующий блок конечного шардчейна.

Идея этой технологии заключается в следующем. Во время «медленной» маршрутизации в гиперкубе сообщение перемещается (в сети) по краям гиперкуба, но задерживается (примерно на пять секунд) в каждой промежуточной вершине и фиксируется в соответствующем шардчейне, прежде чем продолжить свой путь.

Чтобы избежать ненужных задержек, вместо этого можно передавать сообщение вместе с подходящим доказательством Меркла по краям гиперкуба, не дожидаясь его фиксации в промежуточных шардчейнах. Фактически, сетевое сообщение должно быть переадресовано от валидаторов «целевой группы» исходного шарда указанному создателю блоков «целевой группы» конечного шарда; это можно сделать напрямую, без остановок сообщения на краях гиперкуба.

Когда это сообщение с доказательством Меркла достигает валидаторов (точнее, сверщиков) целевого шардчейна, они могут немедленно зафиксировать его в новом блоке, не дожидаясь, пока сообщение завершит продвижение по «медленному пути». 15 Это не обязательно окончательная версия алгоритма, используемого для вычисления следующего перехода при маршрутизации в гиперкубе. В частности, шестнадцатеричные цифры могут быть заменены r-битовыми группами с r конфигурируемым параметром, не обязательно равным четырем.

Однако у валидаторов есть некоторый стимул сделать это как можно скорее, потому что они смогут собрать все платежи за пересылку, связанные с сообщением, которое еще не было использовано на «медленном» пути.

На самом деле, можно было временно или навсегда отключить механизм мгновенной доставки, и система продолжала бы работать, хотя и медленнее. Затем подтверждение доставки вместе с подходящим доказательством Меркла отправляется обратно по краям гиперкуба, и его можно использовать, чтобы остановить движение сообщения по «медленному пути» путем выполнения специальной транзакции.

Обратите внимание, что этот механизм «мгновенной доставки» не заменяет «медленный», но отказоустойчивый механизм «Медленный путь» по-прежнему необходим, поскольку валидаторы не должны наказываться за потерю сообщения или просто решение не фиксировать сообщения в процессе «быстрого пути» в новых блоках своих блокчейнов.

Следовательно, оба метода пересылки сообщений выполняются параллельно, и «медленный» механизм прерывается только в том случае, если доказательство успеха «быстрого» механизма фиксируется в промежуточном шардчейне.

Сбор входных сообщений из очередей вывода соседних шардчейнов
Когда предлагается создание нового блока в шардчейне, некоторые из выходных сообщений соседних (в смысле гиперкуба маршрутизации) шардчейнов включаются в новый блок как «входные» сообщения и немедленно доставляются (т. е. обрабатываются).

Существуют определенные правила относительно порядка, в котором выходные сообщения этих соседних шардчейнов должны обрабатываться. По сути, «старое» сообщение (исходящее из блока шардчейна, относящегося к более старому блоку мастерчейна) должно быть доставлено до любого «нового» сообщения; а для сообщений, поступающих из того же соседнего шардчейна, должен соблюдаться частичный порядок очереди вывода.

Удаление сообщений из очередей вывода

После того, как сообщение очереди вывода помечается как доставленное соседним шардчейном сообщение, оно явно удаляется из очереди вывода специальной транзакцией.

Предотвращение двойной доставки сообщений
Чтобы предотвратить двойную доставку сообщений, взятых из очередей вывода соседних шардчейнов, каждый шардчейн (точнее, каждая цепочка учетных записей в шардчейне) сохраняет набор недавно доставленных сообщений (или только их хэшей) как часть своего состояния. Когда обнаруживается, что доставленное сообщение было удалено из очереди вывода соответствующим исходным соседним шардчейном, оно также удаляется из набора недавно доставленных сообщений.

Пересылка сообщений, предназначенных для других шардчейнов

Маршрутизация в гиперкубе означает, что иногда исходящие сообщения доставляются не в шардчейн, содержащий предполагаемого получателя, а в соседний шардчейн, находящийся в гиперкубе на пути к месту назначения. В этом случае «доставка» заключается в перемещении входящего сообщения в очередь исходящих сообщений. Этот процесс явно отражается в блоке как специальная транзакция пересылки, содержащая само сообщение. По сути, это выглядит так, как если бы сообщение было получено кем-то внутри шардчейна, и в результате было сгенерировано одно идентичное сообщение.

Оплата пересылки и хранения сообщения

Транзакция пересылки фактически расходует некоторое количество газа (в зависимости от размера пересылаемого сообщения), поэтому оплата газа вычитается из стоимости сообщения, пересылаемого от имени валидаторов этого шардчейна. Этот платеж за пересылку обычно значительно меньше, чем платеж за газ, который взимается, когда сообщение окончательно доставляется получателю, даже если сообщение было переадресовано несколько раз в процессе маршрутизации в гиперкубе. Кроме того, пока сообщение хранится в очереди вывода шардчейна, оно является частью глобального состояния шардчейна, поэтому за хранение глобальных данных в течение длительного времени также может взиматься плата с помощью специальных транзакций.

Сообщения, передаваемые в мастерчейн и из него

Сообщения могут быть отправлены напрямую из любого шардчейна в мастерчейн и наоборот. Однако оплата за газ для отправки и обработки сообщений в мастерчейне довольно высокая, поэтому эта возможность будет использоваться только в случае необходимости — например, валидаторами для внесения своих долей. В некоторых случаях может быть определен минимальный депозит (прикрепленное значение) для отправляемых в мастерчейн сообщений, который будет возвращаться только в том случае, если сообщение считается «действительным» принимающей стороной

Автоматическая маршрутизация сообщений в мастерчейне отсутствует. Сообщение с идентификатором workchain_id ≠ —1 (—1 — специальный workchain_id, указывающий на мастерчейн) не может быть доставлено в мастерчейн.

В принципе, можно создать смарт-контракт для пересылки сообщений внутри мастерчейна, однако цена за его использование будет непомерно высокой.

Сообщения между учетными записями в одном шардчейне
В некоторых случаях учетной записью, принадлежащей определенному шардчейну, создается сообщение, предназначенное для другой учетной записи в том же шардчейне. Например, это происходит в новом воркчейне, который еще не разделен на несколько шардчейнов благодаря нормальному уровню нагрузки.

Такие сообщения могут накапливаться в выходной очереди шардчейна, а затем обрабатываться как входящие сообщения в последующих блоках (для этой цели любой шард считается своим собственным соседним элементом). Однако в большинстве случаев эти сообщения можно доставить в самом исходном блоке.

Для этого для всех транзакций в блоке шардчейна вводится частичный порядок, а транзакции (каждая из которых заключается в доставке сообщения какой-либо учетной записи) обрабатываются с соблюдением этого частичного порядка. В частности, транзакции разрешено обрабатывать некоторое выходное сообщение предыдущей транзакции по отношению к этому частичному порядку.

В этом случае тело сообщения не копируется дважды. Вместо этого исходящая и обрабатывающая транзакции ссылаются на общую копию сообщения.