[Ethereum]private_netでトランザクションがある時だけ採掘する(Mac)


## 概要
private_netで遊んでいると、送金の度にminer.start打ってminer.stopかけるのが面倒になってくる。
ので、『トランザクションが発生したら採掘して、終わったら採掘辞める』を自動化する。

### 前準備

```
#Geth
brew tap ethereum/ethereum
brew install ethereum

mkdir eth_private
vim eth_private/genesis.json
======
{
"nonce": "0x0000000000000042",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"difficulty": "0x400",
"alloc": {},
"coinbase": "0x3333333333333333333333333333333333333333",
"timestamp": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x8000000",
"config": {}
}
======

geth --datadir /Users/hoge/eth_private/ init /Users/hoge/eth_private/genesis.json
geth --networkid "10" --nodiscover --datadir "/Users/hoge/eth_private" console 2>> /Users/hoge/eth_private/geth_err.log

personal.newAccount()
miner.start()
miner.stop()
exit
```

### gethの起動

```
#--rpcapiにminerを追加して起動
geth --networkid "19" --nodiscover --datadir "/Users/hoge/eth_private/"  --rpc --rpcaddr "localhost" --rpcport "8545" --rpcapi "eth,net,web3,personal,accounts,miner" --rpccorsdomain "*" console 2>> /Users/hoge/eth_private/geth_err.log
```


### 実装

```html
<html>
<body>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://cdn.rawgit.com/ethereum/web3.js/develop/dist/web3.min.js"></script>
<script type="text/javascript">
var mining_threads = 1
const web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));

function checkWork() {
    if (web3.eth.getBlock("pending").transactions.length > 0) {
        if (web3.eth.mining) return;
        console.log("== Pending transactions! Mining...");
        jsonrpc_api('miner_start', 1);
    } else {
        if (!web3.eth.mining) return;
        console.log("== No transactions! Mining stopped.");
        jsonrpc_api('miner_stop', 0);
    }
}

web3.eth.filter("latest", function(err, block) { checkWork(); });
web3.eth.filter("pending", function(err, block) { checkWork(); });

function jsonrpc_api(method, param) {
//'{"jsonrpc":"2.0","method":"miner_stop","params":[0],"id":1}
  $.ajax({
    url     : 'http://localhost:8545/',
    type    : 'POST',
    dataType: 'json',
    timeout : 30000,
    headers : {
      'Accept'           : 'application/json',
      'Content-type'    : 'application/json'
          },
    data    : JSON.stringify({
      'jsonrpc' : "2.0",
      'method'  : method,
      'params'  : [param],
      'id'      : 1})
      
  }).done(function(data, status, jqXHR) {
    // 成功時
    console.log(data);
  }).fail(function(error, status, errorThrown) {
    // 失敗時
    console.log(error);
  });
}
</script>
</body>
</html>
```

### 実行
1.作成したhtmlを開く
![スクリーンショット 2018-03-14 18.01.44.png](https://qiita-image-store.s3.amazonaws.com/0/236641/0ab21d4d-5b2a-acc5-4d3e-da3b73c957f3.png)

2.gethのコンソールでもweb3でもjsonRPCでも何でもいいので送金を行う

```
#geth console
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(1, "ether")})
```

３. 1で開いたhtmlでトランザクションが検知され採掘開始。送金が処理されると採掘が終わる
![スクリーンショット 2018-03-14 18.06.44.png](https://qiita-image-store.s3.amazonaws.com/0/236641/a962d887-bfbf-36d5-2571-d7c1019b8e9b.png)

### 解説

private_netにトランザクションが発生した時、最後のトランザクションを処理した時にイベント発生。
checkWorkを呼ぶ。

```
web3.eth.filter("latest", function(err, block) { checkWork(); });
web3.eth.filter("pending", function(err, block) { checkWork(); });
```

checkWork
- トランザクションが有れば採掘→採掘中ならreturn
- トランザクションが無ければ採掘終了→採掘してなければreturn

```
    if (web3.eth.getBlock("pending").transactions.length > 0) {
        if (web3.eth.mining) return;
        console.log("== Pending transactions! Mining...");
        jsonrpc_api('miner_start', 1);
    } else {
        if (!web3.eth.mining) return;
        console.log("== No transactions! Mining stopped.");
        jsonrpc_api('miner_stop', 0);
    }
```

jsonrpc_api

```
miner.start()とminer.stop()を行う。
web3でやりたかったけどうまく動作しなかったため、jsonRPCで代用
```

これ単体では何の役にも立たないが、slackのリアクションをフックして送金するみたいなツール作った時に画面端で開いておくとちょっと便利