トランザクション
最終更新日: 2024/12/11
はじめに
Bitcoinトランザクションには署名の方法などによる違いはあるが、データの構成は決まっている。
構成
Bitcoinトランザクションはバイナリデータである。
以下はバイナリデータを構成している要素の名前である。
この名前は解説しているサイトによって多少違う(version
がnVersion
だったりlock_time
がLockTime
だったり)が、
transaction(not witness structure)
item | size | unit | note |
---|---|---|---|
version | 4 | int32_t |
|
txin_count | - | compact size | 0 は不可 |
txins[] | - | txin[txin_count] |
|
txout_count | p | compact size | 0 は不可 |
txouts[] | - | txout[txout_count] |
|
lock_time | 4 | uint32_t |
segwit 以前はこの構造のみだった。
transaction(witness structure)
item | size | unit | note |
---|---|---|---|
version | 4 | int32_t |
|
marker, flag | 1, 1 | uint8_t , uint8_t |
0x00 , 0x01 (BIP-141) |
txin_count | - | compact size | 0 は不可 |
txins[] | - | txin[txin_count] |
|
txout_count | - | compact size | 0 は不可 |
txouts[] | - | txout[txout_count] |
|
script_witnesses[] | - | script_witness[txin_count] |
|
lock_time | 4 | uint32_t |
script_witnesses
の数は txin_count
と同じである。
txin
item | size | unit |
---|---|---|
txid | 32 | char[32] |
index | 4 | uint32_t |
scriptSig | script | |
sequence | 4 | uint32_t |
txout
item | size | unit |
---|---|---|
value | 8 | uint64_t |
scriptPubKey | script |
script_witness
item | size | unit |
---|---|---|
witness_count | compact size | |
scripts | script[witness_count] |
説明
witness 先頭から 5byte目のデータで見分ける。
segwit(witness)のトランザクションの場合、その位置に0x00
が入っている。その場合は marker(0x00)
とflag(0x01)
が並んでいる。
それ以外の場合は segwit非対応のトランザクションで、marker
とflag
がなく 5byte 目からtxin_count
のデータが入っている。
Serializationの表に “Type” 列があるが、これがそれぞれのデータタイプである。
スクリプトの中に数値が使われる場合は命令と組み合わせて使うため Compact Size型 とは別の表現になる(Constants)。
データ例
例としていくつか raw transaction(生のトランザクションバイナリデータ)を分解する。
“<script~>
” となっている項目は、先頭がデータ長でその後ろにデータ長分のデータが続いている。
“<script_witnesses>
” は少し特殊で、全体の数は <txin_count>
で、それぞれスクリプトの個数とスクリプトが続いている。
例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
<txins[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” と呼ばれている(用語集)。
TXIDとWTXID
segwit(segregated witness) が登場するまで TXID はトランザクションの全データをハッシュ計算に含めていた。
segwit 時代になってトランザクション構造が増え、トランザクションを指す ID として WTXID が追加された。
TXID は従来の TXID と同じ立ち位置で、segwit 構造のトランザクションではハッシュ値の計算に segwit 部分を除外した部分を計算に使っている。
もう 1つは WTXID で、これはトランザクションデータ全体を計算する(以前の TXID と同じ計算方法)。
ブロックで merkle root hash を計算するのには WTXID を使い、それ以外では TXID を使うことが多いだろう。
バージョン
トランザクションバージョン
version 1
初回のバージョン。
version 2
version 2 以降のトランザクションは BIP-68 に対応していることになる。
version 3
version 3 はまだドラフトなようだが試作版が Bitcoin Core に実装されているとのこと。
署名
楕円曲線の署名をスクリプトに載せることがある。
DER形式なのだが先頭の値が 0x80
以上になってはいけない(stackexchange)。
おわりに
Decode Rwa Bitcoin Hexadecimal Transactionのようなサイトやライブラリ、bitcoin-cli decoderawtransaction
コマンドなどを使うとトランザクション構造を知らなくても何とかなるのだが、自分でトランザクションデータを作ってブロックチェーンに展開するのであれば知っておいた方がよいと思う。