これは ビットバンク株式会社 Advent Calendar 2020 の 19 日目の記事です。
ビットバンクの宮本です。
最近 Lightning Network (LN) での Escrow プロトコルについて学ぶ機会があったので備忘のためにまとめます。
Escrow とは?
何らかのサービスに対して対価を支払う場合、常に以下の二つのケースが発生しないようにしなくてはなりません。
- 対価を支払ったのにサービスが提供されない
- サービスを提供したのに対価が支払われない。
言い換えると、「支払い」とはサービスと通貨の Atomic な Swap である必要があります。
ブロックチェーン上の資産の場合、ブロックチェーンそのものの仕組みを持ちいてトラストレスに交換を行うことが可能ですが、外部の情報(ここでは、サービスが適切に提供されたか否か)を含む場合、完全なトラストレスで行うことはできず、仲介者を挟む必要があります。
既存の EC サイトなどでは、運営、決済会社が仲介者となることでこの問題を解決していますが、 BTC による支払いでは相手に対して直接支払うのが理想なので、できれば仲介者の関与を最小限に減らしたいという需要があります。
このような需要に対応するため、 BTC において、マルチシグを用いて支払いを仲介するユースケースを一般に Escrow Protocol と呼びます。
理想的には、 このプロトコルは以下の特性を満たします。
- Escrow が資産を盗めない。
- 「盗める」というのは正確には、「任意のアドレスに送金できる」ということをさします。
- 仕組み上、 Escrow は支払いが Buyer または Seller のどちらに行くかを決定することができるので、例えば Buyer と結託して本来は Seller が支払いを受け取るべき(= サービスがきちんと提供されている)場合に、 Buyer に refund させることが可能です。これは Escrow に信用をおく以上防ぐことができません。
- Buyer と Seller の間に争い (dispute) が発生しない限り、 Escrow は契約の内容(何に対する支払いだったのか)を知ることができない。
- dispute がない場合、 Escrow はそもそもこのような支払いがあったことを知ることもできない。
- Escrow が仲介を行った場合、あらかじめ定められた手数料を受け取ることができる。
- Escrow が不正を働いた場合、その証拠を構築することができる。
- ここでいう不正とは、 Buyer または Seller と結託して契約履行のチェックをせずにどちらかに不正に送金するケースを指します。
- これは、他のユーザーがこの Escrow を使うべきか否かを判断する根拠になります。
- 5 の証拠を公開する場合を除いて、第三者はいかなる場合にも何らかの契約があったことを知ることができない
変数定義
以降では以下の変数を使います。
- Buyer, Seller, Escrow の公開鍵をそれぞれ B, S, E 、対応する秘密鍵を b, s, e とする。 E は周知されているものとする。
- || .. byte 列の結合
- h ... hash 関数
- G ... 楕円曲線の base point
- c ... 契約内容文書のバイト表現
Taproot について
前提知識として、 Taproot について簡単に解説します。
これはBIP 340~342 によるビットコインの改善案で、 SegWit 以降の大きなアップデートとして期待されています。
ここでは、従来のように公開鍵のハッシュではなく、 Q=P+h(P||m)∗G という公開鍵そのものに対して支払います。
ただし P は適当な公開鍵で、 m はビットコインスクリプトをマークルツリーで結合したものです。
Taproot には key path spending とscript path spending があります。
- key path spending ... 単一の公開鍵 Q に対応する署名で支払う(Q の秘密鍵は、 P に対応する秘密鍵とスクリプトを知っていれば計算できる)。スクリプトは使えないが、署名が一つしかないので fee が安く匿名性が高い
- script path spending ... m と P を明かした上で、m を実行する。マークルツリーでスクリプトの利用しない部分を隠せる以外は現在のビットコインでの支払いとほぼ同じ
Taproot と同時にトランザクションに対する Schnorr 署名もサポートされる予定であり、以降の説明ではこれらが使えることを前提に書きます。
MuSig
Schnorr 署名で、公開鍵と署名のそれぞれを足し合わせることで、検証速度とサイズと匿名性を向上させたものです。
これにより、 key path spending でもマルチシグを使うことができます。
既存のマルチシグと比較して、署名時に署名者同士の間で通信をする必要があるというデメリットがあります。
Taproot でのオンチェーン支払いの場合
BTC でオンチェーン支払いをする場合、上記 4 以外の性質は簡単に満たせます。
基本的には単に 2-of-3 のマルチシグを作成するだけです。
まず、 あらかじめ Buyer と Seller は c で E をいじって E′ を作成します。これは支払いの前に契約内容に commit させておくことで、後から参加者のどちらかが「そんな契約していない」と言うのを防ぐためです。
E′=E+h(E||c)∗G
次に、 以下のように三つの解除条件を指定します。
- key path spending ... MuSig(B, S)
- script path spending
- Multisig(B, E')
- Multisig(S, E')
dispute が起きなければ Buyer と Seller が通信して MuSig で署名を行い、 Seller に対して支払います。
dispute がある場合は、異議を申し立てたい側が c を Escrow に明かし、Escrow はいずれかと協力して支払いを行います。
2-of-3 の Threshold 署名が可能ならば script path spending は必要なくなるように思えますが、(現在判明しているプロトコルの場合)セットアップ時に通信をする必要があるので、上記の 3 (dispute がない限り Escrow は契約の存在を知らない) を満たすことができなくなるので、Escrow 目的には適していません。
Multisig は、 MuSig か、あるいは既存のビットコインスクリプトのマルチシグのように署名を複数並べるかのどちらでも良い場合をさします。
では、これが上記の 1~6 の性質を満たしているかどうかを検証してみましょう。
-
- Escrow は資産を盗めるか
- Seller または Buyer の協力が必要なので、任意のアドレスに送金することはできない。
-
- Escrow は契約の内容を知ることができるか。
- c の詳細なフォーマットは Seller と Buyer しか知らないので、彼らから提示されない限り知ることはできない
- なお、Escrow が任意のフォーマットに対する仲介を行うことは現実的ではないので、Escrow がサービスの一環として文書の雛形を公開しておき、 Buyer または Seller が自分の名前 (を含む契約のパラメータ) と、お互いに合意した適当な salt を文書に含めることで最終的に commit する文書 c を作成するようなプロトコルになる。
-
- Escrow は取引の有無を知ることができるか
- 支払い先アドレスの構築は、あらかじめ Escrow が公開している E に対して行われるので、Escrow と通信する必要はなく、したがって Escrow は自分の公開鍵がどこで使われているかはわからない。
- MuSig は署名作成時に相手と通信する必要があるが、dispute がない場合は Buyer と Seller だけの通信で良いので、 E は取引の存在を知らない
- 支払い先アドレスがブロックチェーン上で見えるようになっても、 Escrow は c を知らず、したがって E′ もわからないので、そのような支払いがあったことを知ることはできない。
- 4 仲介者は仲介手数料を受け取ることができるか
- このままの仕組みだとできないので、サービスの一環として c を提示される際に同時に LN 支払いをするのが現実的になる。 (少額の支払いだと思われるので、 LN が適している)
-
- Escrow が相手と結託して不正を働いた場合、それを周知する方法はあるか
- c, E, B, S を公開すれば良い。 c の内容に対して送金が不正だったことは別の主体がチェックする必要があるが、これは仕組み上絶対に飛ばすことができない。
-
- 第三者は契約の存在を知ることができない。
- 5 の場合を除いて、dispute があった場合でもブロックチェーン上からは c の内容はわからず、単なるマルチシグに見えるので、問題ない。
LN の場合
LN の場合もう少し別の仕組みが必要になりますが、その前に PTLC について簡単に解説します。
PTLC とは
LN では通常、 ある秘密の値 (preimage) の hash を invoice (請求書)に含めておき、その hash を使って HTLC を中間ノードとの間に作ります。 HTLC は、 Hashted timed-locked contract の略で、「この hash の元になった preimage を制限時間以内に提示すればあなたは資産を受け取ることができる」という契約を表すビットコインスクリプトです。
同時に中間ノードには、次の node との間に同様の契約を作るように伝えます。次のノードも同様に行い、最終的には Invoice を発行したノード (= 支払いを受け取るノード) までたどり着きます。このノードは preimage を持っているので、次のノードを考慮する必要がなく、値を明かして資産をゲットし、支払いを完了します。
これが現在の LN の大まかな仕組みですが、いくつか問題があります。
- preimage は支払いの証明 (= レシート, Proof of Payment, PoP) として機能するはずですが、中間ノードも入手できてしまうので、誰が支払ったのか正確にわからない。
- これは static invoice というプロトコルでも解決できる問題です
- 中間ノードに、同じ人物が運営するノードがあった場合、間のノードを飛ばして手数料を得ることができる。
- hash と preimage の間には加法同型性がないので複数の hash 同士を足し合わせたりするのが難しい。
PTLC は、 Point time-locked Contract の略で、 Hash-preimage を Point-preimage で置き換えるものです。
Point は楕円曲線上の点を表しており、 point-preimage は公開鍵・秘密鍵の関係に等しいです。
実態は単なる公開鍵・秘密鍵ですが、文脈を考慮する場合、 Payment Point, Payment Secret といった言い方をします。
Schnorr 署名(Taproot)が利用可能になった後は PTLC による LN の改善が計画されているので、以降では PTLC を前提に話します。
PTLC を使うことで、次のホップと契約を作るたびに point に適当な値を足していくことで、中間ノードが preimage を知ることを防ぐことができます。これは、 hash の場合 h(x)+h(y)≠h(x+y) ですが、 Point の計算(= G の乗算)の場合、 (x∗G)+(y∗G)=(x+y)∗G を満たすためです。
オフチェーン支払いの Escrow
LN の場合、単純なマルチシグによる Escrow にはちょっと問題があります。
なぜかというと、マルチホップの場合、Escrow がその気になれば中間ノードを犠牲にして、両方が資産を受け取るということが可能だからです。
より正確には、PTLC による支払いでは、支払い条件が単一の公開鍵 (Payment Point) で表される必要があります。これは、 hop のたびにこの公開鍵に加算を行なっていく必要があるためです。
そして、署名を行うのではなく秘密鍵(に相当する preimage) を明かすことで支払いを行います。つまり、オンチェーン支払いのようにスクリプトを使うことができないので、上記の仕組みを用いることができません。
まとめると
- オンチェーン ... スクリプトでロックし、署名を含む Witness でアンロックする
- オフチェーン ... 公開鍵でロックし、秘密鍵でアンロックする。
という点から生じる問題であると言えます。
Threshold 署名を使えば単一の公開鍵で k-of-n 条件を表現することが可能ですが、これは前述のように Escrow と事前に通信する必要があり匿名性に難があります。
Escrow の場合、 (E′∧S)∨(B∧S) という解除条件にしたいので、少なくとも OR (∨) と AND (∧) を、単一の公開鍵の形式で表現できるようにする必要があります
LN では、Payment Secret を明かさなかった場合一定時間後に支払いはキャンセルされるので E′∧B (Refund のケース)は必要ありません。
公開鍵は加法に関して同型なので、 P1+P2 でロックした鍵は、 pk1+pk2 でアンロックできます。
Pa は公開鍵で pka はそれに対応する秘密鍵とします。
ですので、AND 条件は簡単に表現できます。単に二つの公開鍵を足し合わせた値を Payment Point にすれば、対応する秘密鍵を二つとも持っていなければならないためです。
OR 条件は AND に比べて難しいですが、 Verifiable Secret Sharing を用いた方法と、 Verifiable Encryption を用いた方法が提唱されています[1]。 Escrow Protocol の場合、セットアップ時に Escrow とやりとりしたくないので後者を用います。
この方法では、Buyer は b を E′ で暗号化してから、 Seller に渡します。 Seller は、これが確かに B に対応するものであることを(暗号化したまま)検証し、セットアップを行います。
dispute が発生した場合、これを (c とともに) Escrow に渡します。 Escrow は e を知っているので復号化でき、 Seller の味方をしたい場合は Seller に復号した b を送ることで、 OR 条件を達成できます。
このようにして PTLC のアンロック条件を AND と OR の組み合わせで表現したものは、 Monotone Access Structure と呼ばれています。
冗長なので詳細は省きますが、これは上記 1~6 の性質のうち、 5 以外を満たすことができます。
今後
このように、 LN 上でより自由度の高い契約が表現できるようになると、 契約が作成されてから解消するまでにより長い時間がかかるようになっていくので、 LN の流動性枯渇問題が逼迫する可能性が高くなります。
幸い、流動性の問題に関しては、
Channel Factory、 Lightning Pool といった改善策が提案されています。
脚注
[1]: Bitcoin の文脈では、 Verifiable Encryption の最もポピュラーな方法は Adaptor Signature と呼ばれる方法ですが、ここではこれは使えません。なぜかというとこれの場合、復号後の平文と暗号文から秘密鍵が再構築できてしまうためです(これを One-time 性と呼びます)。したがって、Adaptor Signature では暗号化に用いる秘密鍵は使い捨てられることが前提となっています。Escrow の場合 Escrow はあらかじめ単一の公開鍵 E を公開しており、これを使いまわしたいので One-time 性を満たさない別の検証可能暗号を用いる必要があります