深入解析以太坊存储数据格式,MPT、账户与状态
以太坊,作为全球领先的智能合约平台,其核心功能之一是存储和管理链上数据,理解以太坊如何组织和存储数据,对于开发者、节点运营者乃至任何希望深入了解其底层机制的人都至关重要,以太坊的存储数据格式并非简单的键值对堆砌,而是一套精心设计、高效且安全的体系,其核心是Merkle Patricia Trie (MPT,默克尔帕特里夏树),本文将详细探讨以太坊的存储数据格式,包括其核心组件MPT、账户模型以及具体的数据存储结构。
核心基石:Merkle Patricia Trie (MPT)
MPT是以太坊状态存储、交易和收据存储的底层数据结构,它是一种结合了Merkle Tree(默克尔树)和Patricia Trie(帕特里夏树,也称为基数树 Radix Tree)优化的数据结构。

-
Patricia Trie (基数树):
- Patricia Trie是一种压缩前缀树,它通过共享公共前缀来高效存储键值对,特别适合存储像以太坊地址这样的十六进制字符串。
- 与普通前缀树相比,Patricia Trie能显著减少树的深度和节点数量,从而提高查询效率并节省存储空间,它将键值对存储在树的叶子节点中,内部节点则用于指导查找路径。
-
Merkle Tree (默克尔树):
- Merkle Tree是一种哈希树,其特点是每个非叶子节点的值都是其所有子节点值的哈希组合。
- 这种结构带来了一个关键特性:完整性验证,通过计算根节点的哈希值(Merkle Root),可以高效地验证任意数据块是否被篡改,如果树中任何一个叶子节点的数据发生变化,都会引起其所有父节点哈希值的连锁改变,最终导致根哈希值的改变。
-
Merkle Patricia Trie (MPT)的结合优势:
- MPT将Patricia Trie的高效查询和存储特性与Merkle Tree的完整性验证能力相结合。
- 在以太坊中,每个区块头都包含一个状态根(State Root)、一个交易根(Transactions Root)和一个收据根(Receipts Root),这些根就是对应MPT的根哈希值。
- 状态根:代表整个以太坊网络在某个区块高度的所有账户状态的MPT根哈希。
- 交易根:代表该区块中所有交易的MPT根哈希。
- 收据根:代表该区块中所有交易执行后产生的收据的MPT根哈希。
- 这种设计使得轻客户端(如手机钱包)能够高效地验证交易是否被包含在某个区块中,以及状态是否发生了变化,而无需下载整个区块链数据。
账户模型与状态存储
以太坊采用的是账户模型(Account-based Model),与比特币的UTXO模型不同,每个账户都有一个唯一的地址,状态数据就是所有账户信息的集合。

-
账户类型:
- 外部账户 (Externally Owned Account, EOA):由用户私钥控制的账户,用于发起交易、持有以太坊等,没有关联代码。
- 合约账户 (Contract Account):由代码控制,当收到特定交易时,其代码会被执行,有关联的代码和存储。
-
账户状态数据结构: 每个账户(无论是EOA还是合约账户)在状态树中都由以下字段表示:
- nonce:
- 对于EOA:该账户发起的交易数量。
- 对于合约账户:该账户创建的合约数量。
- balance:账户持有的以太币余额,以wei(1 ETH = 10^18 wei)为单位。
- storageRoot:仅合约账户有,指向该合约账户的存储树(Storage Trie)的根哈希,存储树用于存储合约的持久化变量数据,它也是一个MPT,EOA的storageRoot为空。
- codeHash:仅合约账户有,指向该合约账户代码的哈希值,EOA的codeHash是空字符串的哈希,合约代码本身存储在一个单独的代码哈希到代码的映射中,而不是直接存在账户里。
- nonce:
具体数据存储格式详解
了解了MPT和账户模型后,我们可以更具体地看以太坊中不同类型数据的存储格式:
-
状态存储 (State Storage):

- 整个以太坊的状态被组织在一个全局的状态树(State Trie)中。
- 状态树的键是账户地址(经过RLP编码后哈希)。
- 状态树的值是上述账户数据(nonce, balance, storageRoot, codeHash)的RLP编码。
- 对于合约账户,其
storageRoot指向另一个MPT,即存储树(Storage Trie)。- 存储树的键是合约中变量的存储槽(slot)索引(通常是一个32字节的整数,由变量位置和类型决定)。
- 存储树的值是对应存储槽中存储的数据(也是RLP编码)。
- 这种分层设计使得每个合约的存储是独立的,方便管理和查询。
-
交易存储 (Transaction Storage):
- 每个区块中的所有交易被组织在一个交易树(Transactions Trie)中。
- 交易树的键通常是交易在区块中的索引(或经过特定编码的哈希)。
- 交易树的值是交易数据的RLP编码,交易数据包括接收方地址、金额、nonce、有效期、数据负载、签名等。
-
收据存储 (Receipt Storage):
- 每个交易执行后产生的收据被组织在一个收据树(Receipts Trie)中。
- 收据树的键与交易树的键对应,通常是交易在区块中的索引。
- 收据树的值是收据数据的RLP编码,收据包含交易状态(成功/失败)、使用的gas、日志 bloom过滤器、以及交易产生的日志(Log)列表等,日志对于事件监听非常重要。
RLP编码:序列化的基石
无论是状态树、交易树还是存储树,其键和值在存入MPT之前,都需要经过RLP (Recursive Length Prefix)编码,RLP是以太坊中用于编码任意嵌套的二进制数据(如字符串、列表、字节数组)的主要序列化方法,它的设计简洁高效,能够保持数据的原始结构,并且解码时无需提前知道数据大小,MPT中的所有节点(包括叶子节点和扩展节点、分支节点)的键和值,本质上都是RLP编码后的数据。
以太坊的存储数据格式是一套以Merkle Patricia Trie (MPT)为核心,结合账户模型和RLP编码的复杂而精妙的系统,它通过状态树、交易树、收据树以及合约存储树的多层MPT结构,实现了:
- 高效的数据查询与更新:得益于Patricia Trie的压缩特性。
- 强大的数据完整性保障:得益于Merkle Tree的哈希验证机制,确保了链上数据的不可篡改性。
- 状态同步与轻客户端支持:通过根哈希值,轻客户端可以高效验证链上数据。
- 灵活的合约存储:每个合约拥有独立的存储树,便于管理和隔离。
理解这些底层存储格式,不仅有助于开发者更高效地进行智能合约开发(如优化存储成本、理解gas消耗),也能让我们更深刻地认识到以太坊作为一个去中心化平台的强大潜力和技术严谨性,随着以太坊的不断发展(如向以太坊2.0的演进),其存储机制也可能持续优化,但MPT所代表的核心理念仍将是其重要基石。
本文 原创,转载保留链接!网址:https://licai.bangqike.com/bixun/1316883.html
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。






