BigchainDBでブロックチェインを体験する

はじめはこの辺の記事を読み漁った。
https://www.slideshare.net/cookle/5-58379474
http://qiita.com/hshimo/items/1881fba8957c2a6e17ca
http://qiita.com/akitoh/items/bebf1bf3d71d3e4b96b0

で、ブロックチェインがすごくて役に立つのはわかった。

ざっくりしかわかってないが、ともかく動かしたい。間違ってたら突っ込んで頂ければと。
前から気になってたbigchaindbってライブラリを使ってみる。スケーラブルなブロックチェインdbだよと書いてある。
純粋なp2pって感じではなく分散DBとブロックチェーンが融合したライブラリ。

- 公式
https://docs.bigchaindb.com/en/latest/index.html

#BigchainDB ユースケース
##ライセンシングチェーンに沿ったプロパティアセットの追跡
BigchainDBは、クリエイターと視聴者を結ぶチャネルのライセンス争奪を減らし、デジタルアーチファクトに完璧な出資を提供します。 典型的な音楽サービスには3800万曲があります.BigchainDBはこの情報をハートビートで保存することができ、各曲のライセンス情報や加入者の使用に関する情報も保存できます。 別の例では、1日に100,000トランザクションを実行する中規模の写真市場を考えてみましょう。 これをBitcoinに適用すると、1日あたり10,000ドルの費用がかかり、Bitcoinネットワークが繋がります。
##レセプト、および証明書。
BigchainDBは、電子的な行動の反駁できない証拠を提供することによって法的な摩擦を減らします。 また、BigchainDBは、ドキュメントにリンクしたり、ハッシュを格納したりするのではなく、レセプトや証明書（COA）などのサポート情報を直接格納することができます。

略〜

https://www.thoughtworks.com/insights/blog/blockchain-practice-tamper-proof-read-receipts


#伝統的なブロックチェインとの違い
前回のブロックとハッシュで繋ぐ訳ではない。ブロック内部に投票リストというものを保持してる。署名ノードが投票する。ブロックの賛成投票の過半数を得たら有効になる。そして投票時に連鎖が起こる。

<img width="263" alt="スクリーンショット 2017-08-30 21.12.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/64334/0d3767a7-e5b6-6ebe-57a3-5c4a18d87a31.png">


#専門用語
###BigchainDB Node
BigchainDBノードは、MongoDBサーバー、BigchainDBサーバーを実行しているマシンのセットです。各ノードは、個人または組織によって制御されます。
###BigchainDB Cluster
BigchainDBノードのセットは、相互に接続してBigchainDBクラスターを形成できます。
クラスタ内の各ノードは同じソフトウェアを実行します。クラスタには、1つの論理MongoDBデータストアが含まれています。
###BigchainDB Consortium
クラスタ内でノードを実行する人や組織は、BigchainDBコンソーシアム（別の組織）に属します。コンソーシアムには、意思決定を行うためのガバナンス構造が必要です。ある企業がクラスタを運営している場合、「コンソーシアム」はその会社だけです。
クラスタは、接続されたノードの集まり。コンソーシアムは、クラスタを持ち、クラスタ内の各ノードに異なるオペレーターがある組織です。
オペレーターってなんだろう・・・
ともかくコンソーシアムの下にクラスタ、クラスタの下にノードがあるイメージと解釈。


#ドキュメント構成
<img width="314" alt="スクリーンショット 2017-08-19 3.20.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/64334/0a906636-2b99-0990-0cfe-b02162ef3fea.png">

上位レベルでは、BigchainDB Client-Server HTTP API、またはそのAPIのラッパー（BigchainDB Python Driverなど）を使用して、BigchainDBクラスター（ノードのセット）と通信できる。
BigchainDB Python DriverはBigchainDBノードへのトランザクションの準備、実行、および送信のサポート。idによるトランザクションの取得。 idでトランザクションのステータスを取得します。


サーバー側：server docs、server quickstart、http api docs
クライアント側：python driver docs
その他：comannd line tran... tool

#環境
ubuntu14 or mac
python3
conda
DBはRethinkDB か MongoDBを選択だが、RethinkDBはまだサポートされるのか？

#BigchainDB Serverの設定
サーバー側の設定であります。

##python環境周りインストール
python3系じゃないと動かないので、condaでpython3系に切り替えた。

condaについてはこちら
http://qiita.com/miyamotok0105/items/5f26e4ae41f0e35ded16


```
sudo apt-get update
sudo apt-get install g++ python3-dev libffi-dev build-essential libssl-dev
sudo apt-get install python3-pip
sudo pip3 install --upgrade pip setuptools
sudo pip3 install bigchaindb
bigchaindb -y configure mongodb
```


##mongo3.4以上を入れる
https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/

そもそもmongoとはこちら。JSONベースのdbで、型とか考えなくて放り込めます。
http://qiita.com/saba1024/items/f2ad56f2a3ba7aaf8521

```
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6
echo "deb [ arch=amd64 ] http://repo.mongodb.org/apt/ubuntu precise/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list
sudo apt-get update
sudo apt-get install -y mongodb-org
mongo --version
sudo mkdir -p /data/db
sudo chmod -R 700 /data/db
```

##設定
サーバーで動かしてる場合はipかドメインの部分を変更

```
sudo emacs ~/.bigchaindb
```

"server": {"bind": "localhost:9984", ... }
to
"server": {"bind": "0.0.0.0:9984", ... }

0.0.0.0を自分のサーバーの情報へ

参照
https://docs.bigchaindb.com/projects/server/en/latest/production-nodes/setup-run-node.html


##起動


###MongoDB起動

```
sudo mongod --replSet=bigchain-rs
```
これでエラーになった。ならない人は読み飛ばしてOK。
前に入れたmongoが邪魔してる。下記で解決。
http://kiita312.hatenablog.com/entry/2013/03/03/130935

bigchain-rsを起動した状態でコンソールをもう一個立てる。


###BigchainDB Server起動

```
bigchaindb start
```

ドワーっとログが出て動く。
こ。こいつ動くぞ。


```
****************************************************************************
*                                                                          *
*   Initialization complete. BigchainDB Server is ready and waiting.       *
*   You can send HTTP requests via the HTTP API documented in the          *
*   BigchainDB Server docs at:                                             *
*    https://bigchaindb.com/http-api                                       *
*                                                                          *
*   Listening to client connections on: localhost:9984                     *
*                                                                          *
****************************************************************************
 (MainProcess - pid: 15547)
======== Running on http://localhost:9985 ========
(Press CTRL+C to quit)
[2017-08-19 02:47:02] [INFO] (gunicorn.error) Starting gunicorn 19.7.1 (webapi     - pid: 15680)
[2017-08-19 02:47:02] [INFO] (gunicorn.error) Listening at: http://127.0.0.1:9984 (15680) (webapi     - pid: 15680)
[2017-08-19 02:47:02] [INFO] (gunicorn.error) Using worker: sync (webapi     - pid: 15680)
[2017-08-19 02:47:02] [INFO] (gunicorn.error) Booting worker with pid: 15685 (webapi     - pid: 15685)
[2017-08-19 02:47:02] [INFO] (gunicorn.error) Booting worker with pid: 15686 (webapi     - pid: 15686)
[2017-08-19 02:47:02] [INFO] (gunicorn.error) Booting worker with pid: 15687 (webapi     - pid: 15687)
[2017-08-19 02:47:02] [INFO] (gunicorn.error) Booting worker with pid: 15688 (webapi     - pid: 15688)
[2017-08-19 02:47:03] [INFO] (gunicorn.error) Booting worker with pid: 15689 (webapi     - pid: 15689)
[2017-08-19 02:47:07] [INFO] (bigchaindb.backend.mongodb.connection) Closing initial connection to MongoDB (Process-16 - pid: 15659)


```

localhost:9984の部分にアクセス。

ブラウザで叩くと何かしら返って来る

```
{
  "api": {
    "v1": {
      "assets": "/api/v1/assets/", 
      "docs": "https://docs.bigchaindb.com/projects/server/en/v1.0.1/http-client-server-api.html", 
      "outputs": "/api/v1/outputs/", 
      "statuses": "/api/v1/statuses/", 
      "streams": "ws://localhost:9985/api/v1/streams/valid_transactions", 
      "transactions": "/api/v1/transactions/"
    }
  }, 
  "docs": "https://docs.bigchaindb.com/projects/server/en/v1.0.1/", 
  "keyring": [], 
  "public_key": "HPxXw3Kbkj8BVvgR49xa7jaUkHpmmqwL39pmk5qpbdjQ", 
  "software": "BigchainDB", 
  "version": "1.0.1"
}
```


#BigchainDB Python Driver
クライアント側から叩く。

##インストール

```
pip3 install bigchaindb_driver
or
pip install bigchaindb_driver
```

##Asset Creation & Transfer　アセットクリエーションと転送
アセットって資産的な意味があるので、データは資産ってイメージ？
モォ眠い。
bikeはAliceさんのものでBobさんに渡す処理を仮定する。
コメントに処理の解釈を記載した。

```py:
# -*- coding: utf-8 -*-
from bigchaindb_driver import BigchainDB
from bigchaindb_driver.crypto import generate_keypair
from time import sleep
from sys import exit

#暗号ペア生成
alice, bob = generate_keypair(), generate_keypair()

bdb_root_url = 'http://0.0.0.0:9984'  # BigchainDB Root URLに書き換えて！！

bdb = BigchainDB(bdb_root_url)

#アセット定義
bicycle_asset = {
    'data': {
        'bicycle': {
            'serial_number': 'abcd1234',
            'manufacturer': 'bkfab'
        },
    },
}
#オプションでメタデータをトランザクションに追加できる
bicycle_asset_metadata = {
    'planet': 'earth'
}

#Assetクリエーション
#RDBのレコードの代わりにbigchainではtransaction単位でデータが保存される。
#transactionの用意をしている。
prepared_creation_tx = bdb.transactions.prepare(
    operation='CREATE',
    signers=alice.public_key,
    asset=bicycle_asset,
    metadata=bicycle_asset_metadata
)

#トランザクションは、Aliceの秘密鍵で署名することで実現する必要があります。
fulfilled_creation_tx = bdb.transactions.fulfill(
    prepared_creation_tx,
    private_keys=alice.private_key
)

#BigchainDBノードに送信！！！
sent_creation_tx = bdb.transactions.send(fulfilled_creation_tx)

txid = fulfilled_creation_tx['id']

#トランザクションが有効になるまでトランザクションのステータスをチェックし続ける
trials = 0
while trials < 60:
    try:
        if bdb.transactions.status(txid).get('status') == 'valid':
            print('Tx valid in:', trials, 'secs')
            break
    except bigchaindb_driver.exceptions.NotFoundError:
        trials += 1
        sleep(1)

if trials == 60:
    print('Tx is still being processed... Bye!')
    exit(0)

asset_id = txid

transfer_asset = {
    'id': asset_id
}

output_index = 0
output = fulfilled_creation_tx['outputs'][output_index]

transfer_input = {
    'fulfillment': output['condition']['details'],
    'fulfills': {
        'output_index': output_index,
        'transaction_id': fulfilled_creation_tx['id']
    },
    'owners_before': output['public_keys']
}

#アセットクリエーション
prepared_transfer_tx = bdb.transactions.prepare(
    operation='TRANSFER',
    asset=transfer_asset,
    inputs=transfer_input,
    recipients=bob.public_key,
)

fulfilled_transfer_tx = bdb.transactions.fulfill(
    prepared_transfer_tx,
    private_keys=alice.private_key,
)

sent_transfer_tx = bdb.transactions.send(fulfilled_transfer_tx)

print("Is Bob the owner?",
    sent_transfer_tx['outputs'][0]['public_keys'][0] == bob.public_key)

print("Was Alice the previous owner?",
    fulfilled_transfer_tx['inputs'][0]['owners_before'][0] == alice.public_key)


```

bikeはbobの元にある。
前のオーナーはaliceだよ。って結果が見れた。

```
Tx valid in: 0 secs
Is Bob the owner? True
Was Alice the previous owner? True
```


概要はprepareしてfulfillしてsendする。

#Library Reference
- class bigchaindb_driver.BigchainDB

BigchainDB driver class

###bigchaindb_driver.driver.TransactionsEndpoint

- fulfill

指定のトランザクションを実行する。

返り値：fulfilled(完了した)トランザクションペイロードは、BigchainDBフェデレーションに送信する準備のdict

- prepare

トランザクションペイロードの準備、fulfilledに備える。
operationでCREATEかTRANSFERが選べる。

返り値：prepared transactionのdict

- send

フェデレーションに取引を提出する。

返り値：フェデレーションノードに送信されたトランザクションのdict


他にもあるが詳細は下記
https://docs.bigchaindb.com/projects/py-driver/en/latest/libref.html?highlight=prepare#driver


#最後に
次に記事を書くときはモォ少し取引の転送とかapi周りについて深ぼってみる予定。


ps

nodeバージョンもdockerでバッチリdemoが動きました。
https://github.com/bigchaindb/bigchaindb-examples