Ethereum: geth ライブネット接続～ソロマイニング（GPU）するまでの話（2017年8月11日現在）

# 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をインストールしたら、コマンドライン上から実行。
(バッチファイルを作成しておくと楽。）

```cmd:ethnode.bat
  geth.exe --datadir "D:\eth\mainnet" --fast --identity umidachi --rpc --rpcaddr "localhost" --rpcport "8545" --cache=2048 --ipcdisable　console 
```

（オプション：--datadirは後々、チェーンサイズが大きくなることを想定して、容量に余裕のあるディレクトリを指定。）

コマンド投入直後、同期がすぐに完了しない。

同期の状況を確認するため、コンソール上からコマンドを投入

```cmd:gethコンソール
 >eth.syncing

 currentBlock:××××
 highestBlock:4148728　←2017年8月11日時点
 knownStates:××××
 pulledStates:××××
 startingBlock:××××
```

currentBlockがhighestBlockに近づけば同期する。
(currentBlockを400万ブロック以上になるまで気長に待つ。）

上記コマンド投入後、"false"が出力されることがあるが
同期が始まっていない可能性があるため、時間をおいて再度実行する。

ライブネット上の現在のブロックは次のサイトから確認できる。

・https://etherscan.io/
・https://ethstats.net/

ある程度、チェーンデータのダウンロードができると
eth.blockNumberで、自分のノードが持っているブロック番号を表示できる。

```cmd:gethコンソール
 >eth.blockNumber

 4150662　　（同期が進んでいなかったりすると0が出力される）
```

同期が完了すると次の画像のように、eth.blockNumberコマンドを投入したときの
blockNumberとetherscanのblockNumberが一致していることが確認できる。

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/142016/29ba2aaf-724c-623a-806d-1c47def3c2b6.png)

通信環境にも依存すると思うが、自分の場合３日経過して同期が完了した。
eth.syncingコマンド投入すると"false"が出力

```cmd:gethコンソール
 >eth.syncing

 false
```

ノード用にETHを管理するアカウントを作る。

```cmd:gethコンソール
 >personal.newAccount()

 Passphrase:
```
パスフレーズを求められるため、パスワード入力し
アカウントを作成する。

自身のアカウントが作成されたことを確認するため
次のコマンドを入力する。

```cmd:gethコンソール
 >eth.coinbase
 "0x○○○○○○○○○○○○○"　←は自身で作成したアドレス
```

マイニングに成功した場合、"0x○○○○○○○○○○○○○"にEthが
入るはず。

##3.マイニングツールをダウンロードする。

　下記ページからethminer 0.11.0 "Optimized Nvidia mining"のwindows版をダウンロードする。
・https://github.com/ethereum-mining/ethminer/releases
　

ダウンロード完了後、ファイルを展開。
gethとは別にコマンドプロンプトを立ち上げて
ethminerを実行する。（バッチファイルを作っておくと楽）

```cmd:gtx1060の場合
  ethminer.exe -U --cuda-devices 0
```
```cmd:rx580の場合
  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のコンソール上で、マイニングが開始されているか確認をする。

```geth:gethコンソール
 >eth.mining
  true
```

マイニングのハッシュレートについてはgethのコンソール上で確認できる。

```geth:gethコンソール
  >eth.hashrate
 　41201414　 (gtx1060,rx580を同時に実行)
```


最後にgethのコンソール上で次のコマンドを投入し、ノードの残高を確認する。

```geth:gethコンソール
   eth.getBalance(eth.accounts[0])
   0
```
（執筆時点で残高が増えていることは未確認）



##4.python3でノードと通信してみる。

これまでの同期状況やマイニングの状況を確認するために
gethコンソールでコマンドを投入するのも面倒。

python3にapiを叩くスクリプトを書いておき、ethereumノードと通信させる。

json-rpc用のモジュールを入れる。

```cmd:コンソール
  pip3 install json-rpc
```

次のページにEthereumのjson-rpcの説明が載っているのでそれを参考にする。
https://github.com/ethereum/wiki/wiki/JSON-RPC


たとえば、blockNumberを出力させたいなら
次のsample.pyのようにする。

```py3: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)
```

```console:出力
  {'jsonrpc': '2.0', 'id': 0, 'result': '0x3f56d1'}
  bockNumber: 4150993
```
出力からわかるように16進数で値が返されるため、10進数になおしている。

上記と同じ要領で、これまでに確認してきたコマンドを割り当てていく。

```py3:sample_json-rpc.py
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のアドレスを指定すること。

```cmd:結果
--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からアクセスできる。