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

#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"
トランザクションの構成は [参考サイト](https://en.bitcoin.it/wiki/Transaction) を参照してください。**リトルエンディアンである点に注意！！**

```
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 // ロックタイム
```

赤字部分が変更されたところ
"020000000138359278d1ade5b6e59a815c7778756acfb5fd4eae4bc6bc54c826683d9d44a500000000<font color="Red">4961</font>4730440220400f1e3d0ce28bf9fb2ac6749554177b13ec018f6a9171df4ce81883818f70b4022062c77d8271812f68e86b8e8531470d94810e9be304855a086e4d9431c9d68d8e01ffffffff02600d3477000000001976a9147e00e4295f101b0e67b93c98700b2f406bee501f88ac005ed0b20000000017a9145baad546a71ab49cb984c6f3eb43aa423edce3c08700000000"

デコードも問題ない。

```
$ 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を参照しているからコンフリクトが起こっているみたい。
[この辺り](https://bitcoin.stackexchange.com/questions/79004/how-to-cleanup-mempool)を参照し、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"と異なっていることが分かる。