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

(Сначала отметьте Часть 1 и Часть 2)

В этом новом выпуске нашей серии о языке Майкельсона мы собираемся поднять его на ступеньку выше!

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

В отличие от смарт-контрактов Ethereum, смарт-контракты на Tezos не изменяют хранилище на любом этапе выполнения транзакции. Новое хранилище возвращается в конце выполнения, если все прошло хорошо. Это делает смарт-контракты на Tezos чрезвычайно безопасными: Майкельсон позаботится о том, чтобы все выполнялось должным образом, прежде чем изменять хранилище. Solidity изменит хранилище и надеюсь, что в будущем проблем не возникнет 😊

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

Получайте лучшие криптовалютные сделки прямо в свой почтовый ящик

Код Майкельсона

Весь код смарт-контракта доступен в Папке Jupyter notebook. После перехода на страницу и ожидания загрузки ядра Майкельсона в течение минуты выберите MichelsonTutorial-Demo4.ipynb, чтобы увидеть код. Что касается последнего урока, вы можете увидеть встроенный код или выполнить его пошагово.

Давайте посмотрим на встроенный код:

Удивительно, насколько мощен такой небольшой фрагмент кода

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

Вероятно, вы узнали несколько кодов операций, которые были представлены на предыдущих уроках: DUP, CAR, PAIR, NIL, и т. д. Также появились новые инструкции: DIG, SENDER, IFCMPEQ, FAIL и т. д. Не беспокойтесь, мы вот-вот увидят, что они делают.

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

Пошаговое выполнение

А теперь давайте посмотрим, что делает код!

Сначала в стек помещается пара, содержащая предоставленный параметр и хранилище:

DUP

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

АВТОМОБИЛЬ

Помните CAR? Он берет пару наверху стека и извлекает ее левое значение:

DIP {CDR; DUP; CDR}

Это очень интересная и полезная инструкция! Как видите, инструкция состоит из двух частей: части DIP и части между фигурными скобками.

Инструкция DIP «защищает» элемент стека, на который она ссылается. Если после DIP нет числа, он защитит первый элемент на вершине стека. Вы также можете использовать DIP 2 или DIP 10 в зависимости от количества элементов. За инструкцией DIP следует в фигурных скобках некоторый код, который влияет на элемент под элементом, защищенным инструкцией. Таким образом, если вы напишете DIP 0 {code}, это будет как если бы вы написали код, а если бы вы написали DIP 1 {code} , как если бы вы написали DIP {код}:

Код между фигурными скобками не должен содержать для вас секрета: он извлечет правую часть пары (CDR), которая также является парой, продублирует ее (DUP) и извлеките его правую часть (CDR):

DIG 2

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

АВТОМОБИЛЬ

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

DUP

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

ОТПРАВИТЕЛЬ

Еще один новый код операции! SENDER помещает адрес, инициировавший текущую транзакцию, поверх стека. В смарт-контракте Tezos есть небольшая разница между двумя инструкциями: SENDER и SOURCE. ОТПРАВИТЕЛЬ будет адресом, по которому была создана текущая транзакция. Это означает, что если ваш смарт-контракт получает транзакцию от другого смарт-контракта, ОТПРАВИТЕЛЬ будет этим адресом смарт-контракта. ИСТОЧНИК - это всегда неявный адрес учетной записи (т. е. учетная запись, с которой была инициирована самая первая транзакция).

В данном случае это не имеет большого значения, но может быть важно в других ситуациях:

IFCMPEQ {} {FAIL}

Добро пожаловать в вашу первую условную структуру в Michelson 👏🏻 IFCMPEQ означает «IF CoMPare EQual» и сообщит вам, равны ли два значения в верхней части стека. Обратите внимание, что два значения должны быть сопоставимого типа и одного типа.

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

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

После завершения сравнения два значения, которые были наверху стека, удаляются:

DIP {SWAP; CONCAT}

Еще одна инструкция по DIP! Мы проверили, что пользователю, отправившему транзакцию, разрешено изменять хранилище, поэтому мы можем объединить предоставленную им строку с той, которая находится в хранилище!

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

Затем мы хотим переупорядочить две строки, которые есть в нашем стеке, чтобы они имели «Hello» перед «world». Это задание для кода операции SWAP. Как только они будут расположены в правильном порядке, мы можем объединить их с помощью CONCAT. Поскольку мы использовали DIP и поместили следующие две инструкции между фигурными скобками, код проигнорирует первый элемент стека и будет работать со следующими:

ПАРА

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

Используя инструкцию PAIR, мы создаем новую пару, левым элементом которой является элемент с индексом 0 в стеке, а правым элементом является элемент с индексом 1:

NIL операция

Теперь в этой инструкции для вас не должно быть секрета! Мы помещаем пустой список операций поверх нашего нового хранилища:

ПАРА

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

Когда стек содержит только пару со списком операций и хранилищем, все готово, и выполнение может завершиться успешно 🥳

Вы также можете визуализировать весь процесс исполнения смарт-контракта в этом видео:

Заключение

На этом заканчивается часть 3 нашего руководства по языку Майкельсона. Он представил несколько новых инструкций, которые будут чрезвычайно полезны в ваших смарт-контрактах: DIP, DIG, IFCMPEQ, FAIL , ОТПРАВИТЕЛЬ и т. д.

Теперь вы лучше понимаете общую схему смарт-контракта, написанного на языке Майкельсона, как различные элементы перемещаются и взаимодействуют друг с другом. Условные структуры - очень мощный инструмент для проверки данных, поступающих в смарт-контракт посредством транзакций, например, разрешено ли отправителю выполнить действие, было ли отправлено нужное количество tezzies и т. Д. DIG и DIP также являются важными инструкциями, поскольку в предыдущих руководствах мы были ограничены самой вершиной стека, но эти инструкции позволяют нам манипулировать элементами глубже в стеке.

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

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

Получайте лучшие предложения по программному обеспечению прямо в свой почтовый ящик