Beyond Blockchain One を触ってみる

## beyond-blockchain/bbc1

https://github.com/beyond-blockchain/bbc1

Beyond Blockchain (BBc) は，日本発のブロックチェーンプロジェクトです．私がこのプロジェクトを知ったきっかけは，[第 9 回 広域センサーネットワークとオーバレイネットワークに関するワークショップ](https://sites.google.com/site/sensoroverlay/home/9) の斎藤さんのご講演 ([スライド](https://speakerdeck.com/ks91/beyond-blockchain-one-bbc-1)) です．BBc は，外部のパブリックレッジャーを用いることで上位のアプリケーションに対して "トランザクションの正しさの保証" を提供するミドルウェアです．具体的な "正しさ" については，[ここ](https://github.com/beyond-blockchain/bbc1/blob/develop/docs/BBc-trust_ja.pdf) にわかりやすくまとめられています．

Beyond Blockchain One (BBc-1) は，BBc の初期実装です．BBc の基本機能に加えて，イントラドメインネットワーキングとスマートコントラクトを実現しようとしています．BBc-1 は今年の 10 月 31 日にオープンソース化されたばかりのプロジェクトで，まだまだ未実装の機能が多いです．しかし，私はおもしろい試みだと思っているので追っかけを続けています．

詳しいドキュメントは [GitHub 上](https://github.com/beyond-blockchain/bbc1/tree/develop/docs) にあるので，興味を持った方はぜひ読んでみてください．

それでは，実際に macOS 上で BBc-1 を動かしてみます．今回は [README.md](https://github.com/beyond-blockchain/bbc1/blob/develop/README.md) の [Quick Start - From source code in GitHub](https://github.com/beyond-blockchain/bbc1/blob/develop/README.md#from-source-code-in-github) に基づいて作業していきます．

## 前提

- macOS Sierra
- Python 3.6.3 (pyenv)

## 手順

必要なパッケージのインストールを行います．

```shell-session
% brew install libtool automake geth solidity pkg-config
```

次に，OpenSSL を使ったライブラリのビルドを行います．ビルドスクリプトは以下に書かれているので，これを実行するだけです．簡単ですね．

```shell-session
% sh prepare.sh
```

次に，Python のパッケージをインストールします．

```shell-session
% pip install -r requirements.txt 
...
Installing collected packages: pycparser, cffi, six, asn1crypto, idna, cryptography, pyOpenSSL, MarkupSafe, jinja2, urllib3, chardet, certifi, requests, py, attrs, pluggy, pytest, greenlet, gevent, msgpack-python, anyconfig, jsonschema, toposort, pyethash, secp256k1, pysha3, pycryptodome, scrypt, repoze.lru, PyYAML, rlp, pbkdf2, bitcoin, ethereum, Werkzeug, click, json-rpc, eth-testrpc, argh, pathtools, watchdog, contextlib2, semantic-version, py-geth, py-solc, pylru, toolz, cytoolz, typing, eth-utils, eth-keys, eth-tester, eth-abi, eth-keyfile, web3, populus
  Running setup.py install for pycparser ... done
  Running setup.py install for MarkupSafe ... done
  Running setup.py install for pluggy ... done
  Running setup.py install for greenlet ... done
  Running setup.py install for msgpack-python ... done
  Running setup.py install for anyconfig ... done
  Running setup.py install for pyethash ... done
  Running setup.py install for secp256k1 ... done
  Running setup.py install for pysha3 ... done
  Running setup.py install for pycryptodome ... done
  Running setup.py install for scrypt ... error
    Complete output from command /Users/sira/.pyenv/versions/3.6.3/bin/python3.6 -u -c "import setuptools, tokenize;__file__='/private/var/folders/ct/htdqqf7547gb9dznw27kpsyc0000gn/T/pip-build-a8k1zvu2/scrypt/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /var/folders/ct/htdqqf7547gb9dznw27kpsyc0000gn/T/pip-2t3dg7rv-record/install-record.txt --single-version-externally-managed --compile:
    running install
    running build
    running build_py
    creating build
    creating build/lib.macosx-10.12-x86_64-3.6
    copying scrypt.py -> build/lib.macosx-10.12-x86_64-3.6
    running build_ext
    building '_scrypt' extension
    creating build/temp.macosx-10.12-x86_64-3.6
    creating build/temp.macosx-10.12-x86_64-3.6/src
    creating build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0
    creating build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/lib
    creating build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/lib/crypto
    creating build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/lib/scryptenc
    creating build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/lib/util
    creating build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/libcperciva
    creating build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/libcperciva/alg
    creating build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/libcperciva/crypto
    creating build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/libcperciva/util
    clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DHAVE_CONFIG_H -DHAVE_SYSCTL_HW_USERMEM=1 -Iscrypt-1.2.0 -Iscrypt-1.2.0/lib -Iscrypt-1.2.0/lib/scryptenc -Iscrypt-1.2.0/lib/crypto -Iscrypt-1.2.0/lib/util -Iscrypt-1.2.0/libcperciva/cpusupport -Iscrypt-1.2.0/libcperciva/alg -Iscrypt-1.2.0/libcperciva/util -Iscrypt-1.2.0/libcperciva/crypto -I/Users/sira/.pyenv/versions/3.6.3/include/python3.6m -c src/scrypt.c -o build/temp.macosx-10.12-x86_64-3.6/src/scrypt.o
    clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DHAVE_CONFIG_H -DHAVE_SYSCTL_HW_USERMEM=1 -Iscrypt-1.2.0 -Iscrypt-1.2.0/lib -Iscrypt-1.2.0/lib/scryptenc -Iscrypt-1.2.0/lib/crypto -Iscrypt-1.2.0/lib/util -Iscrypt-1.2.0/libcperciva/cpusupport -Iscrypt-1.2.0/libcperciva/alg -Iscrypt-1.2.0/libcperciva/util -Iscrypt-1.2.0/libcperciva/crypto -I/Users/sira/.pyenv/versions/3.6.3/include/python3.6m -c scrypt-1.2.0/lib/crypto/crypto_scrypt_smix_sse2.c -o build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/lib/crypto/crypto_scrypt_smix_sse2.o
    clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DHAVE_CONFIG_H -DHAVE_SYSCTL_HW_USERMEM=1 -Iscrypt-1.2.0 -Iscrypt-1.2.0/lib -Iscrypt-1.2.0/lib/scryptenc -Iscrypt-1.2.0/lib/crypto -Iscrypt-1.2.0/lib/util -Iscrypt-1.2.0/libcperciva/cpusupport -Iscrypt-1.2.0/libcperciva/alg -Iscrypt-1.2.0/libcperciva/util -Iscrypt-1.2.0/libcperciva/crypto -I/Users/sira/.pyenv/versions/3.6.3/include/python3.6m -c scrypt-1.2.0/lib/crypto/crypto_scrypt_smix.c -o build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/lib/crypto/crypto_scrypt_smix.o
    clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DHAVE_CONFIG_H -DHAVE_SYSCTL_HW_USERMEM=1 -Iscrypt-1.2.0 -Iscrypt-1.2.0/lib -Iscrypt-1.2.0/lib/scryptenc -Iscrypt-1.2.0/lib/crypto -Iscrypt-1.2.0/lib/util -Iscrypt-1.2.0/libcperciva/cpusupport -Iscrypt-1.2.0/libcperciva/alg -Iscrypt-1.2.0/libcperciva/util -Iscrypt-1.2.0/libcperciva/crypto -I/Users/sira/.pyenv/versions/3.6.3/include/python3.6m -c scrypt-1.2.0/lib/crypto/crypto_scrypt.c -o build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/lib/crypto/crypto_scrypt.o
    clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DHAVE_CONFIG_H -DHAVE_SYSCTL_HW_USERMEM=1 -Iscrypt-1.2.0 -Iscrypt-1.2.0/lib -Iscrypt-1.2.0/lib/scryptenc -Iscrypt-1.2.0/lib/crypto -Iscrypt-1.2.0/lib/util -Iscrypt-1.2.0/libcperciva/cpusupport -Iscrypt-1.2.0/libcperciva/alg -Iscrypt-1.2.0/libcperciva/util -Iscrypt-1.2.0/libcperciva/crypto -I/Users/sira/.pyenv/versions/3.6.3/include/python3.6m -c scrypt-1.2.0/lib/scryptenc/scryptenc.c -o build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/lib/scryptenc/scryptenc.o
    clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DHAVE_CONFIG_H -DHAVE_SYSCTL_HW_USERMEM=1 -Iscrypt-1.2.0 -Iscrypt-1.2.0/lib -Iscrypt-1.2.0/lib/scryptenc -Iscrypt-1.2.0/lib/crypto -Iscrypt-1.2.0/lib/util -Iscrypt-1.2.0/libcperciva/cpusupport -Iscrypt-1.2.0/libcperciva/alg -Iscrypt-1.2.0/libcperciva/util -Iscrypt-1.2.0/libcperciva/crypto -I/Users/sira/.pyenv/versions/3.6.3/include/python3.6m -c scrypt-1.2.0/lib/scryptenc/scryptenc_cpuperf.c -o build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/lib/scryptenc/scryptenc_cpuperf.o
    clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DHAVE_CONFIG_H -DHAVE_SYSCTL_HW_USERMEM=1 -Iscrypt-1.2.0 -Iscrypt-1.2.0/lib -Iscrypt-1.2.0/lib/scryptenc -Iscrypt-1.2.0/lib/crypto -Iscrypt-1.2.0/lib/util -Iscrypt-1.2.0/libcperciva/cpusupport -Iscrypt-1.2.0/libcperciva/alg -Iscrypt-1.2.0/libcperciva/util -Iscrypt-1.2.0/libcperciva/crypto -I/Users/sira/.pyenv/versions/3.6.3/include/python3.6m -c scrypt-1.2.0/lib/util/memlimit.c -o build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/lib/util/memlimit.o
    clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DHAVE_CONFIG_H -DHAVE_SYSCTL_HW_USERMEM=1 -Iscrypt-1.2.0 -Iscrypt-1.2.0/lib -Iscrypt-1.2.0/lib/scryptenc -Iscrypt-1.2.0/lib/crypto -Iscrypt-1.2.0/lib/util -Iscrypt-1.2.0/libcperciva/cpusupport -Iscrypt-1.2.0/libcperciva/alg -Iscrypt-1.2.0/libcperciva/util -Iscrypt-1.2.0/libcperciva/crypto -I/Users/sira/.pyenv/versions/3.6.3/include/python3.6m -c scrypt-1.2.0/libcperciva/alg/sha256.c -o build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/libcperciva/alg/sha256.o
    clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DHAVE_CONFIG_H -DHAVE_SYSCTL_HW_USERMEM=1 -Iscrypt-1.2.0 -Iscrypt-1.2.0/lib -Iscrypt-1.2.0/lib/scryptenc -Iscrypt-1.2.0/lib/crypto -Iscrypt-1.2.0/lib/util -Iscrypt-1.2.0/libcperciva/cpusupport -Iscrypt-1.2.0/libcperciva/alg -Iscrypt-1.2.0/libcperciva/util -Iscrypt-1.2.0/libcperciva/crypto -I/Users/sira/.pyenv/versions/3.6.3/include/python3.6m -c scrypt-1.2.0/libcperciva/crypto/crypto_aes_aesni.c -o build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/libcperciva/crypto/crypto_aes_aesni.o
    clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DHAVE_CONFIG_H -DHAVE_SYSCTL_HW_USERMEM=1 -Iscrypt-1.2.0 -Iscrypt-1.2.0/lib -Iscrypt-1.2.0/lib/scryptenc -Iscrypt-1.2.0/lib/crypto -Iscrypt-1.2.0/lib/util -Iscrypt-1.2.0/libcperciva/cpusupport -Iscrypt-1.2.0/libcperciva/alg -Iscrypt-1.2.0/libcperciva/util -Iscrypt-1.2.0/libcperciva/crypto -I/Users/sira/.pyenv/versions/3.6.3/include/python3.6m -c scrypt-1.2.0/libcperciva/crypto/crypto_aes.c -o build/temp.macosx-10.12-x86_64-3.6/scrypt-1.2.0/libcperciva/crypto/crypto_aes.o
    scrypt-1.2.0/libcperciva/crypto/crypto_aes.c:6:10: fatal error: 'openssl/aes.h' file not found
    #include <openssl/aes.h>
             ^~~~~~~~~~~~~~~
    1 error generated.
    error: command 'clang' failed with exit status 1
    
    ----------------------------------------
Command "/Users/sira/.pyenv/versions/3.6.3/bin/python3.6 -u -c "import setuptools, tokenize;__file__='/private/var/folders/ct/htdqqf7547gb9dznw27kpsyc0000gn/T/pip-build-a8k1zvu2/scrypt/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /var/folders/ct/htdqqf7547gb9dznw27kpsyc0000gn/T/pip-2t3dg7rv-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /private/var/folders/ct/htdqqf7547gb9dznw27kpsyc0000gn/T/pip-build-a8k1zvu2/scrypt/
```


macOS だと OpenSSL のヘッダを読み込めずにインストールに失敗するので，`pip` にフラグを渡して再度実行します．

```shell-session
% pip install -r requirements.txt --global-option=build_ext --global-option="-I/usr/local/opt/openssl/include" --global-option="-L/usr/local/opt/openssl/lib"
```

これで必要なパッケージのインストールは終わり．

## サンプルコードを動かしてみる

今回は `examples/file_proof` を動かしてみます．このサンプルでは，BBc-1 のコアノードにファイルの格納を行うことができます．そして，そのファイルに対して，更新，取得，検証といった操作を行うことができます．また，コアノードを通してファイルを特定のユーザに送信 (特定のユーザから受信) する機能もあるようです．

まず，BBc-1 のコアノードを起動します．

```shell-session
% cd core
% python bbc_core.py
2017/12/12 00:22:46| DEBUG   | core| config = {'workingdir': '.bbc1', 'client': {'ipv6': False, 'port': 9000}, 'ledger': {'type': 'sqlite3', 'transaction_db': 'bbc_transaction.sqlite3', 'auxiliary_db': 'bbc_aux.sqlite3'}, 'storage': {}, 'network': {'ipv6': False, 'p2p_port': 6641, 'max_connections': 100, 'modules': {'simple_cluster': {'test': 1}, 'p2p_kademlia': {'concurrent_lookup_num': 3, 'redundancy': 3, 'k_value': 10}}}, 'domains':{'0000000000000000000000000000000000000000000000000000000000000000': {'special_domain': True, 'module': 'p2p_domain0', 'static_nodes': {}, 'peer_list': {}}}, 'ethereum': {'chain_id': 15, 'port': 30303, 'log': 'geth.log', 'account': '', 'passphrase': '', 'contract': 'BBcAnchor', 'contract_address': ''}, 'ledger_subsystem': {'subsystem': 'ethereum', 'max_transactions': 4096, 'max_seconds': 3600}}    
2017/12/12 00:22:46| DEBUG   | bbc_network| Start udp_message_loop     
2017/12/12 00:22:46| DEBUG   | bbc_network| Start tcpserver_loop       
2017/12/12 00:22:46| DEBUG   | ledger_subsystem| Start subsystem_loop
```

別のターミナルセッションで，`file_proof.py` を実行します．
まずは，秘密鍵 `.private_key` と公開鍵 `.public_key` を生成し，ドメインとアセットグループのセットアップを行います．

```shell-session
% cd examples/file_proof
% python file_proof.py keypair
created private_key and public_key : .private_key, .public_key
% python file_proof.py setup
Domain df6b3b7e and asset_group 45b2a200 are created.
Setup is done.
```

適当なファイルを格納・取得してみます．

```shell-session
% python file_proof.py store <filename>
file stored : <filename>
done store <filename>
```

```shell-session
% python file_proof.py get README.md
done get README.md_20171212003646
```

今回は時間がないので，このあたりまで．また時間ができたら，もっともおもしろい send/receive の機能についても追記しようと思います．