5.4 编译合约
编译合约
合约以Ethereum特有的二进制格式(Ethereum Virtual Machine(= EVM)字节码)生成在blockchain上。然而,合约通常用更高级的语言来写,如solidity,然后编译成将被上传至blockchain的字节码。
对于Frontier版本,geth
通过系统调用solc
来支持solidity编译,它是Christian R.和Lefteris K写的命令行solidity 编译器。您可以尝试Solidity实时编译器(Christian R)或Cosmo或Mix。
如果你想启动你的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
的实际返回值是合约名称 - 合约对象对的映射。由于我们的合同名称是test
,eth.compile.solidity(source).test
将为您提供包含以下字段的test
合约的合约对象:
code
: 编译过的EVM码info
: 编译输出的元信息的其他部分source
: 源码language
: 合约语言 (Solidity, Serpent, LLL)languageVersion
: 合约语言版本compilerVersion
: 编译器版本abiDefinition
: 应用二进制接口定义userDoc
: NatSpec用户文档developerDoc
: NatSpec开发者文档
编译器输出的直接结构(code
和info
)反映了两个非常不同的部署路径。编译的EVM代码通过合同创建事务发送到块链,而其余的(info)将理想地像云一样分散分布,作为可公开验证的元数据补充块上的代码。
如果您的源包含多个合约,则输出将包含每个合约的条目,可以使用合约名称作为属性名称检索相应的合约信息对象。您可以通过检查最新的GlobalRegistrar代码来尝试这一点:
contracts = eth.compile.solidity(globalRegistrarSrc)