# 雏凤清声

By [choovybi](https://paragraph.com/@choovybi) · 2022-09-13

---

> 以太坊的目的是创建一个用于建立去中心化应用的替代协议，我们认为提供一套不同的折衷方案对大量去中心化应用非常有用，尤其是那些强调快速开发、小型和不常用应用的安全性，以及应用间高效交互能力的程序。——_Vitalik Buterin_

比特币之后，市面上出现了许多使用区块链技术的加密货币，但其中的大部分最后都消失了。究其原因，是这些空气币发行之初并没有明确的目标，人们不明白为什么非它不可。与其用XX币，为什么不用比特币呢？这是新生的加密货币都亟需回答的问题。而上面这段_Vitalik_写在以太坊白皮书中的话，很大程度上解释了人们的疑惑，即“为什么是以太坊”？

博文是对以太坊[白皮书](https://ethereum.org/zh/whitepaper/)和[黄皮书](https://ethereum.github.io/yellowpaper/paper.pdf)的个人理解，[欢迎讨论](https://linktr.ee/choovybi)。

两个系统
----

抽象的来说，去中心化的加密货币都可以用两个系统来表示：

*   状态系统
    
*   共识系统
    

其中状态系统包含：状态表示，状态转移；共识系统包含：区块创建、证明方式、激励等等。状态系统用来表示人们转账、支付等经济行为如何改变各自的状态；共识系统用来表示状态的改变如何被公众所认可。

以比特币为例，比特币状态系统的核心是UTXO。比特币的状态表示是指特定地址拥有多少UTXO，而状态转移则是指UTXO被消耗并生成新的UTXO的过程。

![UTXO被消耗生成新的UTXO（比特币的状态转移）](https://storage.googleapis.com/papyrus_images/ee21eda75b98003d5578929aaf685d0a2e13f5a82ef20dce67fbd59dc5222c3b.png)

UTXO被消耗生成新的UTXO（比特币的状态转移）

比特币使用[工作量证明（POW）](https://nakamotoinstitute.org/finney/rpow/)来进行区块的创建，使用_Merkel_根来防止交易被篡改，同时加入了“挖矿”激励，人们出于利益驱使会信任包含最多工作量的那条链，这使得“共识”得以产生。

但中本聪在创建比特币时可能是出于匿名性的考虑，使用的是UTXO配合不断变换的地址，而不是使用固定地址的钱包来表示状态，这带来了一些问题：

*   状态的数量太少：UTXO的状态只能是已使用或未被使用（1或者0）
    
*   价值盲：UTXO使用时要么全部使用，要么为0
    
*   区块链盲：UTXO看不到区块链上的信息，看到也无用，因为状态数太少没有办法处理这些信息
    
*   脚本图灵不完备：比特币虽有脚本语言，但是图灵不完备，脚本无法实现无限循环等功能，运行效率低下
    

为了应对比特币上述的种种问题，同时也为了创建一个去中心化应用友好的替代协议，以太坊诞生了。

为什么是以太坊
-------

以太坊和比特币系统的差异很大，接下来分状态系统、共识系统这两方面来说，下图是以太坊的结构示意图：

![以太坊结构](https://storage.googleapis.com/papyrus_images/60dadcccc1f6e3ca9d9fa11cc73e34b80af15de5e890f41706a116ec0044344e.jpg)

以太坊结构

### 状态表示

不同于比特币用UTXO来表示状态，**以太坊的世界状态由外部账户和合约账户组成，他们都采用普通记账（即余额，而不是UTXO）的方式来记账**。

外部账户的地址由公钥哈希产生，外部账户通过私钥可以被外部用户所控制，一般被当作用户存钱的账户；合约账户的地址在创建时刻通过创建者地址和随机数生成，合约账户自动运行无人控制，一般被当作部署自动化应用的账户。

这些世界状态只存在记账节点和验证节点运行的[以太坊虚拟机（EVM）](https://ethereum.org/zh/developers/docs/evm/)中，在区块链中我们只能看到世界状态的[默克尔帕特里夏根（MPT root](https://ethereum.org/zh/developers/docs/data-structures-and-encoding/patricia-merkle-trie/)）。

### 状态转移

**以太坊的状态转移有两种方式：交易和消息**。

先说消息，消息是世界状态内账户之间发送的信息，仅仅在 EVM 上存在，消息不会被记录在区块链上。根据发送账户和接受账户的不同，共有四种消息：外部账户-外部账户，外部账户-合约账户，合约账户-外部账户，合约账户-合约账户。

而交易是外部用户发送给以太坊的信息，交易会被记录在区块链上，交易共有两种类型：

*   合约创建交易：该类型交易，接收者的地址为0，数据部分为“ EVM 合约创建标志符”和初始代码，以太坊节点运行的 EVM 在收到该交易后会按要求创建一个合约账户；
    
*   消息调用交易：该类型交易，接收者为160bits地址，数据部分需要提供标志符和消息调用的具体信息（例如图中的输入数据），以太坊节点运行的 EVM 在收到该交易后会按要求往接收者地址所在位置进行消息调用（例如图中“输入数据”更改了合约账户的存储）。
    

节点的 EVM 在收到交易进行状态转移时会按照以下步骤操作

1.  检测交易是否有效，交易格式是否正确
    
2.  计算 gas fee，从交易发送账户扣除 gas fee 并增加发送账户的随机数
    
3.  根据交易中的每个字节，扣除 gas
    
4.  将交易金额从发送账户转移到接收账户，如果接收账户不存在，创建接收账户；如果接收账户是合约账户，则运行该合约的代码，直到代码运行结束或 gas 耗尽（如果接收账户不是合约账户，只需要付每个字节的 gas）
    
5.  如果因为 gas 耗尽导致交易失败，回滚所有状态，并把 gas 支付给矿工；如果交易成功，则将剩余 gas 退还给发送账户，消耗的 gas 支付给矿工。
    

### 节点

以太坊和比特币在共识系统上的差别没有像在状态系统上那么大，他们都是使用工作量证明 POW（以太坊预计2022年9月中合并成质押证明 POS ）来达成共识，即工作量最大的子串最被节点所相信，节点会选择在最长子串上进行挖矿等等。具体可以看之前写的关于[比特币的共识系统](https://mirror.xyz/choovybi.eth/7pX6TiFWVhDwWPsL93irmFVQrrf5iO8CozlBg7Wc8Ts)，这里主要介绍他们共识系统上的不同。

以太坊的节点进行挖矿和验证的过程比比特币更复杂。

以太坊区块验证：

1.  检查父区块是否有效
    
2.  检查当前时间戳是否有效
    
3.  检查当前区块的编号、难度、gas、交易根、叔根等是否有效
    
4.  检查当前区块的工作量证明是否有效
    
5.  按照上面所提到的步骤，根据区块体中包含的交易进行世界状态转移
    
6.  最后添加支付给矿工的区块奖励
    
7.  检查当前区块的状态根和最终状态是否匹配
    

以太坊节点进行挖矿：

1.  记录父区块
    
2.  记录当前时间戳
    
3.  记录当前区块的编号、难度、gas、交易根，添加叔根
    
4.  进行哈希碰撞来完成工作量证明
    
5.  根据区块体中包含的交易进行世界状态转移（完成交易、运行智能合约代码）
    
6.  记录支付给矿工（即挖矿节点自己）的区块奖励
    
7.  记录当前区块的状态根
    
8.  广播已完成挖矿的区块
    

也不同于在比特币中，每个节点只是一个记账本。在以太坊中，**每一个节点都运行着一个 EVM 用来实现交易、运行智能合约以实现状态的转移**，EVM 无论在状态系统还是共识系统都处在核心位置。EVM 的详细结构在这里不赘述，但需要了解的是，EVM 是图灵完备的，他跟我们日常使用的windows虚拟机的计算能力是一样的。很多人会将以太坊称作“世界计算机”，就是因为每个节点运行一个 EVM 这样的设计。

### 图灵完备

_Valtalik_提到，以太坊一个很大的进步在于 EVM 是图灵完备的。我们在电脑上能实现的功能，放到 EVM 上都可以实现，这就使得链上游戏、链上APP等成为了可能。

然而图灵完备的计算机没有办法解决“停机问题”，即：我们无法根据程序的代码描述和输入来判断程序会终止还是会永远运行下去。

“停机问题”无解的证明，基于罗素的“理发师悖论”。

> 理发师悖论：有一个理发师，只为不给自己理发的所有人理发，那么这位理发师为自己理发吗？如果他为自己理发，那么根据理发师“**只为不给自己理发的**所有**人理发**”的原则，他就不给自己理发；如果他不为自己理发，那么根据理发师“只**为不给自己理发的所有人理发**”的原则，他就为自己理发；均矛盾。

我们先假设“停机问题”有解，即存在一个函数 _f_ 能判断程序是否停机

    def f(code):
      if (code stops):
        return True  # 如果code会终止，返回True(停机)
      else:
        return False  # 如果code不终止，返回False
    

那么我们可以定义另一个函数 _g_

    def g(code):
      if (f(code) == True):
        while(1)  # 如果code会终止，g死循环
      if (f(code) == False):
        return  # 如果code不终止，g返回值
    

这样我们就获得了一位“理发师”，假设函数 _g_ 的代码我们记作 _code\_g_ 。那么 _g(code\_g)_ 会怎么样呢？

*   如果 _f(code\_g)_ 返回 True，则说明函数 _g_ 会终止，而此时函数 _g_ _while(1)_ 进入死循环，矛盾
    
*   如果 _f(code\_g)_ 返回 False，则说明函数 _g_ 不终止，而此时函数 _g_ _return_ 返回了值，矛盾
    

通过反证法，能得出结论，解决“停机问题”的函数 _f_ 不存在。

EVM 既然是图灵完备的，那么在 EVM 上运行的程序，也是无法事先被判断能否终止的。如果攻击者向网络中注入死循环的恶意程序，就可以迫使矿工卡住，使得节点无法完成处理、验证交易这样的正常功能。

以太坊使用gas fee和回滚机制来解决程序死循环的问题。EVM 上程序每运行一步，都要消耗gas，当gas耗尽程序如果还没有结束运行，则程序会回滚，并且把消耗的gas fee支付给矿工。通过引入gas fee，以太坊使得 EVM 在图灵完备的同时，节点不会被恶意程序卡死，维持了整个以太坊网络的安全。

### 叔叔区块

以太坊认可了叔叔节点，来降低节点产生陈腐区块的风险。在比特币中，假设两个节点同时挖出了当前最新的区块并广播了出去，那么收到广播的其他节点会短暂分叉，然后在新一轮区块挖掘中，必定有一个分叉获胜先挖出了下一区块，这时所有的节点会转移到获胜的分叉上进行挖矿，则失败的分叉就产生了陈腐区块。

当个人算力与网络整体算力相比微乎其微时，个人挖掘的区块大多数情况下都是陈腐区块，在这种情况下，个体挖矿者常常不得不加入一个大的矿池与他人一起挖矿，比特币事实上挖矿层面重新变成了中心化结构。同时，陈腐区块本身也蕴含着庞大的工作量，如果完全忽略陈腐区块，我们对区块链所包含的工作量的估计会出现严重的偏差，这也违背了工作量证明的初衷。

而以太坊允许新区块 B 在创建的时候包含 2-7 代内的叔块 U ，对于区块 B 中的每个叔块 U，区块 B 的矿工获得额外 3.125% 的铸币奖励，而叔块 U 的矿工获得 93.75% 的标准铸币奖励。因为限制了叔块必须是 2-7 代之内，所以以太坊也有效避免了矿工一直在陈腐的分叉上进行挖矿。

尾记
--

正如_Vitalik_在白皮书中所说的，以太坊为大量去中心化应用提供了一个不同的折衷方案，以太坊通过其强大的 EVM 实现了这一点。但 EVM 的具体结构，以及节点如何运行虚拟机进行交易的验证，在本文中都没有详细展开，因为我认为 EVM 过于重要，且内容非常丰富，值得接下来再写一篇博客来认真描述。

今天就到这里，再见。

subscribe://

---

*Originally published on [choovybi](https://paragraph.com/@choovybi/1PUekJInDpu0JXS8bie8)*
