Segwitに関して調べた記録5
前回の続き
はじめに
この記事ではSegwitによって新たに採用されるトランザクション署名用メッセージのシリアライズ方法について書くが、ここで一点前置きをしておきたい。
Bitcoinの署名用メッセージの生成方法は、予めいくつかの決められたパターンが存在し、そのパターンはHashTypeと呼ばれる。このHashTypeは署名データの一番後ろに1byteで表現されて付け加えられ、unlock scriptに入れられる。
(詳しい仕組みは下記BitcoinWikiのOP_CHECKSIGの項目で確認してください)
このHashTypeはSegwitでの署名検証においても使用されるので、本来であれば、それぞれパターンに分けて説明をするべきなのだが、ここでは簡単に説明するため、一般的に使われる「SIGHASH_ALL(=0x01)」に関するシリアライズに絞って書く。
レガシーな署名用メッセージのシリアライズ (SIGHASH_ALL)
Segwitで使われる署名用メッセージのシリアライズ方法を書く前に、通常のP2PKHなどで使用されるレガシーな署名用メッセージのシリアライズ方法に関して書いておく。
Segwit採用前のトランザクション署名用メッセージのシリアライズ(SIGHASH_ALL)の方法はunlock scriptフィールドが空の状態のトランザクションに、lock scriptを差し込んだものと、Hasyを4byteで表現したデータを合わせてHash256(SHA-256doubleHash)して生成している。
※新たに発行するトランザクションに参照しているロックスクリプトを差し込む際に、script内に
OP_CODESEPARATORがあるときは注意が必要。
ここで、署名用メッセージとしてシリアライズされるフィールドというのはつまり「署名によって守られているフィールド」を意味している。
BIP-143で定められている新しいシリアライズ (SIGHASH_ALL)
では、BIP-143で定められている新しい署名証メッセージ(SIGHASH_ALL)はどうやって生成するのか、BIP-143を引用すると下記のとおりとなっている。
Double SHA256 of the serialization of:
1. nVersion of the transaction (4-byte little endian)
2. hashPrevouts (32-byte hash)
3. hashSequence (32-byte hash)
4. outpoint (32-byte hash + 4-byte little endian)
5. scriptCode of the input (serialized as scripts inside CTxOuts)
6. value of the output spent by this input (8-byte little endian)
7. nSequence of the input (4-byte little endian)
8. hashOutputs (32-byte hash)
9. nLocktime of the transaction (4-byte little endian)
10. sighash type of the signature (4-byte little endian)
BIP-143より引用
https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki
1、4、7、9、10に関しては、レガシーなシリアライズと同じ、新規発行した署名前のトランザクションのフィールドから取り出した値を使用すれば良い。それ以外の2、3、5、6、8に関して、一つずつ見ていこう。
2. hashPrevouts (SIGHASH_ALL)
hashPrevoutsは新規発行TxのTx_Inの中にある全てのoutPointフィールドを取り出して(index順に)繋げたものにHash256を行う。
3. hashSequence (SIGHASH_ALL)
hashPrevoutsは新規発行TxのTx_Inの中にある全てのsequenceフィールドを取り出して(index順に)繋げたものにHash256を行う。
5. scriptCode of the input (SIGHASH_ALL)
これから署名を行おうとするTx_inが参照しているlock scriptについて…
■P2WPKHの場合
0x 19 76 a9 14 {20-byte-pubkey-hash} 88 ac
となる。(lockscriptに格納されている状態から、Bitcoin scriptの処理に変換して使用する)
■P2WSHの場合
witness scriptにOP_CODESEPARATORが含まれていない場合は、witness scriptをそのまま使用する。OP_CODESEPARATORが含まれている場合は、witness scriptにあるOP_CODESEPARATORのうち、一番最後のもの以降のwitness script部分を使用する。
6. value of the output spent by this input (SIGHASH_ALL)
これから署名を行おうとするTx_inのoutPointにて参照しているTx_outのvalueフィールド
(つまりこのTx_inが解錠するBitcoinの量)
8. hashOutputs (SIGHASH_ALL)
新規発行トランザクションのTx_out部分をindex順に全てシリアライズしてつなげたデータにHash256を行う。
署名によって守られる要素 (SIGHASH_ALL)
以上の手続きでシリアライズしたデータに署名を行うということはつまり、署名によってそれらが守られることを意味する。新しいシリアライズによって守られるTxの部分を図で示す。
(着色部分は署名によって守られる)
BIP-143のシリアライズによって新たに加わったところとしては、参照先のTx_outのvalueフィールドが保護されるようになったところである。また、その他の特徴としては、フィールドをそのまま使用するのではなく、トランザクションを構成する要素になる各フィールドを繋げてHash256したダイジェストを使用するところだ。
BIP-143で定められている新しいシリアライズ (さいごに)
BIP-143で定められている新しいシリアライズ(SIGHASH_ALL)に関する説明は以上となる。この辺りの話を実際に理解するには、実際に自分でシリアライズしてみて検証してみたほうが良いと思う。
幸い、BIP-143にはいくつかサンプルが載っているので、それと照合して確認するのが良い方法だと思う。
〜6に続く〜