Solidity的Bytecode和Opcode简介

随着我们更深入地编写智能合约,我们将遇到诸如“ PUSH1”,“ SSTORE”,“ CALLVALUE”等术语。 他们是什么,我们什么时候应该使用到他们?

要了解这些命令,我们必须更深入地了解以太坊虚拟机(EVM)。本文将会尝试尽可能简单地解释一些EVM基础。希望大家都有所收获。

像许多其他流行的编程语言一样,Solidity是一种高级编程语言。 我们可以读懂,但是机器却不能够。 如果大家学过诸如java,c++等编程语言,应该会很容易明白这个道理。

当我们安装诸如geth之类的以太坊客户端时,它还附带了以太坊虚拟机,这是专门为运行智能合约而创建的轻量级操作系统。

当我们使用solc编译器编译Solidity代码时,它将代码转换为只有EVM可以理解的字节码。

让我们以一个非常简单的合同为例:

pragma solidity ^0.4.26;
contract OpcodeContract {
uint i = (10 + 2) * 2;
}

如果我们在remix浏览器中运行此代码,然后单击合同详细信息,则会看到很多信息。

在这种情况下,编译后的代码为:

BYTECODE
{
"linkReferences": {},
"object": "60806040526018600055348015601457600080fd5b5060358060226000396000f3006080604052600080fd00a165627a7a72305820db1d567e501f1682876df36eea80a02d25a8b2adb186da705e2e98e134b08cc60029",
"opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x18 PUSH1 0x0 SSTORE CALLVALUE DUP1 ISZERO PUSH1 0x14 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x35 DUP1 PUSH1 0x22 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0xdb SAR JUMP PUSH31 0x501F1682876DF36EEA80A02D25A8B2ADB186DA705E2E98E134B08CC6002900 ",
"sourceMap": "25:54:0:-;;;64:12;55:21;;25:54;8:9:-1;5:2;;;30:1;27;20:12;5:2;25:54:0;;;;;;;"
}

其中object就是编译后的代码。他们是最终合同的十六进制表示形式,也称为字节码。

在remix浏览器的“ Web3 Deploy”部分下,我们看到:

var opcodecontractContract = web3.eth.contract([]);
var opcodecontract = opcodecontractContract.new(
{
from: web3.eth.accounts[0],
data: '0x60806040526018600055348015601457600080fd5b5060358060226000396000f3006080604052600080fd00a165627a7a72305820db1d567e501f1682876df36eea80a02d25a8b2adb186da705e2e98e134b08cc60029',
gas: '4700000'
}, function (e, contract){
console.log(e, contract);
if (typeof contract.address !== 'undefined') {
console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
}
})

简单来说,这意味着当我们部署合同时,我们需要将编译后的16进制码当成data传递,并且建议的gas为4700000。

任何以“ 0x”开头的内容都表示该值采用十六进制格式。 十六进制前面的“ 0x”并不是强制的,因为EVM会将任何值都视为十六进制。

我们还看到了操作代码(又称Opcode):

"opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x18 PUSH1 0x0 SSTORE CALLVALUE DUP1 ISZERO PUSH1 0x14 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x35 DUP1 PUSH1 0x22 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0xdb SAR JUMP PUSH31 0x501F1682876DF36EEA80A02D25A8B2ADB186DA705E2E98E134B08CC6002900 ",

操作码是程序的低级可读指令。 所有操作码都具有对应的十六进制值,例如“ MSTORE”为“ 0x52”,SSTORE”为“ 0x55”……等等。

具体的操作码对应的数值可以参考以太坊相关资料。

EVM虚拟机是一中堆栈虚拟机,所谓堆栈就是后进先出结构,用计算机科学术语来说,我们称为LIFO。

举个例子,上面的智能合约,如果在普通算术中,我们这样写方程式:

// Answer is 14. we do multiplication before addition.
10 + 2 * 2

在EVM堆栈虚拟机中,它按照LIFO原理工作,所以我们需要这样写:

2 2 * 10 +

这意味着,首先将“ 2”放入堆栈,然后再放入另一个“ 2”,然后再进行乘法运算。 结果是“ 4”放在在堆栈顶部。 现在在“ 4”的顶部加上数字“ 10”,最后将两个数字加在一起。 堆栈的最终值为14。

这种算术类型称为后缀表示法。

将数据放入堆栈的动作称为“ PUSH”指令,将数据从堆栈中删除的动作称为“ POP”指令。 很明显,我们在上面的示例中看到的最常见的操作码是“ PUSH1”,这意味着将1个字节的数据放入堆栈中。

因此,此指令:

PUSH1 0x80

表示将1字节值“ 0x80”放入堆栈中。 “ PUSH1”的十六进制值恰是“ 0x60”。 删除非强制性的“ 0x”,我们可以将此逻辑以字节码形式写为“ 6080”。

让我们更进一步。

PUSH1 0x80 PUSH1 0x40 MSTORE

再次查看以太坊的操作码图表,我们看到MSTORE(0x52)接受2个输入,但不产生任何输出。 上面的操作码表示:

PUSH1(0x60):将0x80放入堆栈。

PUSH1(0x40):将0x40放入堆栈。

MSTORE(0x52):分配0x80的内存空间并移至0x40的位置。

结果字节码为:

6080604052

实际上,在任何固定字节码的开头,我们总会看到这个魔术数字“ 6080604052”,因为它是智能合约引导的方式。

请注意,这里不能将0x40或0x60解释为实数40或60。由于它们是十六进制,所以40实际上等于十进制的64(16 x 4),而80等于十进制的128(16 x 8)。

简而言之,“ PUSH1 0x80 PUSH1 0x40 MSTORE”正在做的是分配128个字节的内存并将指针移到第64个字节的开头。现在,我们有64个字节用于暂存空间,而64个字节用于临时内存存储。

在EVM中,有3个地方可以存储数据。首先,在堆栈中,按照上面的示例,我们刚刚使用了“ PUSH”操作码在此处存储数据。其次,在使用“ MSTORE”操作码的内存(RAM)中,最后在使用“ SSTORE”存储数据的磁盘存储中。将数据存储到磁盘存储所需的gas最昂贵,而将数据存储到堆栈中的gas则最便宜。

我们在Solidity中的智能合约中,有时候也会用到Assembly Language,这个Assembly Language就是使用这样的汇编Opcode来操作EVM字节码。他理解起来比较难,但是通过使用它可以节省燃料和做一些无法通过Solidity完成的事情。

本文仅介绍了字节码和一些操作码的基础。后面会有更多的文章来详细介绍Assembly Language和EVM虚拟机。 敬请期待。

更多教程请参考 flydean的博客

Solidity的Bytecode和Opcode简介的更多相关文章

  1. PHP Opcode内核实现 - [ PHP内核学习 ]

    catalogue . Opcode简介 . PHP中的Opcode . opcode翻译执行(即时解释执行) 1. Opcode简介 opcode是计算机指令中的一部分,用于指定要执行的操作, 指令 ...

  2. php的opcode缓存

    前言:由php的运行机制决定,其实php在运行阶段我们也是可以进行缓存的从而提高程序运行效率,这就是我们常说的opcode缓存.1.简述php的运行机制(因为本文是写opcode缓存的所以这里只是简要 ...

  3. JVM架构

    1 JVM的内存模型 1.1 堆空间 每个jvm都有一个堆,所有的对象都放在这里. 1.2 java栈空间 每个线程都有一个java栈,所有的java栈都放在这里. 1.3 本地方法栈 每个线程都有一 ...

  4. Solidity 官方文档中文版 1_简介

    简介 Solidity是一种语法类似JavaScript的高级语言.它被设计成以编译的方式生成以太坊虚拟机代码.在后续内容中你将会发现,使用它很容易创建用于投票.众筹.封闭拍卖.多重签名钱包等等的合约 ...

  5. Solidity 中文文档 —— 第一章:Introduction to Smart Contracts

    第一章:智能合约简介 粗略地翻译了 Ethereum 的智能合约开发语言的文档:Solidity.欢迎转载,注明出处. 有任何问题请联系我,本人微信:wx1076869692,更多详情见文末. 我是 ...

  6. 小师妹学JVM之:java的字节码byte code简介

    目录 简介 Byte Code的作用 查看Byte Code字节码 java Byte Code是怎么工作的 总结 简介 Byte Code也叫做字节码,是连接java源代码和JVM的桥梁,源代码编译 ...

  7. Living in the Matrix with Bytecode Manipulation--转

    原文地址:https://www.infoq.com/articles/Living-Matrix-Bytecode-Manipulation You are probably all too fam ...

  8. Spark入门实战系列--1.Spark及其生态圈简介

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .简介 1.1 Spark简介 年6月进入Apache成为孵化项目,8个月后成为Apache ...

  9. 深入了解php opcode缓存原理

    什么是opcode opcode(operate code)是计算机指令中的一部分,用于指定要执行的操作,指令的格式和规范由处理器的指定规范指定 opcode是一种php脚本编译后的中间语言,就像ja ...

随机推荐

  1. vulnhub~incllusiveness

    这个机子相对简单一点,但是也是从中发现了自己不少问题 技能一:  nmap 扫描发现了21,22 ,80三个端口,并且ftp服务允许匿名登录,在pub目录下面有writeable权限,这就好办了.我以 ...

  2. MFC 工具栏ToolBar

    一.创建工具栏 1.在MFC工程,找到“资源视图”界面,右键添加资源,选择Toolbar,点击新建: 2.修改工具条属性: 3.添加工具: 新建ToolBar后,会自动生成一个工具,编辑ID后,工具条 ...

  3. DevOps技能自查表

    前篇提到了DevOps的工作岗位要求,但是没有来的及深入细节,本文根据个人10年多的经验,尽量详细地列举DevOps所需要用到的一些技术和相关参考网站. Linux基础 Linux系统的基本概念: 必 ...

  4. udev规则,部署Multipath

    部署Multipath多路径环境 配置iSCSI服务 编写udev规则 配置并访问NFS共享 部署Multipath多路径环境 1 配置iSCSI服务 1.1 问题 本案例要求先搭建好一台iSCSI服 ...

  5. .net core 实现excel 和 word 的在线预览

    最新在搞文件的在线预览,网上很多免费的方案都需要是电脑安装office的,这要就很麻烦:收费的插件又太贵了. 不过还是找到一款相对好用的免费在线预览插件. 直接在nuget上搜索ce.office.e ...

  6. Linux 磁盘管理篇(一 磁盘分区)

    显示系统所有分区内容            fdisk 分区工具                parted fdisk: 执行完后按下 q 是退出不保存操作的意思 执行完后按下 w 是执行操作的意思 ...

  7. Deep Dream模型与实现

    Deep Dream是谷歌公司在2015年公布的一项有趣的技术.在训练好的卷积神经网络中,只需要设定几个参数,就可以通过这项技术生成一张图像. 本文章的代码和图片都放在我的github上,想实现本文代 ...

  8. Kitty-Cloud服务搭建过程剖析

    项目地址 https://github.com/yinjihuan/kitty-cloud 服务搭建 大家目前看到的都是我已经搭建好了的服务,如果让你从零开始自己搭建一个微服务的项目,要怎么做? 我们 ...

  9. 计算机网络-CSMA/CD

    假定1km长的CSMA/CD网络的传输速率为1Gbit/s.设信号在网络上的传播速率为200000km/s,则能够使用此协议的最短帧长是? 答案:2×104bit/s 解析:C=2×105km/s,即 ...

  10. 全方位认识HBase:一个值得拥有的NoSQL数据库(一)

    前言:说起HBase这门技术,在认知上对于稍微接触或使用过它的人来讲,可能只是百千数据库中一个很普通的库,大概就像我对Redis的认知一样:缓存嘛!可对于HBase,我确实是带着某些感情在的.今日突然 ...