上次的关于比特币的文章其实有很大一部分是参考以太坊白皮书的前半部分的分析,这篇文章在上一篇的基础上重点说一下以太坊与比特币的区别。以及以太坊的主要实现逻辑。
以太坊
以太坊模型说明
状态机
以太坊的本质就是一个基于交易的状态机(transaction-based state machine)。在计算机科学中,一个状态机是指可以读取一系列的输入,然后根据这些输入,会转换成一个新的状态出来的东西。
根据以太坊的状态机,我们从创世纪状态(genesis state)开始。这差不多类似于一片空白的石板,在网络中还没有任何交易的产生状态。当交易被执行后,这个创世纪状态就会转变成最终状态。在任何时刻,这个最终状态都代表着以太坊当前的状态。
以太坊的目标
密码学货币上建立高级应用的三种方法:
- 建立一个新的区块链
- 在比特币区块链上使用脚本
- 在比特币区块链上建立元币协议
- 建立新区块链的方法可以自由地实现任意的特性,成本是开发时间和培育努力。使用脚本的方法非常容易实现和标准化,但是它的能力有限。元币协议尽管非常容易实现,但是存在扩展性差的缺陷。在以太坊系统中,以太坊的目的是建立一个能够同时具有这三种模式的所有优势的通用框架。
以太坊的目的是基于脚本、竞争币和链上元协议(on-chain meta-protocol)概念进行整合和提高,使得开发者能够创建任意的基于共识的、可扩展的、标准化的、特性完备的、易于开发的和协同的应用。以太坊通过建立终极的抽象的基础层-内置有图灵完备编程语言的区块链-使得任何人都能够创建合约和去中心化应用并在其中设立他们自由定义的所有权规则、交易方式和状态转换函数。域名币的主体框架只需要两行代码就可以实现,诸如货币和信誉系统等其它协议只需要不到二十行代码就可以实现。智能合约-包含价值而且只有满足某些条件才能打开的加密箱子-也能在我们的平台上创建,并且因为图灵完备性、价值知晓(value-awareness)、区块链知晓(blockchain-awareness)和多状态所增加的力量而比比特币脚本所能提供的智能合约强大得多。
区块链结构
在以太坊交易完成时,都被矿工打包到一个区块中,也就是说一个区块包含一系列交易,而每个区块的头部又指向上一个区块,这中间的链接与区块组合起来就是我们说的区块链。
以太坊账户
概述
以太坊的状态是由账户之间进行交易(转移价值和信息的状态转换结构)构成的。账户包含了四个部分:
- 随机数,用于确定每笔交易只能被处理一次的计数器
- 账户目前的以太币余额
- 账户的合约代码(如果有的话)
- 账户的存储(默认为空)
账户的源码定义如下:
typeAccountstruct
{
Nonce uint64
Balance *big.Int
Root common.Hash//merklerootofthestoragetrie
CodeHash[]byte
}
- Nonce:如果当前账户为EOA,则Nonce为发送的交易序号;如果当前账户为CA,则Nonce为合约创建的序号。
- Balance:账户余额,表示账户所对应地址的余额。
- Root:存储Merkle Patricia树的根节点Hash值(我们后面在解释Merkle树),在EOA中,此字段为空。
- CodeHash:账户绑定的EVM code的hash值,对于合约账户,就是被Hash的代码并作为codeHash保存;在EOA中,此字段为空。
外部账户(EOA)
一般自然人分配的账户,被私钥控制且没有任何代码与之关联。
合约账户(CA)
给智能合约分配的账户,被合约代码控制且有代码与之关联。
EOA 与 CA的比较
两个EOA之间的消息传递只是一个简单的价值转移。但是一个EOA到CA的消息则会激活CA内部的代码,允许执行各种动作(比如转移代币,写入内部存储,挖出一个新代币,执行一些运算,创建一个新的合约等等),因此以太坊要比比特币的应用场景更广(下文会提到以太坊的几个应用场景)
而对于CA来说,它不能自己发起一个交易。相反只能接收到一个EOA发起的交易之后,激活代码而触发对另一个CA的交易。
外部所有的账户没有代码,人们可以通过创建和签名一笔交易从一个外部账户发送消息。每当合约账户收到一条消息,合约内部的代码就会被激活,允许它对内部存储进行读取和写入,和发送其它消息或者创建合约。
所以,以太坊上的任何交易都是被EOA所触发的。
消息和交易
以太坊消息和比特币交易的不同点
- 以太坊的消息可以由外部实体或者合约创建,然而比特币的交易只能从外部创建
- 以太坊消息可以选择包含数据
- 如果以太坊消息的接受者是合约账户,可以选择进行回应,这意味着以太坊消息也包含函数概念
交易(Transaction)
交易存储了发送者要发送至以太坊网络的经过签名的信息,它其中包含了从一个账户要传递给另一个账户(或者合约)的信息。在以太坊中,有两种类型的交易:一种是能够产生消息调用的交易,另一种是能够生成新账户的交易(比如说生成合约)。
交易的组成
- 交易的接收者
- 签名(用以核实交易已发送者身份)
- value值(发送的以太币数量,以wei为单位)
- 可选数据域
- STARTGAS值
- GASPRICE值
交易中的字段
黄皮书对交易的描述
A piece of data, signed by an External Actor. It represents either a Message or a new Autonomous Object. Transactions are recorded into each block of the blockchain.
由外部参与者签名后的一段数据。它代表了一条信息或者一个新创建的自治对象(合约)。交易会被记录至区块链的区块中。
根据以太坊黄皮书,交易具有以下字段:
- nonce:该字段表示的是交易发送者的交易序列号,它是账号的一个交易计数器,这个字段能够防止重放攻击(replay attack)。
- gasPrice:gas的价格,用于计算交易费用
- gasLimit:执行这笔交易所花费的gas的上限
- to:交易接收者的地址或者合约的地址
- value:要发送的以太币数量,以wei为单位
- v, s, r:签名相关的参数,通过这三个参数可以得到发送者的公钥和地址(更详细的内容参见以太坊黄皮书附录F)
如果该交易是由合约创建的,还可能包含如下字段:
- init:用于初始化交易的EVM(以太坊虚拟机)操作码
- data:数据域(理论上数据域的大小是不受限制的)
消息(Message)
先看黄皮书上的一段话:
Data (as a set of bytes) and Value (specified as Ether) that is passed between two Accounts, either through the deterministic operation of an Autonomous Object or the cryptographically secure signature of the Transaction.
在两个账户之间传输的数据(一组字节)和值(以太币的数量),形式是合约的确定性操作或者经过了加密安全签名的交易。
所以我的理解是:消息应该是包含交易的,引用中的“形式是合约的确定性操作或者经过加密安全签名的交易”的前半部分指的是由合约发出的、永远不会被记录到区块链当中的、“虚拟”的事物,并且可以将此类消息看做在EVM中的函数调用;而后半部分指的是被永久记录在链上的、由外部账户(EOA)触发的交易。
费用(fees)与瓦斯(gas)
这两个概念比较好理解,费用就是在每笔交易进行的时候,收取的“手续费”;而瓦斯则是用于支付费用的材料,以“gwei”进行衡量,这里有两个换算公式:
对每个交易,发送者设置gas limit和gas price。gas limit和gas price就代表着发送者愿意为执行交易支付的Wei的最大值。
例如,假设发送者设置gas limit为50,000,gas price为20gwei。这就表示发送者愿意最多支付50,000*20gwei = 1,000,000,000,000,000 Wei = 0.001 Ether来执行此交易。
记住gas limit代表用户愿意花费在gas上的钱的最大值。如果在他们的账户余额中有足够的Ether来支付这个最大值费用,那么就没问题。在交易结束时任何未使用的gas都会被返回给发送者,以原始费率兑换。
在发送者没有提供足够的gas来执行交易,那么交易执行就会出现“gas不足”然后被认为是无效的。在这种情况下,交易处理就会被终止以及所有已改变的状态将会被恢复,最后我们就又回到了交易之前的状态—完完全全的之前状态就像这笔交易从来没有发生。因为机器在耗尽gas之前还是为计算做出了努力,
所以理论上,在gas limit 不够并且还执行交易的情况下,将不会有任何的gas被返回给发送者(因为运行到一半就消耗光了,所以交易终止,状态还原)。
这些gas的钱到底去了哪里?发送者在gas上花费的所有钱都发送给了“受益人”地址,通常情况下就是矿工的地址。因为矿工为了计算和验证交易做出了努力,所以矿工接收gas的费用作为奖励。
通常,发送者愿意支付更高的gas price,矿工从这笔交易总就能获得更多的价值。因此,矿工也就更加愿意选择这笔交易。这样的话,矿工可以自由的选择一笔交易自己愿意验证或忽略。为了引导发送者应该设置gas price为多少,矿工可以选择建议一个最小的gas值他们愿意执行一个交易。
存储也有费用,gas不仅仅是用来支付计算这一步的费用,而且也用来支付存储的费用。存储的总费用与所使用的32位字节的最小倍数成比例。
存储费用有一些比较细微的方面。比如,由于增加了的存储增加了所有节点上的以太坊状态数据库的大小,所以激励保持数据存储量小。为了这个原因,如果一个交易的执行有一步是清除一个存储实体,那么为执行这个操作的费用就会被放弃,并且由于释放存储空间的退款就会被返回给发送者。
注意, gas limit是由原始交易的外部创建者决定的(也就是外部拥有账户)。所以,在合约之间的消息传递是不会发生收取费用的,也就是说内部交易或者消息不包含gasLimit 。
一些体会
在阅读白皮书的时候同时又查阅了很多资料,这中间最让我感到疑惑的就是消息与交易的区别,这个实在是一头雾水,只能说有一个初步的了解,不过决定不再细抠概念了,还是尝试着自己写写代码吧,可能会有一些收获。
还有就是为什么没有写以太坊的挖矿过程,首先,以太坊的挖矿过程几乎和比特币一样,有时间我会把我的另一篇关于比特币的文章再充实一下;再者,针对对区块链挖矿的过程会有更优秀的一些文章讲的更详细,我就没太大必要去写了;最后,挖矿其实不是一个很难理解的过程,读者应该随便找一些资料就可以理解了。