16.ETH-状态树-北大肖臻老师客堂笔记

北京大学肖臻老师《区块链技术与应用》公开课第 15 讲的主题是**"以太坊的状态树" (The State Tree)**。

这一讲深入到了以太坊的底层数据结构,解释了以太坊是如何在区块头中存储"全网状态"的。这节课是理解以太坊"世界计算机"本质的关键,因为它解决了**"如何高效存储和验证海量账户状态"**的难题。

以下是本课内容的结构化详细总结

一、 核心问题:如何存储状态?

在上一讲中我们知道,以太坊采用账户模型 (Account-based),系统需要维护一个巨大的映射(Mapping):

Addr State (Balance, Nonce, CodeHash, StorageRoot)

我们需要一种数据结构来存储这个映射,并满足以下苛刻要求:

  1. 高效查找与更新:状态随着每个区块都在变化,必须能快速修改。
  2. Merkle Proof 支持:轻节点需要能验证某个账户的余额,而不需要下载全网状态。
  3. 持久化与历史溯源:需要能回滚到任意一个历史区块的状态。

二、 方案演进推导 (Evolution of Data Structures)

肖老师按照"提出方案 -> 发现问题 -> 改进方案"的逻辑进行了推导:

1. 哈希表 (Hash Table)
  • 思路:直接用哈希表存状态。
  • 缺陷:虽然查找快,但在构建 Merkle Proof 时非常困难。如果把所有账户哈希成一个根,每次修改一个账户都要重新计算整个哈希树,效率极低。
2. 直观的 Merkle Tree
  • 思路:将所有账户数据排序后,构建一个标准的 Merkle Tree。
  • 缺陷
  • 插入代价大:如果有新账户创建,插入到数组中间会导致后面的数据全部移动,整棵树大部分都要重构。
  • 非确定性:如果没有严格排序,包含相同数据的树可能有不同的 Root Hash。
3. Trie (前缀树/字典树)
  • 思路:使用账户地址(Address)作为路径,一位一位地向下查找。

  • 优点

  • 局部更新:修改一个账户,只影响该分支的哈希值,不影响其他分支。

  • 有序性:无论插入顺序如何,只要数据集合相同,构建出的 Trie 结构是唯一的(Determinism)。

  • 缺陷

  • 效率低:以太坊地址是 160 位(40 个 16 进制字符),会导致树的高度非常高(40 层)。

  • 稀疏:绝大多数路径是空的,浪费存储空间。

4. Patricia Trie (压缩前缀树)
  • 改进 :如果某个节点只有一条路径(比如 "app" 下面只有 "apple"),就将路径压缩合并。
  • 效果:降低了树的高度,提高了效率。

三、 终极方案:Merkle Patricia Trie (MPT)

以太坊最终采用的是 MPT,结合了 Merkle Tree 的加密验证功能和 Patricia Trie 的路径压缩功能。

1. 三种节点类型

为了实现压缩和分支,MPT 设计了三种特殊的节点结构:

  • Leaf Node (叶子节点)

  • 表示路径的终点。

  • 包含:[剩余路径, 账户值]

  • Extension Node (扩展节点)

  • 用于路径压缩(就像高速公路)。

  • 包含:[共享路径, 下一个节点的哈希]

  • Branch Node (分支节点)

  • 用于分岔(就像十字路口)。

  • 包含:[0-F (16个分支), Value]。因为以太坊使用 16 进制,所以每个节点最多有 16 个孩子。

2. 状态存储逻辑
  • Key:账户地址的哈希值(Sha3(Address))。为什么不直接用 Address?为了防止黑客构造特定地址让树变得极度不平衡(DoS 攻击)。
  • Value:账户状态的 RLP 编码(Balance, Nonce...)。
  • 数据库 :虽然逻辑上是一棵树,但物理上这些节点都是以 Key-Value 对的形式存储在 LevelDB 中的。

四、 状态树的特性 (Properties)

1. 根哈希 (Root Hash)

每个区块头里包含一个 Root 字段。这个 Root 是当前时刻全网所有账户状态构建出的 MPT 的根哈希。

  • 防篡改:只要状态有一丝变化,Root 就会彻底改变。
  • 轻节点验证:轻节点只存 Block Header,可以通过向全节点请求 Merkle path 来验证某个账户的余额。
2. 状态共享 (Data Sharing)
  • 问题:每个区块都生成一个新的 MPT,数据量会不会爆炸?
  • 机制不会 。因为大部分账户在两个相邻区块之间是不发生变化的。
  • 新区块的 MPT 只是新建了那些"发生变化"的节点分支,未变化的部分直接指向前一个区块的旧节点。这使得以太坊的状态历史像一个"增量文件系统"。

五、 代码树与存储树 (Code & Storage Trie)

除了全局的状态树 (State Trie),每个账户内部还有两个重要的属性:

  • CodeHash:如果账户是合约,代码本身是只读的。代码被存储在数据库中,账户里只存代码的哈希。
  • StorageRoot :如果合约里有变量(比如 mapping (address => uint) balance),这些变量会构成另一棵 MPT,称为存储树 (Storage Trie)。这个树的根哈希保存在账户状态里。

🧠 核心逻辑图解 (MPT 结构)

为了让你直观理解 MPT 如何运作,请看下图:
MPT优势
路径前缀: A
路径前缀: 3
路径: 1
路径: 5
Block Header: State Root
Branch Node: 分岔口
Extension Node: 共享路径 BC
Leaf Node: 终点
Branch Node: 分岔口
Leaf Node: 账户 A
Leaf Node: 账户 B
逻辑上有序
密码学安全
路径压缩高效

💡 总结

第 15 讲的核心在于理解 MPT (Merkle Patricia Trie)

它是以太坊的"脊梁",完美平衡了效率 (查找快)、安全 (可验证)和存储成本(数据共享)。所有的交易执行、状态变更,最终都体现为这就这棵巨大的 MPT 树上的节点更新。

相关推荐
小妖6669 小时前
js 实现快速排序算法
数据结构·算法·排序算法
xsyaaaan9 小时前
代码随想录Day30动态规划:背包问题二维_背包问题一维_416分割等和子集
算法·动态规划
devmoon9 小时前
在 Paseo 测试网上获取 Coretime:On-demand 与 Bulk 的完整实操指南
开发语言·web3·区块链·测试用例·智能合约·solidity
三水不滴9 小时前
计网ping原理
经验分享·笔记·计算机网络
prog_610310 小时前
【笔记】思路分享:各种大模型免费当agent后台
笔记·大语言模型·agent·cursor
凯尔萨厮10 小时前
Maven(Windows下载安装)
笔记·maven
wdfk_prog10 小时前
[Linux]学习笔记系列 -- [drivers][input]serio
linux·笔记·学习
zheyutao10 小时前
字符串哈希
算法
A尘埃10 小时前
保险公司车险理赔欺诈检测(随机森林)
算法·随机森林·机器学习
大江东去浪淘尽千古风流人物11 小时前
【VLN】VLN(Vision-and-Language Navigation视觉语言导航)算法本质,范式难点及解决方向(1)
人工智能·python·算法