【Ethereum】EthereumでPrivateNetworkを作ってみる
仕事の関係でブロックチェーンのプラットフォームであるEthereumを調べることになり、
簡単な動作確認を行うためにプライベートのEthereumのネットワークを作成してみました。
- ※ 調べながらのものなのでところどころ間違っているかもしれません。
- ※ ブロックチェーン、仮想コイン自体の知識も深くないためそちらも認識に齟齬があるかもしれません。
動作環境
OS: ubuntu:14.04 * ※ 僕の環境はMacOSなのですが、試行錯誤なので環境がよごれないようにDockerでubuntuをインストールして試しています。 * ※ Docker周辺の操作自体は割愛させていただきます。
Ethereumとは
Ethereumは、ブロックチェーンを使ったアプリケーションのプラットフォームです。
(Ethereum、ブロックチェーンの技術詳細については、ここでは割愛します。)
ブロックチェーンを使ったアプリケーションを作成する方法は大きく分けて2つあります。
1つは、「ゼロからブロックチェーンのネットワークを構築する方法」、もう一つは「既存のブロックチェーンの技術基盤を利用して構築する方法」です。
Ethereumは後者にあたるもので、Ethereumを利用することでブロックチェーンを利用したアプリケーションを低コストで作成することができます。
Gethをインストールする
EthereumのP2Pネットワークに参加するためにGeth
というクライアントツールが提供されています。
(GethはGo言語製のツールです)
Gethをインストールすることで、
といった操作を行うことができます。 まずは、このツールをインストールします。
sudo apt-get install software-properties-common sudo add-apt-repository -y ppa:ethereum/ethereum sudo add-apt-repository -y ppa:ethereum/ethereum-dev sudo apt-get update sudo apt-get install ethereum
ネットワーク用のディレクトリを作る
mkdir eth_private cd eth_private
※ このテスト実装では、/ethereum
というディレクトリをルートディレクトリとして作業しています。
アカウントをつくる
一番初めのアカウントを定義します。
geth --datadir /ethereum/eth_private account new
datadir
に先程作成したディレクトリを指定します
WARN [07-09|03:57:57] No etherbase set and no accounts found as default Your new account is locked with a password. Please give a password. Do not forget this password. Passphrase:
No etherbase set and no accounts found as default
- この警告はなんでしょう?デフォルトのアカウントがないよという意味のようですが、何もない状態でアカウントを作成しているから?一旦無視します。
パスワードを聞かれるため入力する
- ※ 注意 パスワードを忘れるとあとで確認する方法がないため、忘れない方法で保管しておきます。
Address: {4e2e0ef96802a54c8e1d5c937e38290c42ced5f0}
- 発行されるとアカウントの公開キーが表示されます。(アカウントのアドレスと呼ばれるものです。)
- アカウントの作成が成功すると作業ディレクトリ配下に
keystore
というディレクトリが作成されています。 - さらにその配下にはUTC-xxxから始まるjsonファイルが作成されています。
root@03be5503f430:/ethereum/eth_private# ls -la total 0 drwxr-xr-x 3 root root 102 Jul 9 03:58 ./ drwxr-xr-x 5 root root 170 Jul 9 03:57 ../ drwx------ 3 root root 102 Jul 9 2017 keystore/ root@03be5503f430:/ethereum/eth_private# ls -la keystore/ total 4 drwx------ 3 root root 102 Jul 9 04:04 ./ drwxr-xr-x 3 root root 102 Jul 9 03:58 ../ -rw------- 1 root root 491 Jul 9 03:58 UTC--2017-07-09T03-58-15.183698355Z--4e2e0ef96802a54c8e1d5c937e38290c42ced5f0
{ "address": "4e2e0ef96802a54c8e1d5c937e38290c42ced5f0", "crypto": { "cipher": "aes-128-ctr", "ciphertext": "ee886a6635bc095337d643de774ec86c38c32016a1f56c5f3d1e9fb092993193", "cipherparams": { "iv": "caa069b4c621db2ddd3c9aa11acd9de2" }, "kdf": "scrypt", "kdfparams": { "dklen": 32, "n": 262144, "p": 1, "r": 8, "salt": "8453090efc0f98075afbb046521273909a3c26d6244e2453b83ddae7d6d0540c" }, "mac": "85249864f73dd75ed70e9e8e2123aa0d10d2c5f73d7bfde510fa547804d092d3" }, "id": "a9d3805d-0a8a-4ef4-a89a-1c0949737951", "version": 3 }
- addressは先程作成したアカウントの公開キーと一致するためこれがアカウント情報のようです。(詳細はここでは追いません)
GenesisBlockの設定ファイルを作成する
{ "config": { "chainId": 13, "homesteadBlock": 0, "eip155Block": 0, "eip158Block": 0 }, "difficulty": "200000000", "gasLimit": "2100000", "alloc": { "4e2e0ef96802a54c8e1d5c937e38290c42ced5f0": { "balance": "100000000" } } }
chainId
: 後に指定するネットワークIDと合わせたIDhomesteadBlock
: 0ブロック以降がHomestead
であるという設定homestead
とは、Ethereumのバージョンのことでこのバージョンの前後で処理が異なるみたいです
eip155Block
: 不明eip158Block
: 不明difficulty
: マイニングの難易度。低ければ低い程、短時間でマイニングできるようです。gasLimit
: トランザクションで指定できる最大gasalloc
: 初期Etherの設定。ここで先程作成したアカウントを指定しています。- 単位は
wei
- 単位は
GenesisBlockを初期化する
geth --datadir /ethereum/eth_private init /ethereum/eth_private/CustomGenesis.json
- ここでもネットワークのディレクトリを指定してます。
INFO [07-09|04:15:31] Allocated cache and file handles database=/ethereum/eth_private/geth/chaindata cache=16 handles=16 INFO [07-09|04:15:31] Writing custom genesis block INFO [07-09|04:15:31] Successfully wrote genesis state database=chaindata hash=6aa7ce…33ec9a INFO [07-09|04:15:31] Allocated cache and file handles database=/ethereum/eth_private/geth/lightchaindata cache=16 handles=16 INFO [07-09|04:15:31] Writing custom genesis block INFO [07-09|04:15:31] Successfully wrote genesis state database=lightchaindata hash=6aa7ce…33ec9a
- 上記のように表示されれば正しく初期化がされています。
root@03be5503f430:/ethereum/eth_private# ls -la total 4 drwxr-xr-x 5 root root 170 Jul 9 04:15 ./ drwxr-xr-x 5 root root 170 Jul 9 03:57 ../ -rw-r--r-- 1 root root 288 Jul 9 04:14 CustomGenesis.json drwxr-xr-x 4 root root 136 Jul 9 04:15 geth/ drwx------ 3 root root 102 Jul 9 04:04 keystore/
root@03be5503f430:/ethereum/eth_private# ll geth/ total 0 drwxr-xr-x 4 root root 136 Jul 9 04:15 ./ drwxr-xr-x 5 root root 170 Jul 9 04:15 ../ drwxr-xr-x 7 root root 238 Jul 9 04:15 chaindata/ drwxr-xr-x 7 root root 238 Jul 9 04:15 lightchaindata/
- geth配下には
chaindata
というディレクトリがあり、ここにはブロックチェーンの起源を表すleveldbデータベースファイルと、それが採掘されてブロックチェーンに追加された後のブロックが含まれているようです。 - つまり新しいブロックが作られるとこのDBにデータが追加されていくようです。
Gethを起動(コンソール)
- Gethを起動しネットワークにattachします。
- Gethには対話式のコンソールが用意されています。このコンソールを起動して色々確認してみます。
geth --networkid 13 --datadir /ethereum/eth_private console 2>> /ethereum/eth_private/geth_err.log
instance: Geth/v1.6.6-stable-10a45cb5/linux-amd64/go1.8.1 coinbase: 0x4e2e0ef96802a54c8e1d5c937e38290c42ced5f0 at block: 0 (Thu, 01 Jan 1970 00:00:00 UTC) datadir: /ethereum/eth_private modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0 >
- networkidには、Genesisファイルで定義したchainIdを指定します。
- errer出力をlogファイルに書き出しています。
アカウントの確認
> eth.accounts ["0x4e2e0ef96802a54c8e1d5c937e38290c42ced5f0"]
- 先程作成したアカウントが確認できます。
etherbase(coinbase)の確認
> eth.coinbase "0x4e2e0ef96802a54c8e1d5c937e38290c42ced5f0"
- etherbase(coinbase)とは、そのノードで発掘を行った時にその報酬を紐付けるEOAのアドレスを指します。
所持Etherの確認
> eth.getBalance("0x4e2e0ef96802a54c8e1d5c937e38290c42ced5f0") 100000000
- 引数にアカウントのaddressを指定します。
- Genesisファイルで初めに指定したEther(単位はwei)を所持していることが確認できます
Gethを起動(JSON-RPC)
- コンソールを使わずにネットワークにattachします。
geth \ --datadir /ethereum/eth_private \ --mine \ --nodiscover \ --maxpeers 0 \ --networkid 13 \ --rpc \ --rpccorsdomain "*"
mine
: マイニングを許可する。このオプションを指定するとマイニングが始まるようです。nodiscover
: Gethはデフォルトで自動的に(同じネットワークID)のEthereumネットワークのノード(Peer)を探し接続を試みます。プライベート・ネットで未知のノードとの接続を避けるため、このオプションを指定することで自動Peer探索機能を無効にします。maxpeers
ネットワークに接続するノードの最大数(デフォルト25) 0を指定するとネットワークが無効になります。networkid
ネットワークID(デフォルト1) 1を指定するとグローバルのネットワークに接続されます。- 2,3,4も予約されているようです。(2=Morden (disused), 3=Ropsten)
rpc
HTTP-RPC serverとして動作を許可するrpccorsdomain
クロスオリジンを許可するリスト
root@03be5503f430:/ethereum/eth_private# geth --datadir /ethereum/eth_private --mine --nodiscover --maxpeers 0 --networkid 13 --rpc --rpccorsdomain "*" INFO [07-09|06:02:23] Starting peer-to-peer node instance=Geth/v1.6.6-stable-10a45cb5/linux-amd64/go1.8.1 INFO [07-09|06:02:23] Allocated cache and file handles database=/ethereum/eth_private/geth/chaindata cache=128 handles=1024 INFO [07-09|06:02:23] Initialised chain configuration config="{ChainID: 13 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: <nil> EIP155: 0 EIP158: 0 Metropolis: <nil> Engine: unknown}" INFO [07-09|06:02:23] Disk storage enabled for ethash caches dir=/ethereum/eth_private/geth/ethash count=3 INFO [07-09|06:02:23] Disk storage enabled for ethash DAGs dir=/root/.ethash count=2 INFO [07-09|06:02:23] Initialising Ethereum protocol versions="[63 62]" network=13 INFO [07-09|06:02:23] Loaded most recent local header number=0 hash=6aa7ce…33ec9a td=200000000 INFO [07-09|06:02:23] Loaded most recent local full block number=0 hash=6aa7ce…33ec9a td=200000000 INFO [07-09|06:02:23] Loaded most recent local fast block number=0 hash=6aa7ce…33ec9a td=200000000 INFO [07-09|06:02:23] Starting P2P networking INFO [07-09|06:02:23] RLPx listener up self="enode://9df46f04a32634b47ce6fe8203b8077029550890d5f118b6ad88aaee15db9d96ac819f119a3997c5b5c9cecff395b866c7c45c39f830ce3111d63fb7c5853bed@[::]:30303?discport=0" INFO [07-09|06:02:23] IPC endpoint opened: /ethereum/eth_private/geth.ipc INFO [07-09|06:02:23] HTTP endpoint opened: http://127.0.0.1:8545 INFO [07-09|06:02:23] Transaction pool price threshold updated price=18000000000 INFO [07-09|06:02:23] Starting mining operation INFO [07-09|06:02:23] Commit new mining work number=1 txs=0 uncles=0 elapsed=178.695µs INFO [07-09|06:02:28] Generating DAG in progress epoch=0 percentage=0 elapsed=3.764s INFO [07-09|06:02:30] Generating DAG in progress epoch=0 percentage=1 elapsed=6.657s
- gethを起動するとしばらく
Generating DAG in progress
というログが流れる。これはDAGという数Gバイトのデータセットを作成しているログのようです。 - これは
Ethash
というProof of Work
を行うための仕組みで使われるもの。詳しくはここを参照。 - DAGはデフォルトで
$(HOME)/.ethash
配下に作成されています。
INFO [07-09|07:09:58] Successfully sealed new block number=1 hash=ef4ec0…62e718 INFO [07-09|07:09:58] 🔨 mined potential block number=1 hash=ef4ec0…62e718 INFO [07-09|07:09:58] Commit new mining work number=2 txs=0 uncles=0 elapsed=431.601µs
- しばらくすると(1,2時間くらい)マイニングが始まりブロックが作成されます
JSON-RPCで通信してみる
クライアントのバージョン(web3_clientVersion)
curl -X POST --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":1}' http://localhost:8545
{"jsonrpc":"2.0","id":1,"result":"Geth/v1.6.6-stable-10a45cb5/linux-amd64/go1.8.1"
Etherの確認(eth_getBalance)
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x4e2e0ef96802a54c8e1d5c937e38290c42ced5f0", "latest"],"id":1}' http://localhost:8545
{"jsonrpc":"2.0","id":1,"result":"0x5f5e100"}
- resultには16進数の値が入っている。これを10進数に変換すると
100000000
となるので正しい値が入っていることがわかります。