LNのインバウンド流動性問題
LNでチャネルを新規に開設する場合、開設時は通常チャネル残高=自分の残高となる。これはチャネルを介して自分が支払うアウトバウンド流動性は保持しているけど、チャネルを介して支払いを受け取るインバウンド流動性はまったくない状態*1となる。
チャネル開設時に限定した話でもなく、資金の受け取りが主なユーザーにおいては、チャネル内の自分側の残高がいっぱいになれば、支払いを受け取ることができなくなってしまう。
そのため、チャネルのインバウンド流動性の管理は特に重要な問題となる。チャネルの流動性を管理しれくれるWoSのようなカストディアルウォレットを導入することで、これらの管理をアウトソースするという方法も選択肢の1つだけど、その場合代わりにサービスプロバイダーへのトラストが発生する。
SuperScalar
今回ZmnSCPxjが提案しているSuperScalar↓は、LSP(Lightning Service Provider)がユーザーとの間で、トラストレスかつ効率的に流動性の売買をできるようにするためのチャネルファクトリーの提案。
SuperScalar: Laddered Timeout-Tree-Structured Decker-Wattenhofer Factories - Protocol Design - Delving Bitcoin
この提案は、
という3つの要素で構成される。
Decker-Wattenhoferチャネルファクトリー
構成要素の1つがチャネルファクトリー↓
techmedia-think.hatenablog.com
チャネルファクトリーは、1つのオンチェーンUTXOで多数のLNチャネルをオフチェーン展開できるようにするスケーリングソリューションであり、またファクトリー内の複数のペイメントチャネル間のチャネルキャパシティの動的な調整を可能にする。
チャネルファクトリーの基本的な構造は、
- 多数のユーザーの資金を1つのUTXO(ファンディング・アウトポイント)にロックし*2、
- ファンディング・アウトポイントを全参加者のn-of-nアウトプットに送信するキックオフトランザクションを作成し、
- キックオフトランザクションをインプットとしたステートトランザクションを作成し*3、
- さらにステートトランザクション以下に、各参加者間でチャネルを構成するトランザクションが続く*4
チャネルファクトリーにおけるステートの更新は、チャネルの流動性を調整するタイミングで行われる。各ステートトランザクションのインプットのnSequenceには、相対的ロックタイムの値が設定されており、ステートを更新する度に、値がデクリメントされていく*5。これは、キックオフトランザクションがブロードキャストされた際に、最新のステートを一番早く承認させるため。このタイムロックにより古いステートを無効化する。
nSequenceの値が0になるとそれ以上更新できなくなるので、次は1つ上の階層のステートトランザクションのnSequenceをデクリメントとして、その子のnSequenceはリセットする。という作業を続け、一番上の階層まで使い終わったらファクトリーを一度閉じる必要がある。
このデクリメントによる状態更新の仕組みから、リーフのLNチャネル内では実質無制限の状態変更が可能だけど、チャネルファクトリーには状態変更の回数に上限がある。ステートトランザクションの階層を増やすことで上限を増やすことはできるけど、一方的なファクトリーの閉鎖が発生した場合に、ブロードキャストしなければならないトランザクション数が増えるというトレードオフが発生する。
ここでいうタイムアウトツリーは、LSPが複数のユーザー向けにライトニングチャネルを提供する際のトランザクションツリー。もともとOP_CTVを用いた提案だったけど、現状OP_CTVは導入されていないので、全参加者の署名による合意で代替するバージョンでタイムアウト署名ツリーと呼ばれてるっぽい。
LSP Lが8人のユーザーA〜Hにチャネルを提供する場合、以下のようなツリーを構成する:
リーフのトランザクションがLSPと各ユーザーとのLNチャネル。非リーフトランザクションの資金は以下の条件にロックされる:
- その階層の参加者+LSPのマルチシグ or
- CLTVによりタイムアウト後にLSPが単独で回収可能
ファクトリーを閉鎖する場合、
- 協力的に閉鎖する場合、ユーザーはツリー内のチャネルの資金をLN経由ですべて送信する(オンチェーン資金とスワップしたり、同じLSPの新しいタイムアウトツリーに移すのも可)
- ユーザーが一方的に退出する場合、ルートとなるファンディングトランザクションからリーフまでのトランザクションを公開し、LNチャネルは現状のLNと同様の方法で閉鎖する。
タイムアウトツリーを利用する利点は、単一のユーザーが退出した場合に他のユーザーは引き続きツリーに残ることができる。
理想的なケースでは、タイムアウトになるまでに全ユーザーがチャネルの資金を移動し、タイムアウト後にLSPがL&CLTV条件でファンディングのアウトプットを回収する。一部のユーザーが一方的に退出したとしても、ツリーの残りの資金は同様にタイムアウト後にL&CLTV条件で回収できる。
チャネルファトリーの状態更新の数は相対時間によるタイムロック(CSV)により制御される一方、タイムアウトツリーの方は絶対時間によるタイムロック(CLTV)なので、予め有効期限が決まっている。
SuperScalarでは、↑のチャネルファクトリーとタイムアウトツリーを組み合わせる。A〜Hのユーザーを持つLSPは以下のようなツリー構造となる。
ステートの更新の仕組みにチャネルファトリーの特性を利用し、CLTVによる指定ブロックにおけるタイムアウトと効率的な退出にタイムアウトツリーの特性を利用する感じ。
上記の構成で、LSPがユーザーAに流動性を提供する場合、ツリーの一番上のA&L、B&L、Lのみのアウトプットを持つステートトランザクション↓
を更新する必要がある。この場合、更新にあたってオンラインになる必要があるのは、A、B、Lの三者のみ。流動性の提供をトリガーするAとLは基本的にオンラインになっているはずなので、あとはBがオンラインになるだけ。
- Bがオンラインになれば、オフチェーンでA&Lのチャネルに資金移動できる。
- Bがオンラインにならない場合は、LSPはオンチェーンなどの代替方法にフォールバックする必要があり、その場合のオンチェーン手数料はおそらくAに転嫁される。
Aへの流動性提供に直接関係のないBがオンラインになって協力するインセンティブとして、Bに少額のインバウンド流動性を提供するといったことが考えられてる模様。
もし、ステートトランザクションのLの資金が枯渇してしまった場合や、ステートトランザクションをこれ以上更新できなくなった場合(nSequneceを0までデクリメントした状態)は、別のステートトランザクションのLの資金を移動する必要がある。これは、1つ上の層のステートトランザクションを更新することを意味し、その場合、オンラインになる必要のあるユーザーが増える。Aに資金提供するケースだと、A&B&C&D&Lに資金がロックされているステートトランザクションを更新する必要があるので、オンラインなる必要があるのは、そのメンバー。
ファクトリーからの退出
各ユーザーはLSPをトラストする必要はないので、どのユーザーもLSPと協力することなく一方的に退出することができる。Aが一方的にファクトリーおよびLNチャネルから退出する場合、Aはツリー上のファンディングアウトプットから、A&Lチャネルまでのトランザクションをそれぞれブロードキャストする必要がある。今回の例では、最初のキックオフトランザクションからリーフのステートトランザクションまで合計4つのトランザクションをブロードキャストする。ステートトランザクションについては、最新の状態のもの。最後にA&LのLNチャネルを、これまでのLNの仕組みと同様にクローズする必要がある。
ただ、Aが一方的に退出すると、同じトランザクション内にチャネルを持つBと、さらにCとDは、これ以上LSPからオフチェーンで安価に流動性の提供を受けること(ステートトランザクションを更新すること)ができなくなる。CとDも影響を受けるのは、↓のキックオフトランザクションがオンチェーン上で承認されるため(CSVタイマーが起動し、最新のステートトランザクションをブロードキャストする必要がでてくる)。
B、C、Dについては、流動性の提供はできなくなるが引き続き各LNチャネルはそのまま利用できる。オフチェーンで流動性の購入ができなくなる分、必要な場合はオンチェーンスプライシングなど、オンチェーン手数料分コスト高になる。
E〜Hについては、キックオフトランザクションはまだ公開されていないので、引き続きオフチェーンで流動性の調整が可能。
全ユーザーが協調的に退出する場合は、上記のタイムアウトツリーで説明したように、各チャネルの資金を別のLNチャネルなどに移動したり、新しいファクトリーに移動する(後述)。
↑の例ではリーフトランザクションのチャネルの数は2つとしているけど、この数(arity)自体は任意に構成することができる。数が増えるとツリーの高さが抑えられ、
- 一方的な退出時のオンチェーントランザクションの数を削減でき
- トランザクション数が削減できるほど、資金を回収するまでのnSequenceによる相対的タイムロックの遅延が短くなる
- LNチャネルのHTLCのCLTVデルタは、この相対的タイムロックの累計最大値を加味する必要がある。
- 一方、流動性の調整時にオンラインになる必要のあるユーザー数が増える
というトレードオフがあり、arityの数や(地理的、稼働率などによる)ユーザーの配置については工夫の余地がある。
ラダー化
ラダー化というのは、技術的な話ではなく、金融商品の取り扱い方法の一種。定期預金のように、契約により一定期間資金を預け、満期になると元本に加えて利息を受け取るような場合、長期間資金がロックされるため資金運用の柔軟性という面ではデメリットがある。そこで、投資可能な金額を、終了日がそれぞれ異なる(1ヶ月おき、1年おきなど)複数の契約に分割することで資金運用の柔軟性を向上させる手法のことをラダー化と呼ぶ。
SuperScalarでは、LSPが有効期限の異なる複数のタイムアウトツリー構造のチャネルファクトリーを作成することで、LSPの資金運用の柔軟性を持たせようとしている。
LSPは、あるファクトリーのタイムアウト期限が来ると、新しいタイムアウトを設定したファクトリーを開始し、古いファクトリーから新しいファクトリーへの資金の提供を各ユーザーに依頼することができる。すべてのユーザーがオンラインになって新しいファクトリーに移動できたら、LSPはツリーの先端のキックオフトランザクションのL&CLTVの条件を使って資金を回収するトランザクションをブロードキャストする。一部のユーザーが応答ない場合でも、配下のユーザーがすべて応答したキックオフトランザクションについてはL&CLTV条件によって資金を回収できる。理想的なケースであれば、キックオフトランザクションとそれを回収するトランザクションの2つのオンチェーントランザクションのみでファクトリーを閉鎖することができる。
新旧のファクトリー間の移動については、OP_CTVがないので、各ユーザーとLSPが特定の期間内にオンラインになり協力する必要がある。
というのがSuperScalarスキームの概要。SuperScalarという名称は、プロセッサのアーキテクチャから来てる?ラダー化して複数のチャネルファクトリー運用する点が似てるとか。