bitcoin-cliを使ったBitcoinAPI入門

流行りのbitcoinを使ったアプリケーションを作るときにお世話になるbitcoin-coreが提供するAPIの使い方を、"bitcoin-cli"というコマンドラインインターフェースを使いながら学習します。
入門したばかりなので、間違いがあるかもしれません。ご容赦ください。

# 環境
* MacBook Pro (Retina 13-inch、Early 2015)
* Mac OSX El Capitan (10.11.3)
* bitcoind v0.12.99
* 実行日 = 2016-05-11

# 事前準備
## アプリケーションの入手
githubで公開されていますので、以下のようにダウンロード＆インストールします。

```
% git clone https://github.com/bitcoin/bitcoin.git
% cd bitcoin
% ./autogen.sh
% ./configure
% make
% make check
% make install
```

私の場合、autoconfなどが足りないというエラーが表示されてインストールが中断されたので、当該パッケージを以下のようにインストール。

```
% brew install autoconf
```

インストールが完了すると、「bitcoind」や「bitcoin-cli」などのbitcoinに関係するコマンドが実行できるようになります。

## 初期設定
bitcoinの処理を司るソフトは"bitcoind"です。"bitcoin-cli"等を通して、bitcoindのAPIを使うことで、bitcoinの残高確認や送金ができるようになります。bitcoindの実態は、JSONリクエストを受けるデーモン（RPCサーバ）として動作しています。そのため、まずは、RPCサーバとしてのポート番号やユーザ名を、設定ファイルである"bitcoin.conf"に記載します。

設定ファイルの場所は、公式サイトを見ると書いてありますが、現バージョンでは以下にあります。
Mac:  ~/Library/Application Support/Bitcoin/bitcoin.conf
Linux: ~/.bitcoin/bitcoin.conf
その他: https://en.bitcoin.it/wiki/Running_Bitcoin#Bitcoin.conf_Configuration_File 参照

bitcoin.confの書き方は以下です。
パラメタに対する各値の書き方は、"（ダブルクォート）で囲まないように注意です。
例えば「rpcuser="osada"」と書くと、認証に失敗するようになります。

```bitcoin.conf
# Osada 2016-05-11

rpcuser=osada
rpcpassword=abc123

HOST=localhost

server=1
txindex=1

rpcport=18332
testnet=3
```

bitcoinには、実際に「価値のある」Bitcoinを取り扱うための"mainnet"と呼ばれるネットワークのほかに、テスト用に「価値の無い」Bitcoinを取り扱う"testnet"と呼ばれるものがあります。上の設定では、"testnet"を使うように設定しています。「3」という値は、最新のtestnetのバージョンを示しています（最新のバージョン番号は公式サイトで知ることができます）。また、"testnet"を使うときは、"rpcport"は18332を使います。
もし、mainnetで使う場合は、testnetの記載を削除するとともに、rpcportは8322を設定してください。

## 動作確認
bitcoindを実行します。（JSON形式のクエリを受付るデーモンとして動きます。）

```
bitcoind -testnet -daemon
```

bitcoindが正しく動作しているかどうか、JSONでクエリを送ってみます。以下の例は、bitcoindの状態を調べる"getinfo"というAPIを呼び出しています。

```
curl --data-binary '{"jsonrpc":"1.0","id":"curltext","method":"getinfo","params":[]}' -H 'content-type:text/plain;' http://osada:abc123@localhost:18332
```

何らかのJSONが返ってくればOKです。

## ブロック構築

bitcoinを使って残高照会や送金等を行うためには、「ブロックチェーン」という仕組み上、過去の取引が記録されたブロックを原則全て入手する必要があります。インターネットに接続した状態でbitcoindを動かしていれば、自動的にブロックのダウンロードが始まり、大体２～３時間くらいで完了します（testnetの場合）。

ブロックのダウンロードの進捗度は、"getinfo"APIで知ることができます。出力に含まれる"block"の値がそれで、この値が世の中で公開されている最新のBlock番号と同じ値になれば完了です。

```
% bitcoin-cli -testnet getinfo
...
   blocks: 12345 <- この値
...
```

ちなみに、最新のBlock番号は以下のトランザクション検証サイトなどで知ることができます。（例はtestnetです）
https://live.blockcypher.com/btc-testnet/
※HeightがBlockの最大値

# CLIコマンド入門
bitcoindの準備ができたら、bitcoin-cliを使ってAPIを試してみましょう。
なお、テスト環境でのコマンド実行時には、"-testnet"を明示的につけます。

## アドレスの発行
bitcoinの送受信で使うアドレスを発行します。

```
osada@mbp16a% bitcoin-cli -testnet getnewaddress
mvYbB238p3rFYFjM56cHhNNHeQb5ypQJ3T
```

* この値（アドレス）は、各端末に保有する公開鍵（これ自体は秘密鍵から生成）から生成しているようです。
* アドレスには、所有者情報（アカウント）を付けて生成することができます。アカウントは、ローカル端末内での管理上のメモのようなもので、bitcoinの送受信自体には特に意味を持ちません。アカウントを指定してアドレスを発行する場合は、以下のように実行します。

```
osada@mbp16a% bitcoin-cli -testnet getnewaddress osada
mvYbB238p3rFYFjM56cHhNNHeQb5ypQJ3T
```

* アカウントを指定せずにアドレスを発行した場合は、""(空白)がアカウントになります。

## 残高照会
利用中の端末が発行したアドレスが保有するbitcoinの残高を表示します。引数を与えない場合は、すべてのアカウントの合計値を表示し、一方、引数にアカウントを指定した場合は、そのアカウントが保有するアドレスのbitcoin残高を表示します。

```
osada@mbp16a% bitcoin-cli -testnet getbalance 
0.00421406
```

* 詳細は別途記載しますが、ここで表示される情報は、過去の取引が確定（Confirm）されたのものみです。例えば、送金直後にこのAPIを実行した場合、送金に使わなかったトランザクション（UTXO）に記載されている確定された残高情報のみが表示されます。
* 例えば、過去3BTCの送金を受けたトランザクションのみを保有している状態で、1BTCを誰かに送金。その後getbalanceした場合、期待値は3-1=2BTCですが、3BTCのトランザクションはUTXOでなくなりますので、0BTCと表示されることになります。
* 但し、元々の3BTCを持つアドレスが複数の複数のトランザクションから生成されている場合は、未確定部分を限定することができるため、この限りではありません。

## 詳しい残高照会
bitcoinが利用するブロックチェーンという仕組みでは、重複利用（重複決済/複製）を避けるために、そのbitcoinが使用されたか未使用かといった情報を管理しています。以下のAPIでは，未使用のbitcoinを持つトランザクション（unspentと言う）のみ表示することができます。

```
osada@mbp16a% bitcoin-cli -testnet listunspent 
[
  {
    "txid": "b16484012e01900fef1521ef7ee2e4693a9a08f44e69d4ca0bc0cfef08672d86",
    "vout": 0,
    "address": "mvYbB238p3rFYFjM56cHhNNHeQb5ypQJ3T",
    "account": "",
    "scriptPubKey": "76a914a4d91666eb7cc21a3fff959861a629354e4275b288ac",
    "amount": 0.00421406,
    "confirmations": 10,
    "spendable": true,
    "solvable": true
  }
]
```

* また、これは、アカウントごとにunspentの量（amount合計値）を表示することができます。

```
osada@mbp16a% bitcoin-cli -testnet listaccounts 
{
  "": 1.10112278,
  "Customer20160516-01": 0.00690000,
  "osada": 0.00000000,
  "test20160516-01": 0.05001200
}
```

## アドレス～アカウント変換
あまり使いませんが、アドレスからアカウントに検索するためのAPIです。

```
osada@mbp16a% bitcoin-cli -testnet getaccount n3YanojWXYXxhgo8DhHUuwBKfRdnUaqkdR
osada
```

* 空白ユーザの場合は、空白文字だけが表示されるため、プロンプトだけが表示されます。

## アカウント～アドレス変換
あまり使いませんが、アカウントからアドレスを検索するためのAPIです。

```
osada@mbp16a% bitcoin-cli -testnet getaddressesbyaccount ""
[
  "mtFTgvmrLTNictj6NXGohYbH3pNTUspWVu", 
  "mvYbB238p3rFYFjM56cHhNNHeQb5ypQJ3T", 
  "myxyWnmJmZuEuBQoZHjCEtd7288866a3u9"
]
```

* ""は空白アカウントを示しています。

## 送金準備：Bitcoin入手
いよいよ送金ですが、その前に、送金用のbitcoinを入手します。testnetであれば、以下のサイトにアクセスし、上の手順で作成したアドレスを入力すれば、無料で若干頂けます。

https://accounts.blockcypher.com/testnet-faucet
http://faucet.luis.im/
(testnetの最新バージョンは3なので、それに対応したサイトで入手しましょう。上記2サイトはバージョン3になっています。)

## 送金
sendtoaddressの後に、送金先のアドレスと送金額をBTC単位で入力します。

```
% bitcoin-cli -testnet sendtoaddress mvYbB238p3rFYFjM56cHhNNHeQb5ypQJ3T 0.005
```
* 0.005BTC送る、という意味
* 送金元アドレスは、""（空白）アカウントが保有しているものになります。
* 送金元アドレスを指定したい場合や、一度に複数の宛先に送金する場合などは、別のAPIが用意されています。公式サイトにアクセスして確認してみてください。

# Bitcoinトランザクション確認
送金後などに、本当に完了したのか不安になるときがあります。そんなときには、インターネットに公開されているトランザクション検索サイトで、送金に使ったアドレスやトランザクションIDを入力することで、その送金等が確定（Confirm）されたかどうか確認することができます。

https://live.blockcypher.com/

# トランザクション調査

```
osada@mbp16a% bitcoin-cli -regtest gettransaction 03f509aeed95b7772b10944d6e81f58e04fcc1c3100172c6d40e4a881911719d 
{
  "amount": 0.00000000,
  "fee": -0.00010000,
  "confirmations": 1,
  "blockhash": "6dfd52cb229cc0432bac5a2224874708589e59134f0351637a0443e7236b9f35",
  "blockindex": 1,
  "blocktime": 1464856445,
  "txid": "03f509aeed95b7772b10944d6e81f58e04fcc1c3100172c6d40e4a881911719d",
  "walletconflicts": [
  ],
  "time": 1464855823,
  "timereceived": 1464855823,
  "bip125-replaceable": "no",
  "details": [
    {
      "account": "",
      "category": "send",
      "amount": 0.00000000,
      "vout": 0,
      "fee": -0.00010000,
      "abandoned": false
    }, 
    {
      "account": "",
      "address": "miC89vR6VHJ4jhxrJEwoC8TDnocDk5wNaW",
      "category": "send",
      "amount": -0.00000600,
      "label": "hoge account",
      "vout": 1,
      "fee": -0.00010000,
      "abandoned": false
    }, 
    {
      "account": "hoge account",
      "address": "miC89vR6VHJ4jhxrJEwoC8TDnocDk5wNaW",
      "category": "receive",
      "amount": 0.00000600,
      "label": "hoge address",
      "vout": 1
    }
  ],
  "hex": "0100000002802bcb3587b583c96df96169d3fe5c2314e23076d9ca9fb0f69aa832c16f7107010000006b483045022100d18a2c7a5cfce10504ef03ceee6743a6c5263127291f23bab7fb7a746676c43c02200fda7443ddf9387373435f1bff27a00e3985c46ec43b9740eede791ecff9546501210276eab9061210b9024149eac8e5cac1e36fe89fde125f6c03a1d5e193b4a39d74ffffffff33de439e68872e598b01963121b9887e3fcaac2ae132124ea1a0f89781146196010000006a47304402203f612fe9e13b404dd26463185ae9da9093902d0d672df99ec12d7f05e0f7af500220184a3d51116fdf0d3092e5edaf24caad72a1fe8107fc3129657911a209762d0a01210276eab9061210b9024149eac8e5cac1e36fe89fde125f6c03a1d5e193b4a39d74ffffffff020000000000000000096a074f41010001010058020000000000001976a9141d58b4619e88ac899c7e6d599d938f4c3924f6fc88ac00000000"
}
```

# 参考
* 公式サイトのコマンドリスト
https://bitcoin.org/en/developer-reference
https://en.bitcoin.it/wiki/Original_Bitcoin_client/API_calls_list

# 発展（後日記載予定）
* 現時点のbitcoinの仕様では、単純な送金などの限られた取引しかできません。例えば、権利証とお金の交換などよくある取引をするためには、仕様を拡張する必要があります。bitcoin互換のOpenAssetProtocolや、bitcoin非互換ながら汎用性に優れたEthereumなど、いくつか可能性のあるものが検討されているようです。
* 実際に開発を行うと、testnetの制約（Confirmationの期間など）のためテンポよく開発・テストできません。テクニックが存在しますので、詳しくは後日記載します。