一、智能合约字节码的结构
pragma solidity ^0.4.18;
contract test {
}
上面是一个很简单的合约,在remix进行对上面的合约进行编译,可以点击compliation detials按钮获得编译的结果,结果中有两个内容:
1.BYTECODE
object选项的全部内容是
60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00a165627a7a72305820395f38545a3c60d8fb3628f35d8ed9df7363257889a1311469f57957730033870029
2.RUNTIME BYTECODE
object选项的全部内容是
6060604052600080fd00a165627a7a72305820395f38545a3c60d8fb3628f35d8ed9df7363257889a1311469f57957730033870029
------------------------------------手动分割线------------------------------------------------
不难发现RUNTIME BYTECODE的字节码BYTECODE的字节码少了这一段
60606040523415600e57600080fd5b603580601b6000396000f300
那为什么会少了这一段呢?RUNTIME BYTECODE和BYTECODE有神不同?
看完下面你就会懂了
智能合约字节码可以分为三个部分,以上面的合约字节码为例子
1.部署代码。
60606040523415600e57600080fd5b603580601b6000396000f300
以太坊虚拟机在创建合约的时候,会先创建合约账户,然后运行部署代码。运行完成后它会将runtime代码+auxdata 存储到区块链上。之后再把二者的存储地址跟合约账户关联起来(也就是把合约账户中的code hash字段用该地址赋值),这样就完成了合约的部署。
2.runtime代码
6060604052600080fd00
是合约运行时的代码
3.auxdata
a165627a7a72305820395f38545a3c60d8fb3628f35d8ed9df7363257889a1311469f57957730033870029
每个合约最后面的43字节就是auxdata,它会紧跟在runtime代码后面被存储起来。
二、字节码的执行
首先贴出字节码和操作码的对应关系
图片来源https://paper.seebug.org/790/
下面让我们用一个更复杂的智能合约来了解字节码的编译和运行
pragma solidity ^0.4.18;
contract test{
int public num = 1;
function function1() public returns(int)
{
return num;
}
}
将上面的智能合约编译后可以点击compliation detials按钮获得编译的结果,这次我们看其中的ASSEMBLY部分,不难发现这里的操作码和合约的字节码是相对应的。
code到data部分就是部署代码,而data后面就是运行代码
上面的3个红框分别是该合约的3个跳转函数。但是这个合约就1个函数,为何会有3个可跳转函数。这3个跳转函数分别是:1个fallback(回退函数),1个public全局变量,1个public函数。
而上面的两个箭头所指的就是函数签名了,可以看出tag1是没有函数签名的,因为tag1所指的是fallback函数。
所以当我们调用某一函数时,合约就跳转到相应的tag执行。
还有一个地方就是我们可以发现每个tag都是以JUMPDEST
开头的,那这个到底是什么意思呢?
编译器在生成编译代码时,JUMP 和JUMPI 指令会跳转到JUMPDEST 指令.JUMPDEST 指令是solidity 编译器用来标识汇编代码的区段声名(Tag).
三、参考
1.https://paper.seebug.org/790/
2.https://blog.youkuaiyun.com/Programmer_CJC/article/details/80218649
3.https://www.codercto.com/a/40206.html