Оверлейные подсети
Эта страница переведена сообществом на русский язык, но нуждается в улучшениях. Если вы хотите принять участие в переводе свяжитесь с @alexgton.
Реализация:
Общие сведения
Архитектура TON построена таким образом, что в ней одновременно и независимо может существовать множество цепочек — они могут быть как частными, так и общедоступными. Узлы имеют возможность выбирать, какие шарды и цепочки они хранят и обрабатывают. При этом протокол связи остается неизменным из-за своей универсальности. Такие протоколы, как DHT, RLDP и Оверлеи, позволяют этого добиться. С первыми двумя мы уже знакомы, в этом разделе мы узнаем, что такое Оверлеи.
Оверлеи отвечают за разделение единой сети на дополнительные подсети. Оверлеи могут быть как общедоступными, к которым может подключиться любой желающий, так и частными, где для входа требуются дополнительные учетные данные, известные только определенному кругу лиц.
Все чейны в TON, включая мастерчейн, общаются с помощью собственного оверлея. Чтобы присоединиться к нему, нужно найти узлы, которые уже состоят в нем, и начать обмениваться с ними данными. Для общедоступных оверлеев вы можете найти узлы с помощью DHT.
ADNL против оверлейных сетей
В отличие от ADNL, оверлейные сети TON обычно не поддерживают отправка датаграмм на другие произвольные узлы. Вместо этого между определенными узлами устанавливаются некоторые “полупостоянные соединения” (называемые “соседними” по отношению к рассматриваемой оверлейной сети), и сообщения обычно пересылаются по этим соединениям (т.е. от узла к одному из его соседей).
Каждая оверлейная подсеть имеет 256-разрядный сетевой идентификатор, обычно равный SHA256 описания оверлейной сети — TL-сериализованного объекта.
Оверлейные подсети могут быть общедоступными или частными.
Оверлейные подсети работают по специальному протоколу gossip.
Взаимодействие с оверлейными узлами
Мы уже разбирали пример с поиском оверлейных узлов в статье о DHT, в разделе Поиск узлов, хранящих состояние блокчейна. В этом разделе мы сосредоточимся на взаимодействии с ними.
При запросе DHT мы получим адреса оверлейных узлов, из которых мы можем узнать адреса других узлов этого оверлея с помощью запроса overlay.getRandomPeers. Как только мы подключимся к достаточному количеству узлов, мы сможем получать от них всю информацию о блоках и другие события чейна, а также отправлять им наши транзакции для обработки.
Найдите больше соседей
Давайте рассмотрим пример получения узлов в оверлее.
Для этого отправьте запрос overlay.getRandomPeers
на любой известный узел оверлея, сериализуйте схему TL:
overlay.node id:PublicKey overlay:int256 version:int signature:bytes = overlay.Node;
overlay.nodes nodes:(vector overlay.node) = overlay.Nodes;
overlay.getRandomPeers peers:overlay.nodes = overlay.Nodes;
peers
- должен содержать известные нам пиры, поэтому мы не получаем их обратно, но поскольку мы пока не знаем ни одного, peers.nodes
будет пустым массивом.
В случае, если мы хотим не просто получить какую-то информацию, а участвовать в оверлее и получать трансляции, мы также должны добавить в peers
информацию о нашем узле, с которого мы делаем запрос.
Когда пиры получат информацию о нас - они начнут отправлять нам широковещательные сообщения с помощью ADNL или RLDP.
Каждый запрос внутри оверлея должен иметь префикс TL-схемы:
overlay.query overlay:int256 = True;
overlay
должен быть идентификатором оверлея - идентификатором ключа схемы tonNode.ShardPublicOverlayId
- тем же, который мы использовали для поиска в DHT.
Нам нужно объединить 2 сериализованные схемы, просто объединив 2 сериализованных байтовых массива, overlay.query
будет первым, overlay.getRandomPeers
- вторым.
Мы оборачиваем полученный массив в схему adnl.message.query
и отправляем ее через ADNL. В ответе ждем overlay.nodes
- это будет список узлов оверлея, к которым мы можем подключиться и, при необходимости, повторить тот же запрос к новым из них, пока не получим достаточное количество подключений.
Функциональные запросы
П осле того, как соединение установлено, мы можем получить доступ к оверлейным узлам с помощью запросов tonNode.*
.
Для запросов такого рода используется протокол RLDP. И важно не забыть префикс overlay.query
- он должен использоваться для каждого запроса в оверлее.
В самих запросах нет ничего необычного, они очень похожи на то, что мы делали в статье про ADNL TCP.
Например, запрос downloadBlockFull
использует уже знакомую схему идентификатора блока:
tonNode.downloadBlockFull block:tonNode.blockIdExt = tonNode.DataFull;
Передав его, мы сможем загрузить полную информацию о блоке, в ответ получим:
tonNode.dataFull id:tonNode.blockIdExt proof:bytes block:bytes is_link:Bool = tonNode.DataFull;
or
tonNode.dataFullEmpty = tonNode.DataFull;
Если присутствует, поле block
будет содержать данные в формате TL-B.
Таким образом, мы можем получать информацию напрямую с узлов.