以太坊的三棵树,详解状态、交易与收据树的奥秘

在以太坊这个庞大而复杂的去中心化世界里,数据的一致性和可追溯性是维持其正常运转的基石,为了高效、安全地管理海量的状态数据、交易记录和执行结果,以太坊借鉴了Merkle树(默克尔树)这一强大的数据结构,有三棵至关重要的“Merkle树”,它们共同构成了以太坊数据模型的骨架,分别是状态树、交易树和收据树,本文将深入探讨这三种树的结构、功能及其在以太坊生态系统中的核心作用,并配以形象的比喻和图示,帮助您彻底理解它们。

图1:以太坊三种树的结构关系示意图

这是一个概念图,用于辅助理解三棵树在区块中的位置和关系

 ----------------------------------------------------- 
|                 以太坊区块                          |
|                                                     |
|   -----------------------    -----------------------  |
|  |      区块头            |  |      区块体            | |
|  |-----------------------|  |-----------------------| |
|  | Parent Hash, ...      |  |                       | |
|  | State Root (状态根)   |----> [状态树]             | |
|  | Tx Root (交易根)      |----> [交易树]             | |
|  | Receipt Root (收据根) |----> [收据树]             | |
|  | ...                   |  |                       | |
|   -----------------------    -----------------------  |
|                                                     |
 ----------------------------------------------------- 

图1说明:区块头中包含了指向三棵树根哈希的指针,这三棵树则存储在区块体中,这种设计确保了状态的完整性和数据的可验证性。


第一棵树:状态树 - 以太坊的“世界名册”

功能与作用: 状态树是整个以太坊网络当前状态的“快照”,它记录了每一个账户(无论是外部账户EOA还是合约账户)的所有信息,这包括账户的余额、nonce值、合约代码(如果是合约账户)以及存储在合约中的数据,如果你想查询任何一个地址当前的余额、代码或存储内容,你都需要查询状态树。

结构特点: 状态树是一个前缀树,其键是账户地址的20字节哈希值,这种结构使得查找、插入和更新账户信息非常高效,平均时间复杂度为O(log n),其中n是账户的数量。

为什么它至关重要? 状态树是以太坊状态同步和轻客户端验证的基础,当一个新节点加入网络时,它需要从创世区块开始,一直同步到最新的区块,来重建完整的状态树,由于区块头中包含了状态树的根哈希,任何人都可以通过计算本地状态树的根哈希并与区块头中的值进行比对,来验证整个网络状态的正确性,无需下载全部数据。

图2:状态树结构示意图

                    [状态树根]
                         |
              ----------- ----------- 
             |           |           |
     [账户A哈希]   [账户B哈希]   [账户C哈希]
             |           |           |
       ------ ------    |    ------ ------ 
      |      |      |   |   |      |      |
  [余额] [Nonce] [代码] | [余额] [Nonce] [存储]
      |      |      |   |   |      |      |
    100...   5    ...   | 50...   3    ...

图2说明:状态树的每个叶子节点都代表一个以太坊账户,包含了该账户的所有关键信息。


第二棵树:交易树 - 区块内的“执行清单”

功能与作用: 交易树存储了某个特定区块内包含的所有交易数据,它是一个按顺序排列的记录,展示了区块内每一笔交易的详细信息,例如发送方、接收方、交易金额、数据负载、Gas限制和Gas价格等,你可以把它想象成这个区块的“执行清单”或“议事录”。

结构特点: 交易树也是一个Merkle树,它的叶子节点是区块中每一笔交易数据的哈希,交易在树中的顺序与它们被包含在区块中的顺序一致,这使得网络中的任何节点都可以快速验证一笔交易是否确实存在于某个特定的区块中。

为什么它至关重要? 交易树是实现交易可追溯性和可验证性的关键,通过交易树的根哈希(位于区块头中),你可以验证一笔交易是否被包含在某个区块内,以及该交易在区块中的确切位置,这对于交易历史查询、钱包软件以及各种区块链浏览器都至关重要。

图3:交易树结构示意图

                    [交易树根]
                         |
            -------------- -------------- 
           |              |              |
   [交易1哈希]     [交易2哈希]     [交易3哈希]
           |              |              |
    ------- -------    --- ---    ------- ------- 
   |  发送方, 接收方 |  | ...  |  |  发送方, 接收方 |
   |  金额, 数据... |  | ...  |  |  金额, 数据... |

图3说明:交易树的每个叶子节点代表一笔完整的交易数据,所有交易按区块内的顺序排列。


第三棵树:收据树 - 交易的“执行报告”

功能与作用: 收据树是三棵树中最容易被误解,但同样至关重要的一棵,它不存储交易本身,而是存储每笔交易执行后的结果报告,即“收据”(Receipt),这个报告告诉我们交易是否成功执行、消耗了多少Gas、以及最重要的——它触发了哪些日志事件。

结构特点: 收据树也是一个Merkle树,其叶子节点与交易树中的交易一一对应,顺序也完全相同,每一份收据都包含以下信息:

  • 状态: 一个布尔值,表示交易执行是成功还是失败。
  • Gas Used: 交易执行实际消耗的Gas数量。
  • 日志: 这是收据的核心,合约在执行过程中可以产生日志,这些日志被记录在收据中,事件监听、DeFi协议的索引、跨链桥的安全确认等,都依赖于这些日志数据。

为什么它至关重要? 收据树是智能合约与外部世界交互的桥梁,它将链上计算产生的结果(尤其是日志)永久地记录下来,使得这些结果可以被其他链下应用(如The Graph索引服务)所查询和利用,没有收据树,我们将难以追踪DeFi活动的发生、验证NFT的铸造或实现复杂的链上事件分析。

图4:收据树结构示意图

                    [收据树根]
                         |
            -------------- -------------- 
           |              |              |
   [收据1哈希]     [收据2哈希]     [收据3哈希]
           |              |              |
    ------- -------    --- ---    ------- ------- 
   | 状态: 成功   |  | ...  |  | 状态: 失败 |
   | Gas Used: 21k|  | ...  |  | Gas Used: 5k |
   | 日志: [...]  |  | ...  |  | 日志: []    |

图4说明:收据树的每个叶子节点对应一笔交易的执行结果,包含了状态、Gas消耗和关键的日志信息。


三棵树的协同工作

这三棵树并非孤立存在,而是协同工作,共同构成了以太坊数据完整性的闭环,在一个新区块被创建时,这个过程如下:

  1. 矿工/验证者收集一批待处理的交易。
  2. 他们将这些交易按照特定顺序打包,并构建一棵交易树
  3. 他们按顺序执行这些交易,更新以太坊的全局状态,每执行一笔交易,就会生成一份收据,所有交易执行完毕后,他们构建一棵收据树
  4. 所有交易对状态造成的改变(例如转账、合约调用等)最终会反映在一棵新的状态树上。
  5. 计算这三棵树的根哈希值,并将它们写入新区块的区块头中。

相关文章