Poon-Dryja 2016年ホワイトペーパーから BOLT 0〜12 の技術仕様まで、lnd / CLN / eclair / LDK の実装差異を含めてインタラクティブに解説します。
Joseph Poon と Thaddeus Dryja が 2016 年に発表した "The Bitcoin Lightning Network: Scalable Off-Chain Instant Payments" は、すべての LN 実装の起点となった技術文書です。
ホワイトペーパーの第1章は Bitcoin ブロックチェーンの根本的スケーラビリティ制約から始まります。
| 指標 | 値 |
|---|---|
| Bitcoin TPS | < 7 TPS |
| Visa ピーク TPS | 47,000 TPS |
| 同等処理に必要なブロックサイズ | 〜8 GB |
| 年間データ量 | 400+ TB |
→ 大多数の取引をオフチェーンで処理し、不正時のみ Bitcoin ブロックチェーンを使用する。
2者間で資金を Bitcoin トランザクションに ロック し、オフチェーンで何度でも残高を更新する。最終的に 1 つのトランザクションのみをブロードキャストする。
txin: Alice の資金 + Bob の資金
txout: 2-of-2 MultiSig
(Alice, Bob 双方の署名が必要)
この 2-of-2 MultiSig output を「チャネル」と呼ぶ。どちらか片方が離脱してもブロードキャストできるよう、commitment TX を事前に合意しておく。
txin: funding TX の 2-of-2 output txout[0]: Alice 残高 (to_local) txout[1]: Bob 残高 (to_remote)
状態が更新されるたびに新しい commitment TX を作成・署名し合う。古い commitment TX は無効化(revocation)が必要。
最大の設計課題: 「古い状態(自分が有利な状態)を勝手にブロードキャストされる」を防ぐ。Poon-Dryja はこれを Revocable Sequence Maturity Contract (RSMC) で解決した。
Commitment TX v3 を使いたい場合: 1. Alice が Bob に revocation_key_v2 を渡す 2. Bob が Alice に revocation_key_v2 を渡す 3. 双方が commitment TX v3 に署名 → v2 をブロードキャストすると相手に 全額持ち去られる (penalty TX)
OP_IF
# revocation key (相手が持つ)
<revocationpubkey>
OP_ELSE
# チャネル更新猶予期間
<to_self_delay> OP_CSV OP_DROP
<local_delayedpubkey>
OP_ENDIF
OP_CHECKSIG
自分の残高(to_local)は to_self_delay ブロック待たないと使えない。相手は revocation key を持っていれば即座に取れる。
2者間チャネルを複数の中継ノード経由で接続するため、ホワイトペーパーは HTLC を導入した。
r を選び、H = HASH(r) を invoice に含める。各 hop は「H の preimage を提示したら支払う(さもなくば期限後に返金)」という条件付き契約を結ぶ。各 hop の timeout を段階的に短くすることで、中継者が preimage を持ちながら upstream を騙すことを防ぐ。
Bob: timeout T+1Δ < Alice: timeout T+2Δ → Alice の HTLC が期限切れになる前に Bob の HTLC が先に期限切れになる
個別チャネルを組み合わせて全体の Payment Network を形成する。各ノードは直接チャネルを持たない相手にも、中継経路経由で支払える。
全ノードが全ルートの状態を把握する必要なし → ルーティングは各ノードが局所的に判断 onion routing で: - 送信者が全経路を指定 - 各中継ノードは次の hop しか知らない - 受信者も送信者を特定できない
| 要素 | ホワイトペーパーの提案 | 現実の実装 |
|---|---|---|
| Revocation | RSMC(Revocable Sequence Maturity) | BOLT 3 として標準化済み |
| HTLC | Hash Time-Lock Contract の設計 | BOLT 2/3 で厳密化 |
| Routing | ネットワーク構造の概念的説明 | Sphinx onion routing(BOLT 4)で具体化 |
| ネットワーク発見 | 言及のみ | BOLT 7 Gossip protocol として設計 |
| Invoice | なし | BOLT 11 → BOLT 12 として追加 |
各 BOLT の役割・主要メッセージ・設計の背景をインタラクティブに解説します。クリックして展開してください。
BOLT 0 は仕様全体の 目次と用語集 です。実装固有のプロトコルを定義するわけではなく、他のすべての BOLT が参照する共通概念を定義します。
| 用語 | 定義 |
|---|---|
MUST | 実装が従わなければならない要件 |
SHOULD | 強く推奨されるが例外あり |
MAY | 選択的実装 |
| funding output | チャネル開設の 2-of-2 MultiSig output |
| commitment number | 各 commitment TX の単調増加カウンタ |
n が even(required)、n+1 が odd(optional)。
すべての LN メッセージが従うワイヤーフォーマットと、接続確立時の基本メッセージを定義します。
+--------+----------+ | type | 2 bytes | | length | 2 bytes | | data | length B | +--------+----------+ TLV (Type-Length-Value) 拡張: +------+--------+---------+ | type | length | value | +------+--------+---------+ type: varint(奇数=unknown OK)
type: 16
fields:
globalfeatures (legacy)
localfeatures (legacy)
tlvs:
networks ← genesis block hash リスト
(feature bits は BOLT 9)
接続時に双方が init を交換して feature bit を合意する。知らない required feature があれば切断。
チャネルのライフサイクル全体(開設→HTLC→クローズ)のメッセージシーケンスを定義します。最も複雑な BOLT の一つです。
open_channel2 / accept_channel2 を使い、双方が funding TX に資金を拠出できる。lnd・LDK は未実装。max_accepted_htlcs ≤ 483。Bitcoin TX の標準性ルール(weight 上限)から来る制約。スロット枯渇 jamming 攻撃の根因。
双方合意なら最短 1 トランザクションで完了。to_self_delay 待ちも不要。
片方が離脱した場合、最新の commitment TX を一方的にブロードキャストする。
to_local: to_self_delay 後に受取 to_remote: 即時受取(P2WPKH) HTLC: HTLC-Success/Timeout TX で解決
BOLT 3 は commitment TX と HTLC TX の厳密な構造を定義します。スクリプト・署名タイプ・手数料計算まで完全に規定されており、実装の中で最も複雑な BOLT です。
txin[0]: funding output (2-of-2 sig) txout[0]: to_local (delayed P2WSH) txout[1]: to_remote (P2WPKH or anchor) txout[2]: anchor_local (330 sat, optional) txout[3]: anchor_remote (330 sat, optional) txout[4+]: HTLC outputs (P2WSH each)
option_anchors 有効時: - HTLC TX: SIGHASH_SINGLE|ANYONECANPAY - 両者に 330 sat の anchor output - force close 時に CPFP で手数料追加可
Lightning Network の送信者プライバシーを実現する Sphinx onion routing プロトコルを定義します。2024 年の改訂で Route Blinding が統合されました。
onion_packet: version: 1 byte (=0) public_key: 33 bytes (Diffie-Hellman) hops_data: 1300 bytes (暗号化された hop 情報) hmac: 32 bytes (認証)
各 hop は自分の鍵でのみ復号できる層を剥がし、残りを次の hop へ転送。1300 bytes で最大 20 hop 程度を収容。
amt_to_forward: 転送金額 outgoing_cltv_value: 次の HTLC の timeout short_channel_id: 次の hop のチャネル ID payment_data: (最終 hop) payment_secret + total_msat
受信者が経路の後半部分を暗号化して invoice に含める。送信者は受信者の実 node ID を知らずに送信できる。
encrypted_recipient_data を使う。送信者には Intro Node の ID だけが見える。BOLT 12 Offers の受信者プライバシーに使用。| 実装 | Route Blinding |
|---|---|
| lnd | 実装中 |
| CLN | ✓ deploy 済 |
| eclair | ✓ deploy 済 |
| LDK | ✓ |
1. 最新の commitment TX をブロードキャスト 2. to_remote: 即時使用可能 3. to_local: to_self_delay ブロック後 4. HTLC-Timeout TX: cltv_expiry 後にブロードキャスト 5. HTLC-Success TX: preimage が判明次第 ※相手が古い commitment TX をブロードキャストしたら: → Penalty TX(breach remedy)で全額没収
to_self_delay(一般的に 144〜2016 ブロック)。この間に Watchtower が代替監視。ノードがオフラインの間も breach(古い commitment TX の使用)を検出・応答するために Watchtower を使用。
| 実装 | Watchtower |
|---|---|
| lnd | 統合型 Altruist Watchtower |
| CLN | プラグイン経由 |
| eclair | 外部連携 |
| LDK | ChainMonitor API |
short_channel_id: ブロック高+tx位置+out番号 node_id_1, node_id_2: チャネルの両端ノード bitcoin_key_1, bitcoin_key_2: on-chain 鍵 signatures: 4 個(双方の node/bitcoin 鍵)
チャネル存在の証明として、on-chain funding TX の署名を含む。
short_channel_id: チャネル識別子 timestamp: 更新タイムスタンプ cltv_expiry_delta: 中継 HTLC の timeout δ htlc_minimum_msat: 最小転送額 fee_base_msat: 固定手数料 fee_proportional_millionths: 比例手数料 (ppm) htlc_maximum_msat: 最大転送額
Act 1 (Initiator → Responder): initiator が ephemeral key を生成 ECDH(ephemeral, responder_static) → shared secret → encrypt empty payload Act 2 (Responder → Initiator): responder が ephemeral key を生成 ECDH(ephemeral_r, ephemeral_i) → shared secret → encrypt empty payload Act 3 (Initiator → Responder): initiator が自分の static key を送信 → 以降 ChaCha20-Poly1305 で暗号化
| 用途 | アルゴリズム |
|---|---|
| 鍵交換 | secp256k1 ECDH |
| ハッシュ | SHA-256 |
| 暗号化 | ChaCha20-Poly1305 |
実装間で機能を交渉するための feature bit 一覧。init メッセージと node_announcement で交換される。
| Bit | 機能 | lnd | CLN | eclair | LDK |
|---|---|---|---|---|---|
| 0/1 | option_data_loss_protect | ✓ | ✓ | ✓ | ✓ |
| 4/5 | initial_routing_sync | ✓ | ✓ | ✓ | ✓ |
| 6/7 | upfront_shutdown_script | ✓ | ✓ | ✓ | ✓ |
| 8/9 | gossip_queries | ✓ | ✓ | ✓ | ✓ |
| 14/15 | payment_secret | ✓ | ✓ | ✓ | ✓ |
| 16/17 | basic_mpp | ✓ | ✓ | ✓ | ✓ |
| 20/21 | option_anchor_outputs | ✓ | ✓ | ✓ | ✓ |
| 22/23 | option_anchors_zero_fee | ✓ | ✓ | ✓ | ✓ |
| 44/45 | option_channel_type | ✓ | ✓ | ✓ | ✓ |
| 48/49 | option_scid_alias | ✓ | ✓ | ✓ | ✓ |
| 50/51 | option_zero_conf | ✓ | ✓ | ✓ | ✓ |
| 12/13 | option_static_remotekey | ✓ | ✓ | ✓ | ✓ |
lnbc10m1p0rsn9qpp5...
│ │ │
│ │ └ データ部 (bech32 エンコード)
│ └─── 金額 (10m = 10 millibitcoin)
└─────── ln + bc (mainnet)
ln + tb (testnet)
ln + bcrt (regtest)
| タグ | フィールド | 必須 |
|---|---|---|
p | payment_hash (32B) | ✓ |
s | payment_secret (32B, MPP用) | 推奨 |
d | description (UTF-8) | d or h |
h | description_hash (SHA256) | d or h |
n | payee node_id (33B) | — |
x | expiry (秒, デフォルト 3600) | — |
c | min_final_cltv_expiry | — |
f | fallback on-chain address | — |
r | routing hint (プライベート CH用) | — |
signature: secp256k1 ECDSA
(payee node の秘密鍵で)
recovery_flag: (0-3)
→ 公開鍵を復元して検証
BOLT 12 は Offer(静的な支払い endpoint)を定義します。受信者が一度 Offer を作ればほぼ永続的に再利用でき、送信者が onion message で動的に invoice を要求します。
offer_id: SHA256 of offer TLV chains: Bitcoin mainnet amount: 固定額 or 任意額 currency: BTC (or fiat) description: "Monthly subscription" issuer: "Example Co." quantity_max: 複数個注文可 recurrence: 定期支払い設定
| 特性 | BOLT 11 | BOLT 12 |
|---|---|---|
| 再利用 | ✗ 1 回のみ | ✓ 何度でも |
| 受信者プライバシー | node ID 公開 | blinded path |
| 送信者プライバシー | なし | onion msg |
| 定期支払い | 非対応 | recurrence |
| 金額指定 | 固定 | 動的指定可 |
| 署名方式 | ECDSA | Schnorr (BIP-340) |
| 実装 | BOLT 12 |
|---|---|
| lnd | 実装中 |
| CLN | ✓ deploy 済(2023〜) |
| eclair | ✓ deploy 済(2024〜) |
| LDK | ✓ |
Taproot(BIP-341)と MuSig2(BIP-327)を利用して、commitment TX の出力を通常の Taproot output に見せる プライバシー改善 と 手数料削減 を実現するドラフト仕様。
現在 (P2WSH): funding output → 2-of-2 OP_CHECKMULTISIG on-chain に "これは LN チャネル" と見える Taproot チャネル: funding output → P2TR (MuSig2 keypath) cooperative close → 通常の keypath spend → on-chain では普通の single-sig TX に見える
Funding output: P2TR with keypath = MuSig2(Alice, Bob) tapscript = penalty script (force close 用) HTLC output: P2TR with keypath = MuSig2 adaptor sig (PTLC 化の前段階として) Commitment TX 署名: MuSig2 の 2-round 署名プロセスを BOLT 2 のメッセージシーケンスに統合
| 実装 | Taproot CH |
|---|---|
| lnd | 実験的 (v0.18+) |
| CLN | 開発中 |
| eclair | なし |
| LDK | 開発中 |
lnd / CLN / eclair / LDK の BOLT 機能サポート状況と設計思想の違いを整理します。
Go 実装。gRPC API 中心のフルノード。豊富な API と周辺ツール(Loop/Pool/Terminal)が強み。Taproot チャネルの先行実装。
C コア + プラグインアーキテクチャ。任意言語でノードを拡張可能。Dual-funded channels・Splicing・BOLT 12 の最速 deploy。
Scala/Akka 実装。Phoenix モバイルウォレットのバックエンド。Cluster モードで大規模ルーティングノード運用。LSPS2 リファレンス。
Rust ライブラリ。アプリに組み込む設計。チェーン同期・鍵管理・ストレージを呼び出し側が提供(Bring Your Own Component)。
| 機能 | lnd | CLN | eclair | LDK |
|---|---|---|---|---|
| コア BOLT 機能 | ||||
| BOLT 1-9 コア | ✓ | ✓ | ✓ | ✓ |
| Anchor Outputs | ✓ | ✓ | ✓ | ✓ |
| MPP (basic_mpp) | ✓ | ✓ | ✓ | ✓ |
| Onion Messages | ✓ | ✓ | ✓ | ✓ |
| 最新機能 | ||||
| BOLT 12 Offers | 実装中 | ✓ (2023〜) | ✓ (2024〜) | ✓ |
| Route Blinding | 実装中 | ✓ | ✓ | ✓ |
| Taproot Channels | 実験的 | 開発中 | — | 開発中 |
| Splicing | — | ✓ | 開発中 | — |
| Dual-funded (v2) | — | ✓ | — | — |
| Zero-conf Channels | ✓ (v0.15+) | ✓ | ✓ | ✓ (v0.0.107+) |
| 固有機能 | ||||
| Watchtower 統合 | ✓ Altruist | プラグイン | 外部連携 | ChainMonitor API |
| Circular Rebalancing | 手動 | プラグイン | ✓ 自動 | — |
| Probabilistic Scoring | ✓ | プラグイン | ✓ | ✓ (主力機能) |
| PostgreSQL バックエンド | — | ✓ | — | — |
| Macaroon 認証 | ✓ | — | — | — |
| Mobile Language Bindings | — | — | ✓ (Phoenix) | ✓ Swift/Kotlin |
BOLT 3 は Lightning Network で最も複雑な仕様です。onchain トランザクションの厳密な構造を定義し、実装のセキュリティの核心を担います。
version: 2 (または 3 for zero_fee)
locktime: obscured commitment number
(privacy のため難読化)
txin[0]: funding output
sequence: obscured commitment number
txout (option_anchors 有効時):
[0] to_local: P2WSH (delayed)
[1] to_remote: P2WPKH or P2WSH
[2] anchor_local: 330 sat P2WSH
[3] anchor_remote: 330 sat P2WSH
[4+] HTLC outputs: P2WSH each
txout (option_anchors なし):
[0] to_local: P2WSH (delayed)
[1] to_remote: P2WPKH
[2+] HTLC outputs
OP_IF
# Penalty path (相手が revocation key を保有)
<revocationpubkey>
OP_ELSE
# Self-spend path (猶予後に自分が使う)
<to_self_delay> OP_CSV OP_DROP
<local_delayedpubkey>
OP_ENDIF
OP_CHECKSIG
P2WPKH(<remote_pubkey>) # 即時使用可能(猶予なし) # ただし commitment ごとに同じ鍵を使用 # → バックアップ不要で鍵を管理可能
# Revocation path: 相手が revocation key を提示して即時没収
OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
OP_IF
OP_CHECKSIG
OP_ELSE
<remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
OP_NOTIF
# HTLC-Timeout TX を経由したローカルノードの回収
OP_DROP 2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
OP_ELSE
# Preimage path: 相手が preimage を提示して受け取り
OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
OP_CHECKSIG
OP_ENDIF
OP_ENDIF
# Revocation path
OP_DUP OP_HASH160 <RIPEMD160(revocationpubkey)> OP_EQUAL
OP_IF
OP_CHECKSIG
OP_ELSE
<remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
OP_IF
# Preimage: ローカルノードが preimage で受け取り
OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
OP_ELSE
# Timeout: 相手が期限後に返金
OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
OP_CHECKSIG
OP_ENDIF
OP_ENDIF
| パス | 誰が | 条件 |
|---|---|---|
| Revocation | 相手ノード | revocation key を保有 |
| Preimage | 受信者 | payment preimage を提示 |
| Timeout | 送信者 | HTLC-Timeout TX 経由 |
commitment TX の force close 後、HTLC output の解決に 2 つの別 TX(HTLC-Success / HTLC-Timeout)を使う。
to_self_delay を待つ必要がある。しかし HTLC には独自の cltv_expiry がある。2 つの遅延を直接合算すると経路全体の timeout が不必要に長くなるため、HTLC output を別 TX で先に解決し、その output に to_self_delay をかける 2 層構造を採用。version: 2
locktime: 0
txin[0]: commitment TX の received HTLC output
witness: 0 <remotehtlcsig> <localhtlcsig> <preimage>
txout[0]: P2WSH (to_self_delay 後に使用可)
script:
OP_IF
<revocationpubkey> # penalty path
OP_ELSE
<to_self_delay> OP_CSV OP_DROP
<local_delayedpubkey>
OP_ENDIF
OP_CHECKSIG
成功条件: preimage + 相手の HTLC 署名が必要。これにより「相手なしに勝手に HTLC を解決できない」。
version: 2
locktime: cltv_expiry # ← HTLC の期限
txin[0]: commitment TX の offered HTLC output
witness: 0 <remotehtlcsig> <localhtlcsig> <>
# preimage なし
txout[0]: P2WSH (同じく to_self_delay 後)
script: 同上 (to_local と同じ delayed 構造)
タイムアウト後にのみ有効: locktime = cltv_expiry により期限前のブロードキャスト不可。remotehtlcsig が必要 → local node が単独で操作できない。
SIGHASH_SINGLE|SIGHASH_ANYONECANPAY で署名 → 後から fee input を追加して手数料を調整できる。dust_limit_satoshis(例: 546 sat)を 下回る金額の HTLC は: option_anchors なし: → commitment TX の miner fee に加算 → onchain に output が現れない option_anchors あり: → shared_anchor output に加算
1 commitment TX に格納できる HTLC output は最大 483 個。
計算根拠: Bitcoin TX 標準性: max weight = 400,000 wu commitment TX の overhead (input/output) を差し引き offered HTLC P2WSH weight ≈ 172 wu received HTLC P2WSH weight ≈ 170 wu → max HTLC ≈ 966 / 2 = 483
| 実装 | デフォルト max_accepted_htlcs |
|---|---|
| lnd | 483 (最大値) |
| CLN | 483 |
| eclair | 30 (デフォルト、設定可変) |
| LDK | 50 (推奨デフォルト) |
HTLC の hash を Schnorr adaptor signature(EC point)で置き換える。経路プライバシーの根本改善。
チャネルを閉じずにオンチェーンで資金を追加・引き出し。CLN が 2023 年に deploy 済み、eclair が開発中。
HTLC Endorsement + Upfront Fee の組み合わせが最有力候補(SoK, AFT 2024)。しかし具体的な設計パラメータが未合意。
Revocation 機構を廃止し、最新状態のみブロードキャストできる対称チャネル。BIP-118 (ANYPREVOUT) が必要 → Bitcoin に未採用。
adaptor signature・MuSig2 など LN の暗号基盤は量子コンピュータ脆弱。格子暗号ベースの adaptor signature 研究が始まっているが、実用的な仕様はない。
lightning/bolts リポジトリで議論・開発。Lightning Summit(年次会議)での合意が各 BOLT のマイルストーンとなる。提案は Lightning-dev メーリングリストまたは GitHub Issues で行う。