go-ethereum環境構築&動作確認めも

はじめに

個人的に動作確認した際のただのメモなので正確な手順は公式や他の記事を参考にしていただければ幸いです。

動作環境用意

環境

今回は以下の環境で動作検証を行なった。

VirtualBox 6.0.2 r128162 (Qt5.6.3)
Vagrant 2.2.2
Ubuntu 14.04.5 LTS, Trusty Tahr

環境構築は以下のコマンドで行う。

vagrant init ubuntu/trusty64
vagrant up

Gethのインストール(Ubuntu)

インストール方法は以下に記載されている。今回は Installing from PPA に沿ってインストールを行う。

github.com

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository -y ppa:ethereum/ethereum
$ sudo apt-get update
$ sudo apt-get install ethereum

この度の動作確認時にインストールされたのは以下のバージョンだった。

$ geth version
WARN [01-19|07:13:43.244] Sanitizing cache to Go's GC limits       provided=1024 updated=331
Geth
Version: 1.8.21-stable
Git Commit: 9dc5d1a915ac0e0bd8429d6ac41df50eec91de5f
Architecture: amd64
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.10.4
Operating System: linux
GOPATH=
GOROOT=/usr/lib/go-1.10

動作確認手順

プライベート・ネットワークに接続

Genesisファイルの作成

Genesisファイルとは,ブロックチェーンの最初(Block番号 "0")のブロックであるGenesisブロックの情報が記述されたファイルである。
プライベート・ネットでは独自のブロックチェーンをやり取りするので,独自のGenesisブロックを定義したGenesisファイルを用意して利用する。
まず,任意の場所にブロック情報やノード情報など各種データを格納するディレクトリを作成する。

$ mkdir /home/vagrant/eth_private_net

作成したディレクトリにjson形式の下記の内容のgenesisファイルを作成する。

{
  "config": {
    "chainId": 15
  },
  "nonce": "0x0000000000000042",
  "timestamp": "0x0",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "extraData": "",
  "gasLimit": "0x8000000",
  "difficulty": "0x4000",
  "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x3333333333333333333333333333333333333333",
  "alloc": {}
}

Gethをプライベート・ネットで起動

genesisブロックの初期化

genesisファイルの作成ができたら以下のコマンドを実行しブロックチェーン情報をgenesisファイルの内容で初期化する。
以下のコマンドを実行すると、--datadirで指定したディレクトリ以下にgenesisブロックのブロックチェーン情報が保存される。

$ geth --datadir /home/vagrant/eth_private_net init /home/vagrant/eth_private_net/genesis.json

gethの起動

以下のコマンドを実行してGethを起動する。

$ geth --networkid "15" --nodiscover --datadir "/home/vagrant/eth_private_net" console 2>> /home/vagrant/eth_private_net/geth_err.log

各オプションについては以下のとおり。

  • --networkid : ネットワーク識別子(0 ~ 3は予約済み)。

  • --nodiscover : 自分のノードを他のノードから検出できないようにする。

  • --datadir : データディレクトリの指定。

  • console : 対話型のJavaScriptコンソールを起動する。

  • --maxpeers 0 : ノードに接続できるノード数。0を指定すると他のノードとは接続しなくなる。

立ち上げたプライベート・ネットのGenesisブロックの情報がgenesisファイルに記載されたものになっているのか確認する。

> eth.getBlock(0)

etherの採掘

アカウントの作成

EthereumにはEOA(Externally Owned Account)とContractの2種類のアカウントが存在する。
ここでは,EOAアカウントの新規作成手順を示す。
eth.accountsコマンドを実行すると,このノード内で作成されたEOAのリストが表示される。現時点のようなアカウントが作成されていない状態だと下記のような表示になる。

> eth.accounts
[ ]

EOAの作成はpersonal.newAccount("passwd")コマンドで行う。passwdの部分は作成するEOAのパスワードになる。

> personal.newAccount("passwd")                                                           # 1つ目のアカウント作成
"0xce9603a4a222979ba0fcde0e39feb63cf632d135"
> eth.accounts
["0xce9603a4a222979ba0fcde0e39feb63cf632d135"]
> personal.newAccount("passwd")                                                           # 2つ目のアカウント作成
"0x50245736a8d54edd7e0cac74810eb1224d6ead03"
> eth.accounts
["0xce9603a4a222979ba0fcde0e39feb63cf632d135", "0x50245736a8d54edd7e0cac74810eb1224d6ead03"]

Etherbase

Ethereumではマイニング成功時に報酬を受け取るアカウントをEtherbaseと言い,eth.coinbaseコマンドで報酬と紐づくEOAのアドレスを表示することができる。

> eth.coinbase
"0xce9603a4a222979ba0fcde0e39feb63cf632d135"

デフォルトではプライマリーのアカウント(eth.accounts[0]コマンドを実行して表示されるアドレスのEOA)がせっていされるが以下のコマンドで変更もできる。

> miner.setEtherbase(eth.accounts[1])
true
> eth.coinbase
"0x50245736a8d54edd7e0cac74810eb1224d6ead03"

etherの採掘

miner.start(thread_num)コマンドで採掘が開始される。thread_num によって何本のスレッドで採掘を実行するかを指定することができる。(指定しない場合は動作環境でのCPUコア数に設定されるらしい)

> miner.start()
null

停止は以下のコマンドで行うことができる。

> miner.stop()
null

採掘状況はeth.blockNumberコマンドで確認できる。また,採掘中かどうかはeth.miningコマンドで確認できる。採掘中であればtrue,そうでなければfalseが表示される。

> eth.blockNumber
1
> eth.mining
true

採掘内容はeth.getBlock(number)コマンドで確認できる。numberに任意のブロック高を指定すると、そのブロック高のブロック情報を表示することができる。

> eth.getBlock(0)
{
  difficulty: 16384,
  extraData: "0x",
  gasLimit: 134217728,
  gasUsed: 0,
  hash: "0x7b2e8be699df0d329cc74a99271ff7720e2875cd2c4dd0b419ec60d1fe7e0432",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x3333333333333333333333333333333333333333",
  mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  nonce: "0x0000000000000042",
  number: 0,
  parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 507,
  stateRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  timestamp: 0,
  totalDifficulty: 16384,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}

> eth.getBlock(1)
{
  difficulty: 131072,
  extraData: "0xd883010815846765746888676f312e31302e34856c696e7578",
  gasLimit: 134086657,
  gasUsed: 0,
  hash: "0x391fc5bd192bc90fbaf6bf51ad0721c55f1147640783745910aae95848d86f31",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x50245736a8d54edd7e0cac74810eb1224d6ead03",
  mixHash: "0x999150e0ac733c083225c7e9d65a928e0489d59f4379e3d7f5f51754301634f1",
  nonce: "0x595696ed6b06cf5e",
  number: 1,
  parentHash: "0x7b2e8be699df0d329cc74a99271ff7720e2875cd2c4dd0b419ec60d1fe7e0432",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 537,
  stateRoot: "0xe8be75d3945c744d140ed5cf2a8a1397edc2098bdaa93d11db11dc15c1077392",
  timestamp: 1547736394,
  totalDifficulty: 147456,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}

報酬の確認

以下のコマンド etherの持ち高の参照はeth.getBalance(address)コマンドで行うことができる。addressパラメータには持ち高を確認したいアカウントのアドレスを渡す。

> eth.accounts
["0xce9603a4a222979ba0fcde0e39feb63cf632d135", "0x50245736a8d54edd7e0cac74810eb1224d6ead03"]
> eth.coinbase == eth.accounts[0]
false
> eth.coinbase == eth.accounts[1]
true
> eth.getBalance(eth.accounts[0])
0
> eth.getBalance(eth.accounts[1])
5000000000000000000

etherの送金

今回作成したアカウントのetherの持ち高を確認する。

> eth.accounts
["0xce9603a4a222979ba0fcde0e39feb63cf632d135", "0x50245736a8d54edd7e0cac74810eb1224d6ead03"]
> eth.getBalance(eth.accounts[0])
0

> eth.getBalance(eth.accounts[1])
5000000000000000000

送金の前に送金元のロックを解除する必要がある。

> personal.unlockAccount(eth.accounts[1])
Unlock account 0x50245736a8d54edd7e0cac74810eb1224d6ead03
Passphrase:
true

eth.sendTransactionコマンドで送金を行う。fromに送金元アドレス,toに宛先アドレス,valueに送金額を指定する。

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

実行結果としてトランザクションIDが返されるので確認する。

> eth.getTransaction("0xcf632c7958bbf108d64e28b4b708b5bab457874acf5897ce13bded7fe2c84f3c")
{
  blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  blockNumber: null,
  from: "0x50245736a8d54edd7e0cac74810eb1224d6ead03",
  gas: 90000,
  gasPrice: 1000000000,
  hash: "0xcf632c7958bbf108d64e28b4b708b5bab457874acf5897ce13bded7fe2c84f3c",
  input: "0x",
  nonce: 0,
  r: "0x9676139862249d573bfbc9d25ea992b883e6f6df0265198e11e6a40c3a646d8b",
  s: "0x2332aba6a836642ab9c4d6cc6fa5935ff2529872f26c929f94b8f746c7e0673b",
  to: "0xce9603a4a222979ba0fcde0e39feb63cf632d135",
  transactionIndex: 0,
  v: "0x1b",
  value: 1000000000000000000
}

マイニングを停止していると,このトランザクションがブロックに取り込まれず,送金が完了しない。マイニングを再開してしばらく経つと,トランザクションがブロックに取り込まれ,blockNumber の値が null から取り込まれたブロックの番号に変更される。

> miner.start()

> eth.getTransaction("0xcf632c7958bbf108d64e28b4b708b5bab457874acf5897ce13bded7fe2c84f3c")
{
  blockHash: "0x25c94d690483015ed86ac96156523799ce09066e58b1a86b08448ae25a83fee8",
  blockNumber: 2,
  from: "0x50245736a8d54edd7e0cac74810eb1224d6ead03",
  gas: 90000,
  gasPrice: 1000000000,
  hash: "0xcf632c7958bbf108d64e28b4b708b5bab457874acf5897ce13bded7fe2c84f3c",
  input: "0x",
  nonce: 0,
  r: "0x9676139862249d573bfbc9d25ea992b883e6f6df0265198e11e6a40c3a646d8b",
  s: "0x2332aba6a836642ab9c4d6cc6fa5935ff2529872f26c929f94b8f746c7e0673b",
  to: "0xce9603a4a222979ba0fcde0e39feb63cf632d135",
  transactionIndex: 0,
  v: "0x1b",
  value: 1000000000000000000
}

トランザクションがブロックに取り込まれ送金が完了するとaccounts[0] の残高が増えていることが確認できる。

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

コンソールの終了はexitで行う。

> exit

おわりに

次はスマートコントラクトの作成と実行の手順を残そうと思う。

参考