Bitcoin Coreを触ってみた

いつもお世話になっております。
ブロックチェーン勉強会リーダーの湯浅です。
蒸し暑い日が続いておりますが、皆様いかがお過ごしでしょうか。
この記事はBitcoin、ブロックチェーンの基礎入門編になります。

アドベントカレンダーぶりのブロックチェーンネタですね。blog.engineer.adways.net

株式会社アドウェイズのブロックチェーン勉強会では、一番初めの手習いとして『ブロックチェーン 仕組みと理論サンプルで学ぶFinTechのコア技術』 を勉強します。
第11章の『Bitcoin Core』を参考にしております。

Bitcoin Coreとは

Bitcoinのプログラムです。
ブロックチェーン基盤です。
Bitcoinってプログラムなんですよ。
しかも、オープンソース(無料)のプログラム。
無料のプログラムが生成する仮想通貨が法定通貨と交換できる。

すごい・・・親父が熱中するわけだ。

Bitcoin Coreは、

  1. bitcoin-daemon(bitcoind)
  2. bitcoin-cli
  3. bitcon.-qt

のパッケージから構成されています。

環境構築

今回は、Docker上にコンテナを立て、bitcoindをregtestで動作させます。
Dockerfileを作りました。
Dockerfileは以下になります。

Dockerfile

FROM ubuntu:16.04
RUN apt-get update -y && apt-get upgrade -y
RUN apt-get install -y python-software-properties
RUN apt-get install -y software-properties-common
RUN add-apt-repository ppa:bitcoin/bitcoin
RUN apt-get update -y
RUN apt-get install -y bitcoind
RUN mkdir ~/.bitcoin
RUN echo "rpcuser=test\nrpcpassword=test\nregtest=1" > ~/.bitcoin/bitcoin.conf
RUN apt-get install iputils-ping net-tools vim -y
CMD ["/bin/bash"]

Ubuntu 16.04をベースのイメージとして使います。
Bitcoin Coreのバージョンを指定してません。
バージョン起因で、動かない場合は指定してください。
著者はv0.16で実行しております。
dockerのubuntu 16.04なので、色々と欠けています。
vimとかifconfigとか、デフォルトでは入っていないので、ここで入れちゃってます。

Bitcoinのdaemon (bitcoind)は ~/.bitcoin/bitcoin.confを読み込みます。
Dockerfile内で、confに設定を最初に書き込んでいます。
RUN echo "rpcuser=test\nrpcpassword=test\nregtest=1" > ~/.bitcoin/bitcoin.conf

bitcoin.confは以下の3つの要素からなっています。

  1. rpcuser=test
  2. rpcpassword=test
  3. regtest=1

rpcuserとrpcpasswordはオマジナイですね。
詳しくは割愛します。
テスト環境なので、このような簡単な設定です。
重要なのは regtest=1です。

Bitcoinには、3つのネットワークがあります。

  1. mainnet: 本番のネットワーク
  2. testnet: 本番同様のテストネットワーク
  3. regtest: ローカルのテストネットワーク

bitcoin.conf内にregtestと明示しておくことで、ローカルのテストネットワークで動作します。
今回は、Dockerでコンテナを立てて、そこでbitcoindをregtestで動作させます。
何も書かないとmainnetに接続します。
ブロックの同期をはじめてブロックのダウンロードを行うので注意してください。

さて、次に

docker-compose.yml

version: "2"
services:
  daemon_one:
    build: "./"
    image: "bitcoind:regtest"
    container_name: 'bitcoin_1'
    hostname: 'bitcoin_1'
    environment:
      - LINE=50
      - COLUMNS=120
    tty: true
    stdin_open: true
    links:
      - daemon_two
      - daemon_three
  daemon_two:
    image: "bitcoind:regtest"
    container_name: 'bitcoin_2'
    hostname: 'bitcoin_2'
    tty: true
    stdin_open: true
  daemon_three:
    image: "bitcoind:regtest"
    container_name: 'bitcoin_3'
    hostname: 'bitcoin_3'
    tty: true
    stdin_open: true

docker-composeを使います。
読者の皆さん、ついて来れてますか?
『Dockerとdocker-composeが、わからない』
がんばってください。
人類の種内競争を共に生き抜きましょう。

大丈夫、あなたなら出来るわ。

上記のDockerfileとdocker-compose.ymlを作成してください。
ここまできたら、あとは大体コピペで出来ます。
灰色で囲われたコマンドをコピペするだけ

docker-compose build
して、docker imageを作ります。
docker-compose up -d
して、コンテナが3つ立ち上がると思います。
bitcoin_1とbitcoin_2とbitcoin_3というコンテナが出来たと思います。
ターミナルを開いて、コンテナに入ります。
docker exec -it bitcoin_1 /bin/bash

作成されたコンテナは同じセグメント内のネットワークに接続されますので、通信が可能です。
ping bitcoin_2
Pongが返って来ると思います。

いざ、お遊びタイム

cat ~/.bitcoin/bitcoin.conf

root@bitcoin_1:/# cat ~/.bitcoin/bitcoin.conf
rpcuser=test
rpcpassword=test
regtest=1

bitcoin.confに、設定が反映されてますね。
bitcoin_1のbitcoindを起動します。
bitcoind -daemon

こいつ、動くぞ!

root@bitcoin_1:/# bitcoind -daemon
Bitcoin server starting

bitcoin-cliというコマンドラインインターフェイスを用います。
cliとdaemonはJSON-RPCを使っています。

ブロックを100個作成します。
bitcoin-cli generate 100

こんな感じの表示になると思います。
※ハッシュはランダムなので実行結果と記事の内容は違います。

root@bitcoin_1:/# bitcoin-cli generate 100
[
  "4b39fd83e743acd2b1780771ec88dd959eadc3290c1885011f3fe010d2ece0c2",
  "03d1716ce3deb63d286ce78fdbc1ff3973e4232a08958f9b2b7100a923fd6b80",
  "453b40f76fcd4a565868d4774cc6446767336513e611326d648e441f6aa5784e",
  "02d679bcdb2e013b3af27bdd165209d85dcabaea72ae28fd7fccffcd869e44de",
  "27305848a93b1ca007c0437628beac00790bfe28b843706e69fc9f643f6bb885",...

bitcoin-cli getblockcount

root@bitcoin_1:/# bitcoin-cli getblockcount
100

これが、マイニングという行為です。
regtest環境なので、凄く早くブロックが作成されました。

では、早速マイニングの報酬を確認しましょう。

bitcoin-cli getbalance

root@bitcoin_1:/# bitcoin-cli getbalance
0.00000000

0です。
リワードは100個あとのブロックに達してから。
なので101個目のブロックを掘ります。

bitcoin-cli generate 1
※ハッシュはランダムなので実行結果と記事の内容は違います。

root@bitcoin_1:~# bitcoin-cli generate 1
[
  "6d78f6db7dcd373751b2d6e5e964ff63ed00b86638c744bdf6f64063141a6318"
]

現在のBitcoin保持数を表示してみましょう。
101ブロック掘ったので、1個目のリワードがcoinbaseから払われているはずです。
bitcoin-cli getbalance

root@bitcoin_1:/# bitcoin-cli getbalance
50.00000000

増えてる・・・!

50Bitcoinです。
そうです、これが仮想通貨です。
これが、暗号通貨です。
テスト環境のビットコインです。
子供銀行券みたいな感じの、オモチャの仮想通貨ですね。

ブロックチェーン技術を用いた暗号通貨の世界にようこそ!

新しいアカウントを作成します。
bitcoin-cli getnewaddress mywallet1
※アドレスはランダムなので実行結果と記事の内容は違います。

root@bitcoin_1:/# bitcoin-cli getnewaddress mywallet1
2MwgCrQY7fTFjCzjrB2tdSQtxHNhGvPJt4K

このアカウントは後で使います。
アカウントの残高は引数に指定すれば取得できます。
bitcoin-cli getbalance mywallet1

root@bitcoin_1:/# bitcoin-cli getbalance mywallet1
0.00000000

0ですね。
bitcoin-cli listaccounts
でも確認できます。

root@bitcoin_1:/# bitcoin-cli listaccounts
{
  "": 50.00000000,
  "mywallet1": 0.00000000
}

では、送金してみましょう。
mywallet1のアドレスを表示します。
bitcoin-cli getaddressesbyaccount mywallet1
※アドレスはランダムなので実行結果と記事の内容は違います。

root@bitcoin_1:/# bitcoin-cli getaddressesbyaccount mywallet1
[
  "2MwgCrQY7fTFjCzjrB2tdSQtxHNhGvPJt4K"
]

sendtoaddress ADDRESS AMOUNT の順番です。
bitcoin-cli sendtoaddress <mywallet1のアドレス> 10
※アドレスとハッシュはランダムなので実行結果と記事の内容は違います。自身のアドレスを入れてください。

root@bitcoin_1:/# bitcoin-cli sendtoaddress 2MwgCrQY7fTFjCzjrB2tdSQtxHNhGvPJt4K 10
bb56ed73fedecf6fd66d83fac31c42f1535490a925cecb2e75488ee494f2d605

表示されているのはtxidと呼ばれる、トランザクションのIDです。

作成したトランザクションを確認してみます。
bitcoin-cli listunspent 0
※アドレスとハッシュはランダムなので実行結果と記事の内容は違います。

root@bitcoin_1:/# bitcoin-cli listunspent 0
[
  {
    "txid": "bb56ed73fedecf6fd66d83fac31c42f1535490a925cecb2e75488ee494f2d605",
    "vout": 0,
    "address": "2MyD56KL3vAM6eFs2aycSxqw89vtQ9hENYv",
    "redeemScript": "0014c78ad6d512d56c770e80eaaeed340210fe53a730",
    "scriptPubKey": "a91441687f2d4a13e57e064572422312bf101a1da8de87",
    "amount": 39.99996240,
    "confirmations": 0,
    "spendable": true,
    "solvable": true,
    "safe": true
  },
  {
    "txid": "bb56ed73fedecf6fd66d83fac31c42f1535490a925cecb2e75488ee494f2d605",
    "vout": 1,
    "address": "2MwgCrQY7fTFjCzjrB2tdSQtxHNhGvPJt4K",
    "account": "mywallet1",
    "redeemScript": "0014ae925009ad2735524c7ea9235f6b4577ee955278",
    "scriptPubKey": "a9143099f43c8261d6b86a32e95295083684b7b98ee987",
    "amount": 10.00000000,
    "confirmations": 0,
    "spendable": true,
    "solvable": true,
    "safe": true
  }
]

トランザクションはブロックに書き込まれて、成立します。
なので、1ブロック作成します。
bitcoin-cli generate 1
※ハッシュはランダムなので実行結果と記事の内容は違います。

root@bitcoin_1:/# bitcoin-cli generate 1
[
  "23d95c1310a4134922b55ac2cbc2e44762a0ab7413e6ef28b792004124e7131d"
]

確認してみましょう。
bitcoin-cli listaccounts

root@bitcoin_1:/# bitcoin-cli listaccounts
{
  "": 89.99996240,
  "mywallet1": 10.00000000
}

端数になってますね。
これは、トランザクションの手数料を払ったためです。
なので、10ビットコインと手数料が、減っています。
そして、mywallet1に10ビットコインが入ってます。
手数料は100ブロック後に払われます。

bitcoin-cli generate 100
bitcoin-cli listaccounts

root@bitcoin_1:/# bitcoin-cli listaccounts
{
  "": 5090.00000000,
  "mywallet1": 10.00000000
}

端数が綺麗になってることが確認出来ました。
さきほどから、bitcoin_1のみを使っています。

ここら辺でbitcoin_2の出番です

bitcoin_2とbitcoin_3のコンテナを使います。
複数のコンテナ内でノードを立てます。
そしてdockerのネットワーク上にBitcoinのネットワークを構築してみましょう。

次回(不定期連載): Bitcoin Coreを触ってみた!! 消えたBitcoin

お楽しみに!!

君は刻の涙を見る