【CTO Tech blog】OP_CHECKSIGFROMSTACKの導入を提案するBIP-348
- CTO Tech blog

先日OP_CHECKSIGFROMSTACK
opcodeの導入を提案するBIP-348がBIPとして登録された↓
OP_CHECKSIGFROMSTACK
OP_CHECKSIGFROMSTACK(OP_CSFS)自体は、昔からElementsに導入されているopcodeで、スタック内の任意のメッセージに対する署名検証を可能にする。既存のOP_CHECKSIGなどの署名検証用のopcodeは、メッセージがそのopcodeの実行中のトランザクションデータに限定されている。
動作
OP_CSFSは、スタックに以下の3つの要素がある前提で動作する。3つ未満の場合は、スクリプトの実行は失敗し終了する。
OP_CSFSを実行すると、↑の3つの要素がスタックからPOPされ以下の検証を行う。
- 公開鍵のサイズをチェック。サイズがゼロの場合、スクリプトは失敗、終了。
- 公開鍵のサイズが32 byteの場合、BIP-340で定義されている公開鍵として扱われる。
- 署名が空でない場合、署名とこの公開鍵とスタックから取得したメッセージに対してBIP-340に従いSchnorr署名の検証が行われる。検証に失敗した場合は、スクリプトは失敗、終了。
- 公開鍵のサイズがゼロでも32 byteでもない場合、未知の公開鍵タイプとして扱われ*1、実際の署名検証は行われず、署名検証が成功したものとして扱われる。
- この段階まで処理が続くと、
- 署名が空の場合は、空のベクトルスタックにプッシュされる
- 署名が空でない場合は、sigopsのカウントがインクリメントされスタックに0x01がプッシュされる
Elementsとの挙動の違い
Elementsには、OP_CHECKSIGFROMSTACKとOP_CHECKSIGFROMSTACKVERIFYの2つのopcodeが用意されている。VERIFYが付く方は署名検証に失敗するとそこで終了し、付かない方は検証結果をスタックのプッシュする(OP_TRUE or OP_FALSE)。
BIP-348の挙動は、これらを組み合わせたような挙動になっていて、署名検証に失敗した場合はそこでエラーとなりスクリプトの実行が終了する。スタックに結果がプッシュされるのは、
- 署名検証に成功した場合:OP_TRUE
- 署名が空だった場合:空のベクトル=OP_FALSE
の2パターンのみ。
用途
OP_CSFSがあると以下のようなことが可能になる。
コベナンツ
Elementsでは結構初期の頃から言われてたもので、OP_CATと組み合わせてコベナンツを実現できる。まだOP_CATとSchnorrトリックが提案される前で、スタック上でトランザクションを組み立ててその署名の検証をOP_CSFSで行い、そこで使用した公開鍵と署名をOP_CHECKSIGでも利用することでコベナンツを実現するというもの
委任
コインの使用条件を第三者に委任することができる。例えば、以下のようなロックスクリプトを構成すると
<公開鍵A> SWAP IF 2 PICK SWAP CSFS VERIFY ENDIF CHECKSIG
これをアンロックするには二通りの方法がある。
- Aの秘密鍵を知る所有者がアンロックする方法で、その場合のwitnessは↓
<Aの秘密鍵で生成したTx署名> 0
- Aの秘密鍵を知る所有者が第三者(公開鍵Bとする)にコインの使用を委任する場合のwitnessは↓
<Bの秘密鍵で生成したTx署名> <公開鍵B> <Aの秘密鍵で生成した公開鍵Bをメッセージとした署名> 1
Aの秘密鍵の所有者は、公開鍵Bをメッセージとして、公開鍵Aに対して有効な署名を生成しそれを渡せば、Bの秘密鍵の所有者はいつでも↑のアンロックができる。
オラクルの署名検証
任意のメッセージに対する署名検証が可能になるので、オラクルの署名をトリガーとした(DLCのような)コントラクトが可能になる。
LN Symmetry
あとBIPに書かれてるのは、OP_CHECKTEMPLATEVERIFY(BIP-119)と組み合わせることで、LN Symmetry(eltoo)が可能になるという点。もともとLN Symmetryは、BIP-118のANYPREVOUT(APO:旧SIGHASH_NOINPUT)の導入が必要なプロトコルだけど、OP_CHECKTEMPLATEVERIFY <公開鍵> OP_CHECKSIGFROMSTACKで、ANYPREVOUTがシミュレートできるっぽい。これもう少し詳細知りたいな。
*1:この振る舞いは、BIP-342で定義されているTapscriptにおける未知の公開鍵タイプの取り扱いと同じ