Bitcoinのエンコードまとめ
最終的に出力する必要のあるものがどういったフォーマットなのかをまとめておく。
アドレス
Base58エンコード(p2sh, p2pkh)
Bech32(p2wsh, p2wpkh)
Bech32m(p2tr)
鍵
秘密鍵は256ビット
16進数の256ビットは32バイトで64文字で扱われることが多い
WIFの秘密鍵は最終的にBase58で出力される
WIFについて
秘密鍵のコピーの誤りを少なくするために、Wallet Import Formatを利用することができる。WIFは秘密鍵にbase58Checkエンコーディングを使用し、標準的なビットコインアドレスのようにコピーエラーの可能性を大幅に減少させる。
秘密鍵を取ってみよう。
メインネットのアドレスの場合はその前に0x80バイト、テストネットのアドレスの場合は0xefを追加する。
圧縮された公開鍵(後のサブセクションで説明する)で使用する場合は、 その後ろに0x01バイトを追加する。非圧縮公開鍵で使用する場合は、何も付加しない。
拡張鍵に対してSHA-256ハッシュを実行する。
SHA-256ハッシュの結果に対してSHA-256ハッシュを実行する。
2番目のSHA-256ハッシュの最初の4バイトを取る。
ポイント2の拡張キーの最後に、ポイント5の4つのチェックサムバイトを追加する。
Base58Checkエンコーディングを使って、結果をバイト列からBase58文字列に変換する。
この処理は、Base58のデコード関数を使用し、パディングを削除することで、簡単にリバーシブルにできる。
トランザクション
16進数でブロードキャストするが、中身を展開したときにリトルエンディアンで表記されている。
生成途中のTXIDがリトルエンディアンになっているため、ちょっとややこしい
スクリプト、オペコード
トランザクションの中に含まれるため、同じ16進数
各オペコードに対応する16進数の値が設定されている
例) OP_IF = 0x63
OP_DUP OP_HASH160 03df2ddaff3ea91aa9425bb51d62fbf7522fc404deab492dacb55b157cf6d30d44 OP_EQUALVERIFY OP_CHECKSIG
"v", "\xA9", "!\x03\xDF-\xDA\xFF>\xA9\x1A\xA9B[\xB5\x1Db\xFB\xF7R/\xC4\x04\xDE\xABI-\xAC\xB5[\x15|\xF6\xD3\rD", "\x88", "\xAC"
code:op_dupがvとなる理由
bitcoinrbライブラリでp2pkhアドレスの OP_DUP OP_HASH160 03df2ddaff3ea91aa9425bb51d62fbf7522fc404deab492dacb55b157cf6d30d44 OP_EQUALVERIFY OP_CHECKSIG をバイナリーにすると "v", "\xA9", "!\x03\xDF-\xDA\xFF>\xA9\x1A\xA9B[\xB5\x1Db\xFB\xF7R/\xC4\x04\xDE\xABI-\xAC\xB5[\x15|\xF6\xD3\rD", "\x88", "\xAC"
となります。なぜOP_DUPはvと表されるのですか。
Bitcoinスクリプトの命令(オペコード)は、それぞれが特定のバイト値にマッピングされています。これらのバイト値は、Bitcoinのスクリプト実行エンジンによって解釈され、対応する操作を実行します。OP_DUP、OP_HASH160、OP_EQUALVERIFY、OP_CHECKSIGなどのオペコードも例外ではありません。
OP_DUPは、スタックのトップにあるアイテムを複製するオペコードです。Bitcoinスクリプト言語において、OP_DUPは16進数で0x76にマッピングされます。16進数の0x76は、ASCIIコード表でvに対応します。そのため、OP_DUPがvと表されるのは、そのバイト値がASCIIでvとして解釈されるからです。
同様に、他のオペコードもそれぞれ特定のバイト値にマッピングされており、それらのバイト値はスクリプトをバイナリ形式で表現する際に使用されます。例えば、OP_HASH160は0xa9、OP_EQUALVERIFYは0x88、OP_CHECKSIGは0xacにマッピングされます。これらのバイト値をASCIIで表現すると、それぞれ\xA9、\x88、\xACとなります。
したがって、あなたが示したスクリプトのバイナリ表現は、これらのオペコードのバイト値と、その他のスクリプト要素(この場合は公開鍵ハッシュ)を組み合わせたものです。
OP_PUSHDATA と OP_PUSHBYTES の違い
OP_PUSHDATA4の場合, 4294967294 bytes まで可能
irb(main):027:0> ("a"*4294967295).bytesize < 0xffffffff
=> false
irb(main):028:0> ("a"*4294967294).bytesize < 0xffffffff
=> true
OP_PUSHBYTES の場合, 75 bytes まで可能
(エクスプローラー側で見やすいように書かれているだけで実際には存在しないオペコードのため注意)
irb(main):025:0> ("a"*75).bytesize < 0x4b
=> false
irb(main):026:0> ("a"*74).bytesize < 0x4b
=> true
短い数値の場合はOP_1などを使う
https://scrapbox.io/files/65b7847dac77a80024365617.png