Разработка Lightning-кошелька
Lightning Network — это payment channel сеть поверх Bitcoin, которая позволяет проводить платежи за миллисекунды при комиссии в доли сатоши. Идея проста: два участника блокируют BTC в мультисиг on-chain, после чего обмениваются подписанными состояниями баланса off-chain сколько угодно раз. On-chain транзакция только при открытии и закрытии канала. На практике — это граф из миллионов каналов, по которым платёж маршрутизируется через промежуточные узлы.
Разработка Lightning-кошелька — принципиально другая задача по сравнению с обычным Bitcoin или EVM кошельком. Здесь нет простого «подпиши транзакцию и отправь». Нужно управлять состоянием каналов, следить за on-chain событиями, обрабатывать routing, хранить секреты (preimage-ы). Ошибки в state management могут привести к потере средств.
Архитектура Lightning-кошелька
Lightning-кошелёк принципиально делится на два класса: custodial и non-custodial. Выбор определяет всю архитектуру.
Custodial кошелёк
Пользователь не держит ключи от каналов. Сервер (провайдер) управляет каналами, пользователь видит баланс и отправляет платежи через API. Примеры: Strike, CashApp, Wallet of Satoshi.
Плюсы: простая реализация клиентской части, нет проблем с channel management, пользователю не нужно быть онлайн. Минусы: custodial risk, регуляторные вопросы, пользователь доверяет провайдеру.
Custodial Lightning — это по сути API обёртка над LND или CLN нодой. Клиентское приложение работает с балансами в базе данных сервиса, реальные Lightning каналы только у провайдера.
Non-custodial: embedded node
Пользователь держит ключи, нода работает прямо в приложении. Два подхода:
LDK (Lightning Development Kit) — библиотека от Spiral (бывший Square Crypto). Rust-core с bindings для Swift, Kotlin, Python, JavaScript (через WASM). Максимальная гибкость: приложение сам решает что хранить, как хранить, откуда брать данные блокчейна. Используется в приложениях типа Phoenix (частично), Mutiny Wallet.
Breez SDK — более высокоуровневый, использует Greenlight под капотом. Greenlight от Blockstream — схема, где ключи у пользователя, но нода исполняется в облаке Blockstream. Разработчик не управляет нодой вообще — только SDK методы.
Глубоко: Payment Channel State Machine
Понимание state machine канала критично для любой серьёзной реализации. Покажу суть на упрощённой модели.
Commitment transaction — подписанная обеими сторонами транзакция, которую каждая из сторон может в любой момент опубликовать on-chain, закрыв канал. В каждый момент времени существует только одна валидная commitment transaction для каждой стороны (у каждой стороны своя версия с асимметричным timelock).
Почему асимметричная? Если Алиса публикует commitment transaction, она не может сразу потратить свой output — стоит OP_CHECKSEQUENCEVERIFY (CSV) задержка (например, 144 блока). Боб может потратить свой output немедленно. Это даёт Бобу время среагировать, если Алиса опубликовала старую (отозванную) commitment — он может взять весь баланс канала через penalty transaction.
Ключевой секрет — commitment revocation key. При каждом обновлении состояния стороны обмениваются per_commitment_secret предыдущего состояния. Получив этот секрет, противоположная сторона может при необходимости построить penalty transaction для наказания мошенника.
State 0: Alice 1 BTC, Bob 0 BTC -> Alice reveals secret_0 to Bob
State 1: Alice 0.5 BTC, Bob 0.5 -> Bob reveals secret_1 to Alice
State 2: Alice 0.3 BTC, Bob 0.7 -> Alice reveals secret_2 to Bob
Если Алиса пытается опубликовать State 0 (ей выгоднее), Боб уже имеет secret_0 и может применить penalty, забрав весь баланс Алисы. Это экономический стимул не мошенничать.
HTLC: маршрутизация через посредников
Для платежей через промежуточные узлы используется HTLC (Hash Time-Locked Contract). Платёж от Алисы к Кэрол через Боба:
- Кэрол генерирует random preimage
R, отдаёт Алисеhash(R)в invoice - Алиса добавляет HTLC в канал с Бобом: «отдай Бобу X сатоши, если он покажет preimage для
hash(R)до блока N» - Боб добавляет аналогичный HTLC в канал с Кэрол (чуть меньше сатоши — его fee, чуть меньший таймаут)
- Кэрол раскрывает preimage Бобу, забирает платёж
- Боб раскрывает preimage Алисе, забирает платёж
Если что-то идёт не так — HTLC истекает по таймауту, средства возвращаются. Боб узнал preimage только когда Кэрол его раскрыла — он не мог схитрить раньше.
В кодовой реализации (LDK) это выглядит как серия event callbacks:
fn handle_event(&self, event: Event) {
match event {
Event::PaymentClaimable { payment_hash, amount_msat, .. } => {
// Мы получаем входящий платёж, нужен preimage
if let Some(preimage) = self.pending_payments.get(&payment_hash) {
self.channel_manager.claim_funds(*preimage);
}
}
Event::PaymentClaimed { payment_hash, amount_msat, .. } => {
// Платёж успешно получен
}
Event::PaymentFailed { payment_hash, .. } => {
// Платёж не прошёл, нужно обновить UI
}
_ => {}
}
}
Watchtower: защита офлайн-пользователей
Non-custodial Lightning имеет фундаментальную проблему: если пользователь офлайн, а контрагент публикует старую commitment transaction — пользователь может потерять средства (окно CSV timelock). Решение — watchtower.
Watchtower — сервис, которому кошелёк делегирует мониторинг блокчейна. Алгоритм:
- При каждом обновлении состояния канала кошелёк отправляет watchtower зашифрованный blob (penalty transaction + ключ для расшифровки, зашифрованный txid отозванной commitment)
- Watchtower следит за блокчейном
- Если видит мошенническую commitment — расшифровывает blob, публикует penalty транзакцию
- Watchtower забирает долю penalty (обычно 1%) как reward
В LDK: channel_manager.get_relevant_txids() возвращает txid-ы, за которыми нужно следить. Данные для watchtower генерирует channel_monitor.get_latest_holder_commitment_txn().
Открытые протоколы: BOLT 13 (черновик). Реальные реализации: The Eye of Satoshi (TEOS), Lightning Rod (Zeus). Можно интегрировать готовый watchtower или поднять свой.
BOLT 12: Offers протокол
BOLT 11 invoice — одноразовый. Нельзя переиспользовать, нет поддержки повторяющихся платежей. BOLT 12 Offers — новый стандарт (уже в CLN, в разработке для LND):
- Offer — постоянный код, аналог payment address. Можно публиковать на сайте, принимать повторные платежи
- Refund — аналог для возвратов
- Встроенная поддержка recurrent payments
- Onion messaging для обмена invoice без on-chain операций
Для нового кошелька с прицелом на e-commerce интеграцию — стоит сразу добавить BOLT 12. CLN поддерживает полностью. LDK — активно разрабатывается.
Channel Management: submarine swaps и liquidity
Одна из главных UX-проблем Lightning — inbound liquidity. Чтобы получать платежи, нужно иметь входящую ликвидность в каналах. Для нового кошелька без каналов — это проблема.
Submarine Swap — атомарный обмен on-chain BTC на off-chain Lightning BTC (и обратно). Используется для:
- Пополнения кошелька через on-chain транзакцию с автоматическим открытием канала
- Вывода средств из Lightning в on-chain адрес
Протоколы: Loop (Lightning Labs), Boltz Exchange. Интеграция через их API или развёртывание собственного swap сервера.
LSP (Lightning Service Provider) — провайдер ликвидности. При первом платеже в кошелёк LSP автоматически открывает канал с нужной входящей ликвидностью. Стандарт: LSPS0/LSPS1/LSPS2. Phoenix использует именно эту модель.
Стек и технологии
| Компонент | Технология | Применение |
|---|---|---|
| Lightning core | LDK (Rust/bindings) | Non-custodial mobile |
| Hosted node | Greenlight + Breez SDK | Managed non-custodial |
| Lightning node | LND (Go) / CLN (C) | Custodial / server |
| On-chain data | Electrum protocol / Esplora | Синхронизация |
| Watchtower | TEOS / кастомный | Защита офлайн |
| Submarine swaps | Boltz API | On/off-ramp |
| Mobile | React Native + LDK bindings | iOS + Android |
Что важно при разработке
Persisting channel state — критично. Потеря channel monitor state может привести к потере средств или невозможности закрыть канал корректно. LDK требует надёжного Persist trait implementation — каждое обновление состояния должно быть записано до подтверждения новому контрагенту.
Fee management — HTLC routing fee и on-chain fee при открытии/закрытии каналов. Пользователь должен понимать fee structure. Для custodial кошельков — можно абсорбировать routing fee.
Invoice expiry — BOLT 11 invoice имеет expiry (по умолчанию 3600 секунд). UI должен показывать оставшееся время и уметь генерировать новый invoice.
Сроки
Custodial Lightning кошелёк (мобильное приложение + backend на LND/CLN): 6-8 недель.
Non-custodial с Breez SDK (упрощённый non-custodial): 8-10 недель — SDK скрывает большую часть сложности.
Полная non-custodial реализация на LDK с watchtower, LSP интеграцией, BOLT 12, submarine swaps: 4-6 месяцев. Это production-grade продукт уровня Phoenix или Mutiny.
Безопасность channel state management требует особого внимания и code review от специалистов с опытом в Lightning протоколе.







