Автор: Тіа, Techub News
Блокчейн жертвує ефективністю через свій децентралізований дизайн, тому підвищення швидкості виконання завжди було одним з термінових завдань. 'Виконавчий шар' блокчейну є ключовою частиною обробки кожної транзакції та її включення в ланцюг. Щоб прискорити обробну здатність, покращення на виконавчому шарі стало однією з основних стратегій, і паралельне виконання є важливим проривом у цьому напрямку.
Традиційний блокчейн зазвичай обробляє транзакції послідовно, що суттєво обмежує швидкість транзакцій, особливо в мережах з інтенсивними транзакціями, які призводять до заторів. Однак через паралельне виконання кілька транзакцій можуть оброблятися одночасно, що значно підвищує ефективність виконання та зменшує навантаження на ланцюг.
Щоб краще зрозуміти, що таке паралельність, ми спочатку почнемо з виконання і використаємо Ефіріум у режимі PBS після злиття як приклад, щоб пояснити, що таке виконання, одночасно демонструючи місце виконання в усьому життєвому циклі транзакцій.
Конкретні етапи виконання транзакцій
Транзакція входить до пам'яті та відфільтровується і сортується: це етап попередньої обробки після подання транзакції, що включає взаємодію Mempool, Searcher та Builder, завершує фільтрацію та сортування транзакцій.
Будівельник створює блок (але не виконує): Будівельник розміщує вигідні транзакції в блоці, щоб завершити упаковку та сортування транзакцій.
Пропозиціонер перевіряє та подає блок: після завершення побудови блоку Будівельник надсилає пропозицію блоку Пропозиціонеру. Пропозиціонер перевіряє структуру блоку та зміст транзакцій, потім офіційно подає блок до мережі для початку виконання.
Виконання транзакції: після подання блоку вузли виконують транзакції в блоці по черзі. Це критичний етап оновлення стану, кожна транзакція викликає виклик смарт-контракту, зміну балансу рахунку або зміну стану.
Свідок засвідчує: валідатор засвідчує результати виконання блоку та корінь стану, і підтверджує їх як остаточне підтвердження. Це забезпечує достовірність і дійсність блоку на виконавчому шарі та запобігає несумісності.
Синхронізація стану: кожен вузол синхронізує результати виконання блоку (наприклад, баланс рахунку, оновлення стану контракту тощо) до свого локального стану, після виконання кожної транзакції вузол обчислює та зберігає новий корінь стану, щоб використовувати його як початковий стан у наступному блоці.
Звичайно, це лише синхронізація стану транзакцій за блоками, щоб підтримувати актуальний стан на ланцюгу, зазвичай вузли синхронізують дані по одному блоку та постійно перевіряють блоки та стан. Але щоб досягти остаточності в механізмі POS, агрегатору потрібно об'єднати підписи свідків у кожному слоті в один повний підпис і передати його до пропозиціонера наступного слоту, а валідатору потрібно, після одного епохи, підтвердити стан усіх блоків у цьому епоху на основі кількості голосів, сформувавши тимчасову точку перевірки консенсусу. Коли два послідовні епохи отримають підтримку більшості валідаторів, блоки та транзакції досягнуть остаточності.
З точки зору всього життєвого циклу транзакцій, виконання відбувається після того, як Пропозиціонер перевіряє структуру блоку та зміст транзакцій, надісланих Будівельником. Фактичний процес виконання потребує покрокової обробки транзакцій та оновлення відповідних станів рахунків або контрактів. Після завершення всіх транзакцій Пропозиціонер обчислює новий корінь стану (корінь Меркле), що є підсумком результатів виконання всіх транзакцій поточного блоку та остаточного глобального стану. Простими словами, повний процес виконання блоку включає в себе серію обчислень, необхідних для переходу Ефіріуму з попереднього стану до наступного.
Послідовне виконання
На відміну від паралельного виконання, існує послідовне виконання, що є досить поширеним способом виконання в сучасних блокчейнах. Зазвичай транзакції виконуються по порядку. Після завершення виконання транзакції, Ефіріум оновлює стан рахунку та відповідну інформацію (наприклад, баланс, дані зберігання контрактів) у дереві стану рахунку, новий хеш стану рахунку генерується. Після завершення оновлення стану Меркле-дерева, хеш кореня дерева стану, відомий як корінь стану Меркле, формується. Після завершення кореня стану Меркле, кореня транзакцій Меркле та кореня отриманих документів, заголовок блоку підлягає обчисленню хешу, генеруючи хеш блоку.
У цьому контексті порядок виконання транзакцій є критично важливим. Оскільки Меркле-дерево є бінарним деревом хешів, різні порядки формують різні значення кореня Меркле.
Паралельне виконання
У середовищі паралельного виконання вузли намагаються обробляти транзакції в блоці паралельно. Вони не виконують транзакції по черзі, а розподіляють транзакції на різні 'виконавчі шляхи', щоб вони могли виконуватися одночасно. Через паралельне виконання система може ефективніше обробляти транзакції в блоці, підвищуючи пропускну здатність.
Після виконання всіх транзакцій вузли підсумовують результати виконання (тобто оновлення стану, на яке вплинули транзакції), формуючи новий стан блоку. Цей стан буде додано до блокчейну, представляючи найновіший глобальний стан на ланцюгу.
Конфлікт стану
Оскільки паралельність обробляє транзакції одночасно на різних шляхах, основним викликом паралельності є конфлікт стану. Це означає, що можуть існувати кілька транзакцій, які намагаються одночасно виконати операції з читання або запису до одного й того ж фрагмента даних (стану) на блокчейні. Якщо не впоратися з цією ситуацією, це призведе до невизначених результатів виконання. Оскільки порядок оновлення стану різний, кінцеві результати обчислень також можуть бути різними. Наприклад,
Припустимо, є дві транзакції, транзакція A та транзакція B, які намагаються оновити баланс одного і того ж рахунку:
Транзакція A: збільшити баланс рахунку на 10.
Транзакція B: збільшити баланс рахунку на 20.
Початковий баланс рахунку становить 100.
Якщо ми виконуватимемо послідовно, порядок виконання буде визначеним:
1. Спочатку виконується транзакція A, потім транзакція B:
Баланс рахунку спочатку збільшується на 10, стає 110.
Потім збільшується на 20, в результаті стає 130.
2. Спочатку виконується транзакція B, потім транзакція A:
Баланс рахунку спочатку збільшується на 20, стає 120.
Потім збільшується на 10, в результаті стає 130.
У обох порядках остаточний баланс становитиме 130, оскільки система забезпечує узгодженість порядку виконання транзакцій.
Але в умовах паралельного виконання транзакція A та транзакція B можуть одночасно читати початковий баланс 100 і виконувати свої розрахунки:
Транзакція A читає баланс 100, після обчислення оновлює баланс до 110.
Транзакція B також читає баланс 100, після обчислення оновлює баланс до 120.
У такому випадку, оскільки транзакції виконуються одночасно, остаточний баланс оновлюється лише до 120, а не до 130, оскільки операції транзакцій A та B 'перекривають' результати одне одного, викликаючи конфлікт стану.
Ці проблеми конфлікту стану зазвичай називають 'перекриттям даних', тобто коли транзакції намагаються одночасно змінити одні й ті ж дані, що може призвести до перекриття обчислювальних результатів одне одного, що в результаті призводить до неправильного стану. Інша проблема, що виникає внаслідок конфлікту стану, полягає в тому, що не можна гарантувати порядок виконання. Оскільки кілька транзакцій завершують операції в різні проміжки часу, це викликає різний порядок виконання. Різний порядок може призвести до різних обчислювальних результатів, що робить результат невизначеним.
Щоб уникнути цієї невизначеності, системи паралельного виконання блокчейну зазвичай впроваджують деякі механізми перевірки конфліктів та відкату або заздалегідь аналізують залежності транзакцій, щоб забезпечити паралельне виконання без впливу на остаточну узгодженість стану.
Оптимістична паралельність і детерміністична паралельність
Існує два способи відношення до можливих конфліктів стану: детермінована паралельність і оптимістична паралельність. Обидві моделі мають свої компроміси в ефективності та складності дизайну.
Детермінована паралельність вимагає заздалегідь оголосити доступ до стану, валідатор або секвенсер перевіряє оголошений доступ до стану під час сортування транзакцій. Якщо кілька транзакцій намагаються записати в один і той же стан, ці транзакції позначаються як конфліктуючі, щоб уникнути одночасного виконання. Конкретна реалізація попереднього оголошення доступу до стану на різних ланцюгах різна, але зазвичай включає кілька способів:
Через специфікації контрактів: розробники безпосередньо визначають область доступу до стану в смарт-контрактах. Наприклад, переказ ERC-20 вимагає доступу до полів балансу відправника та отримувача.
Через структуровані дані транзакцій: у транзакцію додаються спеціальні поля для позначення доступу до стану.
Через аналіз компілятора: компілятори високорівневих мов можуть статично аналізувати код контракту та автоматично генерувати набір доступу до стану.
Заява про примус через фрейм: деякі фрейми вимагають від розробників явно вказувати стан, до якого потрібно отримати доступ під час виклику функцій
Оптимістична паралельність раніше обробляє транзакції, а коли конфлікти виникають, повторно виконує постраждалі транзакції по порядку. Щоб максимально уникнути конфліктів, основа дизайну оптимістичної паралельності полягає в швидкій оцінці та припущенні стану через історичні дані, статичний аналіз тощо. Тобто система, не повністю верифікуючи, припускає, що певні операції або оновлення стану є дійсними, намагаючись уникнути затримки всіх процесів верифікації, таким чином підвищуючи продуктивність та пропускну здатність.
Хоча оптимістична паралельність може максимально уникати конфліктів через швидку оцінку стану та припущення, все ж існують деякі невідворотні виклики, особливо в контексті виконання контрактів або міжланцюгових транзакцій. Якщо конфлікти виникають часто, повторне виконання може суттєво сповільнити продуктивність системи та збільшити споживання обчислювальних ресурсів.
Детермінована паралельність перевіряє залежність стану перед транзакцією, щоб уникнути конфліктів, які можуть виникнути в оптимістичній паралельності, але оскільки потрібно точно вказувати залежності стану перед поданням транзакції, це ставить вищі вимоги до розробників, що ускладнює реалізацію.
Парадокс EVM паралельності
Стан конфлікту має не лише детерміністичний і оптимістичний аспекти, але й у конкретному процесі реалізації паралельності потрібно враховувати це з точки зору архітектури ланцюгової бази даних. Проблема конфлікту стану в паралельності є особливо складною у EVM під архітектурою Меркле-дерева. Меркле-дерево є ієрархічною хеш-структурою, і після кожної транзакції, що змінює певні дані стану, коренева хеш-значення Меркле-дерева також потрібно оновити. Цей процес оновлення є рекурсивним, обчислюючись з листяних вузлів до кореня. Оскільки хеші є незворотними, тобто можна обчислити верхні рівні лише після завершення змін нижчих рівнів, ця риса ускладнює паралельне оновлення.
Якщо дві транзакції виконуються паралельно і доступають до одного й того ж стану (наприклад, балансу рахунку), виникає конфлікт вузлів Меркле-дерева. Зазвичай для вирішення таких конфліктів потрібні додаткові механізми управління транзакціями, щоб забезпечити отримання узгодженого кореня хеш-значення в кількох гілках. Це не легко реалізувати для EVM, оскільки потрібно знайти баланс між паралелізацією та узгодженістю стану.
Не-EVM паралельні рішення
Solana
На відміну від глобального дерева стану Ефіріуму, Solana використовує модель рахунків. Кожен рахунок є незалежним простором зберігання, що зберігається в книзі, тому уникнути проблеми конфлікту шляхів.
Solana є детермінованою паралельністю. У Solana кожна транзакція повинна під час подання чітко заявити, які рахунки будуть доступні та які потребуються права доступу (тільки для читання або читання та запису). Цей дизайн дозволяє вузлам блокчейну заздалегідь аналізувати ресурси, доступні для кожної транзакції, до її виконання. Оскільки залежності всіх рахунків чітко визначені до початку виконання, вузол може визначити, які транзакції будуть отримувати доступ до одного й того ж рахунку, а які транзакції можуть безпечно виконуватися паралельно, таким чином реалізуючи розумне планування, щоб уникнути конфліктів, забезпечуючи основу для паралельного планування.
Оскільки кожна транзакція вже оголосила рахунки та права доступу, які їй потрібні перед виконанням, Solana може перевіряти, чи існують залежності між транзакціями (модель Sealevel). Якщо між транзакціями немає спільних рахунків для читання і запису, система може призначити їх на різні процесори для паралельного виконання.
Aptos
Дизайн паралельного виконання Aptos значно відрізняється від Ефіріуму, оскільки він вніс кілька ключових інновацій в свою архітектуру та механізми, головним чином у моделі рахунків і зберіганні стану.
Ефіріум під час виконання транзакцій потребує частого оновлення глобального стану дерева (MPT). Всі рахунки та контракти зберігаються в спільному дереві стану, і будь-яка транзакція потребує доступу до частини цього дерева стану та його оновлення. Aptos же розділяє рахунки на незалежні одиниці стану, де кожен об'єкт є незалежною парою ключ-значення, об'єкти можуть існувати незалежно один від одного, і будуть пов'язані лише в разі чітко визначених відносин. Між об'єктами немає спільних шляхів дерева, і немає конкуренції за блокування, що дозволяє повністю паралельне виконання.
Основна структура даних Aptos - це Jellyfish Merkle Tree. Статус кожного об'єкта врешті-решт зберігається в JMT як незалежна пара ключ-значення. На відміну від MPT Ефіріуму, Jellyfish Merkle Tree має форму повного бінарного дерева, що спрощує шляхи зберігання вузлів та запитів, що суттєво зменшує час верифікації. Крім того, місце кожного рахунку в дереві є фіксованим, а вузли в дереві зберігаються незалежно, що дозволяє одночасно оновлювати та шукати кілька рахунків.
Aptos є оптимістичною паралельністю, яка не вимагає попереднього визначення залежностей всіх рахунків. Для цього Aptos використовує Block-STM, який використовує встановлений порядок транзакцій для оцінки залежностей, зменшуючи кількість відмов.
Паралельний EVM
На відміну від не-EVM паралельності, паралельний EVM стикається з більшими технічними труднощами при обробці залежностей стану, перевірки конфліктів, управління газом і механізмів відкату. Щоб краще зрозуміти це, ми можемо звернутися до деяких проектів паралельного EVM (таких як Sui, Monad, Canto), які вирішують ці проблеми.
Sui
Sui, як і Aptos, також використовує об'єктну модель для обробки стану, використовуючи кожен об'єкт (наприклад, рахунок, стан смарт-контракту) як незалежний ресурс, ці об'єкти відрізняються за допомогою унікальних ідентифікаторів об'єкта. Коли транзакції стосуються різних об'єктів, ці транзакції можуть оброблятися паралельно, оскільки вони виконують операції над різними станами, не викликаючи прямих конфліктів.
Хоча Sui використовує об'єктну модель для управління станом, щоб бути сумісним з EVM, архітектура Sui включає додатковий адаптаційний рівень або абстрактний механізм, щоб з'єднати об'єктну модель з моделлю рахунків EVM.
У Sui для розподілу транзакцій використовується стратегія оптимістичної паралельності, яка припускає, що між транзакціями немає конфліктів. Якщо конфлікти виникають, система використовує механізм відкату для відновлення стану.
Sui використовує об'єктну модель і технології ізоляції стану, що ефективно запобігає проблемам залежностей стану. Кожен об'єкт є незалежним ресурсом, різні транзакції можуть виконуватися паралельно, підвищуючи пропускну здатність і ефективність. Але цей підхід має зворотну сторону: складність об'єктної моделі та витрати на механізми відкату. Якщо між транзакціями виникають конфлікти, потрібно відкотити частину стану, що збільшує навантаження на систему і може вплинути на ефективність паралельної обробки. На відміну від не-EVM паралельних систем (таких як Solana), Sui потребує більше обчислювальних і зберігаючих ресурсів для підтримки високої ефективності паралельності.
Monad
Як і Sui, Monad також використовує оптимістичну паралельність. Але в оптимістичній паралельності Monad перед виконанням конкретних транзакцій все ж таки оцінює деякі транзакції з залежностями, прогнозуючи їх через статичний аналіз коду Monad. Прогнозування вимагає доступу до стану, і спосіб зберігання стану в базі даних Ефіріуму ускладнює доступ до стану. Щоб підвищити ефективність паралельного зчитування стану, Monad також перебудував базу даних.
Дерево стану Monad розділяється за секціями, кожна секція підтримує своє піддерево стану. Під час оновлення потрібно лише змінити відповідні фрагменти, не потрібно перебудовувати все дерево стану. Швидке знаходження стану в секції здійснюється за допомогою таблиці індексів стану, що зменшує взаємодію між секціями.
Короткий підсумок
Основою паралельності є підвищення ефективності виконання на виконавчому шарі шляхом виконання через кілька шляхів, а для реалізації багатошляхового виконання ланцюг повинен пройти ряд механізмів, таких як перевірка конфліктів та механізми відкату, щоб забезпечити паралельне виконання без впливу на остаточну узгодженість стану, а також вдосконалити базу даних.
Звичайно, підвищення ефективності виконавчого шару не обмежується лише паралельністю; оптимізація виконавчого етапу також може бути досягнута шляхом зменшення необхідних операцій читання та запису для бази даних для однієї транзакції. Підвищення швидкості всього ланцюга охоплює більш широкий спектр, включаючи підвищення ефективності шару консенсусу.
За кожною технологією стоять специфічні обмеження. Паралельність є лише одним із способів підвищення ефективності; остаточне рішення про використання цієї технології також має враховувати, наскільки вона дружня до розробників і чи може бути реалізована без жертви децентралізації. Накопичення технологій не завжди є позитивом, принаймні для Ефіріуму, паралельність не є настільки привабливою. Якщо дивитися лише з точки зору підвищення ефективності, додавання паралельності для Ефіріуму не є оптимальним рішенням, враховуючи простоту та поточну дорожню карту Ефіріуму, зосереджену на Rollup.