ビットコインを支えるブロックチェーン・テクノロジーを触ってみた

拝啓
今年も師走に入り、EthereumというワードまでYahooニュースに登場するようになりました
皆様におかれましてはさぞご興味を抱かれている方もお多いかと存じますが
くれぐれもディスクに潤沢な空き容量を確保されるようご自愛くださいませ
敬具

前回のブログでEthereumについて2行だけ触れたところ、こんな手紙が届きそうな雰囲気になっています。
今日になってEthereumプロジェクトの内部通貨イーサリアム(ETH)が600ドルを付けた、というニュースが出てきました。
UBS銀行がコンプライアンスの仕組みにEthereumを使ったブロックチェーンを採用すると発表したので、それを受けての動きみたいですが、まさかこんなタイムリーに動きが出るとは、と驚きながら書いています。
ということで、非プログラマーが踏み込むブロックチェーンシリーズ2回目は、Ethereumのネットワークに繋ぐまでの奮闘記です。

1. Ehtereumのクライアント「Geth」をインストールしてみる
Ethereumを利用するはじめの一歩は、Gethというフル・クライアントのインストールから始まります。
そのままカナ読みすると何かを極めた乙女を想像されるかもしれませんが、これはGo言語で書かれたEthereumオフィシャルのクライアントの一つなのでご安心ください。
MacのHomebrewを利用してインストールするので、先にXcodeとHomebrewのインストール、最新版へのアップデートをしておきましょう。
※以下の操作はMacのTerminalで行います

Homebrewが動いたら、Ethereum Projectの説明に従ってGethをインストールします。

brew tap ethereum/ethereum
brew install ethereum

某CCのクライアントをダウンロードしてインストールして某XDをインストールして、という手順と比べたらあっという間ですね。

2. Gethを起動してEthereumネットワークに接続してみる
インストールが終わると「Welcome to the Geth JavaScript console!」というメッセージが表示されます。
ここで公式には「Run it」と書かれているので、素直にRunしてみました。

geth console
INFO [12-13|17:24:54] Block synchronisation started 
INFO [12-13|17:24:59] Imported new block headers count=192 elapsed=1.018s number=192 hash=723899…123390 ignored=0
INFO [12-13|17:24:59] Imported new block receipts count=2   elapsed=93.844µs bytes=8 number=2   hash=b495a1…4698c9 ignored=0
INFO [12-13|17:25:03] Imported new state entries count=490 elapsed=434.939µs processed=490 pending=3303 retry=4 duplicate=0 unexpected=0
INFO [12-13|17:25:04] Imported new block receipts count=34  elapsed=894.664µs bytes=3368 number=36  hash=5f81bf…8cbf9a ignored=0
INFO [12-13|17:25:04] Imported new state entries count=291 elapsed=5.267µs   processed=781 pending=7959 retry=0 duplicate=0 unexpected=0
INFO [12-13|17:25:06] Imported new state entries count=1140 elapsed=3.583ms   processed=1921 pending=7577 retry=4 duplicate=0 unexpected=0
INFO [12-13|17:25:08] Imported new state entries count=1130 elapsed=2.803ms   processed=3051 pending=8290 retry=14 duplicate=0 unexpected=0
INFO [12-13|17:25:10] Imported new state entries count=943  elapsed=2.024ms   processed=3994 pending=8551 retry=175 duplicate=0 unexpected=0
INFO [12-13|17:25:10] Imported new block receipts count=156  elapsed=2.174ms   bytes=21124 number=192 hash=723899…123390 ignored=0
INFO [12-13|17:25:12] Imported new state entries count=740  elapsed=1.763ms   processed=4734 pending=11253 retry=14  duplicate=0 unexpected=0
INFO [12-13|17:25:16] Imported new state entries count=1408 elapsed=3.840ms   processed=6142 pending=11274 retry=13  duplicate=0 unexpected=0
INFO [12-13|17:25:20] Imported new state entries count=2000 elapsed=7.729ms   processed=8142 pending=9829  retry=13  duplicate=0 unexpected=0
INFO [12-13|17:25:22] Imported new state entries count=1408 elapsed=4.290ms   processed=9550 pending=9540  retry=243 duplicate=0 unexpected=0
INFO [12-13|17:25:23] Imported new state entries count=1471 elapsed=5.529ms   processed=11021 pending=8557  retry=27  duplicate=0 unexpected=0
INFO [12-13|17:25:24] Imported new state entries count=770  elapsed=2.906ms   processed=11791 pending=9541  retry=72  duplicate=0 unexpected=0
INFO [12-13|17:25:24] Imported new state entries count=1248 elapsed=4.104ms   processed=13039 pending=9008  retry=72  duplicate=0 unexpected=0

おおう・・・
EthereumはP2Pネットワークなので、当たり前ですが次々にトランザクション(みんなの間で交わされる取引記録)が流れ込んできます。
いやしかしこれ、止まらないし、ちょっとあの、どうしようこれ・・・。

exit

とりあえず、ネットワークから切断します。危ないとこだった。
(危なくない)
ということで、実際のEhtereumネットワークに接続するとまずはブロックチェーンの同期が始まるみたいでした。
稼働開始から現在までの取り引き(トランザクション)が全て記録されたチェーン、どれくらいなんだろうと調べてみると、どうも推定40GB以上らしく・・・。

デスクトップマシンを用意して出直してまいります。探さないでください。

というところで終わるわけにはいかないので、公式のドキュメントを読みながら開発用のプライベートネットワークへの接続を試してみます。

3. プライベートネットワークに接続してみる
最初からこっちに繋ぐべきだったプライベートネットワークへの接続は、先にGenesisと呼ばれるファイルを作るところから始まります。
先にテスト用の適当なフォルダを作って、そこに適当なエディタで作ったGenesisファイルを設置します。
下記の内容でJSONファイルを作ればOKです。

{
"nonce": "0x0000000000000042",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"difficulty": "0x400",
"alloc": {},
"coinbase": "0x3333333333333333333333333333333333333333",
"timestamp": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x8000000",
"config": {}
}

これを /User/me/ehtereum_private/ などのフォルダに保存します。
保存したらもう一度、おそるおそるGethを起動してみます。
この時にオプションを合わせて設定することで、さっきのような状態は避けられます。

--datadir /Users/me/ehtereum_private init /Users/me/ehtereum_private/myGenesis.json

トランザクションが流れ込むこともなくて一安心、続けて以下のコマンドで初期化するのですが、なんだかエラーが出たので、先に手動でエラーログを設置しました。
適当なからファイルを用意してgeth_err.log と名付けけ /User/me/ehtereum_private/ に保存します。
そして初期化コマンド!

geth --networkid "10" --nodiscover --datadir /Users/me/ehtereum_private console 2>>/Users/me/ehtereum_private/geth_err.log

Welcome to the Geth JavaScript console!

二度目のウェルカムメッセージと共に無事成功しました。
ここでさっそくmyGenesis.jsonを読めているか確認します。

eth.getBlock(0)

{
  difficulty: 1024,
  extraData: "0x",
  gasLimit: 134217728,
  gasUsed: 0,
  hash: "0x6231b02ac967dff9b0c799e956094408959de862d720d08776302ffefba0300b",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x3333333333333333333333333333333333333333",
  mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  nonce: "0x0000000000000042",
  number: 0,
  parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 507,
  stateRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  timestamp: 0,
  totalDifficulty: 1024,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}

思わず手をあげたくなるほどの初心者が諸手を挙げて喜んだ瞬間でした。
これでひとまずプライベートネットワークへの接続が確認できました。
今日はもう無理ここまでとして、連載ということであれば次はプライベートネットワークでのサムシングを目標に頑張りたいと思います。