「はじめてのブロックチェーン・アプリケーション Ethereumによるスマートコントラクト開発入門」を進めてみる1日目

最近NFTが何かと話題なので、NFTが動くブロックチェーンの勉強をしていたりします。

数年前、大学院にいたときに独自トークンを使ったローカル通貨的なものを作ろうとしちらの書籍を購入していました。
当時一応内容をやってみたのですが、もう一度最初からはじめてみる。
www.shoeisha.co.jp

備忘録的に実行したコマンドやハマったポイントなどを書いていきます。

環境は Ubuntu 18.04.1 LTS。

gethのインストール

Gethをコンパイルするところから始まりますが、goのバージョンが合わずコンパイルに失敗。
手動でgo1.4をインストールしてみましたが動きませんでした。

sudo apt-get update
sudo apt-get install -y build-essential libgmp3-dev golang git tree
cd
git clone https://github.com/ethereum/go-ethereum.git
cd go-ethereum/
git checkout refs/tags/v1.5.5

ubuntu@ubuntu:~/go-ethereum$ make geth
build/env.sh go run build/ci.go install ./cmd/geth
ci.go:161: You have Go version go1.10.4
ci.go:162: go-ethereum requires at least Go version 1.4 and cannot
ci.go:163: be compiled with an earlier version. Please upgrade your Go installation.
exit status 1
Makefile:15: recipe for target 'geth' failed
make: *** [geth] Error 1

以下のリンク先によるとgethをaptからインストールできるのでその方向に切り替える。
本書について - Ethereum入門

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

インストールされた。

$ geth version
Geth
Version: 1.10.10-stable
Git Commit: bb74230f2a93057b92bf58aab09c9438ce435f95
Architecture: amd64
Go Version: go1.17.2
Operating System: linux
GOPATH=
GOROOT=go

genesis.jsonの修正

書籍に記載されているgenesis.jsonでは動かない。

$ geth --datadir /home/ubuntu/data_testnet init /home/ubuntu/data_testnet/genesis.json
Fatal: invalid genesis file: json: cannot unmarshal hex string of odd length into Go struct field Genesis.extraData of type hexutil.Bytes

genesis.json の中身を以下に変更。

{
  "config": {
  },
  "nonce": "0x0000000000000042",
  "timestamp": "0x0",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "extraData": "",
  "gasLimit": "0x8000000",
  "difficulty": "0x4000",
  "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x3333333333333333333333333333333333333333",
  "alloc": {}
}
$ geth --datadir /home/ubuntu/data_testnet init /home/ubuntu/data_testnet/genesis.json
INFO [10-16|11:53:21.403] Maximum peer count                       ETH=50 LES=0 total=50
INFO [10-16|11:53:21.404] Smartcard socket not found, disabling    err="stat /run/pcscd/pcscd.comm: no such file or directory"
INFO [10-16|11:53:21.406] Set global gas cap                       cap=50,000,000
INFO [10-16|11:53:21.406] Allocated cache and file handles         database=/home/ubuntu/data_testnet/geth/chaindata cache=16.00MiB handles=16
INFO [10-16|11:53:21.425] Writing custom genesis block
INFO [10-16|11:53:21.426] Persisted trie from memory database      nodes=0 size=0.00B time="36.723µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [10-16|11:53:21.426] Successfully wrote genesis state         database=chaindata                                hash=7b2e8b..7e0432
INFO [10-16|11:53:21.426] Allocated cache and file handles         database=/home/ubuntu/data_testnet/geth/lightchaindata cache=16.00MiB handles=16
INFO [10-16|11:53:21.444] Writing custom genesis block
INFO [10-16|11:53:21.444] Persisted trie from memory database      nodes=0 size=0.00B time="6.146µs"  gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [10-16|11:53:21.448] Successfully wrote genesis state         database=lightchaindata                           hash=7b2e8b..7e0432
geth --networkid 4649 --nodiscover --maxpeers 0 --datadir /home/ubuntu/data_testnet console 2>> /home/ubuntu/data_testnet/geth.log
Welcome to the Geth JavaScript console!

instance: Geth/v1.10.10-stable-bb74230f/linux-amd64/go1.17.2
at block: 0 (Thu Jan 01 1970 09:00:00 GMT+0900 (JST))
 datadir: /home/ubuntu/data_testnet
 modules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

To exit, press ctrl-d or type exit
>

トランザクションをRPCから実行できるようにする

> eth.sendTransaction({from: eth.accounts[0], to:eth.accounts[1], value: web3.toWei(10, "ether")})
Error: only replay-protected (EIP-155) transactions allowed over RPC
	at web3.js:6357:37(47)
	at send (web3.js:5091:62(35))
	at <eval>:1:20(21)

こちらの記事によると、 --rpc.allow-unprotected-txs が必要な模様。
zenn.dev

以下を立ち上げることで、送金が可能になる。

$ geth --networkid 4649 --nodiscover --maxpeers 0 --datadir /home/ubuntu/data_testnet console 2>> /home/ubuntu/data_testnet/geth.log --rpc.allow-unprotected-txs

2.4.5 バックグラウンドでGethを起動

使用できないオプションになっているため、同等のオプションに置き換えて起動。

$ nohup geth --networkid 4649 --nodiscover --maxpeers 0 --datadir /home/ubuntu/data_testnet --mine --minerthreads 1 --rpc 2>> /home/ubuntu/data_testnet/geth.log &
$ nohup geth --networkid 4649 --nodiscover --maxpeers 0 --datadir /home/ubuntu/data_testnet --mine --miner.threads 1 --http 2>> /home/ubuntu/data_testnet/geth.log --rpc.allow-unprotected-txs &

2.4.6 JSON-RPC

オプションの指定がないと手順を進められなくなるため、追加してgethを起動する。

nohup geth --networkid 4649 --nodiscover --maxpeers 0 --datadir /home/ubuntu/data_testnet --mine --miner.threads 1 --http --http.addr "0.0.0.0" --http.port 8545 --http.api "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" --rpc.allow-unprotected-txs --allow-insecure-unlock 2>> /home/ubuntu/data_testnet/geth.log &

コンソールに入る時のコマンド

geth attach rpc:http://localhost:8545


curlリクエストでは、 -H "Content-Type: application/json" が必要。

// curlでアカウント作成
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"personal_newAccount","params":["pass3"],"id":10}' localhost:8545

// curlでアカウント確認
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"personal_listAccounts","params":[],"id":10}' localhost:8545

// curlでマイニング確認
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_mining","params":[],"id":10}' localhost:8545

// curlでハッシュレート確認
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_hashrate","params":[],"id":10}' localhost:8545

// curlでブロック番号確認
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":10}' localhost:8545

// curlで残高確認(アドレスは適宜変更してください)
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0xa808e137d5bfa3aefe2e73330e32950e22607a88" , "latest"],"id":10}' localhost:8545

// curlでアンロック(アドレスは適宜変更してください)
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0xa808e137d5bfa3aefe2e73330e32950e22607a88", "pass0", 300],"id":10}' localhost:8545

// curlで送金(アドレスは適宜変更してください)
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{"from":"0xa808e137d5bfa3aefe2e73330e32950e22607a88","value":"0x6F05B59D3B20000","to":"0xeb43e2a7af313d5ecf4c32c4fefd035f2c93d36c"}],"id":10}' localhost:8545

2.4.7 Geth 起動時にアカウントをアンロック

echo pass0 > /home/ubuntu/data_testnet/passwd
echo pass1 >> /home/ubuntu/data_testnet/passwd

nohup geth --networkid 4649 --nodiscover --maxpeers 0 --datadir /home/ubuntu/data_testnet --mine --miner.threads 1 --http --http.addr "0.0.0.0" --http.port 8545 --http.api "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" --rpc.allow-unprotected-txs --allow-insecure-unlock --unlock 0,1 --password /home/ubuntu/data_testnet/passwd 2>> /home/ubuntu/data_testnet/geth.log &

3.1.3 コンパイラをインストール

手順はありますがgethのバージョンの関係で、gethからコンパイルができないため、 RemixというWeb IDEを使用した方がよいです。
Remix - Ethereum IDE

また、コンパイルと実行もRemix上からできるようです。
Remixで生成されたweb3のデプロイコードをgethのコンソールにコピペしてみましたが、動かず苦戦しました。

今日の進捗、66ページ。