Ethereum: geth ライブネット接続~ソロマイニングするまでの話
(2017年8月11日現在)
環境
-os:Windows7
-メモリ:8GB
-グラフィックボード:gtx1060,rx580
-ソフトウェア:geth1.67, etherminer0.11,
やろうとしたこと
-Ethereumでライブネットと同期すること
-GPUでソロマイニングをしてみる。
-python3でjson-rpcを触ってみる
結果
-同期まで3日かかる。
-チェーンデータが32GB以上(2017/8/11時点)。
-ソロマイニングは結果を確認しきれない。
-python3で比較的簡単に情報が取り出せる。
1.Ethereumノードを構築する
gethバイナリ版をダウンロードする(現時点:geth1.67)
https://github.com/ethereum/go-ethereum/wiki/Installation-instructions-for-Windows
インストールを実行。
2.Ethereumのライブネットと同期を開始する
gethをインストールしたら、コマンドライン上から実行。
(バッチファイルを作成しておくと楽。)
geth.exe --datadir "D:\eth\mainnet" --fast --identity umidachi --rpc --rpcaddr "localhost" --rpcport "8545" --cache=2048 --ipcdisable console
(オプション:--datadirは後々、チェーンサイズが大きくなることを想定して、容量に余裕のあるディレクトリを指定。)
コマンド投入直後、同期がすぐに完了しない。
同期の状況を確認するため、コンソール上からコマンドを投入
>eth.syncing
currentBlock:××××
highestBlock:4148728 ←2017年8月11日時点
knownStates:××××
pulledStates:××××
startingBlock:××××
currentBlockがhighestBlockに近づけば同期する。
(currentBlockを400万ブロック以上になるまで気長に待つ。)
上記コマンド投入後、"false"が出力されることがあるが
同期が始まっていない可能性があるため、時間をおいて再度実行する。
ライブネット上の現在のブロックは次のサイトから確認できる。
・https://etherscan.io/
・https://ethstats.net/
ある程度、チェーンデータのダウンロードができると
eth.blockNumberで、自分のノードが持っているブロック番号を表示できる。
>eth.blockNumber
4150662 (同期が進んでいなかったりすると0が出力される)
同期が完了すると次の画像のように、eth.blockNumberコマンドを投入したときの
blockNumberとetherscanのblockNumberが一致していることが確認できる。
通信環境にも依存すると思うが、自分の場合3日経過して同期が完了した。
eth.syncingコマンド投入すると"false"が出力
>eth.syncing
false
ノード用にETHを管理するアカウントを作る。
>personal.newAccount()
Passphrase:
パスフレーズを求められるため、パスワード入力し
アカウントを作成する。
自身のアカウントが作成されたことを確認するため
次のコマンドを入力する。
>eth.coinbase
"0x○○○○○○○○○○○○○" ←は自身で作成したアドレス
マイニングに成功した場合、"0x○○○○○○○○○○○○○"にEthが
入るはず。
3.マイニングツールをダウンロードする。
下記ページからethminer 0.11.0 "Optimized Nvidia mining"のwindows版をダウンロードする。
・https://github.com/ethereum-mining/ethminer/releases
ダウンロード完了後、ファイルを展開。
gethとは別にコマンドプロンプトを立ち上げて
ethminerを実行する。(バッチファイルを作っておくと楽)
ethminer.exe -U --cuda-devices 0
ethminer.exe -G --opencl-platform 1 --opencl-devices 1
補足:
ethminerのオプションは適宜自身の環境に合わせて入力すること。
プールマイングは"-F"をつけてプール先のURLを指定するが、
ソロの場合-Fを指定しない。
(デフォルトでhttp://127.0.0.1:8545 となるため。)
上記コマンドを投入すると、gethコンソール上で次のメッセージが出力される。
INFO [08-13|10:53:13] Starting mining operation
gethのコンソール上で、マイニングが開始されているか確認をする。
>eth.mining
true
マイニングのハッシュレートについてはgethのコンソール上で確認できる。
>eth.hashrate
41201414 (gtx1060,rx580を同時に実行)
最後にgethのコンソール上で次のコマンドを投入し、ノードの残高を確認する。
eth.getBalance(eth.accounts[0])
0
(執筆時点で残高が増えていることは未確認)
4.python3でノードと通信してみる。
これまでの同期状況やマイニングの状況を確認するために
gethコンソールでコマンドを投入するのも面倒。
python3にapiを叩くスクリプトを書いておき、ethereumノードと通信させる。
json-rpc用のモジュールを入れる。
pip3 install json-rpc
次のページにEthereumのjson-rpcの説明が載っているのでそれを参考にする。
https://github.com/ethereum/wiki/wiki/JSON-RPC
たとえば、blockNumberを出力させたいなら
次のsample.pyのようにする。
import requests
import json
def eth_blockNumber(url):
headers = {'content-type': 'application/json'}
payload = {
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": 0
}
response = requests.post(url, data=json.dumps(payload), headers=headers).json()
print(response)
print("bockNumber:",i)
if __name__ == "__main__":
url="http://localhost:8545"
eth_blockNumber(url)
{'jsonrpc': '2.0', 'id': 0, 'result': '0x3f56d1'}
bockNumber: 4150993
出力からわかるように16進数で値が返されるため、10進数になおしている。
上記と同じ要領で、これまでに確認してきたコマンドを割り当てていく。
import requests
import json
def eth_syncing(url):
headers = {'content-type': 'application/json'}
payload = {
"jsonrpc": "2.0",
"method": "eth_syncing",
"params": [],
"id": 0
}
response = requests.post(url, data=json.dumps(payload), headers=headers).json()
print("--eth_syncing---")
print(response)
if response["result"]:
f=int(response["result"]["startingBlock"],16)
g=int(response["result"]["knownStates"],16)
h=int(response["result"]["pulledStates"],16)
i=int(response["result"]["currentBlock"],16)
j=int(response["result"]["highestBlock"],16)
print("startingBlcok:",f)
print("knownStates:",g)
print("pulledStates:",h)
print("currentBlock:",i)
print("highestBlock:",j)
def eth_getBalance(url,addr):
headers = {'content-type': 'application/json'}
payload = {
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": [addr,"latest"],
"id": 0
}
response = requests.post(url, data=json.dumps(payload), headers=headers).json()
print("--eth_getBalance---")
print(response)
i=int(response["result"],16)
print("getBalance:",i)
def net_peerCount(url):
headers = {'content-type': 'application/json'}
payload = {
"jsonrpc": "2.0",
"method": "net_peerCount",
"params": [],
"id": 0
}
print("--eth_peerCount---")
response = requests.post(url, data=json.dumps(payload), headers=headers).json()
print(response)
i=int(response["result"],16)
print("peerCount:",i)
def eth_coinbase(url):
headers = {'content-type': 'application/json'}
payload = {
"jsonrpc": "2.0",
"method": "eth_coinbase",
"params": [],
"id": 0
}
print("--eth_coinbase---")
response = requests.post(url, data=json.dumps(payload), headers=headers).json()
print(response["result"])
def eth_hashrate(url):
headers = {'content-type': 'application/json'}
payload = {
"jsonrpc": "2.0",
"method": "eth_hashrate",
"params": [],
"id": 0
}
print("--eth_hashrate---")
response = requests.post(url, data=json.dumps(payload), headers=headers).json()
print(response["result"])
def eth_blockNumber(url):
headers = {'content-type': 'application/json'}
payload = {
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": 0
}
print("--eth_blocknumber---")
response = requests.post(url, data=json.dumps(payload), headers=headers).json()
i=int(response["result"],16)
print(response)
print("eth_blockNumber:",i)
if __name__ == "__main__":
url = "http://localhost:8545"
eth_syncing(url)
eth_getBalance("xxxxx")
net_peerCount(url)
eth_coinbase(url)
eth_blockNumber(url)
eth_getBalance("xxxxx") はcoinbaseのアドレスを指定すること。
--eth_syncing---
{'jsonrpc': '2.0', 'id': 0, 'result': False}
--eth_getBalance---
{'jsonrpc': '2.0', 'id': 0, 'result': '0x18fbbca3faa8c76'}
getBalance: 112514993033481334
--eth_getBalance---
{'jsonrpc': '2.0', 'id': 0, 'result': '0x0'}
getBalance: 0
--eth_peerCount---
{'jsonrpc': '2.0', 'id': 0, 'result': '0x6'}
peerCount: 6
--eth_coinbase---
0xxxxxxxxxx
--eth_blocknumber---
{'jsonrpc': '2.0', 'id': 0, 'result': '0x3f56df'}
eth_blockNumber: 4151007
これでEthereumのライブネット環境へpythonからアクセスできる。