简化的支付验证(SPV)和布隆过滤器(bloom fliter)

目录

1. 全节点

2. SPV:简化的支付验证

2.1 SPV通过参考区块链的深度而非高度来验证交易。

2.2 SPV节点同步消息的过程

3. Bloom filter:布隆过滤器

4. SPV节点如何使用布隆过滤器


hello,大家好,我们第五期的区块链技术分享来啦~~本期分享的主题是简化支付验证(SPV)和布隆过滤器。

要完全理解SPV的验证过程,我们要先对全节点、SPV以及布隆过滤器分别进行解释。那么下面直接进入主题。

1. 全节点

全节点,保存有全网交易数据,又能完成相关验证交易,独立完成与对等节点的连接。这类节点在本地保存了一个完整的区块链网络(保存了所有区块的block header和block body),在其上可进行任何查询、交易的验证与广播,正因为有这样的节点存在,更加使得去中心化成为了可能,同时使得区块链网络更加安全。

在区块链的早期,所有节点都是全节点,全节点启动后的第一件事就是完善更新本地的区块数据。

全节点维护了一份完整的、最新的包含全部交易的比特币区块链副本。

这份副本由节点独立构建和检验,从最初的第一个区块(创世区块)开始一直构建到网络中的最新已知区块。

当一个节点离线,不论离线时间有多长,这个比较本地与对等节点的区块链,并接收缺失区块的过程就会被触发。

如果一个节点只离线几分钟,它只缺少了几个区块;如果离线了一个月,它缺少了几千个区块。

但不论哪种情况,它都会从发送getblocks消息开始,收到一个inv的响应,接着开始下载缺少的区块。

图片


2. SPV:简化的支付验证

SPV,Simplified Payment Verification ,简化的支付验证。在比特币白皮书翻译里面提到过,我们再复(预)习一下。

It is possible to verify payments without running a full network node. A user only needs to keep a copy of the block headers of the longest proof-of-work chain, which he can get by querying network nodes until he's convinced he has the longest chain, and obtain the Merkle branch linking the transaction to the block it's timestamped in. He can't check the transaction for himself, but by linking it to a place in the chain, he can see that a network node has accepted it, and blocks added after it further confirm the network has accepted it.

上面一段是比特币白皮书第八章关于简化支付验证的原文描述。

翻译过来意思就是:

不运行一个完整的网络节点也是可以进行支付验证的。用户只需拥有一个最长工作量证明链的区块头副本,他可以通过向其他网络节点查询以确认他拥有了最长的链,并获取链接交易到给交易打时间戳区块的默克尔分支。虽然他自己不能核实这个交易,但如果交易已经链接到到链中的某个位置,就说明一个网络节点已经接受了此交易,而其后追加的区块进一步确认网络已经接受了它。

这个就是简化的支付验证最初的本意。

在实际的应用中,许多比特币客户端被设计成在空间和电源受限设备上运行,比如说智能手机、平板电脑或者嵌入式设备。对这些设备,通过SPV可以允许它们在不存储完整区块链的情况下工作。这些类型的客户端被称为SPV客户端或者轻量客户端。

随着比特币使用的兴起,SPV节点变成了比特币节点最常见的形式,尤其在比特币钱包中最为常见。

SPV节点仅下载区块头而不下载每个区块内包括的交易。由此得到的不包含交易的区块链,比完整区块链要小1000倍。

SPV节点无法构建所有可用的UTXO的全貌,因为它们不知道网络上的全部交易。SPV节点的交易验证方法略有不同,它们依赖于对等节点按需提供区块链相关部分的局部视图

回到我们本期要解释的问题:全节点可以根据完整的区块数据验证UTXO是否被花费,那么SPV又该如何进行验证交易?

2.1 SPV通过参考区块链的深度而非高度来验证交易。

高度,是指最新区块到创世区块之间的距离。

深度,指最新区块号和当前该笔交易所在区块的区块号之间的距离,比特币区块确认数为6,也就是说,当一笔交易被六个区块确认后就基本不可逆了,从而也就避免了双花攻击。对应到深度就是,在此笔交易所在区块之后又叠加了6个区块。

图片

(1)当在块号300,000上检查一笔交易的时候,一个全节点链接了从创世区块到全部300,000个区块,建立了一个完备的UTXO数据库,通过确认一个UTXO还没有被支付来验证交易的有效性。

(2)一个SPV节点无法验证一个UTXO是否被支付,相反,SPV节点会用一个merkle路径在交易和包含它的区块之间建立联系。

(3)之后SPV节点会一直等到看见从300,001到300,006的6个区块被加在包含这笔交易的区块之上,并通过在区块300,006到300,001之下确立它的深度来验证交易。

(4)事实上,网络上其他节点接受300,000号区块,并在它之上至少又生成了6个区块,根据代理协议,就能证明这笔交易不是双重花费。

由于SPV没有存储所有交易,所以无法证明交易是被双花,只能证明交易存在。所以SPV需要随机连接多个对等节点,以增加至少与一个可靠节点连接的概率,但这种连接方式也让SPV节点容易遭受网络分区攻击和女巫攻击。

2.2 SPV节点同步消息的过程

为了得到区块头,SPV节点使用getheaders消息。

响应的对等节点会用一个headers消息发送不超过2000个区块头。这个过程和全节点获取所有区块是一样的。

SPV节点还会在到对等节点的连接上设置一个过滤器,来过滤对等节点发送的未来块和消息的流。

任何目标交易都是通过使用getdata请求来获取的,对等节点产生一条包含该交易的tx消息作为响应。

图片

因为SPV节点需要获取特定交易以有选择地验证它们,它们还产生了一个隐私风险。(问题终于来了)

不像全区块链节点收集了每个区块内的全部交易,SPV节点针对特定数据的请求可能无意间泄露了它们钱包的地址。

比特币开发者使用bloom filter来解决SPV节点的隐私风险,允许SPV节点在不需要精确指定它们关心的地址的情况下接收一个交易子集。


3. Bloom filter:布隆过滤器

布隆过滤器(Bloom Filter),1970 年由 Burton Howard Bloom 在论文《Space/Time Trade-offs in Hash Coding with Allowable Errors》提出。

布隆过滤器是一种基于 Hash 的高效查找结构,能够快速(常数时间内)回答“某个元素是否在一个集合内”的问题。布隆过滤器最大的特点是:会误报,但绝不会漏报。什么意思?

当布隆过滤器说某个值存在时,这个值可能不存在;当它说不存在时,那就肯定不存在。

布隆过滤器的应用十分广泛,大部分程序员可能都使用过(不知道就赶紧去学~~)。

(1)解决缓存雪崩和缓存穿透。使用Redis时,在某种情况下,可能会出现缓存雪崩和缓存穿透,便可以使用布隆过滤器来解决。

(2)邮箱的垃圾邮件过滤、黑名单等。

(3)去重:比如爬给定网址的时候对已经爬取过的 URL 去重。

 布隆过滤器(Bloom Filter)的核心实现是一个超大的位数组和几个哈希函数。假设位数组的长度为m,哈希函数的个数为k。

图片

1. 假设集合里面有3个元素{x, y, z},哈希函数的个数为3。

2. 首先将位数组进行初始化,将里面每个位都设置位0。

3. 对于集合里面的每一个元素,将元素依次通过3个哈希函数进行映射,每次映射都会产生一个哈希值,这个值对应位数组上面的一个点,然后将位数组对应的位置标记为1。

4. 查询W元素是否存在集合中的时候,同样的方法将W通过哈希映射到位数组上的3个点。如果3个点的其中有一个点不为1,则可以判断该元素一定不存在集合中。反之,如果3个点都为1,则该元素可能存在集合中。

注意:此处不能判断该元素是否一定存在集合中,可能存在一定的误判率。

可以从图中可以看到:假设某个元素通过映射对应下标为4,5,6这3个点。虽然这3个点都为1,但是很明显这3个点是不同元素经过哈希得到的位置,因此这种情况说明元素虽然不在集合中,也可能对应的都是1,这是误判率存在的原因。

关于布隆过滤器的实现和误判率的处理就不详细解释了,只解释简单的工作原理,大家有兴趣可以在网上自行搜索。我们聚焦布隆过滤器在SPV中是应用。

那么SPV究竟是如何使用布隆过滤器的呢?


4. SPV节点如何使用布隆过滤器

1. 一个SPV节点会将一个bloom过滤器初始化为“空”;

2. SPV节点会列出它感兴趣的所有地址、密钥和散列值。它通过从钱包控制的任意UTXO来提取公钥散列值、脚本散列值和交易ID,进而生成这些列表。

3. SPV节点会把这些信息都加入bloom过滤器,这样bloom过滤器可以判断一笔交易是否与这些模式“匹配”而不用泄露模式本身。

4. SPV节点之后会发送一个filterload消息给对等节点,包含了要在连接上使用的bloom过滤器。

5. 在对等节点上,针对每笔传入交易检查过滤器。全节点根据bloom过滤器检查交易的几个部分来寻找匹配,包括:交易ID、每个密钥和脚本中的散列值、每个交易输入、每个输入签名数据组件。

6. bloom过滤器可以被用来匹配公钥散列值、脚本、OP_RETURN值、签名公钥,或者任何智能合约或复杂脚本中的未来组件。

 总结一下:

  • 当全节点向SPV节点发送交易,SPV节点会丢弃所有误报交易,仅使用正确匹配上的交易来更新它的UTXO集合和钱包余额。
  • 当它更新它自己的UTXO视图的时候,它也会修改bloom过滤器来匹配引用到它刚发现的UTXO的未来交易。

  • 之后全节点使用新的bloom过滤器来匹配新交易,并重复这个流程。

至此,今天要回答的问题,也解释清楚了。

本期分享结束,期待下一期吧~~

本文参考:

  • 《区块链:技术驱动金融》

  • 《精通比特币》第二版

猜你喜欢

转载自blog.csdn.net/koudan567/article/details/121714643
今日推荐