bbc1プログラミングガイドを実践する際のトラブルメモ（トランザクションの検索までやってみて）


# 2018/08/05 追記
bbc_domain_config.pyが使えないのはコード冒頭の宣言が抜けていることによるバグでした。修正案をプルリクで出したところ[マージ](https://github.com/beyond-blockchain/bbc1/pull/101)されました。
※プルリクタイトルがbbc_domain_update.pyになってますがbbc_domain_config.pyの間違いです。失礼しました。

# はじめに
本記事は基本的に[Programming guide for BBc-1 version 1.0](https://github.com/beyond-blockchain/bbc1/blob/develop/docs/BBc1_programming_guide_v1.0_ja.md)の写経です。
しかしその中でも起こりうるトラブルなどありますので、それらを知見としてまとめることで自身のbbc1の理解を深めることを目的としています。

# 対象とする読者
- bbc1アプリ開発初心者の人たち（自分含む）
- [BBc1_design_document_v1.0_ja.pdf](https://github.com/beyond-blockchain/bbc1/blob/develop/docs/BBc1_design_document_v1.0_ja.pdf)を一読したことのある人

# 環境
- macOS High Sierra
- その他は[こちら](https://github.com/beyond-blockchain/bbc1/blob/develop/README.md)のEnvironmentと同様です


# 結論から言うと
- 今のところはコアノードを立ち上げたらbbc_domain_update.pyでドメイン情報をconfigに追加するのが良さそう
    - bbc_domain_config.pyの使い方が間違っているかも知れませんのでコードを調べて見たいと思います

# 実践
早速はじめましょう！

## コアノードへの接続
はじめに以下のような記述があります。

> まずは、core nodeをdomainに参加させる必要がある。最も簡単な方法は、bbc_domain_config.pyを利用する方法である。すでにdomainに参加済みであればこの手順は不要である。

具体的なコマンドが記載されてないので一度飛ばして進めてみましょう。

とりあえず、コマンドライン上でコアノードを起動します。

```shell-session
$ bbc_core.py --no_nodekey
2018/07/21 22:45:45| DEBUG   | core| config = {'workingdir': '.bbc1', 'client': {'port': 9000, 'use_node_key': False}, 'network': {'p2p_port': 6641, 'max_connections': 100}, 'domain_key': {'use': False, 'directory': '.bbc1/domain_keys', 'obsolete_timeout': 300}, 'domains': {'0000000000000000000000000000000000000000000000000000000000000000': {'module': 'p2p_domain0', 'static_nodes': {}, 'use_ledger_subsystem': False, 'ledger_subsystem': {'subsystem': 'ethereum', 'max_transactions': 4096, 'max_seconds': 3600}}}, 'ethereum': {'chain_id': 15, 'port': 30303, 'log': 'geth.log', 'account': '', 'passphrase':'', 'contract': 'BBcAnchor', 'contract_address': ''}}
2018/07/21 22:45:45| DEBUG   | bbc_network| Start udp_message_loop
2018/07/21 22:45:45| DEBUG   | bbc_network| Start tcpserver_loop
```

```python:test.py
# Connection to core node

from bbc1.core import bbclib
from bbc1.core import bbc_app

import binascii
b2a = binascii.b2a_hex

user_id = bbclib.get_new_id("user_id for testing",include_timestamp=False)
domain_id = bbclib.get_new_id("domain_id for testing",include_timestamp=False)
keypair = bbclib.KeyPair()
keypair.generate()
path_to_node_key_file = ".nodekey"

def show_info():
    print("user id: %s" % b2a(user_id).decode())
    print("domain id: %s" % b2a(domain_id).decode())

def connect_to_core_node():
    client = bbc_app.BBcAppClient(port=9000, multiq=False, loglevel='all')
    client.set_domain_id(domain_id)
    client.set_user_id(user_id)
    client.set_keypair(keypair)
    client.set_node_key(path_to_node_key_file)
    client.register_to_core()
    return client

show_info()
client = connect_to_core_node()
```

そして上記ファイルを実行してみると．．．

```shell-session
$ python test.py
user id: 92a54325c4eec2ed5b2f573c6feaf6545d43df5fc0f7b4cab9d31472eae83eea
domain id: 748c0b3fafa02e150928a7d3764a4bb1b16a21cb61a1d3f51ed2021933042baa

# 以下はコアノードを立ち上げているコンソールの表示
2018/07/21 22:46:21| DEBUG   | core| [b'748c'] register_user: b'92a54325'
2018/07/21 22:46:21| DEBUG   | core| closing socket
Traceback (most recent call last):
  File "src/gevent/greenlet.py", line 716, in gevent._greenlet.Greenlet.run
  File "/Users/kichinosukey/bbcenv/lib/python3.6/site-packages/gevent/baseserver.py", line 26, in _handle_and_close_when_done
    return handle(*args_tuple)
  File "/Users/kichinosukey/bbcenv/bin/bbc_core.py", line 245, in _handler
    self.networking.domains[user_info[0]]['user'].unregister_user(user_info[1], socket)
KeyError: b't\x8c\x0b?\xaf\xa0.\x15\t(\xa7\xd3vJK\xb1\xb1j!\xcba\xa1\xd3\xf5\x1e\xd2\x02\x193\x04+\xaa'
2018-07-21T13:46:21Z <Greenlet "Greenlet-0" at 0x108683a48: _handle_and_close_when_done(<bound method BBcCoreService._handler of <__main__, <bound method StreamServer.do_close of <StreamServ,(<gevent._socket3.socket [closed]  object, fd=-1, )> failed with KeyError
```

コアノードとの接続でエラーが発生しました。先ほど飛ばしたconfigの設定が要因と思われます。bbc_domain_config.pyを使ってconfigを生成して見ましょう。すでにコアノードを立ち上げているので以下のコマンドを実行します。

```shell-session
$ python bbc_domain_config.py -d748c0b3fafa02e150928a7d3764a4bb1b16a21cb61a1d3f51ed2021933042baa -t write
input filepath : .bbc1/config.json
fpath: .bbc1/config.json
outputfpath: .bbc1/config.json
load from .bbc1/config.json
------
{'client': {'port': 9000, 'use_node_key': False},
 'domain_key': {'directory': '.bbc1/domain_keys',
                'obsolete_timeout': 300,
                'use': False},
 'domains': {'0000000000000000000000000000000000000000000000000000000000000000': {'ledger_subsystem': {'max_seconds': 3600,
                  'max_transactions': 4096,
                  'subsystem': 'ethereum'},
                                                                                  'module': 'p2p_domain0',
                                                                                  'static_nodes': {},
                                                                                  'use_ledger_subsystem': False},
             '748c0b3fafa02e150928a7d3764a4bb1b16a21cb61a1d3f51ed2021933042baa': {'db': {'db_name': 'bbc_ledger.sqlite',
    'db_servers': [{'db_addr': '127.0.0.1',
                    'db_pass': 'pass',
                    'db_port': 3306,
                    'db_user': 'user'}],
    'db_type': 'sqlite',
    'replication_strategy': 'all'},
                                                                                  'static_nodes': {},
                                                                                  'storage': {'type': 'internal'}}},
 'ethereum': {'account': '',
              'chain_id': 15,
              'contract': 'BBcAnchor',
              'contract_address': '',
              'log': 'geth.log',
              'passphrase': '',
              'port': 30303},
 'network': {'max_connections': 100, 'p2p_port': 6641},
 'workingdir': '.bbc1'}
```

成功したようなので、一度コアノードを再起動してから（コアノードは立ち上げ時にしかconfigを読み込まないため）先ほどのサンプルプログラムを実行します。

```shell-session
$ python test.pyuser id: 92a54325c4eec2ed5b2f573c6feaf6545d43df5fc0f7b4cab9d31472eae83eea
domain id: 748c0b3fafa02e150928a7d3764a4bb1b16a21cb61a1d3f51ed2021933042baa

# 以下はコアノードを立ち上げているコンソールの表示
2018/07/21 22:47:21| DEBUG   | core| [b'748c'] register_user: b'92a54325'
2018/07/21 22:47:21| DEBUG   | core| closing socket
Traceback (most recent call last):
  File "src/gevent/greenlet.py", line 716, in gevent._greenlet.Greenlet.run
  File "/Users/kichinosukey/bbcenv/lib/python3.6/site-packages/gevent/baseserver.py", line 26, in _handle_and_close_when_done
    return handle(*args_tuple)
  File "/Users/kichinosukey/bbcenv/bin/bbc_core.py", line 245, in _handler
    self.networking.domains[user_info[0]]['user'].unregister_user(user_info[1], socket)
KeyError: b't\x8c\x0b?\xaf\xa0.\x15\t(\xa7\xd3vJK\xb1\xb1j!\xcba\xa1\xd3\xf5\x1e\xd2\x02\x193\x04+\xaa'
2018-07-21T13:47:21Z <Greenlet "Greenlet-0" at 0x1079fea48: _handle_and_close_when_done(<bound method BBcCoreService._handler of <__main__, <bound method StreamServer.do_close of <StreamServ,(<gevent._socket3.socket [closed]  object, fd=-1, )> failed with KeyError
```

再度エラーが発生しました。configに先ほどのドメイン情報が反映されているか、確認して見ましょう。

```shell-session
$ cat .bbc1/config.json
{
    "workingdir": ".bbc1",
    "client": {
        "port": 9000,
        "use_node_key": true
    },
    "network": {
        "p2p_port": 6641,
        "max_connections": 100
    },
    "domain_key": {
        "use": false,
        "directory": ".bbc1/domain_keys",
        "obsolete_timeout": 300
    },
    "domains": {
        "0000000000000000000000000000000000000000000000000000000000000000": {
            "module": "p2p_domain0",
            "static_nodes": {},
            "use_ledger_subsystem": false,
            "ledger_subsystem": {
                "subsystem": "ethereum",
                "max_transactions": 4096,
                "max_seconds": 3600
            }
        }
    },
    "ethereum": {
        "chain_id": 15,
        "port": 30303,
        "log": "geth.log",
        "account": "",
        "passphrase": "",
        "contract": "BBcAnchor",
        "contract_address": ""
    },
    "domain_default": {
        "storage": {
            "type": "internal"
        },
        "db": {
            "db_type": "sqlite",
            "db_name": "bbc_ledger.sqlite",
            "replication_strategy": "all",
            "db_servers": [
                {
                    "db_addr": "127.0.0.1",
                    "db_port": 3306,
                    "db_user": "user",
                    "db_pass": "pass"
                }
            ]
        },
        "static_nodes": {}
    }
```

どうやら、先ほどの方法だと反映がされないようです。別の方法でconfigへの反映を試みます。

```shell-session
$ python bbc_domain_update.py -d748c0b3fafa02e150928a7d3764a4bb1b16a21cb61a1d3f51ed2021933042baa -a
Result: success


# 以下はコアノードを立ち上げているコンソールの表示
018/07/21 22:48:47| INFO    | bbc_network| Domain 748c0b3fafa02e150928a7d3764a4bb1b16a21cb61a1d3f51ed2021933042baa is created
2018/07/21 22:48:47| DEBUG   | core| closing socket
2018/07/21 22:48:47| DEBUG   | core| connection closed
```

どうやら上手く行った模様ですが、念のためconfigも確認して見ましょう。

```shell-session
$ cat .bbc1/config.json
{
    "workingdir": ".bbc1",
    "client": {
        "port": 9000,
        "use_node_key": false
    },
    "network": {
        "p2p_port": 6641,
        "max_connections": 100
    },
    "domain_key": {
        "use": false,
        "directory": ".bbc1/domain_keys",
        "obsolete_timeout": 300
    },
    "domains": {
        "0000000000000000000000000000000000000000000000000000000000000000": {
            "module": "p2p_domain0",
            "static_nodes": {},
            "use_ledger_subsystem": false,
            "ledger_subsystem": {
                "subsystem": "ethereum",
                "max_transactions": 4096,
                "max_seconds": 3600
            }
        },
        "748c0b3fafa02e150928a7d3764a4bb1b16a21cb61a1d3f51ed2021933042baa": {
            "storage": {
                "type": "internal"
            },
            "db": {
                "db_type": "sqlite",
                "db_name": "bbc_ledger.sqlite",
                "replication_strategy": "all",
                "db_servers": [
                    {
                        "db_addr": "127.0.0.1",
                        "db_port": 3306,
                        "db_user": "user",
                        "db_pass": "pass"
                    }
                ]
            },
            "static_nodes": {},
            "node_id": "cc32b40a21c7d6ddd5cc43228a5daabbe54ea3453ce2bfce9f61dd037ac4f056"
        }
    },
    "ethereum": {
        "chain_id": 15,
        "port": 30303,
        "log": "geth.log",
        "account": "",
        "passphrase": "",
        "contract": "BBcAnchor",
        "contract_address": ""
    }
```

上手く反映されたようですのでプログラムを実行します。

```shell-session
$ python test.py
user id: 92a54325c4eec2ed5b2f573c6feaf6545d43df5fc0f7b4cab9d31472eae83eea
domain id: 748c0b3fafa02e150928a7d3764a4bb1b16a21cb61a1d3f51ed2021933042baa

# 以下はコアノードを立ち上げているコンソールの表示
2018/07/21 22:52:45| DEBUG   | core| [b'748c'] register_user: b'92a54325'
2018/07/21 22:52:45| DEBUG   | core| closing socket
2018/07/21 22:52:45| DEBUG   | core| connection closed
```

# まとめ（繰り返しになりますが...）
- コアノードを立ち上げたらbbc_domain_update.pyでドメイン情報をconfigに追加すること
    - bbc_domain_config.pyの使い方が間違っているかも知れませんのでコードを調べて見たいと思います