Узнайте, как использовать язык программирования Майкельсона и писать смарт-контракты на Tezos

Michelson, должно быть, на данный момент является одним из самых интересных языков программирования для смарт-контрактов. Это стековый, строго типизированный язык, на котором написаны смарт-контракты для обеспечения безопасности блокчейна Tezos. Байт-код Майкельсона сопоставим с байт-кодом смарт-контрактов Ethereum, но он более читаемый, безопасный и надежный. Все языки высокого уровня, которые вы можете использовать для написания смарт-контрактов для Tezos, такие как SmartPy, Ligo или Lorentz, в конечном итоге компилируются до Michelson.

В этой первой статье мы погрузимся в язык Майкельсона, поймем, что означает стековый, и напишем несколько очень простых смарт-контрактов. Эта статья в основном написана для новичков в программировании и / или разработке Tezos, но программисты среднего уровня, которые хотят узнать больше о Майкельсоне, также найдут здесь полезную информацию. Мы собираемся использовать ядро Jupyter, разработанное Baking Bad для написания кода Майкельсона в блокноте Jupyter. В каждом разделе вы найдете ссылку, если хотите увидеть, как работает код.

Напишем код!

Стек

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

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

При кодировании в Michelson вы должны помнить три основных понятия:

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

Давайте посмотрим на пример.

Операция PUSH

Если вы хотите добавить часть данных поверх стека, вы вызовете операцию PUSH. Вот как это работает:

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

PUSH value-type value

Например, если вы хотите протолкнуть целое число, вы напишите PUSH int 2, для строки вы напишите PUSH string "Tezos".

Структура смарт-контракта Майкельсона

Смарт-контракт в Michelson отображает простую структуру, состоящую из трех компонентов:

  • Тип ожидаемого параметра.
  • Тип хранилища.
  • Код Майкельсона.

Это переводится в следующий код:

parameter parameter-type ;
storage storage-type ;
code {
  ...
}

В дополнение к этой структуре есть два правила, которые вы должны учитывать при написании смарт-контракта в Майкельсоне:

  • Пара, содержащая параметр и хранилище (pair parameter storage), всегда автоматически помещается в стек при выполнении кода. Помните - если параметра нет, вместо него используется Unit.
  • Код всегда должен возвращать пару, содержащую список операций и (обновленное) хранилище (pair list(operation) storage). Выполнение остановится, когда такая пара окажется последней в стеке.

Простой смарт-контракт Майкельсона

Теперь, когда мы знаем о PUSH и структуре смарт-контракта Майкельсона, давайте напишем его!

Для этого контракта мы собираемся написать контракт «Hello world» и сохранить строку в хранилище:

Вот что происходит при выполнении этого кода:

  • parameter unit указывает, что переданный параметр имеет тип unit (в основном, без параметра).
  • storage string указывает, что контракт имеет хранилище типа string.
  • DROP - это код операции, который удаляет все, что находится наверху стека. Помните, мы говорили ранее, что пара с параметром и хранилищем автоматически включается в начало стека, мы не собираемся ее использовать, мы можем просто отбросить.
  • PUSH помещает значение на вершину стека, здесь строка «Hello world».
  • NIL - это код операции, который добавляет пустой список указанного типа (здесь operation) поверх стека.
  • PAIR берет два элемента наверху стека, создает новую пару, содержащую эти два элемента, и возвращает пару обратно в стек.

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

Добавление целых чисел и сохранение результата

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

Вот простой контракт, демонстрирующий, как это работает:

Давайте рассмотрим каждую операцию, чтобы понять, что происходит внутри стека:

  • parameter unit — Опять же, мы не используем никаких параметров, поэтому мы передаем unit.
  • storage int— На этот раз мы сохраняем в хранилище значение типа integer.
  • DROP— Нам не нужна начальная пара, поэтому мы можем избавиться от нее, чтобы освободить место для значений, которые нам действительно понадобятся.
  • PUSH int 2 ; PUSH int 3 ; - Обратите внимание, что порядок имеет решающее значение. int 2 будет внизу стека, как только вы нажмете int 3. В случае сложения порядок не имеет большого значения, но если вы, например, вычитаете два числа, важно вставлять их в правильном порядке.
  • ADD работает по тому же принципу, что и PAIR. Вы берете первые два элемента на вершину стека и получаете из них одно значение, которое вы отправляете обратно в стек. ADD сложит два числа. Обратите внимание, что числа должны быть одного и того же числового типа (вы не можете, например, сложить целое число и nat вместе).
  • NIL— Как и в предыдущем контракте, мы помещаем пустой список операций.
  • PAIR - Создает пару, содержащую список операций и новое хранилище, необходимое для остановки выполнения контракта.

Заключение

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

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

В следующей части мы продолжим погружение в Майкельсона. Мы напишем несколько простых смарт-контрактов и изучим удивительные записные книжки Jupyter, созданные командой Baking Bad, которые позволят нам писать код Майкельсона и точно понимать, что происходит.

Будьте на связи!