[Перевод] Lightning network in depth, part 1: payment channels
Lightning network это децентрализованная оф-чейн технология, позволяющая проводить десятки тысяч транзакий в секунду, как это позволяет делать, к примеру, Visa. На данный момент Биткоин — самая популярная в мире криптовалюта, не приспособлена для отправки более чем ~7 транзакций в секунду, а высокие комисси и долгое время подтверждения сводят на нет возможность отправки микротранзакций. Lightning network решает обе эти проблемы.
Table of contents
- Introduction
- Payment channels
- Simple payment channel example
- Trustless channels
- Using timelocks
- Asymmetric revocable commitments
- Conclusion
- Links
Introduction
Lightning network представляет из себя сеть платежных каналов, являющихся обычными мультисиг кошельками. Чтобы открыть канал, стороны создают мультисиг кошелек и отправляют на него средства. Полученная сумма становится балансом канала и все дальнейшие транзакции между участниками канала проводятся вне блокчейна. Канал в любое время может быть закрыт любой из сторон, в таком случае последняя офф-чейн транзакция, определяющая баланс канала, отправится в сеть, делая все предыдущие транзакции невалидными, так как они все тратят один и тот же 'выход'. Таким образом нам нужна всего лишь одна транзакция для открытия канала и еще одна для его закрытия, а все промежуточные транзакции проводятся моментально, без записи в блокчейн.
Сеть таких каналов позволит отправлять вам транзакции другому участнику сети, даже если вы не связаны с ним напрямую. Достаточно чтобы от вас к нему возможно было проложить 'путь', состоящий из цепочки каналов, причем вы не обязаны доверять никому из участников этой цепи, благодаря особым 'смарт-контрактам' (HTLC hash-time-lock-contract), гарантирующим безопасную доставку ваших средств.
Чтобы разобраться в том, как работает лайтнинг нужно сначала понять как работают платежные каналы, а также HTLC контракты, на работу которых он пологается. Это довольно объемные темы, поэтому мы разобьем эту статью на 2 части и начнем с объяснения механизма работы платежных каналов.
Payment channels
Как мы уже говорили выше, платежный канал между двумя участниками сети представляет из себя обычный мультисиг кошелек. Первую транзакцию, закрепляющую баланс канала (нашего мультисиг кошелька), мы будем называть 'открывающей' (funding transaction или же anchor transaction). Эта транзакция должна быть отправлена в сеть и замайнена, чтобы канал был создан.
Далее стороны обмениваются подписанными обоюдно коммит-транзакциями (commitment transaction), которые изменяют изначальный баланс канала. Эти транзакции валидны и могут быть отправлены в сеть, но вместо этого держутся вне сети, ожидая момента закрытия канала. Таким образом, состояние баланса канала может меняться тысячи раз в секунду, ограниченное только тем, как быстро стороны могут создавать, подписывать и передавать друг другу коммит-транзакции.
Каждый раз, обмениваясь новой коммит-транзакцией, стороны инвалидируют предыдущее состояние канала и таким образом только самая новая коммит-транзакция может быть 'выполнена'. Это сделано для того, чтобы стороны не попытались сжульничать, отправив в блокчейн одно из предыдущих состояний канала, которое им более выгодно. Далее я рассмотрю несколько механизмов, которые позволяют это реализовать.
Наконец, канал может быть закрыт как по обоюдному согласию — с помощью отправки в блокчейн 'закрывающей' транзакции (settlement transaction), так и по инициативе только одной и сторон — с помощью отправки в блокчейн последней коммит-транзакции. Таким образом мы предотвращаем случай, когда одна из сторон уходит в оффлайн и средства второй оказываются 'заперты' на канале.
На протяжении всего существования канала только две транзакции отправляются в сеть и записываются в блокчейн (открывающая и закрывающая). Между ними стороны могут обмениваться любым количеством коммит-транзакций, которые никогда не попадут в блокчейн.
Simple payment channel example
Перед тем как перейти к более сложным реализациям, рассмотрим на примере работу простого одностороннего канала. В этом примере сделаем допущение, что обе стороны честные, чтобы не усложнять объяснений. Далее рассмотрим механизмы, позволяющие предотвратить любую попытку сжульничать.
В этом примере у нас есть 2 участника — Эмма и Фабиан. Фабиан предоставляет услуги видео стримингового сервиса, оплачиваемого через канал с помощью микроплатежей — одна секунда видео стоит 0.00001 BTC, что составляет 0.036 BTC за час. Эмма — обычный пользователь, который хочет посмотреть какое-нибудь видео.
Эмма и Фабиан используют специальную программу, позволяющую работать и с платежным каналом и с видео. Эмма запускает эту программу в браузере, Фабиан на своем сервере. Программа имеет в себе функционал обычного биткоин-кошелька, умеет создавать и подписывать транзакции. Весь механизм работы платежного канала скрыт от пользователя, все что они видят — это как видео оплачивается каждую секунду.
Теперь рассмотрим как это будет работать. Для создания канала Эмма и Фабиан должны создать мультисиг адресс с условием два из двух. Со стороны пользователя, программа создает P2SH адрес (мультисиг кошелек) и просит пополнить его на сумму за 1 час просмотра. Эмма заносит на него 0.036 BTC и эта транзакция становится 'открывающей'.
Как только 'открывающая' транзакция подтверждена и канал открыт, начинается стриминг видео. На 1ой секунде пользовательская сторона создает и подписывает коммит-транзакцию, изменяющую баланс канала: 0.00001 BTC Фабиану и 0.03599 Эмме. Транзакция использует выход открывающей транзакции в 0.36 и содержит 2 новых, описанных только что. Программа на стороне сервиса получает эту транзакцию и также ее подписывает, после чего отправляет назад вместе с 1ой секундой видео. Теперь у сторон есть подписанная обеими сторонами коммит-транзакция, представляющая последнее состояние канала, которую они могут при необходимости отправить в сеть.
На 2ой секунде создается очередная коммит-транзакция, использующая тот же выход, что и предыдущая, а новые выходы теперь 0.00002 Фабиану и 0.03598 Эмме. Эта транзакция представляет собой платеж за 2 скаченные секунды видео. Далее она отправляется на вторую сторону и тд.
Допустим, Эмма посмотрела 10 минут видео и ей надоело, она остановила просмотр. За это время было отправлено и подписано 600 коммит-транзакций (600 секунд просмотра). Последняя из них имеет 2 выхода: 0.03 Эмме и 0.006 Фабиану. Эмма закрывает канал, отправляя эту коммит-транзакцию в сеть, делая ее 'закрывающей'. Таким образом в блокчейн попали только 2 транзакции.
Trustless channels
Конечно, в этом примере все работает, но только если обе стороны честны. Несложно придумать сценарий, где одна из сторон может сжульничать, получив преимущество или же канал не будет работать корректно:
- Как только канал открыт, Эмме нужна подпись Фабиана, чтобы вывести средства назад, так канал представляет из себя мультсиг кошелек 2-из-2. Если Фабиан исчезнет, средства Эммы могут навсегда остаться запертыми на канале.
- Пока канал открыт, Эмма может взять любую из коммит-транзакций, подписанную обеими сторонами. Посмотрев видео 10 минут, она может спокойно взять самую 1ую коммит-транзакцию и отправить ее в сеть без ведома Фабиана.
Using timelocks
Одним из решений этих проблем является использование таймеров в коммит-транзакциях (transaction-level timelocks (nLocktime)). Чтобы иметь гарантию, что ее средства не застрянут на канале, вместе с открывающей транзакцией Эмма создает транзакцию возврата средств (refund transaction), использующую выходы ее открывающей транзакции. Сначала она отправляет Фабиану эту транзакцию и как только он подписывает ее и возвращает, Эмма отправляет в сеть открывающую транзакцию, создавая канал.
Транзакция возврата средств становится 1ой коммит-транзакцией и её таймер устанавливает верхнюю границу жизни канала. Допустим, Эмма поставит таймер на 30 дней (4320 блоков). Все следующие коммит-транзакции будут иметь более короткий таймер, чтобы их можно было отправить в сеть раньше.
Теперь Эмма может спокойно открывать канал, зная, что если Фабиан исчезнет, через 30 дней она сможет вернуть свои средства (если бы это был двунаправленный канал и Фабиан вводил какие-то средства, со своей стороны он мог бы точно также создать транзакцию возврата).
Каждая новая коммит-транзакция будет иметь какой-то таймер, а именно более короткий, чем у её предшественника, чтобы таким образом самая последняя коммит-транзакция могла быть отправлена в сеть первой и инвалидировать предыдущие, защищая обе стороны от недобросовестного использования более ранних коммит-транзакций. Если все пройдет хорошо, то Эмма и Фабиан могут просто отправить обычную закрывающую транзакцию, так что коммит-транзакции в таком случае используются только при уходе в офлайн одной из сторон.
Например, если 1ая коммит-транзакция имеет таймер на 4320 блоков, тогда вторая может иметь таймер на 4319 блоков и тд. Транзакция #600 в таком случае может быть отправлена в сеть на 600 блоков раньше, чем транзакция #1 станет валидна.
Думаю, вы уже заметили, что этот метод хоть и помогает предотвратить использование более ранних коммит-транзакций с целью обмана, но тем не менее имеет 2 серьезных недостатка.
Таймер 1ой коммит-транзакции ограничивает время жизни канала.
Если поставить таймер на большое время (допустим год), то можно будет использовать канал очень долго, не открывая его заново, однако в случае исчезновения одной из сторон, второй придется ждать все оставшееся время, чтобы вывести средства с канала, отправив в сеть последнюю коммит-транзакцию.
Таймер 1ой коммит-транзакции ограничивает количество транзакций, которые можно отправить в канал.
Для нашего примера с таймером в 4320 блоков, на канал можно будет отправить не больше чем 4320 транзакций, так как каждая новая коммит-транзакция уменьшает таймер на 1 блок. Более того, используя интервал в 1 блок (10 минут), мы заставляем участников канала следить за тем, чтобы не проспать нужный блок и вовремя отправить последнюю коммит-транзакцию, если что-то пошло не так. Конечно можно увеличить интервал, но в таком случае лимит по транзакциям на канале уменьшится еще сильнее.
Таким образом с помощью таймера мы можем инвалидировать более ранние коммит-транзакции, а также гарантировать безопасное закрытие канала любой из сторон: если обе стороны согласны с последним состоянием канала, они просто могут отправить в сеть закрывающую транзакцию (по сути последнюю коммит-транзакцию) без какого-либо таймера и закрыть канал, а если одна из сторон исчезла, то вторая просто должна дождаться истечения таймера последней коммит-транзакции, чтобы отправить ее в сеть.
Asymmetric Revocable Commitments
Еще одним способом решения описанных ранее проблем доверия в канале является аннулирование более ранних коммит-транзакций. На самом деле, аннулирование это не совсем то слово, ведь в биткоине как только транзакция замайнена и подтверждена, ее нельзя никак отменить. Поэтому можно сконструировать ее таким образом, чтобы было невыгодно ее использовать. Это можно сделать дав каждой стороне по ключу отмены (revocation key).
В этот раз канал решили создать Хитеши и Ирэн. Они оба отправили на канал по 5 биткоинов, которые составляют начальный баланс канала. Теперь, вместо стандартной коммит-транзакции которую они оба должны подписать, Хитеши и Ирэн создают 2 разные ассиметричные коммит-транзакции.
У Хитеши есть коммит-транзакция с 2 мя выходами, подписанная Ирэн. Первый выход выплачивает 5 биткоинов Ирэн моментально, а второй выход выплачивает 5 биткоинов Хитеши, но с задержкой в 1000 блоков. Выгляит это так:
Input: 2-of-2 funding output, signed by Irene
Output 0 <5 bitcoin>:
CHECKSIG
Output 1:
<1000 blocks>
CHECKSEQUENCEVERIFY
DROP
CHECKSIG
В то же время у Ирэн также есть коммит-транзакция с 2 мя выходами, подписанная Хитеши. Первый выход выплачивает 5 биткоинов Хитеши моментально, а второй выход выплачивает Ирэн 5 биткоинов с задержкой в 1000 блоков.
Input: 2-of-2 funding output, signed by Hitesh
Output 0 <5 bitcoin>:
CHECKSIG
Output 1:
<1000 blocks>
CHECKSEQUENCEVERIFY
DROP
CHECKSIG
Таким образом у каждого есть коммит-транзакция, подписанная другой стороной. В любое время Хитеши или Ирэн могут подписать свою коммит-транзакцию и отправить ее в сеть, однако в таком случае другая сторона получит деньги моментально, а отправителю придется ждать 1000 блоков, что не очень выгодно, однако этого, очевидно, все еще мало, чтобы заставить обе стороны играть честно.
И теперь настало время ввести последний штрих — наш ключ отмены, который поволит наказать сторону, попытавшуюся сжульничать, забрав ее деньги.
Каждая из коммит-транзакций имеет один 'отложенный' выход. Сделаем так, чтобы потратить его мог либо отправитель с задержкой в 1000 блоков, либо 2ой участник канала, если у него есть ключ отмены. Таким образом когда Хитеши создает коммит-транзакцию для подписи Ирэной, он создает второй выход на себя с задержкой в 1000 блоков либо Ирэне, если она предъявит ключ отмены. Хитеши будет держать этот ключ в секрете и отправит Ирэн только когда захочет обновить состояние канала новой коммит-транзакцией. Выглядеть такая транзакция будет так:
Input: 2-of-2 funding output, signed by Irene
Output 0 <5 bitcoin>:
CHECKSIG
Output 1 <5 bitcoin>:
IF
# Revocation penalty output
ELSE
<1000 blocks>
CHECKSEQUENCEVERIFY
DROP
ENDIF
CHECKSIG
Разберем пример того, как это работает. Допустим Ирэн хочет отправить Хитеши 2 биткоина. Для этого им нужно обновить состояние канала, создав новую коммит-транзакцию. Они оба создают ассиметричные коммит-транзакции и перед тем, как их подписать, они обмениваются ключами отмены от предыдущих коммит транзакций, таким образом 'аннулируя' их. В данном случае Хитеши заинтересован в самом последнем состоянии баланса канала, однако для Ирэн предыдущее состояние более выгодно. Она могла бы попытаться отправить в сеть свою предыдущую коммит-транзакцию, но ключ отмены от нее уже у Хитеши и если он заметит, что она отправлена, у него будет 1000 блоков на то, чтобы забрать весь баланс канала (да, 'отмена' не произойдет автоматически, Хитеши должен заметить, что Ирэн отправила в сеть свою коммит-транзакцию, и воспользоваться ключом).
Таким образом реализация каналов с помощью ассиметричных отменяемых коммит-транзакций намного более эффективна так как не ограничивает ни время жизни канала, ни количество транзакций, которое можно на него отправить.
Conclusion
На этом мы заканчиваем первую статью. Думаю, вам понадобится некоторое время, чтобы все переварить, так что если есть вопросы — задавайте в комментарии. В следующей части мы разберем работу HTLC контрактов и наконец покажем как работает Lightning Network.
Links
- «Mastering bitcoin» — Andreas M. Antonopoulos
- Lightning network whitepaper
- Segregated witness for dummies