このアプリケーションはEthereumを使ったアプリ開発の流れを習得するために開発したTokenをトレードするデモアプリです。
トークンはEthereumが提唱しているトークンの標準仕様「ERC20」に準拠しています。
トレードはSwapのWhitepaperを参考に実装しました。 トレードの流れは以下の通りです。
【目標】
- EthereumのAPIを使い、WebブラウザからSmart Contractを実行する方法を理解する。
- Rubyで書かれたEthereumのライブラリが使えるようになる。
実装は最低限のものだけを行なっており、allowanceなど使っていない関数もあります。(2017/12/10現在)
Ethereumを使ったアプリ開発の技術習得を目標としているので、「これはERC20に準拠してない!」「これは〜だからSwapではない!」「オフチェーンとオンチェーンの住み分けができてない!」などなど、ご指摘を絶賛募集中です。
よろしくお願いいたします。
- Ruby 2.3.0
- Rails 5.0.6
- postgresql
- go-ethereum 1.5.5
- ethereum.rb 0.5.2
(https://github.com/EthWorks/ethereum.rb.git)
※ リポジトリのPATHは各自の環境に合わせてください※
- go-ethereumをgitリポジトリからクローンする
$ git clone https://github.com/ethereum/go-ethereum.git
$ cd go-ethereum
$ git checkout refs/tags/v1.5.5
- make gethでビルドする
$ make geth
- Gethのバージョン確認
$ ./build/bin/geth version
Geth
Version: 1.5.5-stable
Git Commit: ff07d54843ea7ed9997c420d216b4c007f9c80c3
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.8.3
OS: darwin
GOPATH=/Users/shikitakahashi/go
GOROOT=/usr/local/Cellar/go/1.8.3/libexec
- Gethを/usr/local/binにコピーする
$ sudo cp build/bin/geth /usr/local/bin/
- パスが通っていることを確認する
$ which geth
/usr/local/bin/geth
- データディレクトリを準備する
$ mkdir ~/data_testnet
$ cd data_testnet/
$ pwd
/home/eth/data_testnet
- Genesisファイルを作成する
$ vi genesis.json
{
"nonce": "0x0000000000000042",
"timestamp": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x0",
"gasLimit": "0xffffffff",
"difficulty": "0x4000",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {}
}
- Gethを初期化する
$ geth --datadir /home/eth/data_testnet init /home/eth/data_testnet/genesis.json
- Gethを起動する
今回はHTTP-RPCサーバーを有効にして起動する
geth --networkid 4649 --nodiscover --maxpeers 0 --datadir /home/eth/data_testnet
--mine --minerthreads 1 --rpc --rpcaddr "0.0.0.0" --rpcport 8545 --rpccorsdomain "*" --rpcapi "admin, db, eth,
debug, miner, net, shh, txpool, personal, web3" 2>> /home/eth/data_testnet/geth.log
- 以下のコマンドでGethのコンソールに接続して正常に起動しているか確認する
$ geth attach rpc:http://localhost:8545
Welcome to the Geth JavaScript console!
instance: Geth/v1.5.5-stable-ff07d548/darwin/go1.8.3
coinbase: 0xd34da9604e5e9c2a9cc0aa481b6b24a72af3253b
at block: 50837 (Sat, 21 Oct 2017 18:09:00 JST)
datadir: /home/eth/data_testnet
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
>
- EOAを作成し、マイニングを開始する
> personal.newAccount("pass0")
"0xd34da9604e5e9c2a9cc0aa481b6b24a72af3253b"
> eth.coinbase
"0xd34da9604e5e9c2a9cc0aa481b6b24a72af3253b"
> miner.start(1)
true
初回はDAG(Directed acyclic graph)の生成が行われるため、マイニングが行われるまでに若干時間がかかる。
マイニングが始まればハッシュレートが1以上の値となる。
> eth.hashrate
140956
- 以下のコマンドを実行してSolidityのコンパイラをインストールする。
$ brew update
$ brew upgrade
$ brew tap ethereum/ethereum
$ brew install solidity
$ brew linkapps solidity
- インストールされたことを確認する。
$ solc --version
solc, the solidity compiler commandline interface
Version: 0.4.15+commit.8b45bddb.Darwin.appleclang
- solcのPATHを確認する。
$ which solc
/usr/local/bin/solc
- admin.setSolcコマンドでGethにsolcのパスをセットする。
> admin.setSolc("/usr/bin/solc")
正しく、セットされたことを確認する。
> eth.getCompilers()
["Solidity"]
以下のコマンドを実行し、アプリケーションを起動する。
$ git clone https://github.com/shiki-tak/token-trader-app.git
$ bundle install
$ rake db:create
$ rake db:migrate
$ rails s
※ ethereumAPI.rbの"ETHEREUM_ADDRESS", "SUPPLIER_ADDRESS", "SUPPLIER_PASSWORD"を環境に合わせて変更する。
※※※アプリの使い方はAPP_PROCEDURE.mdを参照※※※
- コントラクトの実行速度が遅い
'transact_and_wait'を使ってコントラクトを実行しているが、一つのトランザクションが完了するまで、次の処理に進まないため、Tokenの発行やトレードに時間がかかる。
→ transactメソッドで実行すれば、次の処理には進む
-
EOAのアドレスをRDBに保存している
誰がコントラクトを実行したのかを識別するために、deviseで作ったユーザー情報とその情報を元にハッシュ化した情報を元にEOAを管理している。(hashedusersテーブル)
しかし、EOAの情報をRDBに保存するのは果たして正しいのか? EOAをRDBに保存せずに、コントラクトを実行できる方法はないのか? -
EOAが一度ロックされると解除できない
これは、ただのバグのような気もするが、EOAを作成して、同時にアンロックするようにしてある。
これは時間が経過するとロックされるのでコントラクト実行の直前にpersonal_unlock_accountでアカウントをアンロックするようにしているが、うまくロックが解除できない。
→ Dappsとしては致命的だが、ユーザーがノードとならないような(プラットフォーム型の)サービスであれば問題ないと考えられる。
- リファクタリング
Ethereumとは直接関係ないが、ビジネスロジックをどこにどう書き、責務をどう分けるか、要検討。