04 ETH-交易树和收据树

发布时间 2023-05-02 14:46:44作者: YangYi215

04 ETH-交易树和收据树

每个交易执行完之后会形成一个收据,记录这个交易的相关信息。

交易树与收据树上的节点是一一对应的。

增加收据树只要考虑到以太坊中的智能合约执行比较复杂,增加收据树有利于我们快速查询一些执行的结果。


交易树和收据树都是MPT。

以太坊中的三棵树都用同样的数据结构,这样代码比较统一,便于管理。(猜的)


对于状态树来说,查找的键值就是账户的地址。

对于交易树和收据树来说,查找的键值就是交易在发布的区块里面的序号。交易的排列顺序由发布区块的节点确定的。


交易树和收据树只把当前发布的区块的交易组织起来的。

状态树是把系统中所有账户的状态都要包含进去,不管当前的账户与之前的交易有没有什么关系。

多个区块的状态树是共享节点的。新发布区块时,只有区块中交易改变了账户状态的需要新建分支,其他节点都是沿用原来的树节点就行。

每个区块的交易树和收据树都是独立的。


交易树和收据树的用处?

提供 Merkle proof

以太坊中支持复杂的操作,比如:过去10天,所有跟某个智能合约有关的交易。符合某种类型的所有事件(众筹事件、发行新币的事件)。这些需要高效的方法支持。

以太坊中引入了 bloom filter 数据结构(支持查找某个元素是不是在一个比较大的集合中)。

笨方法,直接遍历,复杂度是线性的。前提:有足够的存储来保存整个集合的元素。对于轻节点来说,没有交易列表信息,所以这种方式行不通。


bloom filter 数据结构:

集合中的每一个元素,都取hash,找到向量中的对应位置,然后把它变为1,所有集合处理完毕,得到一个向量,便是原来集合的摘要。

新元素d,如果映射到一个是0的位置,可以判断出该元素不在集合中;

如果映射到一个是1的位置,什么也不能说明。(新元素可能集合中存在该元素;或者hash碰撞,该元素刚好和集合中的元素碰撞)

有可能出现误报,但是不会出现漏报(在里面一定说明在里面,不在里面也有可能说在里面)。


如果从该集合中删除一个元素,该怎么操作?

bloom filter 的一个局限性是不支持删除操作。简单的 bloom filter 是不支持删除操作的。


那么以太坊中的 bloom filter 有什么用呢?

每个交易执行完毕,会形成一个收据,收据中包含 bloom filter,记录该交易的类型、地址等其它信息,发布的区块在块头中,也有一个总的 bloom filter,总的 bloom filter 是区块中所有交易的 bloom filter 的一个并集。


需求:查找过去10天与所有跟某个智能合约有关的所有交易。

先查一个区块的块头中的 bloom filter 是否有需要的交易类型,如果块头中的 bloom filter 没有的话,那么我们知道,这个区块不是我们想要的,如果块头的 bloom filter有的话,我们再去查找区块中所包含的交易所对应的收据里面的那些 bloom filter,如果有的话,找到相对应的交易,直接进行确认。

好处:通过 bloom filter 的结构,快速过滤掉大量无关的区块。

轻节点根据块头中的bloom filter可以过滤到很多区块,剩下可能的区块找全节点要就行。


以太坊的运行过程可以看作是一个交易驱动的状态机(transaction-driven state machine)。

(执行交易驱动系统从当前状态转移到下一个状态)

比特币也可以叫做是交易驱动的状态机。

(交易驱动UTXO)

状态转移都得是确定的,对于一个给定的当前状态,一组给定的交易,能够确定性的转移到下一个状态。(所有的全节点都得执行同样的状态转移)


问题:以太坊发布交易,节点收到交易,转账A—>B,有没有可能收款人B的地址,节点没有听说过?

可能。要在状态数中新增加一个账户。


问题:状态树中能不能只包含与该交易相关的状态?可以大幅度减小每个区块对应的状态树的大小,因为大部分的账户状态是不会变的。(类似于交易树和收据树)

这样设计的话,每个区块没有一个完整的状态树,只有当前区块所包含的交易涉及到的账户的状态,查找某个账户的状态不方便(A—>B,有可能A账户在当前很长一段事件没有发生过交易)。

同时,转账 A—>B,B的账户可能是新建的账户,这个时候要找到创世纪快、块去,没有找到才发现是个新建的账户。


区块的数据结构:

函数中创建交易树和收据树,并得到根hash值。

创建交易树:

创建收据树:

创建叔父区块:

DeriveSha 函数:

trie数据结构:

收据的数据结构:

区块头的数据结构:

查询 bloom filter 中是否包含查找元素:

bloom9 是个hash函数。