Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Tapscript

 Tapscript

GBEC動画解説コンテンツのスライドです。
https://goblockchain.network/2020/04/bip342-tapscript/

shigeyuki azuchi

April 10, 2020
Tweet

More Decks by shigeyuki azuchi

Other Decks in Technology

Transcript

  1. TaprootのScript-Path実行時に適用されるルールを定義したもの
 【BIP-342】https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki 
 【日本語訳】https://techmedia-think.hatenablog.com/entry/2019/05/13/13354 1
 
 • Schnorr署名の適用
 • OP_CHECKMULTISG、OP_CHECKMULTISIGVERIFYの無効化


    • OP_CHECKSIGADDの追加
 • OP_SUCCESS系opcodeの追加
 • MINIMALIFを強制
 • 制限の変更
 ※TaprootのScript-Path以外のスクリプトにはこのルールは適用されない 
 
 ※Taprootの仕組みについては、↓のGBEC解説動画参照
 https://goblockchain.network/2020/02/bip341-taproot/ 
 2 Tapscriptとは?

  2. 3 Schnorr署名の適用
 Tapscript内のOP_CHECKSIG、OP_CHECKSIGVERIFYは
 ECDSAに代わってSchnorr署名の検証が行われる
 
 • スタック上の公開鍵のサイズ 
 ◦ 32バイトであれば、BIP-340の公開鍵とみなす。


    ◦ 32バイト以外の場合、未知の公開鍵タイプとして署名検証は行われず、失敗する
 ※将来のソフトフォークで未知の公開鍵タイプに対して新しい署名検証ルールを追加可能。
 ▪ 新しいSIGHASHルール
 ▪ NOINPUTタグ付き公開鍵
 • 署名検証
 BIP-340で定義されているVerify(公開鍵, H TapSigHash (0x00 || SigMsg(hash_type, 1) || ext), 署名)で署名検証
 ◦ hash_type:署名が64バイトの場合0x00(ALLと同等), 署名が65バイトの場合最後の1バイトを指定
 ◦ ext:以下のデータで構成されるメッセージの拡張データ
 ▪ tapleaf_hash:実行するTapleafのハッシュ値
 ▪ key_version:公開鍵の現在のバージョンを表す定数値(0x00)
 ▪ codesep_pos:実行中の署名opcodeの直前に実行されたOP_CODESEPARATORの位置
 公開鍵タイプが異なる場合、署名が流用されるのを防ぐ 
 分岐のあるようなScriptの実行パスの違いで、署名が流用されるのを防ぐ 

  3. 4 マルチシグ関連の変更
 • マルチシグ関連のopcode OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFYの無 効化
 スクリプト内に含まれていた場合、実行されたタイミングですぐに終了
 • 新しいopcode

    OP_CHECKSIGADD(0xba)が追加される。
 
 
 
 
 
 挙動はOP_ROT OP_SWAP OP_CHECKSIG OP_ADDと同じ
 1. スタックから公開鍵と n、署名をポップする。 
 2. 公開鍵が32バイトのデータ=BIP 340の公開鍵の場合 
 a. 署名データが空の場合 
 値nがスタックにプッシュされ、次のopcodeに続く 
 b. 署名データが空でない場合 
 値n + 1がスタックにプッシュされる 
 公開鍵
 n
 署名
 …
 公開鍵
 n
 署名
 公開鍵
 n
 署名
 公開鍵
 n
 署名
 OP_1
 (OP_TRUE)
 n
 n + 1
 OP_ROT
 OP_SWAP
 OP_CHECKSIG 
 OP_ADD

  4. 5 マルチシグの実現方法
 • OP_CHECKSIGADD ベースの構成
 従来の2-of-3マルチシグスクリプト 
 OP_2 <Pubkey 1>

    <Pubkey 2> <Pubkey 3> OP_3 OP_CHECKMULTISIG 
 
 
 <Pubkey 1> OP_CHECKSIG <Pubkey 2> OP_CHECKSIGADD 
 <Pubkey 3> OP_CHECKSIGADD OP_2 OP_NUMEQUAL 
 
 
 
 署名1
 署名3
 署名1
 空
 Pubkey 1
 空
 OP_1
 空
 OP_1
 Pubkey 2
 空
 署名3
 署名3
 署名3
 署名3
 OP_1
 署名3
 OP_1
 Pubkey 3
 OP_2
 OP_2
 OP_2
 OP_TRUE
 <Pubkey 1> 
 witnessにはPubkey1, 3に対応する署名 
 (Pubkey 2分は空)をセット 
 OP_CHECKSIG 
 <Pubkey 2> 
 OP_CHECKSIGADD
 <Pubkey 3> 
 OP_CHECKSIGADD
 OP_2
 OP_NUMEQUAL 
 OP_NUMEQUALVERIFY にすると
 OP_CHECKMULTISIGVERIFY と同様に
 署名検証が成功した場合だけ 
 値がインクリメントされる。 

  5. 6 マルチシグの実現方法
 • 2-of-3を2-of-2の組み合わせに分解 
 分解した組み合わせ毎に以下のスクリプトを作成 
 <Pubkey 1> OP_CHECKSIGVERIFY

    <Pubkey 2> OP_CHECKSIG 
 …
 作成したスクリプトを Taprootの各リーフに配置
 
 
 • n-of-nならMuSigを使って、↑の各リーフの公開鍵を単一の集約公開鍵に変換 
 参考:https://goblockchain.network/2019/04/musig/ 
 
 • k-of-nならSchnorrの閾値署名を使用する 
 Provably Secure Distributed Schnorr Signatures and a (t, n) Threshold Scheme for Implicit Certificates(http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps )
 
 ※ マルチシグ系のopcodeが無効になったのはSchnorr署名のバッチ検証と互換性がないため 
 
 
 H(Script 1)
 (1, 2)
 H(Script 2)
 (2, 3)
 H(Script 3)
 (3, 1)
 H(1, 2)
 Root

  6. 7 OP_SUCCESS系opcodeの追加
 未使用のopcode(80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254)に

    OP_SUCCESS系opcode OP_SUCCESS80..OP_SUCCESS254 を割り当て。
 
 OP_SUCCESSは、将来のソフトフォークで新しいopcodeを割り当てるために確保されたopcodeで、 OP_SUCCESSが実行されると、その時点でスクリプトは成功する。 
 
 • OP_NOP系のopcodeとの違い 
 OP_NOP系のopcodeは、何も実行しないopcodeとして振る舞うため、 
 スタックに影響を与えるような機能追加はできない。 
 
 例:OP_CLTV(OP_NOP2)
 <Time> OP_CLTV OP_DROP OP_DUP OP_HASH160 <H(pubkey)> 
 
 
 
 OP_NOPは何もしないopcodeなので、スタックに残った<Time>を削除す るのにOP_DROPを付与しなければいけない。

  7. 8 MINIMALIFの強制
 OP_IF/OP_NOTIFは、スタックの最上位要素がTrue/Flaseかで実行分岐を決定
 
 • 元々の動作
 False = 空のベクトル or

    OP_0 or 0x80(負のゼロ)
 True = 上記以外のデータ
 → True/Falseの表現が複数存在するため、malleabilityが存在する。
 • P2WSHのStandardルールとして以下の制約を追加
 True=0x01の1バイトのデータ、False=空のベクトル
 上記以外の値はエラー
 ※ Bitcoin Coreでリレーはされなくなるが、ブロック化されてれば許可
 • Tapscriptではコンセンサスルールとして追加

  8. 9 リソース制限の変更点
 • スクリプトサイズの上限 10,000バイトが適用されない 
 署名対象のメッセージの計算が scriptCode(実際に実行されるスクリプト)から、 
 (例:P2WPKHの場合、OP_0

    <H(公開鍵)> → OP_DUP OP_HASH160 <H(公開鍵)> OP_CHECKSIG) 
 UTXOが参照するscriptPubkey(35バイト固定)に変わったため、 
 SIGHASH計算にかかるコストがスクリプトのサイズに比例して増えなくなったため。 
 
 • スクリプトあたり非プッシュopcodeの上限 201が適用されない
 opcodeの制限は、opcode毎の実行時間を増やす(消費リソースが無制限に大きくなる)ことを 
 防ぐ目的で導入されたもの。スタック/アルトスタックのサイズは既に制限されており、 
 今回のMINIMALIFにより分岐処理の判定も O(1)で可能となったため、削除される。 
 
 • sigops制限の変更
 Tapscript内のsigopsはブロック全体で80,000 sigops制限に適用されない。 
 代わりに、スクリプト毎に sigopsバジェット = 「50 + witnessのサイズ」が割り当てられる。 
 Tapscript内で署名opcodeを使用すると1回につき50がバジェットから減る。