hiro99ma blog

何か技術的なこと

トランザクション

最終更新日: 2024/12/11

はじめに

Bitcoinトランザクションには署名の方法などによる違いはあるが、データの構成は決まっている。

構成

Bitcoinトランザクションはバイナリデータである。
以下はバイナリデータを構成している要素の名前である。 この名前は解説しているサイトによって多少違う(versionnVersionだったりlock_timeLockTimeだったり)が、

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非対応のトランザクションで、markerflagがなく 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 計算したものになる。

chiphereditor

下のブロックの計算結果は この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コマンドなどを使うとトランザクション構造を知らなくても何とかなるのだが、自分でトランザクションデータを作ってブロックチェーンに展開するのであれば知っておいた方がよいと思う。

< Top page