Skip to main content

Подгружаем

Как разработать WASM-контракт с помощью Rust в сети Ontology

Ontology

Все упомянутые логотипы и торговые марки являются собственностью соответствующих компаний.

Оригинал текста. Перевод hashrate-and-shares.ru.

С тех пор как технология Ontology Wasm была запущена в тестовой сети Ontology (Ontology TestNet), она получила широкое внимание со стороны разработчиков сообщества, поскольку эта технология снижает стоимость переноса контрактов dAPP со сложной бизнес-логикой на блокчейн, тем самым значительно обогащая dApp экосистему.

В настоящее время Ontology Wasm одновременно поддерживает разработку как на языке Rust, так и на языке C++. Язык Rust лучше поддерживает Wasm, а сгенерированный байт-код проще, что может еще больше снизить стоимость контрактных вызовов. Итак, как Вам использовать Rust для разработки контракта в сети Ontology?

Разработка WASM-контракта с помощью Rust

Создание контракта

Cargo — это хороший инструмент создания проектов и управления пакетами при разработке программ на Rust, который помогает разработчикам лучше организовывать взаимодействие кода и сторонних библиотек. Чтобы создать новый Ontology Wasm-контракт, просто выполните следующую команду:

Структура проекта, которую она генерирует:

Файл Cargo.toml используется для настройки базовой информации проекта и информации зависимой библиотеки. Секция [lib] в файле обязана быть установленной в значение crate-type = [“cdylib”]. Файл lib.rs используется для написания кода логики контракта. В добавок, Вам необходимо добавить параметры зависимостей в раздел [dependencies] файла конфигурации Cargo.toml:

С помощью этой зависимости разработчики могут вызывать интерфейсы, которые взаимодействуют с блокчейном Ontology, и инструменты такие, как параметр сериализации.

Функция ввода контракта

Каждая программа имеет функцию ввода, как например main-функция, которую мы обычно видим, но у контракта нет main-функции. Когда разрабатывается Wasm-контракт с использованием Rust, то функция invoke по умолчанию используется как функция ввода для использования контракта. Имя функции в Rust будет неясным при компиляции исходного кода Rust в байт-код, который может выполнять виртуальная машина. Чтобы предупредить компилятор от генерирования избыточного кода и сократить размер контракта, функция invoke добавляет аннотацию #[no_mangle].

Как функция invoke получает параметры для выполнения транзакции? Библиотека ontio_std предоставляет функцию runtime :: input (), чтобы получить параметры для выполнения транзакции. Разработчики могут использовать ZeroCopySource для десериализации полученного массива байтов. В котором первый считанный массив байтов — это имя invoke-метода, далее параметры метода.

Как возвращается результат выполнения контракта? Функция runtime::ret, которая предоставляется библиотекой ontio_std, возвращает результат выполнения метода.

Законченная invoke-функция выглядит следующим образом:

Сериализация и десериализация данных контракта

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

Библиотека ontio_std предоставляет интерфейсы декодера и кодера для сериализации и десериализации данных. Поля структуры struct также реализуют интерфейсы декодера и кодера, так что структура может быть сериализована и десериализована. Экземпляры класса Sink необходимы, когда сериализуются различные типы данных. Экземпляр класса Sink имеет set-тип поле buf, которое хранит байт тип данные, а все сериализованные данные хранятся в buf.

Для данных с фиксированной длиной (к примеру: byte, u16, u32, u64 и т.д.) данные непосредственно преобразуются в массив байтов и затем сохраняются в buf; для данных нефиксированной длины сначала нужно сериализовать длину, а затем D\data (например целые числа без знака неизвестного размера, включая u16, u32 или u64 и т. д.).

Десериализация является прямой противоположностью. Для каждого метода сериализации есть соответствующий метод десериализации. Десериализация требует использования экземпляров класса Source. Этот экземпляр класса имеет два поля buf и pos. Buf используется для хранения данных, которые будут десериализованы, а pos используется, чтобы хранить текущую позицию считывания. Когда считывается конкретный тип данных, если вы знаете их длину, вы можете считывать их напрямую, для данных неизвестной длины — сначала считайте длину, а затем считайте содержимое.

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

Ontology-wasm-cdt-rust — инкапсулировал операционный метод работы с данными в цепи, который удобен для разработчиков, чтобы реализовывать операции такие, как добавление, удаление, изменение и запрашивание данных в цепи следующим образом:

Ø database::get(key) — используется, что бы запросить данные из цепи, а key запрашивает реализацию интерфейса AsRef;

Ø database::put(key, value) — используется, чтобы хранить данные в сети. Key запрашивает выполнение интерфейса AsRef, а value запрашивает реализацию интерфейса Encoder;

Ø database::delete(key) — используется, чтобы удалить данные из цепочки, а key запрашивает реализацию интерфейса AsRef.

Тестирование контракта

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

Отладка контракта

Разработчики могут использовать console::debug(msg), чтобы выводить отладочную информацию во время отладки контракта. Информация msg будет внесена в лог-файл ноды. Обязательным условием является установка уровня лог-файла в режим отладки, когда запущена локальная тест-нода Ontology.

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

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

Вы разработчик? Присоединяйтесь к нашему техническому сообществу на Discord. Кроме того, загляните в Центр разработчиков на нашем сайте, там вы можете найти инструменты разработчика, документацию и многое другое.

Об Ontology

Новости Ontology

На сайте

Присоединяйтесь к нам