Ethereum(イーサリアム)もBitcoin(ビットコイン)と同様にブロックチェーンを使った暗号通貨ですがちょっと毛色が違います。
Bitcoinが取引決済用のシステムなのに対して、Ethereumは決済機能も持っていますがむしろアプリケーションを実行するプラットフォーム(実行環境)という趣です。
仮想通貨名はEther(イーサ)、単位はETHですが、この通貨の使われ方が独特というか複雑というか。
アプリケーション
EVMがコントラクトコードをEVMバイトコードに変換することでトランザクションを実行(JavaをVMで実行するようなイメージ?)
EVM(Ethereum Virtual Machine):イーサリアムネットワーク上で動作する仮想マシン
コントラクトコード:solidityやLLLというプログラミング言語で記述
今回は、Bitcoin Walletでやったような「送金」をやってみます。
Ethereumクライアントをインストールし起動することでP2Pネットワークに参加することが可能になります。
フルノードで参加したらどうなるの?
*etherの採掘
*etherの送金
*スマート・コントラクトの生成
*トランザクションの生成
*ブロックチェーンの確認
といった動作が可能になります。
クライアント・アプリケーションをインストール
ubuntu 16.04 LTS + VirtualBox(5.2.4) + Windows 7 (64bit)
色々な言語による実装
Go(go-ethereum)、Rust(Parity)、C++(cpp-ethereum)、Python(pyethapp)、Javascript(ethereumjs-lib)、Java(Ethereum(J))、Ruby(ruby-ethereum)、Haskell(ethereumH is not released yet)
Go言語での実装を使ってみます。
Go(go-ethereum)->Gethという名称です。
●ソースからビルドしてインストール
ソースからビルドしてインストールしてみます。
Geth(コマンドラインクライアント)をビルド
Githubからクローン
$ git clone https://github.com/ethereum/go-ethereum
2018/01/15時点のVersion 1.8.0
Go(v1.7.6)言語インストール(gcコンパイラのバイナリ配布版のインストール)
Go言語ツールのダウンロード(このサイトのArchived versionsからv1.7.6のLinux x86-64を選ぶ)
Go言語ツールのインストール
古いバージョンからアップグレードするときは、まず/usr/local/goに在る以前のバージョンを削除($ sudo rm -r /usr/local/go)
/usr/localに解凍
$ sudo tar -C /usr/local -xzf go1.7.6.linux-amd64.tar.gz
環境変数PATH に追加
$export PATH=$PATH:/usr/local/go/bin
インストールの確認
$ go version
gethのビルド
$ sudo apt-get install -y build-essential golang
$ cd go-ethereum
$ make geth
一時的にパスを通しておく場合
$export PATH=”$PATH:/home/<ユーザー名>/go-ethereum/build/bin”
恒久的には
上記のPATHを~/.profileに追加して、
$source ~/.profile
確認
$ geth version
Ethereumが稼働する2つのP2Pネットワーク
●本番ネット(ライブ・ネットワーク)
●プライベート・ネット
プライベート・ネットは自分を含めた限定されたネットワークなので、Etherの採掘が容易で、安全性も高いテスト用ネットワーク。
いろいろな動作を確認するために、インストールしたGethを起動し、プライベート・ネットに接続します。
しばらくは実験・確認用にプライベート・ネットを使用しますが、最後は独自トークン用にライブ・ネットに接続することになります。
データを入れるためのディレクトリを任意の場所名前で作成し、ターミナル上でそのディレクトリ内に移動しておきます。
$mkdir ~/my_eth_chain
$cd ~/my_eth_chain
Genesisファイルを作成します(以下をコピペする場合はダブルクォーテーションがシングルバイトになっているかペースト後ご確認ください)。
【Genesis.json】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "config": { "chainId": 10, "homesteadBlock": 0, "eip155Block": 0, "eip158Block": 0 }, "alloc" : {}, "coinbase" : "0x0000000000000000000000000000000000000000", "difficulty" : "0x20000", "extraData" : "", "gasLimit" : "0x2fefd8", "nonce" : "0x0000000000000042", "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp" : "0x00" } |
Genesisファイルをもとにブロックチェーンの初期化(ジェネシスブロックの作成)をします。
ジェネシス・ブロックとは、一番初めのブロックのことです。
$ geth init ./Genesis.json
.ethereumという隠しフォルダーが生成されます。
Gethを起動します。
gethの起動には必ずオプションを付けてください。単体コマンドだと他のネットのブロック同期のために大量にimportが起きて、HDDが消費されます。
1 |
$ <strong>geth --datadir "/home/<ユーザー名>/my_eth_chain" --networkid 10 --nodiscover --maxpeers 0 console</strong> |
他の同じネットワークIDから見えないように–nodiscoverオプションを付けます。
Gethのコンソールが開きます。
このコンソールはJavaScriptのREPL(Read Eval Print Loop)で、Web3.js API を通じて Geth ノードとインタラクティブにやり取りすることができます。
コンソールは複数立ち上げることもできます。
●Gethの起動時にオプション(–rpc)を追加しておく。
これで8545ポートを使ってGethにattachできます。
$geth attach rpc:http://localhost:8545 console
●ipcを使う
1 |
$geth attach ipc:/home/<ユーザー名>/my_eth_chain/geth.ipc |
アカウントの作成
まだアカウントが1つもない状態なので、Gethコンソールからアカウントを1つ作成します。
新規アカウント用のパスワードを尋ねられますが、今回は自分だけが使う開発用のプライベートチェーンなので、空でも構わないのですが、簡単にa0にしておきます。
> personal.newAccount()
Passphrase:
Repeat passphrase:
…
“0xd98732f1006c3edbc7a078ac3ee6a8dd4d8c1a68”
0x から始まる文字列が今作成したアカウントのアドレスです。
このアカウントの秘密鍵は ~/my_eth_chain/keystore の中に作成されています。
送金用に、もう1つアカウントを作っておきます(passphraseはa1)。
> personal.newAccount()
…
“0x8c0dc53ba68cf2747be23c7aa270b3e3f90092db”
次のコマンドは、作成済みのアカウントのアドレスを配列で表示します。
> eth.accounts
[“0xd98732f1006c3edbc7a078ac3ee6a8dd4d8c1a68”, “0x8c0dc53ba68cf2747be23c7aa270b3e3f90092db”]
このとき、1番目のアドレス (eth.accounts[0]) は、Coinbase (Etherbase) と呼ばれる特別なアカウントです。
eth.coinbase でも Coinbase アドレスは確認できます。
> eth.coinbase
“0xd98732f1006c3edbc7a078ac3ee6a8dd4d8c1a68”
ブロックをマイニングしたときの報酬 (Ether) は、
その Geth ノードの Coinbase アカウントが受け取ります。
アカウントはここに記録されます。
Ether の取得(採掘、マイニング)
eth.getBalance() で Coinbase アカウントの現在の残高 (Balance) を確認してみると、
まだ 0 であることが確認できると思います。
> eth.getBalance(eth.accounts[0])
0
では Ether を受け取るために、マイニングを開始してみましょう。
start関数に引数(スレッド数)を入れる場合もありますが今回は無し(CPUをフルで使います)。
> miner.start()
null
nullが表示されますが、これは仕様です。
マイニングの準備として
DAG(ブロックチェーンのハッシュ計算のために使用されるデータファイル)が作成されますが、epochのpercentageが100になるまで少々時間がかかります。
DAGはここに保存されています。
DAGが作成されたら、マイニングが開始されます。
適当なところで止めて、どうなっているのか確認。
コンソールではマイニング中はプロンプトが表示されていませんが、キー入力などあるとプロンプトは表示されます。
>miner.stop()
true
> eth.getBalance(eth.accounts[0])
大きな桁の数字が出ましたが、この数字の単位は ether ではなく wei になります。
wei は Etherum における最小の単位で、1 ether = 10の18乗 wei。
コンソールの停止。
>exit
獲得したEther通貨で送金してみます。
マイニングしたEtherの受け取り先を変更したい場合
マイニングされたEtherは何の設定変更もなければ最初に作られたアカウントに振り込まれます。
マイニングの振り込みアカウントを2番目に変更する(Coinbaseを変更する)場合は
>miner.setEtherbase(eth.accounts[1])
Coinbaseが変更されたか確認する場合
>eth.coinbase
Ether の送金
次に送金のテストとして、先程作った2つ目のアカウントに対して、
1つ目のアカウント (Coinbase) から 1ether (= 10の18乗wei) を送ってみましょう。
先にexitしたので、再度Gethを起動します。
再起動したら、先に生成されたブロックチェーンを読むので、同期のために少々起動に時間がかかります、
現在の残高を確認、 0 です。
> eth.getBalance(eth.accounts[1])
0
eth.sendTransaction({ from: 送金元アドレス, to: 送金先アドレス, value: 送金額 (wei) }) が送金メソッドですが、
これを実行するためには、先立って送金元アカウントのアンロックが必要です。
> personal.unlockAccount(eth.accounts[0])
Passphrase:
true
では送金を実行します。
> eth.sendTransaction({ from: eth.accounts[0], to: eth.accounts[1], value: 1000000000000000000 })
トランザクションの ID が表示されますが、この段階ではまだ送金は完了していません。
採掘して、このトランザクションがブロックチェーンに書き込まれる必要があります。
このプライベートチェーンではノードは自分しかいないので、マイニングも自分でする必要があります。
マイニングを開始して、1ブロック以上採掘してください。
>miner.start()
1ブロック以上採掘されたら停止して送金を確認します。
マイニング報酬は1ブロック= 5eath
マイニングされているので、送金と同時にCoinbaseには振り込みも行われています。
>miner.stop()
eth.accounts[1] の残高が 1ether = 10の18乗wei になっていることが確認できると思います。
> eth.getBalance(eth.accounts[1])
1000000000000000000
Ethereum の核心技術であるスマートコントラクトについて
go-ethereumの再インストール
Gethを再起動すると結構時間をくいます。テスト段階なら、同期を待つより再インストールして新しい環境で始めたほうが速い場合もあります。
データディレクトリ(my_eth_chain)からGenesis.json以外を削除
go-ethereum、.ethereum、.ethashディレクトリを削除
複数のラズパイでEthereumブロックチェーンをP2Pネットワークで使ってみる
Leave a Reply