Develop with pleasure!

福岡でCloudとかBlockchainとか。

The GHOSTDAG Protocol at Scaling Bitcoin 2018

Scaling Bitcoin 2018 復習シリーズ。今回はヘブライ大学のYonatan Sompolinskyによる「The GHOSTDAG Protocol」の発表↓(30分あたりから)

youtu.be

書き起こしは↓

ghostdag

ホワイトペーパーは↓

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

Bitcoinのオンチェーンスケーラビリティを向上させるプロトコル、GHOSTDAGの提案。

Bitcoinのコンセンサスプロトコル

基本的にBitcoinプロトコルでは、10分間隔でブロックが生成され、そのブロックサイズの上限は1MBと決められている。各ブロックは前のブロックを参照するハッシュチェーンを形成し、同じタイミングでブロックが作られチェーンが分岐すると、後ろにより多くのブロックが続いた方が正当なチェーンとなる最長チェーンのルールが適用され、チェーンが1つに収束するようになっている。

Bitcoinでは正直なマイナーが取る行動は、

  1. 最も長いチェーンの先頭のブロックをマイニングする。
  2. ブロックがマイニングできたらすぐに公開する。

安全性の仮定は、

  1. 51%以上が正直なマイナーであること。
  2. ブロックを作成する時間より、ブロックを伝播する時間の方が短いこと。

この仮定の下、ネットワークに参加している各ノードは最長のチェーンをピックアップし、最長チェーンのトランザクションが別のブロックに置き換わる確率は、後続にブロックが続くほど指数関数的に低くなる。

オンチェーンスケーラビリティを上げるのに問題となるのが、↑のブロック作成時間と伝播時間の関係。スケーリングさせる方法は大きく2つあって、1つはブロックサイズを大きくすることで、この場合ブロックの伝播時間は長くなる。もう1つはブロックの生成間隔を短くするというものだが、いずれも均衡を破ることになる。GHOSTDAGで実現しようとすることは、ブロック伝播の仮定を取り除く、もしくは何らかの方法でそれを弱めること。

プロトコル加える変更は最長チェーンの先頭を見るのではなく、有向非巡回グラフ(DAG)を使用するようにし、その構造でProof of Workでマイニングをする。Proof of Workをすることは変わらず、できるだけ早くブロックを公開するというのも変わらない。ただ最長チェーンを選択するのではなく、最も長いk-クラスター(後述)を選択するようになる。また、確率の高い取引セットを持つというのも変わらず、多くの承認を経ることで二重使用の確率は指数関数的に減少する。

プロトコルの変更によって得られるもの

正しく適用されれば安全性を損なうことなくハイスループットが得られるが、フリーライドではない。レイテンシーはもちろん増加する。コンセンサスプロトコルにおいてスループットレイテンシーは避けられないトレードオフであるため、それを回避するのは難しい。承認のため長時間待たないといけないが、安全性が損なわれるよりは良い。

ブロックチェーン全体を保存する方法や、検証時間の改善方法、起動してデータ全体を同期する方法など、他のコンセンサスの問題は解決しない。ここでターゲットにしているのはコンセンサスレイヤーのみ。

PHANTOMプロトコル

最長チェーンを正とする1つのチェーンを維持するデータ構造を、有向非巡回グラフ(DAG)をベースにしたデータ構造に変えたのがPHANTOMプロトコルになる。Bitcoinの場合、ブロックは1つのチェーンとしてリンクするのに対し、PHANTOMプロトコルではブロックはツリー構造でリンクされ、blockDAGと呼ばれる有向非巡回グラフを形成する。

各ブロックは前の単一のブロックのハッシュを参照するのではなく、前の複数のブロックのハッシュを参照するようになる。

f:id:techmedia-think:20181201133230p:plain
Figure 1: blockDAGのサンプル。各ブロックはそのブロックを作る際にマイナーが知っているすべてのブロックの参照を持つ。

表記

blockDAGの要素を指す際に使用する表記:

  • ブロックDAG:G = (C, E)
    Cはブロックを表し、Eは前のブロックのハッシュを指す。
  •  {past(B, G) \subset C}
    Bから到達可能なブロックのサブセット=Bの前に作られたブロックのセットを表す。
    Figure 1では、past(H) = {Genesis, C, D, E} となる。これはHが直接もしくは間接的に参照するブロックでHより先に作られたことが保証される。
  •  {future(B, G) \subset C}
    Bへ到達可能なブロックのサブセット=Bの後で作られたブロックのセットを表す。
    Figure 1では、future (H) = {J, K, M}となる。これはHを直接もしくは間接的に参照するブロックで、Hより後に作られたことが保証される。
  • anticone (B, G)
     {past(B, G) \subset C} {future(B, G) \subset C}に含まれないブロック=直接または間接的にBを参照せず、Bからも直接または間接的に参照されないDAG内のブロックのセット。
    Figure 1では、anticone (H) = {B, F, I, L}となる。これはHとの順序が曖昧なブロックで、この順序を決めるのがコンセンサスの課題(後述)。
  • tips(G)
    入次数が0のブロック=誰からも参照されていないブロック=最新のブロックのセット
    Figure 1では、tips(G) = {J, L, M}となる。リーフブロックで、次のブロックで参照されるようになる。

DAGのマイニングプロトコル

DAGの場合単一のチェーンを伸ばすのではなく、マイナーが作る新しいブロックはtips(G)のすべてのブロックを参照する(Gはブロック作成時にマイナーがローカルで観測しているDAG)。

新しいブロックを発見したら、マイナーはすぐにそのブロックを公開する(ここはBitcoinの場合と変わらない)。

DAGの順序付けプロトコル

DAGのマイニングプロトコルでは、チェーンのTIPを参照する複数のブロックが作られることになる。Bitcoinの場合、最長チェーンルールによりやがて1つになるが、DAGの場合複数のブロックのまま残る。残った際に問題となるのは順序の問題だ。例えば競合する2つのトランザクションがあった場合(二重使用)、どちらのトランザクションを正とするか?Bitcoinの場合最長チェーンルールにより順序が決まり、これを解決する。DAGの場合、2つのブロックができ、そのブロック内に競合するトランザクションがあった場合、どちらのトランザクションが正しいのか決定する必要がある。

PHANTOMプロトコルでは以下の2段階で順序付けを行う。

  1. 最初にブロックをブルーとレッドに分ける。ブルーのセットは協調ノードによってマイニングされたように見えるブロックを表し、レッドのセットは悪意あるノードもしくは戦略的なノードによってマイニングされた可能性が高い異常値のセット。
  2. 次に、ブルーブロックを優先し、レッドブロックにペナルティを与えるようDAGの順序付けをする。

重要なのは1のカラーリングで、これをどのように行うか?

PHANTOMプロトコルBitcoinと同様Proof of Workによりマイニングが行われ、正直なノードはタイムリーに周りのノードと最近のブロックについて連携する能力を持ち、そんな正直なノードがハッシュパワーの50%以上を保持しているという前提を元にしている。Bitcoinと異なるのは、Bitcoinがブロックの作成が通信(伝播)にかかる時間より遅く設計されているが、PHANTOMプロトコルではそのようなことはなく、フォークが自然的に発生する環境下でも正しいブロックのセットが認識されるよう設計される必要がある。

こういった前提の下、ネットワークの伝播遅延時間の上限をDとし、ブロックBが正直なマイナーによって時刻tでマイニングされた場合、t - Dより前に公開されたブロックは必ず時刻tより前にマイナーに届いており、それはpast(B)に含まれる。同様に正直なマイナーはすぐにBを公開するので、時刻 t + D 後にマイニングされたブロックにはBが過去のブロックとして含まれる。結果として、Bのanticoneになる正直なブロックのセットは、一般的に小さく、期間[t - D, t + D]の間に生成されたブロックのみで構成される。proof-of-workの仕組みは、長さ2・Dの間隔で作成されたブロックの数は通常あるk > 0未満であることを保証する。要するに、正直なノードによって作成されたブロックのセットは、well-connected = anticoneが少ないセットとなる。

つまり正直なノードが発見したブロックをすぐに公開し、かつ周りから受け取ったブロックを組み込んでマイニングしているのであれば、そうやって作られたブロックは多くのTIPへの参照を持ち、多くの後続ブロックから参照が行われるブロック=well-connectedなブロックになる。そのため、そうでないブロックは攻撃者によって作られたブロックであると。この時のセキュリティパラメータがkで、Figure 2はk=3とした場合、DAGのカラーリング結果になる。

f:id:techmedia-think:20180821153359p:plain
Figure 2:与えられたDAG( A, B, C, D, F, G, I, J ブルーカラー)内のブロックの最大3クラスターの例。

kはPHANTOMプロトコルの相互接続パラメータで、k = 3の場合、anticoneのサイズは3を超えてはならない。Figure 2を見てみると、このルールに違反しているのがレッドカラーのブロックで、ブロックEのanticoreは(B, C, D, F, G, I)で3を超えている。これらのブロックがEを参照しないのは、おそらくEを作成したマイナーによってEが保留されていたため。同様にブロックKのanticoreは(B, C, G, F, I, J)で、悪意あるマイナーは既に(B, C, D, G)を受け取っているにもかかわらず、その一部を参照していないという点でマイニングプロトコルに違反している。

ということで、blockDAGの順序付けは以下のように行う。

  1. DAGが与えられた場合に、上記k-クラスタルールを適用してブルーセットを決め、その補足セットとしてレッドセットを使う。
  2. いくつかのトポロジカルなソートに基づいてブルーブロック間の順序を決定する。次に任意のブルーブロックBについて、Bの直前の順序にまだ順序付けされていないpast(B)のレッドブロックを追加する。レッドブロックもトポロジー的に追加する必要がある。

そのため、Figure 2の小さなDAGの順序はA, D, C, G, B, F, I, E, J, H, Kとなる。

こうやってDAG構造の各ブロックの順序が決められるが、1つ大きな問題がある。成長し続けるDAGにおいて、DAG内の最大k-クラスターを見つけるのはNP困難な問題だということ(最良のセットを見つけるのに指数関数的な計算量がかかる)。このためPHANTOMプロトコルを適用するのは実用的ではなく、代わりにgreedyアルゴリズムを導入したPHANTOMプロトコルの変形であるGHOSTDAGプロトコルが提案されている。

k = 0 == Bitcoin

ちなみにk-クラスターの値を0に設定した場合、そのブロックはanticoneを持たないブロックとなり、この設定の下ではPHANTOMプロトコルやGHOSTDAGプロトコルはツリーではなくBitcoinのようにチェーンを形成するようになる。

そういう意味では、SatoshiのBitcoinはPHANTOMプロトコルにおけるk=0のクラスターであるとも言える。

GHOSTDAGプロトコル

PHANTOMと同様、GHOSTDAGプロトコルは(選択されたクラスタ内のブロックである)ブルーと(クラスタ外のブロックである)レッドのブロックのカラーリングを誘発するk-クラスターを選択する。ただし、GHOSTDAGプロトコルでは最大のk-クラスターを見つけるのではなく、greedyアルゴリズム=貪欲法を使って大きなk-クラスターを見つける。このアルゴリズムによって見つけたクラスターは最大のk-クラスターではないものの、十分に大きなものになる。基本的にk-クラスターは正直なノードであると考えられるグループで、最大のk-クラスターを探す場合、正直なマイナーがネットワークの過半数でブロックの大きなセットを生成しそれぞれのブロックのanticoneは小さいと仮定しているため、貪欲法はそれを検出するのにうまく作用する。

  • 各ブロックは前のブロックの中の1つから最もweightの重いk-クラスターを継承する。
  • ブロックを貪欲に追加する(k-クラスターの範囲内で)

ブロックを追加する際にその時点の最良のTIP=これまで最大のブルーセットを持つ  {B_{max}}を継承し、  {B_{max}}の過去に無いブルーセットのブロックに追加することで、DAGのブルーセットを構築する。これでk-クラスター特性は保持される。

GHOSTDAGの基本的な考え方は重いk-クラスターをブロック単位で継承しながら徐々にDAG構築していくことで、最大k-クラスターを発見するというNP困難な問題を回避している。この辺りは同じくGHOSTプロトコルを採用しているEthereumと似ている。

GHOSTDAGの順序付け

GHOSTDAGの各ブロックの最終的な順序付けは、カラーリングの手順と同様の経路に従う。最初にpast( {B_{max}})のブロックに対して  {B_{max}}の順序を継承し、次に  {B_{max}}自体をその順序に追加し、最後にpast( {B_{max}})にないブロックをトポロジカルな順序付けに従って追加することで、blockDAGを順序付けする。

マイニング報酬

マイニングの報酬については、k-クラスター内のすべてのブロックに報酬を与えるようになる。それがSelfish-Miningへの耐性となる。Selfish-Miningはブロックの1つをチェーンから外し、正直な参加者へ報酬を渡すのを拒否しようとする試みになるが、ブロックを隠し持つことで、そのブロックのanticoneは増えていくことになり、後からそのブロックをk-クラスター内に入れるためには、より多くの計算量が必要になる。

Bitcoin CoreはなぜECDSA署名にLOW Rを適用するようになったのか?

Bitcoinでは、送金時にトランザクションにセットする署名に、現在ECDSA署名を採用している。

秘密鍵x、対応する公開鍵をP = xGとした場合、メッセージにに対するECDSA署名は以下のように作成する。

署名の作成

  1. ランダムな値kを選択する。
  2. R = kGを計算する(Rが楕円曲線上の有効な点でない場合の選択からやり直す)。
  3. 点Rのx座標をrとする。
  4.  {s = \frac{H(m) + rx}{k}} を計算する。
  5. 計算した(r, s)のペアが署名のデータとなる。

これは標準的なECDSAの署名ルールだが、Bitcoin Coreの場合、ECDSA署名作成時に以下のようにいくつかルールを加えている(コンセンサスルールではないが、標準トランザクションルールに該当するものはある)。

LOW Sルール

BitcoinではSegwitの導入によりTXIDに関するmalleabilityは排除されたが、ECDSAの署名自体にはmalleabilityが存在する。署名値(r, s)のsの値をマイナスにした -s mod nを使ってもsの値は異なるが正しい署名と判断される。このため、Segwitによりwitness領域に移動した署名データのs値を有効な書き換えることは可能になってしまうので、Bitcoin CoreではLOW_Sルールというのを設けている。

このルールでは、sの値は最大でも曲線の位数を2で割った値以下でなければならないというもので、これによりsを利用したmalleabilityを除外する。この仕様はBIP-146としても定義されている↓

techmedia-think.hatenablog.com

決定性署名

Bitcoin Core(libsecp256k1)では、トランザクションの署名を生成する際に、kの選択を決定論的に行うRFC 6979の決定性署名のルールが適用されている。このため、kはランダムに選択されるのではなく、トランザクションのデータから決定論的に導出される。

techmedia-think.hatenablog.com

この仕組みにより、実装の誤りによりkの生成に偏りが発生するようなことを防ぐことができる。

署名のフォーマット

計算した署名データをトランザクションにセットするわけだが、このときBitcoinではDERエンコードした値をセットする。フォーマットの詳細は

techmedia-think.hatenablog.com

に記載しているけど、簡単に言うと

0x30 データ長 0x02 rのデータ長 R 0x02 sのデータ長 S SIGHASH_TYPE

という構成のデータになる。

そして今回新しいルールが実装に追加され↓、Bitcoin Core 0.17.0でリリースされた。

LOW R

github.com

ECDSAの署名自体にmalleabilityの問題があり、それを解決するのにLOW Sルールを適用するのは理解できるが、このLOW Rのルールは何を意味するのか?

LOW Rの意図

まず署名データは↑のDERフォーマットであることから、

  • 0x03
  • データ長
  • 0x02
  • rデータ長
  • 0x02
  • sデータ長
  • SIGHASH_TYPE

で7バイト使い、残りはrとsの値になる。このrとsの値はそれぞれ256 bitの値=32バイトのデータになるが、DERフォーマットではこれを符号付き整数として扱うため、最上位オクテットが0x80〜0xffの場合、そのままでは負の数として扱われてしまうので、先頭に0x00を付与して正の数とするため1バイト追加され33バイトになる。

sのデータについては↑のLOW Sルールがmalleabilityの解決のため導入された結果、32バイトが標準トランザクションルールとして強制されるが、rにはこのルールが無いため、選択されたkの値によって33バイトになったり32バイトになったりする。

まぁ、そもそもDERフォーマットが効率的でないというのもあるんだけど、既にSatoshiの時代から決まっているのでしょうがない。

今回の変更の目的は、rにも同様のLOW Rルールを適用することで、rのデータ長が常に32バイトになるようにし、データ容量を削減しようというものだ。データを削減すると言ってもrのDER形式の署名データが33バイトになるケースが1バイト分削減されるだけで、大して意味のある削減じゃないかとも思うが、実際Bitcoinの1日のトランザクションで考えると数千バイトの削減効果になるとされていて結構大きい(チリツモ的な)。

LOW Rの適用方法

基本的にrの値は、↑のECDSAのプロトコルからも分かるように、本来は乱数kを秘密鍵とした楕円曲線上の点であり、Bitcoin Coreはこれを乱数生成器の脆弱性を考慮し、トランザクションデータから決定論的にkを導出するようにしている。

R = kGで計算されるので、この結果がLOW Rでない場合、kの選択をやり直す必要があるんだけど、Bitcoinの場合トランザクションデータから決定論的にkを選択してるのにどうやってやり直すの?という疑問が生じるが、これはRFC 6979に答えがある。

RFC 6979は決定論的にnonce kを選択する仕様だが、追加のエントロピーを指定するオプションがあり、このオプションの値を期待するrを得るまでのカウンタとして利用することで、LOW Rを選択できるようにしようというもの。順番にインクリメントするカウンタなので、決定論的にnonceを生成するという特性も維持される。

RFC 6979のオプションというのはおそらく以下の3.6章の内容だと思われる。

 Additional data may be added to the input of HMAC, concatenated
after bits2octets(H(m)):

   K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')

A use case may be a protocol that requires a non-deterministic
signature algorithm on a system that does not have access to a
high-quality random source.  It suffices that the additional data
k' is non-repeating (e.g., a signature counter or a monotonic
clock) to ensure "random-looking" signatures are
indistinguishable, in a cryptographic way, from plain (EC)DSA
signatures.  In [SP800-90A] terminology, k' is the "additional
input" that can be set as a parameter when generating pseudorandom
bits.  This variant can be thought of as a "strengthening" of the
randomness of the source of the additional data k'.

3.2.dのkの生成はもともと↓で

  K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1))

3.6の記述では、追加のインプットとしてk'を付加しているのが分かる。

ということで、k'をカウンタとしてインクリメントしながらLOW Rになるまでnonceの選択を繰り返すよう実装すればいい。

まぁデメリットは、LOW Sルールは簡単にsの値を変換できるものの、rの方は↑のように署名の計算コストが高くなるという点かな。

また、今のところ標準トランザクションルールにはなってないようなので、LOW Rでなくともトランザクションはリレーされる。

Statechains: Off-chain Transfer of UTXOs at Scaling Bitcoin 2018

Scaling Bitcoin 2018復習シリーズ。今回はRuben Somsenによる「Statechains: Off-chain Transfer of UTXOs」の発表について見てみる。

youtu.be

書き起こしは↓

http://diyhpl.us/wiki/transcripts/scalingbitcoin/tokyo-2018/statechains/

ホワイトペーパー(7ページほどなので読みやすい)↓

https://onedrive.live.com/?authkey=%21AOKxfuPbcIsqQTk&cid=C6C37F8DDEF5BDF9&id=C6C37F8DDEF5BDF9%2136661&parId=C6C37F8DDEF5BDF9%2136660&o=OneUp

Statechainとは?

StatechainはPayment Channelとは異なるコンセプトのレイヤー2のスケーリングソリューションになる。Payment Channelの場合、マルチシグにデポジットした金額を上限として、参加者の残高をオフチェーントランザクションで更新していくモデルだが、Statechainは基本的にはUTXOの所有権をオフチェーンで譲渡していくモデルのソリューションになる。

そのため、UTXOの量が例えば1 BTCだった場合、転送できるのは1 BTCまるごとで、1 BTCを分割して0.5 BTC分だけ渡すといったことはできない。0.5 BTCを支払いたい場合は、事前に1 BTCと0.5 BTC×2のUTXOを交換する方法を取るが、適切な交換をするためにはStatechain上のコインの流動性が求められ、適切な交換は意外と難しいんじゃないかと思う。

Statechainを運営するエンティティ

StatechainはオフチェーンでUTXOの所有権を転々と移動させていくプロトコルだが、この台帳を維持し、Statechian上でのUTXOの所有権の移動をサポートする存在としてStatechainを運営するエンティティと呼ばれるものが存在する。Federated SidechainとかのFederationに近いが、Federated Sidechainの場合Federationが機能しなくなると、サイドチェーン上のコインが動かせなかったり、それをメインチェーンに戻したりできなくなるが、そういったリスクはなく、エンティティが機能しなくなっても、Statechain上のUTXOを最終所有者がオンチェーン上で償還できるようになっている。

Statechainを構成する技術要素

このStatechainは以下の技術要素を組み合わせて実装するプロトコルになっている。そのため、プロトコル理解のためには事前に各技術要素について知っておいた方が良い。

Statechainのプロトコル

以下の説明では、StatechainのエンティティをAとする。

Statechainへのコインの移動

ユーザーBがコインをStatechainに移動したい場合、BはエンティティAと協力して、eltooスタイルのチャネルを作成する。この時、Bは自身の鍵を使うのではなく、transitory keyと呼ばれる新しい鍵を生成する(この鍵をXと表記する)。このtransitory keyはこの後、Statechain上でコインの所有権を移動する際に、新しい所有者にも共有される鍵になる。Bは自身が持つUTXOのコインをAとXの秘密鍵の情報がないとアンロックできないスクリプト宛に送金する。

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

オンチェーン上にはAとX間でロックされたコインがあり(eltooのFunding Tx)、このUTXOをインプットとしたオフチェーントランザクション(eltooのTrigger Tx)が作成されるものと思われる。このセットアップ段階ではオフチェーントランザクションのアウトプットのアンロック条件はいかのいずれか。

  • AXでアンロック可能
  • タイムロック付きでBでアンロック可能

ホワイトペーパーには詳しいコントラクトのコードは掲載されてないけど、LNのように両者の残高を管理するのではなくUTXOの所有権を移動するだけなので、eltooで定義されているSettlement Txは不要と思われる。

また、Statechain上ではこの初期段階ではBがこのUTXOの所有者となる。

※ ここで従来のLNのコントラクトではなくeltooのコントラクトが使われるのは、Statechainの場合、UTXOの所有者がどんどん変わっていくので、参加者が2者だけでなく多数になり、不正が行われた際に誰にペナルティ分を支払うかというのが問題になる。eltooの場合ペナルティではなく最終状態が必ず適用される仕組みなので、Statechainの最終所有者にコインが渡るモデルと親和性が高い。

Statechainでコインを送付

Statechian上にコインをデポジットしたら、今度はStatechain上でコイン(UTXO)を送付する=UTXOの所有権の移動。ユーザーBはデポジットしたUTXOをユーザーCに送る。

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

Statechain上のUTXOの所有権がB→Cに移り、新しいオフチェーントランザクションが作成される。このオフチェーントランザクションのタイムロック条件のコインの所有者はCになる。

Statechain上でB→Cに所有権を移動する際は、Bの署名が必要となる。この署名がBがCへの所有権の移動を認めた証拠となる。またCがその移転を認めるという意味でCの署名も必要となる。この両者の署名の作成がアトミックに行われるのを保証するためにAdaptor Signatureを利用する。(この時使われるAdaptor Signatureは、A、B、Cそれぞれが共有シークレットを生成する変種のAdaptor Signature)またこの時作成したAdaptor SignatureからCがtransitory key Xの秘密鍵を知るようになる。

このようにStatechain上での所有権の移転は、エンティティAと現在の所有者B、次の所有者Cによってアトミックに行われる。この時所有権を更新したオフチェーントランザクションも新たに作成されるが、ここでもAdaptor Signatureが利用され、Statechian上で所有権の移転を認める署名が公開されると、その署名から所有権をCに更新したオフチェーントランザクションの有効な署名も作成されるようになるみたい。このためBitcoinサイドとStatechainサイドのトランザクションにもアトミック性が保証される。

Cへのコインの所有権が移動すると、transitory keyの値を知っているのはBとCとなり、Cは次のユーザーにUTXOの所有権を送付することができるようになる。

このようにStatechain上ではデポジットされたUTXO毎に、エンティティによって履歴の管理及び、所有権の移動がサポートれる。

エンティティのフェデレーション化

エンティティAについて1つの鍵のように記載されているが、これを複数人のフェデレーションにすることもできる。Schnorrの集約機能を利用して(おそらくプラス秘密分散)、実運用では8-of-10のようなフェデレーションによる合意の仕組みが用いられると思われる。

不正行為

Statechainを運営するエンティティは、すべての転送が記録される公開台帳を持つことが期待されていて、これは不正な引き出しに対する証拠として機能する。台帳上で不正な引き出しが競合するか、引き出しの際のStatechainのフォークが発生した場合、ユーザーはトランザクションがある時点でStatechainに含まれているという証拠を保存していれば、両方のケースで詐欺の証明ができる。従来のブロックチェーンと異なり、全てのUTXOはコインをマージしたり分割したりできないので、他のUTXOの履歴とは独立した履歴を持っている。そのため気になるUTXOの履歴だけを選択して検証し追跡できる。

コインの移動には常にStatechainのエンティティAの許可と、(UTXOを保有している)transitory key保有者の許可が必要になる。Statechainのエンティティは最後のtransitory keyの所有者と協力しなければならず、そうでない場合、詐欺の証拠を生成することになる。↑のようにAdaptor Signatureを利用しているのは、コインの移動に伴い参加者の署名が存在することを保証するため。

もし前の所有者と共謀して現在の所有者にだまって別の所有者にコインを送付しようとした場合、Statechain上でその証拠となる署名が残ることになり、現在の所有者はそれを詐欺の証拠として提出することができる。当然、そういった行為をしたエンティティのレピュテーションは下がる。

最悪のケース

最悪ケースは悪意あるエンティティが多くのUTXOのtransitory keyを何らかの方法で入手した場合で、この場合オンチェーン上のコインをエンティティAが盗むことができる。このような盗難が発生した場合、transitory keyを盗まれていないユーザーは、すぐにBitcoinのオフチェーントランザクションをブロードキャストして資金を償還することで被害を最小限に留める。

当然こういった行為を行ったエンティティのレピュテーションは著しく低下する。また実際に秘密鍵に該当する鍵はユーザー側が管理しているので、漏洩はユーザー側の管理次第になるが、Statechain上でのUTXOの移動が続くとそれだけtransitory keyを知るユーザーが増えるので、Statechain上での履歴がある程度長くなったら一度オンチェーンに戻す方が鍵管理の安全性上は良い。

逆にtransitory keyさえ漏洩しなければ、エンティティが勝手にコインを移動することはできない。たとえ裁判所からの押収命令があったとしても技術的に押収することは不可能。

Statechainの欠点

Statechainの欠点は良くも悪くも、UTXO単位の送金しかできないという点で、必要な金額にあわせてUTXOをマージしたり分割したりできないという点。また少額のUTXOの場合、そのUTXOをオンチェーンで償還しようとした場合の手数料の方が高くなるといったことも考えられることから、ある一定量以上のUTXOでないと受け入れられず、マイクロペイメントなどは無理だろう。

Lightning Network on Statechain

Statechain上のUTXOの送付先をボブへ送付するのではなく、ボブーキャロルのマルチシグに送付することで、Statechain上でLighting Networkをセットアップするが可能になる。

従来のLighting Networkと違うのが、チャネルはオフチェーンで開かれるので、チャネルのオープン/クローズ、Splicingを非常に安価に行うことができ、残高調整が行いやすいという点。

Graftrootの利用

Graftrootが利用できるチェーンであれば、資金をオンチェーンで償還する際の自由度が上がる。ハードフォークなどでチェーンが分岐した場合、StatechainにデポジットされたUTXOは2つのチェーンで同時に存在していることになる。Statechainのエンティティがどちらのチェーンを採択するのかという問題が浮上するが、エンティティは最新の所有者からの要求があれば、その所有者が望む条件のスクリプトへの署名を提供することで、別の条件を使ってオンチェーンでの償還を行うことができる。それがエンティティが運用すると決めたチェーンでなくても。

所感

  • UTXOの所有権の移転がベースのモデルなので実際の決済などには使いづらそう(ぴったり一致するUTXOはそうないと思うし、それを揃えるために交換が必要でその交換もちゃんとした額で成立するのは難しそう)。
  • LNをこういったオフチェーントランザクションをベースにチャネル構築することで、チャネル開閉やSplicingのコスト、時間を短縮できるようになるのは面白い。
  • Statechainを運営するエンティティのインセンティブはどこにあるんだろう?
  • Adaptor Signatureが数パターンの使われ方がされているので、もう少し詳しいプロトコル解説がほしいところ。

送信者−受信者間で簡単なコインジョインを行うBustapayプロトコルを定義したBIP-79

Bitcoinトランザクションはインプットに送信者のUTXOが、アウトプットに受信者のアドレスと送信者のお釣りがセットされる構成が一般的。ブロックチェーンの分析をする企業でよく採られるアプローチでは、こういうトランザクションの場合、インプットのUTXOは全て同じユーザーのものであるという仮定に基づいていて、その仮定の元、ブロックチェーン上のトランザクショングラフを解析し、ユーザーや企業の動向を分析しようとしている。

今回新しく提案されたBustapayプロトコルは、コインジョインといっても大量のインプット/アウトプットを集めてコインを撹拌しようという目的ではなく、トランザクションのインプットは全て同じユーザーのものという上記ブロックチェーンの分析の仮定を崩すための送信者−受信者間の簡単なコインジョインプロトコルを定義したもの↓

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

同様の目的で以前BlockstreamがPay to EndPoint(P2EP)というプロトコルを提案していた↓

techmedia-think.hatenablog.com

ただBlockstreamのP2EPの場合、受信者が所有するUTXOの情報に関するプライバシーを守るため、フルノードにアクセスしてダミーのUTXOををセットしたダミートランザクションを多数用意し、送信者との間で署名のやりとりをするなど、単一の決済プロトコルとしては重かった部分をBustapayでは削ぎ落としてシンプルになっている↓

Abstract

Bitcoinトランザクションを普通に作成すると、望ましくない情報が漏れることが多い。結果として、効果的なブロックチェーン分析技術により、有用な通貨に期待される重要な特性が危険にさらされる。

Bustapayは、支払いの送信者と受信者が、両者の直接的な利益を守るためいくつかの分析の仮定を破壊する方法で、両者がBitcoinトランザクションに協力して署名するための簡単で実用的なプロトコルだ。さらに、Bitcoin決済をする事業者にとって一定の問題であるUTXOセットのサイズを管理するのを手助けするため、受信者に重要な量の制御を与える方法を取る。

動機

最も強力なブロックチェーン分析のヒューリスティクスの1つは、トランザクションのインプットの全てが、(伝統的なコインジョイン独自の構造やマルチシグの使用など)別で知られている場合を除いて、単一のユーザーによって制御されているという仮定だ。他の手法(特にお釣り用のアウトプットの推測)と組み合わせることで、予想以上に正確な追跡が行われ、Bitcoinの参加者は容認できない個人的に、ビジネス上および財務上のリスクにされされ、Bitcoinの利便性と代替性を損ない、最終的に有用な通貨として機能する能力を損なうことになる。

しかし我々は、送信者と受信者のコインジョインでこれらの仮定を壊すことができる。コストのかからないスパイ/DoS攻撃を防ぐため、プロセスを開始する際に送信者に完全に有効な伝播準備のできたトランザクションの提供を求め、送信者がコインジョインを完了しない場合に受信者がそのトランザクションをブロードキャストできるようになっている。最も有望なことに、Bustapayのトランザクションは識別可能な構造を持たないため、任意のネットワーク分析は与えられたトランザクションがBustapayのトランザクションかどうか分からないため、分析のモデル全体の信頼性が損なわれ、Bitcoinのエコシステム全体に肯定的な外部性がもたらされる。

Bustapayのトランザクションは、受信者のUTXOの数を増やすことなく、実際に受信者に自分のUTXOセットを良いように管理する機会を与え、それは通常の支払い時の取引でのみ行われる。大規模なUTXOセットは、よく問題になり高価で、頻繁にプライバシーを破壊する統合を必要とする。Bustapayは、クラスタ化の仮定を破壊する以外に、送信量の難読化レイヤーも提供する。

この仕様では、導入を促進するにあたってシンプルさが1番重要であるとの前提で、複雑さと潜在的に有用な拡張を避けてきたことが注目に値する。

概要

Bustapayの支払いは送信者から受信者に対して行われる。

手順1:送信者は受信者に支払うBitcoinトランザクションを作成する

このトランザクションは全てのインプットに対してsegwitを使用し、完全に有効で署名済みである必要がある。トランザクションはネットワークに伝播できる状態であること(ただしこの段階ではブロードキャストされない)。

手順2:送信者は受信者にテンプレートトランザクションを送る

これはbustapay urlに対して、HTTPのPOSTリクエストで行われる。

手順3:受信者はトランザクションを処理し、部分的に署名されたコインジョインを返す

受信者はトランザクションを検証し、自身に支払うようにする。受信者は1つ以上のインプットを追加し(contributed inputs)、(オプションで)受信者自身に支払うアウトプットを増額する(一般的にcontributed inputsの合計分増額する)。こうして受信者が送信者に返す、部分的なトランザクションが作成される。これは送信者に自身のインプットに再署名してもらう際などに呼ばれる。

手順4:受信者は検証、再署名、Bitcoinネットワークへの伝播をする

受信者は部分的なトランザクションが正しくかつ悪意なく変更されていることを検証し(潜在的に信頼できない通信シャネルも使用できるため)、元の自分のインプットに最署名し最終的なトランザクションBitcoinネットワークにブロードキャストする。

手順5:受信者はBitcoinネットワーク上で最終トランザクションを確認する

受信者がネットワーク上で最終トランザクションを確認し(そして十分な承認数あるか)、送信された金額は通常の支払いのように見える(ネットワーク上で確認する金額と実際の送金額は異なるが)。タイムアウト後に受信者が最終トランザクションを確認できない場合は、支払いが確実に行われるように元のテンプレートトランザクションをブロードキャストし、強力なアンチDoSの仕組みを機能させる。

仕様

送信者にBustapayトランザクション送信先を知らせる標準的な方法は、BIP-21エンコードされたアドレスを使用する方法だ。この時パラメータとしてキー:bpu(BustaPayUrlの短縮表記)を使用する。アドレスの例は以下のようになる。

bitcoin:2NABbUr9yeRCp1oUCtVmgJF8HGRCo3ifpTT?bpu=https://bp.bustabit.com/submit

URLは短くしておくことを強く推奨する。

送信者がテンプレートトランザクションを作成するにあたっては、segwitインプットだけが使用できるという点を除いて、通常の送金トランザクションを作成するのと変わらない。送信者はBIP125(オプトインのFullRBFのシグナリング)と同様、通常よりやや積極的な手数料レートの使用を勧められるが、どちらも厳密には要求されない。

テンプレートトランザクションは、Bustapay URLにHTTP POSTでバイナリエンコードされたBODYとして受信者に送信する必要がある。

受信者はテンプレートトランザクションの検証で応答する。トランザクションに問題がある場合、もしくはトランザクションに不満がある場合(手数料が低すぎるなど)、HTTPレスポンスコード422を使って、拒否理由をユーザーに伝えるため人が読める形式の文字列と一緒にレスポンスを返す。

受信者がトランザクションを拒否した場合、それをネットワーク上に伝播してはならない。しかし、送信者は(どのエラーが出たかに関わらず)受信者がいつでもテンプレートトランザクションをブロードキャストできることを認識することが重要だ。クライアントはそのため受信者の意思に応じて行動する必要がある(再調整するか、トランザクションを伝播だけするか)。

Contributed Inputの選択

受信者はすくなくとも1つのインプット(=contributed input)をトランザクションに追加しなければならない。受信者のインプットがない場合、500 Internal Server Errorを使用する必要があり、クライアントは通常通りトランザクションを送信できる(もしくは後でやり直す)。一般的には、1つのcontributed inputのみを追加することを推奨するが、複数のインプットを追加するのが便利なケースもある。

受信者のUTXOセットを列挙させるために同じトランザクションのバリエーションを継続的に送信される攻撃を防ぐために、トランザクションに同じインプットがあった場合は、常に同じcontributed inputを返すのが重要だ。

可能であれば、できるだけ多くの他のトランザクションインプットと同じタイプのcontributed inputを選択する努力を受信者がすることが強く望まれる。

アウトプットの調整

トランザクションにインプットを加えた後、受信者はcontributed inputの合計量分、自身宛のアウトプットの合計(手数料を追加したい場合はその分を差し引いて)を追加するよう調整したい。しかし唯一の厳しい要件が、受信者は決してインプットを追加or削除してはならず、アウトプットの量を減らしてはならないという点だ。

部分的なトランザクションの返却

受信者は部分的なトランザクションの全てのcontributed inputに署名する必要がある。部分的なトランザクションはこの時点で有効なトランザクションではなく、送信者により再署名される必要があるため、元のテンプレートトランザクションから全てのwitnessを削除する。受信者は部分的なトランザクションをバイナリエンコードしたHTTPレスポンスとしてレスポンスコード200で返す。

送信者の検証

送信者は部分的なトランザクションについて重要な検証をしなければならない。送信者は以下を検証しなければならない。

最終トランザクションの作成

部分的なトランザクションの検証後、送信者は全てのトランザクションに署名し、最終トランザクションを作成する。送信者は受信者が送信者の別のインプットに署名するよう騙そうとしていないか慎重に注意することが重要だ。送信者はテンプレートトランザクションに存在するインプットにのみ署名する必要がある。送信者が慎重でない場合、受信者は送信者が実際に所有しているUTXOをcontribute inputに入れ、送信者が盲目的に全てに署名するという希望を持っているケースが考えられる。

トランザクションの公開

最終トランザクションが作成されると、送信者はそれを直接Bitcoinネットワークに送信する必要がある。送信者が妥当な時間内(例えば1分間)にトランザクションを送信しない場合、受信者は重要なアンチスパイ/アンチDoS戦略としてテンプレートトランザクションを公開すべきである。送信者はまた、受信者が不当にトランザクションの手数料を下げた(例:トランザクションサイズは増えたけど、手数料が十分でない)と判断した場合、最終トランザクションでなくテンプレートトランザクションを公開することもできる。最終トランザクションをネットワークに公開した後でも、最終トランザクションが承認されずテンプレートトランザクションの方が手数料が高い場合、(RBFのアドバンテージを取り)テンプレートトランザクションの公開を検討することができる。

実装の注意点

Bustapayの支払いを実装したいと思っている人のために、ここに受信者のためのいくつかの注意がある:

  • トランザクションがmempoolに適しているかどうかは、bitcoin core 0.17+でtestmempoolacceptを使うことで簡単にチェックできる。
  • TXIDによりトランザクションの追跡は不確か。正気を保つために全てのインプットが確実にsegwitであること。しかしトランザクションを検証しない限り、segwitはTXIDのmalleabilityを防げない。そのため、少なくともtestmempoolacceptを使っていることを確認すること。
  • Bustapayはあなたが入金アドレスを持っているかどうかを照会するのに悪意あるユーザーによって悪用される可能性がある。既に使用済みの入金アドレス宛に支払うBustapayトランザクションを受け入れないこと。
  • どのUTXOのユーザー、あなたのどのUTXOを明らかにしたのかマッピングを保持する必要がある。同じUTXOで照会があった場合、以前明らかにしたのと同じUTXOを返す必要がある。
  • BIP-69に基づいてトランザクションが既にソートされているかどうかチェックし、ソートされているのであればそのままにする。ソートされていない場合インプット/アウトプットをシャッフルする。
  • 参照実装はhttps://github.com/rhavar/bustapayで公開されており、bitcoin coreウォレットのRPC呼び出しのラッパーとして機能する。
  • 送信者は、受信者が送信者のコントロール下にあるインプットを追加し送信者が盲目的にそれに署名することを期待する攻撃に対して注意しなければならない。

後方互換

Bustapayはオプションのペイメントプロトコルで、後方互換性の問題はない。実際に、通常のトランザクション処理に加えてサポートできる。これは通常のBitcoinトランザクションに戻す必要があるため。

所感

P2EPでもBustapayでも上記仮定を崩すウォレットが1つでも利用可能になっているというのが重要で、実際にこれらのプロトコルが使われていないとしても(使われているかどうかはトランザクション見ても分からないので)、これらのプロトコルが使われている可能性があるということだけで上記の仮定を崩すことに繋がると思われる。

あと(P2PEも一緒だけど)副次的な効果として受信者のUTXOセットを減らせるというのも良いね。

2P-ECDSA: Fungible 2-of-2 MultiSigs for Today's Bitcoin at Scaling Bitcoin 2018

Scaling Bitcoin 2018 復習シリーズ。今回はLightning LabsのConner Fromknechtによる「2P-ECDSA: Fungible 2-of-2 MultiSigs for Today's Bitcoin」の発表↓

youtu.be

書き起こしは↓ scriptless-ecdsa

前半はLindellベースの2者間のECDSA署名プロトコル↓の解説と、後半はそれを実際にLightning Networkに適用する際の考慮事項についてまとめた発表になってる。

techmedia-think.hatenablog.com

あとところどころPedroの話が引用されてるけど、それはこのセッションの前に発表されたMulti-Hop Locksの話↓

techmedia-think.hatenablog.com

2P-ECDSAの歴史

  • 2016年にBlockstreamのAndrew PoelstraがSchnorrベースのScriptless Scriptを発表
    これにより共有データ(通常ペイメントハッシュ)をブロックチェーン上で明らかにすることなく、クロスチェーンでコインのスワップすることが可能になった。チェーン間でトランザクションがリンクされることもない。彼はその後、LNのハッシュプリイメージのチャレンジをこれで置き換える公正を提案する。
  • 2017年3月、PedroがMulti-Hop Locksの発表で言及したように、LNの各ホップで支払い情報がランダム化されることを保証するようになった。全ての決済は伝播された順に決済される。
    • これによりプライバシーが向上
    • Pedroの言うようなWormhole Attackへの防御になる
  • 2017年末、Yehuda Lindellは、効率的な2p-ECDSA署名プロトコルを発表した。このプロトコルは現在のBitcoinのノードと完全な下位互換があり、どのノードもこの署名検証を行える。また現在存在するP2PKHやP2WPKHで利用可能。
  • 2018年4月、PedroがLNのホップの無相関化のフレームワークを形式化したMulti Hop Locksをリリースした。これには2p-ECDSAに基づく、Scriptless Scriptの構築が含まれている。また経路内の各ホップはECDSAをベースにしてもいいし、Schnorrをベースにしてもいい。つまり経路内にECDSAとSchnorrが混在していても問題ない。そのため、現在のLNにECDSAベースのMulti Hop Locksを導入した後、後でSchnorrがBitcoinに導入されたら、LNのネットワークを断片化することなくスムーズに移行することができる。
  • 現在、いくつかの2p-ECDSAを研究している。

2p-ECDSAの概要

  • アリスは秘密鍵aと対応する公開鍵A = aGを持っている。
  • ボブは秘密鍵bと対応する公開鍵B = bGを持っている。
  • お互い公開鍵は共有しており、公開鍵Q = (ab)G = aB = bAを計算する。Qの対応する秘密鍵ab
    • 二人ともabのデータは知らない。 *二人で協力してQに対して有効なECDSA署名を生成する。

有効なECDSA署名を生成するにあたって、2つのアルゴリズムが必要になる。

  • KeyGen(オフライン)
    オンラインのSignプロトコルに参加するためのアリスとボブのセットアップ。コスト的に高価だが実行するのは1回だけ。
  • Sign(オンライン)
    効率的だが2回の往復が発生するオンライン署名プロトコルで、Qに対して有効なECDSA署名を生成する。

KeyGen

  1. 基本的にアリスとボブはそれぞれが持つ公開鍵と、その公開鍵の離散対数(秘密鍵)を知っていることの証明を交換する。これは標準的なShcnorr署名のデータを確認することで、その公開鍵に対応する秘密鍵を持っていることを確認できる。
  2. アリスはPaillier暗号用の鍵ペア(PSK, PPK)を生成する。またアリスがボブを騙すことが無いよう、鍵PPKが {N= p_1 * p_2} {p_1} {p_2}で構成されていることを証明するゼロ知識証明を提供する。
  3. アリスは公開鍵PPKで秘密鍵を暗号化し、暗号テキスト {c = Enc_{PPK}(a)}を作成する。
  4. アリスは(PPK, c)をボブに送る。
    • ボブは暗号テキストを受け取るだけで、元の値のサイズを知ることができないため、アリスはそれが小さいことを証明する必要がある。この証明のため、一緒に暗号テキストcの値が { 0 < Dec_{PSK}(c) < q}の範囲内であることをゼロ知識証明を提供する(qは曲線secp256k1の位数)。実際、暗号テキストは元の値よりはるかに大きなデータになる。
    • そしてcにアリスの秘密鍵を含まれていること =  {A = Dec_{PSK}(c) G} を証明する。
    • Lindellはこれを証明するのに新しいゼロ知識証明を発明しなければならず、2つの異なる暗号システムを混在させていた。
  5. ボブは、受信した証明全てを検証し、Q = bAを計算する。
  6. アリスはQ = aBを計算する。

KeyGenの結果、

  • アリスは2p-ECDSAの公開鍵Q = abG秘密鍵(a, PSK)を持つ。
  • ボブは2p-ECDSAの公開鍵Q = abG秘密鍵(b, c, PPK)を持つ。

Sgin

Paillier暗号の特性

なぜ、KeyGenでPaillierを使っているのか?というと、主な理由は、ECDSAではScnorrのように公開鍵や署名の加算ができない(公開鍵や署名が線形性を持っていないため)。このため非対話型の集約に適していない。ただ、Palliler暗号データは以下のような部分的な準同型の性質を持っている。

  • 加法準同型性(暗号化したデータ同士を加算できる)
    D(E(m1) * E(m2) mod N2) = m1 + m2 mod N
  • 暗号化したデータの元のメッセージに対してスカラ倍できるスカラ乗算
    D(E(m1)k mod N2) = k*m mod N

ボブはこれらをPPKを使って秘密鍵(PSK)の知識無しに計算することができる。

署名プロトコル

ECDSAの署名データは(r, s)。sは、 {\displaystyle s = \frac{H(m) + r * x}{k}}で、rはR = kGのx座標。

このECDSAの署名をアリスとボブは以下のステップで計算する。

  1. アリスとボブはそれぞれnonceを選択し、この公開鍵とそのnonceを持っていることのゼロ知識証明を共有する。アリス: {K_a = k_aG}、ボブ: {K_b = k_bG}
  2. ボブは暗号データ {\displaystyle c_1 = Enc_{PPK}(\frac{H(m)}{k_b})} {v = \frac{r * b}{k_b}}を計算する。ここでrは {R = k_a * k_b G}のx座標。
  3. ボブは {\displaystyle c' = c_1 * c^{v} \mod N^{2} = Enc_{PPK}(\frac{H(m) + r * a * b}{k_b})}を計算し、アリスに送る。
  4. アリスはそれを復号化した {s' = Dec_{PSK}(c')}を計算し、 {s'' = \frac{s'}{k_a} \mod q}
  5. 計算結果のs''は {\displaystyle s'' = \frac{H(m) + r * a * b}{k_a * k_b}}となる。
  6. 最後にアリスは {s = min(s'', q - s'' \mod q)}をセットし、(r, s)をSignアルゴリズムのアウトプットとする。

通常のECDSAプロトコルと比較すると、nonce kがアリスとボブのkに、秘密鍵もアリスとボブの秘密鍵に置き換わっている。

こうやって生成した署名はECDSA署名として機能する。最後のステップはLOW_Sルールの適用。

Scriptless Scriptの署名も同様のアプローチだが、シークレットの抽出で余分なラウンドを必要とする。詳細はPedroのペーパー参照。

ベンチマーク

  時間 割り当てられたメモリ 割り当て数 メッセージ数
KeyGen 1.07 秒 4.99 MB 13.31 K 7
Sign 28.66 ミリ秒 97 KB 746 4
Scriptless-Sign 29.40 ミリ秒 118 KB 1.12 K 5+1

KeyGenプロトコルの実際の暗号や複雑さを考慮するともっと遅くなると思われたが全体的に1.07秒で意外と速い結果になっている。おそらく1番遅い部分はgolangのbigintライブラリを使用している箇所で、これは時間が固定時間でなくメモリパフォーマンスに問題があることで有名だ。そのため、この時間は2倍 or 5倍 or 10倍に速くなる可能性がある。

署名は見ての通り30ミリ秒未満。結構大きい。オンラインプロトコルとしては上手く動作する。

Scriptless-Signには多くの最適化作業が残っている。

ベンチマークのコードは↓

github.com

LNへのデプロイの考慮事項

2P-ECDSA/Schnorrのデプロイの場合

Fundingアウトプット

現在は2-of-2のマルチシグにコインをロックしている部分。このコインをアンロックするには、協調してクローズする場合とCommitment Txをブロードキャストする場合の2ケースがあるが、いずれも2人の署名を必要とする。この部分をP2WPKHのロックスクリプトに置き換える。

通常の2-of-2のマルチシグ、Schnorr版、2P-ECDSA版、P2WPKHにおけるWitness Scriptとアンロックに必要なwitnessは以下のようになる。

  witness witness script
通常 OP_0 <aGの署名> <bGの署名> OP_2 <aGの公開鍵> <bGの公開鍵> OP_2 OP_CHECKMULTISIG
Schnorr <(a+b)Gの署名> <(a+b)Gの公開鍵> OP_CHECKSCHNORRSIG
2P-ECDSA <abGの署名> <abGの公開鍵> OP_CHECKSIG
P2WKH <aGの署名> <aGの公開鍵> OP_CHECKSIG

使用するスペースは約半分になる。2つの公開鍵は1つに、2つの署名は1つの署名になる。また、非広告チャネルのプライバシーを守るチャンスにもなる。LNのノードでチャネルを広告している場合は、プライバシーを諦めることになるが、プライベートチャネルの場合、Funding Txは通常のP2PKHもしくはP2WPKHのように見えるため、プライバシー上の大きなアドバンテージになる。特に、多くのモバイルデバイスやラップトップ上のノードが、ルーティングのためにノードを広告しないネットワークに移行するにつれて、大きな意味を持つ。また最後に、ゴシップレイヤーの帯域幅が少なくなる。署名が1つ少ないので一般的にネットワークの負荷状況が改善する。

HTLCアウトプット

非標準のHTLCスクリプトで(標準というのはBIP-199のこと?)、2-of-2のマルチシグを使っている。HTLCスクリプトには、offeredとreceivedの2種類のスクリプトがある。2つはほとんど似ているが、チャネル上のどの方向を向いているかが異なり、両方とも2-of-2のマルチシグを必要とする。スクリプト内のoffered-timeoutおよびreceived-successの条件でコインを使用する際に2-of-2のマルチシグを必要とし、その部分をよりシンプルになるよう置き換える。

例えば現在のReceived HTLCスクリプト

# revocation clause
OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocation pubkey))> OP_EQUAL
OP_IF
  OP_CHECKSIG
OP_ELSE
  <remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
  OP_IF
    # success clause
    OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY 2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
  OP_ELSE
    # timeout clause
    OP_DROP <cltv_expire> OP_CLTV OP_DROP OP_CHECKSIG
  OP_ENDIF
OP_ENDIF

のようなスクリプトになっているが、2P-ECDSAを利用してより簡単なHTLCスクリプトにすることができる↓

OP_IF
  # revocation clause
  revocationpubkey
OP_ELSE
  OP_IF
    # timeout clause
    <cltv_expire> OP_CLTV OP_DROP <remote_delay_pubkey>
  OP_ELSE
    # success clause
    <2p_htlc_pubkey>
  OP_ENDIF
OP_ENDIF
OP_CHECKSIG

これにより、

  • スクリプトのサイズ自体が20%削減
  • スクリプトの可読性が向上
  • witnessのサイズ削減
    • successの場合のwitnessサイズは78%削減される。
    • revocationのケースでは30%ほど小さくなる。
    • タイムアウトの場合のwitnessサイズは同じまま。

Offered-HTLCスクリプトでも同様の改善が期待できる。

Scriptlessな2P-ECDSA/Schnorrのデプロイの場合

  • HTLCアウトプット
    Scriptlessな2P-ECDSA/Schnorrを使用すると、HTLCのスクリプトからペイメントハッシュを削除することができる。また拡張によってwitnessからプリイメージを削除できるので、witnessから52バイト削減できる。

スペースの削減という観点からは、手数料も安くなり、ブロックチェーンの負荷も軽減する。

双方向の2P-ECDSA

LNのチャネルは双方向なので、HTLCを更新したい場合、全ての更新とパラメータ(ペイメントハッシュや、タイムロック時間など)をチャネルの反対側に送信し、各チャネルはその更新を適用し、その後作成した署名のバッチを送信する。これを行うと片方の参加者のみが署名で終わる。

オンチェーン上に1つのFunding Outputがロックされていて、どちらの参加者もこれを使用するための署名を開始できる。どちらからでも更新を開始できるように、同じ鍵ペアの2つのインスタンスをセットアップし、それでFunding Output(もしくは同様のもの)のコインを使用するCommitment Txに署名できるようにする。

※ この部分の説明がイマイチよく分かってない。

オニオンパケット

BOLT 04で定義されている現在のonionパケットのデータ構造は以下のようになっている

サイズ 名称
1 version
33 public_key
20*65 hops_data
32 hmac

この内、hops_dataはメッセージ転送中に関連するホップによって使われる情報を含む20個の固定サイズのパケットで構成される。

hops_dataを構成する1つ1つのパケットのデータ構造は以下のようなもの↓

サイズ 名称
1 realm
32 per-hop
32 MAC
filter

このうち2P-ECDSA/Schnorrのデプロイにあたって変更するのはホップ毎のペイロードのデータ(per-hop)。

現在のper-hopペイロードは以下の32バイト

サイズ 名称
8 short_channel_id
8 amt_to_forward
4 outgoing_cltv_value
12 padding

新しいペイロードは以下のような構成になる。サイズは161バイトで、トータルのパケットサイズは3880バイトとなり元の1300バイトから約3倍のデータ増になる。

サイズ 名称
8 short_channel_id
8 amt_to_forward
4 outgoing_cltv_value
33 incoming_lock_pubkey
64 incoming_lock_dlog_pok
32 hop_lock_secret
12 padding

これらを構築して解読する際のボトルネックの大半は、一時鍵導出やBlindng Factorなどの非対称暗号操作で、ホップ数の増加と共に線形スケールする。そのため、パケットサイズの増加は構築/解読にほとんど影響を及ぼさない可能性がある。

2P-ECDSAとScriptless Scriptのサマリ

メリット

  • 現時点でデプロイ可能
  • スクリプトとwitnessが小さくなり、手数料が安くなる。
  • funding outputの匿名セットの向上によりオンチェーンプライバシーが向上
  • ホップ間の相関を無くすことでオフチェーンプライバシーが向上
    2P-ECDSAは、既存のトラフィックに混在し、Schnorrが始まると初期は匿名セットが小さくなる。ただ時間の経過と共にSchnorrに移行すると思われる。
  • リアルなProof-of-Payment(Invoice Tunneling)
  • この分野で多くの研究されている。

デメリット

  • 複雑である
    • 正しく実装する決して簡単ではない。
    • モバイルデバイスのリソース使用量はそれほど大きくないけど、プルーフを並行して処理するためのコアは少ない。
  • Commitment Txの更新の際により多くの情報の更新が必要で、より多くのラウンドトリップを必要とする(署名プロトコルをパイブライン化してラウンドトリップを削減することは可能かもしれない)。