Розробка рішень на Bitcoin Lightning Network
Lightning Network — це не просто "швидкі Bitcoin платежі". Це протокол платіжних каналів, який дозволяє робити те, що неможливо на Bitcoin base layer: мікроплатежі в кілька сатоші, субсекундні транзакції, streaming payments (платити посекундно за контент або послугу). Але за цим стоїть нетривіальна інженерія: управління ліквідністю, routing, channel capacity, HTLC механізм. Розробник, який просто "підключив LND", не готов до production нагрузки.
Фундаментальний механізм: як працюють платіжні канали
Канал — це мультисиг 2-of-2 на Bitcoin base layer з commitment transactions. Коли Alice й Bob відкривають канал на 0.1 BTC, на chain ложиться одна funding transaction. Далі вони обмінюються off-chain commitment transactions, які перерозподіляють 0.1 BTC між ними. Поточний стан каналу — остання пара commitment transactions.
Безпека забезпечується наказанням: якщо хтось спробує закрити канал старим станом (у якому у нього більше грошей), інша сторона може протягом to_self_delay блоків забрати ВСІ кошти каналу через revocation secret. Цей justice transaction механізм забезпечує безпеку.
HTLC (Hash Time-Locked Contract) — механізм багатохопових платежів. Одержувач генерує preimage R, публікує H = SHA256(R). Відправник будує ланцюжок HTLC через проміжні ноди: "отримаєш кошти якщо предявиш preimage до хешу H до timeout T". Коли одержувач розкриває R — платіж "розвертається" назад по ланцюжку, кожен хоп отримує свою комісію.
Onion routing (Sphinx): кожна нода на шляху бачить тільки попередню й наступну хоп, не весь маршрут. Privacy за замовчуванням.
Вибір реалізації ноди
LND (Lightning Labs, Go)
Найбільш популярна реалізація. REST й gRPC API, активна розробка, велика екосистема інструментів.
# Базовий запуск (з Bitcoin Core бекендом)
lnd --bitcoin.active --bitcoin.mainnet \
--bitcoin.node=bitcoind \
--bitcoind.rpchost=localhost \
--bitcoind.rpcuser=user --bitcoind.rpcpass=pass \
--bitcoind.zmqpubrawtx=tcp://127.0.0.1:28333 \
--bitcoind.zmqpubrawblock=tcp://127.0.0.1:28332 \
--restlisten=0.0.0.0:8080 \
--tlsextraip=0.0.0.0
gRPC API через lnrpc:
conn, _ := grpc.Dial("localhost:10009", grpc.WithTransportCredentials(creds))
client := lnrpc.NewLightningClient(conn)
// Створити invoice
invoice, _ := client.AddInvoice(ctx, &lnrpc.Invoice{
Memo: "Order #12345",
Value: 1000, // satoshi
Expiry: 3600, // 1 час
Private: true, // використовувати private route hints
})
// invoice.PaymentRequest — BOLT-11 строка для QR коду
CLN (Core Lightning, Blockstream/Rusty Russell)
Мінімалістичний, plugin-архітектура. Кожний plugin — окремий процес, який спілкується через JSON-RPC. Дозволяє писати бізнес-логіку на будь-якій мові.
# CLN plugin на Python
from pyln.client import Plugin
plugin = Plugin()
@plugin.hook("invoice_payment")
def on_payment(payment, plugin, **kwargs):
# Викликається при кожному отриманому платежі
plugin.log(f"Received {payment['msat']} msat")
process_payment(payment)
return {"result": "continue"}
plugin.run()
Eclair (ACINQ, Scala)
Production-ready, використовується в Phoenix wallet. Добре документований. Оптимальний якщо ваш стек JVM/Scala.
Вибір для production
- LND — для більшості випадків. Зрілий API, lndhub сумісність, активна екосистема.
- CLN — якщо потрібна plugin архітектура й максимальна кастомізація.
- Eclair — для JVM стека або якщо працюєте з ACINQ (Phoenix, Strike інтеграції).
Управління ліквідністю: головне операційне завдання
Lightning нода — це не "запустив й забув". Ліквідність у каналах потребує постійного управління.
Inbound vs outbound ліквідність
Outbound capacity — скільки ви можете відправити. Створюється коли ви відкриваєте канал й кладете туди BTC.
Inbound capacity — скільки ви можете прийняти. Створюється коли хтось відкриває канал до вас, або через loop-out операції.
Для merchant ноди (приймаємо платежі) — потрібна inbound capacity. Для routing ноди — потрібен баланс з обох сторін.
Circular rebalancing
Якщо канал з Alice вичерпаний (весь баланс у Alice), а з Bob переповнений (весь баланс у нас), можемо відправити платіж самим собі через маршрут нас → Alice → ... → Bob → нас:
# LND: circular rebalance
lncli payinvoice --allow_self_payment \
--last_hop <bob_pubkey> \
--outgoing_chan_id <our_channel_with_bob> \
<self_invoice>
Автоматизація rebalancing: charge-lnd (правила на основі конфігурації), balanceofsatoshis (bos tool), або кастомний скрипт.
Loop (Lightning Loop)
Lightning Loop від LND дозволяє рухати ліквідність між on-chain й off-chain без закриття каналів:
- Loop Out: виводимо з Lightning в on-chain. Відновлює inbound capacity.
- Loop In: вводимо on-chain кошти в Lightning. Відновлює outbound capacity.
loopClient := looprpc.NewSwapClientClient(conn)
resp, _ := loopClient.LoopOut(ctx, &looprpc.LoopOutRequest{
Amt: 1_000_000, // satoshi
Dest: "bc1q...", // on-chain адреса отримання
MaxSwapRoutingFee: 1000,
MaxMinerFee: 5000,
})
Pool (Channel Leasing)
Lightning Pool — ринок ліквідності. Можна орендувати inbound capacity на період або здавати свою ліквідність в оренду. Актуально для merchant нод які потребують гарантованої inbound capacity.
Routing й комісії
Fee policy
Для routing ноди fee policy — це баланс між привабливістю й прибутковістю:
lncli updatechanpolicy \
--base_fee_msat 1000 \ # 1 sat фіксована комісія
--fee_rate 0.000001 \ # 0.0001% від суми
--time_lock_delta 40 \ # CLTV delta
--chan_point <funding_txid>:<output_index>
Динамічне управління комісіями: підвищуємо комісію на каналах з низьким outbound (запобігти подальшому вичерпанню), знижуємо на каналах з надлишком outbound (привабити routing через них). Інструменти: charge-lnd з конфігурацією стратегій, LNDg (dashboard + автоматизація).
Probing й pathfinding
LND використовує Dijkstra для знаходження шляху з урахуванням capacity, fee, CLTV requirements й historical success rate. Pathfinding враховує недавні failures — канал з якого пришла помилка отримує penalty в оцінці.
MPP (Multi-Path Payments) — розбиваємо великий платіж на кілька шляхів паралельно. Збільшує ймовірність успіху для великих сум:
// LND MPP через SendPaymentV2
req := &routerrpc.SendPaymentRequest{
PaymentRequest: bolt11,
MaxParts: 10, // до 10 частин
TimeoutSeconds: 60,
FeeLimitMsat: 10000, // 10 sat макс комісія
}
BOLT-11 й BOLT-12 інвойси
BOLT-11 — стандартний формат інвойса. Містить: одержувача (pubkey або через private route hints), суму, expiry, payment hash, description.
BOLT-12 Offers — новий стандарт (не всі реалізації підтримують):
- Reusable: один offer для множини платежів (ідеально для донатів)
- Без указання суми (покупатель вводить скільки хоче)
- Privacy: кожен платіж отримує унікальний invoice, offer не розкриває node pubkey напрямо
# CLN: створити BOLT-12 offer
lightning-cli offer any "Donation to my project"
# Повертає: lno1pg257... — це постійна строка для QR коду
Watchtower: захист від breach
Якщо ваша нода була offline, контрагент може спробувати закрити канал старим (выгідним для нього) станом. Watchtower — сервіс який моніторить chain за вас й публікує justice transaction якщо детектує breach.
LND має вбудований watchtower клієнт й сервер. Для production нод — обов'язково підключити кілька зовнішніх watchtowers:
lncli wtclient add <watchtower_pubkey>@<host>:<port>
Альтернатива: Eye of Satoshi — відкритий watchtower сервер для CLN.
Інтеграція в додаток
Прийняття Lightning платежів
import { AuthenticatedLnd } from "lightning";
import { createInvoice, subscribeToInvoices } from "lightning";
const subscription = subscribeToInvoices({ lnd });
subscription.on("invoice_updated", async (invoice) => {
if (!invoice.is_confirmed) return;
await db.orders.markPaid({
paymentHash: invoice.id,
paidAt: new Date(invoice.confirmed_at),
amountSat: invoice.received,
});
await notifyUser(invoice.description);
});
async function createPaymentRequest(orderAmount: number): Promise<string> {
const { request } = await createInvoice({
lnd,
tokens: orderAmount,
description: `Order payment`,
expires_at: new Date(Date.now() + 3600_000).toISOString(),
});
return request; // BOLT-11 строка
}
Streaming payments
Сплачування по одиниці часу — унікальна можливість Lightning:
// Відправка по 1 sat кожну секунду (через keysend)
async function streamPayment(recipientPubkey: string, durationSec: number) {
for (let i = 0; i < durationSec; i++) {
await sendPayment({
lnd,
destination: recipientPubkey,
tokens: 1, // 1 sat
is_allowing_self_payment: false,
});
await delay(1000);
}
}
L402 protocol (HTTP 402 Payment Required) — стандарт для pay-per-request API: клієнт отримує 402 з Lightning invoice, сплачує, включає preimage у заголовок наступного запиту.
Операційні питання
Резервні копії: channel.backup файл містить дані для Static Channel Backup (SCB) — відновлення коштів при потері ноди через cooperative close. Автоматичний backup при кожній зміні — обов'язковий.
Безпека ключів: LND wallet.db містить приватні ключі. HSM або Vault для production. Ніколи не зберігайте на тій же машині що й гарячий сервер без додаткового захисту.
Моніторинг: LND Prometheus exporter — стандартний інструмент. Ключові метрики: channel balance per channel, pending HTLCs, routing fee income, channel count, uptime.
| Компонент | Технологія |
|---|---|
| Lightning нода | LND v0.18+ або CLN v24+ |
| Bitcoin нода | Bitcoin Core (IBD ~1 тиждень) або Neutrino (легка) |
| API інтеграція | lightning npm пакет (LND) або pylightning (CLN) |
| Ліквідність | Lightning Pool + Loop |
| Моніторинг | LND Prometheus exporter + Grafana |
| Backup | Автоматичний SCB у S3/хмара |
Срок: налаштування production ноди з моніторингом й базовою інтеграцією — 2–4 тижні. Повне рішення з управлінням ліквідністю й кастомною бізнес-логікою — 2–4 місяці.







