記事の内容
Hyperledger IrohaでPeerを追加する方法です。
本来、一つのVMにPeerを複数作っても耐障害性を考えるとあまり意味がない気がします。
私も勉強用に下図の構成で作ってみたのですが、上手くいかなかった点の考察も踏まえて記録を残します。
環境構築手順
前提条件
・Dockerがインストールされている
iroha関連のコンテナ準備
gitクローン
$ cd ~
$ git clone https://github.com/hyperledger/iroha --depth=1
iroha用のネットワーク構築
$ docker network create iroha-network
blockstoreの構築
blockstoreはpeer毎に用意するので、今回の環境では3つ作成します。
$ docker volume create blockstore1
$ docker volume create blockstore2
$ docker volume create blockstore3
PostgresSQLのコンテナ作成
それぞれのpeer用のpostgresSQLのコンテナを作成します。
名称やポートなどはそれぞれ変えてます。
# iroha1用
$ docker run --name some-postgres1 \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=mysecretpassword \
-p 15432:5432 \
--network=iroha-network \
-d postgres:9.5
# iroha2用
$ docker run --name some-postgres2 \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=mysecretpassword \
-p 25432:5432 \
--network=iroha-network \
-d postgres:9.5
# iroha3用
$ docker run --name some-postgres3 \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=mysecretpassword \
-p 35432:5432 \
--network=iroha-network \
-d postgres:9.5
irohaの設定ファイル修正
追加するpeerに合わせて設定ファイルを修正する必要があります
ノード用のキーペアを作成する
irohaの鍵は「ed25519」という方式で作る必要があります。
この記事ではpythonでの作り方を紹介します。
from iroha import IrohaCrypto
private_key = IrohaCrypto.private_key()
public_key = IrohaCrypto.derive_public_key(private_key)
print('public key:' + str(public_key))
print('private key:' + str(private_key))
このプログラムを3回実行してノード用の鍵を3個作成します。
# node1用
public key:b'ad456d0433db192e78026cb0d12870bec20e2264041759d648e7af8268945dd2'
private key:b'2e93b266eff7adb139155d7b47e00c97967c89f9de65ecdccc89942676db5044'
# node2用
public key:b'2231fa8d74f764fb3018cc59111f66c09542805720fe5f7b814e29cf95130ecb'
private key:b'58a15765b77acc3eadfbf166fd0111e18b3b1114972fad682b1fec81f3d8ce7a'
# node3用
public key:b'63e250b6532e327613b4ee0e826d346c5e473ef8377b33cca5e5b4e369cba8cb'
private key:b'4d7b8c49a5bb8a5e5274c52ad14ed43867f984cab64eda87d308e94c35efc443'
作成したキーは以下のディレクトリに保存します。
保存する内容はb'公開鍵'の公開鍵の部分だけです。
$ cd ~/iroha/example
$ vi node1.pub
$ vi node1.priv
$ vi node2.pub
$ vi node2.priv
$ vi node3.pub
$ vi node3.priv
genesis.blockの修正
irohaではブロックチェーンの初期化時にアカウントの作成やpeerの追加などを設定することができます。
その設定内容をgenesis.blockに記録しておきます。
修正ポイントは以下の点になります。
・addPeerコマンドを追加する
・addressをiroha1~iroha3にする
・peerKeyには前の手順で作成した公開鍵(public key)を設定する
{
"block_v1":{
"payload":{
"transactions":[
{
"payload":{
"reducedPayload":{
"commands":[
{
"addPeer":{
"peer":{
"address":"iroha1:10001",
"peerKey":"ad456d0433db192e78026cb0d12870bec20e2264041759d648e7af8268945dd2"
}
}
},
{
"addPeer":{
"peer":{
"address":"iroha2:10001",
"peerKey":"2231fa8d74f764fb3018cc59111f66c09542805720fe5f7b814e29cf95130ecb"
}
}
},
{
"addPeer":{
"peer":{
"address":"iroha3:10001",
"peerKey":"63e250b6532e327613b4ee0e826d346c5e473ef8377b33cca5e5b4e369cba8cb"
}
}
},
{
"createRole":{
"roleName":"admin",
"permissions":[
"can_add_peer",
"can_add_signatory",
"can_create_account",
"can_create_domain",
"can_get_all_acc_ast",
"can_get_all_acc_ast_txs",
"can_get_all_acc_detail",
"can_get_all_acc_txs",
"can_get_all_accounts",
"can_get_all_signatories",
"can_get_all_txs",
"can_get_blocks",
"can_get_roles",
"can_read_assets",
"can_remove_signatory",
"can_set_quorum"
]
}
},
{
"createRole":{
"roleName":"user",
"permissions":[
"can_add_signatory",
"can_get_my_acc_ast",
"can_get_my_acc_ast_txs",
"can_get_my_acc_detail",
"can_get_my_acc_txs",
"can_get_my_account",
"can_get_my_signatories",
"can_get_my_txs",
"can_grant_can_add_my_signatory",
"can_grant_can_remove_my_signatory",
"can_grant_can_set_my_account_detail",
"can_grant_can_set_my_quorum",
"can_grant_can_transfer_my_assets",
"can_receive",
"can_remove_signatory",
"can_set_quorum",
"can_transfer"
]
}
},
{
"createRole":{
"roleName":"money_creator",
"permissions":[
"can_add_asset_qty",
"can_create_asset",
"can_receive",
"can_transfer"
]
}
},
{
"createDomain":{
"domainId":"test",
"defaultRole":"user"
}
},
{
"createAsset":{
"assetName":"coin",
"domainId":"test",
"precision":2
}
},
{
"createAccount":{
"accountName":"admin",
"domainId":"test",
"publicKey":"313a07e6384776ed95447710d15e59148473ccfc052a681317a72a69f2a49910"
}
},
{
"createAccount":{
"accountName":"test",
"domainId":"test",
"publicKey":"716fe505f69f18511a1b083915aa9ff73ef36e6688199f3959750db38b8f4bfc"
}
},
{
"appendRole":{
"accountId":"admin@test",
"roleName":"admin"
}
},
{
"appendRole":{
"accountId":"admin@test",
"roleName":"money_creator"
}
}
],
"quorum":1
}
}
}
],
"txNumber":1,
"height":"1",
"prevBlockHash":"0000000000000000000000000000000000000000000000000000000000000000"
}
}
}
peer2、3用の作業ディレクトリを準備する
以下のコマンドでディレクトリをコピーする
$ cd ~/iroha
$ cp -r example example1
$ cp -r example example2
config.dockerの修正
config.dockerにirohaデーモンが接続するpostgresSQLの接続情報が記載されているので修正します。
修正箇所はpostgresの接続するコンテナ名を修正します。
以下の内容はiroha1用になります。iroha2,3については「some-postgres」の末尾をそれぞれ1,2に変更します。
変更するファイルは一つ前の手順で作成したexample1,example2配下のファイルを変更します。
{
"block_store_path" : "/tmp/block_store/",
"torii_port" : 50051,
"internal_port" : 10001,
"pg_opt" : "host=some-postgres1 port=5432 user=postgres password=mysecretpassword",
"max_proposal_size" : 10,
"proposal_delay" : 5000,
"vote_delay" : 5000,
"mst_enable" : false,
"mst_expiration_time" : 1440,
"max_rounds_delay": 3000,
"stale_stream_max_rounds": 2
}
irohaコンテナの作成
irohaコンテナを3つ作成します。
この作業は後のログ確認をしやすくするためにもコンソール3つ開いてやります。
iroha1用コンソール
$ cd ~/
$ docker run -it --name iroha1 \
-p 51051:50051 \
-v $(pwd)/iroha/example:/opt/iroha_data \
-v blockstore:/tmp/block_store \
--network=iroha-network \
--entrypoint=/bin/bash \
hyperledger/iroha:develop
$ irohad --config config.docker --genesis_block genesis.block --keypair_name node1
iroha2用コンソール
$ cd ~/
$ docker run -it --name iroha2 \
-p 52051:50051 \
-v $(pwd)/iroha/example1:/opt/iroha_data \
-v blockstore:/tmp/block_store \
--network=iroha-network \
--entrypoint=/bin/bash \
hyperledger/iroha:develop
$ irohad --config config.docker --genesis_block genesis.block --keypair_name node2
iroha3用コンソール
$ cd ~/
$ docker run -it --name iroha3 \
-p 53051:50051 \
-v $(pwd)/iroha/example2:/opt/iroha_data \
-v blockstore:/tmp/block_store \
--network=iroha-network \
--entrypoint=/bin/bash \
hyperledger/iroha:develop
$ irohad --config config.docker --genesis_block genesis.block --keypair_name node3
irohadを起動するとpeer間の通信が始まります。
以下のログが出なければ通信が出来ています。
[2020-07-12 07:16:41.189637262][W][Irohad/AsyncNetworkClient]: RPC failed: Connect Failed
問題なくpeer間の通信が出来れば任意のirohaコンテナでトランザクションを発行すると他のpeerに伝播されます。
複数VM上での環境構築
冒頭の「記事の内容」にある2枚目の構成ですが、接続先を上述の手順に従って環境構築を行うとpeer間通信に失敗します。
Dockerの仕組みを詳しく理解出来ていないのですが、「some-posetgres」コンテナと「iroha」コンテナにネットワークの設定をしているので、そのネットワークに属しているコンテナ間での通信しか出来ていないようです。
iroha-networkの状態は以下の通りです。
$ docker network inspect iroha-network
[
{
"Name": "iroha-network",
"Id": "7f1bece6bdc22c6b19c37d27688aade48f79ed535fc4559596b8ba37adb5ae32",
"Created": "2020-07-06T10:05:55.231024539+09:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"0ecae19bc240761655a43ad873c21c88988f95a3e9166061039d739848c2627e": {
"Name": "iroha2",
"EndpointID": "830fc0b25dbc28d354d1f7ec3dc28bdc0f566fc1bdaba1bbc41e6e92538052fc",
"MacAddress": "02:42:ac:12:00:07",
"IPv4Address": "172.18.0.7/16",
"IPv6Address": ""
},
"677a6d75ac0a03f06f1a52b4e75d5419ca276bcde64b99128d0d047ac3ad0f34": {
"Name": "iroha3",
"EndpointID": "afb8c6a29e3289ea37979d2fe282084b5ba04973bd4f6a10fed37827f18c60cd",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"7e6cbf92da619affbc28d163a31fd34bfc4c93ea92591e351247e321747d3f68": {
"Name": "some-postgres3",
"EndpointID": "a59da433970aec949b0d165fd3665d20b9ec88ddb9e47458cb4161309f4e0700",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
},
"7efea6ca37944fa3fefc3f9fc9ce10159110626d968a3cb31df8fc46c235d26b": {
"Name": "some-postgres2",
"EndpointID": "9efc395b1c924d3dc19486b759c85ba2412176acc4c930448ebb21efb48e30ba",
"MacAddress": "02:42:ac:12:00:05",
"IPv4Address": "172.18.0.5/16",
"IPv6Address": ""
},
"9a50c10cefa20a294e9e1435d397c26fb8d55b85321f78047ec55fdde0f41089": {
"Name": "iroha1",
"EndpointID": "d29d34a95ca89be928c054b4c6207c5e2d9c5d53138b158a9a3e8dde36d9a4f3",
"MacAddress": "02:42:ac:12:00:06",
"IPv4Address": "172.18.0.6/16",
"IPv6Address": ""
},
"c91191410d2d0224ef4ad816305a0bc3d39864e72777de2eab1ec3038599bcf8": {
"Name": "some-postgres1",
"EndpointID": "78d8fe9782659cf99d161781e1dc91662ebb7bfb7042cce54bbf615169fc8110",
"MacAddress": "02:42:ac:12:00:04",
"IPv4Address": "172.18.0.4/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
恐らくですが、Dockerのオーバーレイネットワークというホストを跨ったコンテナ同士のネットワークを構築する仕組みを利用すれば接続が出来そうです。
ちなみにですが、「some-postgres」、「iroha」コンテナに「--network」の設定をしなかった場合、irohaデーモンの起動時に初期化に失敗します。
オーバーレイネットワークを使用した環境構築はおいおい試してみることにします。