Bitcoin
LightningNetwork

BOLTのこと 2(2017/12月中旬)

BOLTのこと(その2)

はじめに

株式会社Nayutaのuenoです。
今日のAdvent Calendarでは、前回に引き続き、BOLT概要を書いていきます。
(細かい内容は弊社ブログに連載しています。)

チャネルを開く

チャネルを作成するまでにいくつかBOLTメッセージ交換する。
その中で、このチャネルで使用する鍵の情報や、いくら課金するか(Bitcoinでは2^24 satoshis未満=167mBTC程度が上限)、などを伝える。

課金はチャネルを開きたい方だけが行うようになっていて、そのトランザクションはfunding transactionと呼ばれている。
funding transactionがチャネルを開かれる方が指定するconfirmation数以上経過すると、最後にメッセージを交換してチャネルが開かれたことになる。

ただ、この時点では相手とのチャネルが開かれただけで、そのチャネルの情報を他のノードに通知するかどうかは別である。
ノードがチャネル情報を展開するかどうか決められて、双方の合意がないと展開できない(チャネルの情報を展開するメッセージに両ノードの署名を行うため)。
また、6confirmation以上経過していないと展開しない取り決めになっている。

送金

送金は、大きく3段階ある。

  • 請求書の発行(送金先ノード→送金元ノード)
  • 送金情報の転送(送金元ノード→中継ノード→送金先ノード)
  • 送金の反映(送金先ノード→中継ノード→送金元ノード)

請求書(invoice)の体裁はBOLT11に書かれているが、情報としてほしいのは payment_hash という32byteの値である。
これは、送金先だけが持つ payment_preimage という32byteのデータをSHA256でハッシュ化したもので、BOLTのメッセージ中では持ち主確認に使うし、途中でチャネルを閉じるときのスクリプトで使うことにもなる。

「送金情報の転送」では payment_preimage をBOLTメッセージで転送し、「送金の反映」のときに payment_preimage を送り返す。
受け取った payment_preimage のハッシュ値が payment_hash と一致したら送金情報を持ち分として反映させ、1st Layerに戻すためのcommitment transactionも更新する(このときに、前のcommitment transactionの情報も渡す)。

中継の人が payment_preimage を受け取るだけで前の人に戻さなかったとしても、その送金を使いたければ payment_preimage を使ったスクリプトをブロックチェーンに展開する必要があるため、funding transactionを監視していればわかる。
また、使わないままにしていても、期限が切れてしまえば「払い損」になってしまう(そうなるように、期限は送金先から順に長くなるように指定する仕様)。
そういった「普通にやらないと損をする」という状況を仕様で作り上げている。

送金元が送金先までの経路や、途中のノードが相手にいくら転送するかも含めて決定する。
直接相手ノードに送金するだけであれば手数料はかからないが、転送するだけのノードは手数料を請求することができる。

チャネルを閉じる

正常

一番きれいに閉じるのは、BOLTメッセージで閉じるときの手順を踏む場合である(Mutual Close)。
そうすると、待ち時間もなく指定したアドレスに送金される。

準正常

準正常的な閉じ方は、最新のcommitment transactionをブロックチェーンに展開することである(Unilateral Close)。
commitment transactionのinputはfunding_transactionで、outputは大きく4種類ある(4つ、ではない)。

HTLC関係のものは「outputs」と複数形になっていて、これは送金途中で反映が完了していないものの分だけ存在することになる。
to_remote以外はスクリプトになっているため、取り戻すためにunlocking scriptを書かなくてはならない。
通常のwalletはそこまで管理できないので、BOLTアプリが対応することになるだろう。

反則

commitment transactionはfunding transactionをinputとしているだけなので、funding transactionが未使用であればいつでもブロックチェーンに展開できる。
また、何度か送金を行っているとcommitment transactionもそのたびに作り直すことになるが、そのいずれもブロックチェーンに展開できるという意味では有効である。
よって、最新ではないcommitment transactionをブロックチェーンに展開してチャネルを閉じることもできる(Revoked Transaction Close)。

展開すると、まずto_remote outputは相手側が即座に使用できるようになる。
to_local outputは、相手がChannel Establishment時に指定したブロック数以上待たないと自分が使用できない。
また、Offered HTLC outputsとReceived HTLC outputsは、各送金で指定した期限が過ぎるか payment_preimage を入手した後でトランザクションを展開し、そのトランザクションを展開してから相手がChannel Establishment時に指定したブロック数以上待たないと自分が使用できない(期限は絶対ブロック数で、使用できるまでは展開してからの相対ブロック数になる)。

その時間になる前に、相手はトランザクションを監視して、取り戻すことができる。
(もし放置していれば、反則した人が受けとれるようになる。)
そのため、面倒ではあるが、funding transactionの監視と、それが使用された場合の追跡をし続けなくてはならない。

おわりに

長くなりましたが、2017年12月現在のBOLTのことを2回にわたって説明しました。
文字だけだと非常に分かりづらいだろうと思いますが、実際に使ってみないとイメージが付きにくいと思いますが、まだ開発者じゃないと使うのは難しいだろうと思います。

が、もうすぐv1.0になるでしょうから、そろそろ使うための環境も作られていくと思います。
たとえば、ACINQのLightning Network Explorer(TESTNET)は、ブラウザでBOLTのノードが検索できるようになっています(動かなくなったノードも残っていますが)。
こういった仕様や環境が整ってユーザが増えると、今まで気付かなかったことが見えてくるのではないでしょうか。
楽しみですね。