Segwitに関して調べた記録4
前回の続き
Witnessと署名検証に関して
Segwit(BIP141-BIP145)で新たに導入されるWitnessという構造は、それ以前のBitcoinscriptとは異なる部分が多い。
例えば、Witnessは今までのBitcoinscriptのように、OpCodeを淡々と処理した結果がtrueであれば署名を正当なものと判断するのではなく、検知した“バージョン”毎に決められた処理を行い、その結果を署名検証の結果とする。
また、OP_CHECKSIGを行うときなどに使用される署名用のメッセージ(SHA-256doubleHashされる前のデータ)も、今までのように署名前のTxにLockscriptを差し込んだものを使用するのではなく、新しく決められたルールによってシリアライズされたデータを用いる。
(シリアライズは今まで通りHashTypeによってそのルールが異なるが、このブログでは一般的に使われるSIG HASH ALLのみに関して書く)
バージョン0のWitnessProgramとLockscript
ここではまず、WitnessProgramが何をもって「このLockscriptはWitnessProgramだ」と判断するのか、ということについて書く。
Segwit後もLockscriptはそれまでと同じようにTx-outのLockscriptフィールドに入れられ、署名検証を行うとき、適宜WItnessProgramか、レガシーなBitcoinscriptかを判断してそれらにあった方法で署名検証が行われる。
現在はバージョン0のWitnessProgram(P2WPKH,P2WSHの二種類)のみが定められており、下記条件をWitnessProgramのトリガーとしている。
■version0のP2WPKH
- Lockscriptが"0"から始まる(この0をバージョンバイトと呼ぶ)
- 1byteのバージョンバイト(0x00)に続き、20byteのデータプッシュが続く
- 対応するTx-inのunLockscriptが空の状態である

■version0のP2WSH
- Lockscriptが"0"から始まる
- 1byteのバージョンバイト(0x00)に続き、32byteのデータプッシュが続く
- 対応するTx-inのunLockscriptが空の状態である

バージョンバイト(0x00)に続くデータはP2WPKHの場合は圧縮された公開鍵(先頭が0x02または0x03で始まる公開鍵)をHash160(SHA-256_RIPEMD-160)したものであり、P2WSHの場合はredeem-scriptをHash256(SHA-256doubleHash)したデータである。
上記の他に、既存のP2SHでネストさせる方法とそのトリガーもあるが、ここでは紹介しない。簡単に言うと、LockscriptがP2SHで、redeem-scriptにP2WPKHやP2WSHを閉じ込めることも可能であるということだ。
Segwitに対応したノード、クライアントは上記フォーマットのLockscriptを検知すると、Witness用の署名・検証に処理を移す。
署名検証
(流れはP2PKHの OP_DUP ... OP_CHECKSIG と同じ流れ)
未知のバージョンを検知した時
結論から言うと、未知のバージョンを検知した時WitnessProgramはそのLockscriptをANYONE_CAN_PAY(誰でも使用することが出来るTx-out)として処理を行う。つまり、誰が使用したとしても署名検証を通す。
なぜこんなことをするのか、それは将来新しいバージョンのWitnessProgramをフォークして追加した時に、後方互換を意識しなくて済むようにするためだ。新しいプログラムを追加した際、古いノードがネットワークに紛れていても、そのノードはそのTx-outをANYONE_CAN_PAYとして取り扱うので、特別な後方互換手段を用意する必要がなくなる。
次に署名用メッセージのシリアライズの話に移りたいが、長くなってしまうのでここで一旦区切る。
〜5に続く〜

