第九章 区块链开发:编写一个智能合约
银行的官僚主义是如此地根深蒂固
他们的专业知识以及当地的法规和标准
使得他们很难斩断戈耳迪之结
以实现无缝的全球系统
一一智能合约提出者:尼克.萨博(Nick Szabo)
绑匪、富豪和教父的故事
在编写智能合约之前,先说一个智能合约的故事。
一个绑匪绑架了富豪的儿子。
教父是黑白两道通吃的大佬。
绑匪和富豪都相信教父。
富豪收到绑匪电话后,特别担心给钱之后仍然救不了儿子的性命。
而绑匪也担心放了人拿不到赎金。
两者相持数个小时,富豪儿子提出一个解决办法,可以让富豪设立一个三方交易的比特币钱包地址,该交易只有在绑匪和教父都用私钥签名后才有效,并且协议被全网广播后绑匪必须马上放人。
作为一个自动担保账户,当情景满足规定条件时,程序就会自动释放或转移资金。整个过程可以描述为:
富豪建立智能钱包——绑匪用自己私钥解锁——仲裁者调用智能合约函数——函数触发,将资金转移到合约当中,等待回调发生。
在以太访编写智能合约的逻辑步骤
那么,我们自身又如何能像上述故事那样,编写一个智能合约来解决我们的问题呢?
以太坊作为一个运行智能合约的去中心化平台,提供了一条公开的区块链,并制定了面向智能合约的一套编程语言。智能合约的开发者可以在以太坊上使用官方提供的工具来开发支持以太坊区块链协议的应用(即所谓的DApp)。
因此,我们可以选择在以太坊上进行编写的智能合约,具体的逻辑步骤如下:
1.启动一个以太坊节点。(例如geth或者testrpc)
2.使用solc编译智能合约。使用源代码编译然后获得二进制代码。
3.将编译好的合约部署到网络。(这一步会消耗以太币,还需要使用你的节点的默认地址或者指定地址来给合约签名)=> 获得合约的区块链地址和ABI。(合约接口的JSON标识,包括变量,事件和可以调用的方法;ABI是合约接口的二进制标识)
4.用web3.js提供的JavaScript API来调用合约。(根据调用的类型有可能会消耗以太币)
安装以太坊的准备工作
如果你是首次接触ethereum,推荐使用下面的步骤安装部署。
1.安装ethereum
2.安装solc编译器
安装后可以使用geth命令创建ethereum账户
geth account new
3.Solidity语言支持
Browser-solidity提供了在线的Solidity语言测试。需要下载包括Solidity运行环境的安装包。
4.安装客户端Mist
官方提供钱包客户端Mist,支持进行交易,同时支持直接编写和部署智能合约。
所编写的代码编译发布后,可以部署到区块链上。使用者可通过Mist发送指令,调用相应交易合约,让以太坊虚拟机令(EVM) 在区块链上执行交易合约。
以太坊现在有多种语言实现的客户端,包括:
ethereumjs-lib: javascript语言实现
Ethereum(J): Java语言实现
ethereumH: Haskell语言实现
go-ethereum: go语言实现
Parity: Rust语言实现
pyethapp: python语言实现
ruby-ethereum: Ruby语言实现
在以太坊上编程时的注意事项
完成准备工作后,就可以着手开始编写属于自己的智能合约。在编写过程中,还有一些地方需要注意:
1.查看下验证节点能否正常运行。
在成功部署了一个智能合约后,输入数据时即可验证代码是否正常运行。
2.部署在其他节点上
为了使得其他人可以运行你的智能合约,你需要两个信息:
①智能合约地址Address。
②智能合约ABl (Appication Binary Interface)。ABI其实就是一个有序的用户手册,描述了所有方法的名字和如何调用它们。我们可以使用如下代码获得其ABI和智能合约地址 :
然后你可以实例化一个JavaScrip对象,该对象可以用来在任意联网机器上调用该合约,此处ABI 和Address是上述代码返回值。
3. 自毁程序
一个交易被发送到网络需要支付费用,自毁程序是对网络的补充,花费的费用远小于一次常用交易。你可以通过以下代码来检验是否成
功,如果自毁程序运行成功以下代码会返回0:
实例分析
我们在白皮书中可以看到,以太坊上有两种应用。
第一类是金融应用,为用户提供自费管理和参与合约的更强大方法。包括子货币、金融衍生品、对冲合约、储蓄钱包、遗嘱,甚至一些其他全面的雇佣合约。
第二类是半金融应用,这里有包含代币的存在,但也有很重要的非代币方面,比如为解决计算问题而设的自我强制悬赏。最后,还有在线投票和去中心化治理这样完全的非金融应用。
我们根据以太坊白皮书上所说的对冲合约,即一种金融衍生品,来进行代码编写。以下是白皮书上所举的一个例子: 等待A输入1000以太币; 等待B输入1000以太币; 通过查询数据提供合约,将价值1000以太币的等值美元,例如x美元,记录至存储器。
30天后,允许A或B“重新激活”合约以发送价值x美元的以太币(重新查询数据提供合约,以获取新价格并计算) 给A,并将剩余的以太币发送给B。
实现步骤如下:
1.确定进行交易的双方,包含双方地址,是否投票(默认为否),金额等数据。代码如下:
2.对双方进行初始化,首先每个账户内打入1000以太币; 确认交易后,将bool重新设定为true; 接着用一个storage保存相关地址以方便后面调用(如果没有amount而使用balance,将会使得storage无法调用); 最后两个账户之间的转账可以只用msg.sender (准备下次实现),目前只有将amount数值设定为0,来表示将1000ether转入对冲基金,在现实生活中则有很高的风险,是明显不可取的。代码如下:
3.实现对冲的第一步,将1000ether根据汇率转换成其他货币;
4.实现对冲的第二步,30天后再次转化回以太币。值得注意的是,使用了bool以防交易失败;
5.确定双方交易的金额;
通过这五步,一个简单的智能合约就建立起来了。注意,这个智能合约在转换汇率的时候用的是模型,这是一种理想状态,程序可以在Remix上完成调试。
所有代码组合起来如下:
以上代码就简单构成了一个智能合约——对冲合约,这个对冲合约还不够完善,还需要我们更加详细地引入函数和变量来优化它。
结语
智能合约的编写其实并不困难,但对于编写智能合约代码的逻辑和正确性需要认真对待。The DAO事件中,黑客就是利用了智能合约的漏洞,攻击了该智能合约,使合约内源源不断有以太币转账到黑客的账户,给以太坊和众筹投资者造成大量损失。
所以在编写智能合约方面,如果只是想学习下,那么请随意尝试,但如果是要实际应用智能合约,一定要注意其安全性和正确性。