Develop with pleasure!

福岡でCloudとかBlockchainとか。

Grinでオフチェーン決済するためのPayment Channelプロトコル「Elder Channel」

Mimblewimbleを実装したGrinにはBitcoinのようなスクリプト機能は存在しない。コインの所有権は、秘密鍵の役割をするPedersen CommitmentのBlinding Factorの値を知っているかどうかで、UTXOを使用する際はその値を使った電子署名が求められる。Mimblewimble/Grinにおけるコインとその使用方法については、以前GBECで解説動画を作ったので↓参照。

goblockchain.network

そんなスクリプト機能の無いGrinでオフチェーン決済をするためのPayment Channelプロトコルが今回提案されているElder Channel↓

https://gist.github.com/antiochp/e54fece52dc408d738bf434a14680988

Payment Channelを構成するのに必要な要素は、主に2つ↓

  • マルチシグ
  • チャネルの旧状態のトランザクションがブロードキャストされた際の対処方法

Grinの場合これをスクリプトレスで実現する必要がある。この内、マルチシグについては、Schnorr署名の公開鍵の集約特性を利用して実現できる。詳細は↓

techmedia-think.hatenablog.com

そして、旧状態のトランザクションがブロードキャストへの対処は相対的なタイムロックの仕組み(↑で解説)と、MimblewimbleならではのPedersen Commitmentの特性を利用する。現在のLightning Network(Joseph Poon & Tadge Dryjaモデル)は、旧状態をブロードキャストした場合、不正をしたユーザーが資金を全て没収されるペナルティモデルを採用しているが、Elder Channelは最新の状態を適用させるeltooモデルに近い。

Elder Channelのプロトコルは以下のようになる。

チャネルのセットアップ

アリスとボブはそれぞれ自身が所有するコミットメントを持ち寄り、それをマルチシグのコミットメントにロックするFunding Txを作成する。

この時、相手が応答不能になって資金を取り戻せないといった状況が起きないように、Close TxとSettle Txをそれぞれ作成する。

  • Close TxのインプットはFunding Txのマルチシグアウトプットで、アウトプットは、同額をそのまま持つマルチシグのコミットメント。
  • Settle TxのインプットはClose Txのマルチシグアウトプットで、アウトプットはその時のアリスとボブの残高を表す2つのコミットメント。

そして、Settle Txのカーネルにだけ、相対的なタイムロックが設定される。これはSettle TxのインプットであるClose Txがブロックに承認されて1440ブロック経過するまでSettle Txをブロードキャストできないという相対的なものだ。

それぞれ作成したClose TxとSettle Txに署名したら、Funding Txに署名しブロードキャストする。Funding Txが承認されるとチャネルがオープンする。

この時、Close Txのみがブロードキャストされた状態のまま資金がロックされることが内容、お互い相手のSettle Txを持つ。

チャネルの更新

オフチェーンで決済する際はチャネルを更新する。チャネルの更新は新しいClose TxとSettle Txを作成することを意味し、送金額に応じて新しいSettle Txの各自の残高を調整する。

そして、ここで不正対策を行う。古い状態のCloset TxやSettle Txがブロードキャストされるとコインが盗まれてはまずいので、お互いにRevoke Txというのを作る。このRevoke Txは前の状態のClose Txのアウトプットをインプットとし、そのアウトプットはチャネルの実体であるFunding Txのコミットメントと同じ値を再利用する。

こうすることで、古い状態のClose Txがブロードキャストされると、Settle Txのタイムアウトの期間内に、Revoke Txをブロードキャストすることで、古いClose Txの効果を取り消す。そして、最新のClose Txをブロードキャストし、その後タイムロックの期間を待って、Settle Txでチャネルをクローズする。最新の状態にはRevoke Txは存在しないので、最新のClose Txが取り消されることはない。

この仕組みにより、不正が行われた場合にそれを取り消しチャネルの最新残高の反映を可能にする。

チャネルのクローズ

最新のClose Tx、Settle Txをブロードキャストする以外に、両者が協力してチャネルを閉じるMut Txを作成する。このトランザクションのインプットはFunding Txのアウトプットで、アウトプットはそれぞれの最新のチャネル残高を反映したコミットメントになる。

大まかに↑のフローを図にすると以下のようになる。

f:id:techmedia-think:20190531184809j:plain
Elder Channelの構築フロー

注意点

トランザクションカットスルー

個々のRevoke Txが分かると、永遠にClose & Revokeを繰り返し資金をロックする攻撃が可能になるので、Revoke Txとその後の最新のClose Txは個別にブロードキャストするのではなく、トランザクションカットスルーをして1つのトランザクションにしてブロードキャストする必要がある。カットスルーする分、承認時間も短縮され手数料も安くなる。

手数料

手数料について↑では触れてないが、それぞれトランザクションをブロードキャストする際に、手数料用のトランザクションと集約してブロードキャストする必要がある。

コミットメントの重複

あと1番大事なのが、一見これで正常に動作するように思えるが、Elder Chanelは各UTXO=コミットメントの重複(同じコミットメントの値の再利用)を許可することが前提となっている。これは現在のGrin/Mimblewimbleの設計には当てはまらないので、改修が必要になる。

所感

Mimblewimbleプロトコルを採用したペイメントチャネルのプロトコルということで結構面白い。キーになってるのはRevoke Txでコインをチャネルに送り返せば元々作ってたClose Txが再利用できるという点。これはUTXOが単純なPedersen Commitmentでその特徴を上手く利用してると思う(よく思いつくなー)。

後は、LNにするにあたってHTLCとかルーティングとかの課題が残る。特に金額がコミットメントによって秘匿されている状態でルーティングどうするのか気になるところ。