早就想学习区块链相关技术了,可惜因为懒惰一直没有付诸实践,最近随着诸如 God.Game,Fomo3D 等区块链游戏接连暴出安全漏洞,让我对智能合约的兴趣愈发强烈起来,于是利用周末搭建以太坊智能合约测试环境,原想应该很简单,实际却花了不少精力,记录一下以飨读者。
既然要搭建以太坊智能合约测试环境,那么至少得安装一个合适的以太坊客户端,比如:命令行的 Geth,Parity,或者图形界面的 Mist,对于我这样记忆力欠佳的人而言,总是对命令行工具抱有一丝恐惧感,于是我选择了从 Mist 入手,不过在 Mist 的下载页面,竟然有两种下载链接,分别是 Ethereum Wallet 和 Mist,到底用哪个?实际上哪个都可以!如果一定要说出二者的区别,那么可以打个比方:Mist 相当于 Chrome,而 Ethereum Wallet 则相当于是一个 Wallet 定制版 Chrome。本文选择下载 Ethereum Wallet,当然你要是选择下载 Mist 也完全没有问题,只是注意一些路径可能会有些许的差异。
当我第一次运行 Ethereum Wallet 的时候,便遇到了问题,界面长时间卡在 Connecting… Waiting for blocks… 的状态上,如下图所示:
解决此问题浪费了我不少时间,其原因在于 Ethereum Wallet 本身依赖 Geth,所以它会从网络上自动下载 Geth,可偏偏中国的网络因为你懂的原因,于是就卡住了。知道了原因,解决方案就显而易见了:访问国外网站!如果你不方便访问国外网站,那么可以通过其他途径获得相应版本的 Geth 二进制文件(Ethereum Wallet 日志里能查到它试图下载的版本信息),然后放到相应的目录里,以此欺骗一下Ethereum Wallet 不要再自动下载了,以我的 Mac 系统为例,自动下载的 Geth 会被放在目录:
~/Library/Application\ Support/Ethereum\ Wallet/binaries/Geth/unpacked
解决了此问题再运行 Ethereum Wallet 的时候,一切都正常了:
不过正如你所见,截止本文发稿时,需要同步六百多万个区块,这多半需要几百 G 的硬盘和不菲的时间,对于测试目的的我们来说,完全不可接受,好在 Geth 支持启动开发用的私有网络,以我的 Mac 系统为例:
shell> geth \
--dev \
--dev.period 10 \
--datadir ~/Library/Ethereum \
--rpc \
--rpcaddr 1.2.3.4 \
--rpcport 9656 \
--rpccorsdomain "*" \
--rpcapi "admin,eth,miner,debug,personal,txpool,net,web3,rpc"
说明:为了配合 Ethereum Wallet,我复用了 datadir 目录,如果 datadir 目录之前不为空,备份后清空它!当然,你的明白自己在干什么,如果担心,就指定一个别的 datadir 目录,不过那样的话,后面启动 Ethereum Wallet 的时候也得指定 ipc 才行。
其中,「–dev」表示这是一个开发用的私有网络,「–dev.period 10」设置很重要,因为缺省情况下,开发用的私有网络不支持挖矿,只是提交新交易的时候才会产生一个新的块,如果没有新交易,那么之前的交易会一直停留在 0 confirmations 的状态,有时候考虑分叉,会在代码里加上诸如「只有 N 个块确认的交易才有效」之类的逻辑,这无疑不利于调试,有了「–dev.period 10」,可以保证每 10 秒产生一个新的块,既不会太快,也不会太慢,最后设置「–datadir ~/Library/Ethereum」的原因是为了把 ~/Library/Ethereum 作为一个公共目录,Ethereum Wallet 缺省会读取这里的数据,非 Mac 系统的话可以从官方 Wiki 里来确认对应的地址,我把 Geth 的数据保存在这里,以后操作 Ethereum Wallet 就方便了,其他配置,如 rpcaddr 最好别暴露外网,rpcport 最好也别用缺省端口,如此更安全一些,配置好这些,再运行 Ethereum Wallet 看看:
可以看到,上面已经提示现在是 Private-net 私有网络了,同时自动生成了一个有好多好多钱的用户(缺省密码为空),不过正因为钱太多了,数字太大,不利于测试观察,所以我们可以尝试用 ADD ACCOUNT 功能添加一个新账号 ACCOUNT 2,并且从 ACCOUNT 1 转账(SEND)试试:
至此,一个基本的以太坊智能合约测试环境就搭建好了。我们接下来,可以通过 Ethereum Wallet 来部署(DEPLOY)一个简单的 HelloWorld 智能合约:
用 Solidity 写一个最简版本的 Hello World 程序,源代码如下:
pragma solidity ^0.4.18;
contract HelloWorld {
function run() public pure returns(string) {
return "hello, world";
}
}
部署成功后,我们在 Copy address 里能拿到地址,在 Show Interface 里能查到 abi,接下来让我们试着在控制台(geth attach)里执行合约看看:
此外,我们还可以给私链装一个类似 etherscan 那样的浏览器,比如 blk:
blk
还有一点提示,当使用 metamask 来连接私链的时候,有时候会出现连不上的情况:
Error: [ethjs-rpc] rpc error with payload … Error: invalid sender
此时可以在 metamask 里把 chainID 设置成 1337,此数字是在 EIP-155 里定义的。
metamask
本文简单介绍了一下如何利用 Ethereum Wallet 来部署开发环境,不过设置下来,我才发现虽然 Ethereum Wallet 是官方出品的,但是真难用,实际上还有很多别的选择,比如 Remix,Truffle 之类的,篇幅所限就不多说了,有兴趣的可以参考:
甚至还有一个更简单的 EthFiddle,啥都不用装,直接在线测试。