Перейти до основного вмісту
Change page

Мережевий рівень

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

Клієнтське програмне забезпечення складається з двох частин (клієнти виконання та клієнти консенсусу), кожна з яких має власний окремий мережевий стек. Окрім спілкування з іншими вузлами Етеріуму, клієнти виконання та консенсусу повинні спілкуватися між собою. На цій сторінці наведено вступне пояснення протоколів, які забезпечують цей зв'язок.

Клієнти виконання поширюють транзакції через протокол пліток в одноранговій мережі рівня виконання. Це вимагає зашифрованого зв'язку між автентифікованими пірами. Коли валідатор обирається як пропонувач блоку, транзакції з локального пулу транзакцій вузла передаються клієнтам консенсусу через локальне з'єднання RPC, які потім упаковуються в блоки маяка. Потім клієнти консенсусу поширюють блоки маяка через протокол пліток у своїй одноранговій (p2p) мережі. Для цього потрібні дві окремі p2p-мережі: одна з'єднує клієнти виконання для поширення транзакцій, а інша — клієнти консенсусу для поширення блоків.

Передумови

Деякі знання про вузли та клієнти Етеріуму будуть корисними для розуміння цієї сторінки.

Рівень виконання

Мережеві протоколи рівня виконання поділяються на два стеки:

  • стек виявлення: побудований поверх UDP і дозволяє новому вузлу знаходити пірів для підключення

  • стек devp2p: працює поверх TCP і дозволяє вузлам обмінюватися інформацією

Обидва стеки працюють паралельно. Стек виявлення додає нових учасників до мережі, а стек devp2p забезпечує їхню взаємодію.

Виявлення

Виявлення — це процес пошуку інших вузлів у мережі. Цей процес запускається за допомогою невеликого набору завантажувальних вузлів (вузлів, чиї адреси жорстко закодовані (opens in a new tab) в клієнті, щоб їх можна було негайно знайти та підключити клієнт до пірів). Ці завантажувальні вузли існують лише для того, щоб представити новий вузол набору пірів — це їхня єдина мета, вони не беруть участі у звичайних завданнях клієнта, таких як синхронізація ланцюга, і використовуються лише під час першого запуску клієнта.

Протокол, що використовується для взаємодії між вузлом і завантажувальним вузлом, є модифікованою формою Kademlia (opens in a new tab), яка використовує розподілену хеш-таблицю (opens in a new tab) для обміну списками вузлів. Кожен вузол має версію цієї таблиці, що містить інформацію, необхідну для підключення до його найближчих пірів. Ця «близькість» не є географічною — відстань визначається схожістю ідентифікатора вузла (ID). Таблиця кожного вузла регулярно оновлюється з міркувань безпеки. Наприклад, у протоколі виявлення discv5 (opens in a new tab) вузли також можуть надсилати «оголошення», які відображають підпротоколи, що підтримуються клієнтом, дозволяючи пірам домовлятися про протоколи, які вони обидва можуть використовувати для спілкування.

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

Після зв'язування новий вузол може надіслати запит FIND-NEIGHBOURS до завантажувального вузла. Дані, які повертає завантажувальний вузол, включають список пірів, до яких може підключитися новий вузол. Якщо вузли не зв'язані, запит FIND-NEIGHBOURS завершиться помилкою, тому новий вузол не зможе увійти в мережу.

Отримавши список сусідів від завантажувального вузла, новий вузол починає обмін PING-PONG з кожним із них. Успішні PING-PONG зв'язують новий вузол з його сусідами, уможливлюючи обмін повідомленнями.

запуск клієнта --> підключення до завантажувального вузла --> зв'язування із завантажувальним вузлом --> пошук сусідів --> зв'язування із сусідами

Клієнти виконання наразі використовують протокол виявлення Discv4 (opens in a new tab), і ведеться активна робота з переходу на протокол discv5 (opens in a new tab).

ENR: Записи вузлів Етеріуму

Запис вузла Етеріуму (ENR) — це об'єкт, який містить три основні елементи: підпис (хеш вмісту запису, створений відповідно до певної узгодженої схеми ідентифікації), порядковий номер, який відстежує зміни в записі, та довільний список пар ключ:значення. Це формат, орієнтований на майбутнє, який полегшує обмін ідентифікаційною інформацією між новими пірами та є кращим форматом мережевої адреси для вузлів Етеріуму.

Чому виявлення побудовано на UDP?

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

devp2p

devp2p — це цілий стек протоколів, які Етеріум реалізує для створення та підтримки однорангової мережі. Після того, як нові вузли входять у мережу, їхня взаємодія регулюється протоколами в стеку devp2p (opens in a new tab). Усі вони працюють поверх TCP і включають транспортний протокол RLPx, дротовий протокол (wire protocol) та кілька підпротоколів. RLPx (opens in a new tab) — це протокол, що регулює ініціювання, автентифікацію та підтримку сеансів між вузлами. RLPx кодує повідомлення за допомогою RLP (Recursive Length Prefix), що є дуже ефективним з точки зору простору методом кодування даних у мінімальну структуру для надсилання між вузлами.

Сеанс RLPx між двома вузлами починається з початкового криптографічного рукостискання. Це передбачає надсилання вузлом повідомлення автентифікації, яке потім перевіряється піром. У разі успішної перевірки пір генерує повідомлення-підтвердження автентифікації для повернення вузлу-ініціатору. Це процес обміну ключами, який дозволяє вузлам спілкуватися приватно та безпечно. Успішне криптографічне рукостискання потім спонукає обидва вузли надіслати повідомлення «hello» один одному «по дроту» (on the wire). Дротовий протокол ініціюється успішним обміном повідомленнями «hello».

Повідомлення «hello» містять:

  • версію протоколу
  • ID клієнта
  • порт
  • ID вузла
  • список підтримуваних підпротоколів

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

Разом із повідомленнями «hello» дротовий протокол також може надсилати повідомлення «disconnect», яке попереджає піра про те, що з'єднання буде закрито. Дротовий протокол також включає повідомлення PING і PONG, які періодично надсилаються для підтримки сеансу відкритим. Таким чином, обмін за допомогою RLPx та дротового протоколу закладає основи зв'язку між вузлами, забезпечуючи базу для обміну корисною інформацією відповідно до певного підпротоколу.

Підпротоколи

Дротовий протокол

Після підключення пірів і початку сеансу RLPx дротовий протокол визначає, як піри спілкуються. Спочатку дротовий протокол визначав три основні завдання: синхронізація ланцюга, поширення блоку та обмін транзакціями. Однак після переходу Етеріуму на доказ частки (PoS) поширення блоку та синхронізація ланцюга стали частиною рівня консенсусу. Обмін транзакціями все ще залишається в компетенції клієнтів виконання. Обмін транзакціями означає обмін транзакціями, що очікують на обробку, між вузлами, щоб розробники блоків могли вибрати деякі з них для включення в наступний блок. Детальна інформація про ці завдання доступна тут (opens in a new tab). Клієнти, які підтримують ці підпротоколи, надають до них доступ через JSON-RPC.

les (легкий підпротокол Етеріуму)

Це мінімальний протокол для синхронізації легких клієнтів. Традиційно цей протокол використовувався рідко, оскільки повні вузли повинні надавати дані легким клієнтам без жодного стимулювання. Поведінка клієнтів виконання за замовчуванням полягає в тому, щоб не надавати дані легким клієнтам через les. Більше інформації доступно в специфікації (opens in a new tab) les.

Snap

Протокол snap (opens in a new tab) — це додаткове розширення, яке дозволяє пірам обмінюватися знімками останніх станів, що дає змогу пірам перевіряти дані акаунтів і сховища без необхідності завантажувати проміжні вузли дерева Меркла.

Wit (протокол свідків)

Протокол свідків (opens in a new tab) — це додаткове розширення, яке дозволяє обмінюватися свідками стану між пірами, допомагаючи синхронізувати клієнти з верхівкою ланцюга.

Whisper

Whisper був протоколом, який мав на меті забезпечити безпечний обмін повідомленнями між пірами без запису будь-якої інформації в блокчейн. Він був частиною дротового протоколу devp2p, але зараз застарів. Існують інші пов'язані проєкти (opens in a new tab) з подібними цілями.

Рівень консенсусу

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

Виявлення

Подібно до клієнтів виконання, клієнти консенсусу використовують discv5 (opens in a new tab) поверх UDP для пошуку пірів. Реалізація discv5 на рівні консенсусу відрізняється від реалізації клієнтів виконання лише тим, що вона включає адаптер, який підключає discv5 до стека libp2p (opens in a new tab), відмовляючись від devp2p. Сеанси RLPx рівня виконання застаріли на користь рукостискання безпечного каналу noise від libp2p.

ENR

ENR для вузлів консенсусу включає відкритий ключ вузла, IP-адресу, порти UDP і TCP, а також два специфічні для консенсусу поля: бітове поле підмережі атестації та ключ eth2. Перше поле полегшує вузлам пошук пірів, які беруть участь у певних підмережах поширення атестацій. Ключ eth2 містить інформацію про те, яку версію форку Етеріуму використовує вузол, гарантуючи, що піри підключаються до правильного Етеріуму.

libp2p

Стек libp2p підтримує всі комунікації після виявлення. Клієнти можуть здійснювати виклики та прослуховувати IPv4 та/або IPv6, як визначено в їхньому ENR. Протоколи на рівні libp2p можна розділити на домени пліток (gossip) та запитів/відповідей (req/resp).

Плітки (Gossip)

Домен пліток включає всю інформацію, яка повинна швидко поширюватися по всій мережі. Сюди входять блоки маяка, докази, атестації, виходи та скорочення (slashings). Це передається за допомогою libp2p gossipsub v1 і покладається на різні метадані, що зберігаються локально на кожному вузлі, включаючи максимальний розмір корисного навантаження пліток для отримання та передачі. Детальна інформація про домен пліток доступна тут (opens in a new tab).

Запит-відповідь

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

Чому клієнт консенсусу віддає перевагу SSZ, а не RLP?

SSZ розшифровується як проста серіалізація (simple serialization). Він використовує фіксовані зміщення, які дозволяють легко декодувати окремі частини закодованого повідомлення без необхідності декодувати всю структуру, що дуже корисно для клієнта консенсусу, оскільки він може ефективно витягувати певні фрагменти інформації із закодованих повідомлень. Він також розроблений спеціально для інтеграції з протоколами Меркла, з відповідним підвищенням ефективності для мерклізації. Оскільки всі хеші на рівні консенсусу є коренями Меркла, це призводить до значного покращення. SSZ також гарантує унікальне представлення значень.

З'єднання клієнтів виконання та консенсусу

Як клієнти консенсусу, так і клієнти виконання працюють паралельно. Вони повинні бути з'єднані, щоб клієнт консенсусу міг надавати інструкції клієнту виконання, а клієнт виконання міг передавати пакети транзакцій клієнту консенсусу для включення в блоки маяка. Зв'язок між двома клієнтами може бути досягнутий за допомогою локального з'єднання RPC. API, відомий як «Engine-API» (opens in a new tab), визначає інструкції, що надсилаються між двома клієнтами. Оскільки обидва клієнти знаходяться за єдиною мережевою ідентичністю, вони спільно використовують ENR (запис вузла Етеріуму), який містить окремий ключ для кожного клієнта (ключ Eth1 і ключ Eth2).

Короткий опис потоку керування наведено нижче, з відповідним мережевим стеком у дужках.

Коли клієнт консенсусу не є виробником блоку:

  • Клієнт консенсусу отримує блок через протокол пліток для блоків (p2p консенсусу)
  • Клієнт консенсусу попередньо перевіряє блок, тобто переконується, що він надійшов від дійсного відправника з правильними метаданими
  • Транзакції в блоці надсилаються на рівень виконання як корисне навантаження виконання (локальне з'єднання RPC)
  • Рівень виконання виконує транзакції та перевіряє стан у заголовку блоку (тобто перевіряє збіг хешів)
  • Рівень виконання передає дані перевірки назад на рівень консенсусу, тепер блок вважається перевіреним (локальне з'єднання RPC)
  • Рівень консенсусу додає блок до верхівки власного блокчейну та атестує його, транслюючи атестацію по мережі (p2p консенсусу)

Коли клієнт консенсусу є виробником блоку:

  • Клієнт консенсусу отримує повідомлення про те, що він є наступним виробником блоку (p2p консенсусу)
  • Рівень консенсусу викликає метод create block у клієнті виконання (локальний RPC)
  • Рівень виконання отримує доступ до мемпулу транзакцій, який був заповнений протоколом пліток для транзакцій (p2p виконання)
  • Клієнт виконання об'єднує транзакції в блок, виконує транзакції та генерує хеш блоку
  • Клієнт консенсусу бере транзакції та хеш блоку від клієнта виконання та додає їх до блоку маяка (локальний RPC)
  • Клієнт консенсусу транслює блок через протокол пліток для блоків (p2p консенсусу)
  • Інші клієнти отримують запропонований блок через протокол пліток для блоків і перевіряють його, як описано вище (p2p консенсусу)

Після того, як блок був атестований достатньою кількістю валідаторів, він додається до верхівки ланцюга, стає обґрунтованим і, зрештою, фіналізованим.

Diagram of the Ethereum consensus client networking layer Diagram of the Ethereum execution client networking layer

Схема мережевого рівня для клієнтів консенсусу та виконання, з ethresear.ch (opens in a new tab)

Додаткові матеріали

devp2p (opens in a new tab) libp2p (opens in a new tab) Специфікації мережі рівня консенсусу (opens in a new tab) Від Kademlia до discv5 (opens in a new tab) Документація Kademlia (opens in a new tab) Вступ до p2p Етеріуму (opens in a new tab) Зв'язок між Eth1 та Eth2 (opens in a new tab) Відео про Злиття та деталі клієнта Eth2 (opens in a new tab)