Tech

ErisでPermissioned Blockchainを作る

  • このエントリーをはてなブックマークに追加

Erisでテスト・開発用のプライベート・ブロックチェーンをドキュメントを読みながら作成する

ステップ1. 公開鍵を作る

eris keysコマンド

~/.eris/keys/data にデータあり

eris services start keys

上記、鍵を作るためだけのDocker上で鍵を生成している様子。

鍵サービスの起動確認


eris services ls

SERVICES NAME TYPE RUNNING CONTAINER NAME CONTAINER # PORTS


keys service Yes eris_service_keys_1 1 4767/tcp
btcd No 0
do_not_use No 0
eth No 0
ipfs No 0
mindy No 0
mint No 0
openbazaar No 0
tinydns No 0
toadserver No 0

eris keysで、できることを見る

eris services exec keys "eris-keys -h"

鍵用Dockerコンテナ上で、”eris-keys -h”を実行している(?)

A tool for doing a bunch of cool stuff with keys.

Usage:
  eris-keys [flags]
  eris-keys [command]

Available Commands:
  gen         Generate a key
  lock        lock a key
  unlock      unlock a key
  name        Manage key names. `eris-keys name <name> <address>`
  sign        eris-keys sign --addr <address> <hash>
  pub         eris-keys pub --addr <addr>
  verify      eris-keys verify --addr <addr> <hash> <sig>
  hash        eris-keys hash <some data>
  server      eris-keys server
  import      eris-keys import <priv key> | /path/to/keyfile | <key json>
  help        Help about any command

Flags:
      --addr="": address of key to use
      --dir="/home/eris/.eris/keys": specify the location of the directory containing key files
  -h, --help=false: help for eris-keys
      --host="keys": set the host for talking to the key daemon
  -l, --log=0: specify the location of the directory containing key files
      --name="": name of key to use
      --port="4767": set the port for key daemon to listen on


Use "eris-keys [command] --help" for more information about a command.

eris keys -h

Usage: eris keys COMMAND [FLAG...]

The keys subcommand is an opiniated wrapper around
eris-keys and requires a keys container to be running.

It is for development only.
Advanced functionality is available via: [eris services exec keys "eris-keys CMD"]

see https://docs.erisindustries.com/documentation/eris-keys/ for more info

Available Commands:
  gen         Generates an unsafe key using the keys container.
  pub         Returns a machine readable pubkey given an address.
  export      Export a key from container to host.
  import      Import a key to container from host.
  convert     Convert and eris-keys key to tendermint key

Global Flags:
  -d, --debug[=false]: debug level output
  -m, --machine="eris": machine name for docker-machine that is running VM
  -n, --num=1: container number
  -v, --verbose[=false]: verbose output

Use "eris keys COMMAND --help" for more information about a command.

鍵を作る!

eris keys gen

キーペアの公開アドレスが表示される

注意) これ以降は、デモ目的のためだけの方法で、本番ではやっていけない方法です。

管理者の鍵を作る

chain_dir=~/.eris/chains/idiaminchain
mkdir $chain_dir
eris keys gen > $chain_dir/admin_addr

5つのvalidatorの鍵を作る

fin=4
for ((i=0;i<=fin;i++)); do
  eris keys gen >> $chain_dir/val_addr
done

eris-keysで生成した鍵を見る

eris services exec keys "ls /home/eris/.eris/keys/data"

これらの鍵をeris:dbで利用できるようにしないといけない

正しい鍵の文字列を変数に入れる

eris-keysの形式をeris:dbで利用できる形式にする

admin_addr=$(cat $chain_dir/admin_addr | sed -e 's/[[:space:]]//')

bashの場合
(以下、公式マニュアル通りですが、バグっていると思われます。)

readarray vals_addrs < $chain_dir/val_addr
readarray participant_addrs < $chain_dir/part_addr

こちらでは、上記エラーになりました。

zshの場合

zmodload -ap zsh/mapfile mapfile
vals_addrs=( "${(f)mapfile[$chain_dir/val_addr]}" )
participant_addrs=( "${(f)mapfile[$chain_dir/part_addr]}" )

生の公開鍵をeris:db形式にする

eris keys convert $admin_addr > $chain_dir/priv_validator.json

同じことをvalidator keyにもする

declare -a vals_keys
fin=4
for ((i=0;i<=fin;i++)); do
  addr=$(echo ${vals_addrs[$i]} | sed -e 's/[[:space:]]//')
  vals_keys[$i]=$(eris keys pub $addr | sed -e 's/[[:space:]]//')
done

同じことをparticipant keysにもする

declare -a participant_keys
fin=19
for ((i=0;i<=fin;i++)); do
  addr=$(echo ${participant_addrs[$i]} | sed -e 's/[[:space:]]//')
  participant_keys[$i]=$(eris keys pub $addr | sed -e 's/[[:space:]]//')
done

これで、priv_validator.jsonが作成された。

ステップ2. genesis.csvを作成

ステップ3で、ブロックチェーンをインスタンス化ために必要な.csvファイルを作る

ブロックチェーンを作って、停止する

eris chains new idiaminchain
eris chains stop idiaminchain

ブロックチェーンを開始する方法

eris chains start idiaminchain

パーミッションを見る

% eris chains exec -p idiaminchain mintperms all
Perms and SetBit (As Integers)
16383,16383

root: true
send: true
call: true
create_contract: true
create_account: true
bond: true
name: true
has_base: true
set_base: true
unset_base: true
set_global: true
has_role: true
add_role: true
rm_role: true

-p オプションはランダムにportを公開する

chains execコマンドで、port is already allocatedエラーが出たら使う

permissions と set bits のセットアップ

ユーザの”types”ごとにpermissionsとSetBit変数を保存

公式チュートリアルは別々にやっているが、面倒なのでシェルスクリプト化したので、以下を実行

#!/bin/bash
perms_admin=$(eris chains exec -p idiaminchain mintperms all | grep -C 1 "(As Integers)" | tail -n 1 | awk -F ',' '{print $1}')
setbt_admin=$(eris chains exec -p idiaminchain mintperms all | grep -C 1 "(As Integers)" | tail -n 1 | awk -F ',' '{print $2}')
perms_part=$(eris chains exec -p idiaminchain mintperms int root:0 send:1 call:1 create_contract:1 create_account:1 bond:0 name:1 | grep -C 1 "(As Integers)" | tail -n 1 | awk -F ',' '{print $1}')
setbt_part=$(eris chains exec -p idiaminchain mintperms int root:0 send:1 call:1 create_contract:1 create_account:1 bond:0 name:1 | grep -C 1 "(As Integers)" | tail -n 1 | awk -F ',' '{print $2}')
perms_vals=$(eris chains exec -p idiaminchain mintperms int root:0 send:0 call:0 create_contract:0 create_account:0 bond:1 name:0 | grep -C 1 "(As Integers)" | tail -n 1 | awk -F ',' '{print $1}')
setbt_vals=$(eris chains exec -p idiaminchain mintperms int root:0 send:0 call:0 create_contract:0 create_account:0 bond:1 name:0 | grep -C 1 "(As Integers)" | tail -n 1 | awk -F ',' '{print $2}')

echo $perms_part で確認

これでパーミッションができた

各ユーザにトークンをあげる

tokens="2251799813685248"

accounts.csvとvalidators.csvを作成

chain_name="idiaminchain"
write_line() {
  echo "$1","$2","$3","$4","$5" >> $chain_dir/accounts.csv
}
write_line_vals() {
  echo "$1","$2","$3","$4","$5" >> $chain_dir/validators.csv
}

account.csvの例

9B7C6F1F52400C35BE6F5CB7138304369A7DCD77,2251799813685248,idiaminchain_admin,16383,16383
049387262939D3499CB52C9D4CF1E1EB70CF84CC,2251799813685248,idiaminchain_val_00,32,127
E38899B3518EF34BFE3EA898C4D8981A7900202C,2251799813685248,idiaminchain_val_04,32,127
A0FEFEB34F8065BFC6C53926994DD98F430585C6,2251799813685248,idiaminchain_particpant_00,94,127

validators.csvの例

049387262939D3499CB52C9D4CF1E1EB70CF84CC,2251799813685248,idiaminchain_val_00,32,127
1798977C968653221907677907694FA629D30F15,2251799813685248,idiaminchain_val_01,32,127
ABF9F624E42ACB695F04301EBC7BC9B04C0D8464,2251799813685248,idiaminchain_val_02,32,127
9F2891F348AF4748386EE86A9C113CA1E5D17BC9,2251799813685248,idiaminchain_val_03,32,127
E38899B3518EF34BFE3EA898C4D8981A7900202C,2251799813685248,idiaminchain_val_04,32,127

ステップ3. ブロックチェーンをインスタンス化

ジェネシス・ブロックを作ります。

ヘルプを表示

eris chains exec -p idiaminchain "mintgen -h"

問題が起きた時にすること

Dockerプロセスを見る

docker ps -a
eris chains rm --data $chain_name
eris chains new $chain_name --dir $chain_name
eris chains stop $chain_name

genesis.json.bakでバックアップを取る

eris chains exec -p $chain_name "mintgen known --csv=/home/eris/.eris/chains/$chain_name/validators.csv,/home/eris/.eris/chains/$chain_name/accounts.csv $chain_name" > $chain_dir/genesis.json.bak

genesis.json 生成のためのサンプルとコード

genesis.json サンプル

https://github.com/eris-ltd/eris-pm/tree/master/tests/fixtures/chaindata

{
  "chain_id": "my_tests",
  "accounts": [
    {
      "address": "1040E6521541DAB4E7EE57F21226DD17CE9F0FB7",
      "amount": 999999999999,
      "permissions": {
        "base": {
          "perms": 16383,
          "set": 16383
        },
        "roles": []
            }
    },
    {
      "address": "6A3AFFB16BFB95AA547930572D71C460EFBCD857",
      "amount": 110000000000
    },
    {
      "address": "58FD1799AA32DED3F6EAC096A1DC77834A446B9C",
      "amount": 110000000000
    }
  ],
  "validators": [
    {
      "pub_key": [
        1,
        "82DADAE153406412833F8098439ED4B5DCC26C0B43C2775EFFE8B911B49D0182"
      ],
      "amount": 5000000000,
      "unbond_to": [
        {
          "address": "1040E6521541DAB4E7EE57F21226DD17CE9F0FB7",
          "amount": 5000000000
        }
      ]
    }
  ]
}

アカウントのコード

https://github.com/eris-ltd/tendermint/blob/develop/account/account.go#L40-L49

type Account struct {
    Address     []byte `json:"address"`
    PubKey      PubKey `json:"pub_key"`
    Sequence    int    `json:"sequence"`
    Balance     int64  `json:"balance"`
    Code        []byte `json:"code"`         // VM code
    StorageRoot []byte `json:"storage_root"` // VM storage merkle root.

    Permissions ptypes.AccountPermissions `json:"permissions"`
}

パーミッションのコード

https://github.com/eris-ltd/tendermint/blob/develop/permission/types/permissions.go

validatorsのコード

https://github.com/eris-ltd/tendermint/blob/develop/types/validator.go#L14-L23

type ValidatorInfo struct {
    Address         []byte            `json:"address"`
    PubKey          acm.PubKeyEd25519 `json:"pub_key"`
    UnbondTo        []*TxOutput       `json:"unbond_to"`
    FirstBondHeight int               `json:"first_bond_height"`
    FirstBondAmount int64             `json:"first_bond_amount"`
    DestroyedHeight int               `json:"destroyed_height"` // If destroyed
    DestroyedAmount int64             `json:"destroyed_amount"` // If destroyed
    ReleasedHeight  int               `json:"released_height"`  // If released
}

トラブルシューティング

container already exists問題

何かコマンドを打った時に以下が出る問題

container already exists

解決方法:

docker ps -a

上記で、eris_interactive_eris_chain_idiaminchain_1 があるなら、削除する

docker ps -a | grep eris_interactive_eris_chain_idiaminchain_1
docker rm [コンテナID]

検索用語

  • Ethereum, イーサリアム
  • Eris, HydraChain, PoA
  • Private blockchain, プライベート・ブロックチェーン, プライベートチェーン
  • Eris Industries, エリス・インダストリーズ
  • このエントリーをはてなブックマークに追加