在以太坊这个庞大的去中心化应用生态中,账户余额是衡量用户资产、驱动智能合约交互的核心要素,这些看似简单的“余额数字”究竟是如何在以太坊区块链上被存储、管理和查询的呢?理解以太坊账户余额的存储机制,是深入掌握以太坊工作原理的关键一步。
以太坊的两种账户类型
我们需要知道以太坊存在两种不同类型的账户,它们的存储方式和结构截然不同:
- 外部账户 (Externally Owned Account, EOA):由用户通过私钥控制,如我们常用的钱包账户(如 MetaMask 中的账户),EOA 没有关联的代码,其行为由交易发起者(用户)的私钥签名驱动。
- 合约账户 (Contract Account):由智能代码控制,其地址在创建时生成,并且存储了代码和状态,合约账户的交互(如接收转账、执行逻辑)是通过交易或其他合约的调用触发的。
关键区别:EOA 的余额直接存储在账户本身的状态中,而合约账户的余额也存储在其状态中,但其状态还包括了存储的变量(存储在 storage 中)和代码。
账户状态与“余额”的存储位置
无论是 EOA 还是合约账户,其核心状态信息都记录在以太坊的状态树(State Trie)中,具体来说是每个账户的状态对象中,一个账户的状态对象大致包含以下字段:
nonce:- 对于 EOA:表示该账户发起的交易数量,也用于防止重放攻击。
- 对于合约账户:表示该账户创建的合约数量。
balance:这就是我们关心的账户余额! 它以 Wei 为单位(1 ETH = 10^18 Wei)。balance是一个整数,直接存储在账户状态对象中。storageRoot(仅合约账户):指向一个存储树的根哈希,该树存储了合约账户的所有持久化变量(即storage中的数据),EOA 没有这个字段,或者说其storageRoot为空。codeHash:存储账户关联代码的 Keccak-256 哈希值,对于 EOA,其codeHash是一个空字符串的哈希值;对于合约账户,是其代码的哈希值。
账户余额 balance 是账户状态对象的一个直接组成部分,它存储在以太坊的状态树(也称为账户状态树 Account State Trie)的叶子节点中,状态树的键是账户地址,值就是上述的状态对象。
存储结构详解:Merkle Patricia Trie
以太坊使用一种称为 Merkle Patricia Trie (MPT) 的数据结构来组织账户状态和合约存储,这种结构具有以下优点:
- 高效查询与验证:可以快速查找特定账户的状态,并且通过默克尔证明高效验证状态的真实性。
- 数据完整性:任何数据的修改都会导致其路径上所有节点哈希的改变,最终影响根哈希,这使得轻客户端(如手机钱包)可以快速验证状态数据的最新性和完整性,而无需下载整个区块链。
