以太坊源码解读(1)以太坊概念

一、定义

以太坊是一个开源的带有智能合约功能的公共区块链平台。

以太坊特点

  • 支持智能合约,以太坊不是给用户一系列预先设定好的操作,而是充分允许用户按照自己的意愿创建复杂的逻辑操作;
  • 以太坊同时还构建了较完整的、开源的生态系统:有底层的geth、编程的solidity、合约在线浏览器browser-solidity、合约钱包Mist/wallet、前端开发框架Treffle,以及在此基础上运行的各种开源Dapp等等。

二、以太坊的发展阶段

以太坊的完整发展路线分为四个阶段,阶段之间的切换需要通过硬分叉来实现,即:

  • “前沿”(Frontier)  2015年7月30日
  • “家园”(Homestead)  2016年3月14日
  • “大都会”(Metropolis)  第一阶段2017年10月15日,第二阶段尚未确定
  • “宁静”(Serenity)  尚未确定

目前,以太坊正处于第三阶段“大都会”,这个阶段主要有四个特性,即零知识证明的执行、权益证明的早期实施、智能合约更为灵活和稳定、抽象账户的应用。由于这些特性不会一次性被引入,而通过两个阶段进行引入,这个两个阶段就是分别命名为“拜占庭”和“君士坦丁堡”的两次硬分叉。也就是说,目前以太坊处于“拜占庭”硬分叉阶段。

这里有一个概念叫“难度炸弹”。“难度炸弹”可以说是从以太坊被设计之初就确定了,因为以太坊从一开始就目标先通过POW来建立生态,在“宁静”阶段的时候彻底转为POS模式,降低挖矿对硬件的依赖。这样的转变势必会遭到前期花费大量投资去购买挖矿设备的矿工的抵制。为了防止这些矿工不接受新的规则从而产生硬分叉,以太坊设计者在计算区块难度的时候加入了“难度炸弹”这个参数。难度炸弹指的是计算难度时除了根据出块时间和上一个区块难度进行调整外,加上了一个每十万个区块呈指数型增长的难度因子。

三、核心概念

EVM

EVM是以太坊中智能合约的运行环境。它不仅被沙箱封装起来,事实上它被完全隔离,也就是说运行在EVM内部的代码不能接触到网络、文件系统或者其它进程。甚至智能合约之间也只有有限的调用。

EVM不是基于寄存器,而是基于栈的虚拟机。因此所有的计算都在一个被称为栈的区域执行。栈最大有1024个元素,每个元素256比特。对栈的访问只限于其顶端,无法只访问栈上指定深度的那个元素,在那之前必须要把指定深度之上的所有元素都从栈中移除才行。当然可以把栈上的元素放到storage或者memory中。

存储,主存(Storage, Memory )

每个账户有一块持久化内存区域被称为存储。其形式为key-value,key和value的长度均为256比特。在合约里,不能遍历账户的存储。相对于另外两种,存储的读操作相对来说开销较大,修改存储更甚。一个合约只能对它自己的存储进行读写。

第二个内存区被称为主存。合约执行每次消息调用时,都有一块新的,被清除过的主存。主存可以以字节粒度寻址,但是读写粒度为32字节(256比特)。操作主存的开销随着其增长而变大(平方级别)。

账户

外部账户:被公钥-私钥对控制,其地址由公钥决定,没有代码,可通过创建和签名一笔交易从一个外部账户发送消息。合约账户:被存储在账户中的代码控制,每当合约账户收到消息,合约内部的代码就会被激活,允许它对内部存储进行读取/写入/发送其他消息和创建合约。

交易

交易是指从外部账户发出的签名数据包,包含交易接收者、用于确认发送者的签名、交易额度、要发送的数据、GasLimit、GasPrice。GasLimit通过需要支付的燃料来对计算步骤进行限制,防止合约代码出现指数型爆炸和无限循环。

当一个交易的目标账户是一个合约账户,那么合约账户里的代码就会与交易里的数据(payload)一同执行。如果交易目标账户是零账户,代表要创建一个合约,交易的payload就是一个合约代码的ABI,ABI作为EVM字节码执行,输出真正的合约代码被永久储存。这个过程就是“部署合约”。

消息调用

合约可以通过消息调用的方式调用其他合约,或者发送以太币到非合约账户。消息调用和交易非常类似,他们都有一个消息源、一个目标、数据负载、以太币、gas和返回数据。

事实上,每个交易都可以被认为是一个顶层消息调用,这个消息调用会依次产生更多的消息调用。调用层数被限制为1024。

gas

以太坊上的每笔交易都会被收取一定数量的gas,gas的目的是限制执行交易所需的工作量,同时为执行支付费用。当EVM执行交易时,gas将按照特定规则被逐渐消耗。

gas price(gas价格,以太币计)是由交易创建者设置的,发送账户需要预付的交易费用 = gas price * gas amount。 如果执行结束还有gas剩余,这些gas将被返还给发送账户。

无论执行到什么位置,一旦gas被耗尽(比如降为负值),将会触发一个out-of-gas异常。当前调用帧所做的所有状态修改都将被回滚。

指令集

EVM所支持的指令编码,EVM所有的指令都针对256位这个基本的数据单位进行操作。此外合约可以访问当前区块的相关属性,比如它的编号和时间戳。

日志(Logs)

在区块层面,可以用一种特殊的可索引的数据结构来存储数据。这个特性被称为日志,Solidity用它来实现事件。合约创建之后就无法访问日志数据,但是这些数据可以从区块链外高效的访问。因为部分日志数据被存储在布隆过滤器(Bloom filter) 中,我们可以高效并且安全的搜索日志,所以那些没有下载整个区块链的网络节点(轻客户端)也可以找到这些日志。

以太坊的世界状态

包括每一个账户的余额、合约代码、账户的储存、Nounce值。以太坊的状态转换是指在一个交易发生时,以太坊从一个正确的状态S转到下一个正确的状态S'的转换过程。

共识算法的两种实现

以太坊共识算法对外暴露的接口是Engine接口,共识算法由两种实现体:

  • Ethash算法:基础运算能力,是目前以太坊基于POW工作量证明的一个共识引擎(也叫挖矿算法)。
  • Clique算法:基于“同行”认证,网络中的每一个区块是由某一个认证节点进行认证的,其他节点仅需要验证认证信息来判断该区块是否合法。

也就是说,以太坊的共识算法是系统提供的一个接口,实现可插拔式的,只要实现了共识算法就可以被引用。Ethash和Clique都是Engine接口的两种实现。

下一章:以太坊源码解读(2)geth目录结构

Geth是以太坊官方唯一推荐的客户端,相当于是对以太坊区块链的官方实现。源码的地址是:https://github.com/ethereum/go-ethereum下面我们来从Geth源码的目录来看看以 ...