先日、bitcoin-dev MLにGregory MaxwellがポストしていたTaprootというコンセプトが興味深かったので見てみる↓
[bitcoin-dev] Taproot: Privacy preserving switchable scripting
まだBitcoinにはデプロイされていないが、MASTというscriptPubkeyをマークル化するアプローチが提案されている↓
techmedia-think.hatenablog.com
techmedia-think.hatenablog.com
複数の条件でコインをアンロックできるscriptPubkeyがある場合(例えば、2-of-2の署名があればアンロックできる or 24時間経過したら1人の署名でアンロックできるなど)、通常のP2SHでは元の条件を全て含むredeem scriptを公開してどちらかの条件でアンロックする必要があるが、↑のMASTを利用すると実際にアンロックに使用する条件のみを公開するだけで良い。使用しない条件を公開する必要がないためプライバシーが少し向上し、ブロックチェーン上に記録される容量も削減できる。
ただ、MASTを使用してアンロックしていること自体は分かるので、公開されるのはアンロックに使用した条件のみだが、他に何らかの条件が存在したことは知られてしまう。
これを改善するのに、複数の条件が無い場合にもダミーのハッシュなんかを用意してMASTを構成するスクリプトを作り、別の条件があるかのように偽装するという方法も考えられる。ただこの場合ネックになるのが、複数の条件を必要としないケースに比べて32バイトほど余計にトランザクションスペースを消費する点だ。この余分な32バイトを使ってもプライバシーを考慮すべきかというトレードオフが発生する。
マルチシグ or 他の条件がアンロック条件となるスクリプトに対して、このトレードオフを発生することなくプライバシーの向上と容量のセーブの両方を実現するのがTaprootのコンセプトだ。
アリス(公開鍵A)とボブ(公開鍵B)がいて、以下のいずれかの条件でアンロック可能なコインがあるとする。
普通にscriptPubkeyを書くと以下のようなスクリプトになる。
OP_IF 2 <A> <B> 2 OP_CHECKMULTISIG OP_ELSE <ロック時間> OP_CSV OP_DROP <B> OP_CHECKSIG OP_END
TaprootのscriptPubkey
Taprootのコンセプトでは、これを以下のようにしてある1つの公開鍵への支払いにする。
※ 前提としてSchnorrの集約特性を必要とする。
- まずAとBのマルチシグの部分について、AとBの公開鍵を集約した集約鍵
C = A + B
を作る。(rogue key攻撃の懸念がある場合はMuSig*1を利用して集約鍵を作る。) - タイムロックスクリプトを
S = <timeout> OP_CSV OP_DROP B OP_CHECKSIGVERIFY
とする。 C
とS
から楕円曲線上の点P = C + H(C || S)G
を計算する。
(H()
はハッシュ関数で、G
は楕円曲線のジェネレータ)- scriptPubkey
[Taprootのバージョン] [楕円曲線上の点P]
宛てに支払いをする。
(segwitのscriptPubkey[witness version] [witness program]
みたいなイメージだと思う)
このscriptPubkeyにロックされた資金をアンロックする方法は当然2つあり、それぞれ以下のようにアンロックする。
アリスとボブのマルチシグを使ってアンロックする方法
P
は楕円曲線上の点=公開鍵で、この点はアリスとボブの公開鍵を集約して作った点CとH(C||S)をシークレットとして生成した点を加算した点なので、アリスとボブの秘密鍵にH(C||S)を加算して、P
に対して有効な署名を作成することができる。
タイムロックの条件を使ってアンロックする方法
マルチシグ以外でアンロックできる条件がもう1つのタイムロックされている条件で、この条件を使用するのに以下のような新しいコンセンサスルールを導入する。
P
を構成するアリスとボブの集約鍵C
ともう1つの条件のスクリプトS
を提供し、C + H(C||S) = P
が成立する場合、S
のスクリプトのタイムロックの条件をクリアし、ボブの秘密鍵による署名があればコインをアンロックできるというものだ。
どちらの方法でアンロックするかの判定はwitness stackのアイテムの数で判断するのかな?
まとめ
Taprootでは、所謂マルチシグのアンロック条件とそれ以外のアンロック条件を持つスクリプトを組み合わせて1つの公開鍵にする。マルチシグの場合はマルチシグの参加者の署名があればその公開鍵に対する有効な署名を作ることができアンロックできる。もう1つのスクリプトの条件を使ってアンロックする場合は、マルチシグを構成する際の集約鍵とその元の条件のスクリプトを公開することで、スクリプトの条件を使ったアンロックを可能にする。
↑はアリスとボブのだったけど何人でも動作原理は同じで、S
にも任意のスクリプトをセット可能だ。
最初に説明したようにMASTのプライバシーをさらに向上させるのに、複数の条件がない場合でも条件があるように見せるようMASTを構成すると無駄なデータサイズが発生するが、Taprootの場合はロックに使用するのは公開鍵P
だけあれば良いのでこの問題が解消できる。
条件が課されたコントラクトを含むロックスクリプトを、オーバーヘッドの無い単純な公開鍵として表現するアイディアがおもしろいなー。