hiro99ma blog

トランザクション

目次 (最終更新日:2025/04/15)
  • TXID
  • おわりに
  • 関連ページ
  • はじめに

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

    構成

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

    transaction(not witness structure)

    witness structure と比較すると markerflag がない。
    marker = 0x00 なので、そのデータをこの not witness structure に当てはめると txin_count がゼロになって不可になってしまう。
    つまり、version の次の 1 バイトが 0x00 なら witness structure、そうでないなら 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

    script_witness は各 vin ごとに存在する。

    item size unit
    witness_count   compact size
    scripts   stack[witness_count]

    stack

    scriptSig と違い、全体のデータ長 を compact size 型で示した後、そのサイズ分のデータが載る。
    例えば P2TR key path では 64 バイトの署名データだけなので、先頭に 0x40、それに 64 バイトのデータが続く。
    わかりにくい違いであるが、たとえば 1 ~ 16 だけのデータをスタックに載せる場合は OP_1OP_16 ではなく 0x01010x0110 になる。
    null 値に相当するデータはデータ長 0 の 0x00 だけを使う(scriptSig と同じ)。

    item size unit
    size   compact size
    script size char[size]

    説明

    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(P2TR key path)

    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
    

    例4: Segwit(P2TR script path)

    cd399d2312218711c6a4a80863e7b101a40e310118bc094f601c170965133eda

    <全 raw transaction データ>
    02000000000101079eca858d65c783a6f4e47ee4fbe0aaa7fa28023c263a962e70888d2d1a2ad00000000000fdffffff012202000000000000225120d1c1c55764e7795ba8e627a80a78c5a140611f3dbef0464c7a0c85ca34d56a3303401b52cc0ce1a7fcfb0518dc4b9f94d31d9589c1a15dd833ad456b66dd384500dcfc47716b4c48bd7d4e4cc93759279043eaeae484202c109a665f363fcce86ce4c720585fb99f72a8daecb1beb80cd7a06deb470fc71153ef3da5043e3a47cd376c13ad0200000063406c012bb4be7567f316165c1ba71e99620638d2b78b40d5e0a0ceb629ecf4fd9678dec2fa3382247ca8d40b65025ff9e881ae5f777748b156e3826aa808d6457a2103015a7c4d2cc1c771198686e2ebef6fe7004f4136d61f6225b061d1bb9b821b9b310032697a89a1631d0ff34bfafaa20fe0af9e7de6919eae68126b3a6814c7e79a4601ab0d0000000000e8ae0d00000000006808945f0000000000007721c0585fb99f72a8daecb1beb80cd7a06deb470fc71153ef3da5043e3a47cd376c1300000000
    --------------------------
    <version>
    02000000
    
    <marker, flag>
    0001
    
    <txin_count>
    01
    
    <txins[0]>
      <txid:index>
      079eca858d65c783a6f4e47ee4fbe0aaa7fa28023c263a962e70888d2d1a2ad000000000
      <scriptSig>
      00
      <sequence>
      fdffffff
    
    <txout_count>
    01
    
    <txouts[0]>
      <value>
      2202000000000000
      <scriptPubkey>
      225120d1c1c55764e7795ba8e627a80a78c5a140611f3dbef0464c7a0c85ca34d56a33
    
    <script_witnesses>
      <txins[0]>
        <witness_count>
        03
        <witness[0]>
        401b52cc0ce1a7fcfb0518dc4b9f94d31d9589c1a15dd833ad456b66dd384500dcfc47716b4c48bd7d4e4cc93759279043eaeae484202c109a665f363fcce86ce4
        <witness[1]>
        c720585fb99f72a8daecb1beb80cd7a06deb470fc71153ef3da5043e3a47cd376c13ad0200000063406c012bb4be7567f316165c1ba71e99620638d2b78b40d5e0a0ceb629ecf4fd9678dec2fa3382247ca8d40b65025ff9e881ae5f777748b156e3826aa808d6457a2103015a7c4d2cc1c771198686e2ebef6fe7004f4136d61f6225b061d1bb9b821b9b310032697a89a1631d0ff34bfafaa20fe0af9e7de6919eae68126b3a6814c7e79a4601ab0d0000000000e8ae0d00000000006808945f00000000000077
        <witness[2]>
        21c0585fb99f72a8daecb1beb80cd7a06deb470fc71153ef3da5043e3a47cd376c13
    
    <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)。 そうなってしまう場合は頭に 0x00 を付けるようにする。
    署名は RS の 2つで構成されるので、署名データ長だけでいうと以下の3パターンがある。

    DER形式の部分だけで 70~72 バイトと幅がある。署名のデータ長を加えると 71~73 バイトになるし、署名タイプを加えると 72~74 バイトになる。

    P2TR というか、シュノア署名の場合はサイズが 64 バイト固定である。 署名対象が全体の場合は署名タイプを省略する(SIGHASH_DEFAULT)のでデータ長を加えても 65 バイト固定になる。

    おわりに

    Decode Rwa Bitcoin Hexadecimal Transactionのようなサイトやライブラリ、bitcoin-cli decoderawtransactionコマンドなどを使うとトランザクション構造を知らなくても何とかなるのだが、自分でトランザクションデータを作ってブロックチェーンに展開するのであれば知っておいた方がよいと思う。

    関連ページ

    writer: hiro99ma
    tags: Bitcoin開発  

     < Top page

    コメント(Google Formへ飛びます)

    GitHub

    X/Twitter

    Homepage

    About me