12-ETH中的数据结构

简介

账户地址到 账户状态的映射

eth的addr是160b的数,一般表示为 40个 16进制的数;

trie

我们先介绍一下 trie 结构:

截屏2024-12-17 20.57.46

trie 结构,只要地址不一样,就一定会映射到trie 树的两个不同的分支,

它不会碰撞;

给定的单词不变,顺序打乱,不影响树的结构;

更新如果是局部性的,只需要改变一条分支即可;

patricia tree

patricia tree路径压缩的trie,会如下:

截屏2024-12-17 21.03.38

截屏2024-12-17 21.07.27截屏2024-12-17 21.07.35

以上这样密集的情况路径压缩比较好;
但是eth地址是160位,也就是2**160 是一个非常大的数,所以地址在这个地址空间中,其实非常稀疏(为了防碰撞),不需要压缩;

state tree 状态树

merkle Patricia tree (MPT)

截屏2024-12-17 21.19.54

右上角是四个账户,假设只有7位的地址,账户状态只显示了余额;

第一个账户是 45个 eth;第二个是 1 wei;第三个 1.1eth;第四个 0.12 eth。

如果有路径压缩就会有 extension node;

可以看见他们 root 结点 a7 ,后面就分支了;就是一个 树的结构。

最后,这个 root 结点取hash 得到了一个hash 值写在block header 中。

都是 一个结点算hash 值,这个值放进上一个结点中作值,来实现指针。

截屏2024-12-23 21.28.17

这个value的实现是靠 RLP 序列化。

截屏2024-12-23 20.39.15

上图是 两个 block 相连的例子;

state root 在block header中,但是 每一个block 中的 状态树state tree 下的结点,都共用了很多个结点, 看见右边的block state tree中大部分结点都指向了左边状态树的结点,只有那些发生改变的结点需要新建分支;

上面图片的例子中只有一个结点 的值 ,从29变成 45,这就是上图表达的意思;

对于全结点而言,每新建一个block ,就需要在本地维护一个新的 merkle Patricia tree,只不过大部分结点是重复利用上的。

回滚困境

截屏2024-12-23 21.03.03

淘汰掉的一条链,想要直接回滚是不可能的,因为eth 中有智能合约,智能合约 可能非常复杂,合约执行完之后想要回滚实现不了。

所以想要回滚必须要 保存历史状态;

header 块结构

截屏2024-12-23 21.09.15

前一个 block header的 hash 值;

叔叔区块hash值;

coinbase 矿工地址 ;

Root 是 状态树的根hash;

TxHash 是交易树的根hash;

receipthHash 是收据树的根hash;

bloom 查询某种交易的执行结果;

Gas 消耗的汽油费用;

Time 是block 的产生时间;

Nonce 也是 挖矿时候的随机数;

截屏2024-12-23 21.19.03

transaction是这个block 中交易的列表;

截屏2024-12-23 21.21.45

这个区块真正发布出去在网上 就是上面external的这些信息;

交易树、收据树

bloom filter 布隆过滤器

截屏2024-12-25 16.22.07

就是一个 hash表的结构,看一个元素是不是真的在 abc 这个集合中,就对这个元素 hash,算出来的值看看在不在hash 表中,有冲突可能性,也就是可能错报,但是不可能漏报。

删除的操作,只存0和1的基础情况下,bloom filter 不支持删除操作,因为理论上可能多个 集合内的元素落在hash 表的一个位置上,你想改0,可能会破坏 整体存储情况。

每一笔交易执行完之后,会形成一个收据,收据内就会包含一个bloom filter ,记录交易的地址、类型 等七七八八的信息。

发布的区块在 block header中 也有一个 总的 bloom filter,这个总的 bloom filter 是这个block 中所有交易的bloom filter的并集。

查找过去十天 和这个智能合约相关的所有交易:

1、查哪个区块的 block header 中的 总bloom filter 中有我要的交易的类型。如果 block header 中没有的话,这个block 就不是我们想要的;

2、如果block filter中总 bloom filter 中有,就从这个 block 所对应的交易所对应的收据树里面的bloom filter里面找;

transaction-driven state machine

交易驱动状态机

state 指的是eth 所有账户的状态,每次发布的 block 中 包含的交易,通过执行这些交易,让eth 系统的状态从一个状态到下一个状态;

为什么要有状态树?

eth 和 btc 一样 创建一个账户是可以私下完成的,只有当这个账户第一次收到钱的时候,才能被记录进链中;

状态树 是保留全部账户 状态信息的,而不是 交易树、收据树 仅仅包含交易相关的账户的信息,这样的好处在于 当 A->B 转账时,B 是新建账户时,不用一路回溯 全部结点找一遍来确认 B 是一个新建的账户,而有状态树 可以快速发现B不在状态树中,快速确认了B是一个新建账户,而将其纳入状态树。

代码中数据结构

截屏2024-12-25 21.41.43

以上是交易树和收据树的创建过程。
bloom 就是 前面说的 bloom filter ,散列表。

截屏2024-12-25 21.52.19

截屏2024-12-25 21.53.51

截屏2024-12-25 21.56.58

截屏2024-12-25 21.57.57

block header 中的bloom 是由 bloom 汇总来的。

截屏2024-12-25 22.00.23

截屏2024-12-25 22.07.15

bloomlookup 是查看 bloom filter 中有没有我们感兴趣的topic;