用語集 / ライトニングとレイヤー2
CLTV有効期限デルタ
- CLTV有効期限デルタとは?
- CLTV有効期限デルタとは、ライトニングのノードが受信した支払いのタイムロックから差し引いて次のホップへ渡すブロック数のことで、gossipでチャネルの方向ごとに通知されます。
ライトニングのルート上で転送を行う各ノードは、ミリサトシ単位の手数料とブロック単位の遅延という2つの対価を課し、CLTV有効期限デルタはこの遅延にあたります。BOLT 7では、channel_updateメッセージ内の16ビットのフィールドとしてfee_base_msatと並んで格納され、チャネルの各側がそれぞれ独立に自身の値を公開します。支払いが滞留すると、この積み上がったブロック数が、資金が凍結される時間になります。
仕組み
CLTV有効期限デルタは、転送を行うノード自身が選択するものであり、そのノードの送出方向にのみ適用されます。
仕様の文言は正確です。ノードは、受信したHTLCのcltv_expiryから差し引くブロック数をこのフィールドに設定しなければなりません。つまり、デルタは期限ではなく、差分です。ノードは、ある絶対ブロック高までロックされた支払いを受け入れ、デルタを自分の取り分として保持し、次のホップにはその高さからデルタを引いた高さまでロックされた支払いを提示します。この差分がノードの安全余裕です。下流のホップが最後の瞬間に決済したとしても、上流で請求できるブロックがその分だけ残ります。
公開チャネルはそれぞれ、方向ごとに1つずつ、合計2つのこの数値を保持し、それぞれを設定したノードが署名します。これらはchannel_update、メッセージタイプ258に、htlc_minimum_msatと2つの手数料フィールドと並んで格納されます。重要なのは、転送を行うノードが通知した更新だけです。AからB、BからC、CからDというルートでは、支払者はBからCにはBの更新を、CからDにはCの更新を使い、自身の更新は使いません。
したがって、ルートは後ろ向きに構築されます。支払者は宛先から始め、インボイスが要求する最小の最終有効期限を取り、各ホップの通知されたデルタを遡りながら加算していきます。その累計が、最初のピアに渡すHTLCのタイムロックになります。ノードが対価を改定するとき、BOLT 7は、gossipがすべての支払者に一斉に届くわけではないため、10分間は以前のパラメータを受け入れ続けるよう求めています。
どこで目にするか
CLTV有効期限デルタは、滞留したライトニングの支払いが残高を拘束する時間を決めます。BOLT 7自身のルーティング例では、それ以外は同一の2つのルートに数値が示されています。
4つのノードが菱形に配置されています。A、B、C、Dがそれぞれ10、20、30、40ブロックを通知し、Cは18の最終有効期限デルタを要求しており、仕様はこれをデフォルトと呼んでいます。AはCへ4,999,999ミリサトシを送ります。B経由でルーティングする場合、Aはピアに5,010,198ミリサトシを渡し、そのうち10,199がBの手数料であり、最初のHTLCは現在のブロック高に80を加えた高さで失効します。Bのホップに20ブロック、Cに18、さらに余裕として42ブロックです。D経由でルーティングする場合、同じ支払いは5,020,398ミリサトシかかり、現在の高さに100を加えた高さで失効します。送信者も受信者も金額も同じで、リスクにさらされるブロック数が20ブロック多くなります。
この42は恣意的な余裕ではありません。BOLT 7は、デルタを正直に合計して構築したルートでは、中間ノードが自身の位置を割り出し、そこから誰が支払われているかを推測できると警告しており、支払者にはランダムなオフセットを加えることが推奨されています。これは受信者からグラフを外側へたどり、出会ったデルタを合計することで求めます。仕様はその結果をshadow route extension(シャドウルート拡張)と呼んでいます。
転送ノードを運用していない限り、ここで設定するのはあなたではありません。当サイトのレビューが携帯端末上の真に自立したライトニングノードと評するPhoenixは、その送信価格を0.4%に4satを加えた額として公開しており、その表はブロックではなく資金に値付けしています。
CLTV有効期限デルタvs OP_CHECKLOCKTIMEVERIFY
CLTV有効期限デルタはgossipで公開されるルーティングポリシーの数値であり、OP_CHECKLOCKTIMEVERIFYはオンチェーンで絶対的な期限を強制するビットコインスクリプトのオペコードです。
共通するのは3文字だけで、それ以外はほとんどありません。デルタは相対的で、完全にオフチェーンに存在します。どのスクリプトにも現れず、フルノードが検証することもなく、設定したノードが新しいchannel_updateで改定します。OP_CHECKLOCKTIMEVERIFYはコインに書き込まれ、すべてのフルノードが検証し、コインが存在した後は編集できません。