Сетевой слой
Узел Tycho должен найти других узлов в сети, установить с ними соединение, объединиться с частью из них в логические подсети под конкретную задачу и через эти подсети обменяться данными цепочки: блоками, архивами, устойчивыми состояниями, внешними сообщениями. Этот раздел документации разбирает эти задачи по пяти частям. Три из них образуют сетевой слой узла: QUIC-транспорт с базовыми типами внутри, распределённая хеш-таблица (DHT, реализация Kademlia-подобная) для обнаружения пиров и оверлеи как логические подсети над транспортом. Ещё две части — его потребители: клиент оверлея, который подбирает и оценивает участников для запросов, и blockchain RPC, прикладной протокол обмена данными цепочки поверх этого клиента.
Пять частей разобраны отдельными статьями раздела. Эта статья — карта того, как они связаны друг с другом.
Транспорт и базовые типы
В основании — транспорт, единая точка входа в сетевой слой узла. Он собирается из приватного ключа, адреса для UDP-сокета и одного корневого сервиса-обработчика входящих обращений. Внутри он владеет одним и тем же QUIC-объектом на одном UDP-сокете для входящих и исходящих соединений, фоновой задачей, которая ведёт установление соединений и периодически проверяет связность, и реестрами известных и активных пиров. Идентификатор узла в Tycho служит его собственным публичным ключом ed25519, поэтому личность пира проверяется прямо из идентификатора, без обращения к внешнему реестру.
Корневой сервис, который транспорт принимает при сборке, на практике — Router. Он читает первые четыре байта тела обращения как идентификатор TL-конструктора и по нему передаёт обращение нужному сервису. DHT, оверлеи и прочие подсистемы узла сами реализуют общий контракт сервиса (on_query/on_message) и регистрируются в Router каждая под своим диапазоном идентификаторов. Так один QUIC-транспорт обслуживает сразу несколько независимых подсистем. Router и базовые типы (идентификатор узла, контактная информация, абстракция сервиса) в отдельную статью раздела не выделены: они разобраны в статье о транспорте вместе с самим QUIC-соединением, рукопожатием и форматом кадров.
DHT
DHT — распределённая хеш-таблица, через которую узлы публикуют подписанные записи о себе и находят контактную информацию друг друга без центрального реестра. Идентификаторы узлов и хеши ключей значений живут в одном 256-битном пространстве с XOR-метрикой. Узел, знающий из транспорта только идентификатор пира, обменивается с ним DHT-запросами тем же способом, каким передаёт и остальные обращения: сервисом, зарегистрированным в Router.
Роль DHT не исчерпывается поиском адреса по идентификатору: тем же механизмом хранения и поиска значений оверлеи публикуют и находят себя, а резолвер узлов держит контактную информацию конкретных пиров актуальной для тех, кому это важно постоянно. Таблица маршрутизации, итеративный поиск, виды хранимых значений и бан на этом уровне — предмет отдельной статьи о DHT.
Оверлеи
Транспорт одинаково обслуживает обращения любых узлов сети, но многие задачи касаются не всей сети, а лишь её части. Такое подмножество — оверлей: логическая подсеть поверх общего транспорта, публичная (с открытым членством) или приватная (с фиксированным списком участников). На узле единый оверлей-сервис обслуживает оба вида. Он тоже зарегистрирован в Router транспорта и дальше сам разводит обращения по конкретным оверлеям.
Публичный оверлей опирается на DHT: список его участников — единственный вид группового (объединяемого) значения DHT в системе. Узел кладёт туда свой снимок записей строго локально, в собственное DHT-хранилище, без рассылки по сети, а снимки других узлов ищет там обычным сетевым поиском. Приватный оверлей не зависит от DHT по членству: список участников задаётся и меняется напрямую, без публикации и поиска в DHT (резолвер узлов через DHT для контактной информации участников остаётся опциональным). Устройство обоих видов, запись участника, ограничитель частоты и наполнение списка участников разбирает статья об оверлеях.
Клиент оверлея
Оверлей даёт список участников и правила членства, но не решает, кому из них адресовать конкретный запрос и как понять, что участник отвечает исправно. Это делает клиент оверлея — надстройка, которая строится из сетевого слоя, одного публичного оверлея и своей конфигурации. Он держит два независимых пула пиров:
- соседей — обычных участников оверлея, через которых отправляются запросы и скачиваются данные;
- валидаторов — цели широковещания, чьи контакты разрешаются через резолвер узлов оверлея и поддерживаются актуальными отдельным резолвером валидаторов.
Клиент опирается сразу на три нижних части:
- на оверлей — берёт из него текущий набор записей и уведомления об их изменении;
- на транспорт — через него отправляет запросы и получает на них ответы, а по типу сетевой ошибки (таймаут, битый сертификат или адрес, неизвестный транспорту пир) решает, как наказать соседа;
- на DHT — через резолвер узлов оверлея разрешает контакты валидаторов.
Сам клиент живёт не в tycho-network, а в tycho-core: он потребитель сетевого слоя, а не его часть. Статья о клиенте оверлея переходит к набору соседей, оценке надёжности, наказаниям и алгоритмам выбора адресата.
Blockchain RPC
Blockchain RPC — прикладной протокол поверх одного публичного оверлея, которым узел синхронизируется с сетью и распространяет сообщения. У протокола две независимые стороны: клиентская, которой узел скачивает у соседей блоки, ключевые блоки, архивы и устойчивые состояния и рассылает валидаторам внешние сообщения, и сервисная, которой узел сам отвечает на такие запросы и принимает широковещания. Клиентская сторона сама обращений не принимает и через транспорт их не отправляет — это делает клиент оверлея; сервисная, наоборот, сама реализует контракт сервиса сетевого слоя.
Blockchain RPC строится целиком поверх клиента оверлея и не заводит собственного механизма выбора адресатов. Загрузка блока выбирает соседа через автоматический выбор клиента, а рассылка внешнего сообщения берёт текущие цели широковещания у резолвера валидаторов. Наказание соседа за отсутствие данных, которые у него обязаны были быть, встраивается в ту же оценку надёжности, что ведёт клиент оверлея. Собственный вклад blockchain RPC — прикладная семантика: набор TL-запросов и ответов о блоках и состояниях, чанковая докачка крупных объектов и классификация трафика на лёгкие запросы, тяжёлые запросы и широковещания для раздельного ограничения частоты. Механизм самого ограничения частоты по IP и классу запроса общий для публичных оверлеев tycho-network, а blockchain RPC задаёт для него политику классификации и сами лимиты. Blockchain RPC, как и клиент оверлея, живёт в tycho-core. Статья о blockchain RPC разбирает протокол целиком, обе его стороны и лимиты трафика.
Граф зависимостей
Зависимости между частями идут в одну сторону, без циклов:
- транспорт — основание, использует только собственные базовые типы;
- DHT — как и оверлеи, зарегистрирован в Router транспорта сервисом наравне с прочими подсистемами;
- оверлеи опираются на транспорт (доставка обращений, проверка известности пира); публичные оверлеи дополнительно опираются на DHT (публикация и обнаружение списка участников), приватные — обходятся без неё по членству (резолвер узлов через DHT для них всё же опционален);
- клиент оверлея опирается на оверлеи (записи участников), транспорт (отправка и приём) и DHT (резолвер валидаторов);
- blockchain RPC опирается на клиент оверлея, но дотягивается и до самого оверлея напрямую: даёт прямой доступ к нему и может задавать для него политику ограничения частоты, если ограничитель включён. Его клиентская сторона сама обращений не принимает и через транспорт их не отправляет — это делает клиент оверлея; сервисная сторона, наоборот, сама реализует контракт сервиса сетевого слоя.
Слоями снизу вверх: транспорт как основание, DHT как зависящая от него, публичные оверлеи — над транспортом и DHT, приватные — по членству только над транспортом, клиент оверлея ещё выше, а blockchain RPC как самая верхняя прикладная надстройка.