zoukankan      html  css  js  c++  java
  • 如何部署、调用智能合约

    RPC

    之前的章节中我们看到了怎么写、部署合约以及与合约互动。现在该讲讲与以太坊网络和智能合约沟通的细节了。

    一个以太坊节点提供一个RPC界面。这个界面给Ðapp访问以太坊区块链的权限和节点提供的功能,比如编译智能合约代码,它用JSON-RPC 2.0规范(不支持提醒和命名的参数) 的子集作为序列化协议,在HTTP和IPC (linux/OSX上的unix域接口,在Windows上叫pipe’s)上可用。

    如果你对细节不感兴趣,正在寻找使用javascript库的简便方法,你可以略过下面的章节,从Using Web3继续。

    惯例

    RPC界面使用一些惯例,它们不是JSON-RPC 2.0规范的一部分:

    • 数字是十六进制编码。做这个决定是因为有些语言对运行极大的数字没有或有很少的限制。为了防止这些错误数字类型是十六进制编码,由开发者来分析这些数字并正确处理它们。在维基页百科查看十六进制编码章节查看案例。
    • 默认区块数字,几个RPC 方法接受区块数字。在一些情况下,给出区块数字是不可能的或者不太方便。 在那样的情况下,默认区块数字可以是以下字符串中的一个[”earliest”, “latest”, “pending”]。在维基页面查看使用默认区块参数的RPC方法列表。

    部署合约

    我们会通过不同的步骤来部署下面的合约,只用到RPC界面。

    1
    2
    3
    4
    5
    6
    7
    
    contract Multiply7 {
       event Print(uint);
       function multiply(uint input) returns (uint) {
          Print(input * 7);
          return input * 7;
       }
    }

    要做的第一件事是确保HTTP RPC界面可用。这意味着我们在开始为geth供应—rpc标志,为eth提供-j标志。在这个例子中我们用私有开发链上的geth节点。通过这种方法,我们就不需要真实网络上的以太币了。

    1
    
    > geth --rpc --dev --mine --minerthreads 1 --unlock 0 console 2>>geth.log

    这会在http://localhost:8545 上启动HTTP RPC界面。

    注意:geth支持CORS查看—rpccorsdomain标志了解更多。

    我们可以通过用curl检索coinbase地址和余额来证明界面正在运行。请注意这些例子中的数据在你本地的节点上会有所不同。如果你想要试试这些参数,视情况替换需要的参数。

    1
    2
    3
    4
    
    > 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。

    1
    2
    
    > web3.fromWei("0x1639e49bba16280000", "ether")
    "410"

    现在我们在私有开发链上有一些以太币,我们就可以部署合约了。第一步是验证solidity编译器可用。我们可以用eth_getCompilers RPC method方法来检索可用的编译器。

    1
    2
    
    > curl --data '{"jsonrpc":"2.0","method": "eth_getCompilers", "id": 3}' localhost:8545
    {"id":3,"jsonrpc":"2.0","result":["Solidity"]}

    我们可以看到solidity编译器可用。如果不可用,按照这些说明操作。

    下一步是把Multiply7合约编译到可以发送给以太坊虚拟机的字节代码。

    1
    2
    
    > 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方法,会给我们一个预估数量。

    1
    2
    
    > curl --data '{"jsonrpc":"2.0","method": "eth_estimateGas", "params": [{"from": "0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a", "data": "0x6060604052605f8060106000396000f3606060405260e060020a6000350463c6888fa18114601a575b005b60586004356007810260609081526000907f24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da90602090a15060070290565b5060206060f3"}], "id": 5}' localhost:8545
    {"id":5,"jsonrpc":"2.0","result":"0xb8a9"}

    最后部署合约。

    1
    2
    
    > 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方法检索接收。

    1
    2
    
    > curl --data '{"jsonrpc":"2.0","method": "eth_getTransactionReceipt", "params": ["0x3a90b5face52c4c5f30d507ccf51b0209ca628c6824d0532bcd6283df7c08a7c"], "id": 7}' localhost:8545
    {"id":7,"jsonrpc":"2.0","result":{"transactionHash":"0x3a90b5face52c4c5f30d507ccf51b0209ca628c682

    我们可以看到合约在0x6ff93b4b46b41c0c3c9baee01c255d3b4675963d上被创建。如果你得到了零而不是接收,说明还没有被纳入区块。等一下,检查看看你的矿工是否在运行,重新试一遍。

    和智能合约互动

    现在已经部署了合约,我们可以和它互动了。有两种方法,发送交易或像之前所介绍的那样使用调用。在这个例子中,我们会发送交易到合约的multiply方法。

    如果我们看eth_sendTransaction 的档案,可以发现我们需要提供几个参数。

    在我们的实例中,需要具体说明from, to 和data参数。From是我们账户的公共地址,to是合约地址。Data参数有一点困难。它包括了规定调用哪个方法和哪个参数的负载量。这就需要ABI发挥作用了。ABI规定了如何为以太坊虚拟机规定和编码数据。你可以在这儿阅读ABI的所有具体信息。

    负载量的字节是功能选择符,规定了调用哪个方法。它取Keccak散表的头4个字节,涵盖功能名称参数类型,并进行十六进制编码。multiply功能接受一个单元,也就是uint256的别名。这就让我们进行:

    1
    2
    
    > web3.sha3("multiply(uint256)").substring(0, 8)
    "c6888fa1"

    在此页查看细节。

    下一步是编码参数。我们只有一个unit256,让我们假定提供了值6。ABI有一个章节规定了怎么编码uint字节。

    int: 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.

    我们来试一下:

    1
    2
    
    > 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

    由于我们发送了交易,于是有交易散表返回。如果我们检索接收,可以看到一些新内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    {
    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.。除数据外,主题用于决定什么事件来创建日志,是毫无意义的:

    1
    2
    
    > web3.sha3("Print(uint256)")
    "24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da"

    你可以在Solidity教程中阅读更多关于事件,主题和索引的内容。

    这只是对一些最常见任务的简单介绍。在RPC维基页面查看可用RPC方法的完整列表。

    Web3.js

    正如我们在之前的案例所见,使用JSON-RPC界面相当单调乏味且容易出错,尤其是在处理ABI的时候。Web3.js是javascript库,在以太坊RPC界面顶端。它的目标是提供更友好的界面,减少出错机会。

    用web3部署Multiply7合约看起来是这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    var source = 'contract Multiply7 { event Print(uint); function multiply(uint input) returns (uint
    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}, func
       if (!err && contract.address)
          console.log("deployed on:", contract.address);
       }
    );
    deployed on: 0x0ab60714033847ad7f0677cc7514db48313976e2

    装载一个部署的合约,发送交易:

    1
    2
    3
    4
    5
    
    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"})

    注册一个回调,打印事件创建日志的时候会被调用。

    1
    2
    
    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章节的例子可以被复制进控制台。

    查看合约与交易

    有几个可用的在线区块链浏览器,能让你查询以太坊区块链。

    查看列表:区块链浏览器。

    在线区块链浏览器

    • EtherChain
    • EtherCamp
    • EtherScan (为测试网)

    其他资源

    • EtherNodes – 节点的地理分配,由客户端区分
    • EtherListen – 实时以太坊交易可视器和可听器
  • 相关阅读:
    oracle 数据库服务名怎么查
    vmware vsphere 6.5
    vSphere虚拟化之ESXi的安装及部署
    ArcMap中无法添加ArcGIS Online底图的诊断方法
    ArcGIS中字段计算器(高级计算VBScript、Python)
    Bad habits : Putting NOLOCK everywhere
    Understanding the Impact of NOLOCK and WITH NOLOCK Table Hints in SQL Server
    with(nolock) or (nolock)
    What is “with (nolock)” in SQL Server?
    Changing SQL Server Collation After Installation
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13313417.html
Copyright © 2011-2022 走看看