ブロックチェーンを理解したいなと思ってきたので、イーサリアムサーバを
コンテナ上に作って動かしたいと思います
下記の記事を参考にしてます
Ethereum スマートコントラクト入門:geth のインストールから Hello World まで
Ethereum入門
Ethereum Chain Spec Format
Ethereum 白書
1.Dockerコンテナを起動し接続する
centosイメージから起動してコンテナを作ります# docker run --net mynetwork --name geth --hostname geth -id -t docker.io/centos /bin/bash
# docker exec -it geth /bin/bash
2.インストール(go-ethereum)
前提となるPKGインストール
# yum install -y epel-release # yum install -y golang gmp-devel git make
gitによるgo-ethereumのインストール
起動設定
設定ファイルを作成する
# git clone https://github.com/ethereum/go-ethereum # cd go-ethereum # make geth # cp build/bin/geth /usr/local/bin
# vi /etc/systemd/system/geth.service
[Unit] Description=go-ethereum After=syslog.target network.target [Service] Type=simple ExecStart=/usr/local/bin/geth --networkid "15" --nodiscover --datadir "/root/my_eth_chain" --rpc -rpccorsdomain "*" --rpcaddr "0.0.0.0" 2>> /root/my_eth_chain/geth_err.log WorkingDirectory=/root KillMode=process Restart=always User=root Group=root [Install] WantedBy=multi-user.target
# systemctl enable geth
# systemctl start geth
3.gethを起動して、プライベートブロックチェーンに接続する
myGenesis.json でマイニングの難易度を下げて簡単にマイニングできるよう設定ファイルを作成する
# mkdir ~/my_eth_chain
# cd ~/my_eth_chain
# vi myGenesis.json
{ "config": { "chainId" : 15 }, "nonce" : "0x0000000000000042", "timestamp" : "0x0", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "extraData" : "", "gasLimit" : "0x8000000", "difficulty": "0x4000", "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "coinbase" : "0x3333333333333333333333333333333333333333", "alloc": {} }
# chainId => チェーンID。replay protection対象のネットワーク
# nonce => ナンス値
# timestamp => タイムスタンプ
# parentHash => 親ブロックのハッシュ値
# gasLimit => ブロックに入るトランザクションの量は、block gas limitにより制限される Bitcoinにおけるブロックサイズに近い
Ethereumではトランザクションを送ったり、プログラムを実行するのにGasが必要(手数料のようなもの)
# difficulty => マイニングの難易度(ナンス値の見つける難しさ)
# mixhash => ナンス値と合わせて利用する。ブロックの計算量を調整する
# coinbase => 採掘報酬(コインベース)
# alloc => 事前にEtherが割り当てられたアカウントのリスト
Ethereumのブロックチェーンのブロックの初期化を行います
4.アカウント(EOA)を作成する
アカウントを作成
5.マイニング(発掘)する
マイニング(発掘)してみます
# geth --datadir /root/my_eth_chain init /root/my_eth_chain/myGenesis.jsonGethを起動します。RPC-JSONでHTTPリクエストを受けられるようにします
# コンソールに直接入る場合
# geth --networkid "15" --nodiscover --datadir "/root/my_eth_chain" --rpc -rpccorsdomain "*" --rpcaddr "0.0.0.0" console 2>> /root/my_eth_chain/geth_err.log
# バックグラウンドで実行し、その後コンソールに接続する場合
# geth --networkid "15" --nodiscover --datadir "/root/my_eth_chain" --rpc -rpccorsdomain "*" --rpcaddr "0.0.0.0" 2>> /root/my_eth_chain/geth_err.log &
# geth --datadir "/root/my_eth_chain" --ipcpath /root/my_eth_chain/geth.ipc attach
4.アカウント(EOA)を作成する
アカウントを作成
> eth.accounts [ ]
# hogehoge01はパスワード
> personal.newAccount("hogehoge01") '0xb718613624e9eb3639a3f53b474dccc62def8b59'
> personal.newAccount("hogehoge02") '0x44afab018ff28d2010d3a858bbc9efc483d80172'
> eth.accounts ["0xb718613624e9eb3639a3f53b474dccc62def8b59", "0x44afab018ff28d2010d3a858bbc9efc483d80172"]
5.マイニング(発掘)する
マイニング(発掘)してみます
# マイニングのアカウントのセット
> miner.setEtherbase(eth.accounts[1]) true
# 報酬対象アカウントの確認
> eth.coinbase "0x44afab018ff28d2010d3a858bbc9efc483d80172"
# マイニング開始 > miner.start() null
# マイニングの停止 > miner.stop() true
# マイニングのハッシュ確認(これが0より大きいと動いている証拠) > miner.getHashrate() 3421
# 報酬状態の確認
> eth.getBalance(eth.accounts[0]) 0
> eth.getBalance(eth.accounts[1]) 125000000000000000000
# 現在のブロック数を確認 > eth.blockNumber
6.送金する
マイニング(発掘)してEther(正確にはwei)がもらえたので、送金してみます
また送金時には手数料としてgas料金を支払います
# アカウントの確認 > eth.accounts ["0xb718613624e9eb3639a3f53b474dccc62def8b59", "0x44afab018ff28d2010d3a858bbc9efc483d80172"] > eth.getBalance(eth.accounts[0]) 23999244000000001000 > eth.getBalance(eth.accounts[1]) 2.961000755999999999e+21
# この数字の単位は ether ではなく wei # wei は Etherum における最小の単位で、1 ether = 10の18乗 wei # accounts[1]のパスワードのアンロック > personal.unlockAccount(eth.accounts[1]) Unlock account 0x44afab018ff28d2010d3a858bbc9efc483d80172 Passphrase: # account[1]からaccount[0]へ 1000 wei 送信 > eth.sendTransaction({from: eth.accounts[1], to: eth.accounts[0], value: 1000}) "0xa6811340ba6f6736584ee166d2921109be697597c72819c3cf27035bf73aaaac" > eth.getBalance(eth.accounts[0]) 23999244000000001000 > eth.getBalance(eth.accounts[1]) 2.961000755999999999e+21 # マイニングを止めているので、送金が動いていない。 # マイニングを動かしてみる > eth.coinbase "0x44afab018ff28d2010d3a858bbc9efc483d80172" → account[2] がマイナー > miner.start() null > eth.getBalance(eth.accounts[0]) 23999244000000002000 # 100の増えています。 > eth.getBalance(eth.accounts[1]) 3.016000755999999998e+21 > miner.getHashrate() 7037 # account[1]がマイナーなので、マイニングの報酬をもらっているため増えています # また送金時にgas料金を支払うので少しへ減っています # account[1]からaccount[0]へ 10Ether送信 > eth.sendTransaction({from: eth.accounts[1], to: eth.accounts[0], value: web3.toWei(10, "ether")}) "0x10665396f1a399a65bb1099c715be9546a025e2cea538a59a1682b3f0afc1011" > eth.getBalance(eth.accounts[0]) 33999244000000002000 # 10*10の18乗増えています。 > eth.getBalance(eth.accounts[1]) 3.076000755999999998e+21 > miner.getHashrate() 6986
7.コントラクトを作成する
Ethereumには2つのタイプのアカウントが存在します。
EOA(Externally Owned Account)
ユーザーアカウント。アカウントを通じてEthereumネットワークとのやり取りを行うもの。
EOA はコードを持たず、EOA からトランザクションを生成し署名することによって メッセージユーザーアカウント。アカウントを通じてEthereumネットワークとのやり取りを行うもの。
を送ることができる
Contract
オブジェクト指向言語での「クラス」に似たもの。
内部状態を保持するストレージ部分と、メソッドに相当するような、実行コードである「コントラクト・コード」を持っていて下記を順番に実行する。
オブジェクト指向言語での「クラス」に似たもの。
内部状態を保持するストレージ部分と、メソッドに相当するような、実行コードである「コントラクト・コード」を持っていて下記を順番に実行する。
- メッセージを受信
- 保持コードをアクティベート
- 内部ストレージを読み書き可能にする
- メッセージを送信するもしくは新しいコントラクトを作る
コントラクトの作成
すごく簡単なコントラクトを作ってみます。
ユーザ名をSetして、Hello XXX がGetと表示されるコントラクトです
# concatを利用するためstrings.solをインポート
import "http://github.com/Arachnid/solidity-stringutils/strings.sol "; contract HelloUser { using strings for *; string storedData = "Hello Ethereum"; function set(string x) { storedData = "Hello ".toSlice().concat(x.toSlice()); } function get() constant returns (string retVal) { return storedData; } }
コンパイル(Browser-solidityを利用)
https://remix.ethereum.org/ へアクセス
(https://github.com/ethereum/browser-solidity/archive/gh-pages.zip でzip版をダウンロードしてローカル実行も可能)
1.ソースコードを貼り付けます

2.右のRunのタブをクリック

3.ピンク色のCreateをクリック

4.getしてみる(初期値のHello Ethereum が返却される)

5.set で名前をセットする(hogehoge)

6.getする(Hello hogehoge が返却される)

Detailsを押してWEB3DEPLOYをコピーしGeth Console上で貼り付ける
Contractのブロックチェーンへの登録
> personal.unlockAccount(eth.accounts[0])
> var hellouserContract = web3.eth.contract([{"constant":false,"inputs":[{"name":"x","type":"string"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]); > var hellouser = hellouserContract.new( { from: web3.eth.accounts[0], data: '0x60606040526040805190810160405280600e81526020017f48656c6c6f20457468657265756d0000000000000000000000000000000000008152506000908051906020019061004f929190610060565b50341561005b57600080fd5b610105565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100a157805160ff19168380011785556100cf565b828001600101855582156100cf579182015b828111156100ce5782518255916020019190600101906100b3565b5b5090506100dc91906100e0565b5090565b61010291905b808211156100fe5760008160009055506001016100e6565b5090565b90565b61044b806101146000396000f30060606040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680634ed3885e146100515780636d4ce63c146100ae575b600080fd5b341561005c57600080fd5b6100ac600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190505061013c565b005b34156100b957600080fd5b6100c16101ad565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101015780820151818401526020810190506100e6565b50505050905090810190601f16801561012e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61019461014882610255565b6101866040805190810160405280600681526020017f48656c6c6f200000000000000000000000000000000000000000000000000000815250610255565b61028390919063ffffffff16565b600090805190602001906101a992919061034c565b5050565b6101b56103cc565b60008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561024b5780601f106102205761010080835404028352916020019161024b565b820191906000526020600020905b81548152906001019060200180831161022e57829003601f168201915b5050505050905090565b61025d6103e0565b600060208301905060408051908101604052808451815260200182815250915050919050565b61028b6103cc565b6102936103cc565b600083600001518560000151016040518059106102ad5750595b9080825280601f01601f191660200182016040525091506020820190506102dd8186602001518760000151610301565b6102f68560000151820185602001518660000151610301565b819250505092915050565b60005b6020821015156103295782518452602084019350602083019250602082039150610304565b6001826020036101000a0390508019835116818551168181178652505050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061038d57805160ff19168380011785556103bb565b828001600101855582156103bb579182015b828111156103ba57825182559160200191906001019061039f565b5b5090506103c891906103fa565b5090565b602060405190810160405280600081525090565b604080519081016040528060008152602001600081525090565b61041c91905b80821115610418576000816000905550600101610400565b5090565b905600a165627a7a72305820baa15bd1ebd345bbf909a9a9abf44c75f86bb2047bce28ecdbe79b55214f93d90029', gas: '4700000' }, function (e, contract){ console.log(e, contract); if (typeof contract.address !== 'undefined') { console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash); } })
null [object Object] undefined
ブロックチェーン上のコントラクトの確認
マイニングしていないと動かないので、動いていない場合は miner.start() する
> hellouser.get() "Hello Ethereum"
> personal.unlockAccount(eth.accounts[0],"hogehoge01",0) true
> hellouser.set("test",{from:eth.accounts[0]}) "0x724965c2055c567248adfe3bde23c3069f833a3259f82a7909b20fdddac9c06a"
> hellouser.get() "Hello test"
Dapp開発フレームワークのTruffleを導入する
下記でフレームワーク検討し、Truffleを導入することにしましたEtherum 上で動かすDAppを開発するためのフレームワークは何が良いか?(Meteor、Truffle、Embark、Dapple)
Truffleのインストール方法は下記にあります。
http://truffleframework.com/docs/getting_started/installation
NodeJSインストール(npm 5.0以上)
# 最新版を入れるのでリポジトリ追加
# curl --silent --location https://rpm.nodesource.com/setup_9.x | bash -
# yum install nodejs
# node --version v6.12.3
# npm --version 5.6.0
Truffleインストール
# npm install -g truffle
/usr/bin/truffle -> /usr/lib/node_modules/truffle/build/cli.bundled.js /usr/lib `-- truffle@4.1.3 +-- mocha@3.5.3 | +-- browser-stdout@1.3.0 | +-- commander@2.9.0 | | `-- graceful-readlink@1.0.1 | +-- debug@2.6.8 | | `-- ms@2.0.0 | +-- diff@3.2.0 | +-- escape-string-regexp@1.0.5 | +-- glob@7.1.1 | | +-- fs.realpath@1.0.0 | | +-- inflight@1.0.6 | | | `-- wrappy@1.0.2 | | +-- inherits@2.0.3 | | +-- minimatch@3.0.4 | | | `-- brace-expansion@1.1.11 | | | +-- balanced-match@1.0.0 | | | `-- concat-map@0.0.1 | | +-- once@1.4.0 | | `-- path-is-absolute@1.0.1 | +-- growl@1.9.2 | +-- he@1.1.1 | +-- json3@3.3.2 | +-- lodash.create@3.1.1 | | +-- lodash._baseassign@3.2.0 | | | +-- lodash._basecopy@3.0.1 | | | `-- lodash.keys@3.1.2 | | | +-- lodash._getnative@3.9.1 | | | +-- lodash.isarguments@3.1.0 | | | `-- lodash.isarray@3.0.4 | | +-- lodash._basecreate@3.0.3 | | `-- lodash._isiterateecall@3.0.9 | +-- mkdirp@0.5.1 | | `-- minimist@0.0.8 | `-- supports-color@3.1.2 | `-- has-flag@1.0.0 +-- original-require@1.0.1 `-- solc@0.4.19 +-- fs-extra@0.30.0 | +-- graceful-fs@4.1.11 | +-- jsonfile@2.4.0 | +-- klaw@1.3.1 | `-- rimraf@2.6.2 +-- memorystream@0.3.1 +-- require-from-string@1.2.1 +-- semver@5.5.0 `-- yargs@4.8.1 +-- cliui@3.2.0 | +-- strip-ansi@3.0.1 | | `-- ansi-regex@2.1.1 | `-- wrap-ansi@2.1.0 +-- decamelize@1.2.0 +-- get-caller-file@1.0.2 +-- lodash.assign@4.2.0 +-- os-locale@1.4.0 | `-- lcid@1.0.0 | `-- invert-kv@1.0.0 +-- read-pkg-up@1.0.1 | +-- find-up@1.1.2 | | +-- path-exists@2.1.0 | | `-- pinkie-promise@2.0.1 | | `-- pinkie@2.0.4 | `-- read-pkg@1.1.0 | +-- load-json-file@1.1.0 | | +-- parse-json@2.2.0 | | | `-- error-ex@1.3.1 | | | `-- is-arrayish@0.2.1 | | +-- pify@2.3.0 | | `-- strip-bom@2.0.0 | | `-- is-utf8@0.2.1 | +-- normalize-package-data@2.4.0 | | +-- hosted-git-info@2.6.0 | | +-- is-builtin-module@1.0.0 | | | `-- builtin-modules@1.1.1 | | `-- validate-npm-package-license@3.0.3 | | +-- spdx-correct@3.0.0 | | | `-- spdx-license-ids@3.0.0 | | `-- spdx-expression-parse@3.0.0 | | `-- spdx-exceptions@2.1.0 | `-- path-type@1.1.0 +-- require-directory@2.1.1 +-- require-main-filename@1.0.1 +-- set-blocking@2.0.0 +-- string-width@1.0.2 | +-- code-point-at@1.1.0 | `-- is-fullwidth-code-point@1.0.0 | `-- number-is-nan@1.0.1 +-- which-module@1.0.0 +-- window-size@0.2.0 +-- y18n@3.2.1 `-- yargs-parser@2.4.1 `-- camelcase@3.0.0
コンテナを保存する
# docker commit get pug_docker/geth
# docker rm geth
# docker run -v /conteiner_share:/conteiner_share --net mynetwork --name geth --hostname geth -p 8545:8545 -id -t --privileged pug_docker/geth /sbin/init # docker exec -it geth /bin/bash
コメント