Develop with pleasure!

福岡でCloudとかBlockchainとか。

Watchtowerと連携したLightning Networkウォレットのバックアッププロトコル「Açai」

Scaling Bitcoin 2019復習シリーズ第一弾は、「Açai: a backup protocol for Lightning Network wallets」

通常のオンチェーン決済をするウォレットであれば、BIP-32やBIP-39などの技術を使って、ニーモニックワードさえ記録しておけば、そこからマスターシードを復元し、ウォレット内の取引で使用する秘密鍵を復元することができるが、LNのようなオフチェーン決済では、このような事が難しく、ウォレットの障害などでデータが破損、欠落してしまうとLNのチャネル内の資金を失う可能性がある。このような問題に対処するためのLNウォレットのバックアッププロトコルの提案が↑の内容。

Watchtower

バックアッププロトコルに関連するプロダクトの1つがWatchtower。

LNを利用した支払いでは、取引相手が不正をした場合(相手に有利な古い状態のチャネルをオンチェーンのブロードキャストするなど)、不正をした相手の資金を含むチャネルの全資金をペナルティとして没収するトランザクション(Justice Tx)をオンチェーンにブロードキャストすることで対抗する。ただ、これを正しく実行するためには常にオンチェーンの状態を監視しておく必要があるが、スマートフォンなど常にオンラインにあるか分からないようなデヴァイスにとっては難しいこともある。そこで監視とJustice Txのブロードキャストをアウトソースするための仕組みがWatchtowerだ。

Watchtowerの仕組み

アリスがボブとチャネルを開いいる場合、Watchtowerは以下のように動作する。

アリスはボブとのチャネルのコミットメントが更新される度に、最新のチャネル状態をWatchtowerに通知する。具体的には、以下のようにHintとBlobをWatchtowerに送信する。

  1. アリスとボブ間のチャネル状態を変更(新しいコミットメントに署名)
  2. アリスは新しいコミットメントTxのtxidの先頭16バイトをHintとする。
  3. アリスはtxidの後半16バイトを共通鍵としてコミットメント自体も暗号化したBlobを作成する。
  4. アリスはHintとBlobをWatchtowerに送信する。

ボブがアリスを裏切って古い状態のコミットメントをブロードキャストすると、

  1. Watchtowerはアリスから送られてきたHintとメモリプール内のトランザクションのtxidの先頭16バイトを比較し、合致するトランザクションが無いかチェックする。
  2. 合致するトランザクションがあれば、そのtxidがHintと一緒に送られてきたBlobを復号するための鍵になるので、その鍵を使ってBlobを復号する。
  3. WatchtowerはそのBlobのデータを使ってJustice Txを完成させ、ブロードキャストする。

という手順で監視およびJustice Txのブロードキャストをする。

※ Watchtowerに関しては、インセンティブの問題や、いつまでHintやBlobを保持するのか?、ちゃんとJustice Txをブロードキャストされるか?、プライバシーなど課題もまだあり、さまざまな提案が出ている。

Açaiプロトコル

識別子 Açaiプロトコルでは、Watchtowerをチャネルの監視だけでなく、バックアップサービスとして利用するプロトコルで以下の機能がベースになっている。

  • Watchtower
  • Eltoo
  • BIP-32, 44, 39

そしてWatchtowerののtxid、Hint、Blobの仕組みをバックアップの仕組みでも同様に使用する(監視とAçaiによるバックアップの仕組みを区別するのにAçaiバックアップに使用する際の表記をtxidç, Hintç, Blobçと表記する)。

Watchtowerへのバックアップの送信

チャネルを更新する都度、アリスは新しいチャネル情報(従来のHintとBlob)と新しいバックアップ( Hintçと Blobç)をWatchtowerに送信する。

  1. blobçを復号化したり、識別に使用するtxidçを生成するため*1、その準備としてまずアリスは現在のブロック高を導出変数として利用しBIP-44ベースで公開鍵を生成する(公開鍵= m’/108’/0(mainnet)/(アカウント番号)’/0/現在のブロック高)。108'はBIP-44の任意のpurpose番号で、アカウント番号は使用しているウォレットアカウントの番号。
  2. 続いて算出した公開鍵を使ってtxidçnを計算する。アリスは同じブロック高で多くの支払いを実行する可能性があるので、同じブロック高において新しいAçaiバックアップの状態:txidç_0, txidç_1, txidç_2, txidç_3を列挙する必要がある。同じブロック高ではその識別ができないので、同じブロック高内で行われた変更は、前のtxidçの値をハッシュした値として計算する。つまり、txidçnは前のtxidç_n-1のハッシュ値として計算される。3回支払いしているケースでは、txidç_1= SHA256(txidç_0)txidç_2= SHA256(txidç_1)txidç_3= SHA256(txidç_2)のようになる。
  3. txidç_nの前半16バイトをヒントHintç_n= txidç_n[:16]とし、後半16バイトを使ってBlobを暗号化するencrypt Blobç_n= Enc(dataç_n,txidç_n[16:])。ここで暗号化する対象のデータdataç_nはアリスが持つ全チャネルの最新のコミットメントTxのTXIDのリストだ。
  4. 新しいチャネル状態と一緒にバックアップ情報としてHintçnとBlobçnをWatchtowerに送信する。

ポイント

上記のように、ブロック高を変数に鍵導出した公開鍵からtxidçを計算し、その先頭16バイトをユーザーがWatchtowerへ問い合わせする際の識別子(Hintç)として使用し、後半16バイトをBlobçを暗号化/復号化する際の共通鍵として使用する。

Watchtowerへのバックアップの要求

アリスは誤ってデータを失った場合、Watchtowerに対してバックアップを要求できる。また実際にデータを失っていない場合も、Watchtowerにバックアップを要求することで、Watchtowerがちゃんと約束したサービスを提供しているか確認できる。

  1. アリスはノードに現在のブロック高を確認する。
  2. ブロック高とシードを使って決定論的に公開鍵を計算する。 address= m/108’/0(mainnet)’/(アカウント番号’)/0/現在のブロック高
  3. 公開鍵を使ってtxidç_0 = 2SHA256(公開鍵)を計算し、その先頭16バイトをヒントhintç_0=txidç_0[:16]とする。
  4. Watchtowerに対してhintç_0を問い合わせる。
    • Watchtowerがhintç0を知っている場合、同じブロック内に複数のトランザクションがある場合はhintç1も含まれるので、アリスのウォレットはtxidç_1= SHA256(txidç_0)を計算し、Watchtowerにhintç1が含まれるか尋ねる。Watchtowerがhintç1を知っていればさらにtxidç2の計算hintç2の確認と繰り返す。Watchtowerがhintç2を知らない場合、txidç1に最新のチャネル情報が含まれていると想定できるので、アリスはblolbç_1を復号しtxidのリストを抽出する。
    • Watchtowerがhintç_0を知らない場合、アリスには現在のブロック高でのトランザクションは存在しないと想定できるので、ブロック高をデクリメントして新しい公開鍵を公開鍵= m/108’/0(mainnet)’/(アカウント番号)’/0/(現在のブロック高 - 1)を計算する。計算した公開鍵に対して再度ヒントを計算し、上記のチェックを行う。
  5. アリスのウォレットがhintçnを見つけたら、Watchtowerに対して、対応するBlobçnを送るよう要求する。Blobç_nはdataçとtxidç[:16]で構成され、dataç= [アリスが開いているチャネルの最新の状態のtxidのリスト(ボブとそれ以外ともチャネルを開いている場合、その最新のtxidのリスト)]
  6. アリスはdataçからボブとのチャネルの最新のtxid_Blobを復元できる。その値を使って、Hint_Bob = txid_Blobの先頭16バイトを計算し、対応するblob_BlobをWatchtowerに問い合わせる。アリスはtxid_Blobの後半16バイトを使ってblob_Blobのデータを復号し、ボブとのチャネルを復元することができる。
  7. この時点でアリスは自分のデータがWatchtowerに保存されているものと一致するかチェックしたり、データを復元することができる。

ポイント

上記のように、現在のブロック高からバックアップに使用した公開鍵を計算し、そのHintçをWatchtowerに照会し、見つかるまでブロック高をデクリメントしながら繰り返し、最新のバックアップを見つける。最新のバックアップには、アリスの全チャネルの最新のコミットメントTxのTXIDのリストが含まれているので、今度はこのTXIDの先頭16バイトをHintとしてWatchtowerにチャネル状態を問い合わせ、対応するBlobを取得し、TXIDの後半16バイトを使ってそのBlobを復号する。基本的にEltooであれば最新のコミットメントTxが復元できればいいので、復号化したBlobから最新のコミットメントTxを復元できればいい。

Açaiプロトコルの前提条件

  • LNウォレットがWatchtowerとデータ交換する機能がWatchtower側に実装されていること。
  • Watchtowerにはサービスのための追加のストレージや帯域幅を考慮し、経済的に実行可能なトラストレスは支払いの形態が必要であること。
  • Watchtowerに保存されるAçaiデータは削除されたり、置換/改竄されることが無いこと。
  • Açaiプロトコルを使用するユーザーはどのWatchtowerを使用したか分かっていること。

所感

既存のWatchtowerの監視とJustice Txの保持の仕組みと上手く連携して、鍵導出の仕組みを組み合わせた興味深いバックアッププロトコル。まだインセンティブやデータの保持期間など課題はまだあるけど。ちなみにAçaiは植物のアサイーからの名付けとのこと。

*1:txidçと書いてるけどバックアップに用いるtxidçの実体はトランザクションの識別子ではなく、これから計算する公開鍵を使った識別子でしかない