Bitcoin Optech Newsletterで取り上げられていた、LNのマルチホップ決済で中間者の資金を奪う攻撃方法について↓
もともとはLigning-DevやBitcoin-Dev MLでMatto Coralloによって議論されていた内容。
HTLCの構成
LNにおいてアリス→ボブ→マロリーの経路の送金をする場合(HTLCを使ったマルチホップ支払)
アリスとボブ間の送金の挙動は以下のいずれか(分かりやすくするため旧ステートのペナルティ条件は除外)
- ボブがハッシュのプリイメージを公開すればアリスからの送金を受け取ることができる。
- ボブがプリイメージを公開しない場合、80ブロック待ったらアリスは送金の払い戻しを受けられる。
ボブとマロリー間の送金の挙動は
- マロリーがハッシュのプリイメージを公開すればボブからの送金を受け取ることができる。
- マロリーがプリイメージを公開しない場合、40ブロック待ったらボブは送金の払い戻しを受けられる。
通常このコントラクトを含むコミットメントトランザクションが作成され、プリイメージを使った決済もオフチェーンで行われるが、プロトコル的にはコミットメントトランザクションをブロードキャストすることで、オンチェーン上で決済をすることも可能。
↑のHTLCはオンチェーン上では以下のように動作する。
攻撃方法
↑のオンチェーンHTLCプロセスに対する攻撃は、ボブのプリイメージの学習を妨げると同時に、ボブによる払い戻し用トランザクションの作成を防ぐことで、中継者であるボブから資金を盗むというもの。
プリイメージの拒否
マロリーは自身の決済トランザクションの手数料をすぐにはブロックに取り込まれないよう低く設定する。この場合、ボブがメモリプールを監視しておらず、ブロックチェーン上のトランザクションのみを監視している場合、マロリーの決済トランザクションがブロックに含まれるまで、その存在に気付かず、プリイメーが分からない。
払い戻しの拒否
ボブは80ブロック過ぎればブロードキャストされたコミットメントトランザクションのHTLCアウトプットをインプットとした払い戻し用のトランザクションを作成することで取り戻せるが、それより前にマロリーが↑のように決済トランザクションを事前にブロードキャストすることで、マイナーや他のBitcoinノードが後からブロードキャストされるボブの払い戻しトランザクションの受け入れを拒否する可能性がある。ブロックに含まれてはいないとは言え、決済トランザクションは各ノードにリレーされており、そのインプットであるコミットメントトランザクションのHTLCアウトプットは使用済みであるとされるから、ボブの払い戻しトランザクションはリジェクトされる。
ボブの払い戻しトランザクションはRBF(Replacement by Fee)を使ってより高い手数料を支払うことで、マロリーの決済トランザクションに取って代わる可能性はあるが、実際にはマロリーはさまざまなトランザクション固定技術(RBFを使えないようにするなど)を使ってその交換を防ぐことができる。
↑の攻撃により、ボブは決済トランザクションのプリイメージを知ることも、払い戻しトランザクションが承認されることも防がれるので、80ブロックが過ぎるとアリスはアリス−ボブ間のHTLCコントラクトにより払い戻しを受けられる。マロリーの決済トランザクションが最終的に承認されると、ボブだけが資金を失うことになる。
ただ、オンチェーントランザクションを使った攻撃になるので、トランザクション手数料とか考えると少額決済とかであれば攻撃は割に合わない場合もあるのと、決済トランザクションがブロックに入るタイミングを正確に制御することはできない。
解決策
解決策として挙げられているのは以下の3つ。
メモリプールもチェック
ボブがフルノードを使ってBitcoinのリレーネットワークを監視しメモリプールのトランザクションまで監視することで、マロリーの決済トランザクションについて知ることができるという解決策。ネックはフルノードを稼働させる必要があるというのと、これで完全解決できるわけでも無いということ。全てのフルノードが他のノートと全く同じトランザクションを受信するという保証はなく、マロリーのような攻撃者が、異なるピアに異なる競合トランザクションを送信するケースが考えられる(簡単に攻撃できるわけでもないけど)。
プリイメージの開示を頼むか支払いをするか
既にマロリーによりブロードキャストされた決済トランザクションを各ノードは持っており、それによりボブは払い戻しトランザクションをブロードキャストできない訳だが、接続先のノードがreject
メッセージでrejected: code 123: conflicts with txid 0123...cdef
のようにメモリプール内の決済トランザクションのtxidを受け取ることができれば、getdata
メッセージを利用して対象のトランザクションを受け取りプリイメージを学習するという方法も考えられる。ただ残念ながらreject
メッセージはBitcoin Coreでは既に無効化されているので使えない(もともと信頼性が低かったので無効化されたっぽいけど)。もしくは、マイナーや他のサードパーティにプリイメージと引き換えに支払いをするというのも考えられるが、こういったことをするためには、別のソフトウェアが必要になる。
Anchor Outputを持つ決済トランザクション
現在LNで新しく提案されている手数料を引き上げられるように設計されたLNのコミットメントトランザクションの特別なアウトプットAnchor Outputを利用して決済トランザクションを再設計する方法。ただし、この場合トランザクションサイズの増加により手数料が増え、事前署名が必要となる。
3つの解決策の中では好ましい解決策とされているみたいだけど、まだ利用できる状態ではないので、実装を待つ必要がある。
またこの攻撃とは別に、オンチェーンLNトランザクションの手数料管理に関連する別の課題もある。コミットメントトランザクションの手数料が署名時に設定されているので、署名後、実際にトランザクションがブロードキャストするまで数日、数週間かかる可能性があり、この場合迅速にブロックに入れるためには手数料が署名時の額では足りないケースが考えられるというもの。攻撃にもなるが、事前設定されたコミットメントトランザクションの手数料をバンプする仕組みはいずれの課題でも必要になる。