Розробка 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.
Плюси: простота реалізації клієнтської частини, немає проблем з управлінням каналами, користувачеві не потрібно бути онлайн. Мінуси: custodial ризик, нормативні питання, користувач довіряє провайдеру.
Custodial Lightning — це по суті API обгортка над LND чи CLN нодою. Клієнтське приложення працює з балансами у базі даних сервісу, реальні Lightning каналу лише у провайдера.
Non-custodial: вбудований вузол
Користувач тримає ключі, нода запускається прямо у приложенні. Два підходи:
LDK (Lightning Development Kit) — бібліотека від Spiral (колишній Square Crypto). Rust-ядро з біндингами для 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%) як награду
У LDK: channel_manager.get_relevant_txids() повертає txids, за якими потрібно слідкувати. Дані для 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 платежів
- Onion messaging для обміну invoice без on-chain операцій
Для нового кошелька з прицілом на e-commerce інтеграцію — варто одразу додати BOLT 12. CLN підтримує повністю. LDK — активно розробляється.
Channel Management: submarine swaps й ліквідність
Одна з головних UX-проблем Lightning — inbound ліквідність. Щоб отримувати платежі, потрібно мати входящу ліквідність у каналах. Для нового кошелька без каналів — це проблема.
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 — кожне оновлення стану повинно бути записане до підтвердження новому контрагенту.
Fee management — HTLC routing fee й on-chain fee при відкритті/закритті каналів. Користувач повинен розуміти fee структуру. Для 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 протоколі.







