Перейти к основному содержимому

Обзор TVM

warning

Эта страница переведена сообществом на русский язык, но нуждается в улучшениях. Если вы хотите принять участие в переводе свяжитесь с @alexgton.

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

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

подсказка

Курс TON: TVM

подсказка

Перед началом курса убедитесь, что вы хорошо понимаете основы технологии блокчейн. Если у вас есть пробелы в знаниях, рекомендуем пройти курс Основы блокчейна с TON (версия RU, версия CHN).

Курс по блокчейну TON — это комплексное руководство по разработке на блокчейне TON.

Модуль 2 полностью охватывает TVM, транзакции, масштабируемость и бизнес-кейсы.

Пройдите курс по блокчейну TON

CHN

RU

Транзакции и фазы

Когда на аккаунте в одной из цепочек TON происходит какое-либо событие, оно вызывает транзакцию. Наиболее распространенным событием является "получение некоторого сообщения", но, вообще говоря, могут быть tick-tock, merge, split и другие события.

Каждая транзакция состоит из 5 фаз:

  1. Фаза хранения - на этой фазе рассчитываются сборы за хранение, накопленные контрактом из-за занятия некоторого пространства в состоянии цепочки. Подробнее читайте в разделе плата за хранение.
  2. Фаза кредита - на этой фазе рассчитывается баланс контракта относительно (возможной) стоимости входящего сообщения и собранной платы за хранение.
  3. Фаза вычислений - на этом этапе TVM выполняет контракт (см. ниже), а результатом выполнения контракта является совокупность exit_code, actions (сериализованный список действий), gas_details, new_storage и некоторых других.
  4. Фаза действий - если фаза вычислений прошла успешно, на этом этапе обрабатываются actions из фазы вычислений. В частности, действия могут включать отправку сообщений, обновление кода смарт-контракта, обновление библиотек и т. д. Обратите внимание, что некоторые действия могут завершиться неудачей во время обработки (например, если мы попытаемся отправить сообщение с большим количеством TON, чем есть в контракте), в этом случае вся транзакция может быть отменена или это действие может быть пропущено (это зависит от режима действий, другими словами, контракт может отправить сообщение типа send-or-revert или try-send-if-no-ignore).
  5. Фаза возврата — если фаза вычислений не удалась (возвращено exit_code >= 2), в этой фазе формируется сообщение о возврате для транзакций, инициированных входящим сообщением.

Фаза вычислений

В этой фазе происходит выполнение TVM.

подсказка

Пропуск фазы вычислений

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

Это отражено в соответствующих конструкторах:

  • cskip_no_state$00 - Отсутствие состояния (т. е. код и данные смарт-контракта) как в аккаунте (несуществующем, неинициализированном или замороженном), так и в сообщении.

  • cskip_bad_state$01 - Недопустимое состояние, переданное в сообщении (т. е. хэш состояния отличается от ожидаемого значения) замороженного или неинициализированного аккаунта.

  • cskip_no_gas$10 - Отсутствие средств для покупки газа. (Около < 0,00004 TON к 08.2024)

Состояние TVM

В любой момент состояние TVM полностью определяется 6 свойствами:

  • Стек (см. ниже)
  • Регистры управления - (см. ниже) проще говоря, это означает до 16 переменных, которые могут быть напрямую установлены и прочитаны во время выполнения
  • Текущее продолжение - объект, который описывает текущую выполняемую последовательность инструкций
  • Текущая кодовая страница - проще говоря, это версия TVM, которая в данный момент запущена
  • Лимиты газа - набор из 4 целочисленных значений; текущий лимит газа gl, максимальный лимит газа gm, оставшийся газ gr и кредит газа gc
  • Контекст библиотеки - хэш-карта библиотек, которые может вызывать TVM

TVM - это стековая машина

TVM - это стековая машина по принципу "последний вошел - первый вышел". Всего существует 7 типов переменных, которые могут храниться в стеке — три типа, не являющихся ячейками:

  • Integer — 257-битные целые числа со знаком
  • Tuple — упорядоченная коллекция из до 255 элементов с произвольными типами значений, возможно, разными.
  • Null

И четыре различных вида ячеек:

  • Cell — базовая (возможно, вложенная) непрозрачная структура, используемая блокчейном TON для хранения всех данных
  • Slice — специальный объект, позволяющий читать из ячейки
  • Builder — специальный объект, позволяющий создавать новые ячейки
  • Continuation — специальный объект, позволяющий использовать ячейку в качестве источника инструкций TVM

Управляющие регистры

  • c0 — Содержит следующее продолжение или возврат продолжения (аналогично адресу возврата подпрограммы в обычных конструкциях). Это значение должно быть продолжением.
  • c1 — Содержит альтернативное (возвратное) продолжение; это значение должно быть продолжением.
  • c2 — Содержит обработчик исключений. Это значение является продолжением, которое вызывается при возникновении исключения.
  • c3 — Вспомогательный регистр, содержит текущий словарь, по сути хэш-карту, содержащую код всех функций, используемых в программе. Это значение должно быть продолжением.
  • c4 — Содержит корень постоянных данных или просто раздел data контракта. Это значение является ячейкой.
  • c5 — Содержит выходные действия. Это значение является ячейкой.
  • c7 — Содержит корень временных данных. Это кортеж.

Инициализация TVM

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

Подробное описание процесса инициализации можно найти здесь: Инициализация TVM

Инструкции TVM

Список инструкций TVM можно найти здесь: Инструкции TVM.

Результат выполнения TVM

Помимо exit_code и данных о потребленном газе, TVM косвенно выводит следующие данные:

  • Регистр c4 — ячейка, которая будет сохранена как новая data смарт-контракта (если выполнение не будет отменено на этой или последующих фазах)
  • Регистр c5 — (список выходных действий) ячейка с последним действием в списке и ссылка на ячейку с предыдущим действием (рекурсивно)

Всеми остальными значениями регистра можно пренебречь.

Обратите внимание, что существует глобальное ограничение на максимальную глубину ячейки <1024 во время выполнения контракта. Однако регистры c4 и c5 должны быть <=512 в глубину. Выход за эти пределы приводит к ошибке в конце фазы вычислений. Дополнительное ограничение накладывается на фазе действий. Контракт не может создать более 255 выходных действий.

подсказка

Если контракт хочет отправить более 255 сообщений, он может сделать это, отправив сообщение самому себе, в котором будет содержаться запрос на отправку оставшихся сообщений. Пример такого подхода можно увидеть по ссылке https://github.com/ton-blockchain/highload-wallet-contract-v3/blob/main/contracts/highload-wallet-v3.func#L50.

См. также