Develop with pleasure!

福岡でCloudとかBlockchainとか。

Bitcoinのトランザクション伝播時の匿名性を強化するDandelionについて定義したBIP-156

Bitcoin Coreなどのノードがトランザクションをリレーする際、ノードは接続中のピアに対して一斉にトランザクションを送信する訳ではなく、接続中の各ピア毎に指数関数的な遅延時間をもって各ピアにトランザクションを送信するようになっている。これによりトランザクションを作成したノードを判定しにくくし、プライバシーを向上させるのが狙いだ。

ただBitcoinネットワークのノード数は10,000ノードくらいなので、安価に大量のスパイノードを配置して、送信されるトランザクションメッセージの対称性を観測することで、トランザクションをブロードキャストしたソースノードを推論することができるとして、もっとプライバシーを向上させようと、新しくDandelionというトランザクション伝播プロトコルがBIP-156提案された↓

https://github.com/bitcoin/bips/blob/master/bip-0156.mediawiki

なお、Bitcoin CoreではDandelionの採用とは別に、各ネットワークブロック(IPブロック)毎にランダムな遅延時間を設定することで、分析コストを上げてよりプライバシーを向上させようという提案がマージされ↓、0.17.0で導入される見込みなので、CoreでDandelionが採用されるかどうかは未定。

github.com

具体的なDandelionのBIPの仕様について見てみる↓

概要

Bitcoinのトランザクション拡散プロトコルは、匿名性を奪う攻撃に対して脆弱だ。Dandelionはこれらの攻撃に対して正式な匿名性保証を提供するトランザクションルーティングメカニズムだ。Dandelionを使わずにノードがトランザクションを生成すると、ノードは接指数関数的な遅延をさせつつ接続中のピアに個別にトランザクションを送信する。Diffusionとして知られるこのアプローチは、ネットワーク内の敵対者がトランザクションIPアドレスにリンクすることを可能にする。

Dandelionは拡散前にランダムに選択されたパスを介してトランザクションを送信することで、この種の攻撃を緩和する。トランザクションは「stemフェーズ」中にこのパスに沿って移動し、その後の「fluffフェーズ」で拡散される(stem=幹、fluff=綿毛なのでDandelion=たんぽぽ)。このルーティング・プロトコルは追加の暗号メカニズムを導入することなく、最適な匿名性保証を提供する。

動機

Bitcoinのトランザクション拡散は、匿名性を奪う攻撃に対して脆弱だ。トランザクションはピア毎に個別に指数関数的な遅延をもって送信されるため、メッセージは統計的に対称な方法でネットワーク全体に広がる。このパターンはスパイノードと結託してトランザクションソースを推論することを可能にする。この対称性を破ることで攻撃を防ぐ。しかし、我々は対称性の破壊が適切に行われない場合、ネットワークトポロジーの知識を持つ敵がより効果的な指紋攻撃を開始できることが分かった。

P2Pグラフにアクセスできるボットネット型の敵を考えてみよう。BitcoinのP2Pネットワークに匹敵するサイズのボットネットは一般的に安価で、これらの敵はプローブメッセージでネットワーク構造を知ることができる。このような敵は、各ノード毎に10以下のトランザクションを観察した後、ネットワーク全体の完全な非匿名化を達成できることが分かった。

Dandelionは、Bitcoinネットワークの正式な匿名性の保証を提供する実用的で軽量なプライバシーソリューションだ。他のプライバシーソリューションは個々のユーザーを保護することを目的としているが、Dandelionは敵対者がネットワーク全体を非匿名化することを制限することで、匿名性を保護する。

Dandelionはどのように動作するのか?

Dandelionはトランザクションをネットワークに拡散する前に、「anonymityフェーズ」を介してトランザクションを送信することでユーザーのプライバシーを強化する。高レベルでは、

  • 拡散の対称性の破壊
  • 同じパスに沿って異なるソースからのメッセージを転送することによりトランザクションをミキシング

することで、プライバシーを強化する。

Dandelionのルーティングは3つのフェーズで概念化される。最初にプライバシーグラフが構築される。実際に、このプライバシーグラフは完全に分散された方法で構築され、既存のBitcoinのP2Pネットワークのサブグラフになる。次に、stemフェーズ中にこのプライバシーグラフに沿ってトランザクションが転送される。最後にメッセージはfluffフェーズで、拡散の典型的な方法でネットワークにブロードキャストされる。

https://github.com/bitcoin/bips/raw/master/bip-0156/1-dandelion.png

分散型でプライバシーグラフを選択するために、各ノードはそのアウトバウンドピアのサブセットをDandelionの宛先に選択する。インバウンドの接続を介してこのノードに届くDandelionトランザクション(stemフェーズ中のトランザクション)は、これらDandelionの宛先に転送される。

理想的な設定では、ハミルトン閉路がほぼ最適なプライバシー保証を提供することが分かった。しかし分散型のBitcoinのP2Pネットワークを介してトラストレスな方法でハミルトン閉路を構築するのは不可能だ。そのため、各ノードはアウトバウンドピアのリストから置換することなく、ランダムに一様に2つのDandelionの宛先を選択することを推奨する。我々のテストでは、この方法が堅牢性の向上と同等のプライバシーを提供することが分かった。

stemフェーズのルーティングの際、プライバシーを保護するためにどのようにルーティングするかという問題がある。例えば2つのDandelionトランザクションが異なるインバウンドピアからノードに届いた場合、どのDandelionの宛先にこれらのトランザクションを送信すべきだろうか?我々はいくつかの選択肢が他の選択肢よりずっと優れていることに気づいた。

各Dandelionのトランザクションが、ランダムに一様に選択されたDandelionの宛先に転送される場合を考えてみよう。このアプローチの結果、指紋攻撃が発生し、ネットワークレベルのボットネット攻撃者がノードあたり10件未満のトランザクションを観察した後、P2Pネットワークの完全な非匿名化を達成できるようになる。

https://github.com/bitcoin/bips/raw/master/bip-0156/2-attack.png

指紋攻撃の間に、グラフ構造の知識を持つボットネット形式の敵対者は最初にトランザクションの伝搬をシミュレートする。このオフラインステップにより、敵対者は各ネットワークノードの指紋を生成することができる。オンライン攻撃中、敵対者はスパイノードでトランザクションを収集し、これらの観測結果をシミュレートした指紋と一致させる。我々のシミュレーションでは、この攻撃がネットワーク全体の匿名化を壊滅させると示されている。

https://github.com/bitcoin/bips/raw/master/bip-0156/3-attack-plot.png

この問題を回避するには、インバウンドエッジ毎のルーティングを推奨する。各インバウンドピアには、特定のDandelionの宛先が割り当てられる。このピアを介して届いたDandelionトランザクションは同じDandelionの宛先に転送される。インバウンドエッジ毎のルーティングは攻撃者が有用な指紋を構築する能力をブロックすることで、攻撃を破る。指紋はルーティングの決定が各ノードでトランザクション毎に独立して行われる際に発生する。この場合、同じノードからの2つのトランザクションは通常ネットワークの異なる経路をとる。重要なのは、指紋と一致するような複数、単一のデータポイントが得られることだ。

Dandelionでは、同じノードからの2つのトランザクションは同じネットワーク経路を取るようにし、Figure 3の左端に敵対者を限定する。言い換えると、敵対者の知識は、複数のトランザクション経路の豊富なプロファイルではなく、1つの観察されたメッセージに限定される。Dandelionはまた拡散の対称性を破壊し、トランザクションソースの推測を困難にする。

https://github.com/bitcoin/bips/raw/master/bip-0156/4-dandelion-plot.png

トランザクションはDandelionのstemフェーズでランダム数ホップした後、ルーティングのfluffフェーズに移行する。トランザクションは既存の拡散プロセスを通じてネットワークに共有される。実際には、fluffの仕組みは各ノードでコインフリップの重み付けで強制される。ランダム値がある閾値を下回る場合、Dandelionトランザクションは典型的なトランザクションに変換される。我々のテストでは、あるノードを離れる際、特定のDandelionトランザクションがfluffフェーズに入る確率を10%と選択した。この値はstemの経路長とトランザクション拡散のレイテンシーとの間で良好なバランスを取る。

Dandelionの予測精度保証は集団レベルのメトリックだが、期待リコール保証は個人レベルのメトリックとして解釈できる。期待リコールは、敵対者が単一のトランザクションを所与のソースに関連付ける確率に相当する。これらの保証は確率的だ。彼らは、ノードが他のノードによって覆い隠されたシナリオ、またはISPのような敵対者によってノードが具体的にターゲットにされているシナリオに対処していない。非匿名化のターゲットとされるのを心配する個人は、Torを使用する必要がある。

高いレベルでは、DandelionはBitcoinのプライバシーの課題を意識していないようなユーザーを含む、一般の人々のための匿名性の注入のようなものだ。Torを使っていないユーザーにも、採用が増えると大きなメリットがもたらされる。Dandelionの早期採用者は、プライバシー上の利益を得ている。隣接するノード群がDandelionをサポートしない最悪の場合、トランザクションはDiffusion前に1ホップを作成する。ルーティングにのみ基づくソリューションは、オリジナルのDandelionペーパーに示されている精度とリコールに関する基本的な下限のため、完全に匿名にすることはできない。Dandelionはそのようなソリューションの中で最適な匿名性保証を提供する。

仕様

Dandelionは以下のいくつかの機能で定義される。

仕様の詳細について以下にまとめる。

Dandelionトランザクションサポート

stemフェーズ中、トランザクションはDandelionトランザクションとなる。Dandelionトランザクションがfluffフェーズに入ると、トランザクションはBitcoinの通常のトランザクションとなる。Dandelionトランザクションと通常のBitcoinトランザクションとの違いは、NetMsgTypeのみ。

stemフェーズのDandelionトランザクションは通常のBitcoinトランザクションと区別できなければならない。

Dandelionルーティングデータとロジック

stemフェーズ中のDandelionのルーティングでは、インバウンドピア、アウトバウンドピア、Dandelion宛先、Dandelionルートという4つの概念がある。インバウンドピアはピアが接続を開始してから現在接続されている全てのピアで構成される。アウトバウンドピアは、このノードによって現在接続されている全てのピアで構成される。Dandelionの宛先はアウトバウンドピアのサブセットである。Dandelion宛先の数は、DANDELION_MAX_DESTINATIONSパラメータによって制限される。参照実装ではこの値は2に設定されている。我々のテストでは、この値がプライバシーと堅牢性の両方を提供することを示している(パラメータのトレードオフに関する詳細は参考文献を参照)。Dandelionルートは、Dandelion宛先へのインバウンドピアのマップだ。各インバウンドピアはDandelion宛先にマッピングされている。

Dandelionノードは、プライバシーグラフから分割することなく異なるDANDELION_MAX_DESTINATIONSパラメータを選択できることに注意すること。Dandelionルートのインバウンド接続をアウトバウンド接続にマッピングする際は、次のルーティングロジックを実装する。最初に、アウトバウンドピアのセットからDandelionの宛先のセットを選択する。このDandelionの宛先のセットのサイズは、DANDELION_MAX_DESTINATIONS以下である。インバウンド接続毎に、最小数のルートを持つDandelion宛先のサブセットを最初に識別する。例えば、Dandelion宛先の一部がゼロルートに属し、他の全てのDandelion宛先は1以上のルートに属する。このサブセットの中から一様にランダムに1つのDandelion宛先を選択する。インバウンド接続からこのDandelion宛先へのDandelionルートを確立する。

あるDandelionルートエポックでは、2つの個別のDandelion宛先を、アウトバウンド接続のセットから一様にランダムに選択する必要がある。特定のインバウンド接続から受信した全てのDandelionトランザクションは、同じDandelion宛先に送信する必要がある。特定のインバウンド接続に対してDandelion宛先を選択する際は、最小のインバウンド接続がそれらにマップされているDandelion宛先のセットから一様にランダムに選択しなければならない。

定期的なDandelionルートシャッフル

Dandelionルートのマップは、平均10分毎にクリアされ再構築される。我々は敵がプライバシーグラフを学習するのを困難にするため、経験的に10分という時間を選択した。Dandelionノードは、プライバシーグラフを分割することなく、異なる平均シャッフル時間を選択できることを注意すること。embargoes

Dandelionルートは、ランダムな間隔でクリアし再構築しなければならない。Dandelionルートは平均10分毎にクリアして再構築する必要がある。

メモリプールロジック

Dandelionトランザクションは、一般的なトランザクションとは区別される。ただメモリプールは変更されない。stempoolと呼ばれるCTxMemPoolの別のインスタンスが、Dandelionトランザクションに使用される。適切なトランザクション伝播を保証するため、情報がmempoolからstempoolへ流れる。Dandelionトランザクションが通常のトランザクション流入しない限り、情報がstempoolからmempoolに流れることはない。

Dandelionトランザクションが届くと、そのトランザクションはstempoolに追加され、mempoolに追加されてはならない。一般的なトランザクションが届くと、そのトランザクションはmempoolに追加され、stempoolにも追加されなければならない。Dandelionトランザクションがfluffに入ると、そのトランザクションはmempoolに追加しなければならない。

fluffメカニズム

DandelionルートにDandelionトランザクションを中継すると、Dandelionトランザクションは10%の確率で通常のBitcoinトランザクションになり、Diffusionで中継される。我々のテストでは、この値はstemのパス長とトランザクション拡散レイテンシー間で良好なバランスを保っている。Dandelionノードは、プライバシーグラフを分割することなく異なる確率を選択できることに注意すること。

ノードがDandelionトランザクションの送信を準備する際、偏ったコインフリップをしなければならない。コインフリップの結果がDandelionトランザクションの場合、ノードはトランザクションを適切なDandelion宛先に送信する必要がある。結果がDandelionトランザクションでない場合は、Dandelionトランザクションを通常のBitcoinトランザクションに変換する必要がある。Dandelionトランザクションは10%の確率で通常のBitcoinトランザクションに変換されるはずだ。

トランザクションの停止

stemフェーズ中、トランザクションは単一のパスに沿って中継される。このパスの任意のノードがDandelionトランザクションを受信してオフラインになると、そのトランザクションの伝播は停止する。堅牢性を高めるため、Dandelionトランザクションを転送する全てのノードは受信時にタイマーを初期化する。タイマーが終了するまでにDandelionトランザクションがメモリプールに現れない場合、トランザクションはfluffフェーズに入り、Diffusionで転送される。

Dandelionトランザクションを受信すると、ノードは将来のランダムな時間を停止タイマーとしてセットしなければならない。Dandelionトランザクションが通常のBitcoinトランザクションとして届いた場合、ノードはタイマーをキャンセルする必要がある。Dandelionトランザクションがタイマーが切れる前に通常のBitcoinとして観測されたら、ノードはDandelionをfluffで処理する。

Dandelionトランザクションロジック

以下のケースは、Dandelionトランザクションを参照するネットワークパケットを受信した際のノード振る舞いを定義している。

  • Dandelion TxのINVを受信した場合
    ピアがインバウンドで、そのピアからDandelionトランザクションを受信していない場合、GETDATAで応答する。
  • Dandelion TxのGETDATAを受信した場合
    ピアがインバウンドではなく、Dandelionトランザクションがこのピアに配信されている場合、Dandelionトランザクションで応答する。
  • Dandelion Txを受信した場合
    ピアがインバウンドの場合、Dandelion Txを適切なDandelion宛先に中継する。

実装

参照実装は以下から入手可能。

github.com

全ての機能は以下のURLの単一のコミットに圧縮されている。

https://github.com/dandelion-org/bitcoin/tree/dandelion

互換性

DandelionはBitcoinの既存バージョンと競合しない。DandelionをサポートするBitcoinノードは、古いソフトウェアバージョンを実行するBitcoinノードと同様に見える。DandelionをサポートするBitcoinノードは、プローブメッセージを介して機能サポートを識別することができる。明らかに古いノードはDandelionルーティングの互換性はない。DandelionをサポートするBitcoinノードでも、接続先にDandelionをサポートするピアがない場合、Dandelionトランザクションの停止により、自然とDandelionサポートのないBitcoinノードの動作になる。

Bitcoinのプライバシーを向上する決済プロトコル Pay to EndPoint(P2EP)

Blockstreamが先日公開した、Bitcoinのfungibilityの問題を改善するため、Pay to EndPoint(P2EP)という決済プロトコルを発表してたので見てみる↓

blockstream.com

Bitcoinのプライバシーの課題

Bitcoinの課題の1つとして挙げられるのがfungibility。

現金であれば、それがどのような使われ方をして自分の財布の中にあったとしても、その紙幣を使って支払いができる。偽札でも無い限り、紙幣での支払いを拒否されることはない。1万円札はどこに行っても同じ1万円の価値があり、交換可能。

たがBitcoinの場合、自分が持っているコインがどういう経路を辿ってきたか、ブロックチェーンを分析することである程度分かる可能性がある。そのコインの出処によってはそのコインの支払いを拒否するといった可能性も否定できない。本来、どいういう経路であれ自分が受け取り財布の中にあるコインは、同じコインとして使用できるべきで、コインの出処によって関係のないユーザーの価値が毀損されるという自体は避けたいが、現金と比べると、こういった代替可能性がBitcoinの場合は低い。

このfungibilityの課題について改善しようというのがPay-to-EndPoint (P2EP)のゴール。

コインの出処や所有権が追跡できるようにしようとブロックチェーンの分析がされているが、この分析は、1つのトランザクションのインプットは全て同じユーザーが所有している「common input ownership」という仮定に基づいて行われている。まぁマルチシグやCoinJoinのような取引を除いて、ほとんどの取引は事実そういうトランザクションになっている。コインの追跡はこの前提を元に行われるので、この前提を壊せばコインの追跡がしにくくなり、Bitcoinにおけるfungibilityの課題を改善できるのではないか?ということみたい。

では、「common input ownership」の前提を崩すにはどうすれば良いかというと、

普段コインを送金する際は、コインの受信者が送信者にアドレスを伝え、送信者がそのアドレス宛にコインを支払うトランザクションを作成&署名し、ネットワークにブロードキャストする。この場合、当然送信者が作成するトランザクションのインプットのUTXOの所有権は送信者が持つものだ。

P2EPでは、この送金トランザクションのインプットに送信者のUTXOに加え、受信者のUTXOも加えることで「common input ownership」の前提を崩そうとしている。

具体的には↓

Pay to EndPointのプロトコル

Pay to EndPointでは、以下の手順で、受信者と送信者が協力して送金トランザクションを作成する。

手順1

受信者はまずBIP-21形式の送金先URIを生成し、送金先として送信者に送る。この時、URIにP2EPのエンドポイントを付与する。

bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?p2ep=3j4tau93wkc8mh32.onion

↑のようなURIが生成される。通常のBIP-21のURIに加えて、p2epキーでP2EPのエンドポイントのURI3j4tau93wkc8mh32.onionが付与されている。

※ BIP-21のURIの定義には未定義のkey-valueを指定可能なので、P2EPに対応していないウォレットは、従来の方法でコインを送ることになる。

手順2

送信者は受信者から送られてきたエンドポイントが有効であれば、受信者との対話を始める。

  • エンドポイントが有効でない場合
    通常の送金と同様BIP-21のURIに記載されているアドレス宛にコインを送金する。
  • エンドポイントが有効な場合
    UTXOの所有権の証明として、自分が送金する額を持つ自身のUTXOをトランザクションのインプットにセットした署名済みのトランザクションを受信者に送る。

手順3

受信者は署名のため多数のトランザクションを署名のため送信者に送る(これらのトランザクションはさっき送信者が送ってきた送信者のUTXOと、受信者のUTXOがセットされたものと思われる)。 ただこれらのトランザクションのうち、実際に受信者が所有しているUTXOがセットされたトランザクションは1つのみで、それ以外は未使用のUTXOプールから選択されたUTXOがセットされたトランザクションになる。

このトランザクションは、送信者に直列もしくは並列で送られる。

直列送信

順番に送信されるトランザクションのどれが受信者のUTXOを持つトランザクションかの確率は、受信者が選択し署名したトランザクションの数と順番がどのようにランダム化されたかによって代わる。一連のトランザクションの交換は、送信者が受信者のUTXOを使った署名済みのトランザクションを受信者に送ると終了する。

並列送信

受信者によって作成されたトランザクションは全て一度に送信者に送られる。送信者が受け取った一連のトランザクションの内、受信者が所有するのは1つのみ。送信者が正しいもの(受信者のUTXOを持つTx)を選択する確率は、受信者が選択して送信したトランザクションの数に比例する。送信者は全てのトランザクションに署名し、受信者に送付する。

上記いずれかの方法で受信者が送信するトランザクションの数は今のところ100個で、いずれかの側でプライバシーとデータ送信/処理のバランスを取る。

UTXOを交換する上記の方法は、Bulletproofsを使用する方法で置き換えられるかもしれない。

手順4

手順3のどちらのケースでも、受信者は署名済みのトランザクションを手に入れので、このトランザクションに受信者の署名を加えてブロードキャストする。このトランザクションのインプットには受信者と送信者の両方のUTXOが含まれている。

上記P2EPのプロセスが何らかの理由で失敗した場合は、従来通りの方法でコインを送金する。

P2EP送金の具体例

アリスがボブに1 BTC送金したい場合、P2EPのプロトコルを使って以下のようなトランザクションを作成する。

  • アリスはトランザクションのインプットに3 BTCをセットする。
  • ボブはトランザクションのインプットに5 BTCをセットする。
  • アリスはお釣りとして2 BTC受け取る。
  • ボブはアリスからの送金分とお釣りで6 BTC受け取る。

こうやってできたトランザクションは「common input ownership」の仮定を崩したものになる。これがどういう送金なのかはいろんな解釈ができる。例えば、アリスが3 BTCと5 BTCのUTXOを使って、ボブに6 BTC支払い、2 BTCのお釣りを受け取ったなど。

P2EPの利点と欠点

利点
  • 「common input ownership」の仮定を崩せる。最小限の採用であっても、通常の非P2EPトランザクションのプライバシーを改善できる。
  • subset sum analysisを壊す。
  • 受信者のUTXOを使用することで、UTXOの膨張を低減させるのに役立つ。
  • 受信者はP2EPを使うことでUTXOセットを統合できる。
  • 従来のCoinJoinトランザクションと異なり、見た目は通常のトランザクションと変わらないので、トランザクションタイプを特定するのが困難。
  • 送信者のウォレットは軽量ウォレットでいい。
  • 送信者と受信者にはより大きなプライバシーが与えられる。
欠点

P2EPの今後

P2EPはまだ初期段階なので、正式な提案の前に今後コミュニティからのレビューと改良が加えられる。

P2EPの考え方は、支払いの分割やコインスワップなど他の形態のトランザクションを含むよう拡張することも可能と。

所感

  • 受信者側にホットウォレットとフルノードへのアクセスが必要というのは、それなりにハードル高い。
  • ↑の手順3で受信者が多数のトランザクションを送信者に送ってるのが、UTXOのスプーフィング攻撃への対応?
  • P2EPに限らず、P2Pの参加者間で対話的に決済トランザクションを作成するネットワークの標準仕様とかあると便利かも。
  • 通常のP2PKHの送金だと一般的には1つのインプットと2つのアウトプット(送金先のアウトプットとお釣りのアウトプット)が考えられ、UTXOの数は増えていくトランザクションが多いと思うけど、インプットに受信者のUTXOが増えることでUTXOの膨張を低減させるって視点はおもしろいな。

安全性とプライバシーを強化するペイメントチャネルネットワーク「Multi-Hop Locks」

LNではHTLCを使って仲介者を経由したマルチホップ決済を可能にしている。例えばアリス→キャロルのオフチェーン決済をボブとマイクを経由して行うケースでは以下のような決済フローになる。

f:id:techmedia-think:20180704140150p:plain

  1. 最初に受信者のキャロルがランダムな値Rとそのハッシュ値H(R)を生成し、H(R)をアリスに渡す(invoice)。
  2. アリスはキャロルまでの経路を決め、H(R)とタイムロックを組み合わせたHTLCトランザクションをボブとのペイメントチャネルに投げる。
  3. 仲介者はさらに経路上の隣のユーザーにHTLCを流していく。
  4. キャロルまでHTLCが届いたら、マイクにRを明かして資金を受け取る。
  5. 今度は逆方向に終着点アリスまでRと交換に資金をセトルメントしていく。

ここでタイムロックとシークレットを組み合わせたHTLCは、以下のような条件を持つコントラクト(↑のアリスとボブで考えた場合)

  • 3日経過する前にボブがハッシュを取るとH(R)になるようなRを生成できればアリスはボブにコインを支払う。
  • 3日経過するとアリスにコインが戻ってくる。

こういったマルチホップ決済について、一般化し安全性およびプライバシー保護を強化するMulti-Hop Locksという新しい提案が発表された↓

https://eprint.iacr.org/2018/472.pdf

↑のホワイトペーパーの著者であるPedro Moreno-Sanchezのプレゼン↓

youtu.be

マルチホップ決済のモデル化

↑のホワイトペーパーではこのマルチホップ決済のようなロック機構をMulti-Hop Locksという暗号プリミティブとしてモデル化している。このモデル自体はマルチホップ環境下のロックを一般化したもので、LNはその使用形態の1つ。LNの場合はロックの解除=コインの入手を意味するMulti-Hop Locksの一使用形態になる。

ホワイトペーパーでは、このモデルを実装するための方法として以下の3つの方法を提示している。

  • 一方向準同型関数を使った一般的なスクリプトベースの構成
  • Schnorr署名を使ったScriptless Scriptベースの構成
  • ECDSAを使ったScriptless Scriptベースの構成

一般的なスクリプトベースの構成では一方向の準同型関数を使った任意のコントラクトを作成できるブロックチェーンである必要があり、EthereumやHyperledger Fabricがターゲットとして挙げられている。BitcoinはまだSchnorrはサポートしていないので、現状のBitcoinベースでMulti-Hop Locksを実装する場合、ECDSAを使ったScriptless Scriptの構成になる。この場合、2017年にYehuda Lindellが発表した「Fast Secure Two-Party ECDSA Signing」を使って後述する鍵生成やロックが実装される。

(参考) techmedia-think.hatenablog.com

Multi-Hop Locksは以下の5つのプロトコルで構成される。

f:id:techmedia-think:20180705095024p:plain

1. 鍵生成

チャネルを構成する二者間の鍵を生成するプロトコルで、アリスとボブがいた場合アリスの鍵 {sk_1}とボブの鍵 {sk_2}、最後にアリスとボブの共通公開鍵 {pk}を返す。

基本的にはチャネルを開設した時点で、お互いの公開鍵を知り、共通公開鍵を共有している状態(チャネルを開いた時点で鍵生成プロトコルは実行済み)になると思われる。

2. セットアップ

セットアッププロトコルは、参加者の集合(=LNで決済する際の経路)が与えられた際に、経路上の各参加者に状態 {s_i}を与えられる。また最後の参加者(=LNでコインの最終的な受信者)にはさらにオープン鍵 {k_n}が与えられる。各状態はこの後のロックを生成するのに使われる。

3. ロック

続いて隣り合う各参加者のペアがロックプロトコルを実行する。ユーザーのペアを {U_i} {U_{i+1}}とした場合、2人は両者の初期状態 {s_i} {s_{i+1}}を使ってロック( {L_i})を作成する。このロックは、ある暗号条件が {U_{i+1}}によって解かれた場合に、 {U_{i}}がある量のコインを {U_{i+1}}に支払うというコミットメントになっている。

既存のLNではこのロックをアンロックする際に必要となるのは、受信者がコインを受け取る際に必要なプリイメージで、経路上の全ノードのコミットメントで同じ値が使用されるが、Multi-Hop Locksの場合はアンロック条件は隣り合うノード毎に異なるのが特徴だ。

↑の図のアリスとボブの場合は、初期状態 {s_0} {s_1}を使って、ロック {L_0}を生成し、 {s_0^{R}}をアリスに {s_1^{L}}をボブに送る。

このロックは、 {L_0}のロックを解いたらアリスがボブにコインを支払うというコミットメントを表す。

4. リリース

リリースプロトコルは↑のロックを解放するプロトコルで、オープン鍵kと {(s_i , s_i^{R}, s_{i}^{L})}が与えられた時、新しいオープン鍵k'を返す。

↑の図では、キャロルがロック {L_2}をアンロックするために、最初に受信したオープン鍵 {k_3} {(s_3 , s_{3}^{L})}を使って新しいオープン鍵 {k_2}を入手する。キャロルは {k_2}でL2をアンロックすると、今度はマイクが {k_2} {(s_2 , s_2^{R}, s_{2}^{L})}を使って、L1をアンロックするためのオープン鍵 {k_1}を入手できる。これを送信者のアリスに辿り着くまで続ける。

5. 検証

検証プロトコルは、↑のリリースプロトコルで生成したオープン鍵とロックから、そのロックがリリースできるか検証する。

一方向準同型関数を使った実装

モデルでなんとなーくのイメージは掴めるけど、一般化されたモデルで実際のロジックが分かりづらいため、一方向準同型関数を使った実装で理解する。

一方向準同型関数というのは、 { y = f(x)}のような関数で、yからxを計算することが困難で、かつ {f(x) \cdot f(x') = f(x \cdot x')}のような準同型性がある関数。

楕円曲線の鍵ペアを使うのが簡単で、秘密鍵をxとした場合y = xGとなり、xG + x'G = (x + x')Gとなる性質を持つ関数を採用する。

セットアップフェーズ

  1. LNで支払いを行う送信者は受信者までの数分(n)、ランダムに値をサンプリング( {y_0, ..., y_n})する。
  2. 送信者は受信者までの各ユーザーに対して3つのアイテム= {(\sum_{j=0}^{i-1}y_jG,\, \sum_{j=0}^{i}y_jG,\, y_i)}を送る。参加者が3人の場合、以下のデータが送られる。
    •  {U_0}(送信者)には {(n/a, y_0G, y_0)}
    •  {U_1}(中間者)には {(y_0G, (y_0 + y_1)G, y_1)}
    •  {U_2}(受信者)には {((y_0 + y_1)G, (y_0 + y_1 + y_2)G, y_2)}
  3. 受信者にだけ、 {\sum_{i=0}^{n-1}y_i}をオープン鍵を送る(この場合オープン鍵 =  {y_0 + y_1 + y_2})。

ロックフェーズ

各ユーザーは、送信者から送られたデータを元に、ロックスクリプトを構成する。3つ受信したアイテムの内、右側のノードの2つめのアイテムと、左側のノードの1つめのアイテムは同じデータを指しているので、それを使ってロックをする。

例えばU_2U_3の間のロックはU_2 {(y_0G, (y_0 + y_1)G, y_1)}の2つめのデータと、U_3 {((y_0 + y_1)G, (y_0 + y_1 + y_2)G, y_2)}の1つめのデータは {(y_0 + y_1)G}で同じ値になる。これを使ってロックスクリプトを構成する。この時の条件は、 {y_0 + y_1}が明らかになればU_2からU_3にコインを支払うというもの。

これがHTLCの代わりで経路上の全ノードが実行する。

リリースフェーズ

受信者がセットアップフェーズで送信者から送られた y_{n-1}とオープン鍵を使ってコインを入手する。3者の場合、受信者U_3は、y_2を知っているので、別途送信者からもらったオープン鍵 {k = y_0 + y_1 + y_2}からy_2を引いて {y_0 + y_1}の知識を得る。 {y_0 + y_1}は、  {U_2} {U_3}間でロックされているコインのアンロックするのに有効なプリイメージなので、これを  {U_2}開示するとコインを入手することができる。

続いて {U_2} {y_0 + y_1}が分かるので、セットアップフェーズで受信したy_1を引いてy_0を計算する。y_0が分かれば {U_0}からコインを入手できるという仕組みだ。

図にまとめると↓な感じ。

f:id:techmedia-think:20180801142831p:plain

説明のためにプリイメージのみをアンロック条件として記載しているけど、実際はプリイメージを知っているアリスが不正をしないよう、各ノード間のコントラクトには別途参加者の鍵での署名も条件に加わると思われる。

こうやって準同型性のある一方向関数を使うことで、受信者側(左側)から順にコインをアンロックし、アンロックに使用した値がさらにその先のロックをアンロックするのに使われる仕組みを実現しており、これがHTLCの代替になる。HTLCと比べて各中間ノードで扱われる条件はそれぞれ異なるのでプライバシー及びセキュリティの向上になると考えられる。

※ なお、現状のBitcoinでは一方向準同型関数を使った構成はスクリプトで実装できないので、現状のBitcoinに適用する場合は別のECDSAを使ったScriptless Scriptの構成を取る必要がある。SchnorrやECDSAを利用した実装については、別途書けるといいな。

Multi-Hop Locks のメリット

従来のペイメントチャネルが、ハッシュのプリイメージとコインを交換するHTLCの連鎖であったのに対し、Multi-Hop Locksでは各ホップで両者の状態( {s_i, s_{i+1}})を使ってロックを構成し、そのロックは右側のロックをリリースした際のオープン鍵を使ってアンロックできるようになっている。

このモデルでは既存のペイメントチャネルに比べて以下のようなメリットがある。

  • HTLCでは経路上に同じシークレット値とそのハッシュを使用するが、Multi-Hop Locksは各ホップ毎にロック条件が異なるのでプライバシーが向上する。
  • HTLCの場合、途中のコミットメントトランザクションがブロードキャストされると、HTLCが使われていたことがチェーン上で明らかになるが、Scriptlessで構成した場合チェーン上に現れるのは(P2PKHのような)通常の決済のトランザクションと同じになるのでプライバシーが向上し、さらにトランザクションサイズも削減され、その結果、手数料、オンチェーン上のスペースの削減が見込まれる。
  • Scriptlessの構成の場合、EthereumなどのECDSA(もしくはSchnorr)をサポートするその他の暗号通貨にも同様に適用可能。
  • LNに限らずAtomic SwapもScriptlessベースで行うと、HTLCトランザクションがオンチェーン上に記録されることはなく、プライバシーの向上が見込める。

Bitcoinベースの新しいデジタルアセットプロトコル「RGB」

Lightining Networkとの連携も含めた、「RGB」というBitcoinベースの新しいデジタルアセットプロトコルが発表された↓

github.com

RGBのプロトコル仕様は、現状以下の5つのモジュールに分かれている。

  1. RGB
    プロトコルのコアおよび低レベルのアセットロジックを定義。
  2. Kaleidoscope
    他のモジュールを包括しプロトコルとして相互作用するための高レベルの機能を定義。
  3. Bifröst
    クライアントサイド検証の枠組みのプルーフの保存と公開について定義。
  4. Lighting Network Integration
    RGBをLighting Networkに適用する(アセットに対応したルーティング、チャネルの更新、クローズなど)ために必要なBOLTの拡張などを定義。
  5. Proofmarshal
    アセットに特化した形で、スケーラビリティとプライバシーを向上させる、Lightning Networkを補完・代替するレイヤー2ソリューションの定義。

まだ完成という訳ではないっぽく、現時点で使用が少しでも記載されてるのはRGBと、Bifröst、Lighting Network Integration。いずれもまだ作成途中っぽい。Lighting Networkで任意のアセットをオフチェーンで取引するための拡張仕様が定義されてたり、LNとは別のスケーラビリティソリューションの提案とか特徴的。

まずは、RGBモジュールみながらコア機能についてまとめた。

アセットの検証

一般的に、カラードコインはOP_RETURNを利用してBitcoinのトランザクションレイヤーを拡張しているが、Bitconのプロトコル上、OP_RETURNにあるデータは何の意味ももたず、その上に構成されるアセットの取引もコンセンサスレベルで関与することはない。そのため、こういった拡張プロトコルでは、そのプロトコルに対応したウォレットやノードなどのクライアントが、アセットの振る舞いの検証をするClient Side Validationモデルを採用する。RGBも他のカラードコインのプロトコルと同様このClient Side Validationを採用している。

コントラクト

アセットがどのようなもので、アセットの発行方法、転送のルールなどを定義したものをコントラクトと呼んでいる。このコントラクトのデータは以下の2つのデータで構成される。

  • header
    コントラクトの全種類共通のヘッダ項目
  • body
    コントラクトの種類毎に定義される項目

headerのデータ項目は以下の通り。

フィールド 内容
title アセットコントラクトのタイトル
description アセットコントラクトの定義
contract_url コントラクトとlight-anchorの発行に関する一意のURL
issuance_utxo このコントラクトをデプロイするためのコミットメントを持つトランザクションで使用されるUTXO
network 使用中のネットワーク(mainnet, testnet)
total_supply 総供給量(単位はsatoshi)
min_amount dust limitのように転送する際のトークンの最小量
max_hops 再発行前の最大ホップ数(この機能を無効にする場合は0xFFFFFFFFを設定する)
reissuance_enabled 再発行機能を有効にするかどうか
reissuance_utxo (オプション)トークンを再発行する際に使用するUTXO
burn_address トークンを償却する際の送信先アドレス
commitment_scheme このコントラクトで使用するコミットメント方式
version 使用されたブループリントのバージョンを表す16 bitの数値

Open Assets ProtocolなんかだとAsset Definition Fileに近いけどあれはメタデータ的な位置付けで、↑ではアセットの種類による振る舞いやルールも定義するようになっている。

アセット識別子:asste_id

各アセットはasset_idで識別される。このasset_idコントラクトのいくつかのデータ項目のハッシュから計算されるようだが、現時点では算出方法については書かれてない。

Proof-of-burn

アセットを焼却する際は、コントラクトのheader内のburn_addressで指定されたアドレスにアセットを送る。

ブループリント

コントラクトには種類があって、この種類によってアセットがどのように管理されるかであったりその振る舞いが決まる。これをブループリントと呼んでいる。

現状定義されているブループリントは以下の3つ。

Simple issuance: 0x01, version: 0x0008

シンプルなアセット発行のコントラクトで、headerのtotal_supplyで指定された量のアセットを発行し、owner_utxo宛に送る。

このタイプのコントラクトのbodyのデータ項目は、以下の通り。

フィールド 内容
owner_utxo 全てのトークンを受け取るUTXO

この場合コントラクトは以下のようになる。

{
  "kind": 0x01 // 作成するコントラクトの種類で、これは一般的な発行
  "version": 0x0008 // このコントラクトの種類で使われるバージョン
  "title": <String>, // アセットコントラクトのタイトル
  "description": <String>, // 償還可能なアクションと非スクリプトによる条件の定義
  "issuance_utxo": <String>, // このコントラクトへのコミットメントに使われるUTXO
  "contract_url": <String>, // コントラクトおよびlight-anchorを公開するための一意のURL
  "total_supply": <Integer>, // 総供給量(satoshi)
  "max_hops": <Integer>, // 再発行前にアセットに対して実行可能なオンチェーン転送の最大量
  "min_amount": <Integer>, //一緒に転送可能なカラーリングされたsatoshiの最小量
  "network": "BITCOIN", // 使用するネットワーク
  "reissuance_enabled": 0, // 再発行の無効化
  "burn_address": <Address>, // トークンを焼却するのに使用するアドレス
  "commitment_scheme": "OP_RETURN", // このアセットで使用するコミットメント方式
  "owner_utxo": <String>, // 全ての発行トークンを受信するUTXOで、コントラクト指定のフィールド。
}
Crowdsale: 0x02, version: 0x0008

クラウドセール用のブループリント。total_supplyまで指定した価格でトークンを販売する。コントラクトには異なるasset_idをもつ2つのアセットが作られる。1つは通常のトークン用のアセットでもう1つは払い戻し用のトークン。払い戻し用のトークンはクラウドセールの期間前や後に送金してセールを逃したユーザー向けのもの。

このタイプのコントラクトのbodyのデータ項目は、以下の通り。

フィールド 内容
deposit_address トークンを購入する際のBitcoinの送金先アドレス
price_sat 1トークンあたりの価格(satoshi)
from_block クラウドセールを開始するブロック
to_block クラウドセール終了のブロック
Re-issuance: 0x03, version: 0x0008

アセットの発行者が、供給量を増やすことでアセットの再発行を可能にするブループリント。このコントラクトを使用する際は、オリジナルのコントラクトのreissuance_enabledが0でないこと。またオリジナルコントラクトのreissuance_utxoで指定されているUTXOを使ってデプロイする必要がある。

このコントラクトの場合、header内のtitle,description,network,min_amount,max_hops,burn_address,commitment_schemeはオリジナルから変わらないので全て0をセットする。

またbodyのデータ項目はない。

プルーフ

コントラクトは上記のように種類によってルールが異なるが、各コントラクトに設定された全ての条件を満たすことでアセットの所有権を証明し、そのアセットの送付が可能になる。このコントラクトに設定された全ての条件を満たしたことを証明するのがプルーフになる。

プルーフコントラクトと同様headerbodyを持つとされているが、具体的な項目についてはまだ定義されていないっぽい。

アセット送付時のプルーフ

アセットを送付する際は、以下のデータがプルーフになる。

  • アセットの発行から今までの全てのプルーフのチェーン
  • 以下3つの項目からなるリスト
    • 取引するトークンのカラー
    • 取引する量
    • 送信するトークンのアウトプットに関する情報で、UTXOベースのトランザクションを送信する場合はSHA256D(TX_HASH || OUTPUT_INDEX_AS_U32)で、アドレスベースのトランザクションを送信する場合は受信者に送信するアウトプットインデックス。
  • (オプション)meta-dataに関連するmeta-script

これらのプルーフは以下のdark-tagを使ってAES256で暗号化され、Publisher Serverに送られる。

dark-tag

アセットの受取人が生成する30バイトのエントロピーを持つ共通鍵で、アセットを送ってもらう際に、アドレスおよびPublisher Serverの情報と一緒に、アセットの送信元に送る。

受取人がdark-tagを生成する際は、受信用のアドレスを生成するのに使用しているBIP32ベースの導出鍵を使って導出する。

プルーフの情報はこのdark-tagで暗号化されているため、取引されているカラーや量に関してはこのdark-tagを知っているユーザーのみが把握でき、第三者ブロックチェーン上のトランザクションを確認してもこれらの情報は確認できないと思われる。

dark-tagが漏洩すると、発行トランザクションからそのトランザクションまでのアセットの流通経路は分かるが、途中で分岐していた場合などはそっちのアセットの流通経路までは分からない。

Publisher Server

Publisher Serverは、各アセットの取引で生成された暗号化されたプルーフを保存し、そのクエリに対応するサーバー。アセットの発行者によってメンテナンスされる場合もあるし、個々の受信者がメンテナンスしたり、第三者によって提供されることも考えられる。

BitTorrentやIPFSなどの分散ストレージの利用も挙げられているが、RGB自体はPublisher Serverについてシンプルさのため集中型の管理もありとしてる。

コミットメント方式

アセットを新規発行する際は↑のコントラクトのデータを、アセットを送付する際はその条件を満たしていることを証明する↑のプルーフをそれぞれブロックチェーンにコミットする必要がある。Open Assets Protocolでは、これらは基本的にOP_RETURNのアウトプットにMakerOutputと呼ばれるOA用のペイロードをプッシュする形態をとっていたけど、RGBの場合は以下の2種類の方法が用意されている。

OP_RETURN

他のカラードコイン同様OP_RETURNを使う方法で、OP_RETURNの後に↑のコントラクトやプルーフのエンティティ情報をプッシュする。OP_RETURNを使ったRGBの有効なコミットメントを含むトランザクションのルールは以下の通り。

pay-to-contract

pay-to-contractは直訳するとコントラクトへの支払い。コントラクトの内容を元に鍵およびアドレスを生成するプロトコルで、昔Blockstreamが発表したSidechainのホワイトペーパーなどで紹介されている。

RGBのエンティティにコミットするpay-to-contractアドレスは以下のように計算する。

  1. ランダムに128 bitのnonceを生成する。
  2. weak = hmac_sha256(key=original_pubkey, data=(nonce||double_sha256(RGBのエンティティ)))を計算する。
  3. new_pubkey = original_pubkey + G * tweakを計算する。
  4. 計算したnew_pubkeyを公開鍵として、P2WPKH or P2PKHアドレスを生成する。

この公開鍵に対応する秘密鍵は、元の秘密鍵に対して同じ計算を適用することで計算できる。

後は計算したアドレス宛に送金するトランザクションを作るだけで、トランザクションの構成は通常の支払いと何ら変わらない。

アセットの送付方法

RGBで実際にアセットを送付する際、送信者は以下の2つの方法でアセットの所有権を移転できる。

アドレスベース

アセットの受信者がアセットのUTXO自体を受け取りたい場合に使用する。この場合、プルーフには、トランザクション内の受信者の送信先アドレス宛のアウトプットのインデックスをセットする。

※ アセットを受信者のアドレスに送るという直観的に分かりやすい方法で、他のカラードコインなどでも一般的によく使われている方法。

UTXOベース

受信者が既に持っているUTXOに、トークンをバインドしたい場合に使用する。このためこの送付トランザクションには受信者向けのアウトプットは含まれず、プルーフには、送信先のUTXOのハッシュをセットする。

※ この場合ブロックチェーントランザクションを見ただけでは、誰から誰にアセットが送付されているのか推測できない。

この場合、複数のアセットが同じUTXOを指定していた場合、そのUTXOは両方のアセットを持つということになるのかな?

RgbOutPoint

上記のようにアドレスベースの場合は送信トランザクションのアウトプットインデックスを、UTXOベースの場合は受信者の既存のUTXOのOutPointを指定することになるが、それぞれをエンコードしたオブジェクトをRgbOutPointと呼んでいる。

RgbOutPointシリアライズする際は、どちらか分かるようUTXOベースの場合は0x01、アドレスベースの場合は0x02がプレフィックスとして付与される。(長さで分かりそうな気がするけど)

所感

Open Assets Protocolとかだと、取引するアセットの量や宛先は全てトランザクション内のMarkerOutput(OP_RETURNにOpen Assets Payloadをプッシュしたもの)で管理されていて、OAのトランザクションを解釈できれば、ブロックチェーン上でどのアドレスからどのアドレスにいくつのアセットが送られているか確認できるプロトコルだったけど、RGBの場合取引するアセットやその量は全てプルーフに記載され、受信者が生成した共通鍵dark-tagで暗号化されPublisher Serverと呼ばれる外部ストレージに保存されるようになっている。ブロックチェーン単体ではアセットの動きは追えず、外部にあるプルーフが必要になる。UTXOベースのトランザクションであれば、プルーフのみがブロックチェーンアンカリングされているといっても良い。

ノードはトランザクション内のコミットメントとプルーフから受信したアセットの情報を判断するので、フルノードでなくSPVノードのような軽量ウォレットでもアセットの管理ができるだろう。

まだ不明点も多いので具体的な実装を含めてプロトコルの完成までまだ時間かかりそうだけど、他にもLNとの連携や、LNとは別のスケーラビリティソリューションなど面白そうな機能はあるので、今後が楽しみ。

不明点

↓のようにドキュメントの中に出てくるけど、内容や仕組みについてまだ書かれてないことが多い。

  • asset_idの計算方法
  • プルーフの具体的な構成と、検証の仕組み
  • プルーフチェーンの構成方法とその正しさの証明
  • meta-dataやmeta-scriptの内容と振る舞い
  • dark-tagの導出方式
  • Publish Serverと通信する際の具体的なプロトコル

ペイメントチャネルへの資金のチャージ/引き出しを行うSplicing

Lightning Networkはオフチェーン決済を行う2者が資金を両者のマルチシグにデポジットするトランザクション(Funding Tx)をオンチェーンにブロードキャストし、そのデポジットした額(キャパシティ)の範囲内でオフチェーン決済を行う。キャパシティを超える額の決済はできないし、どちらか一方の残高が0になると、0になったユーザーからのそれ以上の送金はできなくなる。ここでチャネルに資金をチャージできるようになると便利だし、逆にチャネルの資金の一部を、別のオンチェーン決済に使いたいというケースも考えられる。こういった既存のチャネルへのチャージおよび既存のチャネルからの引き出しをできるようにしようというのがSplicingのコンセプト。

現在提案されている基本的なSplicingは以下のように動作する。

Splice-in

アリスとボブのペイメントチャネルにアリスが資金をチャージしたいケースでは、以下のようにチャネルに資金をチャージする。

f:id:techmedia-think:20180623145002p:plain

アリスとボブは新しいFunding Txを作成する。この新Funding Txのインプットは

  • 既存のペイメントチャネルのFunding Txのアウトプット
  • アリスがチャネルにチャージするコインを持つUTXO

の2つ。新Funding Txのアウトプットは変わらずアリスとボブの2-of-2のマルチシグ。

続いて新Funding Txをインプットにして、それぞれCommitment Txを作成する。この新しいチャネルのCommitment Txの初期状態の残高は

  • ボブの残高は、旧チャネルの最終のCommitment Txのボブの残高
  • アリスの残高は旧チャネルの最終のCommitment Txのアリスの残高 + 新しく追加したUTXOのコインの量

となる。

両者が新しいCommitment Txの作成・署名・交換を終えたら、新Funding Txをブロードキャストする。これにより、旧チャネルのクローズと新チャネルのオープンが同時に行われる=セトルメントトランザクションが自動的に新しいチャネルのFunding Txになる。

また新Funding Txの作成途中や、新Funding Txがオンチェーン上で必要な承認数を待っている間も、ペイメントチャネルを使ったオフチェーン決済は可能で、新旧両方のチャネルでそれぞれ決済を反映したCommitment Txの更新をすれば良い。

Splice-out

反対にチャネルから資金を取り出すケースも同様の仕組みで対処することができる。

アリスがチャネル上の資金の一部を使ってオンチェーン決済を行うケースでは、以下のようにチャネルから資金を取り出してオンチェーン決済を行う。

f:id:techmedia-think:20180623153436p:plain

アリスとボブは新しいFunding Txを作成する。この新Funding Txのインプットは

  • 既存のペイメントチャネルのFunding Txのアウトプット

新Funding Txのアウトプットは、

  • アリスとボブの2-of-2のマルチシグ。
  • アリスがオンチェーン決済したいアドレス宛のアウトプット。

の2つ。

続いて新Funding Txをインプットにして、それぞれCommitment Txを作成する。この新しいチャネルのCommitment Txの初期状態の残高は

  • ボブの残高は、旧チャネルの最終のCommitment Txのボブの残高
  • アリスの残高は旧チャネルの最終のCommitment Txのアリスの残高 - オンチェーン決済に使用するコインの量

となる。

後はSplice-inと同様、両者が新しいCommitment Txの作成・署名・交換を終えたら、新Funding Txをブロードキャストする。

HTLCを使ったSplicing

もともとSplicingの議論は昨年LNの開発者MLの↓の投稿から始まった。

[Lightning-dev] Channel top-up

↑のプロトコルは、アリスがチャージしたい額のコインをオンチェーンでボブに送信し、それと同額のコインをチャネル上でボブからアリスに送る処理をHTLCを使ってアトミックにするというものだった。

この場合、アリスがボブにオンチェーン上で送金するトランザクションと、ボブからHTLCに設定された期間内にその送金を受け取るトランザクションの2つをオンチェーン上にブロードキャストする必要が出てくる。

↑のSplicingを使えば、オンチェーン上のトランザクションは1つだけで済むのと、プロトコル的にもシンプルになる。ただチャネルのクローズが発生するため、LNの各ノード上はペイメントチャネルのクローズとして認識してしまう。実際はSplicingによりキャパシティの変更があっただけで、チャネル及びルーティングは有効なままなので、それらを認識できるようなメッセージの追加なりが必要になる。

いずれにせよ、LNにおけるSplicingの仕様はまだFixされている訳ではないので、今後新しいアプローチが出てくるかもしれない。