Witness
はじめに
Segregated Witness(以下Witness)は簡単にいえば「トランザクションの"署名"を別の領域に移したトランザクション」を用いる
仕様のこと
トランザクションに署名をするということは
署名対象データのハッシュ値を作成し、そのハッシュ値に秘密鍵で署名し、その署名データをScript_sigにセットする
ってこと
https://gyazo.com/071841596fd1733199c05f54ac842435
図1:トランザクションの署名対象データ
つまり、この時Script_sigは署名されることがないのでScript_sigを改竄されると、検出できない。
(TXIDはScript_sigも含めた上記のデータから作成されたハッシュ値なのでScript_sigが改竄されると別のTXIDができる)
これはまずい!この問題をmaliabirity問題と言う
→Segwitで対策
Segwitでは図2のようなデータ構造をもつ
トランザクションのインプットから署名を分離し、署名を別のデータ領域(witness)に移動した
これで、未署名のトランザクションでもTXIDを決定できる。
https://gyazo.com/a478bfdec47e11fe4f8cf772000afae2
図2:トランザクションデータの比較
新たに marker, flag, witnessが追加された。
SegwitのトランザクションもTXIDは今までと同じデータ・同じ方法で計算される。
Witness program
全てのトランザクションがSegwitを用いるわけではない
これを判断するのがWitness programである
これは2~40バイトのデータで、これに1バイトのversion byteを加えたスクリプトで判断する
(最初にversion byteがプッシュされ、次にWitness programがプッシュされる)
この、スクリプトがScriptPubkey(もしくはredeem script)に設定されている場合、そのUTXOを使用するトランザクションの署名はwitness領域に配置される。
この判別はversion byteでなされるが、今のところversion byte = 0だけであり
Witness programの長さによって解釈が次のようにちがう
P2WPKH
version byte = 0 ,Witness programのデータが20バイト
P2PKHのWitness版
署名と公開鍵をもつ(それぞれ520バイト以下)
この署名が公開鍵に対応した署名か検査する(P2PKHでも同じようなことをしてる)
P2WSH
version byte = 0 ,Witness programのデータが32バイト
P2SHのWitness版
スクリプトハッシュのredeem scriptをみたすために必要なアイテムとシリアライズされたredeem script(witness script)をもつ
witness scriptがポップ、そのSHA256値がwitness program(スクリプトハッシュのredeem scriptをみたすために必要なアイテムがwitness programに残っている)と一致すると残りのスタックのアイテムと合わせてwitness scriptgが評価される(P2SHでも同じようなことをしてる)
スクリプトのネスト
Segwitに対応していないワレットからP2WPKHやP2WSHのスクリプトに対して送金する場合は、それらのスクリプトをP2SHでネストする必要がある
P2WPKHの場合
Script Pubkeyに以下のP2SHのスクリプトをセットする
code:P2WPKHをP2SHでネスト
OP_HASH <P2WPKHのScriptPubkey をHASH160した20バイトのハッシュ値> OP_EQUAL
また、このUTXOを使用する際にはScript Sigに上記スクリプトのredeem scriptとなるP2WPKHの ScriptPubkeyをセットする
(通常のP2WPKHはScript Sigは空)
検証はredeem scriptを用いたP2SH仕様の検証のあと、P2WPKH仕様の検証が行われる
code:P2WSHをP2SHでネスト
OP_HASH <P2WSHのscriptPubkey をHASH160した20バイトのハッシュ値> OP_EQUAL
また、このUTXOを使用する際にはScript Sigに上記スクリプトのredeem scriptとなるP2WSHの ScriptPubkeyをセットする
検証はredeem scriptを用いたP2SH仕様の検証のあと、P2WSH仕様の検証が行われる