Ethereumを掘り直してみた

拝啓
NHKニュースでもビットコインやネムという言葉を耳にするようになりました
あまりにネムネム繰り返すと全てが春眠のまやかしのように思えてまいります
それもあながち間違いではございませんが
積もった雪が溶けていくように資産を溶かさないようご自愛ください
敬具

前回、まさかのnull続きが解決できず、このまま某リーダー伝たけしのように打ち切終わってしまうかと思われた、非プログラマーが雇用を賭けて挑むブロックチェーンシリーズ。
なんとか解決するべくあらゆるドキュメントを読み漁り、ようやく再開できました。


1.とりあえずなかったことにする
前回あれこれ手を尽くした結果ダメだったので、まずはGethを全て削除(安直)することにしました。
ついでにHomebrewもdoctorして、新年の清々しい気持ちのようにスッキリします。
Gethの削除はHomebrewで簡単にできたのですが、ログなどは残るので、テスト用に作ったディレクトリは手動で削除しました。

homebrew uninstall geth

2.ドキュメントを読む
心機一転(振り出しに戻っただけ)Gethをインストールする前に、現在の状況を把握すべくドキュメントを読んでみることにしました。
Googleにそっと「mac geth インストール」と問いかけます。
いつものようにあちこちに分散したウェブのデータをひとまとめにしてくれる便利なGoogleですが、
その画面を見ていた時にふと気付いたことがあるんです。

「日付・・・」

そう、今まで全国津々浦々のGethユーザー様が残してくださった書簡の中には、古いものが存在しているのです。
そういうのって、当時は正だったものが今は違うってことがあります。

こういう時は日本語ドキュメントはどうしてもタイムラグが出るもので、そうだよねGethって今も開発が進んでるんだよねと、
気合いを入れて、英語圏の大海原に向かって舵を切りました。

ちなみに今まで読んでいたのは日本語版でしたが、これからはこっちを読むことにしました。

https://github.com/ethereum/go-ethereum/wiki

早速英語で検索して読んでいくと、あちこちで同じようにminer.start()でnullが返ってくる問題が発生している様子。
それと合わせて、実はmine.start()は何もreturnしないよ?という書き込みがちらほら。
なんで何かreturnしなきゃいけないんだい?それ美味しいの?みたいな煽りっぽいのはスルーしていくと、とにかく初期設定ファイルにはconfigが必要だぜ、という指摘がありました。

どうもプライベートネットワーク起動時に必要な初期設定ファイル(myGenesis.json)の内容を変えた方がいいみたいです。
ポイントはconfigの中に、前は書いてなかったhomesteadBlockを追加することでした。

GitHubってよく聞くけど画像がなくて取っつきにくい印象があったんですが、
そんな印象に負けずに読み込んでいくと、ふむふむなるほどーと理解が深まるばかりですね。

3.Gethを改めてインストールする
さて、色々と分かった(コピペできるソースが見つかった)とこで、心機一転インストールです。

brew update
Already up-to-date.
brew doctor
Your system is ready to brew.
brew tap ehtereum/ethereum
brew install ethereum

ここまでやってバージョンチェック。

geth version
Geth
Version: 1.7.3-stable
Architecture: amd64
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.9.3
Operating System: darwin
GOPATH=
GOROOT=/usr/local/Cellar/go/1.9.3/libexec

4.myGenesis.jsonを書き換える
以前使っていたmygenesis.jsonの内容を書き換えます。
ここで何をどう書くかがポイントみたいなので、先に色々調べて設定項目をざっくり理解しました。

新しいmyGenesis.jsonがこちら。

{
    "config": {
        "chainId": 8888,
        "homesteadBlock": 0,
        "eip155Block": 0,
        "eip158Block": 0
    },
    "alloc": {
        "0x0000000000000000000000000000000000000001": {"balance": "111111111"},
        "0x0000000000000000000000000000000000000002": {"balance": "222222222"}
    },
    "coinbase"   : "0x0000000000000000000000000000000000000000",
    "difficulty" : "0x00001",
    "extraData"  : "",
    "gasLimit"   : "0x2fefd8",
    "nonce"      : "0x0000000000008888",
    "mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",
    "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
    "timestamp"  : "0x00"
}

設定項目は大体こんな感じ。

  • chainId:リプレイアタック(承認されていないユーザーが正規のユーザーとして振る舞うこと)を防ぐための設定。ここの番号と起動時のnetworkIdは同じにする。
  • homesteadBlock:HomesteadはEthereumのセカンドメジャーリリースで実装された設定で、ここを0にすることでセカンドリリースを使う設定になる
  • eip155Block:epiはEthereumの改善提案に基づくもので、設定することでその提案を実装できる(らしい)。
  • alloc:すでに積立イーサがあるアカウントを設定する。単位はWei(ドルに対するセントみたいな小さい単位)。ここを設定したからって新規アカウントは作成されない。
  • coinbase:イーサを貯めるアカウントのID(らしい)。
  • difficulty:マイニングの難しさを設定する。ここの値を低くするとマイニングが早く(成功しやすく)なる。
  • gasLimit:マイニングに成功したマイナーに対する報酬であるGASの上限を設定する。
  • 他:追って訳したいなと思っているところです。

5.初期化して採掘してみる
Gethの起動と初期化は今まで通り。
起動時にも色々とオプションが設定できるのですが、必要なものだけ指定します。
なお、ディレクトリ名が長いと打ち間違えそうなので「eth」だけにしました。

geth --networkid "8888" --nodiscover --datadir "/Users/me/eth" console 2>> /Users/me/eth/geth_err.log

Welcome to the Geth JavaScript console!

instance: Geth/v1.7.3-stable/darwin-amd64/go1.9.3
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

起動したら今の状態を確認して、テスト用にアカウントを2つ作成します。

> eth.accounts
[]
> personal.newAccount('test1')
"0xaf6d968b9f076f3f47061af7add356d52ec85fac"
> personal.newAccount('test2')
"0x03e5f8ca8bbaf6762c0340ec058bd3ebaab40e11"
> eth.accounts
["0xaf6d968b9f076f3f47061af7add356d52ec85fac", "0x03e5f8ca8bbaf6762c0340ec058bd3ebaab40e11"]
> eth.coinbase
"0xaf6d968b9f076f3f47061af7add356d52ec85fac"

ここまで来たら、えいやっとマイニング開始!

> miner.start()
null

紅白歌合戦の誰も驚かないサプライズ並みにまた出てくる、nullとの再会。
しかしここで怯むわけにはいかないというか、予想の範疇というか想定の範囲内というか、何も返さないということは読みました。
落ち着いて、残高を確認します。

> eth.blocknumber
undefined
> eth.getBalance(eth.accounts[1])
0

うん、ゼロですよね知ってた。
でもね、もう知ってるんです。
もうちょっと待ってたら何とかなるはずなので、コーヒー飲んでから確認します。

> eth.mining
true

待ちかねたtrueが!
よし、それではマイニングの結果を見るgetBalanceで確認です。

> eth.getBalance(eth.accounts[0])
2.625e+21

0じゃない!

> eth.getBalance(eth.accounts[0])
3.01e+21

増えてる!

> eth.getBalance(eth.accounts[0])
3.775e+21
> eth.getBalance(eth.accounts[0])
8.35e+21

やっぱり増えてる!

6.ログを確認してみる
色々読み漁る中で「Gethのログはtailコマンドで見れる」というのを知りました。
tailと言われても牛テールのスープくらいしか思い付かないのですが、とりあえず打ってみます。

tail -100f /Users/me/eth/geth_err.log
INFO [02-02|19:30:55] 🔨 mined potential block  number=455 hash=0eb578…32a529
INFO [02-02|19:30:55] Mining too far in the future  wait=2s
INFO [02-02|19:30:57] Commit new mining work  number=456 txs=0 uncles=0 elapsed=2.000s
INFO [02-02|19:30:58] Successfully sealed new block  number=456 hash=3204d0…2c3ba5
INFO [02-02|19:30:58] 🔗 block reached canonical chain          number=451 hash=05b9c3…a8a56c
INFO [02-02|19:30:58] 🔨 mined potential block  number=456 hash=3204d0…2c3ba5
INFO [02-02|19:30:58] Commit new mining work  number=457 txs=0 uncles=0 elapsed=130.91µs
INFO [02-02|19:30:59] Successfully sealed new block  number=457 hash=282df5…65843f
INFO [02-02|19:30:59] 🔗 block reached canonical chain  number=452 hash=3c69be…41bf5f

おお・・・
なんだか分かりにくいけど、ポテンシャルブロックというのをマイニングして、コミットして、シールして、ブロックにチェーンが追加されている様子。
絵文字付きで分かりやすいですね。
ここでコンソール側で一旦ストップして、確認します。

> miner.stop()
true
> eth.getBalance(eth.accounts[0])
1.0895e+22
INFO [02-02|20:05:23] 🔨 mined potential block  number=2179 hash=8c4c78…07cf09
INFO [02-02|20:05:23] Commit new mining work  number=2180 txs=0 uncles=0 elapsed=140.836µs
INFO [02-02|20:12:00] IPC endpoint closed: /Users/me/eth/geth.ipc 
INFO [02-02|20:12:00] Blockchain manager stopped 
INFO [02-02|20:12:00] Stopping Ethereum protocol 
INFO [02-02|20:12:00] Ethereum protocol stopped 
INFO [02-02|20:12:00] Transaction pool stopped 
INFO [02-02|20:12:00] Database closed  database=/Users/me/eth/geth/chaindata

eとか+とか意味が分かりませんが、増えてることは理解しました。
これは採掘成功!!です!!
ふー、これでなんとか首の皮が繋がったので、次は送金処理を目標に頑張ってみたいと思います。