找回密码
 立即注册

本文来自

电脑/上网

电脑/上网

订阅|关注

致力于提供软件新闻发布,和软件知识学习,包括常用软件应用技巧及评测,创意设计相关的图文及视频教程

动手编写一个以太坊智能合约

[复制链接]
240 448190058 发表于 2017-9-14 19:24:22
本文节选自图书《区块链开发指南》,本书由 申屠青春 主编,宋波、张鹏、汪晓明、季宙栋、左川民 联合编著。
区块链相关约稿、文章纠错、寻求报道等可邮件联系 jiawd@csdn.net
之前的章节中讲到了怎么写、部署合约以及与合约互动。现在该讲讲与以太坊网络和智能合约沟通的细节了。
一个以太坊节点提供一个RPC界面。这个界面给Dapp(去中心化应用)访问以太坊区块链的权限和节点提供的功能,比如编译智能合约代码,它用JSON-RPC 2.0规范(不支持提醒和命名的参数) 的子集作为序列化协议,在HTTP和IPC (linux/OSX上的unix域接口,在Windows上叫pipe’s)上可用。
数字是十六进制编码。做这个决定是因为有些语言对运行极大的数字没有或有很少的限制。为了防止这些错误数字类型是十六进制编码,由开发者来分析这些数字并正确处理它们。在维基页百科查看十六进制编码章节查看案例。
默认区块数字。几个RPC 方法接受区块数字。在一些情况下,给出区块数字是不可能的或者不太方便。在那样的情况下,默认区块数字可以是以下字符串中的一个[”earliest”, “latest”, “pending”]。在维基页面可查看使用默认区块参数的RPC方法列表。
要做的第一件事是确保HTTP RPC界面可用。这意味着我们在开始为geth供应—rpc标志,为eth提供-j标志。在这个例子中,用的是私有开发链上的geth节点。通过这种方法,我们就不需要真实网络上的以太币了。
这会在http://localhost:8545上启动HTTP RPC界面。
注意:geth支持CORS查看—rpccorsdomain标志了解更多。
我们可以通过用curl检索coinbase地址和余额来证明界面正在运行。请注意这些例子中的数据在你本地的节点上会有所不同。如果你想要试试这些参数,视情况替换需要的参数。
\ curl --data '{"jsonrpc":"2.0","method":"eth_coinbase", "id":1}' localhost:8545
{"id":1,"jsonrpc":"2.0","result":["0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a"]}
curl --data '{"jsonrpc":"2.0","method":"eth_getBalance", "params": ["0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a"], "id":2}' localhost:8545
{"id":2,"jsonrpc":"2.0","result":"0x1639e49bba16280000"}
记不记得前面说过数字是十六进制编码?在这个情况下,余额作为十六进制字符串以Wei的形式返还。如果希望余额作为数字以太币为单位,可以从控制台用web3,示例如下:
现在我们在私有开发链上有一些以太币,就可以部署合约了。第一步是验证solidity编译器可用,可以用eth_getCompilers RPC method方法来检索可用的编译器,示例如下:
\ curl --data '{"jsonrpc":"2.0","method": "eth_getCompilers", "id": 3}' localhost:8545
{"id":3,"jsonrpc":"2.0","result":["Solidity"]}
我们可以看到solidity编译器可用。
下一步是把Multiply7合约编译到可以发送给以太坊虚拟机的字节代码中,示例如下:
\ curl --data '{"jsonrpc":"2.0","method": "eth_compileSolidity", "params": ["contract Multiply7 { event Print(uint); function multiply(uint input) returns (uint) { Print(input
{"id":4,"jsonrpc":"2.0","result":{"Multiply7":{"code":"0x6060604052605f8060106000396000f360606040
现在我们有了编译代码,需要决定花多少gas去部署它。RPC界面有eth_estimateGas方法,会给我们一个预估数量,如下:
\ curl --data '{"jsonrpc":"2.0","method": "eth_estimateGas", "params": [{"from": "0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a", "data": "0x6060604052605f8060106000396000f3606060405260e060020a6000350463c6888fa18114601a575b005b60586004356007810260609081526000907f24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da90602090a15060070290565b5060206060f3"}], "id": 5}' localhost:8545
{"id":5,"jsonrpc":"2.0","result":"0xb8a9"}
最后部署合约。
\ curl --data '{"jsonrpc":"2.0","method": "eth_sendTransaction", "params": [{"from": "0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a", "gas": "0xb8a9", "data": "0x6060604052605f8060106000396000f3606060405260e060020a6000350463c6888fa18114601a575b005b60586004356007810260609081526000907f24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da90602090a15060070290565b5060206060f3"}], "id": 6}' localhost:8545
{"id":6,"jsonrpc":"2.0","result":"0x3a90b5face52c4c5f30d507ccf51b0209ca628c6824d0532bcd6283df7c08
交易由节点接受,交易散表被返还。我们可以用这个散表来跟踪交易。
下一步是决定部署合约的地址。每个执行的交易都会创建一个接收。这个接收包含交易的各种信息,比如交易被包含在哪个区块,以太坊虚拟机用掉多少gas。如果交易创建了一个合约,它也会包含合约地址。我们可以用eth_getTransactionReceipt RPC方法检索接收,示例如下:
\ curl --data '{"jsonrpc":"2.0","method": "eth_getTransactionReceipt", "params": ["0x3a90b5face52c4c5f30d507ccf51b0209ca628c6824d0532bcd6283df7c08a7c"], "id": 7}' localhost:8545
{"id":7,"jsonrpc":"2.0","result":{"transactionHash":"0x3a90b5face52c4c5f30d507ccf51b0209ca628c682
可以看到,合约在0x6ff93b4b46b41c0c3c9baee01c255d3b4675963d上被创建。如果你得到了零而不是接收,说明还没有被纳入区块。这时,要检查看看你的矿工是否在运行,然后重新试一遍。
现在已经部署了合约,我们可以和它互动了。有两种方法进行互动,即发送交易或调用。在本节的例子中,将会发送交易到合约的multiply方法里。
在我们的实例中,需要具体说明from、to 和data参数。From是我们账户的公共地址,to是合约地址,Data参数有一点复杂,它包括了规定调用哪个方法和哪个参数的负载量。这就需要ABI发挥作用了,ABI规定了如何为以太坊虚拟机规定和编码数据。
负载量的字节是功能选择符,规定了调用哪个方法。它取Keccak散表的头4个字节,涵盖功能名称参数类型,并进行十六进制编码。multiply功能接受一个参数。示例如下:
下一步是编码参数。我们只有一个unit256,假定提供了值6。ABI有一个章节规定了编码uint字节的方法,如下:
int M : enc(X) is the big-endian two’s complement encoding of X, padded on the higher-oder (left) side with 0xff for negative X and with zero 字节s for positive X such that the length is a multiple of 32 bytes.
它会编码到
0000000000000000000000000000000000000000000000000000000000000006。
将功能选择符和编码参数结合起来,数据就会变成0xc6888fa10000000000000000000000000000000000000000000000000000000000000006。
我们来试一下:
\ curl --data '{"jsonrpc":"2.0","method": "eth_sendTransaction", "params": [{"from": "0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a", "to": "0x6ff93b4b46b41c0c3c9baee01c255d3b4675963d", "data": "0xc6888fa10000000000000000000000000000000000000000000000000000000000000006"}], "id": 8}' localhost:8545
{"id":8,"jsonrpc":"2.0","result":"0x759cf065cbc22e9d779748dc53763854e5376eea07409e590c990eafc0869
由于我们发送了交易,于是有交易散表返回。如果检索接收,可以看到一些新内容,如下:
blockHash: "0xbf0a347307b8c63dd8c1d3d7cbdc0b463e6e7c9bf0a35be40393588242f01d55",
blockNumber: 268,
contractAddress: null,
cumulativeGasUsed: 22631,
gasUsed: 22631,
logs: [{
address: "0x6ff93b4b46b41c0c3c9baee01c255d3b4675963d",
blockHash: "0xbf0a347307b8c63dd8c1d3d7cbdc0b463e6e7c9bf0a35be40393588242f01d55",
blockNumber: 268,
data: "0x000000000000000000000000000000000000000000000000000000000000002a",
logIndex: 0,
topics: ["0x24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da"],
transactionHash: "0x759cf065cbc22e9d779748dc53763854e5376eea07409e590c990eafc0869d74",
transactionIndex: 0
transactionHash: "0x759cf065cbc22e9d779748dc53763854e5376eea07409e590c990eafc0869d74",
transactionIndex: 0
}
接收包含一个日志。日志由以太坊虚拟机在交易执行时生成,包含接收。如果我们看Multiply功能,可以看到打印事件和输入次数7一起被提出。由于打印事件的参数是uint256,因此可以根据ABI规则对它进行编码,这样就会得到预期的十进制42。
\ web3.sha3("Print(uint256)")
"24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da"
这只是对一些最常见任务的简单介绍。在RPC维基页面查看可用RPC方法的完整列表。
正如在之前的案例所见,使用JSON-RPC界面相当单调乏味且容易出错,尤其是在处理ABI的时候。Web3.js是Javascript库,它的目标是提供更友好的界面,减少出错机会。
用web3部署Multiply7合约看起来是这样:
var source = 'contract Multiply7 { event Print(uint); function multiply(uint input) returns (uint) { Print(input
var compiled = web3.eth.compile.solidity(source);
var code = compiled.Multiply7.code;
var abi = compiled.Multiply7.info.abiDefinition;
web3.eth.contract(abi).new({from: "0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a", data: code}, function (err, contract) {
if (!err contract.address)
console.log("deployed on:", contract.address);
deployed on: 0x0ab60714033847ad7f0677cc7514db48313976e2
装载一个部署的合约,发送交易:
var source = 'contract Multiply7 { event Print(uint); function multiply(uint input) returns (uint) { Print(input
var compiled = web3.eth.compile.solidity(source);
var Multiply7 = web3.eth.contract(compiled.Multiply7.info.abiDefinition);
var multi = Multiply7.at("0x0ab60714033847ad7f0677cc7514db48313976e2")
multi.multiply.sendTransaction(6, {from: "0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a"})
注册一个回调,打印事件创建日志的时候会被调用。
multi.Print(function(err, data) { console.log(JSON.stringify(data)) })
{"address":"0x0ab60714033847ad7f0677cc7514db48313976e2","args": {"":"21"},"blockHash":"0x259c7dc0
在web3.js维基页面可查看更多信息。
geth控制台提供命令行界面和Javascript执行时间。它可以连接到本地或远程的geth或eth节点。它会装载用户能使用的web3.js库,从而方便用户从控制台通过web3.js部署智能合约,并和智能合约互动。实际上Web3.js章节的例子可以被复制进控制台并且调用。
以太坊是区块链开发领域最好的编程平台,而truffle是以太坊(Ethereum)最受欢迎的一个开发框架,这也是介绍truffle的原因。实战是最重要的事情,这篇文章不讲原理,只搭建环境,运行第一个区块链程序(Dapp)。
1. 安装truffle
安装truffle的命令如下:
可用的系统包括:Windows、Linux和Mac OS X,推荐Mac OS X,不建议使用Windows,会碰到各种各样的问题,很可能导致放弃。首先,访问https://nodejs.org 官方网站下载安装NodeJS。
此外,需要安装Ethereum客户端,来支持JSON RPC API调用。
至于开发环境,推荐使用EthereumJS TestRPC,地址为: https://github.com/ethereumjs/testrpc
安装命令如下:
$ npm install -g ethereumjs-testrpc
3. 新建第一个项目
通过以下命令新建一个项目:


图5-3 项目的目录结构
项目所有文件的目录如图5-4所示。


图5-4 项目文件目录目录结构
现在,通过以下命令编译项目。
图5-5是运行以上命令后的结果。


图5-5 Truffle compile执行结果图
下面介绍部署项目的方式。
部署之前先启动TestRPC,命令如下:
$ testrpc
$ truffle deploy(在Truffle 2.0以上版本中,命令变成了:truffle migrate)
图5-6是运行truffle deploy后的结果。


图5-6 truffle deploy执行结果图
$ truffle migrate migrate的执行结果见图5-7。


图5-7 truffle migrate migrate执行结果图
现在,可以启动服务了,命令如下:


图5-8 truffle serve执行结果图
启动服务后,可以在浏览器访问项目了,地址是:http://localhost:8080/ ,网页界面如图5-9所示。


图5-9智能合约运行界面
好了,第一个区块链程序跑起来了,后面可以不断地实践深入学习了。

区块链开发(三)编写调试第一个以太坊智能合约
李赫 2016年9月10日
一、 智能合约IDE简介
目前以太坊上支持三种语言编写智能合约,
Solidity:类似JavaScript,这是以太坊官方推荐语言,...
如何成为一名机器学习的大咖? 对于机器学习,很多人的观点是:机器学习技术是今后所有技术人员都绕不过的一个门槛。 那么,普通程序员该学习机器学作为一名对机器学习心有向往的程序员,我该以什么样的姿势开始呢?
以太坊(3):以太坊私有链环境下的智能合约的编写、编译、创建与执行
在以太坊(1):在CentOS
6.5上搭建以太坊私有链的步骤 中我们搭建了以太坊的私有链,在 以太坊(2):以太坊私有链环境下的账户管理、挖矿与转账 中演示了普通账户的创建、挖矿与转账操作,但实...
以太坊智能合约编程之菜鸟教程
手把手带你走上智能合约编程之路
译注:原文首发于ConsenSys开发者博客,原作者为Eva以及ConsenSys的开发团队。如果您想要获取更多及时信息,可以访问ConsenSys首页点击左下角New...
一步一步学区块链(2)工具和技术的介绍
有了第一篇的区块链概念的大致了解,我们可以开始真正的学习区块链之旅。
要说区块链技术那么必须说以太坊,区块链技术通过上一篇的了解可以知道,它是支撑比特币的一个底层技术架构,随后被提取和抽象。以太坊将区...

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
温馨提示:
1、在论坛里发表的文章仅代表作者本人的观点,与本网站立场无关。
2、论坛的所有内容都不保证其准确性,有效性,时间性。阅读本站内容因误导等因素而造成的损失本站不承担连带责任。
3、若因线路及非本站所能控制范围的故障导致暂停服务期间造成的一切不便与损失,论坛不负任何责任。
4,本网站内容均摘自其他网站,如涉及侵权定当第一时间删除
5、如侵犯您的权益请联系936144721@qq.com



上一篇:狗粮
下一篇:前一方高层辟谣换队名说:没接受过采访 我躺枪了
转载请说明出处,本文地址:http://bbs.imicun.com/thread-15470743-1-1.html
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表