techmedia-think.hatenablog.com
について整理したので、今回は応用編ということでAtomic Swapや、タイムロックの仕組みをアウトプットと組み合わせた(BitcoinのOP_CLTV使うようなイメージ)条件付きのタイムロック支払いのコントラクトの構成方法についてまとめる。
Atomic Swap
異なるチェーン間でコインをトラストレスに交換するAtomic Swapプロトコルには、よくHTLCsが使われるが、Mimblewimbleにはスクリプトは無いので、Adaptor Signatureを利用して以下のように実現する。
アリスがgrinを持ってて、ボブがbitcoinを持ってて、それぞれを交換するケースを考える。まずボブはBitcoinのトランザクションを作成し以下のいずれかの条件でコインをアンロックできるロックスクリプト宛にコインを送る。
- アリスがハッシュのプリイメージ
xを知っていれば、アリスの署名でアンロック可能 - 時間が
Tb経過したらボブの署名でアンロック可能
ただこの時、ハッシュ関数を使うのではなく、代わりにx*Gを使う。つまりスクリプトは以下のような形式になる。
OP_IF 2 <アリスの公開鍵> <x*G> 2 OP_CHECKMULTISIG OP_ELSE <有効期間> OP_CLTV OP_DROP <ボブの公開鍵> OP_CHECKSIG OP_ENDIF
続いてアリスは、ボブがxを明らかにしたらgrinをボブが入手できるようGrinのブロックチェーン上でセットアップする。
- アリスは最初に自分が持っているgrinを、↑のマルチパーティ+タイムロック付きトランザクションを作成しそこに送る。この時払い戻しトランザクションはアリス宛で、その時にセットするタイムロックは
Ta < TbとなるようなTa。 - アリスはこのトランザクションをブロードキャストし、コインを2-of-2のマルチシグにロックする。
続いて、交換プロセス。
- アリスはランダムなnonce
ksを選択し、アリスのランダムファクターの合計rsを計算し、ks*Gとrs*Gをボブに送る。 - ボブはコインを受け取るのに使うランダムなブラインディングファクター
rrとランダムなnoncekrを選択する。ここで単純にsr = kr + e*rrを計算するのではなく、sr' = kr + x + e * rrを計算しsr``とkrG、rrG、x*G`をアリスに送る。 - アリスは
sr'*G = kr*G + x*G + e*rr*Gが成立するか検証する。そしてボブがBitcoinのチェーンでコインをx*Gにロックしているか検証する。 - 検証が成功したらアリスは自身の署名値
ss = ks + e*rsを計算し、ボブに送る。 - ボブは署名を完成させるため、
sr = kr + e*rrを計算し、最終的な署名(sr + ss, kr*G + ks*G)を完成させる。 - ボブはトランザクションをブロードキャストしgrinを手に入れる。アリスはそのトランザクションの署名値
sr + ssからsrを入手し、前にボブから受け取ったsr'を使って、sr' - sr = xを導出する。 - アリスは
xを使ってBitcoinのブロックチェーン上でコインを入手する。
という感じ。BitcoinにもSchnorrが導入されると、Bitcoinサイドも↓みたいにスクリプトレスにできるようになる。
アウトプットへのタイムロック条件の適用
前回の記事でトランザクションカーネルのlock_heightにブロック高を指定することで絶対的、相対的なタイムロックをトランザクションに施せることは分かった。こういった何の条件もついていないタイムロックの機能に対し、BitcoinではOP_CLTVやOP_CSVといったopcodeを使ってトランザクションアウトプットにタイムロック条件を付けることができる。
Mimblewimbleにはそういったスクリプトは無いので、前回の記事に書いた条件の無いタイムロックトランザクションにちょっと変わった仕掛けを組み合わせる。
まず2つの秘密鍵Key1とKey2を用意する。そして、2つの秘密鍵を合算して新しい秘密鍵を作る。
Key3 = Key1 + Key2
そして2つのトランザクションTx1とTx2のアウトプットをOut1とOut2とし、
Out1のブラインドファクターはKey1Out2のブラインドファクターはKey2Tx2にだけロックタイムが付いている
という状況を作る。これは、
Tx1はすぐにでもブロードキャストでき、ブロックチェーンに格納される。Tx2はロックタイムが設定されているため、それを経過するまでブロードキャストできない。Key3を使う場合、Out1とOut2を同じトランザクションで同時に使用する場合、Tx2のロックタイムを待たなければならない。
という状況が作られることを意味する。
そのため、Key1とKey2の情報を知り得ない形でKey3を構成すれば、Out1とOut2を個別に使用できないため、タイムロックの期間を過ぎるまで待つしか無い。つまりこういう鍵の公開スコープをハンドリングすることで、アウトプットにタイムロック条件を適用させることができる。
どうやってスクリプトレスなアウトプットにタイムロックのような条件を付与するのかと不思議だったけど、↑みたいに秘密鍵のスコープ調整と組み合わせて実現するのね。スクリプトと比べて手間ではあるけど、よく考えるなー。