一 以太坊简介
1 以太坊是什么?
1) 区块链2.0
区块链2.0实现了智能合约的功能,从而是区块链系统具有图灵完备的计算能力,可以在区块链上上传并执行应用程序,并且程序的有效执行能得到保障。
基于区块链2.0的技术架构目前主要有以太坊和Linux基金会发起的超级账本(Hyperledger)。
如果对区块链不熟悉,可以参考之前的博客:《区块链》、《区块链-区块结构》
2) 以太坊简介
我们先回顾一下比特币,比特币可以被看成一个系统,该系统是维护比特币交易的账簿,这个账簿对任何人都可见,所以比特币可以被看成共享的“全球账簿”。对比特币更详细的介绍见:《比特币原理简介》
以太坊(Ethereum)可以被看作一台“全球计算机”:一个任何人都可以上传和执行应用程序,并且可以确保程序能够被有效的执行。和比特币相同,以太坊也是去中心化的,有全球成千上万的计算机组成的共识网络。
在以太坊之前,如果我们想创建一个类似于比特币的区块链网络,就必须组建大量的机器(矿工),因为如果矿工数量较少,整个区块链网络是很容易出现被人操纵的,这不是我们想见的事情,反之,则需要投入非常巨大的成本。而以太坊正好可以解决这个事情,我们可以创建自己的应用,然后接入以太坊的区块链网络,将应用产生的一些重要信息通过交易的方式写在以太坊的区块中。以太坊是一个巨大的网络,从目前看来,还没有那个组织或个人有能力操作整个网络。
简单来说,以太坊是一个去中心化的区块链平台;以太坊是一个可以编程的区块链;在以太网络中交易的不仅仅是转账金额,还可以是一段代码。
以太坊与比特币的最主要区别主要体现在两个方面:
- 更快的出块速度以及更先进的奖励机制。即性能更高,吞吐量更大。
- 以太坊支持智能合约。
2 以太坊网络
目前以太坊网络主要分为:公有链、私有链和联盟链。
1) 公有链
公有链是任何人都能查看、发送交易,并能记录符合规则的交易,均可以参与共识过程的一种链。作为中心化或准中心化信任的替代品,公有链受加密经济的保护,加密经济是经济激励和加密图形验证的结合,用类似工作量证明或权益证明的机制,遵循的总原则是人们影响共识形成的程度和他们能够影响的经济资源数量成正比。这类区块链通常被认为是“完全去中心化“。
2) 联盟链
联盟链是一种有预先选定节点决定共识过程的区块链。例如,设想一个有N个金融机构的团体,每个机构都操作一个节点,为了使区块生效,其中的2/3个(此数字仅是一个示例)金融机构必须签署那个区块。阅读区块链的权利可能是公开的,或仅限于参与者,也有混合的路径,比如区块的根散表和应用程序编程接口一起公开,使公共成员可以进行一定量的查询,重获一部分区块链状态的加密图形证明。这类区块链被认为是“部分去中心化”。
3) 私有链
私有链的区块写入权由中心化节点或者一个组织所控制,块、链查询权限是公共的或者受到不同程度的限制。
3 以太币从何而来?
和比特币类似,以太币(Ether)也是系统对挖矿矿工的奖励,每当挖出一个区块,矿工将获得5个以太币。和比特币不同的是,以太坊中挖出叔块的矿工也能获得一定的以太币奖励;而引用叔块的区块也能获得一定的奖励。具体见叔块部分。
以太币的数量=Pre-mine(矿前)+ Block rewards(区块奖励)+ Uncle rewards(叔块奖励)+ Uncle referencing rewards(叔块引用奖励)
挖矿前(2014年7月/8月间)为众筹阶段,大约发行了7200万以太币;众筹阶段之后,以太币每年的产量被限制在7200万以太币的25%,即每年以太币的矿产量,不高于1800万。
以太坊网络以1个区块/15秒左右的速度生成新区块,每年大概产生260w(365*24*60*60/15)个区块,矿工奖励的以太币产量为:1050w/年左右;目前每天有大约500个叔块被创建,加上引用区块的奖励产量大概为:80-90W/年。
4 账户类型
我们将以太币看成一种电子货币,那么就一定会有账户来保存自己的以太币。以太坊有两种类型的账户:外部账户(Externally Owned Account,即EOA)、合约账户。
1) 外部账户(EOA)
也被称为:外部拥有账户、普通账户。
外部账户是由人创建的,是我们存放以太币的账户,被公钥-私钥对控制,地址由公钥决定。
外部账户具有以下特性:
- 拥有以太币余额。
- 用于确定每笔交易只能被处理一次的计数器(nonce)。
- 发送交易(以太币转账、发布合约、调用智能合约)
- 通过私钥控制
- 没有相关联的代码
2) 合约账户
合约账户由外部账户创建;合约账户的地址是在创建该合约时确定;合约账户被存储在账户中的代码控制。
与外部账户不同,合约账户不能自行发起新的交易,合约帐户只能触发交易以响应其他交易。每当合约账户收到一条消息,合约内部的代码就会被激活,允许它对内部存储进行读取和写入,和发送其它消息或者创建合约。
合约账户的特性有:
- 拥有一定的以太币余额
- 有相关联的代码,代码通过交易或其他合约发送的调用来激活。
- 当合约账户被执行时,智能操作合约账户拥有的特定存储。
3) 外部账户VS合约账户
一个外部拥有账户可以通过创建和用自己的私钥来对交易进行签名,来发送消息给另一个外部拥有账户或合约账户。
在两个外部拥有账户之间传送的消息只是一个简单的价值转移。
从外部拥有账户到合约账户的消息会激活合约账户的代码,允许它执行各种动作。
不像外部拥有账户,合约账户不可以自己发起一个交易。相反,合约账户只有在接收到一个交易之后(从一个外部拥有账户或另一个合约账户接),为了响应此交易而触发一个交易。因此,在以太坊上任何的动作,总是被外部控制账户触发的交易所发动的。
4) 账户状态
外部账户存储以太币余额状态,合约账户除了余额还有智能合约及其变量的状态,所以以太坊中外部账户和合约账户统称为状态对象(存储状态)。不管账户的类型如何,账户状态由四个部分组成:
nonce(随机数)用于确定每笔交易只能被处理一次的计数器。如果账户是一个外部拥有账户,nonce代表从此账户地址发送的交易序号;如果账户是一个合约账户,nonce代表此账户创建的合约序号
balance:账户目前的以太币余额,确切来说是此账户拥有Wei的数量。1Ether=10^18Wei
storageRoot:Merkle树的根节点Hash值。Merkle 树会将此账户存储内容的Hash值进行编码,默认是空值。
codeHash:此账户EVM代码的hash值,对于合约账户,就是被Hash的代码并作为codeHash保存;对于外部拥有账户,codeHash域是一个空字符串的Hash值
5 交易
以太坊的消息在某种程度上类似于比特币的交易,但是两者之间存在三点重要的不同。第一,以太坊的消息可以由外部实体或者合约创建,然而比特币的交易只能从外部创建。第二,以太坊消息可以选择包含数据。第三,如果以太坊消息的接受者是合约账户,可以选择进行回应,这意味着以太坊消息也包含函数概念。
1) 交易是什么
以太坊中“交易”是指由外部账户生成的一段加密签名的指令,序列化后提交给区块链网络。如:给某一账户转10以太币;创建一个智能合约。交易包含消息的接收者、用于确认发送者的签名、以太币账户余额、要发送的数据和两个被称为STARTGAS和GASPRICE的数值。
交易类型分为:消息通信和合约创建(也就是交易产生一个新的以太坊合约)。
2) 交易的数据域
一个交易的典型数据结构如下:
nonce:输出交易的次数,从0开始
gasPrice:交易中愿意花费的单位Gas的价格
gasLimit:处理交易允许花费的最大Gas量
to:交易发送到的账户,如果是空,交易就会创建合约
value:发送的以太币的量
data:可以是任意的消息或合约函数调用或创建合约的代码
3) 交易数据示例
一个发送1000wei以太并且留下消息0Xc0de 的交易可以被构造如下:
var rawTx = {
nonce: web3.toHex(0),
gasPrice: web3.toHex(20000000000),
gasLimit: web3.toHex(100000),
to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',
value: web3.toHex(1000),
data: '0xc0de'
};
注意,from地址并没有指定,在私钥签署后,它会从签名中提取。签署交易:
var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');
var transaction = new tx(rawTx);
transaction.sign(p);
6 Gas和费用
1) 费用的作用
以太坊网络中,任意一个节点执行的操作,最终会被全网所有节点执行,这就导致在以太坊网络中执行的计算操作、存储内容都是非常昂贵的。所以以太坊网络中执行的合约应该尽可能简单(例如验签),不适合进行复杂的操作(例如文件存储)。
如果没有费用的话,恶意的执行者通过执行一个包含无限循环的交易就可以很容易的让网络瘫痪而不会产生任何实际结果。对每一个命令收取一定的费用,通过这种方式可以恶意攻击者望而却步。存储同样会对网络造成负担,所以也需要支付费用。
2) 交易费用
在以太坊网络上进行的交易而产生的每一次计算,都会产生费用,这个费用是通过“gas”来支付的。
对每个交易,发送者都需要设置gas limit和gas price。gas用来表示的费用单位,gas price就是你愿意在每个gas上花费Ether的数量,以“gwei”进行衡量。gas limit * gas price代表发送者愿意为执行交易(一般为合约代码)而付出的最大以太币数量。以太坊货币单位的换算如下:
单位 |
wei值 |
Wei |
Kwei (babbage) |
1e3 wei |
1,000 |
Mwei (lovelace) |
1e6 wei |
1,000,000 |
Gwei (shannon) |
1e9 wei |
1,000,000,000 |
microether (szabo) |
1e12 wei |
1,000,000,000,000 |
milliether (finney) |
1e15 wei |
1,000,000,000,000,000 |
ether |
1e18 wei |
1,000,000,000,000,000,000 |
如果发送者提供的gas超过合约需要的以太币,在交易结束时多余的gas都会被返回给发送者。
执行交易时,如果需要的gas超过发送者提供的gas limit,交易将会被回滚,但是已经消耗的gas不会退还,发送者支付的gas都改了受益人地址(通常是矿工的地址)。因为矿工为了计算和验证交易做出了努力,所以矿工接收gas的费用作为奖励。
通常,发送者愿意支付更高的gas price,矿工从这笔交易总就能获得更多的价值。因此,矿工也就更加愿意选择这笔交易。这样的话,矿工可以自由的选择一笔交易自己愿意验证或忽略。为了引导发送者应该设置gas price为多少,矿工可以选择建议一个最小的gas值他们愿意执行一个交易。
3) 存储费用
gas不仅仅是用来支付计算这一步的费用,而且也用来支付存储的费用。存储的总费用与所使用的32位字节的最小倍数成比例。
由于增加了的存储增加了所有节点上的以太坊状态数据库的大小,所以激励保持数据存储量小。为了这个原因,如果一个交易的执行有一步是清除一个存储实体,那么为执行这个操作的费用就会被放弃,并且由于释放存储空间的退款就会被返回给发送者。
7 叔块(Uncle块)
1) 叔块是什么?
我们知道在比特币中,没有叔块的概念。那以太坊中叔块是什么,有什么作用呢?
我们假设一个场景,当多个矿工在几乎相同的时间挖出一个新区块,他们都会尝试向网络中广播自己的区块,以求此区块能成为主链的一部分,让后续所有矿工都在当前区块的基础上进行挖矿。在比特币网络中,因为主链只有一条,所以这些基于同一个父块挖出来的多个子块,最终只有一个子块能被比特币网络接受,其他子块区块会被抛弃,挖出这些被抛弃子块的矿工的工作也就白费了。但是在以太坊中,也会认同这种区块,也会给挖出这种区块的矿工一定奖励,这种区块就是所谓的叔块。
2) 区块共识时间越短,对大矿池越有利。
在比特币网络中,大约每10分钟产生一个区块,大概1个小时可以确认区块的可靠性;这是一个效率极低的网络,对于用户的体验也不友好,那为什么不通过缩短共识时间来提升用户体验呢?这是因为广播区块的时间可能需要十几秒,对于10分钟来讲这点时间并不是十分重要,正是因为如果去缩短共识间隔,中心化矿池的优势将会越来越明显,这不是去中心化网络希望看到的结果。
新区块的计算工作从收到上一个区块生成的广播开始,如果上一个区块是一个大矿池的矿工产生,那么同一个矿池内的其他矿工几乎可以立即基于这个区块挖后续的区块,但是因为广播需要一段时间,区块链网络中有些矿工需要一段时间(可能是十几秒钟)才能收到广播,这就意味着这些矿工比大矿池的矿工晚一段时间开始,而且这段时间的工作量实际上是被浪费掉了,这就是一种不公平。而这种不公平在[广播时间差/区块共识时间]比越大时,越明显。
举一个形象的例子:跑步比赛中,如果有人能提前一段时间开始跑步,那么整个比赛也就失去了公平性,想来这种比赛的结果也不会收人认同。
3) 叔块(Uncle Block)
2013年10月,由乔森纳和特拉维夫首次提出的GHOST协议是加快生成区块时间的第一个认真尝试,GHOST的目的是要解决挖矿过时造成的安全性降低的问题。Ghost协议的详细内容参考《以太坊-GHOST协议》,这里仅简单介绍一下此协议。
以太坊通过引入叔块(Uncle Block)来解决这个问题(可以理解为叔块是GHOST协议的实现),将共识间隔减少到了15秒钟,在支付确认速度上较比特币有了很大的提升。
在以太坊网络中,在基于同一个父区块进行挖矿时,如果一个大矿池的矿工A挖出一个区块(BlockA),并广播到网络中,与此同时矿工B也挖出一个区块(BlockA),并进行广播,但因为B只有一条有效的主链的,所以最终只有一个区块能成为主链的一部分(假设是BlockA),那么BlockB成为下一个区块的叔块。叔块仅仅提供工作量证明,其中所包含的交易是无效的。
共识时间越短,大矿池中因为所有矿工几乎能立即基于新挖出的区块进行挖矿,对其他矿工来说的不公平就越大,通过引入叔块,对挖出叔块的矿工进行补偿。
二 以太坊原理
1 以太坊区块链
1) 区块链结构
2) Block Header
Header是区块的核心。
a) Header主要内容
ParentHash:指向父区块(parentBlock)的指针。除了创世块(Genesis Block)外,每个区块有且只有一个父区块。
Coinbase:挖掘出这个区块的作者地址。在每次执行交易时系统会给与一定补偿的Ether,这笔金额就是发给这个地址的。
UncleHash:Block结构体的成员uncles的RLP哈希值。uncles是一个Header数组,它的存在,颇具匠心。
stateHash:StateDB中的“state Trie”的根节点的RLP哈希值。Block中,每个账户以stateObject对象表示,账户以Address为唯一标示,其信息在相关交易(Transaction)的执行中被修改。所有账户对象可以逐个插入一个Merkle-PatricaTrie(MPT)结构里,形成“state Trie”。
transactionHash: Block中“tx Trie”的根节点的RLP哈希值。Block的成员变量transactions中所有的tx对象,被逐个插入一个MPT结构,形成“tx Trie”。
ReceiptHash:Block中的"Receipt Trie”的根节点的RLP哈希值。Block的所有Transaction执行完后会生成一个Receipt数组,这个数组中的所有Receipt被逐个插入一个MPT结构中,形成"Receipt Trie"。
Bloom:Bloom过滤器(Filter),用来快速判断一个参数Log对象是否存在于一组已知的Log集合中。
Difficulty:区块的难度。Block的Difficulty由共识算法基于parentBlock的Time和Difficulty计算得出,它会应用在区块的‘挖掘’阶段。
Number:区块的序号。Block的Number等于其父区块Number +1。
Timestamp:区块“应该”被创建的时间。由共识算法确定,一般来说,要么等于parentBlock.Time + 10s,要么等于当前系统时间。
GasLimit:区块内所有Gas消耗的理论上限。该数值在区块创建时设置,与父区块有关。具体来说,根据父区块的GasUsed同GasLimit * 2/3的大小关系来计算得出。
GasUsed:区块内所有Transaction执行时所实际消耗的Gas总和。
Nonce:一个64bit的哈希数,它被应用在区块的"挖掘"阶段,并且在使用中会被修改。
b) MPT
Header中stateRoot、transactionsRoot、receiptsRoot都对应一颗Merkle Patricia Tree,其对于整个以太坊网络数据的维护、安全都有着极其重要的影响,具体可以参考《Merkle Patricia Tree原理》
3) Block Body
Body主要记录交易数据。
2 难度更新算法
1) 更细规则
目前以太坊通过以下规则进行难度更新:
diff(genesis) = 2^32
diff(block) = diff.block.parent + floor(diff.block.parent / 1024) *
1 if block.timestamp - block.parent.timestamp < 9 else
-1 if block.timestamp - block.parent.timestamp >= 9
2) 设计目标
难度更新规则的设计目标如下:
- 快速更新:区块间的时间应该随着hash算力的增减而快速调整;
- 低波动性:如果Hash算力恒定,那么难度不应剧烈波动;
- 简单:算法的实现应相对简单;
- 低内存:算法不应依赖于过多的历史区块,要尽可能少的使用”内存变量“。假设有最新的十个区块,将存储在这十个区块头部的内存变量相加,这些区块都可用于算法的计算;
- 非开发性:算法不应让矿工有过多篡改时间戳或者矿池、反复添加或删除算力的能力,以使他们的收益最大化。
3 以太坊架构
1) 以太坊软件架构
以太坊软件架构分为三层:底层服务、核心层、顶层应用。
可以将以太坊虚拟机想象成一个操作系统,它能理解并执行通过以太坊特定编程语言编写的软件。由以太坊虚拟机执行的软件/应用程序被称为“智能合约”。
2) 底层服务
底层服务包括P2P网络服务、LevelDB数据库、密码学算法、分片优化等。
P2P网络中每一个节点都是彼此对等,各个节点共同提供服务,不存在任何特殊的节点,网络中的节点可以生成合生和新数据。
以太坊中的区块、交易等数据最终都是被存储在LevelDB数据库中。
密码学算法用于保证数据的隐私性和区块链的安全性。
分片优化师德可以并行验证交易,加快区块生成速度。
3) 核心层
以区块链为主体,以太坊特有的共识算法为辅助,并以EVM(以太坊虚拟机)作为运行智能合约的载体,他们构成以太坊的核心部分。
EVM是以太坊中智能合约的运行环境,使得以太坊能够实现复杂的逻辑。
4) 顶层应用
主要包括API接口、智能合约、去中心化应用(Decentralized Application,即DApp)、域名服务。
三 参考资料
1 书籍
《以太坊技术详解与实战》
2 博客
《比特币原理简介》
《区块链》
《区块链-区块结构》
科普| 以太坊是什么——以太坊创始人Vitalik Buterin 的亲自解答
白皮书| 以太坊(Ethereum ):下一代智能合约和去中心化应用平台