C 在 Oracle Blockchain Platform 上使用 EVM 运行 Solidity 智能合同

您可以使用 Oracle Blockchain Platform 上作为链代码部署的以太坊虚拟机 (Ethereum Virtual Machine,EVM) 运行 Solidity 智能合同。

EVM 在以太坊网络中运行 Solidity 智能合约。EVM 是通过 Hyperledger Burrow 项目创建的,并集成到 Hyperledger Fabric 中。通过此项目,您可以使用 Hyperledger Fabric 许可的区块链平台与以 EVM 兼容语言(例如 Solidity)编写的以太坊智能合同进行交互。

以下步骤概述了在预配的 Oracle Blockchain Platform 上运行 Solidity 智能合同的过程:
  1. Oracle Blockchain Platform 控制台下载 EVM 链代码包。
  2. 在渠道中部署 EVM 链代码。
  3. 使用 Remix IDE 为 Solidity 智能合约生成字节码。
  4. 将智能合同字节码部署到部署的 EVM 链代码中。使用从部署返回的地址发送事务处理。
本主题中的步骤已通过 Oracle Blockchain Platform 控制台提供的 EVM 链代码程序包进行了测试,可能无法与其他发行版一起使用。

注意:

如果您的链代码以前安装在 Hyperledger Fabric v1.4.7 实例上,则当您的实例升级到 Hyperledger Fabric v2.x 时,链代码应继续按预期工作。

下载 EVM 链代码和 Fab3 程序包

Oracle Blockchain Platform 控制台的 Developer Tools(开发人员工具)选项卡中,打开应用开发窗格,然后单击 Download the EVM chaincode package(下载 EVM 链代码包)。您必须是管理员用户才能下载该文件。

Oracle Blockchain Platform 上部署 EVM 链代码

下载 EVM 链代码包后,将其部署在 Oracle Blockchain Platform 上。

  1. 登录 Oracle Blockchain Platform 控制台。
  2. Chaincodes 选项卡上,单击 Deploy a New Chaincode
  3. 选择快速部署,然后输入以下信息:
    • 程序包标签:输入链代码程序包的说明。
    • Chaincode Language(链代码语言):GoLang。
    • 链代码名称:输入链代码的名称。例如,输入 soliditycc
    • 版本:v1
    • Init-required:不选中此项。
    • 渠道:选择要安装链代码的渠道。
    • 是否为打包链代码:不选中此项。
    • Chaincode source(链代码源):上载您以前下载的 evmcc.zip 软件包。
    有关“快速部署”向导的更多详细信息以及对程序包标签链代码名称等字段的限制,请参阅:使用快速部署

提交信息后,EVM 链代码将在 Chaincodes 选项卡中可见,并作为已部署链代码在您选择安装它的每个通道上列出。

创建和编译 Solidity 智能合约

  1. 打开基于浏览器的 Remix IDE:https://remix.ethereum.org/
  2. 如果您已经编写了 Solidity 智能合约,请将其导入 Remix。
  3. 如果您没有编写 Solidity 智能合约,请在 Remix 中创建 Solidity 文件 (.sol),然后执行以下操作之一:
    • 如果你熟悉 Solidity,你可以创建自己的智能合约文件。
    • 您可以使用 Solidity 文档中提供的 Simple Storage 示例代码: Solidity:Introduction to Smart Contracts
    • 可以使用用于此示例的示例代码,该代码将 string name 作为输入,并使用 set(name)get() 输出与输出字符串相同:
      pragma solidity ^0.4.0;
      contract Myname {
          string public yourName;
      
          function set(string name) public {
              yourName = name;
          }
          function get() public view returns (string) {
              return yourName;
          }
      }
      
    您可能会看到有关默认编译器版本与智能合同中指定的版本不匹配的错误消息。
  4. 编译您的智能合约。在 Remix 中打开 Solidity Compiler 面板,确保打开智能合约选项卡以将其选为正在编译的文件,并将编译器版本设置为最新的 4。X 版本,然后单击编译。
    Remix Compiler 视图中测试 Solidity 智能合约的屏幕截图。

  5. 编译文件后,单击 Bytecode 图标将字节码作为 JSON 文档复制到剪贴板。
  6. 将复制的字节码粘贴到文本编辑器中并保存。

部署智能合同

在复制的字节码中,您需要的部分是 "object" 字段。这是示例智能合同的 EVM 字节码。
"object": "608060405234801561001057600080fd5b50610410806100206000396000f30060
8060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463
ffffffff1680634ed3885e1461005c5780636d4ce63c146100c5578063d97d663014610155575b600080fd5b34801561
006857600080fd5b506100c3600480360381019080803590602001908201803590602001908080601f01602080910402
602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506101
e5565b005b3480156100d157600080fd5b506100da6101ff565b60405180806020018281038252838181518152602001
91508051906020019080838360005b8381101561011a5780820151818401526020810190506100ff565b505050509050
90810190601f1680156101475780820380516001836020036101000a031916815260200191505b509250505060405180
910390f35b34801561016157600080fd5b5061016a6102a1565b60405180806020018281038252838181518152602001
91508051906020019080838360005b838110156101aa57808201518184015260208101905061018f565b505050509050
90810190601f1680156101d75780820380516001836020036101000a031916815260200191505b509250505060405180
910390f35b80600090805190602001906101fb92919061033f565b5050565b6060600080546001816001161561010002
03166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615
6101000203166002900480156102975780601f1061026c57610100808354040283529160200191610297565b82019190
6000526020600020905b81548152906001019060200180831161027a57829003601f168201915b505050505090509056
5b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190
818152602001828054600181600116156101000203166002900480156103375780601f1061030c576101008083540402
83529160200191610337565b820191906000526020600020905b81548152906001019060200180831161031a57829003
601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f01
6020900481019282601f1061038057805160ff19168380011785556103ae565b828001600101855582156103ae579182
015b828111156103ad578251825591602001919060010190610392565b5b5090506103bb91906103bf565b5090565b61
03e191905b808211156103dd5760008160009055506001016103c5565b5090565b905600a165627a7a72305820a990d4
0b57c66329a32a18e847b3c18d6c911487ffadfed2098e71e8cafa0c980029",
一般来说,EVM 需要两个参数:
  • to 地址。
  • 以太坊交易中必需的 input

要部署智能合同,to 字段是零地址,input 是合同的已编译 EVM 字节码。因此,向 invoke 命令提供了两个参数。第一个通常应该是链码内部的函数名,现在是 0000000000000000000000000000000000000000,第二个参数是 Solidity 智能合约字节码。

  1. 要在 Oracle Blockchain Platform 上部署 Solidity 智能合同,您可以调用以下 REST 代理,将两个参数发送到 EVM。
    {
        "chaincode": "<evmcc-ccid>",
        "args": [
            "0000000000000000000000000000000000000000",
            "<bytecode-of-the-smart-contract>"
        ],
        "timeout": 0,
        "sync": true
    }
    以下示例使用 cURL 将 Solidity 智能合同部署到名为 solidityccOracle Blockchain Platform
    curl -L -X POST 'https://<hostname>:7443/restproxy/api/v2/channels/<channelname>/transactions' \
    -H 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' \
    -H 'Content-Type: application/json' \
    --data-raw '{"chaincode":"<evmcc-ccid>","args":["0000000000000000000000000000000000000000","<bytecode-of-the-smart-contract>"],"timeout":0,"sync":true}'
  2. 事务处理的响应 payload 是已部署合同的合同地址。复制此地址并保存。运行智能合同功能时,将使用合同地址。
    API 调用和响应的屏幕抓图,其中显示有效负载响应字段中的智能合同地址。
    在此示例中,智能合同地址为 66b92979bb66d645371b3247177e4b2513cb9834
与部署的智能合同交互的方法有两种:
  1. 通过使用方法和输入参数的散列值。
  2. 直接使用方法名称和输入参数。

使用散列值与智能合同交互

拥有智能合同地址后,您可以使用以下调用通过 REST 代理与部署的智能合同进行交互。

要执行函数,可以使用调用和查询事务处理,但使用不同的参数。示例合同包含两个函数:getset

在这些事务中,to 字段是合同地址,input 字段是与任何必需参数连接的函数执行散列。

您需要获取函数执行的散列才能运行事务处理。这样做的一个简单方法是执行 Remix IDE 中的函数,然后从事务日志中复制散列:

  1. 在 Remix IDE 中,打开 Deploy and Run Transactions(部署并运行事务处理)面板。确保在合同字段中选择了合同,然后单击部署
    即将部署的 Solidity 合同的屏幕抓图。

    部署完成后,合同应列在部署的合同列表中。
  2. 部署的合同列表中展开合同。将列出智能合同功能。
  3. 运行事务处理。对于提供的示例,输入 oracle ,然后单击 set
  4. “终端”窗口显示事务处理日志。如果事务处理日志已最小化,请单击日志展开它们。通过单击 input 字段旁边的图标,复制该字段的值(即函数执行散列)。将此值保存到与合同地址相同的位置,删除前导 0x
    “部署”页的屏幕抓图,其中显示已完成的事务处理和字段值,并指向包含函数执行散列值的输入字段。

  5. 在函数执行散列和合同地址之后,您可以使用散列和地址作为原始数据参数在 Oracle Blockchain Platform 上运行集事务处理。
    
    --data-raw '{"chaincode":"<chaincodename>","args":["<contractaddress>","<setfunctionexecutionhash>"]}'
    
    例如,使用 cURL:
    curl -L -X POST 'https://<hostname>:7443/restproxy/api/v2/channels/<channelname>/transactions' \
    -H 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' \
    -H 'Content-Type: application/json' \
    --data-raw '{"chaincode":"soliditycc","args":["66b92979bb66d645371b3247177e4b2513cb9834","4ed3885e000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000066f7261636c650000000000000000000000000000000000000000000000000000"]}'
    
  6. 打开 Oracle Blockchain Platform 控制台,检查事务处理是否列在分类账中。

要使用智能合约的 get 函数运行另一个事务(如查询),您可以在 Remix 中生成函数执行散列,然后将其与合同地址结合:

  1. 部署和运行事务处理面板上的混音中,确保您的合同仍列在部署的合同下。如果没有,则重新部署。
  2. 单击 get 。与使用 set 事务一样,从事务中检索并保存输入,删除前导 0x
    Remix 中 get 事务处理的屏幕捕获,说明输入字段包含所需的函数执行散列。

  3. 您可以使用此事务处理散列和合同地址针对 Oracle Blockchain Platform 上部署的链代码运行查询事务处理。
    
    --data-raw '{"chaincode":"<chaincodename>","args":["<contractaddress>","<getfunctionexecutionhash>"]}'
    
    例如,在 cURL 中:
    curl -L -X POST 'https://<hostname>:7443/restproxy/api/v2/channels/<channelname>/chaincode-queries' \
    -H 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' \
    -H 'Content-Type: application/json' \
    --data-raw '{"chaincode":"soliditycc","args":["66b92979bb66d645371b3247177e4b2513cb9834","6d4ce63c"]}'
    
    返回的有效负载将包含要查询的资产 - 在示例中为字符串 oracle

以下示例有效负载说明了使用以十六进制格式编码的输入发送事务处理的另一种方式。

{
    "chaincode": "<evmcc-ccid>",
    "args": [
        "<smart-contract-address>",
        "<hexadecimal-encoded-method-and-input-parameters>"
    ],
    "sync": true
}

使用方法名称与智能合同交互

使用可选的 setAbi 方法设置应用程序二进制接口 (Application Binary Interface,ABI) 规范,该规范允许您以可读(非十六进制编码)格式而非字节码发送输入和获取输出。在 Remix IDE 的 Solidity Compiler 面板上单击 ABI 图标( Bytecode 图标旁边)以获取 ABI 规范。可读输入格式支持以下输入类型:uintstringaddress booluint[]string[]address[]fab3 代理不支持在实施方法覆盖和方法重载的智能合同上运行事务处理,仅支持从 REST 代理运行事务处理。以下示例有效负载使用 setAbi 方法设置 ABI 规范。

{
    "chaincode": "<evmcc-ccid>",
    "args": [
        "setABI",
        "<smart-contract-address>",
        "<abi-spec-of-smart-contract>" --> use the string format of the abi specification
    ],
    "sync": true
}

您还可以直接使用方法名称和输入参数进行调用,如以下示例有效负载中所示。

{
    "chaincode": "<evmcc-ccid>",
    "args": [
        "<smart-contract-address>",
        "<smart-contract-method-name>",
		"[<array-of-input-parameters>]", --> empty array if there are no input parameters.
		"[<string-array-of-input-types>]" --> this is optional and is needed when there is method overriding in the smart contract.
    ],
    "sync": true
}

配置气体金额

您可以使用 setGasAmountgetGasAmount 方法配置气量,如以下有效负载样例中所示。

{
    "chaincode": "<evmcc-ccid>",
    "args": [
        "setGasAmount",
        "<gas-amount>"
    ],
    "sync": true
}
{
    "chaincode": "<evmcc-ccid>",
    "args": [
        "getGasAmount"
    ],
    "sync": true
}