Как устроена платформа

Смарт-контракты

Смарт-контракт - это отдельное приложение, которое записывает в блокчейн свои входные данные и результаты исполнения заложенного алгоритма. Блокчейн-платформа Waves Enterprise поддерживает разработку и применение Тьюринг-полных смарт-контрактов для создания высокоуровневых бизнес-приложений.

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

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

Доступ смарт-контракта к стейту ноды для обмена данными осуществляется посредством gRPC и REST API-интерфейсов.

Создавать и вызывать смарт-контракты может любой участник сети. Разработанный смарт-контракт упаковывается в Docker-образ, который хранится в открытом репозитории Waves Enterprise. Этот репозиторий основан на технологии Docker Registry, к нему имеет доступ любой разработчик смарт-контрактов. Для добавления смарт-контракта в репозиторий свяжитесь со службой технической поддержки Waves Enterprise. После одобрения вашей заявки смарт-контракт будет загружен в репозиторий, и вы сможете вызвать его при помощи клиентского приложения или запроса по REST API к вашей ноде.

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

Ниже приведена общая схема работы смарт-контракта:

../../_images/docker-11.png

Создание и установка смарт-контракта

Практические указания по разработке логики смарт-контрактов, а также пример реализации на Python приведены в статье Разработка и применение смарт-контрактов Docker.

Участник, разрабатывающий смарт-контракт, должен иметь роль contract_developer в сети. Участник с ролью разработчика смарт-контрактов получает возможность вызывать смарт-контракты, а также запрещать их исполнение и обновлять их код.

Создание смарт-контракта начинается с подготовки Docker-образа, который содержит готовый код смарт-контракта, сценарный файл Dockerfile, а также, в случае использования gRPC-интерфейса для обмена данных с нодой, необходимые protobuf-файлы.

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

Для установки смарт-контракта и работы с ним необходима настройка секции docker-engine конфигурационного файла ноды. Если ваша нода работает в Waves Enterprise Mainnet, на ней по умолчанию настроены установка смарт-контрактов из открытого репозитория и установлены рекомендованные параметры для обеспечения оптимального исполнения смарт-контрактов.

Установка смарт-контракта в блокчейне выполняется посредством транзакции 103 CreateContract Transaction, в теле которой указывается ссылка на образ смарт-контракта в репозитории. При работе со смарт-контрактами рекомендуется отправлять транзакции последних версий.

При работе в частной сети транзакция 103 предусматривает загрузку Docker-образа контракта не только из репозиториев, указанных в секции docker-engine конфигурационного файла ноды. Если вам необходимо загрузить смарт-контракт из репозитория, не внесенного в конфигурационный файл, укажите в поле name транзакции 103 полный адрес смарт-контракта в созданном вами репозитории. Пример заполнения полей транзакции 103 приведен в ее описании.

После получения транзакции нода скачивает образ по ссылке, указанной в поле``image``. Затем скачанный образ проверяется нодой и запускается в Docker-контейнере.

Запуск смарт-контракта и фиксация результатов исполнения

Запуск смарт-контракта инициируется участником сети при помощи транзакции 104 CallContract Transaction. В этой транзакции передается ID Docker-контейнера, в котором запускается смарт-контракт, а также его входные и выходные параметры в виде пар «ключ-значение». Контейнер запускается, если не был запущен ранее.

Результаты исполнения смарт-контракта фиксируются в его стейте при помощи транзакции 105 ExecutedContract Transaction.

Запрет запуска смарт-контракта

Для того, чтобы отключить запуск смарт-контракта в блокчейне, отправьте транзакцию 106 DisableContract Transaction с указанием ID Docker-контейнера, в котором запускается смарт-контракт. Отправить эту транзакцию может только участник с ролью contract_developer.

После отключения смарт-контракт становится недоступен для запуска. Информация об отключенном смарт-контракте продолжает храниться в блокчейне и доступна для gRPC или REST API-методов.

Обновление смарт-контракта

Если вы изменили код вашего смарт-контракта, обновите его. Для этого заново загрузите смарт-контракт в репозиторий Waves Enterprise, отправив завявку на обновление смарт-контракта в службу технической поддержки.

Затем отправьте на ноду транзакцию 107 UpdateContract Transaction. Обновляемый смарт-контракт не должен быть отключен при помощи транзакции 106.

После обновления смарт-контракта ноды-майнеры блокчейна скачивают его и проверяют корректность исполнения. Затем информация об обновлении смарт-контракта вносится в его стейт при помощи транзакции 105, содержащей тело исполненной транзакции 107.

Подсказка

Изменять смарт-контракт может только участник, создавший транзакцию 103 для этого смарт-контракта и имеющий роль contract_developer.

Валидация смарт-контрактов

Блокчейн-платформа поддерживает три варианта политик валидации смарт-контракта для обеспечения дополнительного контроля его целостности. Эта возможность доступна при выполнении следующих условий:

  • в сети активирована функциональная возможность 162;

  • в сети присутствует хотя бы один участник с активной ролью contract_validator;

  • для загрузки и обновления смарт-контрактов используются транзакции 103 и 107 версии 4.

Политика валидации настраивается при помощи строкового поля validationPolicy.type соответствующей транзакции.

Доступные политики валидации:

  • any – сохраняется действующая в сети общая политика валидации: для майнинга обновляемого смарт-контракта майнер подписывает соответствующую транзакцию 105. Также этот параметр устанавливается, если в сети нет ни одного зарегистрированного валидатора.

  • majority – транзакция считается валидной, если она подтверждена большинством валидаторов: 2/3 от общего числа зарегистрированных адресов с ролью contract_validator.

  • majorityWithOneOf(List[Address]) – транзакция считается валидной, если собрано большинство валидаторов, среди которых присутствует хотя бы один из адресов, включенных в список параметра. Адреса, включаемые в список, должны иметь действующую роль contract_validator.

Предупреждение

При выборе политики валидации majorityWithOneOf(List[Address]), список адресов должен содержать хотя бы один адрес, передача пустого списка запрещена.

Параллельное исполнение контрактов

Платформа Waves Enterprise позволяет запускать несколько смарт-контрактов одновременно. Такая опция поддерживается только смарт-контрактами, использующими gRPC-интерфейс для обмена данными.

Принцип параллельного исполнения нескольких смарт-контрактов:

  1. Разработчик смарт-контракта указывает параметр async-factor в коде контракта. Данный параметр определяет допустимое количество одновременно выполняемых транзакций по смарт-контракту.

  2. При старте контракт передает в ноду значение параметра async-factor.

  3. Когда запускается исполнение контрактов, транзакции на исполнение смарт-контрактов передаются из UTX-пула в буфер для необработанных транзакций смарт-контрактов до его заполнения.

  4. Транзакции, поступившие в буфер, разбиваются на группы по идентификаторам смарт-контрактов. В один момент времени допускается выполнение только одной группы, в которой параллельно выполняется async-factor транзакций.

  5. При переходе очередного смарт-контракта к выполнению освобождается одна ячейка в буфере транзакций. При этом, ячейка блокируется при поступлении транзакции из UTX-пула. Таким образом, операции заполнения буфера и обработки вызовов контракта происходят параллельно, что позволяет избежать пауз при загрузке новых транзакций.

Значение параметра async-factor может быть как установлено заранее в диапазоне от 1 до 999, так и вычисляться динамически. Вы можете устанавливать фиксированное значение этого параметра как константу, однако рекомендуется устанавливать вычисляемое значение данного параметра. Например, контракт может запросить количество свободных ядер и передать это число в качестве значения параметра async-factor. Это число будет использоваться для параллельной обработки транзакций с контрактом.

Если параметр async-factor не будет определён, то по умолчанию все транзакции с контрактом будут обрабатываться последовательно.

Параллельное исполнение нескольких смарт-контрактов иллюстрируется следующей схемой:

../../_images/docker-parallel1.png

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

API-инструменты, доступные смарт-контракту

Для обмена данными между смарт-контрактом и нодой предусмотрены методы gRPC и REST API. При использовании этих методов вы можете осуществлять широкий спектр операций с блокчейном.

Подробнее: