В мультичейн-системе, такой как блокчейн TON, даже полные ноды обычно заинтересованы в получении обновлений (т. е. новых блоков) только для некоторых шардчейнов. С этой целью внутри сети TON для каждого шардчейна должна быть построена специальная оверлейная (под) сеть поверх протокола ADNL.
Следовательно, возникает необходимость в создании произвольных оверлейных подсетей, открытых для любых узлов, желающих в них участвовать. В этих оверлейных сетях будут работать специальные протоколы сплетен, основанные на ADNL. В частности, эти протоколы сплетен могут использоваться для распространения (передачи) произвольных данных внутри такой подсети.
Оверлейные сети
Оверлейная (под) сеть — это просто (виртуальная) сеть, реализованная внутри более крупной сети. Обычно только некоторые узлы более крупной сети участвуют в оверлейной подсети, и только некоторые «связи» между этими узлами, физическими или виртуальными, являются частью оверлейной подсети.
Таким образом, если представить сеть в виде графа (возможно, полного графа в случае сети датаграмм, такой как ADNL, где любой узел может легко связываться с любым другим), оверлейная подсеть является подграфом этого графа.
В большинстве случаев оверлейная сеть реализуется с использованием какого-либо протокола, построенного на сетевом протоколе более крупной сети. Она может использовать те же адреса, что и более крупная сеть, либо использовать собственные адреса.
Оверлейные сети в TON
Оверлейные сети в TON построены на протоколе ADNL в них также используются 256-битные абстрактные адреса ADNL в качестве адресов. Каждый узел обычно выбирает один из своих абстрактных адресов, который удваивается в оверлейной сети.
В отличие от ADNL, оверлейные сети TON обычно не поддерживают отправку датаграмм на другие произвольные узлы. Вместо этого между некоторыми узлами (называемыми «соседями» по отношению к рассматриваемой оверлейной сети) устанавливается «полупостоянная связь», и сообщения обычно пересылаются по этой связи (т. е. от узла к одному из его соседей). Таким образом, оверлейная сеть TON представляет собой (обычно не полный) подграф внутри (полного) графа сети ADNL.
Связи с соседями в оверлейных сетях TON могут быть реализованы с использованием выделенных одноранговых каналов ADNL
Каждый узел оверлейной сети поддерживает список соседей (по отношению к оверлейной сети), содержащий их абстрактные адреса (которые они используют для собственной идентификации в оверлейной сети) и некоторые данные связи (например, канал ADNL, используемый для связи).
Частные и общедоступные оверлейные сети
Некоторые оверлейные сети являются общедоступными, что означает, что любой узел может присоединиться к ним по своему желанию. Другие являются частными – в них могут быть допущены только определенные узлы (например, узлы, которые могут подтвердить, что они являются валидаторами). Некоторые частные оверлейные сети могут быть даже неизвестны «широкой публике». Информация о таких оверлейных сетях доступна только определенным доверенным узлам; например, она может быть зашифрована открытым ключом, и расшифровать эту информацию смогут только узлы, имеющие копию соответствующего закрытого ключа.
Централизованно управляемые оверлейные сети
Некоторые оверлейные сети управляются централизованно одним или несколькими узлами или владельцем широко известного открытого ключа. Другие являются децентрализованными – это означает, что за них не отвечают какие-либо конкретные узлы.
Присоединение к оверлейной сети
Когда узел хочет присоединиться к оверлейной сети, он сначала должен узнать свой 256-битный сетевой идентификатор, обычно равный SHA256 описания оверлейной сети — TL-сериализированный объект, который может содержать, например, центр оверлейной сети (то есть его открытый ключ и, возможно, его абстрактный адрес33), строка с именем оверлейной сети, идентификатор сегмента блокчейна TON, если это оверлейная сеть, связанная с этим шардом, и т. д.
Иногда возможно восстановить описание оверлейной сети, начиная с идентификатора сети, просто просмотрев его в TON DHT. В других случаях (например, для частных оверлейных сетей) необходимо получить описание сети вместе с идентификатором сети.
Поиск одного члена оверлейной сети
После того, как узел узнает идентификатор сети и описание оверлейной сети, к которой он хочет присоединиться, он должен найти хотя бы один узел, принадлежащий этой сети. Это также необходимо для узлов, которые не хотят присоединяться к оверлейной сети, а хотят просто связаться с ее участниками. Например, может существовать оверлейная сеть, предназначенная для сбора и распространения транзакций-кандидатов для определенного шардчейна, и клиент может захотеть подключиться к любому узлу этой сети, чтобы предложить транзакцию.
Метод, используемый для обнаружения элементов оверлейной сети, определяется в описании этой сети. Иногда (особенно для частных сетей) нужно уже знать принадлежащий этой сети узел, чтобы иметь возможность присоединиться. В других случаях в описании сети содержатся абстрактные адреса некоторых узлов. Более гибкий подход состоит в том, чтобы указать в описании сети только центральный узел, ответственный за сеть, и тогда абстрактные адреса будут доступны через значения определенных ключей DHT, подписанных этим центральным узлом.
Наконец, действительно децентрализованные общедоступные оверлейные сети могут использовать механизм «распределенного трекера», также реализованный с помощью TON DHT.
Поиск дополнительных участников оверлейной сети
Создание ссылок. Как только один узел оверлейной сети будет найден, этому узлу может быть отправлен специальный запрос, запрашивающий список других членов, например, соседей запрашиваемого узла, или список случайных узлов.
Это позволяет присоединяющемуся узлу заполнить «список своих соседей» по отношению к оверлейной сети, выбрав некоторые недавно изученные сетевые узлы и установив с ними связи (т. е. выделенные двухточечные каналы ADNL). После этого всем соседям отправляются специальные сообщения, указывающие, что новый участник готов работать в оверлейной сети. Соседи включают свои ссылки на нового участника в свои списки соседей.
Ведение списка соседей
Узел оверлейной сети должен время от времени обновлять свой список соседей. Некоторые соседи или хотя бы ссылки (каналы) на них могут перестать отвечать; в этом случае эти ссылки должны быть помечены как «приостановленные», должны быть предприняты некоторые попытки повторного подключения к таким соседям, и, если эти попытки не удались, ссылки должны быть уничтожены.
С другой стороны, каждый узел иногда запрашивает у случайно выбранного соседа свой список соседей (или некоторый случайный выбор из них) и использует его для частичного обновления своего собственного списка соседей, добавляя к нему несколько недавно обнаруженных узлов и удаляя некоторые старые узлы (случайным образом или в зависимости от времени отклика и статистики потери датаграмм).
Оверлейная сеть как случайный подграф
Таким образом, оверлейная сеть становится случайным подграфом внутри сети ADNL. Если степень каждой вершины не менее 3 (т. е. если каждый узел связан, по крайней мере, с тремя соседями), этот случайный граф связан с вероятностью, почти равной единице. Точнее, вероятность того, что случайный граф с n вершинами будет отключен, экспоненциально мала, и этой вероятностью можно полностью пренебречь, если, скажем, n ≥ 20. (Конечно, это не применимо в случае разделения глобальной сети, когда узлы на разных сторонах раздела не имеют возможности узнать друг о друге.) С другой стороны, если n меньше 20, достаточно потребовать, чтобы каждая вершина имела, скажем, как минимум десять соседей.
Оптимизация оверлейных сетей TON для уменьшения задержки
Как вариант, абстрактный адрес может храниться в DHT. Оверлейные сети TON оптимизируют «случайный» сетевой граф, сгенерированный предыдущим методом, следующим образом. Каждый узел пытается сохранить как минимум трех соседей с минимальным периодом кругового обращения, причем этот список «быстрых соседей» очень редко меняется. В то же время у каждого узла есть как минимум три других «медленных соседа», которые выбираются совершенно случайным образом, поэтому граф оверлейной сети всегда будет содержать случайный подграф. Это необходимо для поддержания связи и предотвращения разделения оверлейной сети на несколько несвязанных местных подсетей. Также выбираются и сохраняются как минимум три «промежуточных соседа», которые имеют промежуточный период кругового обращения, ограниченный определенной константой (фактически, функцией периода кругового обращения для быстрых и медленных соседей).
Таким образом, в графе оверлейной сети сохраняется достаточный уровень произвольности подключения, однако он оптимизирован для более низкой задержки и более высокой пропускной способности.
Протоколы сплетен в оверлейной сети
Оверлейные сети часто используются для запуска одного из так называемых протоколов сплетен, которые достигают какой-то глобальной цели, позволяя каждому узлу взаимодействовать только со своими соседями. Например, существуют протоколы сплетен для построения приблизительного списка всех членов (не слишком большой) оверлейной сети или для вычисления оценки числа членов (произвольно большой) оверлейной сети, используя только ограниченное количество памяти на каждом узле.
Оверлейная сеть как домен широковещательной рассылки
Самый важный протокол сплетен, работающий в оверлейной сети, — это протокол широковещательной передачи, предназначенный для распространения широковещательных сообщений, генерируемых любым узлом сети или одним из назначенных узлов-отправителей, всем другим узлам.
На самом деле существует несколько протоколов широковещательной передачи, оптимизированных для разных случаев применения. Самый простой из них принимает новые широковещательные сообщения и ретранслирует их всем соседям, которые сами еще не отправили копию этого сообщения.
Более сложные протоколы широковещательной передачи
Для некоторых приложений могут потребоваться более сложные протоколы широковещательной передачи. Например, при широковещательной рассылке сообщений большого размера имеет смысл отправлять соседям не само вновь полученное сообщение, а его хэш (или набор хэшей новых сообщений). Соседний узел может запросить само сообщение после изучения ранее невидимого хэша передаваемого сообщения, скажем, с использованием надежного протокола больших датаграмм (RLDP). Таким образом, новое сообщение будет загружено только от одного соседнего узла.
Проверка возможности подключения оверлейной сети
Связность оверлейной сети можно проверить с использованием известного узла (например, «владельца» или «создателя» оверлейной сети), который должен находиться в этой оверлейной сети. Затем рассматриваемый узел просто время от времени передает короткие сообщения, содержащие текущее время, порядковый номер и подпись. Любой другой узел может быть уверен, что он все еще подключен к оверлейной сети, если он недавно получил такое широковещательное сообщение. Этот протокол может быть расширен на нескольких хорошо известных узлов; например, все они будут отправлять такие широковещательные рассылки, а все остальные узлы будут ожидать широковещательные рассылки от более чем половины хорошо известных узлов.
В случае оверлейной сети, используемой для распространения новых блоков (или только новых заголовков блоков) определенного шардчейна, хороший способ для узла проверить возможность подключения — это отслеживать самый последний полученный блок. Поскольку блок обычно генерируется каждые пять секунд, если новый блок не принимается в течение, скажем, тридцати секунд, то узел, вероятно, был отключен от оверлейной сети.
Протокол потоковой трансляции
Существует протокол потоковой трансляции для оверлейных сетей TON, который используется, например, для распространения блоков-кандидатов среди валидаторов некоторого шардчейна («группа задач шардчейна»), которые, конечно же, создают для этой цели частную оверлейную сеть. Тот же протокол можно использовать для распространения новых блоков шардчейна на все полные ноды этого шардчейна.
Этот протокол новое (большое) широковещательное сообщение разбивается, скажем, на N блоков по одному килобайту; последовательность этих фрагментов увеличивается до M ≥ N фрагментов с помощью стирающего кода, такого как код Рида-Соломона или исходный код (например, код RaptorQ), и эти M фрагментов передаются всем соседям в порядке возрастания номеров блоков. Участвующие узлы собирают эти фрагменты до тех пор, пока они не смогут восстановить исходное большое сообщение (для этого необходимо успешно получить не менее N фрагментов), а затем проинструктировать своих соседей прекратить отправку новых фрагментов потока, потому что теперь эти узлы могут генерировать последующие блоки самостоятельно, имея копию исходного сообщения. Такие узлы продолжают генерировать последующие фрагменты потока и отправлять их своим соседям, если соседи, в свою очередь, не укажут, что в этом больше нет необходимости.
Таким образом, узлу не нужно полностью загружать большое сообщение перед его дальнейшим распространением. Это позволяет минимизировать задержку потоковой трансляции, особенно в сочетании с оптимизацией.
Построение новых оверлейных сетей на основе существующих сетей
Иногда строить оверлейную сеть с нуля нет смысла. Вместо этого известна одна или несколько ранее существовавших оверлейных сетей, и ожидается, что членство в новой оверлейной сети будет значительно перекрываться с объединенным членством этих оверлейных сетей.
Важный пример – разделение шардчейна TON на два шардчейна, либо объединение двух родственных шардчейнов в один. В первом случае оверлейные сети, используемые для распространения новых блоков на полные ноды, должны быть построены для каждого нового шардчейна. Однако можно ожидать, что каждая из этих новых оверлейных сетей будет содержаться в сети распространения блоков исходного шардчейна (и включать примерно половину ее членов). Во втором случае оверлейная сеть для распространения новых блоков объединенного шардчейна будет состоять примерно из объединения членов двух оверлейных сетей, связанных с двумя объединяемыми родственными шардчейнами.
В таких случаях описание новой оверлейной сети может содержать явную или неявную ссылку на список связанных существующих оверлейных сетей. Узел, желающий присоединиться к новой оверлейной сети, может проверить, является ли он уже членом одной из этих существующих сетей, и запросить своих соседей в этих сетях, заинтересованы ли они также в новой сети. В случае положительного ответа для таких соседей могут быть установлены новые двухточечные каналы, и они могут быть включены в список соседей для новой оверлейной сети.
Этот механизм не заменяет полностью общий механизм, скорее, оба механизма выполняются параллельно и используются для заполнения списка соседей. Это необходимо для предотвращения случайного разделения новой оверлейной сети на несколько несвязанных подсетей.
Оверлейные сети внутри оверлейных сетей
Другой интересный случай возникает при реализации сервиса TON Payments («сеть моментальных платежей» для мгновенных переводов стоимости вне сети). В этом случае сначала строится оверлейная сеть, содержащая все транзитные узлы «сети моментальных платежей». Однако некоторые из этих узлов имеют платежные каналы в блокчейне; они всегда должны быть соседями в этой оверлейной сети, в дополнение к любым «случайным» соседям, выбранным общими алгоритмами оверлейной сети, эти «постоянные соединения» с соседями с установленными платежными каналами используются для запуска определенных сетевых протоколов Lightning. Таким образом, обеспечивается эффективное создание оверлейной подсети (не обязательно подключенной, если что-то пойдет не так) внутри охватывающей (почти всегда подключенной) оверлейной сети.