読者です 読者をやめる 読者になる 読者になる

is Neet

ネトゲしながら暮したい

Ethereumで建国するための第一歩を踏み出した

Ethereum知ってますか?なんか名前だけは聴いたことあるけど、よくわからないという方が多いのではないでしょうか。
Bitcoinみたいな何かでしょ?という認識の方も多いかと思います。だいたい合ってるのですが、最近真面目に取り組んでみたら案外面白かったし、上手いこといけば結構世界が変わるな〜、これ使って建国したいな〜、と思ったのでザッと紹介するエントリーを残しておきます。認識が間違っている所があるかもしれないのでご指摘いただければ幸いです。

Ethereumとは?

本題ではないので若干雑な説明になります。
Ethereumを説明するには、まずBitcoinの話から入る必要があります。Bitcoinは一言でいうと仮想通貨です。特徴として挙げられるのは「非中央集権的」に通貨の健全性が担保されている点です。その「非中央集権的」に通貨の健全性を担保するという部分に使われているアーキテクチャがBlockchain(とProof of Work)になります。
これまた物凄く簡単に言うとBlockchainとは、仮想通貨の過去全ての取引履歴の事を指します。トランザクションのデータベースとか言われたりしています。Bitcoinは、P2Pネットワークに繋がっている全てのノードがこのBlockchain(過去全ての取引履歴)を持っており、新しいトランザクションの妥当性を照明し合います。理論上全ノードの計算量の51%を上回らない限り、データの改ざんは不可能という設計になっています。

ちょっと話がいったん逸れてしまうのですが、SmartContractという考え方があります。これはBitcoinが登場するよりも古くから(多分?)ある概念で、1990年代からあるようです。何かというと、例えば自動販売機でジュースを買う時に「150円を自動販売機に支払う」「欲しいジュースのボタンを押す」という2つの行動があった場合に自動販売機は、我々に「ジュースを提供」します。書類上の契約を必要としない契約(取引行動全般を指す)、これを「契約の自動化」とする考え方です。これは、コンビニ店員などを介してジュースを購入するより「非中央集権」な取引が行われていると言えます。そして、BitcoinからBlockchainというテクノロジーを抽出して、仮想通貨以外の分野に適用することでSmartContractを実現し、分散型の自動化組織を作っていけるのでは?みたいな流れが生まれます。

しかし、Blockchainでアプリケーションを作成するのは容易ではありませんでした。
Bitcoin上で動くチューリング完全ではないスクリプト(詳しくは知らない)でアプリケーションを作るわけにもいかないし、かと言って新たにアプリケーション毎に設計したBlockchainでP2Pネットワークを再構築するのも自由度は高いものの現実的ではありません。
そこでEthereumが登場します。EthereumはBitcoinのようなP2Pネットワークと、チューリング完全スクリプトを提供してくれるプラットフォームです。Ethereumの登場により、自ら新たなP2Pネットワークを構築する必要もなくなり、Ethereumが提供してくれるBlockchainの仕組みを使ってより柔軟なアプリケーションの開発が可能になりました。まぁ勿論、Ethereumネットワーク自体が発展してくれないと話にならないワケではありますが。
ちなみにEthereumには、Etherという仮想通貨が存在しています。
やや長くなりましたが、本エントリーではEthereumのテスト環境を構築し、簡単な取引を実行してみるところまでやってみます。

gethのインストール

EthereumのP2Pネットワークに参加する必要があるので、goで実装されている「geth」というCLIクライアントを使って、Ethereumネットワークにノードとして参加します。

$ bash <(curl -L https://install-geth.ethereum.org)

gethでは、Ethereum上での仮想通貨であるetherのマイニングや送金、コントラクトの作成や実行などが出来ます。

プライベートネットに接続して色々試す

いきなり本番ネットワークに繋いでもいいのですが、10GB以上のデータサイズのblockChainの同期が始まったり、いざ接続してもなかなかetherのマイニングに成功しなかったりするので、まずはプライベートネットにテスト接続して感じを掴んでみるのがオススメです。

テストデータ格納用のディレクトリを作成します。

$ mkdir $HOME/eth_private_net

Genesisファイルの作成

ブロックチェーンの最初のブロック(これをGenesisブロックというらしい)の情報を記述したjsonファイルが必要になります。
先ほど作成したディレクトリに、myGenesis.jsonというファイルを下記の内容で作ります。

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

マイニングモードにする

次に、デフォルトではGethはマイニングモードではないので、明示的にマイニングモードにしてあげる必要があるっぽいです。この辺若干ハマった上にイマイチ概念を理解しきれてない気がするので不安ですが。

$ geth --mine --minerthreads=4

--minerthreads=4その名の通りマイニング用のスレッド数なのでこのオプションはまぁ何でもいいです。初回だとここで1%, 2% ...とマイニング用の準備(かな?)が始まりますので大人しく100%になるまで待ちましょう。
consoleでminer.start(n)と打ってもいいらしいですが、私の環境ではこれだとマイニングが始まりませんでした。一度--mineオプションで立ち上げた後なら、miner.start(n)でもスタートすることが出来ました。

consoleを起動

geth consoleの起動ですが、色々とオプションがあるようです。取り敢えず、先ほど作成したデータディレクトリと、myGenesis.jsonを指定してconsoleを起動してみます。

$ geth --networkid "10" --nodiscover --datadir "$HOME/eth_private_net" --genesis "$HOME/eth_private_net/myGenesis.json" console 2>> $HOME/eth_private_net/geth_err.log

####################################################################
#                                                                  #
# --genesis is deprecated. Switch to use 'geth init /path/to/file' #
#                                                                  #
####################################################################

Welcome to the Geth JavaScript console!

instance: Geth/v1.4.9-stable-b7e3dfc5/darwin/go1.6.2
coinbase: 0x88xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
at block: 680 (Thu, 07 Jul 2016 09:18:37 JST)
 datadir: /Users/xxxx/eth_private_net
 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

>

これでめでたくプライベートネットと、REPL consoleが立ち上がりました。

プライベートネットでetherをマイニング、送金してみる

何はともあれアカウントを作成しましょう。後に送金までの手順を確認したいので2つのテストアカウントを作成します。以降の作業は全てgeth console上でのコマンドになります。
newAccount()メソッドを呼び出して、第一引数にパスワードを渡します。

> personal.newAccount("hoge")
"0x88e9f8cf1e6a996f849b681696a8c960410be669"

> personal.newAccount("fuga")
"0x0b79b067f4b4c02a922dc8972375fb35e3795fbb"

eth.accountsで作成したアカウント一覧がみれます。

> eth.accounts
["0x88e9f8cf1e6a996f849b681696a8c960410be669", "0x0b79b067f4b4c02a922dc8972375fb35e3795fbb"]

eth.coinbaseでマイニングの報酬を紐付けるアカウントを確認することができます。一番最初に作ったアカウントがデフォルトでは設定されているはずです。

> eth.coinbase
"0x88e9f8cf1e6a996f849b681696a8c960410be669"

マイニングしてみる

miner.start()でマイニングを開始し、miner.stop()で止めることができます。また、miner.start()には第一引数にマイニングを実行するスレッド数を渡すことができます。

> miner.start()
true

マイニングを開始したら、eth.hashrateで採掘処理のハッシュ・レートを確認することができます。0以外の数値が返ってきた場合は、マイニングが行われていますが、0が返った場合はマイニングが行われていません。 なお、以前はminer.hashrateだったようですが、1.4.3から(かな?)はレシーバがethに変更になったようです。

> eth.hashrate
965

適当なタイミングでminer.stop()を実行しマイニングを止めて、掘り起こしたetherを確認してみましょう。

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

上記の確認方法でもいいですが、存在するアカウント一覧とether残高を一緒に確認したいので(後の送金確認時とかにも便利)、スクリプトを書いておくといいかもしれません。適当なディレクトリに適当な名前で以下内容でjsファイルを作成します。

function checkAllBalances() {
  var i =0;
  eth.accounts.forEach( function(e){
    console.log("  eth.accounts["+i+"]: " +  e + " \tbalance: " + web3.fromWei(eth.getBalance(e), "ether") + " ether");
  i++;
  })
};

続いて、geth consoleに戻り、作成したjsファイルをロードして、functionを実行してみます。

> loadScript("./ethereum/hoge.js")
true

> checkAllBalances()
  eth.accounts[0]: 0x88e9f8cf1e6a996f849b681696a8c960410be669   balance: 3715.78125 ether
  eth.accounts[1]: 0x0b79b067f4b4c02a922dc8972375fb35e3795fbb   balance: 0 ether
undefined

送金してみる

送る側と、受け取る側のアカウントを分かりやすくするために変数に入れておきます。これは必須の手順ではないです。

> var sender = eth.accounts[0];
undefined
> var receiver = eth.accounts[1];
undefined

次に、送金する側(sender)のlockを解除しておく必要があります。パスワードの入力を求められるので、入力します。

 personal.unlockAccount(sender)
Unlock account 0x88e9f8cf1e6a996f849b681696a8c960410be669
Passphrase:
true

なお、unlockAccountの第二引数に文字列でパスワードを渡してあげても良いようです。
次にeth.sendTransactionを使って、試しに5 etherほど送金して、checkAllBalances()で確認してみます。 この時、マイニングが行われている必要があるらしいので、miner.start()を最初に呼び出します。(ずっとマイニングしてるのであればこの処理は必要ではありません)

> miner.start()
true

> eth.sendTransaction({from: sender, to: receiver, value: web3.toWei(5, "ether")})
"0xf997c2aee483bc74fa3bcb134af8ab99525d37b8cbe0afe73d620627e243db3d"

> checkAllBalances()
  eth.accounts[0]: 0x88e9f8cf1e6a996f849b681696a8c960410be669   balance: 3755.78125 ether
  eth.accounts[1]: 0x0b79b067f4b4c02a922dc8972375fb35e3795fbb   balance: 5 ether

Contractについて

さて、Ethereumでは上記で行った送金と同じ要領で、任意のタイミングでTransactionを発生させ、同時にコントラクト・コードを走らせる事ができます。流れとしては、Contractを作成し、ブロックチェーンに作成したContractを登録し、Contractへアクセスし実行、というイメージになります。Solidityという言語で開発することになります。

長くなってきたので一端この辺で切りますが、次回は実際にContractを作成して実行してみる部分を書いたりしたいと思います。embarkというフレームワークを使ってサンプルアプリケーションを開発する流れまで出来れば最高ですが「建国する気持ち」が持つかどうかが不安です。

参考URL

この辺読みながらやりました。ありがとうございます。 Ethereum入門 ethereum/go-ethereum wiki スマートコントラクトとDAO