Разработка решений на 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 через intermediate узлы: "получишь средства если предъявишь preimage к хешу H до timeout T". Когда получатель раскрывает R — payment "разворачивается" обратно по цепочке, каждый hop получает свой fee.
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 и fees
Fee policy
Для routing ноды fee policy — это баланс между привлекательностью и прибыльностью:
lncli updatechanpolicy \
--base_fee_msat 1000 \ # 1 sat фиксированная fee
--fee_rate 0.000001 \ # 0.0001% от суммы
--time_lock_delta 40 \ # CLTV delta
--chan_point <funding_txid>:<output_index>
Динамическое управление fee: поднимать fee на каналах с низким 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 max fee
}
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 нод — обязательно подключить несколько внешних watchtower-ов:
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. Никогда не хранить на той же машине что и горячий сервер без дополнительной защиты.
Monitoring: 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 (lightweight) |
| API интеграция | lightning npm пакет (LND) или pylightning (CLN) |
| Ликвидность | Lightning Pool + Loop |
| Мониторинг | LND Prometheus exporter + Grafana |
| Backup | Автоматический SCB в S3/облако |
Срок: настройка production ноды с мониторингом и базовой интеграцией — 2–4 недели. Полное решение с управлением ликвидностью и custom бизнес-логикой — 2–4 месяца.







