[備忘録]gethを用いてプライベートネットワークを立ち上げetherを送金するまで

#目的
macを購入して、何もセットアップしてない状態から、ethereumのプライベートネットワークを立ち上げ、etherの送金までを最短で実行する

#動作環境
- macOS High Sierra 10.13.6
- geth 1.8.14

#Homebrewインストール 〜 geth起動まで
##Homebrewインストール
Homebrewは、macOS用のパッケージマネージャー

```
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

##gethインストール

```
$ brew tap ethereum/ethereum
$ brew install ethereum
```

正常にインストールされたか確認

```
$ geth version

Geth
Version: 1.8.14-stable
Architecture: amd64
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.10.3
Operating System: darwin
GOPATH=
GOROOT=/usr/local/Cellar/go/1.10.3/libexec
```

##Genesisブロックの作成
ローカル環境に一番最初のブロックであるGenesisブロックを作成。
以下のディレクトリ配下に格納。
`/Users/e9d26/Work/ethereum/eth_private_net`

###(1) genesis.jsonの作成

```json:genesis.json
{
  "config": {
    "chainId": 15
  },
  "nonce": "0x0000000000000042",
  "timestamp": "0x0",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "extraData": "",
  "gasLimit": "0x8000000",
  "difficulty": "0x4000",
  "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x3333333333333333333333333333333333333333",
  "alloc": {}
}
```

###(2)初期化処理

```
geth --datadir /Users/e9d26/Work/ethereum/eth_private_net init /Users/e9d26/Work/ethereum/eth_private_net/genesis.json
```
**Successfully wrote genesis state** と出力されたらOK

##geth起動

```
geth --networkid "15" --nodiscover --datadir "/Users/e9d26/Work/ethereum/eth_private_net" --rpc --rpcaddr "localhost" --rpcport "8545" --rpccorsdomain "*" --rpcapi "eth,net,web3,personal" --targetgaslimit "20000000" console 2>> "/Users/e9d26/Work/ethereum/eth_private_net/geth_err.log"
```

#アカウント作成 ~ etherの送金まで
##アカウント作成
パスワードはめんどくさいから空。

```
> personal.newAccount()
Passphrase: 
Repeat passphrase: 
...
"0x41388e612c7373e596c0ccb9459cc07e0ddd4117"
```
0x から始まる文字列が今作成したアカウントのアドレス。このアカウントの秘密鍵は /Users/e9d26/Work/ethereum/eth_private_net/keystore の中に作成されている。

##アカウント確認

```
> eth.accounts
["0x5c815601e2db82cddf1f55896d16cd8e589e48e5", "0xb7630196334ee8cbf1be0766056a46e2cc284b4a", "0x9de021494b3d109aaf9ccee7318f5f13789fa814", "0x41388e612c7373e596c0ccb9459cc07e0ddd4117"]
```

このとき、1番目のアドレス (eth.accounts[0]) は、Coinbase (Etherbase) と呼ばれる特別なアカウントです。eth.coinbase でも Coinbase アドレスは確認できます。

```
> eth.coinbase
"0x5c815601e2db82cddf1f55896d16cd8e589e48e5"
```

##coinbase変更と確認

```
> miner.setEtherbase(eth.accounts[1])
true
> eth.coinbase
"0xb7630196334ee8cbf1be0766056a46e2cc284b4a"
```

#gethコンソールでよく使うコマンド
##genesisブロックの確認

```
> eth.getBlock(0)
```

##マイニングする
引数はマイニングに使用するスレッド数

```
> miner.start(2)
null
```

**null** or **true** と表示されたらOK

##マイニング確認

```
> eth.mining
true
```
**true**であれば、マイニング中

##残高確認
eth.getBalanceで残高確認できるが、結果がwei表記のため、web.fromWei関数を使って、etherに変換して出力。

```
> web3.fromWei(eth.getBalance(eth.accounts[0], "ether"))
1500
```

##ether送金

```
> eth.sendTransaction({ from: eth.accounts[0], to: eth.accounts[2], value: web3.toWei(5,"ether")})
Error: authentication needed: password or unlock
    at web3.js:3143:20
    at web3.js:6347:15
    at web3.js:5081:36
    at <anonymous>:1:1
```

##ロック解除

```
> personal.unlockAccount(eth.accounts[0])
Unlock account 0x5c815601e2db82cddf1f55896d16cd8e589e48e5
Passphrase: 
true
```
**true**と表示されたら、解除成功。本番環境だと、セキュリティ観点からロックしておくのが望ましい。
しかし、プライベートネットで都度解除するのは面倒なので、gethオプションを使って、geth起動時にアンロックするようにする。

以下のファイルをeth_private_netディレクトリ直下に作成。

```text:password.txt
password
password
password
password
```

geth起動時に指定するアンロックオプションは以下。

```
--unlock アンロックするアカウントアドレス --password "パスワードファイルのパス"
```


##アンロックオプションを指定したgethの起動方法

```
> geth --networkid "15" --nodiscover --datadir "/Users/e9d26/Work/ethereum/eth_private_net" --rpc --rpcaddr "localhost" --rpcport "8545" --rpccorsdomain "*" --rpcapi "eth,net,web3,personal" --targetgaslimit "20000000" --unlock 0x5c815601e2db82cddf1f55896d16cd8e589e48e5,0xb7630196334ee8cbf1be0766056a46e2cc284b4a,0x9de021494b3d109aaf9ccee7318f5f13789fa814,0x41388e612c7373e596c0ccb9459cc07e0ddd4117 --password password.txt  console 2>> "/Users/e9d26/Work/ethereum/eth_private_net/geth_err.log"
```

##ether送金

```
> eth.sendTransaction({ from: eth.accounts[0], to: eth.accounts[2], value: web3.toWei(5,"ether")})
"0xf1b68fd7da899d29dfd0be534fe176771b40b9535ee208aa1e83b7db29d92cf5"
```

##トランザクション確認
引数に、トランザクションハッシュを指定。

```
> eth.getTransaction("0xf1b68fd7da899d29dfd0be534fe176771b40b9535ee208aa1e83b7db29d92cf5")
{
  blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  blockNumber: null,
  from: "0x5c815601e2db82cddf1f55896d16cd8e589e48e5",
  gas: 90000,
  gasPrice: 1,
  hash: "0xf1b68fd7da899d29dfd0be534fe176771b40b9535ee208aa1e83b7db29d92cf5",
  input: "0x",
  nonce: 4,
  r: "0x2cc7a436179a5ec76eb003ebf5794b2c2048c789c639291509e9ea514da708ed",
  s: "0x24c5c696c06e80ea75b7c4a39b1cfa046648f3ee5e41262f32ac730372ef198d",
  to: "0x9de021494b3d109aaf9ccee7318f5f13789fa814",
  transactionIndex: 0,
  v: "0xa96",
  value: 5000000000000000000
}
```

##トランザクションのレシート確認
引数に、トランザクションハッシュを指定。

```
> eth.getTransactionReceipt("0xf1b68fd7da899d29dfd0be534fe176771b40b9535ee208aa1e83b7db29d92cf5")
null
```

nullが返ってきた場合は、まだトランザクションがブロックに取り込まれていないということ。
少し時間を置いて（1分くらい）、もう一度実行すると、

```
> eth.getTransactionReceipt("0xf1b68fd7da899d29dfd0be534fe176771b40b9535ee208aa1e83b7db29d92cf5")
{
  blockHash: "0x1170cc794b12b29fab9e67fc8cde64fadf1d4b0c47384f9c623dd9f5ece3ada6",
  blockNumber: 5,
  contractAddress: null,
  cumulativeGasUsed: 21000,
  from: "0x5c815601e2db82cddf1f55896d16cd8e589e48e5",
  gasUsed: 21000,
  logs: [],
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  status: "0x1",
  to: "0x9de021494b3d109aaf9ccee7318f5f13789fa814",
  transactionHash: "0xf1b68fd7da899d29dfd0be534fe176771b40b9535ee208aa1e83b7db29d92cf5",
  transactionIndex: 0
}
```

おけ、成功

##eth.accounts[2]の残高確認

```
> web3.fromWei(eth.getBalance(eth.accounts[2]), "ether")
5
```
残高が更新されていることが確認できる。

##ブロック高を指定した残高確認

```
> web3.fromWei(eth.getBalance(eth.accounts[2], 4), "ether")
0
```

```
> web3.fromWei(eth.getBalance(eth.accounts[2], 5), "ether")
5
```

ブロック4では、まだ残高が０であることが確認できる。

#文字列変換
##16進数表記の文字列をASCII変換後の文字列で出力

```
> web3.toAscii("0x68696d69747375")
"himitsu"
```

##16進数表記の文字列をUTF8変換後の文字列で出力

```
> web3.toUtf8("0xe382a4e383bce382b5e383aae382a2e383a0")
"イーサリアム"
```

#マイニングを終了する
##マイニング終了

```
miner.stop()
true
```

#その他のコマンド
eth, personal, minerから始まるコマンドは、web3というオブジェクトに含まれるものであり、厳密にはweb3.eth, web3.personal, web3.miner から始まる。なお、web3は省略可。

#参考リンク
https://qiita.com/amachino/items/b59ec8e46863ce2ebd4a