Перейти к содержимому

Архитектура

В Singula два слоя. В блокчейне лежит то, о чём все должны договориться: кто есть кто, кто заплатил и кто сколько отработал. Всё остальное — программы, которые работают постоянно и общаются по gRPC.

sequenceDiagram
    autonumber
    participant C as Клиент
    participant CP as Control Plane
    participant N as Узел
    participant B as Блокчейн

    C->>CP: SessionRequest с подписью кошелька<br/>или AccessProof
    CP->>N: PrepareSession
    Note over N: учётные данные запечатаны ECDH<br/>на ключ клиента
    N-->>CP: SessionReady
    CP-->>C: SessionCredentials<br/>(прочитать их CP не может)
    C->>N: VLESS поверх REALITY<br/>(TCP с Vision или xHTTP)
    loop каждые 30 секунд
        C->>CP: чекпоинт, подписанный ключом сессии
    end
    CP->>N: подпиши этот интервал
    N-->>CP: подпись узла
    CP->>B: EpochAttestations.push
КонтрактЧто делает
SingulaProtocolДиректория. Единственный адрес, который нужно знать; остальные адреса и параметры эпох читаются из него
StarRegistryКто есть кто: владелец, подписант, роль. Ещё это часы эпох
CPEndpointRegistryХост и порт каждого Control Plane и ключ его фронта
SubscriptionNFTOrbit: цена, срок, как делятся деньги
SubscriberRegistryМножество анонимности — упорядоченный список коммитментов
VoucherKeyRegistryКоммитменты к ключам, которыми Control Plane вслепую подписывают разрешения, по одному на окно
EpochAttestationsОтработанные секунды, с подписью узла на каждом интервале
RewardDistributorПулы и выплаты в USDC
GasStationПлатит газ за операции, ради которых пользователю не стоит заводить ETH

Подробно о каждом — в главе ончейн-слой.

И Control Plane, и клиенты читают эти адреса из SingulaProtocol при запуске.

Control Plane выдаёт сессии, проверяет право на них, собирает отчёты и публикует отработанное время. Трафик через него не идёт. Своё состояние он хранит локально в BadgerDB.

Рядом со своим gRPC каждый Control Plane держит фронт — вход по REALITY на порту 443, который ведёт к тому же gRPC и больше никуда. Он нужен клиентам из сетей, где сам адрес Control Plane заблокирован. Параметры фронта одинаковые у всех Control Plane, отличается только ключ, и каждый публикует свой в CPEndpointRegistry. Как им пользоваться — в разделе вход через фронт.

Узел — та же программа. На нём работает Xray с четырьмя входами REALITY, он обслуживает сессии и каждые 30 секунд шлёт своему Control Plane heartbeat.

Одна программа на обе роли. При запуске программа читает свою роль из блокчейна и включает то, что этой роли нужно.

Stargate — панель для операторов. Неизменяемые факты она берёт прямо из блокчейна, живые данные — у Control Plane. Одно от другого не зависит: если ни один Control Plane не отвечает, управлять звёздами всё равно можно, пропадает только текущая статистика.

Wanderer — клиент для Windows, Linux и Android на том же открытом API, что доступен всем.

  1. Клиент читает список Control Plane из CPEndpointRegistry, вызывает у каждого GetHealth и сортирует по скорости ответа. Никто не назначает клиенту Control Plane.
  2. Клиент показывает, что имеет право на сессию: подписью кошелька с именем этого Control Plane, которую тот проверит по SubscriptionNFT, или доказательством принадлежности к SubscriberRegistry, где кошелька нет вовсе.
  3. Control Plane выбирает узел по загрузке, свежести heartbeat и случайной добавке. Но не по тому, где находится клиент — этого он не знает и не спрашивает. Страна учитывается, только если клиент сам её попросил, и тогда это требование: если узла там нет, запрос отклоняется, а не обслуживается из другой страны. Клиент может и сам назвать узел.
  4. Узел заводит учётную запись VLESS и запечатывает учётные данные через ECDH на ключ клиента. Control Plane их передаёт, но прочитать не может.
  5. Клиент подключается прямо к узлу. С этого момента Control Plane трафика не видит.
  6. Клиент регулярно, обычно раз в 30 секунд, шлёт чекпоинт, подписанный ключом сессии. Время засчитывается, когда с последнего засчитанного чекпоинта пройдёт 64 КиБ, а если за 10 минут столько не набралось, это время сгорает.
  7. До истечения сессии клиент продлевает её через RenewSession, подписав ключом сессии. Control Plane снова проверяет право, так что истёкший Orbit останавливается на ближайшем продлении.
  8. Каждые четыре часа — и ещё раз за пять минут до конца эпохи — Control Plane склеивает соседние интервалы, просит каждый узел подписать свои и отправляет их в EpochAttestations. Без подписи узла контракт запись не примет.
  9. Когда эпоха закрывается, claimNode и claimCp выплачивают USDC на кошельки владельцев звёзд.

Секунда узла оплачивается по фиксированной ставке RewardDistributor.nodeRate(), а Control Plane получает фиксированную сумму за каждую эпоху своего места; подробнее — в экономике.

У звезды есть холодный владелец, куда приходят деньги, и горячий подписант на сервере. Кто захватит сервер, получит подписанта, но не деньги. Подробнее, в том числе как сменить ключ после взлома, — в главе звёзды и роли.