人生は勉強ブログ

黒地に白ってかっこいい。。。

スマートコントラクト本格入門を読んだ

スマートコントラクト本格入門を読んだ

スマートコントラクト本格入門―FinTechとブロックチェーンが作り出す近未来がわかる

スマートコントラクト本格入門―FinTechとブロックチェーンが作り出す近未来がわかる

1章から5章

fintechの情勢や、それにまつわる法律、各種サービスの紹介や、その会社の紹介を書いていた。

また、スマートコントラクトとは、ということの説明が書いてあった。

簡単に言えば、契約の仕組みだと感じた。

6章

ethereumを用いた実装

$ brew tap ethereum/ethereum
$ brew install ethereum

# 作業したいディレクトリに移動
$ git clone https://github.com/ethereum/go-ethereum.git
$ cd go-ethereum/

$ make geth

また、パブリックネットワークと、プライベートネットワークのためのディレクトリを作成する。

$ mkdir ${HOME}/eth_private_net
$ mkdir ${HOME}/eth_main_net

また、${HOME}/eth_private_net/genesis.json というファイルを作成する。これは、初期ファイルみたいなもの。

{
    "nonce":      "0x0000000000000042",
    "mixhash":    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "difficulty": "0x00",
    "coinbase":   "0x0000000000000000000000000000000000000000",
    "timestamp":  "0x00",
    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "gasLimit":   "0xffffffff"
}

本の通りに書いたら動かなかったので、ググった結果、このように書いた。

{
    "nonce":      "0x0000000000000042",
    "mixhash":    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "difficulty": "0x00",
    "coinbase":   "0x0000000000000000000000000000000000000000",
    "timestamp":  "0x00",
    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "gasLimit":   "0xffffffff",
    "alloc":      { },
    "config": {
        "chainId": 987654321,
        "homesteadBlock": 0,
        "eip155Block": 0,
        "eip158Block": 0
    }
}

コマンドライン上で、gethを起動する際には、

$ geth --datadir ~/eth_private_net/ --rpc --rpcaddr "localhost" --rpcport "8545" --rpccorsdomain "*" console

このように使うことが多いらしい。

上のコマンドはローカルホストへの接続を許可するためのもの

--rpcは、RPC接続を許可するためのもの

--rpcaddrは、HTTP-RPCサーバのアドレス。デフォルトでは、localhost

--rpcportは、HTTP-RPCサーバのポート

--rpccorsdomainは、クロスドメイン許可設定。カンマ区切り。*を指定することが多い。

$ geth --datadir ~/eth_private_net/ --rpc --rpcaddr "localhost" --rpcport "8545" --rpccorsdomain "*" console

このコマンドを叩くと、gethが起動するはずなのだが、

# Fatal: Error starting protocol stack: listen udp :30303: bind: address already in use

このようなエラーが出てしまう。

$ ps aux | grep geth

# myname 32704   0.0  0.0 556720592    204 s004  T    月03PM   0:03.49 geth /Users/myname/eth_private_net/ init /Users/myname/eth_private_net/genesis.json
# myname 41370   0.0  0.0  2432804    800 s000  S+   10:34AM   0:00.00 grep geth

この、PID 32704をkillしても、なぜか消えてくれない。macを再起動したら治った。

$ geth --datadir ~/eth_private_net/ --rpc --rpcaddr "localhost" --rpcport "8545" --rpccorsdomain "*" console
# WARN [08-30|11:01:25] No etherbase set and no accounts found as default
# INFO [08-30|11:01:25] Starting peer-to-peer node               instance=Geth/v1.6.7-stable-ab5646c5/darwin-amd64/go1.9
# INFO [08-30|11:01:25] Allocated cache and file handles         database=/Users/myname/eth_private_net/geth/chaindata cache=128 handles=1024
# INFO [08-30|11:01:25] Initialised chain configuration          config="{ChainID: 987654321 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: <nil> EIP155: 0 EIP158: 0 Metropolis: <nil> Engine: unknown}"
# INFO [08-30|11:01:25] Disk storage enabled for ethash caches   dir=/Users/myname/eth_private_net/geth/ethash count=3
# INFO [08-30|11:01:25] Disk storage enabled for ethash DAGs     dir=/Users/myname/.ethash                     count=2
# INFO [08-30|11:01:25] Initialising Ethereum protocol           versions="[63 62]" network=1
# INFO [08-30|11:01:25] Loaded most recent local header          number=0 hash=bb387d…5420b3 td=0
# INFO [08-30|11:01:25] Loaded most recent local full block      number=0 hash=bb387d…5420b3 td=0
# INFO [08-30|11:01:25] Loaded most recent local fast block      number=0 hash=bb387d…5420b3 td=0
# INFO [08-30|11:01:25] Starting P2P networking
# INFO [08-30|11:01:27] UDP listener up                          self=enode://e1179c7266036c933b0a82bc68c8c0aaefb9bc7d0e251609a4e549ca97b42eaec2c6514f34ea52da4901f887aa3c4bb70857e13738064f842f0cd6a482a10550@[::]:30303
# INFO [08-30|11:01:27] RLPx listener up                         self=enode://e1179c7266036c933b0a82bc68c8c0aaefb9bc7d0e251609a4e549ca97b42eaec2c6514f34ea52da4901f887aa3c4bb70857e13738064f842f0cd6a482a10550@[::]:30303
# INFO [08-30|11:01:27] IPC endpoint opened: /Users/myname/eth_private_net/geth.ipc
# INFO [08-30|11:01:27] HTTP endpoint opened: http://localhost:8545
# Welcome to the Geth JavaScript console!

# instance: Geth/v1.6.7-stable-ab5646c5/darwin-amd64/go1.9
#  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
>personal.newAccount("password")

INFO [08-30|13:05:00] New wallet appeared                      url=keystore:///Users/myname status=Locked
"0xe27eb6072f1c2ab2e16514169c32a887ba8f3bc8"

ここで使うパスフレーズは、対応するアカウントからの送金、コントラクト実行の際に必要になる。復元できないので、覚えておくこと。

> eth.accounts
["0xe27eb6072f1c2ab2e16514169c32a887ba8f3bc8"]

もう一個何かしらで必要なので、作っておく。(personal.newAccountをもう一回)

> eth.accounts
["0x16bceeeaa2aa38d8ad8c4202f089d6e7644c6053", "0xe27eb6072f1c2ab2e16514169c32a887ba8f3bc8"]
マイニング

etherbaseとは、マイニング時に報酬を受け取るアカウントのことである。

デフォルトでは、eth.account[0]がetherbaseになっている。

変更するには、

> miner.setEtherbase(eth.accounts[1])
true

とする。

では、マイニングを初めていく。

miner.start() # マイニングが始まる

eth.mining # trueなら、マイニング中

eth.hashrate # 単位時間あたりのハッシュ計算量が表示される

miner.stop() # マイニングを止める

自分の場合、start()した時から、表示が止まらず、マイニングが終了しても、次のマイニングを始めてしまった。

stopし、eth.miningの値がfalseとなっても、出力が出続けたので、Ctrl+Zで抜けざるを得なかった。

> web3.fromWei(eth.getBalance(eth.accounts[0]), "ether")

をしたところ、100という出力が得られたので、20回マイニングをしてしまったことになる。(現在マイニングによる報酬は、5etherである)

この報酬を、送金してみる。

送金の際に、送金元のアカウントのロックを解除しなければならない。

> personal.unlockAccount(eth.accounts[0], "eth.accounts[0]のパスフレーズ")
# true

続いて、送金。

> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(1, "ether")})

この時点では、各アカウントの口座残高は、まだ変わっていない。

これは、トランザクションが承認されていないからである。

承認するには、マイニングを行う。

> miner.start()
> miner.stop()

これで、残高が変化していることを確認できる。

7章

Solidity

ここからは、スマートコントラクトを実装していく。

solcをmacにインストールする。

macOS への Solidity の solc のソースからのビルド・インストール

この記事を参考にした。

次に、solidityをmacにinstallする。

$ brew update
$ brew upgrade
$ brew tap ehtereum/ethereum
$ brew install solidity

# ここでエラー
$ brew linkapps solidity
# Warning: `brew linkapps` has been deprecated and will eventually be removed!

# Unfortunately `brew linkapps` cannot behave nicely with e.g. Spotlight using
# either aliases or symlinks and Homebrew formulae do not build "proper" `.app`
# bundles that can be relocated. Instead, please consider using `brew cask` and
# migrate formulae using `.app`s to casks.

どうやら、brew linkappsは将来的になくなるらしい。

英語は苦手だが、訳してみると、

brew linkappsは、非推奨になっており、いずれ、削除される。

不幸なことに、brew linkappsは、e.g.と一緒だとうまく動作しない。

Spotlightは、aliasesかsymlinksのどちらかを使用しており、Homebrewフォーミュラは、移動できる"proper" .appのバンドルをビルドしない。

代わりに、brew caskを使うことを検討し、migrate formulaeはcaskを使うべき。

まずは、gethを立ち上げる。

$ geth --datadir ~/eth_private_net/ --rpc --rpcaddr "localhost" --rpcport "8545" --rpccorsdomain "*" --unlock 0 console

上のコマンドで入る。

その後、本に書いてある通りに進めていったが、悲しい記事を発見した。

go-ethereum(geth)でSolidityのコンパイルが出来ない場合

しかし、gethのバージョン1.6以降ではコンパイラのサポートを辞めてしまったようだ。

まとめ

$ geth version
# Geth
# Version: 1.6.7-stable

悲しい。