Перейти к основному контенту
Change page

Сетевой уровень

Эфириум — это одноранговая сеть с тысячами узлов, которые должны иметь возможность общаться друг с другом с использованием стандартизированных протоколов. «Сетевой уровень» — это стек протоколов, который позволяет этим узлам находить друг друга и обмениваться информацией. Это включает в себя распространение информации по протоколу сплетен (связь «один ко многим») по сети, а также обмен запросами и ответами между конкретными узлами (связь «один к одному»). Каждый узел должен соблюдать определенные сетевые правила, чтобы гарантировать отправку и получение правильной информации.

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

Клиенты исполнения распространяют транзакции по протоколу сплетен через одноранговую сеть уровня исполнения. Это требует зашифрованной связи между аутентифицированными пирами. Когда валидатор выбран как предлагающий блок, транзакции из локального пула транзакций узла будут переданы клиентам консенсуса через локальное RPC-соединение, которые будут упакованы в блоки сигнальной цепи. Затем клиенты консенсуса будут распространять блоки сигнальной цепи по протоколу сплетен в своей одноранговой сети. Для этого требуются две отдельные одноранговые сети: одна соединяет клиенты исполнения для распространения транзакций по протоколу сплетен, а другая соединяет клиенты консенсуса для распространения блоков по протоколу сплетен.

Предварительные требования

Для понимания этой страницы будет полезно некоторое знание об узлах и клиентах Эфириума.

Уровень исполнения

Сетевые протоколы уровня исполнения делятся на два стека:

  • стек обнаружения: построен поверх 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, стоят дополнительных функциональных возможностей. Поэтому большая часть однорангового стека работает поверх 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 и передачи данных закладывают основы связи между узлами, обеспечивая основу для обмена полезной информацией в соответствии с определенным подпротоколом.

Подпротоколы

Протокол передачи данных (Wire protocol)

Как только пиры подключены и начат сеанс 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 можно подразделить на домены протокола сплетен и запросов/ответов (req/resp).

Протокол сплетен

Домен протокола сплетен включает всю информацию, которая должна быстро распространяться по сети. Сюда входят блоки сигнальной цепи, доказательства, аттестации, выходы и штрафы (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).

Краткое описание потока управления показано ниже, с соответствующим сетевым стеком в скобках.

Когда клиент консенсуса не является производителем блока:

  • Клиент консенсуса получает блок через протокол сплетен для блоков (одноранговая сеть консенсуса)
  • Клиент консенсуса предварительно проверяет блок, т. е. убеждается, что он прибыл от действительного отправителя с правильными метаданными
  • Транзакции в блоке отправляются на уровень исполнения в качестве полезной нагрузки исполнения (локальное RPC-соединение)
  • Уровень исполнения выполняет транзакции и проверяет состояние в заголовке блока (т. е. проверяет совпадение хешей)
  • Уровень исполнения передает данные проверки обратно на уровень консенсуса, теперь блок считается проверенным (локальное RPC-соединение)
  • Уровень консенсуса добавляет блок в начало своего собственного блокчейна и аттестует его, транслируя аттестацию по сети (одноранговая сеть консенсуса)

Когда клиент консенсуса является производителем блока:

  • Клиент консенсуса получает уведомление о том, что он является следующим производителем блока (одноранговая сеть консенсуса)
  • Уровень консенсуса вызывает метод create block в клиенте исполнения (локальный RPC)
  • Уровень исполнения обращается к мемпулу транзакций, который был заполнен протоколом сплетен для транзакций (одноранговая сеть исполнения)
  • Клиент исполнения объединяет транзакции в блок, выполняет транзакции и генерирует хеш блока
  • Клиент консенсуса берет транзакции и хеш блока из клиента исполнения и добавляет их в блок сигнальной цепи (локальный RPC)
  • Клиент консенсуса транслирует блок через протокол сплетен для блоков (одноранговая сеть консенсуса)
  • Другие клиенты получают предложенный блок через протокол сплетен для блоков и проверяют его, как описано выше (одноранговая сеть консенсуса)

Как только блок будет аттестован достаточным количеством валидаторов, он добавляется в начало цепи, становится обоснованным и в конечном итоге финализированным.

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) Введение в одноранговую сеть Эфириума (opens in a new tab) Отношения Eth1/Eth2 (opens in a new tab) Видео с подробностями о Слиянии и клиентах Eth2 (opens in a new tab)