だいぶ前に書き始めて放置してたのでちゃんと実装してみた。
以前↓のようにwitnessなトランザクションのパース方法について書いたので、
techmedia-think.hatenablog.com
続いてwitnessなトランザクションを作ってみる。
P2WPKHにBitcoinを送付
まず最初にP2WPKH(Pay-to-Witness-Public-Key-Hash)のscriptPubkey
に対してBitcoinの支払いをするトランザクションを作成する。
P2WPKHのscriptPubkey
は以下のフォーマットの22バイトのデータになる。
0 < 20-byte-pubkey-hash >
実際にtestnetでP2WPKHの支払いをしたトランザクションが↓
{ "hex": "0100000001f55cb86d8d04d4759fb8b05a198cf4d48d790e6c64d00e072aed98281d0ebff1010000006b483045022100fe718c5f0bb58d86225e1d9370f858b8c864f00112c6a33f9910fa7ea8e9c34b02203cef1a73a0a8e210c6a264446bbb90c86b7b6f6e6f411aa505f0a835ff147204012102effb2edfcf826d43027feae226143bdac058ad2e87b7cec26f97af2d357ddefaffffffff02806d0d00000000001600148911455a265235b2d356a1324af000d4dae0326250a1c917000000001976a9142c159d64daa0de5ae6abac61a9416c8a54e834bd88ac00000000", "txid": "fdb55428ed5a1949cad4732fcb1be031a9790e7e0f651fd33129909065511580", "hash": "fdb55428ed5a1949cad4732fcb1be031a9790e7e0f651fd33129909065511580", "size": 223, "vsize": 223, "version": 1, "locktime": 0, "vin": [ { "txid": "f1bf0e1d2898ed2a070ed0646c0e798dd4f48c195ab0b89f75d4048d6db85cf5", "vout": 1, "scriptSig": { "asm": "3045022100fe718c5f0bb58d86225e1d9370f858b8c864f00112c6a33f9910fa7ea8e9c34b02203cef1a73a0a8e210c6a264446bbb90c86b7b6f6e6f411aa505f0a835ff147204[ALL] 02effb2edfcf826d43027feae226143bdac058ad2e87b7cec26f97af2d357ddefa", "hex": "483045022100fe718c5f0bb58d86225e1d9370f858b8c864f00112c6a33f9910fa7ea8e9c34b02203cef1a73a0a8e210c6a264446bbb90c86b7b6f6e6f411aa505f0a835ff147204012102effb2edfcf826d43027feae226143bdac058ad2e87b7cec26f97af2d357ddefa" }, "sequence": 4294967295 } ], "vout": [ { "value": 0.00880000, "n": 0, "scriptPubKey": { "asm": "0 8911455a265235b2d356a1324af000d4dae03262", "hex": "00148911455a265235b2d356a1324af000d4dae03262", "type": "witness_v0_keyhash" } }, { "value": 3.99090000, "n": 1, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 2c159d64daa0de5ae6abac61a9416c8a54e834bd OP_EQUALVERIFY OP_CHECKSIG", "hex": "76a9142c159d64daa0de5ae6abac61a9416c8a54e834bd88ac", "reqSigs": 1, "type": "pubkeyhash", "addresses": [ "mjY3vKRzyHkpB5kbEwCxFNmkFb4wKVDVab" ] } } ] }
0番目の出力がP2WPKHへの支払いで、scriptPubKeyのtype
がwitness_v0_keyhash
になっているのがわかる。
witnessなトランザクションの作成と署名
↑でP2WPKH宛に送ったBitcoinを入力にしたトランザクションの作成と署名をする。
ここで注意するのが、署名の方法も従来とは変わっているということ。
署名時に計算するトランザクションのSIG_HASHの新しい計算方法がBIP-143で定義されている↓
techmedia-think.hatenablog.com
BIP-143の仕様をbitcoin-rubyで実装してみたのが↓
まだプルリクは出してないけど、bitcoin-rubyにsegwit対応のコードを実装してるのが↓
作成したプルリクがbitcoin-rubyの0.0.11で取り込まれたのでそのバージョンからは以下のコードで署名可能
(仕様が変わる可能性はあるけど)現状の↑を使ってP2WPKHのUTXOを使用するコードは以下のように書ける↓
P2WPKHのwitness
は<signature> <pubkey>
の構成になる。
from_key = Bitcoin::Key.from_base58('P2WPKHのUTXOの秘密鍵') prev_tx = Bitcoin::Protocol::Tx.new('P2WPKHのUTXOを持つトランザクションのrawデータ') tx = Bitcoin::Protocol::Tx.new tx.add_in(Bitcoin::Protocol::TxIn.from_hex_hash(prev_tx.hash, 0)) tx.add_out(Bitcoin::Protocol::TxOut.value_to_address(880000 - 10000, from_key.addr)) # BIP-143の仕様でSIGHASHを生成 sig_hash = tx.signature_hash_for_witness_input(0, prev_tx.out[0].script, 880000) sig = from_key.sign(sig_hash) + [Bitcoin::Script::SIGHASH_TYPE[:all]].pack("C") # witnessを構成(P2WPKHなのでwitnessは、 "<署名> <公開鍵>" の構成) tx.in[0].script_witness.stack << sig tx.in[0].script_witness.stack << from_key.pub.htb # witnessなペイロード puts tx.to_witness_payload.bth
生成したwitnessペイロードを実際にtestnetでブロードキャストしたトランザクションが↓
{ "hex": "010000000001018015516590902931d31f650f7e0e79a931e01bcb2f73d4ca49195aed2854b5fd0000000000ffffffff0170460d00000000001976a9148911455a265235b2d356a1324af000d4dae0326288ac02473044022009ea34cf915708efa8d0fb8a784d4d9e3108ca8da4b017261dd029246c857ebc02201ae570e2d8a262bd9a2a157f473f4089f7eae5a8f54ff9f114f624557eda7420012102effb2edfcf826d43027feae226143bdac058ad2e87b7cec26f97af2d357ddefa00000000", "txid": "07b09f22abd2d78c41b2984f05d3dd83a3c5905771f0ee290b04f933e0c13d59", "hash": "ac6506dab409881178f4d1b416188f903e85a5d588f175d930911532cb53ac58", "size": 194, "vsize": 113, "version": 1, "locktime": 0, "vin": [ { "txid": "fdb55428ed5a1949cad4732fcb1be031a9790e7e0f651fd33129909065511580", "vout": 0, "scriptSig": { "asm": "", "hex": "" }, "txinwitness": [ "3044022009ea34cf915708efa8d0fb8a784d4d9e3108ca8da4b017261dd029246c857ebc02201ae570e2d8a262bd9a2a157f473f4089f7eae5a8f54ff9f114f624557eda742001", "02effb2edfcf826d43027feae226143bdac058ad2e87b7cec26f97af2d357ddefa" ], "sequence": 4294967295 } ], "vout": [ { "value": 0.00870000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 8911455a265235b2d356a1324af000d4dae03262 OP_EQUALVERIFY OP_CHECKSIG", "hex": "76a9148911455a265235b2d356a1324af000d4dae0326288ac", "reqSigs": 1, "type": "pubkeyhash", "addresses": [ "mt1hZLajqyc63NkWy7qvgiuum5nuTBdVZ6" ] } } ] }
次はP2WSHの署名を。