5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ビットコインのtransaction malleabilityを体験してみる

Posted at

#Transaction malleabilityとは
日本語ではトランザクション展性と呼ばれています。
ビットコインではトランザクションに署名を行うのですが、トランザクションの構成要素である、scriptSigという署名を格納するスクリプトには署名を行いません。
scriptSigに署名は行いませんが、トランザクションのID(txid)の計算にscriptSigは絡んできます。
従って、このscriptSigを変更することで、トランザクションの意味を失わずにtxidを変更することが可能になります。これがtransaction malleabilityです。

#準備
regtest環境 (v0.16.3) で実験を行う。
まずはブロックの生成。

$ bitcoin-cli -regtest generate 101
[
  "481154f46e3a0823adadeb08b688095f9dd3a2ad0a0a7a14fcba83734da7a7cb",
  "475cb6e1f629cd78d4b9b59c588ed25b282919d2beabf6582b42a6b67892f602",
   ...
  "3f317090c7eb981b24cfc5318e0c112dd6f57231a0ab389b7826e24002662dab"
]

未使用アウトプットを確認し、50BTC保持していることが分かる。

$ bitcoin-cli -regtest listunspent
[
  {
    "txid": "a5449d3d6826c854bcc64bae4efdb5cf6a7578775c819ae5b6e5add178923538",
    "vout": 0,
    "address": "ms1CW9fcUxTDzs1FquA1p7ck5XVLgY29hk",
    "scriptPubKey": "21037973215150cd5ae90799905a702db97e98aeaa928e98118adf88baf3f1d56658ac",
    "amount": 50.00000000,
    "confirmations": 101,
    "spendable": true,
    "solvable": true,
    "safe": true
  }
]

中身を確認する。

$ bitcoin-cli -regtest gettxout a5449d3d6826c854bcc64bae4efdb5cf6a7578775c819ae5b6e5add178923538 0
{
  "bestblock": "3f317090c7eb981b24cfc5318e0c112dd6f57231a0ab389b7826e24002662dab",
  "confirmations": 101,
  "value": 50.00000000,
  "scriptPubKey": {
    "asm": "037973215150cd5ae90799905a702db97e98aeaa928e98118adf88baf3f1d56658 OP_CHECKSIG",
    "hex": "21037973215150cd5ae90799905a702db97e98aeaa928e98118adf88baf3f1d56658ac",
    "reqSigs": 1,
    "type": "pubkey",
    "addresses": [
      "ms1CW9fcUxTDzs1FquA1p7ck5XVLgY29hk"
    ]
  },
  "coinbase": true
}

新しいアドレスを生成。

$ bitcoin-cli -regtest getnewaddress
2N1bv8S529pHgyjZqocuwnsvMppcymnkS5v

"ms1CW9fcUxTDzs1FquA1p7ck5XVLgY29hk"から"2N1bv8S529pHgyjZqocuwnsvMppcymnkS5v"へ 30BTC 送信してみる。
手数料は0.001BTCとした。

$ bitcoin-cli -regtest createrawtransaction '[{"txid":"a5449d3d6826c854bcc64bae4efdb5cf6a7578775c819ae5b6e5add178923538", "vout":0}]' '{"ms1CW9fcUxTDzs1FquA1p7ck5XVLgY29hk":19.999, "2N1bv8S529pHgyjZqocuwnsvMppcymnkS5v":30}'
020000000138359278d1ade5b6e59a815c7778756acfb5fd4eae4bc6bc54c826683d9d44a50000000000ffffffff02600d3477000000001976a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac005ed0b20000000017a9145baad546a71ab49cb984c6f3eb43aa423edce3c08700000000

署名する。signrawtransactionコマンドの前にwallepassphraseコマンドで秘密鍵のロックを行うのを忘れずに。

$ bitcoin-cli -regtest signrawtransaction 020000000138359278d1ade5b6e59a815c7778756acfb5fd4eae4bc6bc54c826683d9d44a50000000000ffffffff02600d3477000000001976a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac005ed0b20000000017a9145baad546a71ab49cb984c6f3eb43aa423edce3c08700000000
{
  "hex": "020000000138359278d1ade5b6e59a815c7778756acfb5fd4eae4bc6bc54c826683d9d44a500000000484730440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e01ffffffff02600d3477000000001976a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac005ed0b20000000017a9145baad546a71ab49cb984c6f3eb43aa423edce3c08700000000",
  "complete": true
}

#トランザクションの中身を見てみる
signrawtransactionコマンドで返ってきた16進数テキストをデコードする。

$ bitcoin-cli -regtest decoderawtransaction 020000000138359278d1ade5b6e59a815c7778756acfb5fd4eae4bc6bc54c826683d9d44a500000000484730440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e01ffffffff02600d3477000000001976a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac005ed0b20000000017a9145baad546a71ab49cb984c6f3eb43aa423edce3c08700000000
{
  "txid": "aa31a089161541e0993f213d5266142878b556088ea9a8f052f430a112e6f453",
  "hash": "aa31a089161541e0993f213d5266142878b556088ea9a8f052f430a112e6f453",
  "version": 2,
  "size": 189,
  "vsize": 189,
  "locktime": 0,
  "vin": [
    {
      "txid": "a5449d3d6826c854bcc64bae4efdb5cf6a7578775c819ae5b6e5add178923538",
      "vout": 0,
      "scriptSig": {
        "asm": "30440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e[ALL]",
        "hex": "4730440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e01"
      },
      "sequence": 4294967295
    }
  ],
  "vout": [
    {
      "value": 19.99900000,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 7e00e4295f101b0e67b93c98700b2f406bee501f OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "ms1CW9fcUxTDzs1FquA1p7ck5XVLgY29hk"
        ]
      }
    },
    {
      "value": 30.00000000,
      "n": 1,
      "scriptPubKey": {
        "asm": "OP_HASH160 5baad546a71ab49cb984c6f3eb43aa423edce3c0 OP_EQUAL",
        "hex": "a9145baad546a71ab49cb984c6f3eb43aa423edce3c087",
        "reqSigs": 1,
        "type": "scripthash",
        "addresses": [
          "2N1bv8S529pHgyjZqocuwnsvMppcymnkS5v"
        ]
      }
    }
  ]
}

何が起こったかよく分からないので、元の16進を整形してみる。
"020000000138359278d1ade5b6e59a815c7778756acfb5fd4eae4bc6bc54c826683d9d44a500000000484730440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e01ffffffff02600d3477000000001976a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac005ed0b20000000017a9145baad546a71ab49cb984c6f3eb43aa423edce3c08700000000"
トランザクションの構成は 参考サイト を参照してください。リトルエンディアンである点に注意!!

02000000 // バージョン

01 // インプットの数
38359278d1ade5b6e59a815c7778756acfb5fd4eae4bc6bc54c826683d9d44a5 // txid 
00000000 // インデックス
48 // scriptSigのバイト長
47 // 署名のバイト長
30440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e01
ffffffff // シーケンスナンバー

02 // アウトプットの数
600d347700000000 // 19.999 BTC = 1999900000 satoshi = 0x77340D60 satoshi
19 // scriptPubKey のバイト長
76a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac // scriptPubKey
005ed0b200000000 // 30 BTC
17 // scriptPubKey のバイト長
a9145baad546a71ab49cb984c6f3eb43aa423edce3c087 // scriptPubKey

00000000 // ロックタイム

#Transaction malleabilityをやってみる
sendrawtransactionコマンドで、ビットコインネットワーク(この環境でネットワークと呼ぶのは正しくないと思うが)にトランザクションを送信する。

$ bitcoin-cli -regtest sendrawtransaction 020000000138359278d1ade5b6e59a815c7778756acfb5fd4eae4bc6bc54c826683d9d44a500000000484730440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e01ffffffff02600d3477000000001976a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac005ed0b20000000017a9145baad546a71ab49cb984c6f3eb43aa423edce3c08700000000
aa31a089161541e0993f213d5266142878b556088ea9a8f052f430a112e6f453

txid "aa31a089161541e0993f213d5266142878b556088ea9a8f052f430a112e6f453"が返ってきたので、上手くいってる。

このトランザクションの妥当性を失わずにtxidを変えたい。

scriptSigは署名対象ではないが、txidの算出には関わるので、scriptSigをいじればtransaction malleabilityを行うことができる。
scriptSigにOP_NOP(0x61)を加えてみる。

02000000 // バージョン

01 // インプットの数
38359278d1ade5b6e59a815c7778756acfb5fd4eae4bc6bc54c826683d9d44a5 // txid 
00000000 // インデックス
49 // scriptSigのバイト長
OP_NOP(0x61) 47 // 署名のバイト長
30440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e01
ffffffff // シーケンスナンバー

02 // アウトプットの数
600d347700000000 // 19.999 BTC = 1999900000 satoshi = 0x77340D60 satoshi
19 // scriptPubKey のバイト長
76a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac // scriptPubKey
005ed0b200000000 // 30 BTC
17 // scriptPubKey のバイト長
a9145baad546a71ab49cb984c6f3eb43aa423edce3c087 // scriptPubKey

00000000 // ロックタイム

赤字部分が変更されたところ
"020000000138359278d1ade5b6e59a815c7778756acfb5fd4eae4bc6bc54c826683d9d44a50000000049614730440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e01ffffffff02600d3477000000001976a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac005ed0b20000000017a9145baad546a71ab49cb984c6f3eb43aa423edce3c08700000000"

デコードも問題ない。

$ bitcoin-cli -regtest decoderawtransaction 020000000138359278d1ade5b6e59a815c7778756acfb5fd4eae4bc6bc54c826683d9d44a50
000000049614730440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e01ff
ffffff02600d3477000000001976a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac005ed0b20000000017a9145baad546a71ab49cb984c6f3eb43aa423edce3c08700000000
{
  "txid": "055320a1ab4e48e6858d8795b6ff32873447646f833048b1f1806878e32039fa",
  "hash": "055320a1ab4e48e6858d8795b6ff32873447646f833048b1f1806878e32039fa",
  "version": 2,
  "size": 190,
  "vsize": 190,
  "locktime": 0,
  "vin": [
    {
      "txid": "a5449d3d6826c854bcc64bae4efdb5cf6a7578775c819ae5b6e5add178923538",
      "vout": 0,
      "scriptSig": {
        "asm": "OP_NOP 30440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e[ALL]",
        "hex": "614730440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e01"
      },
      "sequence": 4294967295
    }
  ],
  "vout": [
    {
      "value": 19.99900000,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 7e00e4295f101b0e67b93c98700b2f406bee501f OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "ms1CW9fcUxTDzs1FquA1p7ck5XVLgY29hk"
        ]
      }
    },
    {
      "value": 30.00000000,
      "n": 1,
      "scriptPubKey": {
        "asm": "OP_HASH160 5baad546a71ab49cb984c6f3eb43aa423edce3c0 OP_EQUAL",
        "hex": "a9145baad546a71ab49cb984c6f3eb43aa423edce3c087",
        "reqSigs": 1,
        "type": "scripthash",
        "addresses": [
          "2N1bv8S529pHgyjZqocuwnsvMppcymnkS5v"
        ]
      }
    }
  ]
}

再び、sendrawtransactionコマンド。

$ bitcoin-cli -regtest sendrawtransaction 020000000138359278d1ade5b6e59a815c7778756acfb5fd4eae4bc6bc54c826683d9d44a50000000049614730440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e01ffffffff02600d3477000000001976a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac005ed0b20000000017a9145baad546a71ab49cb984c6f3eb43aa423edce3c08700000000
error code: -26
error message:
18: txn-mempool-conflict

同一UTXOを参照しているからコンフリクトが起こっているみたい。
この辺りを参照し、mempoolをクリーンアップ。

$ rm ~/.bitcoin/regtest/mempool.dat
$ bitcoin-cli -regtest stop
$ bitcoind -regtest -zapwallettxes -daemon

もう一度、sendrawtransactionコマンド。

$ bitcoin-cli -regtest sendrawtransaction 020000000138359278d1ade5b6e59a815c7778756acfb5fd4eae4bc6bc54c826683d9d44a50000000049614730440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e01ffffffff02600d3477000000001976a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac005ed0b20000000017a9145baad546a71ab49cb984c6f3eb43aa423edce3c08700000000
055320a1ab4e48e6858d8795b6ff32873447646f833048b1f1806878e32039fa

txid "055320a1ab4e48e6858d8795b6ff32873447646f833048b1f1806878e32039fa"が返ってきた。
先程のtxid "aa31a089161541e0993f213d5266142878b556088ea9a8f052f430a112e6f453"と異なっていることが分かる。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?