目录

5.4 编译合约

优质
小牛编辑
123浏览
2023-12-01

编译合约

合约以Ethereum特有的二进制格式(Ethereum Virtual Machine(= EVM)字节码)生成在blockchain上。然而,合约通常用更高级的语言来写,如solidity,然后编译成将被上传至blockchain的字节码。

对于Frontier版本,geth通过系统调用solc来支持solidity编译,它是Christian R.和Lefteris K写的命令行solidity 编译器。您可以尝试Solidity实时编译器(Christian R)或CosmoMix

如果你想启动你的geth节点,你可以先检查下solidity编译器是否可用,假如不可用,则会出现下面的情况:

> eth.compile.solidity("")
eth_compileSolidity method not available: solc (solidity compiler) not found
    at InvalidResponse (<anonymous>:-57465:-25)
    at send (<anonymous>:-115373:-25)
    at solidity (<anonymous>:-104109:-25)
    at <anonymous>:1:1

找到一种方式安装solc后,确保它在路径中。如果eth.getCompilers()仍然找不到(返回一个空数组),您可以在命令行上使用solc标志设置solc可执行文件的自定义路径。

geth --datadir ~/frontier/00 --solc /usr/local/bin/solc --natspec

您还可以通过控制台在运行时设置此选项:

> admin.setSolc("/usr/local/bin/solc")
solc v0.9.32
Solidity Compiler: /usr/local/bin/solc
Christian <c@ethdev.com> and Lefteris <lefteris@ethdev.com> (c) 2014-2015
true

下面我们使用简单的智能合约作例子:

> source = "contract test { function multiply(uint a) returns(uint d) { return a * 7; } }"

这个合同提供了一个一元的方法:一个正整数a传入并调用,它返回a * 7

您可以geth使用eth.compile.solidity在JS控制台中编译solidity代码:

> contract = eth.compile.solidity(source).test
{
  code: '605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056',
  info: {
    language: 'Solidity',
    languageVersion: '0',
    compilerVersion: '0.9.13',
    abiDefinition: [{
      constant: false,
      inputs: [{
        name: 'a',
        type: 'uint256'
      } ],
      name: 'multiply',
      outputs: [{
        name: 'd',
        type: 'uint256'
      } ],
      type: 'function'
    } ],
    userDoc: {
      methods: {
      }
    },
    developerDoc: {
      methods: {
      }
    },
    source: 'contract test { function multiply(uint a) returns(uint d) { return a * 7; } }'
  }
}

编译器也可以通过RPC调用,因此 借助RPC/IPC,也可以在连接至geth的浏览器内置Dapp中通过web3.js调用.

以下示例显示了如何通过JSON-RPC连接geth以使用编译器。

./geth --datadir ~/eth/ --loglevel 6 --logtostderr=true --rpc --rpcport 8100 --rpccorsdomain '*' --mine console  2>> ~/eth/eth.log
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_compileSolidity","params":["contract test { function multiply(uint a) returns(uint d) { return a * 7; } }"],"id":1}' http://127.0.0.1:8100

一个源文件的编译器输出将为您提供表示单个合约的合约对象。eth.compile.solidity的实际返回值是合约名称 - 合约对象对的映射。由于我们的合同名称是testeth.compile.solidity(source).test将为您提供包含以下字段的test合约的合约对象:

编译器输出的直接结构(codeinfo)反映了两个非常不同的部署路径。编译的EVM代码通过合同创建事务发送到块链,而其余的(info)将理想地像云一样分散分布,作为可公开验证的元数据补充块上的代码。

如果您的源包含多个合约,则输出将包含每个合约的条目,可以使用合约名称作为属性名称检索相应的合约信息对象。您可以通过检查最新的GlobalRegistrar代码来尝试这一点:

contracts = eth.compile.solidity(globalRegistrarSrc)