トランザクション
最終更新日: 2024/10/09
はじめに
Bitcoinトランザクションには署名の方法などによる違いはあるが、データの構成は決まっている。
構成
Bitcoinトランザクションはバイナリデータである。
以下はバイナリデータを構成している要素の名前である。
この名前は解説しているサイトによって多少違う(version
がnVersion
だったりlock_time
がLockTime
だったり)が、
version
marker
,flag
(存在しない場合あり)txin_count
txins[]
txid:index
(out_point)scriptSig
sequence
txout_count
txouts[]
value
scriptPubKey
script_witnesses[]
(存在しない場合あり)lock_time
先頭から 5byte目のデータで見分ける。
segwit(witness)のトランザクションの場合、その位置に0x00
が入っている。その場合は maker(0x00)
とflag(0x01)
が並んでいる。
それ以外の場合は segwit非対応のトランザクションで、marker
とflag
がなく 5byte 目からtxin_count
のデータが入っている。
Serializationの表に “Type” 列があるが、これがそれぞれのデータタイプである。
txins[]
, txouts[]
, script_witnesses[]
はさらにデータ構造がある。
下に例としていくつか raw transaction(生のトランザクションバイナリデータ)を分解する。
“<script~>
” となっている項目は、先頭がデータ長でその後ろにデータ長分のデータが続いている。
“<script_witnesses>
” は少し特殊で、全体の数は <txin_count>
で、それぞれスクリプトの個数とスクリプトが続いている。
値の表現
値については 2の補数の little endian。
固定長の場合はそのバイト数のデータ型、可変長は Compact Size型が使われている。
Compact Size型はあまり見慣れないと思う。
例えば 0xfc
までなら 1バイトでそのまま表現できるが、0xfd
は 0xfdfd00
(little endian)になる。
var_int
, VarInt
と呼ばれることもあるが厳密には異なるとのこと。
ちなみにスクリプトの中に数値が使われる場合は命令と組み合わせて使うため別の表現になる(Constants)。
例1: 非segwit
a1d0efa306442b1b7b82535e3531407ab5916f9adb0761afc5b83bfdbbdcda70
<全 raw transaction データ>
01000000016e74e6814a1e0eafc9a80c8589b705f8d6791cd7a401e6046d53c38f75daae5d01000000fdfd000047304402205c97e03a51c148a15e444578e0efce7b39731f0672f5bd7ecc473810e1e1e5ec02207ca1ea0b93fd7a9a61966ab37bb3ae2d29240ee79eeb70df3660d3f47c371c5901483045022100c02f853575468daf9fbc667d1331aea792f2709ed576b6a9fe416ecb27bc0dc70220519884f5a2c39c03eab6f073a5dde4a08ef6090908a0ed14a068e30ca90c62c9014c695221021edb59dffb17e9cc4c70cc68890125216ad5a8062879be20430600138c87e0422102bae72de833cc5914d0f19a959836245d7e1b8dc0b168f289a01acdcffc02a73e2103af0b0289d979fca04aa1bb1eef1325d4dd8fbddc690297d81811c5282841f1d453aeffffffff0200911c500200000017a91401e2f991b1d8d904eea641d7971c9eee6a4e72588740420f000000000017a914e031febb6904a7e7b8192b78ab1fc6572e8d585b8700000000
--------------------------
<version>
01000000
<txin_count>
01
<txins[0]>
<txid:index>
6e74e6814a1e0eafc9a80c8589b705f8d6791cd7a401e6046d53c38f75daae5d01000000
<scriptSig>
fdfd000047304402205c97e03a51c148a15e444578e0efce7b39731f0672f5bd7ecc473810e1e1e5ec02207ca1ea0b93fd7a9a61966ab37bb3ae2d29240ee79eeb70df3660d3f47c371c5901483045022100c02f853575468daf9fbc667d1331aea792f2709ed576b6a9fe416ecb27bc0dc70220519884f5a2c39c03eab6f073a5dde4a08ef6090908a0ed14a068e30ca90c62c9014c695221021edb59dffb17e9cc4c70cc68890125216ad5a8062879be20430600138c87e0422102bae72de833cc5914d0f19a959836245d7e1b8dc0b168f289a01acdcffc02a73e2103af0b0289d979fca04aa1bb1eef1325d4dd8fbddc690297d81811c5282841f1d453aeff
<sequence>
ffffff
<txout_count>
02
<txouts[0]>
<value>
00911c5002000000
<scriptPubkey>
17a91401e2f991b1d8d904eea641d7971c9eee6a4e725887
<txouts[1]>
<value>
40420f0000000000
<scriptPubkey>
17a914e031febb6904a7e7b8192b78ab1fc6572e8d585b87
<lock_time>
00000000
例2: segwit
0931d995f2e84b610bfcc6e5a960dea3baee16229c156518d7fbaee4141d14ef
<全 raw transaction データ>
01000000000101064c370388c7bb573fb574983e8f5740f697f45dba4dc96a16b2e31ea9034a070100000000ffffffff02314a0d00000000001600144c6a32c4a3344daf0fdc12e9202287786e5ac882e09304000000000016001468a211ede685d089ce170065948aa80790e00f9e0247304402201b3913c5ee01d6ceff87a861f8554ced9e99e281884530fd7828a50099cedad202204b641d827fcfb7c1cfd5cb7bbc4379b50f75531f063b814f4998b3507eea3033012103ec5f3495edf84da8d308bb59802a25baebab382a3c1fdccdc3462685ab09b73200000000
--------------------------
<version>
01000000
<marker, flag>
0001
<txin_count>
01
<txin[0]>
<txid:index>
064c370388c7bb573fb574983e8f5740f697f45dba4dc96a16b2e31ea9034a0701000000
<scriptSig>
00
<sequence>
ffffffff
<txout_count>
02
<txouts[0]>
<value>
314a0d0000000000
<scriptPubkey>
1600144c6a32c4a3344daf0fdc12e9202287786e5ac882
<txouts[1]>
<value>
e093040000000000
<scriptPubkey>
16001468a211ede685d089ce170065948aa80790e00f9e
<script_witnesses>
<txins[0]>
<witness_count>
02
<witness[0]>
47304402201b3913c5ee01d6ceff87a861f8554ced9e99e281884530fd7828a50099cedad202204b641d827fcfb7c1cfd5cb7bbc4379b50f75531f063b814f4998b3507eea303301
<witness[1]>
2103ec5f3495edf84da8d308bb59802a25baebab382a3c1fdccdc3462685ab09b732
<lock_time>
00000000
例3: segwit
026a8f0c6e6050cf237f42a7f2ed27efffead6c8750d991f746cef44448f3e2e
<全 raw transaction データ>
010000000001020ae960ef2054fd508f59b52e0ef3c19f7d2e865927f9059ec3779e568d30e9bf0100000000ffffffffb4e0d2298e0413cdb98cce33f22b240affbbd6c6eff7e9ec6eae5e70855e25bf0100000000ffffffff01bbb00100000000002251205779bec9d3f59f7b7bbefa606a81f171b3996659642bdf83a3fee52149d25e7901408893d9c6381da9984762b7bdb89427c154da5906e07678da2f8f15de292b40858fa0065170e7bca5e72cf3ce623c64533a4229527c6565d41cfb1ba411f5c1f70140093c5d8bdfdc06e33cab1f1a76bfaf93f8b5bc0a8e7d8075a7f2443772ebf648d39cac8f7bcd545c0ddfa08e62146f3079dabb284a3d47dd11280509d5cc88da00000000
--------------------------
<version>
01000000
<marker, flag>
0001
<txin_count>
02
<txins[0]>
<txid:index>
0ae960ef2054fd508f59b52e0ef3c19f7d2e865927f9059ec3779e568d30e9bf01000000
<scriptSig>
00
<sequence>
ffffffff
<txins[1]>
<txid:index>
b4e0d2298e0413cdb98cce33f22b240affbbd6c6eff7e9ec6eae5e70855e25bf01000000
<scriptSig>
00
<sequence>
ffffffff
<txout_count>
01
<txouts[0]>
<value>
bbb0010000000000
<scriptPubkey>
2251205779bec9d3f59f7b7bbefa606a81f171b3996659642bdf83a3fee52149d25e79
<script_witnesses>
<txins[0]>
<witness_count>
01
<witness[0]>
408893d9c6381da9984762b7bdb89427c154da5906e07678da2f8f15de292b40858fa0065170e7bca5e72cf3ce623c64533a4229527c6565d41cfb1ba411f5c1f7
<txins[1]>
<witness_count>
01
<witness[0]>
40093c5d8bdfdc06e33cab1f1a76bfaf93f8b5bc0a8e7d8075a7f2443772ebf648d39cac8f7bcd545c0ddfa08e62146f3079dabb284a3d47dd11280509d5cc88da
<lock_time>
00000000
TXID
個別のトランザクションを指し示すとき、通常は TXID(Transaction ID)を使う。
データを SHA256 で 2回計算する。
データはトランザクションデータそのものではなくこちらのようにデータを組む(非segwitの場合はそのまま使うことになる)。
図に出ている “Witness ID” はブロックデータを作る際に使われる。それ以外ではほぼ使われていないと思う。
計算すると 32byte のデータになる。
例1に上げたトランザクションデータを使うと、こういう計算になる。
上のブロックが raw transactionデータ全体を SHA256 計算したもの。
下のブロックはその SHA256 結果をさらに SHA256 計算したものになる。
下のブロックの計算結果は このTXIDの逆順になっている。
<計算結果>
70dadcbbfd3bb8c5af6107db9a6f91b57a4031355e53827b1b2b4406a3efd0a1
<TXID>
a1d0efa306442b1b7b82535e3531407ab5916f9adb0761afc5b83bfdbbdcda70
計算結果そのものの並びを “internal byte order”、逆順にした並びを “RPC byte order” と呼ばれている(用語集)。
おわりに
Decode Rwa Bitcoin Hexadecimal Transactionのようなサイトやライブラリ、bitcoin-cli decoderawtransaction
コマンドなどを使うとトランザクション構造を知らなくても何とかなるのだが、自分でトランザクションデータを作ってブロックチェーンに展開するのであれば知っておいた方がよいと思う。