Skip to content

HPB EVM 合约介绍

BlockGeek edited this page Oct 14, 2019 · 2 revisions

合约是是什么?

契约是代码(其功能)和数据(其状态)的集合,它位于以太坊区块链的特定地址。 合同帐户能够在它们之间传递消息以及实际上进行图灵完整计算。 合同以区块链为特色,是以太坊特定的二进制格式生成,称为以太坊虚拟机(EVM)字节码,现在HPB芯链在上层也用ETH同样的架构,这篇文章技术介绍基本的合约理念!

合约通常用一些高级语言(如Solidity)编写,然后编译成字节码以上传到区块链中。

还存在其他语言,特别是Serpent和LLL,这篇文档的以太坊高级语言部分对此进行了进一步描述。

Dapp开发资源列出了集成开发环境,开发者工具可帮助您使用这些语言,并提供测试和部署等功能。

EVM 高阶语言

最早的合约以区块链的形式存在于以太坊特定的二进制格式(EVM字节码)中,由以太坊虚拟机(EVM)执行。 但是,合同通常使用更高级别的语言编写,然后使用EVM编译器编译为字节代码以部署到区块链。

以下是开发人员可以用来为以太坊编写智能合约的不同高级语言。

Solidity

Solidity是一种类似于JavaScript的语言,它允许您开发合同并编译为EVM字节码。 它目前是EVM开发的旗舰语言,也是最受欢迎的语言。

Serpent

Serpent是一种类似于Python的语言,可用于开发合约并编译为EVM字节码。 它旨在最大限度地简洁,将低级语言的许多效率优势与编程风格的易用性结合起来,同时为合约编程添加特殊的域功能。 Serpent使用LLL编译。

LLL

Lisp Like Language (LLL) 是一种类似于汇编的低级语言。 它意味着非常简单和简约; 基本上只是在EVM中直接编码的一个小包装器。

Mutan (deprecated)

Mutan 是由Jeffrey Wilcke设计和开发的静态类型C语言, 它不再维护。

开发一个合约吧

没有Hello World计划,任何语言都不会完整。 在以太坊环境中运行,Solidity没有明显的“输出”字符串的方法。 我们最接近的是使用日志事件将字符串放入区块链中:

contract HelloWorld {
        event Print(string out);
        function() { Print("Hello, World!"); }
}

此合约将在每次执行时使用参数“Hello,World!”在Print类型的区块链上创建一个日志条目。

还可以看这些文档

Solidity docs 里面有过多的关于如何写合约的代码例子。

编译一个合约

可靠性合同的汇编可以通过许多机制来完成。

注意:

更多的关于编译的合约code可以在这里 这里发现.

在geth中设置solidity编译器

如果启动geth节点,则可以检查哪些编译器可用。

> web3.eth.getCompilers();
["lll", "solidity", "serpent"]

此命令返回一个字符串数组,指示当前可用的编译器。

注意:

这个 solc 编译器用这个去编译 cpp-ethereum. 或者这样, 看这段例子 build it yourself.

如果您的solc可执行文件位于非标准位置,则可以使用--solc标志指定solcexecutable的自定义路径。

$ geth --solc /usr/local/bin/solc

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

> admin.setSolc("/usr/local/bin/solc")
solc, the solidity compiler commandline interface
Version: 0.2.2-02bb315d/.-Darwin/appleclang/JIT linked to libethereum-1.2.0-8007cef0/.-Darwin/appleclang/JIT
path: /usr/local/bin/solc

编译一个简单的合约

让我们编译一段简单的合约代码:

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

此契约提供单个方法->乘法,使用正整数a调用并返回a* 7,您已准备好使用eth.compile.solidity()geth 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获得,也可以通过web3.javasdk连接到任何通过RPC / IPC连接到geth的浏览器Ðapp。

以下示例显示如何通过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将为您提供包含以下字段的测试合同的合同对象:

  • code

    编译好的 EVM 字节码

  • info

    编译器的其他元数据输出

  • source

    源代码

  • language

    编写合约的语言 (Solidity, Serpent, LLL)

  • languageVersion

    合约语言版本

  • compilerVersion

    编译合约时的solidity编译器版本

  • abiDefinition

    The Application Binary Interface Definition

  • userDoc

    用户手册 NatSpec Doc

  • developerDoc

    开发者手册NatSpec Doc .

编译器输出的结构(代码和信息)反映了两种截然不同的部署路径。 已编译的EVM代码通过合约创建事务发送到区块链,而其余(信息)将理想地作为可公开验证的元数据部署在分散的云上,以补充区块链上的代码。

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

contracts = eth.compile.solidity(globalRegistrarSrc)

创建和部署一个合约

在开始此部分之前,请确保您拥有未锁定的帐户以及一些资金。

现在,您将区块链上的合约创建为空地址,并将上一节中的EVM代码作为数据。

如果你用这两个工具会更快些: online Solidity realtime compiler 或者 Mix IDE

var primaryAddress = eth.accounts[0]
var abi = [{ constant: false, inputs: { name: 'a', type: 'uint256' } }]
var MyContract = eth.contract(abi)
var contract = MyContract.new(arg1, arg2, ..., {from: primaryAddress, data: evmByteCodeFromPreviousSection})

所有二进制数据都以十六进制形式序列化。 十六进制字符串的前缀始终为 0x

请注意,arg1,arg2,...是合同构造函数的参数,以防它接受任何参数。 如果契约不需要任何构造函数参数,则可以省略这些参数。

值得指出的是,此步骤需要您支付执行费用, 一旦您的交易成为一个区块,您在帐户上的余额(您在from的字段中作为发件人)将根据HPB EVM的GAS规则减少, 一段时间后,您的交易应该出现在一个块中,确认它所带来的状态是一致的,你的合同现在住在区块链上。

执行相同操作的异步方式如下所示:

MyContract.new([arg1, arg2, ...,]{from: primaryAccount, data: evmCode}, function(err, contract) {
  if (!err && contract.address)
    console.log(contract.address);
});
Clone this wiki locally