Greenlightとチャネルの強制閉鎖
Greenlight, BreezSDKを使ったライトニング搭載ビットコインウォレットを開発中に、テスターから強制チャネル閉鎖になると報告がいくつかありました。そこでテスターからログをいただき、解析してみた結果、ビットコイン、ライトニング特有な原因であることがわかりました。以下はそのログの原因箇所を抜粋したものです。
19:08:57 : DEBUG 02c...70d-channeld-chan#1: Received commit_sig with 0 htlc sigs
19:08:59 : DEBUG 02c...70d-channeld-chan#1: sending_revoke_and_ack: HTLC REMOTE 15 = SENT_ADD_REVOCATION/RCVD_ADD_REVOCATION
19:08:59 : DEBUG 02c...70d-channeld-chan#1: revoke_and_ack made pending: commit timer
19:08:59 : DEBUG 02c...70d-channeld-chan#1: Sending master 1021
19:08:59 : UNUSUAL 02c...70d-chan#1: Deferring incoming commit until we sync
ライトニングの送金は、送信者と受信者が互いにその取引に署名をします。まずは、送信者がコミットメントに対して署名をします。受信者はそれを受け取り、内容に問題がなければ、古いコミットメントを失効させます。この際、受信者は古いコミットメントがオンチェーンへブロードキャストされていないか確認する必要があります。そのためには、まずはビットコインの最新のブロック高まで同期して確認します。もしブロック高の同期が未完であれば、相手からのコミットメントを受け取ってもその処理を中断して、ブロック高の同期を待ちます。もし、この状態でアプリを閉じてしまうとどうなるか...送信者はコミットメントに署名をして受信者へ渡した状態で、これは送金が宙に浮いている状態です。この場合ライトニングでは、ある一定期間が経過すると、その中途半端な取引をオンチェーンへ展開して資金を回収するプロトコルになっています。これが所謂、チャネルの強制閉鎖です。
ウォレットを開き、支払いを受け取ろうとする。しかしブロック高の同期が完了していない場合、その取引は中途半端になる。その状態でアプリを閉じることで、一定期間経過後にチャネルが閉鎖されてしまう。これがテスターから報告のあったチャネル強制閉鎖の原因でした。
対応策は、ブロック同期が完了するまでインボイスの生成や受け取りができないようにすれば良いはずです。
GreenlightやBreezSDKといったライトニングウォレットの開発が楽になるツールがでてきても、ブロック高の同期など、ビットコインの基本的な処理が必須で、これが「Don't trust. Verify」たる所以だなと改めて実感しました。
Greenglithgt はサーバーサイドにノードがあるから、モバイル側のアプリを起動した時にこのような sync を待たなくても良い、というのがメリットではないんでしたっけ?