Этот блог содержит технические инструкции по преобразованию необработанных сообщений, хранящихся в gosssip_store, в базе данных sqlite3 с использованием Node.js.
Хранение сетевых сообщений Lightning
Есть несколько способов решить эту проблему, c-lightning, а также LightningD можно использовать для получения последних сообщений gossip_messages.
Подход, используемый для целей этого проекта, заключается в архивировании всех gossip_messages в базе данных sqlite3 с использованием плагина Historian, созданного для core-lightning (https://github.com/lightningd/plugins/tree/master/historian)
Какие сообщения Lightning Network извлекаются?
С помощью подключаемого модуля архива извлекаются три типа сообщений Lightning Network.
- Channel_announcement
- Channel_update
- node_announcement
Channel_announcement gossip_message отвечает за предоставление информации о владельце канала. Он создает связь между каждым биткойн-ключом в цепочке с каждым ключом узла сети Lightning.
Сообщение Channel_update gossip_message отвечает за обновление информации в сети о каждой стороне канала (узла). Два узла на каждом конце канала обновляют сеть Lightning о своих комиссиях и минимальной дельте срока действия, необходимой для ретрансляции HTLC через этот канал.
node_announcement gossip_message позволяет узлу указывать дополнительные данные, связанные с ним, в дополнение к его открытому ключу.
Разбор Channel_announcement
Необработанное сообщение channel_announcement обычно представляет собой буфер длиной 432 байта. Каждый байт имеет свое значение и должен быть назначен определенному полю, чтобы получить осмысленный вывод из необработанного сообщения.
Преобразование необработанных сообщений в JSON можно выполнить с помощью Node.js или JavaScript. Чтобы узнать больше о полях, связанных с channel_announcement, вы можете ознакомиться со спецификациями сети Lightning по адресу https://github.com/lightning/bolts/blob/master/07-routing-gossip.md#the-node_announcement-message.
Первым шагом для анализа необработанного сообщения является сбор необработанного сообщения, это можно сделать с помощью SCID канала или, если вы анализируете все сообщения channel_announcement, мы можем просто перебрать их.
Node.js имеет встроенную функцию буфера, которую можно использовать для чтения потоков буфера, но мы также можем просто перебирать буфер с помощью циклов. У встроенной буферной функции Node.js есть несколько проблем, связанных с памятью, которых можно избежать, используя циклы.
Первые 2 байта буфера channel_announcement содержат информацию о версии.
Следующие 64 байта содержат подпись узла первого узла. Мы можем разобрать их, используя следующий метод:
В приведенном выше методе я создал переменную curr_index, которая значительно упрощает итерацию по буферу по сравнению с вычислением начальной и конечной точки по индексу. Приведенный выше код помогает нам сохранить шестнадцатеричное значение node_signature_1.
Следующие 64 байта содержат подпись узла второго узла, следующие 64 байта содержат подпись биткойна первого узла, а последующие 64 байта содержат подпись биткойна. второго узла.
Вот как выглядит вывод после разбора биткойнов и подписи узлов обоих узлов.
Теперь следующие 2 байта — это flenбайты, мы собираем и анализируем эти байты flen в целочисленном формате.
После синтаксического анализа мы узнаем точное количество байтов, которое нам нужно пройти, чтобы получить переменную feature.
После получения переменной функции мы анализируем следующие 32 байта, чтобы получить chain_hash.
Следующие 8 байтов содержат short_channel_id. Short_channel_id помогает нам проверить канал с блокчейном биткойна, поскольку он содержит номер блока, transaction_id и output_index канал. Первые 3 байта из этих 8 байтов содержат номер блока, следующие 3 байта содержат tx_id, а последние 2 байта содержат output_index. Нам также необходимо преобразовать шестнадцатеричные значения в целые, чтобы сделать их поддающимися проверке.
Short_channel_id при синтаксическом анализе должен выглядеть примерно так, как показано выше, мы можем дополнительно проверить этот канал, используя этот short_channel_id.
Далее мы анализируем node_id_1, перебирая следующие 33 байта, за которыми следуют еще 33 байта для node_id_2. Таким же образом мы читаем bitcoin_key_1, читая следующие 33 байта, и bitcoin_key_2, читая последний оставшийся 33 байта.
Разбор Channel_update
Необработанное сообщение channel_update обычно представляет собой буфер длиной 138 байт.
Первые 2 байта буфера channel_update содержат информацию о версии.
Первые 64 байта содержат подпись, следующие 32 байта содержат chain_hash. Уникальный факт с chain_hash заключается в том, что он должен быть эквивалентен «000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f», это значение можно использовать для проверки того, можете ли вы правильно проанализировать chain_hash или нет.
Следующие 8 байтов содержат short_channel_id, их анализ аналогичен анализу short_channel_idсообщения channel_annoucement.
Следующие 4 байта содержат отметку времени. Далее нам нужно преобразовать эту отметку времени из шестнадцатеричной в десятичную.
Следующий 1 байт содержит message_flags, следующий 1 байт содержит channel_flags, следующие 2 байта содержат cltv_expiry_delta, следующие 8 байтов содержат htlc_minimum_msat, следующие 4 байта содержат Fee_base_msat, следующие 4 байта содержат fee_proportional_millionths.
Теперь, если длина буфера равна 138, мы можем прочитать оставшиеся 8 байт для htlc_maximum_msat
Разбор node_announcement
Буфер node_annoucement имеет длину 161 байт.
Первые 2 байта буфера node_annoucement содержат информацию о версии.
Следующие 64 байта содержат подписьузла.
Теперь следующие 2 байта — это flenбайты, мы собираем и анализируем эти байты flen в целочисленном формате.
После синтаксического анализа мы узнаем точное количество байтов, которое нам нужно пройти, чтобы получить переменную feature. (То же, что и канал_объявление)
Следующие 4 байта содержат метку времени,мы преобразуем метку времени из шестнадцатеричной в десятичную.
Следующие 33 байта содержат parsed_node_id, следующие 3 байта содержат цвет RGB узла, а следующие 32 байта содержат псевдоним.
То же, что и flen bytes, следующие 2 байта буфера node_announcement содержат abytes, мы анализируем эти 2 байта из шестнадцатеричного в десятичное, чтобы получить количество байтов, которое нам нужно прочитать для получения адреса.
Первый абайт содержит тип адреса, в зависимости от адреса мы узнаем количество байтов, которые мы должны прочитать, чтобы получить адрес. Адрес может быть следующего типа:
- ipv4 (читаем 4 байта)
- ipv6 (читаем 16байт)
- Луковые сервисы Tor v2 (читаем 10 байт)
- Луковый сервис Tor v3 (читаем 35 байт)
далее во всех вышеперечисленных 4 типах мы должны прочитать оставшиеся два байта для получения номера порта.
Окончательный адрес должен выглядеть как приведенный выше объект JSON, адрес на приведенном выше рисунке представляет собой адрес типа ipv6.
Я создал репозиторий GitHub https://github.com/vinayaksh42/clightning-node-server, с помощью которого вы можете легко развернуть свой собственный сервер Node.js для разбора gossip_message. В приведенном выше репозитории вам нужно будет скопировать содержимое файла config/example.default.json и создать файл config/default.json, который будет указывать на ваше собственное развертывание базы данных sqlite3.
Я надеюсь, что этот блог помог вам разобрать ваши gossip_messages!