Bitcoinトランザクション作成手順 秘密の値でロックするP2SH

秘密の値を知っていれば、誰でもコインを使えるようなトランザクションを作成してみます。

RedeemScriptは、以下のようにします。

```
OP_SHA256 <SecretHash> OP_EQUAL
```

# 前提
* Windows 10 (64bit)
* bitcoind 0.15.1 (regtest)
* libbitcoin explorer
* segwitなし
* regtest
* コマンドプロンプト

ディレクトリ構成

```
<root>
└─bitcoin-0.15.1
    ├─bin
    ├─data
    │  └─regtest
    │      ├─blocks
    │      │  └─index
    │      ├─chainstate
    │      └─database
    ├─include
    ├─lib
    └─share
        └─man
            └─man1
```

# 準備

## bitcoind

### ダウンロード

https://bitcoincore.org/bin/bitcoin-core-0.15.1/

bitcoin-0.15.1-win64.zipをダウンロード。

解凍する。

### 起動

コマンドプロンプトを立ち上げる。

```powershell
> cd bitcoin-0.15.1
> mkdir data
> cd bin
> bitcoind -datadir="..\data" -regtest -printtoconsole -rpcuser=<user> -rpcpassword=<password>
```

`<user>`と`<password>`の箇所は何か入れてください。

### コマンド確認

使えるコマンドが羅列されるか確認。

```powershell
> bitcoin-cli -regtest -rpcuser=<user> -rpcpassword=<password> help
== Blockchain ==
getbestblockhash
getblock "blockhash" ( verbosity )
getblockchaininfo
...
```

以降、`-regtest -rpcuser=<user> -rpcpassword=<password>`は記載を省略します。実際のコマンド投入のときは付けてください。それか、aliasを設定するか、bitcoin.confを使うとよいかもしれません。

bitcoin.confを使う場合は、以下のファイルに以下のように記入します。

```
> notepad.exe %AppData%\Bitcoin\bitcoin.conf
rpcuser=<user>
rpcpassword=<password>
regtest=1
```

### マイニング

100承認ないと、マイニング報酬は使用可能になりません。なので101ブロックを事前にマイニングします。

```powershell
> bitcoin-cli generate 101
> bitcoin-cli getbalance
50.00000000
```


## libbitoin explorer

### ダウンロード

https://github.com/libbitcoin/libbitcoin-explorer/releases

`bx-windows-x64-icu.exe`をダウンロード

### 起動

コマンドプロンプトを立ち上げます。

`bx-windows-x64-icu.exe`があるフォルダに移動してください。

使えるコマンドが羅列されるか確認。

```powershell
> bx-windows-x64-icu.exe help

Usage: bx COMMAND [--help]

Version: 3.2.0

Info: The bx commands are:

address-decode
address-embed
address-encode
...
```

# P2SHアドレス作成

秘密の値を作成

```powershell
> bx-windows-x64-icu.exe seed -b 128
666ba935d6ac853b77cae59f180085b3
```

秘密の値のハッシュを作成

```powershell
> bx-windows-x64-icu.exe sha256 666ba935d6ac853b77cae59f180085b3
9335595211f33e762838007a614887a518fd7bf8434654e1bfe12a7eba6a27f8
```

redeem scriptを作成

```powershell
> bx-windows-x64-icu.exe script-encode "SHA256 [9335595211f33e762838007a614887a518fd7bf8434654e1bfe12a7eba6a27f8] EQUAL"
a8209335595211f33e762838007a614887a518fd7bf8434654e1bfe12a7eba6a27f887
```

script hashを導出

```powershell
> bx-windows-x64-icu.exe bitcoin160 a8209335595211f33e762838007a614887a518fd7bf8434654e1bfe12a7eba6a27f887
aada77d31171bf21f262ea066ed7bc8b0f3aa734
```

P2SH addressを導出

```powershell
> bx-windows-x64-icu.exe base58check-encode -v 196 aada77d31171bf21f262ea066ed7bc8b0f3aa734
2N8pcaKeeCwHq1F6DQc3XTAueAjPjhPMu74
```

# P2SHアドレスに送金

P2SHアドレスへ送金します。トランザクションIDが返ってきます。

```powershell
> bitcoin-cli sendtoaddress 2N8pcaKeeCwHq1F6DQc3XTAueAjPjhPMu74 1
3be9910eb7b38fa494cd4937d517c6246a7f106e6f791f3a20993f9bc3123aab
```

マイニングします。

```powershell
> bitcoin-cli generate 1
```

先ほどのトランザクションを見てみます。confirmationsが1になっており、ブロックに取り込まれたことがわかります。

```powershell
> bitcoin-cli gettransaction 3be9910eb7b38fa494cd4937d517c6246a7f106e6f791f3a20993f9bc3123aab
{
  "amount": -1.00000000,
  "fee": -0.00004480,
  "confirmations": 1,
  "blockhash": "3dd604840ade8e56ca9c6f7f3ae233f7079a0a08dfee93cc57a1cd90d9ae4818",
  "blockindex": 1,
  "blocktime": 1527920143,
  "txid": "3be9910eb7b38fa494cd4937d517c6246a7f106e6f791f3a20993f9bc3123aab",
  "walletconflicts": [
  ],
  "time": 1527920133,
  "timereceived": 1527920133,
  "bip125-replaceable": "no",
  "details": [
    {
      "account": "",
      "address": "2N8pcaKeeCwHq1F6DQc3XTAueAjPjhPMu74",
      "category": "send",
      "amount": -1.00000000,
      "vout": 1,
      "fee": -0.00004480,
      "abandoned": false
    }
  ],
  "hex": "0200000001e8b328e217914c76fcdaf2f92ad2899225d432c9be2d62d74f0dccdac4b493db000000006b48304502210087c63ba58e46c23a6a9ecfe29d77624abd5c55728606ebd3743be9273e4e2dc902205bcbc0fac0ab1727dc9e5baf10b68b8e99c74c2ac38efdb3724171aeb482f667012102f3b361c78b4a8b7aaeac77bbb1dcad4de6671a8b630a74d2e50348400d07dabafeffffff02a80f1a1e010000001976a9149c34642af476cc95780f6073cd6afd33bb85c9dd88ac00e1f5050000000017a914aada77d31171bf21f262ea066ed7bc8b0f3aa7348766000000"
}
```

また、hexには、トランザクションのバイト列が表示されます。こちらも見てみます。ひとつめのアウトプットがおつり用で、ふたつめのアウトプットに送っていることがわかります。

```powershell
> bitcoin-cli decoderawtransaction 0200000001e8b328e217914c76fcdaf2f92ad2899225d432c9be2d62d74f0dccdac4b493db000000006b48304502210087c63ba58e46c23a6a9ecfe29d77624abd5c55728606ebd3743be9273e4e2dc902205bcbc0fac0ab1727dc9e5baf10b68b8e99c74c2ac38efdb3724171aeb482f667012102f3b361c78b4a8b7aaeac77bbb1dcad4de6671a8b630a74d2e50348400d07dabafeffffff02a80f1a1e010000001976a9149c34642af476cc95780f6073cd6afd33bb85c9dd88ac00e1f5050000000017a914aada77d31171bf21f262ea066ed7bc8b0f3aa7348766000000
{
  "txid": "3be9910eb7b38fa494cd4937d517c6246a7f106e6f791f3a20993f9bc3123aab",
  "hash": "3be9910eb7b38fa494cd4937d517c6246a7f106e6f791f3a20993f9bc3123aab",
  "version": 2,
  "size": 224,
  "vsize": 224,
  "locktime": 102,
  "vin": [
    {
      "txid": "db93b4c4dacc0d4fd7622dbec932d4259289d22af9f2dafc764c9117e228b3e8",
      "vout": 0,
      "scriptSig": {
        "asm": "304502210087c63ba58e46c23a6a9ecfe29d77624abd5c55728606ebd3743be9273e4e2dc902205bcbc0fac0ab1727dc9e5baf10b68b8e99c74c2ac38efdb3724171aeb482f667[ALL] 02f3b361c78b4a8b7aaeac77bbb1dcad4de6671a8b630a74d2e50348400d07daba",
        "hex": "48304502210087c63ba58e46c23a6a9ecfe29d77624abd5c55728606ebd3743be9273e4e2dc902205bcbc0fac0ab1727dc9e5baf10b68b8e99c74c2ac38efdb3724171aeb482f667012102f3b361c78b4a8b7aaeac77bbb1dcad4de6671a8b630a74d2e50348400d07daba"
      },
      "sequence": 4294967294
    }
  ],
  "vout": [
    {
      "value": 47.99991720,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 9c34642af476cc95780f6073cd6afd33bb85c9dd OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a9149c34642af476cc95780f6073cd6afd33bb85c9dd88ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "muktUBwtsrdKT4iERXAP9AVYrYoPFHwQoY"
        ]
      }
    },
    {
      "value": 1.00000000,
      "n": 1,
      "scriptPubKey": {
        "asm": "OP_HASH160 aada77d31171bf21f262ea066ed7bc8b0f3aa734 OP_EQUAL",
        "hex": "a914aada77d31171bf21f262ea066ed7bc8b0f3aa73487",
        "reqSigs": 1,
        "type": "scripthash",
        "addresses": [
          "2N8pcaKeeCwHq1F6DQc3XTAueAjPjhPMu74"
        ]
      }
    }
  ]
}
```

# P2SHアドレスから出金

先ほど送ったトランザクションをインプットにして、自分のアドレスへ送金します。

まず、自分のアドレスを確認します。

```powershell
> bitcoin-cli getaccountaddress ""
muGQPeUuHbUfigatjysh9wRxLv4zbCP9bz
```

トランザクションを作ります。インプットとなるトランザクションIDと、送り先と量を指定します。

```powershell
> bitcoin-cli createrawtransaction "[{\"txid\":\"3be9910eb7b38fa494cd4937d517c6246a7f106e6f791f3a20993f9bc3123aab\",\"vout\":1}]" "{\"muGQPeUuHbUfigatjysh9wRxLv4zbCP9bz\":0.99}"
0200000001ab3a12c39b3f99203a1f796f6e107f6a24c617d53749cd94a48fb3b70e91e93b0100000000ffffffff01c09ee605000000001976a91496d14e45a09d77a0fa3eca7392c8d01e633a9c2d88ac00000000
```

ScriptSigはまだ空なのがわかります。

```powershell
> bitcoin-cli decoderawtransaction 0200000001ab3a12c39b3f99203a1f796f6e107f6a24c617d53749cd94a48fb3b70e91e93b0100000000ffffffff01c09ee605000000001976a91496d14e45a09d77a0fa3eca7392c8d01e633a9c2d88ac00000000
{
  "txid": "f5496c4011538543e056558cad30b81624ddbab51725dffb01c4add51787212d",
  "hash": "f5496c4011538543e056558cad30b81624ddbab51725dffb01c4add51787212d",
  "version": 2,
  "size": 85,
  "vsize": 85,
  "locktime": 0,
  "vin": [
    {
      "txid": "3be9910eb7b38fa494cd4937d517c6246a7f106e6f791f3a20993f9bc3123aab",
      "vout": 1,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "sequence": 4294967295
    }
  ],
  "vout": [
    {
      "value": 0.99000000,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 96d14e45a09d77a0fa3eca7392c8d01e633a9c2d OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a91496d14e45a09d77a0fa3eca7392c8d01e633a9c2d88ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "muGQPeUuHbUfigatjysh9wRxLv4zbCP9bz"
        ]
      }
    }
  ]
}
```


なので、これからScriptSigを作っていきます。

まず、ScriptSigを入れるべき場所についてです。

先ほど作ったトランザクションを分解します。

| Item             |        | Data                |
|:----------------:|:------:|:--------------------|
| version          | 4byte  | 02000000            |
| input-count      | varint | 01                  |
| previous-txhash  | 32byte | ab3a12c3...e93b     |
| output-index     | 4byte  | 01000000            |
| scriptsig-length | varint | 00                  |
| scriptsig        | -      | -                   |
| ...              | -      | ...                 |

これを見ると、scriptsig-lengthを変更し、その後ろにscriptsigを挿入することになります。

次に、ScriptSigに入れるべきデータは、以下のようになります。

```
<Secret> <RedeemScript>
```

ではScriptSigを作ります。

```powershell
> bx-windows-x64-icu.exe script-encode "[666ba935d6ac853b77cae59f180085b3] [a8209335595211f33e762838007a614887a518fd7bf8434654e1bfe12a7eba6a27f887]"
10666ba935d6ac853b77cae59f180085b323a8209335595211f33e762838007a614887a518fd7bf8434654e1bfe12a7eba6a27f887
```

このデータは53byteですので、scriptsig-lengthは35になります。

データを挿入し、送信します。成功すれば、トランザクションIDが返ってきます。

```
> bitcoin-cli sendrawtransaction 0200000001ab3a12c39b3f99203a1f796f6e107f6a24c617d53749cd94a48fb3b70e91e93b010000003510666ba935d6ac853b77cae59f180085b323a8209335595211f33e762838007a614887a518fd7bf8434654e1bfe12a7eba6a27f887ffffffff01c09ee605000000001976a91496d14e45a09d77a0fa3eca7392c8d01e633a9c2d88ac00000000
3efcdc86c5665892ab74c5a40696f36c2d7b600467a6c2ed563486804f910d9a
```

マイニングします。ブロックハッシュが返ってきます。

```powershell
> bitcoin-cli generate 1
[
  "2465bb4f8a833fbe112a645189fbb43b9a5b0783b8492cbb250a6abba7952a96"
]
```

今度は、ブロックを見てみます。

```powershell
> bitcoin-cli getblock 2465bb4f8a833fbe112a645189fbb43b9a5b0783b8492cbb250a6abba7952a96
{
  "hash": "2465bb4f8a833fbe112a645189fbb43b9a5b0783b8492cbb250a6abba7952a96",
  "confirmations": 1,
  "strippedsize": 365,
  "size": 365,
  "weight": 1460,
  "height": 104,
  "version": 536870912,
  "versionHex": "20000000",
  "merkleroot": "6c4762260057d1ec4dbc3a1ed9fc8566d89ab6fb1adfb74214b0e07a3edbe833",
  "tx": [
    "0976c13963e050b6878a44644393f3f2c506372bed4f8ee5b0d07c71849d565b",
    "3efcdc86c5665892ab74c5a40696f36c2d7b600467a6c2ed563486804f910d9a"
  ],
  "time": 1527920432,
  "mediantime": 1527912456,
  "nonce": 0,
  "bits": "207fffff",
  "difficulty": 4.656542373906925e-010,
  "chainwork": "00000000000000000000000000000000000000000000000000000000000000d2",
  "previousblockhash": "3dd604840ade8e56ca9c6f7f3ae233f7079a0a08dfee93cc57a1cd90d9ae4818"
}
```

`3efcdc86...`のトランザクションが入っていることが確認できます。

# コメント
* P2SHアドレスからの出金トランザクションは、署名で守られていません。ノードかマイナーによって、改ざんされる可能性があります。
* P2PKHのインプットをもう一つ作り、SIGHASH_ALLで署名すれば、改ざんは防げるかもしれません。
* もしくは、秘密の値＋署名が必要となるようなRedeemScriptにすれば、改ざんされません。
* その場合、署名を作成する手順が増えるので、今回は割愛しました。

ちなみに、秘密の値＋署名が必要となるようなスクリプトは、以下のようになると思います。

```
OP_HASHxxx <SecretHash> OP_EQUALVERIFY OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
```