Develop with pleasure!

福岡でCloudとかBlockchainとか。

Ethereum環境のセットアップとPrivate Chainの作成

Bitcoinのブロックチェーンは取引記録を台帳に記録していくプラットフォームなのに対し、Ethereumは独自のブロックチェーンネットワークで分散アプリケーションを実行するプラットフォームを提供している。

今回は、そんなEthereumの動作環境を作ってみた。

セットアップ

Ethereumの実装は公式では今のところ↓の3つの言語で用意されている。

インストール

今回はGoの実装をUbuntu上にインストールする。 パッケージをインストールするだけなので、基本的にはethereumのPPAリポジトリ追加してapt-getでインストールするだけ。

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository -y ppa:ethereum/ethereum
$ sudo add-apt-repository -y ppa:ethereum/ethereum-dev
$ sudo apt-get update
$ sudo apt-get install ethereum

コマンド

インストールされると↓のコマンドが利用可能になる。

  • geth
    EthereumのCLI
  • bootnode
    Ethereum Discovery Protocol用のbootstrapノードを起動する
  • ethtest
    JSONファイルに記述されたテストを実行する。
  • evm
    EVM(Ethereum Virtual Machine)*1のコードを実行する。
  • disasm
    EVMのバイトコードをpretty printしてくれる。
  • rlpdump
    RLP(Recursive Length Prefix)*2なデータをpretty printしてくれる。

アカウントの作成

Ethereumのアカウントには2種類ある。

  • Externally Owned Accounts (EOAs)
    一般的に認識されているアカウントで外部からユーザが作成してコントロールするタイプのもの。
    ehterの残高を持ち、トランザクションを送信でき、秘密鍵によって制御されコードとの関連は無い。
  • Contract Accounts
    Ethereumにはcontractと呼ばれるコード(機能)とデータ(状態)の集合が、ブロックチェーン上の特定のアドレスに存在しており、このcontractと関連付けられるアカウント。
    etherの残高を持ち、コードとの関連があり、他のcontractsからのトランザクションもしくはメッセージの受信をトリガーにコードを実行する。

console上では↓でアカウントが作れる。

> personal.newAccount("パスワード")
"0x4d3477c4b74c1d30f803984d363b4603c230a309"

※ consoleで使えるコマンドの一覧は↓で確認できる。

JavaScript Console · ethereum/go-ethereum Wiki · GitHub

Test Network

BitcoinのtestnetのようにEthereumにもMordenと呼ばれるテスト用のネットワークがある。
また、Morden testnetのetherを取得には↓の2通りの方法がある。

testneは--testnetオプションを付加すれば起動できる。

$ geth --testnet

ローカルにprivate testnetをセットアップする

Morden testnetでも↑のようにetherを入手する必要があるが、private testnetを利用すれば事前にetherを生成するか自前でマイニングが簡単に行える。(Bitcoinでいうregtestモードみたいなもの)

private chainを作成するにあたって必要なのが↓

Custom Genesis File

Bitcoinと同様にgenesisブロックがブロックチェーンの開始となる。このgenesisブロックを↓のようにJSON形式でファイルに定義して、

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

gethコマンドでノードをスタートする際に、--genesisオプションでこのファイルを指定する。

同じgenesisブロックを持ってない限り、他のノードとブロックチェーンのバージョンが異なるため、他のブロックチェーンからはこのノードに接続できないので、すきなだけprivate testnetが作れるみたい。

Custom Data Directory

private chainのデータを保存する場所を--datadirオプションで指定する。

Custom NetworkID

--networkidオプションでネットワークIDを指定。(通常のtestnetは2)

Disable Node Discovery

自分のノードを他のノードから見つけれれないよう--nodiscoverオプションを付加する。(このオプションを付けても手動で追加することはできる) ※ Custom Genesis Fileを使っても万が一同じ内容だった場合、network idも一緒なら繋がってしまうため。

↑を意識してgethコマンドでノードを起動すればprivate chainが起動できる。

$ geth --identity "MyNodeName" --genesis /path/to/CustomGenesis.json --rpc --rpcport "8080" --rpccorsdomain "*" --datadir "C:\chains\TestChain1" --port "30303" --nodiscover --rpcapi "db,eth,net,web3" --networkid 1999 console

※ ↑実行すると以下のような警告が表示される。特に起動に問題は無いが将来的にinitに置き換わって使われなくなるっぽい。

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

↑のCustom Genesis Fileにdifficultyが“0x400”と指定されているが、これはすぐにetherのマイニングが可能なレベルの値になっている。もしくはマイニングするより前にetherを入手したい場合は以下の手順でできる。

  1. private chainを起動した後にアカウントを作成する
  2. 作成したアカウントのアドレスをコピーする
  3. Custom Genesis Fileの"alloc"の項目を以下のように追記する
"alloc":
{
        "2でコピーしたアドレスを記述":
        { "balance": "20000000000000000000" }
}

ノードを再起動しetherの残高を確認すると

> eth.getBalance(eth.accounts[0])
20000000000000000000

etherが増えてるのが分かる。

*1:JavaScriptPythonをモデルに作られた言語で書かれた任意のアルゴリズムを実行する仮想マシン

*2:Ethereum内でオブジェクトをシリアライズする際に使用されているエーンコーディング方式