Розбір розумних контрактів: Hyperledger Fabric проти MultiChain проти Ethereum проти Corda

Вихідний вузол: 1585333

Існує більше ніж один спосіб розмістити код на блокчейні

У більшості дискусій про блокчейни не потрібно багато часу, щоб з’явитися поняття «розумні контракти». У популярній уяві розумні контракти автоматизують виконання міжсторонніх взаємодій, не вимагаючи надійного посередника. Виражаючи правовідносини в коді, а не словами, вони обіцяють надати можливість транзакціям здійснюватися безпосередньо і без помилок, навмисно чи ні.

З технічної точки зору смарт-контракт — це щось більш специфічне: комп’ютерний код, який живе в блокчейні та визначає правила для транзакцій цього ланцюжка. Цей опис звучить досить просто, але за ним криється велика кількість варіацій у тому, як ці правила виражаються, виконуються та перевіряються. При виборі блокчейн-платформи для нового додатку питання «Чи підтримує ця платформа смарт-контракти?» це не правильний запит. Натомість ми повинні запитати: «Які смарт-контракти підтримує ця платформа?»

У цій статті моя мета — вивчити деякі основні відмінності між підходами до смарт-контрактів і компромісами, які вони представляють. Я зроблю це, розглянувши чотири популярні корпоративні платформи блокчейну, які підтримують певну форму налаштованого коду в ланцюжку. По-перше, IBM Тканина Hyperledger, який називає свої контракти «ланцюговим кодом». По-друге, наша платформа MultiChain, яка представляє розумні фільтри у версії 2.0. по-третє, Ethereum (і це дозволено Кворум та Нора spin-offs), які популяризували назву «розумний контракт». І, нарешті, R3 Corda, який посилається на «контракти» у своїх транзакціях. Незважаючи на різну термінологію, в кінцевому підсумку всі вони стосуються одного і того ж – конкретного програмного коду, який визначає правила ланцюжка.

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

Основи блокчейна

Почнемо з контексту. Уявіть собі програму, яка використовується кількома організаціями, яка базується на базовій базі даних. У традиційній централізованій архітектурі цю базу даних розміщує та адмініструє одна сторона, якій довіряють усі учасники, навіть якщо вони не довіряють один одному. Транзакції, які змінюють базу даних, ініціюються лише програмами в системах цієї центральної сторони, часто у відповідь на повідомлення, отримані від учасників. База даних просто виконує те, що їй сказано, оскільки програмі неявно довіряють, щоб надсилати їй лише ті транзакції, які мають сенс.

Блокчейни надають альтернативний спосіб управління спільною базою даних без довіреного посередника. У блокчейні кожен учасник запускає «вузол», який містить копію бази даних і незалежно обробляє транзакції, які її змінюють. Учасники ідентифікуються за допомогою відкритих ключів або «адрес», кожен з яких має відповідний закритий ключ, відомий лише власнику особи. Хоча транзакції можуть створюватися будь-яким вузлом, вони «цифрово підписуються» закритим ключем ініціатора, щоб підтвердити їх походження.

Вузли з’єднуються один з одним рівноправним способом, швидко розповсюджуючи транзакції та «блоки», в яких вони мають мітки часу та підтверджуються по всій мережі. Сам блокчейн — це буквально ланцюжок цих блоків, який формує впорядкований журнал кожної історичної транзакції. «Алгоритм консенсусу» використовується для того, щоб усі вузли досягли згоди щодо вмісту блокчейна, не вимагаючи централізованого контролю. (Зауважте, що частина цього опису не стосується Corda, в якій кожен вузол має лише часткову копію бази даних і не існує глобального блокчейну. Ми поговоримо більше про це пізніше.)

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

  • Правила операцій. Якщо будь-який учасник може безпосередньо змінити базу даних, як ми гарантуємо, що він дотримується правил програми? Що заважає одному користувачеві пошкодити вміст бази даних в особистий спосіб?
  • Детермінізм. Як тільки ці правила будуть визначені, вони будуть застосовані кілька разів кількома вузлами під час обробки транзакцій для власної копії бази даних. Як ми гарантуємо, що кожен вузол отримує абсолютно однаковий результат?
  • Запобігання конфліктам. Без центральної координації, як ми матимемо справу з двома транзакціями, кожна з яких відповідає правилам програми, але, тим не менш, конфліктує одна з одною? Конфлікти можуть виникати внаслідок навмисної спроби обіграти систему або бути невинним результатом невдачі та невизначення часу.

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

Давайте почнемо з правил транзакцій, першої з цих проблем, і подивимося, як вони виражені в Fabric, MultiChain, Ethereum і Corda відповідно.

Правила операцій

Правила транзакцій виконують особливу функцію в базах даних на основі блокчейна – обмежують перетворень що можна виконати для стану цієї бази даних. Це необхідно, оскільки транзакції блокчейну можуть бути ініційовані будь-яким з його учасників, і ці учасники недостатньо довіряють один одному, щоб дозволити змінювати базу даних за бажанням.

Давайте розглянемо два приклади того, чому потрібні правила транзакцій. По-перше, уявіть собі блокчейн, призначений для агрегації та відмітки часу PDF-документів, які публікують його учасники. У цьому випадку ніхто не повинен мати права видаляти або змінювати документи, оскільки це підірве всю мету системи – збереження документів. По-друге, розглянемо блокчейн, який представляє загальну фінансову книгу, яка відстежує баланси своїх користувачів. Ми не можемо дозволити учаснику самовільно завищувати власний баланс або забирати чужі гроші.

Входи та виходи

Наші блокчейн-платформи покладаються на два широкі підходи до вираження правил транзакцій. Перша, яку я називаю «моделью введення-виведення», використовується в MultiChain і Corda. Тут транзакції явно перераховують рядки бази даних або «стани», які вони видаляють і створюють, утворюючи набір «входів» і «виходів» відповідно. Зміна рядка виражається як еквівалентна операція видалення цього рядка та створення нового на його місці.

Оскільки рядки бази даних видаляються лише на входах і створюються лише на виходах, кожен вхід повинен «витрачати» вихід попередньої транзакції. Поточний стан бази даних визначається як набір «невитрачених виходів транзакцій» або «UTXO», тобто результатів попередніх транзакцій, які ще не були використані. Транзакції також можуть містити додаткову інформацію, яку називають «метаданими», «командами» або «додатками», які не стають частиною бази даних, але допомагають визначити їх значення або мету.

Враховуючи ці три набори вхідних, вихідних даних і метаданих, дійсність транзакції в MultiChain або Corda визначається деяким кодом, який може виконувати довільні обчислення для цих наборів. Цей код може підтвердити транзакцію або повернути помилку з відповідним поясненням. Ви можете думати про модель введення-виведення як про автоматизованого «інспектора», який тримає контрольний список, який гарантує, що транзакції відповідають кожному правилу. Якщо транзакція не пройде жодної з цих перевірок, вона буде автоматично відхилена всіма вузлами мережі.

Слід зазначити, що, незважаючи на спільну модель введення-виведення, MultiChain і Corda реалізують її дуже по-різному. У MultiChain вихідні дані можуть містити активи та/або дані в JSON, текстовому або двійковому форматі. Правила визначаються в «фільтрах транзакцій» або «фільтрах потоків», які можна налаштувати на перевірку всіх транзакцій або лише тих, що включають певні активи або групи даних. На відміну від цього, вихідний «стан» Corda представлений об’єктом на мові програмування Java або Kotlin з визначеними полями даних. Правила Corda визначаються в «контрактах», які прикріплюються до конкретних станів, а контракт штату застосовується лише до транзакцій, які містять цей стан у своїх входах або виходах. Це стосується Corda's незвичайна модель видимості, у яких трансакції можуть бачити лише їхні контрагенти або ті, на чиї наступні операції вони впливають.

Договори та повідомлення

Другий підхід, який я називаю «модель контракт-повідомлення», використовується в Hyperledger Fabric та Ethereum. Тут на блокчейні можна створити кілька «розумних контрактів» або «ланцюгових кодів», і кожен з них має свою власну базу даних і пов’язаний з ним код. Базу даних контракту можна змінювати лише за допомогою його коду, а не безпосередньо за допомогою блокчейн-транзакцій. Цей шаблон проектування схожий на «інкапсуляцію» коду та даних в об’єктно-орієнтованому програмуванні.

У цій моделі транзакція блокчейну починається як повідомлення, що надсилається в контракт, з деякими додатковими параметрами або даними. Код контракту виконується як реакція на повідомлення та параметри і може вільно читати та записувати власну базу даних як частину цієї реакції. Контракти також можуть надсилати повідомлення іншим контрактам, але не можуть отримати прямий доступ до баз даних один одного. У мові реляційних баз даних контракти виступають як примусово «збережені процедури», де весь доступ до бази даних здійснюється через деякий попередньо визначений код.

І Fabric, і Quorum, різновид Ethereum, ускладнюють цю картину, дозволяючи мережі визначати кілька «каналів» або «приватних станів». Мета полягає в тому, щоб пом’якшити проблему конфіденційності блокчейну шляхом створення окремих середовищ, кожне з яких є видимим лише для певної підгрупи учасників. Хоча теоретично це звучить багатообіцяюче, насправді контракти та дані в кожному каналі чи приватному стані ізольовані від тих, що знаходяться в інших. В результаті, з точки зору смарт-контрактів, ці середовища еквівалентні окремим блокчейнам.

Приклад правил

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

  1. Загальна кількість активів у виходах транзакції має відповідати загальній кількості її входів. Це не дозволяє користувачам створювати або видаляти гроші довільно.
  2. Кожна транзакція має бути підписана власником кожного з її входів. Це не дозволяє користувачам витрачати гроші один одного без дозволу.

У сукупності ці дві умови – це все, що необхідно для створення простої, але життєздатної фінансової системи.

У моделі контракт-повідомлення контракт активу підтримує повідомлення «відправити платіж», яке приймає три параметри: адресу відправника, адресу одержувача та кількість, яку потрібно надіслати. У відповідь контракт виконує такі чотири кроки:

  1. Переконайтеся, що транзакцію підписав відправник.
  2. Перевірте, чи є у відправника достатньо коштів.
  3. Відніміть потрібну кількість із рядка відправника.
  4. Додайте цю кількість до рядка одержувача.

Якщо будь-яка з перевірок на перших двох кроках не вдасться, контракт буде розірвано, а оплата не буде здійснена.

Таким чином, як моделі введення-виведення, так і контракт-повідомлення є ефективними способами визначення правил транзакцій і забезпечення безпеки спільної бази даних. Дійсно, на теоретичному рівні кожна з цих моделей може бути використана для моделювання іншої. Однак на практиці найбільш підходяща модель буде залежати від програми, що створюється. Кожна транзакція впливає на декілька чи багато частин інформації? Чи потрібно нам бути в змозі гарантувати незалежність транзакцій? Чи має кожна частина даних чіткого власника чи є якийсь глобальний стан, яким потрібно поділитися?

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

Вбудовані правила

Коли справа доходить до правил транзакцій, є один спосіб, у якому MultiChain особливо відрізняється від Fabric, Ethereum і Corda. На відміну від цих інших платформ, MultiChain має кілька вбудованих абстракцій, які надають деякі основні будівельні блоки для додатків, керованих блокчейном, без що вимагає розробникам писати власний код. Ці абстракції охоплюють три області, які зазвичай необхідні: (a) динамічні дозволи, (b) активи, що передаються, і (c) зберігання даних.

Наприклад, MultiChain керує дозволами на підключення до мережі, надсилання та отримання транзакцій, створення активів або потоків або керування дозволами інших користувачів. Кілька взаємозамінних активів можуть бути випущені, передані, виведені з експлуатації або обмінені безпечно й атомарно. У ланцюжку можна створити будь-яку кількість «потоків» для публікації, індексації та отримання даних у ланцюжку або поза ланцюгом у JSON, текстовому або двійковому форматі. Усі правила транзакцій для цих абстракцій доступні «з коробки».

При розробці програми на MultiChain можна ігнорувати цю вбудовану функціональність і виражати правила транзакцій лише за допомогою розумних фільтрів. Однак розумні фільтри розроблені так, щоб працювати разом із своїми вбудованими абстракціями, дозволяючи їх поведінку за замовчуванням обмежений налаштованими способами. Наприклад, дозвіл на певні дії можуть керуватися певними адміністраторами, а не поведінкою за замовчуванням, якою буде займатися будь-який адміністратор. Передача певних активів може бути обмежена часом або вимагати додаткового затвердження понад певну суму. Дані в певному потоці можуть бути перевірені, щоб переконатися, що вони складаються лише із структур JSON із обов’язковими полями та значеннями.

У всіх цих випадках розумні фільтри створюють додаткові вимоги для підтвердження транзакцій, але цього не роблять видаляти прості правила, які вбудовані. Це може допомогти вирішити одну з ключових проблем у додатках блокчейну: той факт, що помилка в деякому коді мережі може призвести до катастрофічних наслідків. Ми бачили нескінченні приклади цієї проблеми в загальнодоступному блокчейні Ethereum, найбільш відомим у Загибель DAO і Помилки паритетної мультисигнатури. Більш широкі опитування знайшли велику кількість поширених вразливостей в смарт-контрактах Ethereum, які дозволяють зловмисникам красти або заморожувати кошти інших людей.

Звичайно, розумні фільтри MultiChain також можуть містити помилки, але їх наслідки більш обмежені. Наприклад, вбудовані правила активів запобігають тому, щоб один користувач витрачав гроші іншого або випадково зникав власні гроші, незалежно від того, яку іншу логіку містить розумний фільтр. Якщо в розумному фільтрі виявлено помилку, її можна деактивувати та замінити виправленою версією, при цьому основна цілісність книги буде захищена. У філософському плані MultiChain ближче до традиційних архітектур баз даних, де платформа бази даних надає ряд вбудованих абстракцій, таких як стовпці, таблиці, індекси та обмеження. Більш потужні функції, такі як тригери та збережені процедури, можуть бути запрограмовані розробниками додатків у випадках, коли вони дійсно потрібні.

Правила операцій Тканина MultiChain Ethereum Corda
Model Договір–повідомлення Введення-виведення Договір–повідомлення Введення-виведення
Вбудовані ніхто Дозволи +
активи + потоки
ніхто ніхто

Детермінізм

Переходимо до наступної частини нашої розбірки. Незалежно від того, який підхід ми виберемо, користувацькі правила транзакцій блокчейн-додатків виражаються у вигляді комп’ютерного коду, написаного розробниками додатків. І на відміну від централізованих програм, цей код буде виконуватися не один раз і в більш ніж одному місці для кожної транзакції. Це пов’язано з тим, що кілька вузлів блокчейну, що належать різним учасникам, повинні перевірити та/або виконати цю транзакцію для себе.

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

Давайте подивимося, як це виглядає на практиці, спочатку в моделі введення-виведення. Якщо два вузли мають різну думку щодо того, чи є транзакція дійсною, то один прийме блок, що містить цю транзакцію, а інший — ні. Оскільки кожен блок явно посилається на попередній блок, це створить постійну «розділку» в мережі, при цьому один або кілька вузлів не приймають думку більшості щодо вмісту всього блокчейну з цього моменту. Вузли в меншості будуть відрізані від стану бази даних, що розвивається, і більше не зможуть ефективно використовувати програму.

Тепер давайте подивимося, що станеться, якщо консенсус порушується в моделі контракт-повідомлення. Якщо два вузли мають різну думку щодо того, як контракт повинен реагувати на конкретне повідомлення, це може призвести до різниці у вмісті їхніх баз даних. Це, у свою чергу, може вплинути на відповідь контракту на майбутні повідомлення, включаючи повідомлення, які він надсилає іншим контрактам. Кінцевим результатом є зростаюча розбіжність між поглядами різних вузлів на стан бази даних. (Поле «корінь стану» в блоках Ethereum гарантує, що будь-яка різниця у відповідях контрактів негайно призведе до повністю катастрофічного форка блокчейна, замість того, щоб ризикувати залишатися прихованим протягом певного періоду часу.)

Джерела недетермінізму

Отже, недетермінізм у коді блокчейну є очевидною проблемою. Але якщо основні будівельні блоки обчислень, такі як арифметика, є детермінованими, про що нам турбуватися? Ну, виявляється, чимало речей:

  • Найбільш очевидно, генератори випадкових чисел, оскільки за визначенням вони призначені для отримання різних результатів щоразу.
  • Перевірка поточного часу, оскільки вузли не будуть обробляти транзакції в один і той же час, і в будь-якому випадку їх годинники можуть бути несинхронізовані. (Все ще можна реалізувати залежні від часу правила, посилаючись на часові позначки в самому блокчейні.)
  • Запит зовнішніх ресурсів, таких як Інтернет, дискові файли або інші програми, запущені на комп’ютері. Не можна гарантувати, що ці ресурси завжди дають однакову відповідь, і вони можуть стати недоступними.
  • Виконання кількох фрагментів коду в паралельних «потоках», оскільки це призводить до «стану гонки», коли не можна передбачити порядок завершення цих процесів.
  • Виконання будь-яких обчислень з плаваючою комою, які можуть дати навіть дещо різні відповіді на різних архітектурах процесора комп’ютера.

Наші чотири блокчейн-платформи використовують кілька різних підходів, щоб уникнути цих пасток.

Детермінізоване виконання

Почнемо з Ethereum, оскільки його підхід найбільш «чистий». Контракти Ethereum виражаються у форматі спеціального призначення, який називається «байт-код Ethereum», який виконується віртуальною машиною Ethereum («EVM»). Програмісти не пишуть байт-код безпосередньо, а генерують або «компілюють» його з мови програмування, подібної до JavaScript, яка називається Solidity. (Раніше були доступні інші мови, але з тих пір їх заборонено.) Детермінізм гарантується тим, що байт-код Solidity та Ethereum не можуть кодувати жодні недетерміновані операції – це так просто.

Фільтри MultiChain і контракти Corda вибирають інший підхід, адаптуючи наявні мови програмування та середовища виконання. MultiChain використовує JavaScript, який працює в Google V8 двигун, який також складає ядро ​​браузера Chrome і платформи Node.js, але з вимкненими джерелами недетермінізму. Аналогічно, Corda використовує Java або Котлін, обидва з яких компілюються до «байт-коду Java», який виконується у віртуальній машині Java («JVM»). Наразі Corda використовує стандартну недетерміновану JVM Oracle, але ведеться робота з інтеграції детермінована версія. Тим часом розробники контрактів Corda повинні подбати про те, щоб не допускати недетермінізму в своєму коді.

Як пуризм Ethereum порівнюється з еволюційним підходом MultiChain і Corda? Основною перевагою Ethereum є мінімізація ризику — створена для цілей віртуальна машина з меншою ймовірністю містить ненавмисне джерело недетермінізму. Хоча будь-який подібний недогляд можна було б виправити оновленням програмного забезпечення, він був би руйнівним для будь-якого ланцюга, якому не пощастило зіткнутися з ним. Однак проблема Ethereum полягає в тому, що Solidity і EVM є крихітною екосистемою, що зароджується в більш широкому контексті мов програмування та середовищ виконання. Для порівняння, JavaScript і Java є дві найкращі мови на Github, працює на мільярдах цифрових пристроїв і оптимізовано протягом десятиліть. Мабуть, саме тому публічний блокчейн Ethereum розглядає перехід на Ewasm, детермінована розгалуження нового стандарту WebAssembly.

Детермінізм шляхом індосаменту

Коли справа доходить до детермінізму, Hyperledger Fabric використовує зовсім інший підхід. У Fabric, коли «клієнтський» вузол хоче надіслати повідомлення певному ланцюговому коду, він спочатку надсилає це повідомлення деяким вузлам «підтримувача». Кожен з цих вузлів виконує ланцюговий код незалежно, формуючи думку про повідомлення ефект у базі даних цього ланцюгового коду. Ці висновки надсилаються назад клієнту разом із цифровим підписом, який є офіційним «підтвердженням». Якщо клієнт отримує достатню кількість підтверджень передбачуваного результату, він створює транзакцію, що містить ці схвалення, і транслює її для включення в ланцюжок.

Щоб гарантувати детермінізм, кожна частина ланцюгового коду має «політику схвалення», яка точно визначає, який рівень схвалення потрібен, щоб зробити його транзакції дійсними. Наприклад, у політиці одного ланцюгового коду може бути зазначено, що підтримка вимагається принаймні від половини вузлів блокчейну. Для іншого може знадобитися схвалення будь-якої з трьох довірених сторін. У будь-якому випадку, кожен вузол може самостійно перевірити, чи були отримані необхідні підтвердження.

Щоб прояснити різницю, детермінізм у більшості платформ блокчейн базується на питанні: «Який результат запуску цього коду на цих даних?» – і ми повинні бути абсолютно впевнені, що кожен вузол відповість на це питання однаково. Навпаки, детермінізм у Fabric ґрунтується на іншому питанні: «Чи погоджується достатня кількість підтримувачів щодо результату виконання цього коду на цих даних?» Відповідь на це досить проста справа підрахунку, і немає місця для недетермінізму.

Детермінізм Fabric за схваленням має ряд цікавих наслідків. По-перше, ланцюговий код можна написати багатьма різними мовами програмування, оскільки їх не потрібно адаптувати для детермінізму (наразі підтримуються Go, Java та JavaScript). По-друге, ланцюговий код може бути прихований від деяких учасників блокчейну, оскільки його мають виконувати лише клієнти та індосанти (сама база даних є глобальною). І, нарешті, найголовніше, ланцюговий код Fabric може робити те, що заборонено в інших середовищах блокчейну, наприклад перевіряти погоду за допомогою онлайнового веб-API. У гіршому випадку, коли кожен індосант отримує різну відповідь від цього API, клієнт не зможе отримати достатньо схвалення для будь-якого конкретного результату, і транзакція не відбудеться. (Слід зазначити, що члени команди Fabric все ще рекомендувати використання детермінованої логіки всередині ланцюгового коду, щоб уникнути несподіванок.)

Яку ціну Fabric платить за цю гнучкість? Якщо мета блокчейну полягає в тому, щоб видалити посередників із програми на основі спільної бази даних, то залежність Fabric від індоссерів робить великий крок від цієї мети. Для учасників ланцюга вже недостатньо дотримуватися правил ланцюгового коду – їм також потрібні певні інші вузли, щоб погодитися, що вони це зробили. Ще гірше те, що зловмисний підбір індоссерів може схвалити зміни бази даних, які взагалі не відповідають ланцюговому коду. Це дає індоссерам набагато більше повноважень, ніж валідатори в звичайних блокчейнах, які можуть цензурувати транзакції, але не можуть порушувати правила блокчейну. Розробники блокчейн-додатків повинні вирішити, чи має цей компроміс сенс у їх конкретному випадку.

Детермінізм Тканина MultiChain Ethereum Corda
Model Затвердження Адаптований час виконання Спеціальна ВМ Адаптований час виконання
мови Go + Java + JavaScript JavaScript Solidity Java + Kotlin
Видимість коду Контрагенти +
індосанти
Blockchain Blockchain Контрагенти +
утриманці
Насильницькі Немає Так Так ні (поки що)

Запобігання конфліктам

Наразі ми обговорювали, як різні платформи блокчейну виражають правила транзакцій у коді, і як вони детерміновано гарантують, що кожен вузол однаково застосовує ці правила. Тепер настав час поговорити про третій аспект нашого протистояння: як кожна платформа бореться з можливістю того, що дві транзакції, які самі по собі дійсні, конфліктують одна з одною? У найпростішому прикладі уявіть, що Аліса має 10 доларів у фінансовій книзі й транслює дві трансакції: одна надсилає 8 доларів Бобу, а інша — 7 доларів Чарлі. Очевидно, що лише одна з цих трансакцій може бути успішною.

Дві моделі

Ми можемо почати з групування підходів MultiChain і Corda до цієї проблеми разом. Як було описано раніше, обидва вони використовують модель введення-виведення для представлення транзакцій та їх правил, у яких кожна введена транзакція витрачає вихід попередньої транзакції. Це веде до простого принципу запобігання конфліктам: кожен результат можна витратити лише один раз. Фільтри MultiChain і контракти Corda можуть покладатися на свої відповідні платформи, щоб повністю застосувати це обмеження. Оскільки 10 доларів Аліси представлені результатом попередньої транзакції, це правило одноразових витрат автоматично зупиняє її надсилання як Бобу, так і Чарлі.

Незважаючи на цю схожість, важливо вказати на ключову відмінність у тому, як MultiChain і Corda запобігають конфліктам. У MultiChain кожен вузол бачить кожну транзакцію і тому може незалежно перевірити, що кожен вихід витрачається лише один раз. Будь-яка трансакція, яка виконує подвійні витрати проти раніше підтвердженої трансакції, буде миттєво й автоматично відхилена. Натомість у Corda немає глобального блокчейну, тому для запобігання подвійним витратам потрібні «нотаріуси». Кожен вихідний стан Corda призначається нотаріусу, який повинен підписати будь-яку транзакцію, яка витрачає цей вихід, підтверджуючи, що він не був витрачений раніше. Учасники блокчейну повинні довіряти нотаріусам чесно дотримуватися цього правила, а зловмисні нотаріуси можуть спричинити хаос за бажанням. Як і у випадку з рекомендаціями в Fabric, це «одноразові витрати як послуга” дизайн має переваги з точки зору конфіденційності, але знову залучає посередників, що суперечить принципу блокчейна. (Важливо пояснити, що нотаріуси Corda можуть керуватися групами учасників за допомогою алгоритму консенсусу, тому цілісність книги все ще може бути захищена від окремих поганих акторів).

Переходимо до Ethereum. Нагадаємо, Ethereum використовує контракти та повідомлення, а не входи та виходи. В результаті конфлікти транзакцій, такі як два платежі Аліси, не відразу видно для механізму блокчейна. Натомість вони виявляються та блокуються контракт який обробляє транзакції, після того як їх замовлення буде підтверджено в ланцюжку. Під час обробки кожного платежу Аліси контракт перевіряє, чи достатній її баланс. Якщо трансакція з виплатою 8 доларів Бобу буде першою, вона буде оброблена як зазвичай, залишивши Алісу на рахунку 2 доларів. В результаті, коли контракт обробляє другу транзакцію, сплачуючи 7 доларів Чарлі, він бачить, що Алісі не вистачає необхідних коштів, і транзакція припиняється.

Виходи проти контрактів

Наразі ми бачили дві різні методики запобігання конфліктним транзакціям – вихідні дані за одну витрату в MultiChain і Corda і перевірку на основі контракту в Ethereum. Так що краще?

Щоб допомогти відповісти на це запитання, давайте розглянемо приклад облікового запису «1 з 2 мультипідписів», на якому зберігається 100 доларів США від імені Гевіна та Хелен і дозволяє кожному з них витрачати ці гроші самостійно. Гевін доручає своїй заявці заплатити 80 доларів Донні, а через кілька секунд Хелен хоче надіслати 40 доларів Едварду. Оскільки коштів для обох платежів недостатньо, ці операції неминуче будуть конфліктувати. Якщо обидві транзакції транслюються, результат буде визначатися тим, хто першим потрапить у ланцюжок. Зауважте, що на відміну від прикладу Аліси, цей конфлікт є випадковість, оскільки ніхто не намагається порушити правила програми – у них просто невдалий час.

Розглядаючи ймовірність виникнення цього конфлікту, ключове питання полягає в наступному: після того, як Гевін відправить свою транзакцію, скільки часу знадобиться вузлу Хелен, щоб дізнатися, що її платіж може бути невдалим? Чим коротший цей період, тим більша ймовірність, що Хелен зупинять спробу оплати, врятуючи її та її заяву від несподіванки.

З моделлю введення-виводу будь-який конфлікт між транзакціями безпосередньо видно платформі блокчейн, оскільки дві транзакції будуть явно намагатися витратити той самий попередній вихід. У MultiChain це відбувається, як тільки транзакція Гевіна поширюється на вузол Хелен, зазвичай за секунду або менше. У Corda нотаріус виходу відхилить запит на підписання транзакції Хелен, оскільки він уже підписав угоду Гевіна, тому Хелен миттєво дізнається, що її платіж не вийде. (Хоча, якщо нотаріус Corda сам розповсюджується, їй, можливо, доведеться почекати кілька секунд на відповідь.) У будь-якому випадку, немає необхідності чекати підтвердження та замовлення транзакції в блокчейні.

А як щодо моделі Ethereum? У цьому випадку платформа блокчейн не може негайно дізнатися, що станеться конфлікт. Хоча вузол Хелен може бачити транзакцію Гевіна в мережі, він не може знати, як це вплине на власну транзакцію Хелен, оскільки з його точки зору це просто два повідомлення, які надсилаються одному контракту. Можливо, через десять секунд, коли остаточне впорядкування конфліктуючих транзакцій буде підтверджено в блокчейні, вузол Хелен перерахує фактичний замість очікуваного результату, і її програма відповідно оновить своє відображення. Тим часом і Гевін, і Хелен залишаться в темряві.

Але ми не повинні робити з цього висновок, що модель введення-виведення завжди працює найкраще. Розглянемо варіант нашого прикладу сценарію, коли і Гевін, і Хелен вимагають менші платежі в 40 доларів США з початкового балансу в 100 доларів США в один і той же час. У моделі введення-виведення ці транзакції будуть конфліктувати, оскільки обидві вони витрачають один і той же рядок бази даних, що містить ці 100 доларів, і лише один із платежів буде успішним. Але в Ethereum обидві транзакції будуть успішно оброблені, незалежно від їх остаточного порядку, оскільки рахунок містить достатньо коштів для обох. У цьому випадку Ethereum більш вірно виконує наміри Гевіна і Хелен.

Набори для читання-запису

Нарешті, давайте поговоримо про Fabric, чий підхід, заснований на схваленні, є гібридом цих двох методів. Як пояснювалося раніше, коли «клієнтський» вузол Fabric хоче надіслати повідомлення до контракту, він спочатку просить деякі підтверджуючі вузли виконати це повідомлення від його імені. Вузли-підтримки роблять це подібно до Ethereum – виконують контракт у своїй локальній базі даних – але цей процес спостерігається, а не відразу застосовується. Кожен індосант записує набір рядків, які будуть прочитані та записані, відзначаючи також точну версію цих рядків на той момент часу. Цей «набір для читання-запису» версійних рядків явно посилається в індосаменті та включається в транзакцію, яку транслює клієнт.

Конфлікти між транзакціями Fabric вирішуються після завершення їхнього замовлення в ланцюжку. Кожен вузол обробляє кожну транзакцію незалежно, перевіряючи політику підтримки та застосовуючи вказані зміни в базі даних. Однак, якщо транзакція читає або записує версію рядка бази даних, яка вже була змінена попередньою транзакцією, ця друга транзакція ігнорується. Щоб повернутися до суперечливих платежів Аліси Бобу та Чарлі, обидві ці транзакції будуть читати та змінювати ту саму версію рядка, що містить 10 доларів, з яких Аліса починала. Таким чином, друга транзакція буде безпечно й автоматично перервана.

Підхід Fabric до вирішення конфліктів працює чудово, але з точки зору продуктивності та гнучкості він поєднує найгірше з двох попередніх моделей. Оскільки індосаменти перетворюють транзакції в конкретні набори для читання-запису, одночасні, але сумісні платежі 40 доларів Гевіна та Хелен призведуть до конфлікту, якого Ethereum уникає. Однак Fabric не отримує переваги в швидкості моделі введення-виводу, оскільки індосанти виконують контракти з останньою версією бази даних, підтвердженою блокчейном, ігноруючи непідтверджені транзакції. Отже, якщо Хелен ініціює свій платіж через кілька секунд після Гевіна, але до того, як Гевін буде підтверджено в блокчейні, Fabric створить конфліктні транзакції, яких уникає чиста модель введення-виведення.

Запобігання конфліктам Тканина MultiChain Ethereum Corda
Model Набори для читання-запису Поодинокі витрати Перевірки контрактів Поодинокі витрати
перевірка Незалежний Незалежний Незалежний Довірені нотаріуси
швидкість ~10 с (підтвердження) ~1с (розповсюдження) ~10 с (підтвердження) 0~5с (нотаріус)

Складний вибір

У цій статті ми розглянули багато різних способів, за допомогою яких Corda, Ethereum, Fabric і MultiChain вирішують ключові проблеми «розумних контрактів» або коду програми, вбудованого в блокчейн. І кожна платформа має різні відповіді на наші три основні запитання: як представлені правила транзакцій? Як код виконується детерміновано? А як запобігти конфліктам?

Тож хто переможець у нашому розборці смарт-контрактів? Наразі має бути очевидно, що простої відповіді немає. Кожна платформа являє собою складний багатосторонній компроміс між гнучкістю, простотою, продуктивністю, припиненням посередництва, безпекою та конфіденційністю. Отже, вибір платформи для конкретної програми має починатися з детального розуміння моделі довіри цієї програми, типів транзакцій, які вона включає, та їх ймовірних моделей конфліктів. Якщо ви виявите, що хтось просуває конкретне рішення для смарт-контрактів, перш ніж він дізнається відповіді на ці запитання, я пропоную ввічливо, але твердо наполягати на тому, щоб вони застосували «розумніший» підхід.

Будь ласка, залишайте будь-які коментарі на LinkedIn.

Часова мітка:

Більше від Багатоканальний