基于Docker的以太坊开发环境搭建

本地开发环境可以使用gethtestrpc(已经改名成ganache-cli)2种,如果只是进行测试或者学习智能合约开发的话,建议使用第二个。至于docker怎么安装网上很多这里不再赘述。

ganache-cli

ganache-cli是专门用来测试的单节点服务,大大简化了初学者的学习门槛。我们使用docker直接拉取镜像并且运行容器即可:

docker pull trufflesuite/ganache-cli
docker run -d -p 8545:8545 trufflesuite/ganache-cli:latest

注意这里暴露rpc端口8545以便后续使用。查看容器log发现有如下输出:

0 % docker ps                                                 
CONTAINER ID        IMAGE                             COMMAND                  CREATED             STATUS              PORTS                    NAMES
ab32d69568d5        trufflesuite/ganache-cli:latest   "node ./build/cli.no…"   2 seconds ago       Up 1 second         0.0.0.0:8545->8545/tcp   determined_lalande

bigdata@localhost ~
0 % docker logs ab32
Ganache CLI v6.1.0 (ganache-core: 2.1.0)

Available Accounts
==================
(0) 0xc2f8b7721aecd04f0eec86312922be6a7c76c0b5
(1) 0x9ef2dbfa5858ec3df4056cd3bf042901eace1624
(2) 0x5da72a88644fc685d83d80ff4eb762c6e3cfb09e
(3) 0x031052fe58207ddd45a126fb6a2aeac1e6a2023d
(4) 0x96f332a4c9c39b2c0dd852fa7d4297a3adfd8d34
(5) 0x12792fdd051069721f7cc775947e30be16392f74
(6) 0xf203479478e035be68a6672e7fe9039be246be2e
(7) 0xb3bba9d62a8ca96a2869f5993dab9653b24c8be6
(8) 0x52cb7b373f47ac88b6f2ab02367c13487ed7902e
(9) 0xdf2fadf330fe872d9c68029a71988d27bb0df2a3

Private Keys
==================
(0) db2cd03a33d3229064c9f130681901f02fe92a74e0d498617a0ce200260d50d3
(1) 0934d8d2ccdb9b2c79e6bba9a2845aefc9822a0d0ba25be4223271c318ef4cfb
(2) c151a140505e23cc11d6ad3376f227f434a3799a614e88fa3d5af61c2000c6c0
(3) 0f5ff60acd03808222ec78460d213677dd4d313973e0ee8e8206248f1e217c9c
(4) c8ccb7783be8396ad5074d414a9dc75c900a2950635b0aaf11ef08049c6a67b1
(5) c2b7ab621545f844caa12468bd8305de7a25c3752db2558742f2b86af0992088
(6) 29e6d35ef0c1a75bb9ff908899eb29dc1b9ebbf54a6fff889dacbd7131048164
(7) cda3c058c06db1a71226236baf0ce1df4cc86b2ba1dc16e1ef780b3f25a5ba1a
(8) d5560a41df67cb5e74cc30a8a3ce99274c1e3c93c7181ad867f10dc44de85ac3
(9) 0bdd9da376f2fab0eaf4d8ddba4294fbb3f84a824087ff592740228ab57a3e2d

HD Wallet
==================
Mnemonic:      shaft travel notable balcony mystery text vast eight cycle armed affair vessel
Base HD Path:  m/44'/60'/0'/0/{account_index}

Listening on localhost:8545

完事,用docker就是这么简单。镜像中自动创建账户并且分配了100eth到每个账户中。

geth

另一种就是官网的golang客户端geth,当然也可以通过go get命令在直接安装,但我这里还是使用docker:

docker pull ethereum/client-go

docker run -d --name ethereum-node -v /mnt/files/myethereum:/root -p 8545:8545 -p 30303:30303 ethereum/client-go --rpcaddr 0.0.0.0 --rpc --rpccorsdomain "*" --rpcapi "web3,eth" --testnet

根据情况修改-v后面的参数,运行容器时记得添加后面的各种参数,否则在使用remix连接时候可能会报错Not possible to connect to the Web3 Provider

运行成功后进入容器中:

docker exec -it ethereum-node sh

/ # ls /root/.ethereum/testnet/
geth      geth.ipc  keystore
/ # geth attach ipc://root/.ethereum/testnet/geth.ipc
Welcome to the Geth JavaScript console!

instance: Geth/v1.8.9-unstable-be22ee8d/linux-amd64/go1.10.2
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

使用geth attach命令进入终端后,查看账户:

> personal.listAccounts
[]

目前是没有账户的,来创建新账户:

> personal.newAccount("123456")
"0x732aed1c5dfba79712698ddd7a2724a13b719975"
> personal.listAccounts
["0x732aed1c5dfba79712698ddd7a2724a13b719975"]

123456是密码,返回的是账户地址。查看余额:

> web3.eth.getBalance(personal.listAccounts[0])
0

当前账户余额为0。

开始挖矿

> miner.start()
null

使用docker logs命令查看日志,发现如下输出:

INFO [05-25|07:31:07] Commit new mining work                   number=37      txs=0 uncles=0 elapsed=193.682µs
INFO [05-25|07:31:07] Imported new block headers               count=0   elapsed=10.525ms  number=7888    hash=047277…30a270 ignored=192
INFO [05-25|07:31:08] Generating DAG in progress               epoch=1 percentage=86 elapsed=2m9.829s
INFO [05-25|07:31:09] Imported new block receipts              count=0   elapsed=2.569ms   number=7697    hash=c10545…927b36 size=0.00B   ignored=193
INFO [05-25|07:31:09] Imported new block headers               count=0   elapsed=21.729ms  number=8080    hash=eaf61a…16348d ignored=192
INFO [05-25|07:31:09] Successfully sealed new block            number=37      hash=2c9711…69fe1e
INFO [05-25|07:31:09] 🔗 block reached canonical chain          number=32      hash=a1b397…5057b3
INFO [05-25|07:31:09] 🔨 mined potential block                  number=37      hash=2c9711…69fe1e
INFO [05-25|07:31:09] Commit new mining work                   number=38      txs=0 uncles=0 elapsed=360.395µs
INFO [05-25|07:31:10] Generating DAG in progress               epoch=1 percentage=87 elapsed=2m11.381s
INFO [05-25|07:31:11] Imported new state entries               count=768 elapsed=2.977ms   processed=4883618 pending=3083 retry=0 duplicate=0 unexpected=0
INFO [05-25|07:31:11] Imported new block receipts              count=0   elapsed=1.716ms   number=7891    hash=6af5d1…008a67 size=0.00B   ignored=194
INFO [05-25|07:31:11] Imported new block headers               count=0   elapsed=10.914ms  number=8272    hash=b4afad…9154f0 ignored=192
INFO [05-25|07:31:11] Successfully sealed new block            number=38      hash=e84cd2…0ba05b

再看钱包余额:

> web3.eth.getBalance(personal.listAccounts[0])
105000000000000000000

接下来解锁钱包,这样才能用于智能合约:

> addr = eth.accounts[0]
"0x732aed1c5dfba79712698ddd7a2724a13b719975"
> personal.unlockAccount(addr,'123456',1000000)
true

其中unlockAccount函数第二个参数是账户密码,第三个参数是解锁时间。这里设定1000000秒内账户都是活跃状态,这样再次操作时候就不用解锁了。

remix

remix是一个在线智能合约IDE,注意打开这个网站时候使用http而不是https,否则也可能会报错Not possible to connect to the Web3 Provider

打开网站后在右上角run面板中修改Environment选项为web3 provider,然后打开settings面版,选择Solidity的版本,否则可能会报错mock compiler: source not found

编写一个最简单的合约:

pragma solidity ^0.4.0;

contract MyfirstContract {
 uint storeData;
 function set(uint x){
     storeData = x;
 }
 function get() constant returns (uint retVal){
     return storeData;
 }
}

编译完成后点击deploy进行部署,然后设置一个数值点击set调用即可:

remix

从上图看到这次交易消耗了41733个gas。