[Bitcoin] dockerを使ったregtest環境でのお手軽bitcoind ハンズオン

# bitcoind ハンズオン

## はじめに
もはや何番煎じかわからないですがせっかく作ったので公開します。
これは[村井純研究室Bcali Group](https://bcali.org)の新人研修ハンズオンとして作ったものです。

## ハンズオン内容
このハンズオンではdocker環境でregtestモードのbitcoindを用いた送金を行う方法を学ぶ。

## ハンズオンの前に

![](https://i.imgur.com/VE8Eiad.png)


今回のハンズオンで使用するのはregtestと呼ばれるローカルで実行するBitcoinの環境である。
mainnetやtestnetとは異なり、メッセージのやり取りや、block/txのブロードキャストのようなノード同士のコミュニケーションはない。なのでPeer to Peerの面白みを感じることはできない。
１つのノード上にwalletを複数作成し、送金・マイニングを行うBitcoinのコマンドライン操作について学ぶためのハンズオンであることに留意してほしい。

## 環境構築
Dockerのインストール方法については説明しない。

使うdocker image
https://hub.docker.com/r/bitcoindevelopernetwork/bitcoind-regtest

docker imageをpullし、コンテナの起動。

```
docker pull bitcoindevelopernetwork/bitcoind-regtest
docker run <IMAGE ID>
```

別タブを開き、コンテナに接続

```
docker exec -it <コンテナ> bash
```

以後、コンテナ内で操作。

## 基本のコマンドとオプション
BitcoinCoreの公式が以下で各コマンド操作の方法を説明している。
https://bitcoincore.org/en/doc/0.20.0/rpc/util/createmultisig/

ブロックチェーンの情報を取得するコマンドを実行。

```shell
$ bitcoin-cli getblockchaininfo
{
  "chain": "regtest",
  "blocks": 0,
  "headers": 0,
  "bestblockhash": "109deb99f483919d60f3204906be91043f57252466a86e5c0dee9b027f516738",
  "difficulty": 4.656542373906925e-10,
  "mediantime": 1623243522,
  "verificationprogress": 1,
  "initialblockdownload": false,
...
```

よく使うオプション

| オプション | 説明 | 例 |
| -------- | -------- | -------- |
| -mainnet, -testnet, -regtest | コマンド実行に使用するBitcoin networkの種類 |  |
| -rpcuser, -rpcpassword | RPC呼び出しに使用するユーザー名とパスワード | -rpcuser=user |
| -rpcwallet | コマンド実行時に使用するWallet名 | -rpcwallet=wallet1 |


コマンド例)

```shell
$ bitcoin-cli -testnet -rpcuser=user -rpcpassword= -rpcport=10001 -rpcwallet=wallet1 getnewaddress
```

## Walletの作成
![](https://i.imgur.com/drnh59v.png)

"wallet1"という名前のwalletを作成する

```shell
$ bitcoin-cli -regtest createwallet "wallet1"
{
  "name": "wallet1",
  "warning": ""
}
```

同じノード上で別のwalletを作成

```shell
$ bitcoin-cli -regtest createwallet "wallet2"
{
  "name": "wallet2",
  "warning": ""
}
```

## addressの生成
送金の際の宛先となるアドレスの生成を行う。
特定のwalletを使用する操作は`-rpcwallet`オプションをつける必要がある。

```shell
$ bitcoin-cli -regtest -rpcwallet=wallet1 getnewaddress
2NBCnpWoqZzF1qS9zVPW1k1ofvrQVmjqea7
```

wallet2の方でも実行

```shell
$ bitcoin-cli -regtest -rpcwallet=wallet2 getnewaddress
2NCWaopFpatcD7VHPTxaa2RnM1Wc9qB11S2
```

## マイニングによる報酬の取得

### 実行前の所持金の確認
実行前の所持金がゼロであることを確認。
* getbalance

```shell
$ bitcoin-cli -regtest -rpcwallet=wallet1 getbalance
0.00000000
```

* listunspent

```shell
$ bitcoin-cli -regtest -rpcwallet=wallet1 listunspent
[
]
```

### マイニングの実行
![](https://i.imgur.com/kHjQZ4l.png)

送金に使用するコインを得るため、walletでマイニングを行い、ブロック報酬を受け取る
`bitcoin-cli -rpcwallet=<walletの名前> generatetoaddress <生成するblock数> <報酬を受け取るアドレス>`

マイニングを実行

```shell
bitcoin-cli -regtest -rpcwallet=wallet1 generatetoaddress 101 "2NDWSqmyNQrWdD2QtJrrtEGEfZWrshWcvL6"
```
(101ブロック生成されないと残高が認識されない？)

### 実行後の所持金の確認
* getbalance

```shell
bitcoin-cli -regtest -rpcwallet=wallet1 getbalance
```

* listunspent

```shell
bitcoin-cli -regtest -rpcwallet=wallet1 listunspent
```

## 送金
### 送金の実行
![](https://i.imgur.com/VyTkfJF.png)


wallet1からwallet2へ`0.01BTC`送金

```shell
$ bitcoin-cli -rpcwallet=wallet1 sendtoaddress <wallet2のアドレス> 0.01
76e72b6683b7a408f884cd5dd4cee5050d360cb8f32f5bb8627c7c64d6b89926
```

実行すると文字列が返ってくる。これはtransactionのidである。

### 残高の確認
一度walletの残高を確認してみる。
**この段階ではトランザクションが承認されていないため残高としてう認識されない**
なので0が返ってくるはずである。

```shell
bitcoin-cli -regtest -rpcwallet=wallet1 getbalance
0.00000000
```

### マイニング

```shell
bitcoin-cli -regtest -rpcwallet=wallet1 generatetoaddress 1 "2NDWSqmyNQrWdD2QtJrrtEGEfZWrshWcvL6"
```

### 残高の確認
* getbalance

```shell
bitcoin-cli -regtest -rpcwallet=wallet1 getbalance
```

* listunspent

```shell
bitcoin-cli -regtest -rpcwallet=wallet1 listunspent
```

## トランザクションの情報の確認
```shell
$ bitcoin-cli -regtest -rpcwallet=wallet1 gettransaction 76e72b6683b7a408f884cd5dd4cee5050d360cb8f32f5bb8627c7c64d6b89926
{
  "amount": 0.01000000,
  "confirmations": 1,
  "blockhash": "282bd6bcae1d20189354d28aa395a38c213f83283bf1965f404becf6e7045b21",
  "blockindex": 1,
  "blocktime": 1623255101,
  "txid": "76e72b6683b7a408f884cd5dd4cee5050d360cb8f32f5bb8627c7c64d6b89926",
  "walletconflicts": [
  ],
  "time": 1623253089,
  "timereceived": 1623253089,
  "bip125-replaceable": "no",
  "details": [
    {
      "address": "2N1mPv3ybesM6xgahTXZyhVy93q1yphvzzP",
      "category": "receive",
      "amount": 0.01000000,
      "label": "",
      "vout": 0
    }
  ],
  "hex": "020000000001018e653bc6d18573d92e53e9718b864d1ad6cb7508f22d931939cf3c355aa8b92f0000000017160014a7e29b84bdf1250c5bc934b81778d2f042268523feffffff0240420f000000000017a9145d75c594845f0a1a451656b8a72959a92e982e8d87c8a2f6290100000017a91443f3ee36da527deb79d03e4272d13201a68aa4d2870247304402207b873d7b6bcb4f6985adeeb13f0473ee2e28a32ab982c435e46b1cae18f81d230220617958f60b7c4319c7583fe02d878f811742df9475bd8f76f435682baf7ebdd70121037147b16d714d716ebb3bf281b923ad6462436e24f02f8563395d8ad1323a87cf7a000000"
}

```


### Bitcoinの操作を完璧にマスターしたい人へ
以下の資料はBitcoinの操作を網羅的に解説している
https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line


また、mainnetやtestnetはregtestと全く違ったP2P独特の面白さがあひろ
ぜひ実際にトライしてみてほしい。