この記事ではMac OS Sierra 10.12.4を使っています
Ethereumは、シンプルなコードで書かれた「コントラクト」を実行することで、様々なネットワークを生み出すことのできるブロックチェーンです。
コントラクトとしては「通貨を発行する」、「税金を払う」、「クラウドセールを実施する」など様々な種類のものを発行することができ、その手軽さと汎用性の高さからAugur,DAO,OmiseGOなどEthereum上でトークンを発行されたプロジェクトは多々あります。
何回かに分けてEthereumで仮想通貨を発行する、というところまでチュートリアルでやってみます。今回はgethの環境構築までを実施します。
gethのインストール
ethereumのクライアントとして今回はgethをインストールします。goで書かれたEthereumのクライアントでメジャーなものになります。
Mac OSではhomebrewで簡単にインストールできます。
brew tap ethereum/ethereum
brew install ethereum
あるいは、ethereumのGitHubrリポジトリよりgit cloneしてビルドする形になります。
(探せばいくらでもあるのでここは省略)
genesisファイルの作成
json形式でブロックチェーンの元となる、genesisブロックを作成します。
genesisブロック例
{
"nonce" : "0x0000000000000099",
"alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20000",
"extraData" : "",
"gasLimit" : "0x2fefd8",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00"
}
gethを初期化する
genesisblockができたので、genesisを元にgethによって初期化、フォルダを作成します。
geth --datadir $HOME/eth/testnet init $HOME/eth/testnet/genesis.json
実行後にtreeコマンドを打つと以下のように結果が出ます。自動的にフォルダが作成されて便利ですね。
tree
├── genesis.json
├── geth
│ └── chaindata
│ ├── 000002.log
│ ├── CURRENT
│ ├── LOCK
│ ├── LOG
│ └── MANIFEST-000003
└── keystore
##RPCオプションを設定してgethを起動する
rpcオプションを追加してgethを起動します。
rpcオプションを設定することで、gethのコンソールからだけでなく、HTTP経由でリクエストの受け口を設定することができます。(rpcはremote procedure callの略)
これを設定しないと、後から仮想通貨コントラクトを実行するためのbrowser-solidityからローカルネットワークへの接続ができなくなってしまいます。
geth --networkid 2222 --nodiscover --maxpeers 0 --datadir $HOME/eth/testnet/ --rpc -rpccorsdomain "*" --rpcaddr "0.0.0.0" console
オプションの説明
- --rpc HTTP-RPC を有効にする
- --rpccorsdomain RPC接続する接続元のIPアドレス、ポート番号を設定します。「*」を設定すると全ての接続元からアクセスを許可します。
- --rpcaddr RPC接続の受け口のIPアドレスを設定します。デフォルトはlocalhostで、「0.0.0.0」を設定すると、全てのアクセスを受け付けます。(よしなに割り振ってくれます)
- --networkid ネットワーク識別子。0~3までは予約済だが、それ以外の数値を設定します
- --nodiscover 他のノードから検出できないようにするオプション
- --maxpeers 自分のノードに接続できるノード数。テストなので0を設定します
- console gethを実行してコンソールを起動する
他のオプションの詳細はEthereumのgithubに載っています。
Ethereumのgithub
https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options
ローカルネットワークなので、「*」など雑に指定しておりますが、本当はIPアドレスなどをきちんと設定した方が良いです。
##アドレスを作成する
consoleが起動したら新しいアドレスを作成します。
personal.newAccountの引数はパスワードです。
"first","second"というパスで2つアドレスを作成します。
personal.newAccount("first")
0x4351987e308450b8e6d2c46031add1f4e4a4f330
personal.newAccount("second")
0xa7dc9556fdd013545ba496dd981422eaa53a0a62
eth.accountsでアドレスができている事を確認します。
eth.accounts
["0x4351987e308450b8e6d2c46031add1f4e4a4f330", "0xa7dc9556fdd013545ba496dd981422eaa53a0a62"]
確認後、後ほど実施するマイニングのために、
マイニング報酬受け取り用アドレスを設定します。
miner.setEtherbase(eth.accounts[0]) #マイニング報酬受け取り用アドレスを設定
eth.coinbase #マイニング報酬受け取り用アドレスの確認
"0x4351987e308450b8e6d2c46031add1f4e4a4f330"
ローカルのテストネットワークでマイニングを実施する
最初に作ったアドレスの残高と、このネットワークのブロックが0であることを確認します。
> eth.getBalance(eth.accounts[0]) #アドレス残高0
0
> eth.blockNumber #ブロック高0
0
マイニングを開始します。
引数1はマイニングのためのスレッドの数です。成功するとtrueが帰ってきて、ログが流れます。
> miner.start(1)
true
> I0908 01:27:02.630945 eth/backend.go:475] Automatic pregeneration of ethash DAG ON (ethash dir: /Users/nao/.ethash)
I0908 01:27:02.630946 miner/miner.go:136] Starting mining operation (CPU=1 TOT=2)
I0908 01:27:02.631403 eth/backend.go:482] checking DAG (ethash dir: /Users/nao/.ethash)
I0908 01:27:02.642987 miner/worker.go:516] commit new work on block 1 with 0 txs & 0 uncles. Took 11.628222ms
I0908 01:27:02.644081 vendor/github.com/ethereum/ethash/ethash.go:259] Generating DAG for epoch 0 (size 1073739904) (0000000000000000000000000000000000000000000000000000000000000000)
I0908 01:27:03.696831 vendor/github.com/ethereum/ethash/ethash.go:291] Generating DAG: 0%
....
0909 10:01:52.497921 miner/worker.go:516] commit new work on block 942 with 0 txs & 0 uncles. Took 229.749µs
I0909 10:01:53.426768 miner/unconfirmed.go:105] 🔗 mined block #937 [3911fcec…] reached canonical chain
I0909 10:01:53.426836 miner/unconfirmed.go:83] 🔨 mined potential block #942 [aac320ba…], waiting for 5 blocks to confirm
報酬を確認します。
eth.getBalance(eth.accounts[0]) #weiで表示
4.955e+21
web3.fromWei(eth.getBalance(eth.accounts[0]),"ether") #etherで表示
4955
先ほどは0でしたが、4955ether溜まっていましたね。
マイニング報酬のetherが溜まったようです。
マイニングはこのまま続けておきます。
browser-solidityからローカルのネットワークに接続する
Ethereumでは、ブラウザ上で開発できるIDEであるbrowser-solidityが存在します。
自動的なコンパイル、GUIでコントラクト発行テストも実施できる、と便利なIDEになっております。
githubのリポジトリからbrowser-solidityを落としてきてinstallします。
開発時の安定版として提供されているのはgh-pagesブランチであるため、git clone後にブランチを切り替えます。
git clone https://github.com/ethereum/browser-solidity.git #masterを落としてくる
cd browser-solidity #落としてきたフォルダに移動
git checkout -b gh-pages origin/gh-pages # branchを切り替え
起動後、index.htmlをひらけばbrowser-solidityが開かれます。
右側のEnvironmentでWeb3 Providerを選択します。
どこに接続するか聞かれるので、localhostを選択しましょう。
ポート番号はgethのデフォルト、8545を指定します。
右側の「account」にローカルのアカウントが出てくれば成功です。
ずっとマイニングしっぱなしだったのでetherがかなり溜まっていますね。
browser-solidityで仮想通貨コントラクトを発行する
さて、ついにやっと仮想通貨を発行します。
まずはローカルネットワークのアドレスを使うためにgethからアカウントのアンロックを行います。
personal.unlockAccountの第1引数はアカウント、第2引数はパスフレーズ、第3引数はアンロックする秒数です。
第3引数のデフォルトは300(5分)で、0を設定すると無限になります。
アカウントのアンロックもセキュリティ上あまりよろしくはないので、開発時限定として気をつけてください。
personal.unlockAccount(eth.accounts[0],"first")
true
browser-solidityにEthereum公式チュートリアルから仮想通貨コントラクトコードから持ってきて貼り付けます。
EthereumはSolidityというJavaScriptライクな言語でスマートコントラクトを書いて動かします。
pragma solidity ^0.4.16;
contract MyToken {
/* This creates an array with all balances */
mapping (address => uint256) public balanceOf;
/* Initializes contract with initial supply tokens to the creator of the contract */
function MyToken(
uint256 initialSupply
) {
balanceOf[msg.sender] = initialSupply; // Give the creator all initial tokens
}
/* Send coins */
function transfer(address _to, uint256 _value) {
require(balanceOf[msg.sender] >= _value); // Check if the sender has enough
require(balanceOf[_to] + _value >= balanceOf[_to]); // Check for overflows
balanceOf[msg.sender] -= _value; // Subtract from the sender
balanceOf[_to] += _value; // Add the same to the recipient
}
}
function MyTokenがこのコントラクトのコンストラクタで、initialSupplyを設定して初期のトークンコントラクトを発行します。
二つ目にあるfunction transferが送り先アドレスと金額を設定する送金のための関数です。
今回は100000単位分のトークンを設定してContractを発行します。
browser-solidityの右下にある「Create」にinitialSupplyの引数100000を設定してクリックします。
10~20秒ほどして、マイニングが完了すると、使用したgasの代金、変数や関数のボックスが右下に現れます。
うまくいかない場合は、コンソール側でマイニングが走っているか確認してみてください。
balanceOfに実行したアドレスを設定してクリックし、実行してみます。
アドレスは"(ダブルクォート)で囲んで設定します。
MyToken100000単位ができていることが確認できますね。
あっけない感じですが、最低限のコイン発行は完了しました。
発行した仮想通貨を送金する
右下のtransfer関数に、「送り先アドレス」、「送金金額」を設定して実行します。
送り先アドレスには二つ目に作ったアドレス、送金金額には20000単位を設定します。
しばらくしてマイニングが完了すると送金結果が出てきます。
balanceOfを先ほど同様に確認すると、1つ目のアドレスから20000単位へり、2つ目のアドレスに20000単位増えていることが確認できます。
送金もできることが確認できましたね。
感想
Ethereumで、最低限の機能に限ればこれだけでも通貨は発行できます。
Dappsと組み合わせて作成を行い、流通のプラットフォームとなるプロジェクトをいかに設計し、通貨としての機能をいかに使わせるシステムにするかが肝となると考えています。
そんなわけで近々、Dappの開発に関して(勉強して)記事を書きたいと思います。