区块链 第10.4章 以太坊区块结构 区块链 第10.4章 以太坊区块结构

1天前

一、区块结构

比特币的区块链是由 PoW 保证每个区块都指向前一个区块,而在每一个区块内部,由一个独立的Merkle Tree 来保证所有交易的不可篡改。用户的比特币是以 UTXO 的方式存储的,因此,比特币的交易就是不断地消耗现有的 UTXO,并产生新的 UTXO。

而以太坊采用的是账户模型,如果小明的账户在某个区块的资产是 1 ETH,当小明给小红转账 0.2 ETH后,刨除手续费,他的账户还剩下约 0.8 ETH。由于小明的账户地址不变,所以,以太坊的区块结构必须能在每个区块持续地跟踪并记录小明的账户余额变动。因此,和比特币相比,以太坊的区块数据结构更加复杂。

二、Merkle Patricia Tree

以太坊存储账户数据的数据结构是 MPT:Merkle Patricia Tree,它是一种改进的Merkle Tree。当MPT的每个叶子结点的值确定后,计算出的Root Hash就是完全确定的。例如,在第一个区块中,4个账户的余额确定后,即可确定Root1:

https://file.lulublog.cn/images/3/2025/11/Iq4JeQ45dAMwfmUFAttim5I4mAwWfQ.png

在第二个区块中,如果发生了转账,将计算出一个新的 Root2:

https://file.lulublog.cn/images/3/2025/11/lpJ9bjnCSSSS8WESaNZzBESOppo9wX.png

每一个区块通过 Root Hash 将完全确定所有账户的状态,所以,从全局看,以太坊就是一个状态机,每个区块通过记录一个 stateRoot 来表示一个新状态。如果给定某个区块的 stateRoot,我们肯定能完全确定所有账户的所有余额等信息。因此,stateRoot 就被称为当前的世界状态。

有的同学可能会思考,如果第一个区块只有几个账户,随着账户的增加,如果有数百万个账户,到后面岂不是区块存储的数据量会越来越大?

实际上,每个区块的 stateRoot 表示的是一个完全状态的逻辑树,但每个区块记录的数据只包括修改的部分,如果我们观察第二个区块的树,它实际上只记录修改的两个账户,以及两个账户因修改后导致的上层路径的 Hash 发生的变化:

https://file.lulublog.cn/images/3/2025/11/J3MMp77iM5PVmIVPHSMTIh35IM3P3P.png

想要将一个有几百万节点的树完整地放入内存需要消耗大量的内存,而以太坊全节点也并不会将整颗逻辑树放入内存。实际上,每个节点的数据被存放到 LevelDB 中,节点仅在内存中存储当前活动的一些账户信息。如果需要操作某个不在内存的账户,则会将其从 LevelDB 加载到内存。如果内存不够,也会将长期不活动的节点从内存中移除,因为将来可以通过节点的路径再次从 LevelDB 加载。

三、账户数据

一个以太坊账户由4部分数据构成:

  • nonce

  • balance

  • storageRoot

  • codeHash

其中,nonce 是一个递增的整数,每发送一次交易,nonce 递增 1,因此,nonce 记录的就是交易次数。

balance 记录的就是账户余额,以 wei 为单位,1 Ether 等于 10 的 18 次方 wei。

如果一个账户是合约账户,则 storageRoot 存储合约相关的状态数据,codeHash 存储合约代码的 Hash。对于外部账户,这两部分数据都是空。

四、区块数据

一个以太坊区块由区块头和一系列交易构成。区块头除了记录 parentHash(上一个区块的 Hash)、stateRoot(世界状态)外,还包括:

  • sha3Uncles:记录引用的叔块;

  • transactionRoot:记录当前区块所有交易的Root Hash;

  • receiptsRoot:记录当前区块所有交易回执的Root Hash;

  • logsBloom:一个Bloom Filter,用于快速查找Log;

  • difficulty:挖矿难度值;

  • number:区块高度,严格递增的整数;

  • timestamp:区块的时间戳(以秒为单位);

  • ……

transactionRoot 和 receiptsRoot 也是两个 MPT 树,但他两和 stateRoot 不同,他们仅表示当前区块的两棵树,与前面的区块状态无关。

五、叔块

在 2022 年 9 月升级之前,以太坊采用和比特币类似的 PoW 挖矿,只是算法为改进的 Ethash 算法。PoW 挖矿肯定会产生分叉,但由于最长链共识,最终某个分叉将胜出:

https://file.lulublog.cn/images/3/2025/11/fdD4nwFY6HpCl68Ha5wDV1CVDPhpdy.png

但是和比特币不同的是,虽然 #4 的竞争导致一个胜出另一个失败,但以太坊鼓励后续的 #5 区块引用另一个废弃的 #4 块,这种引用的废弃块被称为叔块(Uncle Block):

https://file.lulublog.cn/images/3/2025/11/PJJORClRuLOmlHCcrey10loroLZYF1.png

区块头记录的 sha3Uncles 就是叔块,一个区块可引用 0~2 个叔块,且叔块高度必须在前 7 层之内。

叔块的目的是给予竞争失败的矿工部分奖励,避免出现较长的分叉。

六、小结

以太坊的核心数据结构是以 Merkle Patricia Tree 记录的世界状态,每个区块通过打包新的交易,从而导致世界状态的变化。

阅读 16