Posted inОсвіта та поради

Що таке смарт-контракти і як вони працюють

Розповідаємо про смарт-контракти Tezos: якою мовою програмування їх пишуть і як їх виконує віртуальна машина.

В уроці майже немає інформації про синтаксис: на цьому етапі важливіше зрозуміти, як працює віртуальна машина блокчейна.

Що таке смарт-контракти

Смарт-контракт (Smart contract) — набір функцій і даних, який зберігається в блокчейні. Смарт-контракти виконують різні завдання — від продажу токенів до управління децентралізованими організаціями. Наприклад:

  • вестинг-контракти відправляють користувачам токени в зазначений час. Ранні інвестори Tezos отримують кошти з контракту KT1KCYaULopm8i2CBbGF5EHXeXLUr4R6r2dA;
  • оракули опитують джерела даних і повертають усереднені ціни активів або іншу інформацію. Так працює оракул Harbringer, який отримує ціни криптовалют з торгових майданчиків;
  • алгоритмічні стейблкоїни випускають токени і змінюють вартість їх випуску залежно від курсу нативного токена. Смарт-контракт Kolibri коригує ціну випуску kUSD залежно від ціни tez.

Смарт-контракти виконує віртуальна машина (Virtual Machine або VM). Вона використовує обчислювальну потужність блокчейна: смарт-контракти виконують усі вузли мережі, але тільки найшвидший записує результат у блок.

Часті виклики смарт-контрактів можуть паралізувати блокчейн. Щоб цього уникнути, розробники протоколів обмежують максимальний розмір смарт-контрактів за обсягом коду і розміром комісій.

Як працюють віртуальні машини блокчейнів

Віртуальні машини "розуміють" низькорівневі мови програмування — байт-код. Вони інтерпретують такий код швидше, ніж команди мовами на кшталт JavaScript або Python. Це можна показати на прикладі однієї фрази, записаної різними словами:

  • низькорівнева мова — 2 + 2 = 4;
  • високорівнева мова №1 — два плюс два дорівнює чотири;
  • високорівнева мова №3 — Якщо Скласти два І два, Отримаємо чотири
  • високорівнева мова №2 — у результаті підсумовування двійки і двійки виходить чотири;

Під час читання ми автоматично переводимо останні рядки в найзручніший для розуміння варіант — 2 + 2 = 4. У програмуванні так само: компілятор переводить високорівневу мову в байт-код.

Віртуальна машина Tezos працює з байт-кодом Michelson. Це низькорівнева мова програмування з прямим доступом до стека — структури даних зі швидким доступом до інформації. Код на Michelson має такий вигляд:

parameter unit ; одиниця зберігання ; код  CAR ; PUSH int 3 ; PUSH int 3 ; IFCMPEQ  DROP >  DROP > ; UNIT; операція NIL;PAIR > //Функція if. Оператори PUSH двічі додають число 3 у стек. Оператор IFCMPEQ порівнює два перші елементи в стеку, а потім виконує команди < DROP >і виводить результат операції. 

Досвідчені блокчейн-розробники найчастіше пишуть смарт-контракти на Michelson. Новачкам краще використовувати високорівневі мови програмування з набором бібліотек і людиночитабельним синтаксисом.

Мови програмування смарт-контрактів на Tezos: SmartPy, LIGO і Lorentz

Учасники екосистеми Tezos розробили кілька високорівневих мов програмування. Найпопулярніші з них:

  • SmartPy — об’єктно-орієнтована мова на основі Python. Підтримує онлайн-компілятор SmartPy.io, в якому можна розробляти, тестувати і публікувати смарт-контракти.
  • LIGO — імперативна мова програмування з простою системою типів та онлайн-компілятором ide.ligolang.org. Існує кілька діалектів із синтаксисом поширених мов: PascaLIGO (Pascal), CameLIGO (OCaml), ReasonLIGO (ReasonML) і jsLIGO (JavaScript).
  • Lorentz — вбудована предметно-орієнтована мова на базі Haskell. За допомогою Lorentz розробники можуть безпосередньо працювати зі стеком Michelson.

У цьому курсі ми будемо використовувати мову з найпростішим синтаксисом — PasaLIGO.

Простий смарт-контракт з однією точкою входу

Основа смарт-контракту на LIGO — точка входу (entry point). Це головна функція смарт-контракту (main function), яка приймає вхідну транзакцію і викликає інші функції.

function ім'я_функції (const параметр_вхідної_транзакції : тип; const сховище : тип) : тип_результату is результат 

Вхідні параметри main function:

  • параметр вхідної транзакції . Функція використовує його під час виконання коду;
  • сховище [storage] . Інформація, яку потрібно зберігати в блокчейні до наступного виконання смарт-контракту, наприклад кількість токенів або записи про користувачів. Розробник задає значення storage під час розгортання смарт-контракту. Надалі вміст сховища може змінювати тільки смарт-контракт.

Вихідні параметри main function:

  • список виконаних операцій, наприклад деталі транзакцій, які відправив смарт-контракт;
  • результати виконання функцій, які прописав розробник.

Приклад смарт-контракту з функцією-інкрементом, яка приймає число і збільшує його на 1:

function main (const number : int; const сховище : int) : список (операція) * int is ((нуль : список (операція)), number + 1) 
  • function main (const number : int; const storage : int) — оголошуємо main function із вхідними параметрами number і storage. Коли користувач надсилає контракту число, головна функція сприйме його як number і виконує код;
  • : list (operation) * int — визначаємо тип результату, який повертає функція. У цьому випадку — пара зі списку виконаних операцій і число-результат;
  • is ((nil : list (operation)), number + 1) — визначаємо результат виконання функції:
  • nil : list (operation) — повертає порожній список;
  • , — слугує роздільником для значень типу tuple;
  • number + 1 — однорядкова функція, збільшує число на 1.

Смарт-контракт можна модифікувати: реалізувати декремент, піднесення до квадрата або іншу математичну операцію. У нього одна точка входу, яка активує єдиний ланцюжок функцій. Такий смарт-контракт не може виконати кілька завдань, наприклад прийняти депозит, повернути баланс і відправити транзакцію.

Смарт-контракт із кількома точками входу

Віртуальна машина починає виконання смарт-контракту з main function . Вона може виконати тільки ті функції, які викликає точка входу.

Розробники збільшують кількість операцій, створюючи псевдо-точки входу всередині головної функції. Для цього потрібно:

  1. Оголосити псевдо-точки входу і тип параметра, з яким вони працюватимуть.
  2. Описати функції, які викликатиме кожна псевдо-точка.
  3. Використовувати оператор case у головній функції. Він вкаже віртуальній машині, яку функцію викликати в разі звернення до псевдо-точки входу.

Приклад смарт-контракту з псевдо-точками — калькулятор, який приймає назву математичної операції та два числа, а повертає результат обчислень. Смарт-контракт не записує значення в storage, тому що нам для виконання математичних операцій не потрібно поміщати дані в блокчейн.

//оголошення типу numbers, який містить пару з двох чисел (tuple) type numbers is (int * int) //оголошення типів action, які містять пари чисел type action is | Addition of числа | Віднімання of числа | Множення of числа | Ділення of числа //оголошення типу даних у сховищі смарт-контракту type storage is int //оголошення математичних функцій. //(const a : int ; const b : int) - параметри функції //: int - тип результату функції //is a + b - результат виконання функції function add (const a : int ; const b : int) : int is a + b function відняти (const a : int ; const b : int) : int is a - b function множити (const a : int ; const b : int) : int is a * b function розділити (const a : int ; const b : int) : int is a / b //оголошення головної функції //призначаємо першому параметру тип action, параметру store - тип storage //функція повертає дані типів list(operation) і int - пару зі списку і числа //після is йде результат виконання функції: //1) порожній список nil : list(operation). //2) const result : int = - запис результату виконання функції в константу result. //2) case parameter of - результат виконання об'єкта типу action, //чия назва збігається з параметром вхідної транзакції. function main (const параметр : action ; const сховище : storage) : (список(операція) * int) is блок  const результат : int = case параметр of | Додавання(n1, n2) -> add(n1, n2) | Віднімання(n1, n2) -> відняти(n1, n2) | Множення(n1, n2) -> множити(n1, n2) | Ділення(n1, n2) -> розділити(n1, n2) end; //виведення результату виконання головної функції: порожній список операцій і значення result > with ((нуль : список(операція)), result) 

Якщо надіслати смарт-контракту запит із параметром Multiplication(3, 9) , він поверне число 27. Віртуальна машина виконає контракт так:

  • Зіставить параметр Multiplication з варіантами псевдо-точок під оператором case .
  • Перейде до функції multiply , яку розробник описав на початку контракту.
  • Підставить замість констант a і b параметри запиту — 3 і 9.
  • Виконає функцію multiply і запише її в store .
  • Завершить виконання головної функції — поверне порожній список і нове значення store .

Для перевірки смарт-контракту скопіюйте код калькулятора в редактор на ide.ligolang.org. Виберіть значення Dry Run зі списку, що випадає, на панелі Configure . У полі Parameters введіть назву математичної операції та два параметри, а потім натисніть кнопку Run .

Змініть значення Parameters і Storage і подивіться, як змінюється результат

Підбиваємо підсумки

Смарт-контракт — це код у блокчейні. Віртуальна машина виконує його, коли отримує транзакцію з потрібними параметрами.

Розробники пишуть смарт-контракти високорівневими мовами програмування із синтаксисом Python, Pascal, JS або Haskel. Досвідчені розробники часто пишуть байт-код на Michelson.

Смарт-контракти мовою PascalLIGO складаються зі змінних і функцій. Віртуальна машина виконує контракт починаючи з точки входу — головної функції main. У неї можна вставити псевдо-точки входу — додаткові функції.

Смарт-контракт завжди повертає результат виконання: список операцій і значення сховища storage .

  • Автор — Павло Скоропляс
  • Продюсер — Світлана Коваль
  • Стилі — Дмитро Бойко
  • Ілюстрації — Кшиштоф Шпак
  • Верстка — Зара Аракелян
  • Розробка — Олександр Пупко
  • Керівник — Влад Ліхута

Добавить комментарий