[LN#023]HTLC (トランザクション)

Lightning Network BOLTの概要について、書いていくシリーズ。

LN#020, LN#021とLightning Network BOLTで使われているHTLCについて書きましたが、読んだ方から「スクリプトのどこでロックしているの?」という質問を受けました。
確かに、スクリプトの内容ばかり書いていて、どう制限がかかっているかについては、OP_CHECKLOCKTIMEVERIFYやOP_CHECKSEQUENCEVERIFYという命令名を書いただけになっていました。

今回は、HTLCとトランザクションについて、実データを例にしながら書いていきます。


regtestで行った例になります。
amountの単位として書いているmsatは msatoshi(ミリsatoshi)です。

  • Aさんが持つamount:300000000 msat
  • Bさんが持つamount : 300000000 msat

ここで、送金を行います。

  • Aさん→Bさん:200000000 msat

送金は、大ざっぱに書くと以下のような通信を行います。

image

送金する額のHTLCをcommitment transactionに追加する工程と、それを反映してcommitment transactionからHTLCを削除する工程です。
commitment transactionの構成が変わるのでそのたびに署名を交換します。

今回は、HTLCの追加に焦点を当てます。


Aさん:送金元(payer)

HTLC追加後の、Aさんが持つcommitment transactionはこうなりました。

ptarmiganが持っているトランザクション出力を使っているため、”bitcoin-cli decoderawtransaction” などとは構成が違うと思いますが、だいたいの雰囲気は伝わるかと思います。

image

HTLCへの送金になるのは、commitment transactionの出力が3つあるうちの真ん中になります。
Aさん=送金元なので、HTLCは「Offered HTLC output」になります。

Offered HTLC outputは、相手への送金を目的としているので、基本的にはBさん宛になるはずです。
Bさん宛=Bさんが署名してどこかに送金する、ということになります。
そのために必要になるのは、送金前に相手からもらったinvoiceに含まれている情報「payment_hash」のハッシュ計算をする前の値である「payment_preimage」という値です。

Aさんの立場からすると、

  • Bさんがpayment_preimageを使ってOffered HTLC outputをどこかに送金すれば、それでよし
  • もしそうしないまま放置するようだったら、送金はなかったものとして、Aさんがどこかに送金する

ということになっています。

この「放置するようだったら」の期限は、commitment transactionを見ても分からず、かといってOffered HTLCのスクリプトを見てもわかりません。
実は、BOLT仕様によって「時間切れになった場合のトランザクション」というものが決められています(2人の署名がいる)。
そして、HTLCを追加した後に署名交換を行いますが、そのときにHTLCの署名も交換するようになっています。

事前に署名をする以上、トランザクションの内容は仕様できっちり決められています。
そのため、Aさんは決められたトランザクション以外をブロックチェーンに展開することができません。

Aさんの時間切れになったときに取り戻すトランザクション(HTLC Timeout Transaction)は、このような形になりました。
(witnessは省略)

image

一番下の、locktimeに値が指定されているところに注目してください。

commitment transactionにもlocktimeは指定しますが、タイプは日時になっていて、それは既に過ぎ去った時間になっているためいつでも展開できますが、Timeout Transactionはブロック高になっています。

そのため、このトランザクションをブロックチェーンに展開するには、現在のブロック高がlocktime以上になるまで待たなくてはなりません(regtestなので、値は小さめになっています)。

Bさんの立場からすると、もしAさんがcommitment transactionをブロックチェーンに展開したとしても、送金をAさんが取り戻すまでにlocktimeまでの余裕があることになります。
その間にpayment_preimageを使って、下図の赤枠の経路を通って取り戻します。

image


Bさん:送金先(payee)

Bさんのcommitment transactionはこうなりました。

image

こちらも、真ん中のoutputがHTLCです。
なお、commitment transactionはBIP69に従ってソートします。

Bさんはお金を受け取る方なので、

  • payment_preimageを使ったトランザクションを期限までに展開する

という動作を行います。

payment_preimageを使って取り戻すトランザクション(HTLC Success Transaction)は、こうなりました。

image

構成はHTLC Timeout Transactionとほぼ同じで、違いはlocktimeの有無になります。
Success Transactionはlocktimeが0なので、payment_preimageを持っていればすぐに展開できます。

Aさんの立場からすると、もしBさんがcommitment transactionを展開したままpayment_preimageを使わずに放置したままになっていても、実はそれほど困りません。
それは、Aさんがpayerだからです。

しかし、Aさんが単に送金を中継している場合、それでは困ります。
Aさんが転送する元になった入金を手に入れるためには、payment_preimageが必要になるからです。

image

放置したままにならないよう、Bさんがcommitment transactionを展開した場合は、payment_preimageを持たなくても一定時間が経過したら取り戻せるようになっています。
それが、下図の赤枠で囲んだ命令です。

image

<cltv_expiry>というのはブロック高で、そのブロック高以上の時間になればその経路が有効になります。
Bさんにとってみれば、その経路をAさんが使う=自分の手に入れられない、ということになり、それまでの間にpayment_preimageを使ってしまおう、と考えることになります。


今回はトランザクションを含めて、Offered/Received HTLCの説明をしました。

今回の話が出てくるのは、HTLCを追加して、そのまま反映されずに残って、チャネルを閉じたくなった場合です。
通常は、HTLCを追加した後、すぐにHTLCを反映するので、commitment transactionにHTLCが残ったままになることはあまりないでしょうが、そういう場合も考慮されているということは知っておいてよいと思います。