在区块链上,用户通过运行部署在区块链上的合约,完成需要共识的操作。而为智能合约提供运行环境的便是对应的虚拟机。
目录
- EVM
- 基础概念
- 技术细节
- EVM的存储模型
- 交易在EVM的执行
- 普通转账交易
- 智能合约的创建或者调用
- EVM机器语言
- 与现有的虚拟机科技作比较
- EVM的几个功能
- EVM和公链的关系
- HVM
- 概述
- 使用
- 1.虚拟机层
- 2.库函数层
- 3.合约操作层
- 优势
- WASM
- 概述
- 工作原理
- 优势
- 与 EVM 对比
- MOVE
- 概述
- 实现细节
- Move 编程语言
EVM
基础概念
EVM,是ERC协议和运作的心脏。
简单的类比:EVM之于以太坊,正如Java虚拟机之于Java语言
我们写的java代码会被编译成字节码,但计算机无法识别字节码;java虚拟机把字节码编译成计算机系统可以识别的机器码指令,然后在计算机上运行。如下图所示:
EVM的存在是为了能让我们用Solidity编写的合约代码,运行在以太坊的环境中。这样类比的话,以太坊就相当于计算机环境,EVM把合约代码编译成以太坊能识别的机器码运行。如下图所示:
大致流程:
当智能合约被编译成二进制文件后,被部署到区块链上。用户通过调用智能合约的接口,来触发智能合约的执行操作。EVM执行智能合约的代码,修改当前区块链上的数据(状态)。被修改的数据,会被共识,确保一致性。
它实际上是完全隔离的,这意味着在EVM上运行的代码无法访问网络、文件系统和其他进程。智能合约对其他的智能合约的访问权也有限,在区块链网络上单独运作。
编写智能合约有三个主要步骤:
- 用高级语言编写,如Solidity
- 用EVM编译器编译成字节码
- 用客户端上传到区块链网络
技术细节
EVM的存储模型
EVM是一个基于堆栈的虚拟机,具有临时内存字节数组和持久键值存储(持久存储在Storage中)。
Stack:EVM是基于栈(stack)的虚拟机,stack用来保存指令的输入输出数据,最大深度为1024个字,其中每个单元就是一个字。
临时存储Memory:内存,一个简单的内存数组,用于临时存储EVM代码运行中需要存取的各种数据,基于字进行寻址和扩展
永久存储 Storage:用来保存所有合约“状态”的永久存储,由以太坊客户端独立维护,每个账户的存储区域被以“字”为单位划分为若干个“槽”(solt),合约中的状态变量会根据其具体类型分别保存到这些槽中。例如在合约创建时由EVM根据合约定义的状态变量进行初始化,将他们保存进以"字"为单位划分的"存储槽(solt storage)"中。
Storage也是作为是世界状态的一部分存在的,客户端会用一个MPT来维护其数据。
ROM:用来保存所有EVM程序代码的只读存储,由以太坊客户端独立维护。
交易在EVM的执行
输入一笔交易,内部会转换成一个 Message 对象,传入 EVM 执行。
普通转账交易
如果是一笔普通转账交易,那么直接修改 StateDB 中对应的账户余额即可。
智能合约的创建或者调用
如果是 智能合约的创建或者调用,则通过 EVM 中的解释器加载和执行字节码,执行过程中可能会查询或者修改 StateDB。
1.生成Contract对象
交易会被转换成一个Message对象传入EVM,而EVM则会根据Message生成一个Contract对象以便后续执行。
2.送入解释器执行
EVM是基于栈的虚拟机,解释器中需要操作四大组件
PC:类似于CPU中的PC寄存器,指向当前执行的指令
Stack:执行堆栈,位宽为256 bits,最大深度为1024
Memory:内存空间
Gas:油费池,耗光油费则交易执行失败
EVM的每条指令称为一个OpCode,占用一个字节,所以指令集最多不超过256
● 首先PC会从合约代码中读取一个OpCode
● 然后从一个JumpTable中检索出对应的operation,也就是与其相关联的函数集合
● 接下来会计算该操作需要消耗的油费,如果油费耗光则执行失败,返回ErrOutOfGas错误。如果油费充足,则调用execute()执行该指令,根据指令类型的不同,会分别对Stack、Memory或者StateDB进行读写操作。
EVM机器语言
EVM机器语言分为特定的指令集组,例如算术运算,逻辑和比较运算,控制流,系统调用,堆栈操作和储存器操作。除典型的Bytecode 操作外,EVM还必须管理帐户资讯(即地址和余额),当前gas价格和区块资讯。
通用堆栈操作
POP // 项目出栈
PUSH // 项目入栈
MLOAD // 将项目加载到记忆体中
MSTORE // 在记忆体中储存项目
JUMP // 改变程式计数器的位置
PC // 程式计数器
MSIZE // 活动的记忆体大小
GAS // 交易可用的gas数量
DUP // 复制栈项目
SWAP // 交换栈项目
通用系统操作
CREATE // 创建新的帐户
CALL // 在帐户间传递消息的指令
RETURN // 执行停机
REVERT // 执行停机,恢复状态更改
SELFDESTRUCT // 执行停机,并标记帐户为删除的
算术运算
MUL //乘法
SUB //减法
DIV //整数除法
SDIV //有符号整数除法
MOD // Modulo(剩余)操作
SMOD //签名模运算
ADDMOD //模数加法
MULMOD //模数乘法
EXP //指数运算
STOP //停止操作
环境操作码
ADDRESS //当前执行帐户的地址
BALANCE //帐户余额
CALLVALUE //执行环境的交易值
ORIGIN //执行环境的原始地址
CALLER //执行调用者的地址
CODESIZE //执行环境程式码大小
GASPRICE //gas价格状态
EXTCODESIZE //帐户的程式码大小
RETURNDATACOPY //从先前的记忆体调用输出的数据的副本
与现有的虚拟机科技作比较
● 虚拟机(Virtual Machine)
● Java 虚拟机(VM)
虚拟机技术与EVM的不同之处在于它们的目的是提供管理程式功能,或者处理客户作业系统与底层主机作业系统和硬体之间的系统调用,任务调度和资源管理的软体抽象。
然而,Java VM(JVM)规范的某些方面确实包含与EVM的相似之处。从高级概述来看,JVM 旨在提供与底层主机作业系统或硬体无关的运行时环境,从而实现各种系统的兼容性。在JVM上运行的高级程式语言(如Java或Scala)被编译到相应的指令集Bytecode 中。这与编译要在EVM上运行的Solidity源档案相当。
EVM的几个功能
● 便于测试:为了保证各种“智能合约”的顺利执行,我们需要给它们创建一个安全的运行环境,EVM就是一个代码的运行环境。
正如我们上文所说,在虚拟机里的各种操作不会影响主机一样,任何想要在EVM创建智能合约的开发者可以在虚拟机上测试各种应用而不占用主链资源也不受其他区块链的影响。
● 增加安全性:ETH上承载着具有强大功能的各种应用,其逻辑也就更加复杂,开发者也越容易出现各种漏洞。而EVM是一个完全独立的沙盒,合约代码可对外完全隔离并在 EVM 内部运行。
不仅可以防止因为不法分子或者程序员的编程错误而影响整个主链,还可以防止运行智能合约的物理设备遭受攻击。
● 保障稳定性:由于EVM部署在ETH网络的每个节点,整个ETH网络的数据由众多节点共同维护和更新,这保持了整个区块链数据的一致性,这同样也使ETH有极高的故障容错性,保证零停机。
EVM和公链的关系
目前市面上主流的公链,大部分都兼容EVM。
为什么这些链要做EVM兼容呢?
核心当然是以太坊在公链领域的影响力。目前市场上的各种公链此起彼伏,但是ETH依然是公链领域的龙头。这些新兴的公链需要利用以太坊引流,如果开发者可以把智能合约直接无缝迁移到自己的链上,那就是最好的引流方式。
在这些公链产生之前,以太坊的生态里,EVM已经部署了大量的应用。如果你不兼容这些应用,前进的道路必然是举步维艰。
下面这个图是2022年5月31日的全球公链的市场份额:
这个网站看到所有兼容EVM的公链:https://www.coincarp.com/zh/chainlist/
HVM
HVM介绍
概述
HVM为趣链科技首创支持Java语言的智能合约执行引擎,支持符合Java编写规范多种数据结构,内置数据表结构,可以实现业务数据可视化,在保证智能合约执行的安全性、确定性、可终止性的前提下,提供了一系列灵活的应用模式和工具方法集,以满足复杂多样的业务场景需求,为广泛的区块链开发人员提供更便捷、灵活、安全的区块链应用开发模式。
使用
HVM合约执行的操作:从SDK调用一笔HVM的合约,首先需要共识模块将通过共识的区块交易发送给执行模块,然后执行模块调用HVM暴露出来的合约接口,最后合约执行完成后会将结果返回,将执行结果写入账本中。
在架构层面,HVM自上而下主要分为三个部分:合约操作层、库函数层以及虚拟机层。
1.虚拟机层
虚拟机层主要是在合约执行过程中,对于合约解析执行的内部操作。为了提高整体的执行效率,HVM设计定制类加载器,类加载缓存提供合约地址到合约类加载器的映射,一个合约类加载器保存合约的字节码和合约类实例,采用最近最少使用淘汰策略(LRU)减少类重复加载带来的开销;指令解析从开始的每次对指令进行解析到将指令做成单例,并进行栈帧复用,大量节省指令执行时间,提高整体执行效率。
2.库函数层
库函数包括数据结构、账本操作、日志信息以及加解密等功能。
● 数据结构符合 Java 编写范式:HyperList、HyperMap为平台独立研发,为了方便Java 软件开发者习惯,使其无需感知区块链底层 KV 结构即可编写相应业务逻辑代码。HyperMap 和 HyperList 的使用类似于开发者所熟知的 HashMap 和 ArrayList,但做了原创性地优化,在减少内存使用的同时也提高了更新账本的插入效率。
- 内置数据表结构:为了满足复杂业务场景下数据类型多样化、业务数据可视化与可分析的需求,智能合约需要支持复杂的表结构数据组织形式。HVM 提供了内置数据结构 HyperTable,支持在合约内部按照表的形式组织业务数据,便于业务数据可视化以及后续的数据分析与价值挖掘。这种结构可以让原Solidity 语言中复杂嵌套的数据操作简单化,同时在性能方面,能有效解决序列化、反序列化造成的性能瓶颈,整体维护成本更低、使用更高效。
- - 内置嵌套Map数据结构:HyperList、HyperMap数据结构都无法满足复杂数据组织结构的需求;HyperTable的表结构拥有严格的层级格式(表-行-列簇-列-值),缺乏在复杂结构下的灵活性(例如:不可只有列,没有列簇)。针对上述问题,HVM推出新型的数据结构——NestedMap,支持用户按需进行灵活的数据组织,并且实现对多层映射数据更高的读写性能。
3.合约操作层
这一层与用户直接相关联,主要包括合约部署、调用等全生命周期管理,对于合约的操作通过会对链上的合约数据状态产生影响,所以平台采取了灵活的合约管理提案申请-阈值投票-提案执行的策略,通过合约管理员对合约操作进行控制,保证合约管理操作的公平与安全。
● 合约部署 :编写Java智能合约,并通过SDK发交易的形式将其部署到区块链上;
● 合约调用 : 根据合约地址,调用相应合约中的逻辑。
● 合约升级 : 需要对合约进行升级操作时,因为升级合约是一个链级操作(改变整个链上的状态),所以需要采用CAF联盟自治框架才可以进行合约升级,保证链上合约的安全控制。
● 合约冻结/解冻 :将链上的合约冻结,在合约所有者解冻之前,禁止任何人调用,冻结不同于销毁,其具备一个可逆的过程,可以通过合约解冻的操作重新使用。
● 合约销毁 :不同于合约冻结,合约销毁是一个不可逆的操作,被销毁的合约不能够被访问,不可以恢复,不允许再进行任何操作,但合约销毁后的数据仍然会存在链的底层账本中,仅用于监管审计。
优势
● 支持多级日志
EVM 未对出现的异常进行详细定位,给编译调试造成极大的难度。而 HVM 通过内置日志工具类,支持六种日志级别:critical、error、warning、notice、info、debug。可以为每种常见的错误进行合理的提示,方便使用者 对合作操作过程中产生的异常进行debug,方便开发和运维快速定位问题。
● 分层调用模式
HVM采取分层调用的模式,可以有效降低合约升级的成本。其实现方法主要通过InvokeBean的方式在业务调用层在不更新合约的情况下定义丰富的业务逻辑, 合约层只实现最核心、最基本的原子操作。以转账场景为例,合约层只有增加余额和减少余额的方法,在InvokeBean调用层定义转账的逻辑:如余额是否充足、 减少转让方余额和增加接收方余额。
● 支持加解密工具
一些业务场景需要在智能合约中进行签名验签逻辑处理,从而进行身份认证,便于进行权限判断或者后续业务的开展。因此 HVM 设计了基于 TEE的加解密工具, 支持在合约中调用存储于 TEE 的公私钥完成签名、验签操作,并支持 ECDSA国标系列、SM 国密系列等多种加解密算法,具有方便友好安全的特性。
● 支持合约访问控制
合约编码者可以通过智能合约和访问控制策略来限制访问数据的角色和用户,在合约中针对节点、角色、用户定制不同的合约函数访问权限。合约编码者可以在 合约中为一些高权限的函数设置权限控制,使得该函数只能被固定地址的调用者调用,从而实现访问权限控制。
WASM
WASM-VM 简介
概述
WebAssembly(wasm) 是一个基于二进制操作指令的栈式结构的虚拟机,wasm可以被编译为机器码,可以更快,更高效的执行本地方法和硬件资源,通过和js协作,前端可以实现更快,更复杂的计算和应用。
不仅可以嵌入浏览器增强web应用,也可以应用于其他的场景。
wasm 支持高级语言编程,目前比较成熟的编译器支持C \ C++ \Rust。
工作原理
WASM 是一种不依赖于具体物理机器的汇编语言,可以抽象的理解成它是概念的机器语言,而不是实际的物理机器语言,因此,WebAssembly 指令也可称为虚拟指令,可以更快的更直接的映射的到机器码!
优势
WASM虚拟机已经被Google,Facebook,Microsoft等世界顶级互联网公司同时支持,同时也可以在所有流行的浏览器中运行。WASM虚拟机一开始设计的目的是用于解决Web程序日益严峻的性能问题,因其有以下优越的特性,被越来越多的非Web项目所采用。
1、快速、高效、可移植:通过利用常见的硬件能力,WASM代码在不同平台上能够以接近本地速度运行。
2、可读、可调试:WASM是一门低阶语言,但是它有一种人类可读的文本格式,这允许通过人工来写代码、看代码以及调试代码。
3、保持安全:WASM被限制运行在一个安全的沙箱执行环境中。像其他网络代码一样,它遵循浏览器的同源策略和授权策略。
4、不破坏网络:WASM的设计原则是与其他网络技术和谐共处并保持向后兼容。
与 EVM 对比
速度
● EVM
○ 只能处理256位字节码,这意味着小于256位的字节码必须先转换为256位格式,然后才能发送给EVM。
○ EVM的可扩展性问题很明显,因为它每秒只处理25个交易。
● WASM
○ 直接转换为编译后的代码,这使它能够更快地加载,同时增加每个区块所处理的交易数量。
预编译
● EVM
○ 依赖于预编译(预编译合约)。当发出预编译调用时,EVM将执行预定义的本机代码,然后显示结果。这些预编译特定于用于基本操作的特定协议,例如签名方案和哈希。
○ 尽管预编译在不消耗大量gas的情况下使加密计算变得高效,但它们也带来了问题。引入新的预编译器通常要求网络经历一个系统范围的硬分叉。
● WASM
○ 消除了以太坊对预编译合同的依赖。由于WASM非常高效,开发人员可以创建高效、快速的智能合约,而无需担心潜在的硬分叉。
灵活性和互操作性
WASM支持更多的语言,并且提供了比EVM更广泛的工具集。WASM支持传统语言,如Rust、C和c++。WASM也被本地JavaScript引擎支持,例如 Google 的 V8 引擎(基于 Node.js 和 Chromium 的浏览器)、微软的 Chakra 引擎(Microsoft Edge)和 Mozilla 的 Spidermonkey 引擎(Thunderbird 和 Firefox)。
MOVE
概述
MoveVM 是具有静态类型系统的堆栈机。 MoveVM 从几个方面来约束 Move 语言规范,包括混合文件格式、验证和运行时的约束。文件格式的结构允许定义模块,类型(资源和非限制类型)和函数。代码通过字节码指令表示,字节码指令可以引用外部函数和类型。
实现细节
Move VM 执行以 Move 字节码表示的交易。它有两个核心包:核心 VM 和 VM 运行时。
MoveVM核心包提供文件格式的定义以及与文件格式相关的所有实用程序:
● 一个简单的Rust抽象文件格式 (libra/language/vm/src/file_format.rs) 和字节码。这些Rust结构广泛用于代码库中。
● 文件格式的序列化和反序列化。这些定义了代码的链上二进制表示。
● 一些漂亮的输出展示功能。
● 文件格式的基本架构。
● gas 成本/综合基础设施。
Move 编程语言
Move是一种新的编程语言,旨在为Libra区块链提供安全可编程的基础。
Move 与平台无关,支持跨区块链的共享库、工具和开发人员社区。Move 语言的设计强调安全性,旨在避免许多Web3.0 用户受害的情形,包括但不限于重入漏洞(re-entrancy vulnerabilities)、毒令牌(poison tokens)和欺骗性令牌批准(spoofed token approvals)等问题
Move 语言目录由五个部分组成:
● 虚拟机 (VM), 它包含字节码格式、字节码解释器和执行交易块的基础设施。该目录还包含生成创世区块的基础设施
● 字节码验证器, 其中包含一个静态分析工具,用于拒绝无效的Move字节码。虚拟机在执行新的Move代码前,会先运行字节码验证器。编译器运行字节码验证器则会把输出和错误显示给程序员。
● Move中间层表示 (IR: intermediate representation) 编译器, 它将可读的程序文本编译成Move字节码. 警告:IR编译器是一个测试工具。它会生成将被Move字节码验证器拒绝的无效字节码。IR语法工作仍在进行,或将经历重大的变化。
● 标准库, 其中包含 LibraAccount 和 LibraCoin 等核心系统模块的Move IR代码。
● 一些测试 ,用于虚拟机,字节码验证程序和编译器。 这些测试是用Move IR 编写的,由测试框架运行,该测试框架从注释中编码的特殊指令解析运行测试的预期结果。