以太坊区块中有三颗MPT树,分别是状态树,交易树,收据树 ,分别存储了以太坊中的世界状态,本区块的交易,本区块的交易回执,其中交易和交易回执是一一对应的。

状态树

每次生成一个新的区块,以太坊状态发生改变后并不会去修改原来的MPT树,而是会新建一些分支,如下图所示;

优势
  • 当一个账户的余额发生改变后,对应路径的哈希也发生了变化,然后自底而上的更新对应路径上的哈希值,直至Satet Root,这样可以计算最少的哈希次数。
  • 以太坊中的全节点维护的是增量的MPT状态树,因为每次一个区块对世界状态的修改都只是很小的一部分,增量修改既有利于区块回滚,又可以节约开销。
  • 在以太坊中区块临时分叉很普遍,但是由于以太坊智能合约的复杂性,如果不记录原始状态,很难根据合约代码回滚状态。

收据树

以太坊在智能合约执行时会产生一个交易回执(Receipt)记录了此笔交易的执行结果,交易信息和区块信息。

当查询轻节点查询通过布隆过滤器找到交易后,为了避免误识,还会再次查询回执来避免误识。

交易树

交易树的作用是提供了交易的默克尔证明,证明某个交易被打包到某个区块里,轻节点不用存储区块体仅根据提供的默克尔证明就可以快速判断交易是否已经被打包。

三颗树的差异

交易树和收据树只依赖当前的区块,而状态树是把链上所有状态都包含进去,交易树和收据树是独立的,状态树会共享树的节点。

为什么状态树要包含所有链上所有的状态呢?

举个例子,当一笔转账操作的发起时,需要判断发起账户是否有足够的ETH来完成这笔转账,这个时候要通过查找状态树查看对应账户的状态,但是如果为了节约空间,只保存了当前区块账户的状态,就需要逐块查找,非常影响性能,甚至这个转账交易的发起者都不存在,是一个恶意操作。