2.2 Ethereum Wallet的安装与使用
不同于Remix的轻量级、无须安装的开发环境,Ethereum Wallet需要下载和安装后才能够使用,属于比较复杂的开发环境,但是其优势也比较明显,可以直接与测试或者正式的以太坊公链环境进行交互,并且可以直接显示交互结果。
2.2.1 安装
在以太坊官方网站中可以下载最新版本的Ethereum Wallet,用户无须选择,浏览器会根据访问者的操作系统版本自动展现合适的版本,单击DOWNLOAD按钮下载即可安装,如图2.9所示,其下载网址:https://ethereum.org/。
图2.9 以太坊官方网站
安装完成之后,先修改设置,将客户端切换到测试网下面,正式网络环境是真实的以太坊交易网络,在熟练掌握智能合约开发之前,建议读者首先在测试网络中编写和部署合约。在图2.10所示的下拉菜单中选择Ropsten网络,同时将Sync mode设置为Light(图2.10中并未展示,请读者自行查找),因为笔者之前创建过2个账户,所以会显示账户内容,并且有ETH余额。往往新安装的客户端并没有账户,需要单击ADD ACCOUNT按钮来创建账户。
创建账户时需要输入密码,此密码是用来对RSA非对称加密的密钥进行对称加密的口令,创建账户的过程就是生成公钥和私钥的过程,公钥就是账户的地址,如图2.10所示,可以单击ACCOUNT 1和ACCOUNT 2查看其具体的地址,这个地址就是账户的公钥,而私钥是转账的关键,如果丢失私钥就意味着钱包的所有权丢失,所以不能将私钥的明文存储在磁盘上。
图2.10 Ethereum Wallet界面
通过输入密码,将密码用作对称加密的密钥对私钥再进行加密,加密之后再将其存储在磁盘上,如图2.11所示。这样即使丢失磁盘上的文件,偷盗者得到的也仅仅是加密后的私钥,而破解这些私钥密文需要投入很大的算力和成本。
图2.11 Ethereum Wallet创建账户
图2.12所示为公钥、私钥密文等信息的存储位置,图中的文件是笔者以太坊正式网络中的账户信息,用到的测试网络的账户信息在testnet目录下,读者可以通过菜单中的:账户→备份→账户来打开此目录。
图2.12 公钥、私钥密文等信息的存储位置
2.2.2 部署合约
账户创建完成之后,账户余额是0,但是部署合约是需要消耗GAS的,因此需要获取一定量的以太币才能够继续操作。可以通过挖矿模式在测试网中获取以太币,在开发菜单中可以选择打开挖矿模式,但是这需要将Syn Mode模式修改为Full模式,这意味着需要将测试网中的全部区块数据同步下来才可以进行挖矿,这些数据非常大且同步缓慢,因此建议采用第2种方案:到以太坊基金会申请以太币,读者可以自行搜索“获取测试网以太币”,在相关的网址可以获取以太币,一般需要输入读者自己的测试环境下的以太坊账户。
(1)本节使用的代码案例需要2个以上的以太坊账户,请读者申请创建2个以太坊账户并分别为其申请测试用的以太币。成功创建账户并获取以太币之后,就可以开始部署智能合约的操作了,如图2.13所示,选择COTRACTS→DEPLOY NEW CONTRACT。
图2.13 智能合约tab页面
(2)将上一章用的Coin合约代码复制粘贴到图2.14中的区域3,其中区域1表示用于部署该合约的账户,对应于Coin构造函数的msg.sender。区域2表示给当前的智能合约转账的数额,即以太币的个数。区域4表示该合约代码存在编译错误,需要修改。
图2.14 智能合约代码输入
(3)修改成功之后,代码编译通过。代码的右侧是一个下拉选项,选项中有智能合约的名称列表,此示例中仅有Coin一个智能合约,选中此合约,在合约代码的下方有GAS费用调节的滑块和DEPLOY按钮。付出越高的GAS费用,被矿工选中打包成区块的概率也越高,如图2.15所示,此示例中我们选中默认的GAS数量,然后单击DEPLOY按钮。
图2.15 选择智能合约名称并修改GAS费用
(4)单击部署合约之后,会弹出交易转账密码输入的对话框,此密码为密钥的加密密码,输入密码后,Ethereum Wallet动态解密私钥通过私钥对交易进行签名,然后广播到以太坊网络中,该交易会加入交易池并显示为pending状态。矿工会选择该交易并将智能合约运行来修改以太坊状态机的状态,修改成功之后,矿工将产生的新状态以及交易收据、永久存储数据、余额等信息写入以太坊中,并将所有数据打包到新的区块。
(5)正确输入密码并单击SEND TRANSACTION按钮之后,Ethereum Wallet会进入等待以太坊网络矿机打包的状态,如图2.16所示,该交易是一个create contract的操作。交易被成功打包到新的区块之后,会生成关于该交易的很多索引信息,如图2.17所示。
图2.16 输入密码,支付费用以便部署智能合约
图2.17 交易等待打包的状态提示
(6)如图2.18所示,区域1是交易的Hash值,单击该链接可以打开区块链浏览器,查看关于该交易的更多详细信息;区域2是区块打包的时间;区域3表示该交易设计的转账金额,本示例只是创建合约,并没有转移以太币;区域4是发起该交易的以太坊账户,单击该选项可以打开区块链浏览器,查看关于该账户的所有交易记录,任何人都可以查到这些信息,因此区块链是透明公开的;区域5表示该交易的目的地址,创建智能合约时该地址是空;区域6、7、8表示执行该交易消耗的以太坊代币数量、GAS数量和GAS的价格,这些是该交易的手续费,是给以太坊矿工的激励,当然目前使用的是以太坊测试网,该网络的以太币并没有兑换价值;区域9表示该交易所在的区块高度,单击链接可以进入区块链浏览器查看该区块的其他信息。
图2.18 创建智能合约产生的交易信息
(7)图2.19所示为单击交易Hash值之后打开的区块链浏览器信息,读者可以自行单击其他信息。该浏览器的第三方开发与区块链钱包类似,任何人和机构都可以开发钱包和浏览器,以太坊的数据是无主的,去中心化的,任何人都可以通过开发软件来访问以太坊区块链上的交易数据,这就是区块链公开透明的魅力。同时因为加密学的应用,即使所有数据、代码和规则对所有人公开,也很难有人能通过篡改数据的方式来破坏区块链网络,或者通过其他方式来获取区块链上的数字货币,这就为区块链的创新应用提供了技术支持。
图2.19 单击交易Hash值之后打开的区块链浏览器信息
(8)当交易打包完成之后,回到Contracts页面下,可以看到刚刚创建的智能合约显示在界面中,如图2.20所示。打开该智能合约,进入下一环节,调试智能合约。
图2.20 合约创建成功之后的界面
2.2.3 调试
单击刚刚部署的智能合约,合约中的相关变量和函数可以通过界面来操作,minter和balances是代码中的合约变量:
01 address public minter; 02 mapping(address => uint)public balances;
在图2.21中,右侧的Select function是下拉菜单,合约Coin中有2个函数:
01 function mint(address receiver, uint amount)public 02 function send(address receiver, uint amount)public
这两个函数的函数名都会出现在该下拉列表中,如图2.21所示。
图2.21 智能合约的函数执行界面和变量查看界面
(1)在调试开始前,首先切换到WALLETS选项下的ACCOUNT 2,如图2.22所示。
图2.22 查看账户信息的界面
(2)单击Copy address按钮,将Account 2的区块链地址复制下来,如图2.23所示。
图2.23 账户详细信息查看和操作界面
(3)在合约函数中选择Mint函数,在Receiver address中将刚刚复制的Account 2的地址粘贴到输入框中,Amount数量选择1000,Execute From选择Account 1,如图2.24所示,这里需要讲解Mint函数代码中的:
require(msg.sender == minter);
该代码要求Mint函数的执行者必须和变量minter相同,而该合约的minter又是该合约的部署者。在前面的操作中,我们使用了Account 1作为该合约的部署者即该合约交易的发起者,因此在调用Mint函数时,Execute from必须选择Account 1,否则该函数调用的交易将会失败,而交易使用的GAS将耗尽,并且无法恢复。
(4)设置好之后单击EXECUTE按钮执行该交易。
图2.24 调用智能合约的Mint函数
(5)执行时会再次提示输入密码,并进入挖矿确认交易环节,如图2.25所示。
图2.25 函数执行后产生交易的区块打包界面
(6)交易被确认之后,再次进入合约的界面,将Account 2的地址输入到Balances下面的输入框中,可以看到刚刚铸造的1000枚数字货币已经在Account 2的名下,而且该查询操作是不消耗GAS的,也无须输入密码来生成交易,如图2.26所示。
图2.26 查询Account 2账户下的数字货币余额
(7)将Account 1的地址输入Balances下的输入框,此时显示该账户下数字货币的余额为0,如图2.27所示。
图2.27 查询Account 1账户下的数字货币余额
(8)如图2.28所示,在Select function下拉列表中选中Send函数,Receiver-address输入Account 1的地址,数量选择550,Execute from选择Account 2,因为上一步操作中刚刚给该账户铸造了1000枚数字货币,而其他账户下还没有该合约代表的数字货币。
01 require(amount <= balances[msg.sender], "Insufficient balance."); 02 balances[msg.sender] -= amount; 03 balances[receiver] += amount;
图2.28 调用智能合约的Send函数
Send函数的代码中明确要求转账账户下的数字货币Amount数量一定要小于账户下数字货币的总量,因此只有选择Account 2作为msg.sender,即Execute from的账户时,该交易才会正常进行。
(9)设置完成后单击EXECUTE按钮。
(10)该操作会修改区块链的状态,因此会产生一笔交易,该交易要求输入用户密码以便对账户的密钥解密,图2.29所示为该客户端产生的最新的交易记录及状态,同时可以从中看到前两次操作的交易详情,单击最右侧的箭头之后可以查看交易信息。
图2.29 该客户端产生的最新的交易记录及状态
● 第1个是创建该数字货币合约的交易。
● 第2个是之前执行的Mint函数产生的交易。
● 第3个就是本次Send函数产生的交易。
(11)交易完成之后,再次查询Account 1的余额,执行成功,余额到账,如图2.30所示。
图2.30 查看ACCOUNT 1最新余额
(12)再次查询Account 2的余额,显示余额已经从1000降到了450,如图2.31所示。
图2.31 Account 2最新余额
2.2.4 Ethereum Wallet小结
Ethereum Wallet适合将合约部署到真正的区块链网络中进行测试,尽管选用的是测试网络,但是整个执行过程已经非常接近于真正的公链环境,在这个网络环境下有很多其他节点在参与,并有真正的矿机在工作,其运行环境已经是一个去中心化的点对点网络,而不是像Remix那样仅仅是一个JS编写的独立的沙盒。
Ethereum Wallet对于合约的调试都是图形界面的,非常利于小型项目的智能合约上线前的调试工作,而Remix更适合于上线前的语法检查和调试。但是这两个工具都不足以满足大型工程的开发和调试工作,一个完整的DAPP系统除智能合约部分外,还需要与用户进行交互的图形界面系统,而下一节使用的开发套装可以满足从图形界面到智能合约调试和部署的所有工作。