以太坊
以太坊是一个具有图灵完备智能合约的公有链平台,对底层区块链技术进行了封装,这样区块链应用开发者可以直接基于以太坊平台进行开发, 只需要专注应用本身,从而大大降低了开发的难度。
智能合约
以太坊上的程序 被称为 智能合约,它是 **代码和数据(状态)**的集合。
编程语言:Solidity
智能合约的默认编程语言是Solidity,文件扩展名以
.sol
结尾。Browser-Solidity Web IDE是一个基于Web的Solidity IDE。
Solidity是和JavaScript相似的语言,用来开发智能合约并将其编译成以太坊虚拟机字节代码。
运行环境:以太坊虚拟机(EVM)
EVM ( Ethereum Virtual Machine ) 即 以太坊虚拟机 是以太坊中智能合约的运行环境。而EVM运行在以太坊节点上,当我们把合约部署到以太坊网络上之后,合约就可以在以太坊网络中运行了。
- EVM使用了256比特长度的机器码,是一种基于堆栈的虚拟机,用于执行智能合约,并使用了**以太坊账户模型(Account Model)**来进行价值传输。
- EVM是图灵完备的,由于以太坊系统中引入了
Gas
的概念,所以原则上在EVM中可执行的计算总量受Gas
总量限制。 - EVM是一个隔离的环境,在EVM内部运行的代码不能跟外部有任何联系。
EVM采用了基于**栈(Stack)的架构,也就是后进先出(LIFO)**的方式。
EVM有如下特殊设计:
- 区分临时存储(Memory,存在于VM的每个实例中,并在VM执行结束后消失)和永久存储(Storage,存在于区块链状态层);
- 采用基于栈(Stack)的架构;
- 机器码长度为256比特,即32字节;
- 使用了可变、可扩展的内存大小;
- 栈的大小没有限制;
- 1024调用深度限制;
- 无类型。
像之前定义的那样,EVM是图灵完备虚拟机器,而EVM本质上是被Gas束缚,因此可以完成的计算总量本质上是被提供的Gas总量限制的。
此外,EVM具有基于堆栈的架构。每个堆栈顶的大小为256位,堆栈有一个最大的大小,为1024位。
EVM有内存(Memory),项目按照可寻址字节数组来存储。内存是易失的,也就是说数据是不持久的。EVM还有一个存储器(Storage),与内存不同,存储器是非易失的,并作为系统状态的一部分进行维护。EVM分开保存程序代码,在虚拟ROM中只能通过特殊指令来访问。
智能合约如何部署?
智能合约的部署是指把合约字节码发布到区块链上,并使用一个特定的地址来表示这个合约,这个地址称为合约账户。
以太坊中有两种不同类型但是共享同一地址空间的账户:
- 外部账户由一对公私钥控制,没有关联任何代码,其地址是由公钥(经过Hash运算)决定的
- 合约账户由账户内部的合约代码控制,该类账户被它们的合约代码控制且有代码与之关联,其地址在此合约被创建的时候决定。每个账户都有一个持久的
Key-Value
类型的存储,并将256位的Key
映射到256位的Value
上
EVM的缺陷与不足
机器码长度为256位
目前大多数的处理器主要由以下4种选择来实现快速的数学运算:
- 8bit整数
- 16bit整数
- 32bit整数
- 64bit整数
虽然在一些情况下32bit比16bit快,并且在x86架构中8bit数学运算并不是完全支持,但基本上如果你采用以上的任意一种,都可以保证数学运算在若干个时钟周期内完成,并且这个过程非常迅速,往往是纳秒级的。因此,可以说这些位长的整数是目前主流处理器能够原生支持且不需要额外操作的。
EVM处于所谓运算速度和效率方面考虑,采用了非主流的256bit整数。x86汇编码运算的比较实验,证明了采用256bit整数远比采用处理器原生支持的整数长度要复杂,即EVM的运算效率并不高。
缺少标准库
在开发Solidity智能合约时就会碰到这个问题,因为Solidity中根本没有标准库。目前的情况是,人们只能不断的从一些开源软件中复制粘贴代码。首先这些代码的安全性无法保证,再加上人们会为了更小的Gas消耗而不断修改代码,这就有可能对他们的合约引入更严重的安全性问题。
难以调试和测试
这个问题不仅仅是EVM的设计缺陷,也和其实现方式有关。EVM唯一能抛出的异常就是OutOfGas
,并且没有调试日志,也无法调用外部代码。同时,以太坊本身很难生成一条测试网络的私链,即使成功,私链的参数和行为也与公链不同。
不支持浮点数
浮点数有很多应用实例,比如风险建模、科学计算,以及其他一些范围和近似值比准确值更加重要的情况。EVM将浮点数排除在外的做法有潜在的局限性。
不可修改的代码
智能合约在设计时需要考虑的重要问题之一就是是可升级性,因为合约的升级是必然的。
在EVM中代码是完全不可修改的,并且由于其采用哈佛计算机结构,也就不可能将代码在内存中加载并执行,代码和数据是被完全分离的。
目前只能够通过部署新的合约来达到升级的目的,这可能需要复制原合约中的所有代码,并将老的合约重定向到新的合约地址。给合约打补丁或是部分升级合约代码在EVM中是完全不可能的。