Глоссарий / Lightning и layer 2
Луковая маршрутизация
Другие названия: sphinx.
- Что такое луковая маршрутизация?
- Луковая маршрутизация представляет собой многослойное шифрование, с помощью которого Lightning отправляет платеж через несколько узлов, и каждый узел получает только указания для собственной пересылки и ничего больше.
Каждый платеж Lightning путешествует внутри пакета фиксированного размера 1366 байт, слои которого снимаются по одному, так что пересылающий узел узнает своего предшественника и преемника и ничего больше. Размер пакета остается одинаковым на каждом шаге, что скрывает длину маршрута и ваше место в нем. От посторонних в середине маршрута ваша приватность надежна; от кошелька или биржи на каждом конце маршрута уже нет.
Как это работает
Луковая маршрутизация шифрует маршрут слоями, по одному на каждый шаг, обернутыми в обратном порядке, так что снятие внешнего слоя является единственной операцией, которую может выполнить любой узел.
BOLT 4 называет эту конструкцию Sphinx, дополненной полезной нагрузкой для каждого шага. Прежде чем платеж отправится в путь, ваш кошелек знает публичный ключ каждого узла на маршруте и применяет ECDH к каждому из них, чтобы вывести общий секрет. Из каждого общего секрета получаются четыре ключа: rho порождает поток байтов, который запутывает пакет, mu вычисляет HMAC целостности, um аутентифицирует ошибки на обратном пути, а pad задает начальное значение заполнителя. Этот поток представляет собой ChaCha20, примененный к нулям с нулевым одноразовым числом длиной 96 бит, что безопасно здесь только потому, что ни один ключ никогда не используется повторно.
У пакета четыре поля и один фиксированный размер: байт версии, сейчас 0x00, сжатая точка secp256k1 размером 33 байта, играющая роль эфемерного ключа, 1300 байт полезных нагрузок шагов и HMAC размером 32 байта. Вместе это 1366 байт в сети, и префикс длины не нужен.
Сборка идет в обратном порядке. Область размером 1300 байт начинается как случайные байты из потока ChaCha20, и для каждого шага от последнего к первому она сдвигается вправо, чтобы освободить место, при этом дальний конец выталкивается за край и отбрасывается. Для полезной нагрузки меньше 253 байт сдвиг равен длине этой нагрузки плюс 33: один байт длины и 32 байта HMAC. После каждого сдвига выполняется XOR с потоком rho этого шага, который заново перемешивает предыдущие слои.
Шаг читает короткий список типизированных полей: тип 2 означает amt_to_forward в миллисатоши, тип 4 означает outgoing_cltv_value, временную блокировку, которую он должен поставить на HTLC, предлагаемый дальше, а тип 6 означает short_channel_id, называющий канал, который нужно использовать, хотя узел может выбрать другой канал к тому же контрагенту. Вместо этого короткого идентификатора канала конечный узел получает тип 8, несущий секрет платежа размером 32 байта и общую сумму.
Еще один шаг не позволяет связать последовательные пакеты. Каждый шаг изменяет эфемерный ключ с помощью ослепляющего множителя, прежде чем передать его дальше, поэтому одна и та же луковица выглядит как несвязанные байты на каждом канале связи, который она пересекает. BOLT 4 честно говорит о пределе: запутывание "does not preclude the possibility of packet association by an attacker via traffic analysis".
Почему это важно при покупке биткоина
Луковая маршрутизация защищает вас от посторонних в середине маршрута и ни от кого на его концах, а это то, что чаще всего понимают неправильно, когда речь идет о приватности Lightning.
Первым шагом обычно выступает сервис, с которым у вас уже есть отношения, и он видит гораздо больше, чем случайный пересылающий узел. В обзоре Phoenix на этом сайте цитируется собственный FAQ ACINQ без смягчений: "The current version of Phoenix offers no advantage regarding privacy over existing, hosted, custodial wallets. We (ACINQ) know the final destination and amount of payments." Phoenix получает здесь оценку 4,0 и действительно является кошельком с самостоятельным хранением, настоящим узлом на смартфоне за сид-фразой из 12 слов. Хранение и приватность являются разными вопросами, и только на один из них он отвечает хорошо.
Принимающий конец не лучше. Strike хранит средства, пока они находятся в приложении, и требует верификации личности (KYC), поэтому вывод Lightning на ваш собственный кошелек сообщает Strike сумму, момент и счет, который был оплачен, сколько бы шагов ни прошел пакет. Wallet of Satoshi имеет в этом обзоре статус предостережения и оценку 2,7 отчасти потому, что компания держит ключи, и она уже вывела свой кастодиальный сервис Lightning из Европейского союза.
Поэтому не воспринимайте луковую маршрутизацию как способ обойти требования законодательства. Она не меняет того, какой раздел о законности в гиде по стране относится к вам, не скрывает покупку от биржи, которая ее продала, и ничего не дает, когда оператор вашего кошелька является одним из концов маршрута. То, что она дает, все равно стоит иметь: маршрутизирующий узел, о котором вы никогда не слышали, не может построить граф того, кто кому платит, не может определить, являетесь ли вы отправителем или очередным шагом, и не может отличить короткий маршрут от длинного.
Оплата счета Strike через два узла, о которых вы никогда не слышали
Оплата счета Strike через Lightning показывает, что каждый узел на маршруте узнает, а что нет.
Пусть ваш кошелек выбирает путь из четырех узлов: ваш собственный контрагент, два публичных маршрутизирующих узла, затем Strike. Пакет собирается в обратном порядке, начиная со Strike. Полезная нагрузка Strike получает итоговую сумму и секрет платежа. Каждая промежуточная полезная нагрузка получает amt_to_forward, который еще содержит комиссии всех нижестоящих узлов, outgoing_cltv_value, уменьшенное на объявленную этим узлом величину, и short_channel_id канала связи, который нужно использовать.
Второй маршрутизирующий узел читает ровно одну полезную нагрузку. Он узнает, что узел перед ним передал ему HTLC и что теперь он сам должен предложить дальше немного меньший HTLC. Он не узнает, что Strike находится в конце, не узнает, что вы находитесь в начале, и не может определить, состоит путь из четырех шагов или из восьми, потому что область, которую он передает дальше, представляет собой те же 1300 байт, которые он получил.
Если у этого узла нет ликвидности для пересылки, он собирает обратный пакет: HMAC под своим ключом um, код отказа, заполнитель, выбранный так, чтобы сообщение об отказе вместе с заполнителем занимало не меньше 256 байт, и результат, пропущенный через XOR с потоком из ключа ammag. Каждый шаг на обратном пути снова его запутывает. Ваш кошелек снимает слои и затем продолжает расшифровывать, пока цикл не выполнится 27 раз, что равно самому длинному маршруту, который допускает формат полезной нагрузки TLV, так что отказавший узел не может вычислить свою позицию по времени повторной попытки. Более новые узлы также прикрепляют данные об атрибуции: HMAC, усеченные до 4 байт, в количестве 210 для маршрута максимального размера в 20 шагов, и время удержания в единицах по 100 миллисекунд.
Луковая маршрутизация vs слепой маршрут
Луковая маршрутизация скрывает маршрут от узлов, пересылающих платеж, а слепой маршрут скрывает конец маршрута от того, кто платит.
Обычная луковая маршрутизация требует, чтобы отправитель знал настоящий публичный ключ каждого узла, потому что общие секреты выводятся через ECDH по этим ключам. Ослепление маршрута переворачивает это для последнего отрезка: получатель строит цепочку измененных идентификаторов узлов, превращая Bob в Bob prime, а Carol в Carol prime в собственном примере BOLT 4, затем передает отправителю точку входа плюс один зашифрованный блок данных на каждый шаг. Отправитель заворачивает в луковицу блоки, которые не может прочитать. Оба подхода дополняют друг друга, а не конкурируют: BOLT 4 требует, чтобы каждое луковое сообщение использовало ослепление маршрута, а луковое сообщение использует ту же форму пакета, что и платежная луковица.
Луковая маршрутизация vs HTLC
Луковая маршрутизация несет инструкции, а HTLC несет деньги, и платежу Lightning нужны оба, потому что каждый из них проверяет другой.
Луковица говорит шагу, куда пересылать и сколько. HTLC является условным платежом, который фактически предлагается по каналу. Поскольку область полезных нагрузок покрыта HMAC для всего пакета, который могут создать только отправитель и этот шаг, узел сравнивает предложенный ему HTLC с amt_to_forward и outgoing_cltv_value, записанными для него, и возвращает отказ, когда они не совпадают, что выявляет вышестоящий узел, незаметно урезающий сумму. Они также расходятся: луковое сообщение типа 513 представляет собой ту же конструкцию, не несущую денег, и ни одна ошибка никогда не возвращается от промежуточного шага по такому сообщению.