以太坊的交易树和收据树

以太坊的交易树和收据树用于记录区块中的交易和执行信息,通过Merkle Proof支持轻节点验证。收据树提供快速查询执行结果,而Bloom Filter则用于高效地判断元素是否存在,减少查找成本。在以太坊中,每个区块头包含Bloom Filter,帮助轻节点过滤无关区块。虽然Bloom Filter可能导致误报,但其变种设计能缓解哈希碰撞问题。删除操作在Bloom Filter中较复杂,需要考虑计数器。以太坊状态树无法仅包含与区块交易相关的账户状态,因为新账户的创建需要追溯到创世块。

交易树和收据树

 

每次发布一个区块时,区块中的交易会形成一颗交易树。此外,以太坊还添加了一个收据树,每个交易执行完之后形成一个收据,记录交易相关信息。也就是说,交易树和收据树上的节点是一一对应的。

为什么要增加收据树?

由于以太坊智能合约执行较为复杂,通过增加收据树,便于快速查询执行结果。


交易树和收据树都是M(Merkle)PT,而BTC中都采用普通的MT(Merkle Tree)。(以太坊为啥不用Merkle Tree,肖老师认为可能就仅仅是为了以太坊的三棵树代码统一好所以这样设计的)
MPT的好处是支持查找操作,通过键值沿着树进行查找即可。对于状态树,查找键值为账户地址;对于交易树和收据树,查找键值为交易在发布的区块中的序号。

交易树和收据树的用途:

1.向轻节点提供Merkle Proof。

2.更加复杂的查找操作(例如:查找过去十天的交易;过去十天的众筹事件等)。

Bloom filter(布隆过滤器)

Bloom filter支持比较高效的查找某个元素是否在某个集合中。

如果不用Bloom filter,最原始的方法是全部遍历一遍,O(n)的复杂度,且轻节点没有足够的空间存储所有元素,也没有全部的交易列表,所以暴力遍历的方法轻节点是用不了的!

Bloom filter的查找思想

如下图,给定一个数据集,其中含义元素a、b、c,通过一个哈希函数H()对其进行计算,将其映射到一个其初始全为0的128位的向量的某个位置,将该位置置为1。将所有元素处理完,就可以得到一个向量,则称该向量为原集合的“摘要”。可见该“摘要”比原集合是要小很多的。
假定想要查询一个元素d是否在集合中,假设H(d)映射到向量中的位置处为0,说明d一定不在集合中;假设H(d)映射到向量中的位置处为1,有可能集合中确实有d,也有可能因为哈希碰撞产生误报。

false positive

利用 Bloom filter有一个特点就是,该在集合里的元素,一定会在能播报正确,不在集合里的元素有可能也被播报成在集合里。

由此 Bloom filter会有一些变种用法,比如在映射哈希的时候,采用一组哈希函数进行向量映射,有效避免哈希碰撞。

如果集合中要删除一个元素要怎么做?

若想用 Bloom filter的话,就不好做了。如果你只是简单的把1改成0,其实你没办法判定这个操作改的是你需要改的1,还是哈希碰撞造成的1。如果想要支持删除操作,需要将记录数不能为0和1,需要修改为一个计数器(需要考虑计数器是否会溢出)。

以太坊中Bloom filter的作用

每个交易完成后会产生一个收据,收据包含一个Bloom filter记录交易类型、地址等信息。在区块block header中也包含一个Bloom filter,其为该区块中所有交易的Bloom filter的一个并集。
所以,查找时候先查找块头中的Bloom filter,如果块头中包含。再查看区块中包含的交易的Bloom filter,如果存在,再查看交易进行确认;如果不存在,则说明发生了“碰撞”。
好处是通过Bloom filter这样一个结构,比如你是一个轻节点,那么你可以利用块头就快速大量过滤掉大量无关区块,从而提高了查找效率,接着再去问全节点要进一步的信息。

总结

以太坊的运行过程,可以视为交易驱动的状态机,通过执行当前区块中包含的交易,驱动系统从当前状态转移到下一状态。当然,BTC我们也可以视为交易驱动的状态机,其状态为UTXO。
对于给定的当前状态和给定一组交易,可以确定性的转移到下一状态(保证系统一致性)。

A转账到B,有没有可能收款账户不包含再状态树中?
可能。因为以太坊中账户可以节点自己产生,只有在产生交易时才会被系统知道。
可否将每个区块中状态树更改为只包含和区块中交易相关的账户状态?(大幅削减状态树大小,且和交易树、收据树保持一致)
不能。首先,这样设计要查找账户状态很不方便,因为不存在某个区块包含所有状态,你需要逐个向前一个区块遍历是否包含你需要的账户的上一个状态。

最麻烦的情况是如果要向一个新创建账户转账,因为需要知道收款账户的状态,才能给其添加金额,但由于其是新创建的账户,所有需要一直找到创世纪块才能知道该账户为新建账户,系统中并未存储,而区块链是不断延长的。

参考资料

1.北京大学肖臻老师《区块链技术与应用》公开课

2.参考笔记

<think>好的,我需要回答用户关于布隆过滤器的概念、实现应用场景的问题。首先,我得回忆一下布隆过滤器的基本概念。布隆过滤器是1970年由布隆提出的,主要用来判断一个元素是否在一个集合中。它的优点在于空间效率查询时间都比一般的算法好,但缺点是有一定的误判率,并且删除元素困难。用户提供的引用资料里也提到了这些点,比如引用[2]详细解释了它的结构优缺点,而引用[3]补充了关于删除困难误报率的问题。 接下来,关于实现部分,我需要说明布隆过滤器的核心组成部分:一个很长的二进制向量多个哈希函数。当添加元素时,使用这些哈希函数将元素映射到位数组中的多个位置,并将这些位置设为1。查询时,检查所有对应的位是否都为1。如果有任何一个位为0,元素肯定不在集合中;如果全为1,则可能存在,但可能有误判。这部分在引用[2]中有提到,需要正确引用。 然后,应用场景方面,用户可能想知道它在实际中的用途。根据引用[1],布隆过滤器用于性能内存敏感的场景,比如数据库查询优化、缓存系统防止缓存穿透、网络爬虫去重等。引用[3]还提到了Cuckoo Filter的应用场景,但这里应该集中在布隆过滤器本身。 误判率的计算也是一个重点。用户可能需要知道如何推导误判率,这里需要数学公式。根据概率学,误判率与位数组的大小、哈希函数的数量以及插入元素的数量有关。公式大概是$(1 - e^{-kn/m})^k$,其中m是位数,n是元素数量,k是哈希函数个数。需要确保使用正确的LaTeX格式,如引用[2]中的推导。 另外,用户可能关心如何优化布隆过滤器。比如调整哈希函数的数量,或者使用变种如计数布隆过滤器(CounterBloom Filter)来支持删除操作,如引用[3]所述。这些可以作为优化方法的一部分。 最后,生成相关问题时要考虑用户可能进一步想知道的内容,比如如何选择参数、与其他数据结构对比、具体实现代码等。需要确保问题覆盖概念、实现细节应用实例。 现在需要整理这些信息,按照用户的要求分点回答,使用中文,正确引用资料,并添加相关问题。同时注意行内公式用$...$,独立公式用$$...$$,并检查LaTeX语法是否正确。</think>### 布隆过滤器(Bloom Filter)解析 #### 一、核心概念 布隆过滤器是一种**概率型数据结构**,用于快速判断元素是否属于某个集合。其特点如下: 1. **空间效率极高**:使用$m$位二进制向量存储信息,远小于传统哈希表空间占用[^2]。 2. **存在误判率(False Positive)**:可能错误判定未存储的元素为存在,但**绝不会漏判已存储元素**。 3. **不支持元素删除**:标准布隆过滤器无法直接删除元素(可通过变种如计数布隆过滤器实现)[^3]。 #### 二、实现原理 1. **数据结构** - 位数组:长度为$m$的二进制向量,初始全为0。 - $k$个独立哈希函数:每个函数将元素均匀映射到$[0, m-1]$区间。 2. **操作流程** - **添加元素**:对元素$x$进行$k$次哈希,将对应位设为1 $$ \forall i \in [1,k], \quad \text{bit}[h_i(x)] = 1 $$ - **查询元素**:检查所有$k$个哈希位是否均为1 3. **误判率公式** 误判率$p$与参数关系: $$ p \approx \left(1 - e^{-kn/m}\right)^k $$ 其中$n$为插入元素数量,最优哈希函数数量$k_{opt} = \frac{m}{n}\ln 2$ #### 三、应用场景 | 场景 | 说明 | 优势 | |------|------|------| | 缓存穿透防护 | 防止查询不存在的数据导致数据库压力 | 减少无效查询[^1] | | 网页爬虫去重 | 快速判断URL是否已抓取 | 节省内存空间 | | 垃圾邮件过滤 | 快速判断邮件特征是否在黑名单 | 毫秒级响应[^3] | #### 四、代码实现示例(Python) ```python import mmh3 from bitarray import bitarray class BloomFilter: def __init__(self, size, hash_num): self.size = size self.hash_num = hash_num self.bit_array = bitarray(size) self.bit_array.setall(0) def add(self, item): for seed in range(self.hash_num): index = mmh3.hash(item, seed) % self.size self.bit_array[index] = 1 def contains(self, item): for seed in range(self.hash_num): index = mmh3.hash(item, seed) % self.size if not self.bit_array[index]: return False return True ``` #### 五、性能优化方向 1. **参数调优**:根据预期元素量$n$选择合适$m$$k$ 2. **硬件加速**:使用SIMD指令并行处理哈希计算 3. **分层设计**:多级布隆过滤器降低整体误判率
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值