SPV) 节点与Bloom 过滤器

区块链鼻祖比特币之12:(SPV) 节点与Bloom 过滤器

置顶 2018年04月27日 16:55:28 尹成 阅读数:975

 版权声明:本文为博主尹成联系QQ77025077,微信18510341407原创文章,欢迎转载侵权不究。 https://blog.csdn.net/yincheng01/article/details/80110273

   (SPV) 节点

        并非所有的节点都有能力储存完整的区块链。许多比特币客户端被设计成运行在空间和功率受限的设备上,如智能电话、平板电脑、嵌入式系统等。对于这样的设备,通过简化的支付验证(SPV)的方式可以使它们在不必存储完整区块

链的情况下进行工作。这种类型的客端被称为 SPV 客户端或轻量级客户端。随着比特币的使用热潮,SPV 节点逐渐变成比特币节点(尤其是比特币钱包)所采用的最常见的形式。SPV 节点只需下载区块头,而不用下载包含在每个区块中的交易信息。由此产生的不含交易信息的区块链,大小只有完整区块链的 1/1000。SPV 节点不能构建所有可用于消费的 UTXO 的全貌,这是由于它们并不知道网络上所有交易的完整信息。SPV 节点验证交易时所使用的方法略有不同,这个方法需依赖对等节点“按需”提供区块链相关部分的局部视图。打个比方来说,每个全节点就像是一个在陌生城市里的游客,他带着一张包含每条街道、每个地址的详细地图。相比之下,SPV 节点就像是这名陌生城市里的游客只知道一条主干道的名字,通过随机询问该城市的陌生人来获取分段道路指示。虽然两种游客都可以通过实地考察来验证一条街是否存在,但没有地图的游客不知道每个小巷中有哪些街道,也不知道附近还有什么其他街道。没有地图的游客在“教堂街 23 号”的前面,并不知道这个城市里是否还有其他若干条“教堂街 23 号”,也不知道面前的这个是否是要找的那个。对他来说,最好的方式就是向足够多的人问路,并且希望其中一部分人不是要试图抢劫他。简易支付验证是通过参考交易在区块链中的深度,而不是高度,来验证它们。一个拥有完整区块链的节点会构造一条验证链,这条链是由沿着区块链按时间倒序一直追溯到创世区块的数千区块及交易组成。而一个 SPV 节点会验证所有区块的链(但不是所有的交易),并且把区块链和有关交易链接起来。例如,一个全节点要检查第 300,000 号区块中的某个交易,它会把从该区块开始一直回溯到创世区块的 300,000 个区块全部都链接起来,并建立一个完整的 UTXO 数据库,通过确认该 UTXO 是否还未被支付来证实交易的有效性。 SPV节点则不能验证 UTXO 是否还未被支付。相反地,SPV节点会在该交易信息和它所在区块之间用 merkle 路径建立一条链接。然后

SPV 

节点一直等待,直到序号从 300,001 到 300,006 的六个区块堆叠在该交易所在的区块之上,并通过确立交易的深度是在第 300,006区块~第 300,001 区块之下来验证交易的有效性。事实上,如果网络中的其他节点都接受了第300,000 区块,并通过足够的工作在该块之上又生成了六个区块,根据代理网关协议,就可以证明该交易不是双重支付。如果一个交易实际上不存在,SPV 节点不会误认为该交易存在于某区块中。SPV 节点会通过请求 merkle 路径证明以及验证区块链中的工作量证明,来证实交易的存在性。可是,一个交易的存在是可能对 SPV 节点“隐藏”的。SPV 节点毫无疑问可以证实某个交易的存在性,但它不能验证某个交易(譬如同一个UTXO 的双重支付)不存在,这是因为 SPV 节点没有一份关于所有交易的记录。这个漏洞会被针对 SPV 节点的拒绝服务攻击或双重支付型攻击所利用。为了防御这些攻击,SPV 节点需要随机连接到多个节点,以增加与至少一个可靠节点相连接的概率。这种随机连接的需求意味着 SPV 节点也容易受到网络分区攻击或 Sybil 攻击。在后者情况中,SPV 节点被连接到虚假节点或虚假网络中,没有通向可靠节点或真正的比特币网络的连接。在绝大多数的实际情况中,具有良好连接的 SPV 节点是足够安全的,它在资源需求、实用性和安全性之间维持恰当的平衡。当然,如果要保证万无一失的安全性,最可靠的方法还是运行完整区块链的节点。

Bloom 过滤器

Bloom 过滤器是一个允许用户描述特定的关键词组合而不必精确表述的基于概率的过滤方法。它能让用户在有效搜索关键词的同时保护他们的隐私。在SPV 节点里,这一方法被用来向对等节点发送交易信息查询请求,同时交易地址不会被暴露。我们之前的例子,一位手中没有地图的游客需要询问去特定地方的路线。如果他向陌生人询问“教堂街 23 号在哪里”,不经意之间,他就暴露了自己的目的地。Bloom 过滤器则会这样问,附近有带‘堂’字的街道吗?”这样的问法包含了比之前略少的关键词。这位游客可以自己选择包含信息的多少,比如 “以‘堂街’结尾”或者“‘教’字开头的街道”。如果他问得越少,得到了更多可能的地址,隐私得到了保护,但这些地址里面不乏无关的结果;如果他问得非常具体,他在得到较准确的结果的同时也暴露了自己的隐私。Bloom 过滤器可以让 SPV 节点指定交易的搜索模式,该搜索模式可以基于准确性或私密性的考虑被调节。一个非常具体的 Bloom 过滤器会生成更准确的结果,但也会显示该用户钱包里的使用的地址;反之,如果过滤器只包含简单的关键词,更多相应的交易会被搜索出来,在包含若干无关交易的同时有着更高的私密性。首先,SPV 节点会初始化一个不会匹配任何关键词的“空白”Bloom 过滤器。接下来,SPV 节点会创建一个包含钱包中所有地址信息的列表,并创建一个与每个地址相对应的交易输出相匹配的搜索模式。通常,这种搜索模式是一个向公钥付款的哈希脚本、,该脚本是一个会出现在每一个向公钥哈希地址付款的交易中的锁定脚本。如果SPV 节点需要追踪 P2SH 地址余额,搜索模式就会变成 P2SH 脚本。然后,SPV 节点会把每一个搜索模式添加至 Bloom 过滤器里,这样只要关键词出现在交易中就能够被过滤器识别出来。最后,对等节点会用收到的 Bloom 过滤器来匹配传送至 SPV 节点的交易。Bloom 过滤器的实现是由一个可变长度(N)的二进制数组(N 位二进制数构成一个位域)和数量可变(M)的一组哈希函数组成。。这些哈希函数的输出值始终在 1 和 N 之间,该数值与二进制数组相对应。并且该函数为确定性函数,也就是说任何一个使用相同 Bloom 过滤器的节点通过该函数都能对特定输入得到同一个的结果。Bloom 过滤器的准确性和私密性能通过改变长度(N)和哈希函数的数量(M)来调节。

Bloom 过滤器数组里的每一个数的初始值为零。关键词被加到 Bloom 过滤器中之前,会依次通过每一个哈希函数运算一次。该输入经第一个哈希函数运算后得到了一个在 1 和 N 之间的数,它在该数组(编号依次为 1 至 N)中所对应的位被置为 1,从而把哈希函数的输出记录下来。接着再进行下一个哈希函数的运算,把另外一位置为 1;以此类推。当全部 M 个哈希函数都运算过之后,一共有 M 个位的值从 0 变成了 1,这个关键词也被“记录”在了 Bloom 过滤器里。图 显示简易 Bloom 过滤器添加关键词“A”。

SPV) 节点与Bloom 过滤器_第1张图片

增加第二个关键是就是简单地重复之前的步骤。关键词依次通过各哈希函数运算之后,相应的位变为 1,Bloom 过滤器则记录下该关键词。需要注意的是,当Bloom 过滤器里的关键词增加时,它对应的某个哈希函数的输出值的位可能已经是 1 了,这种情况下,该位不会再次改变。也就是说,随着更多的关键词指向了重复的位,Bloom 过滤器随着位 1 的增加而饱和,准确性也因此降低了。该过滤器之所以是基于概率的数据结构,就是因为关键词的增加会导致准确性的降低。准确性取决于关键字的数量以及数组大小(N)和哈希函数的多少(M)。更大的数组和更多的哈希函数会记录更多的关键词以提高准确性。而小的数组及有限的哈希函数只能记录有限的关键词从而降低准确性。

图显示了向该简易 Bloom 过滤器里增加第二个关键词“B”。

SPV) 节点与Bloom 过滤器_第2张图片

为测试某一关键词是否被记录在某个 Bloom 过滤器中,我们将该关键词逐一代入各哈希函数中运算,并将所得的结果与原数组进行对比。如果所有的结果对应的位都变为了 1,则表示这个关键词有可能已被该过滤器记录。之所以这一结论并不确定,是因为这些字节 1 也有可能是其他关键词运算的重叠结果。简单来说,Bloom 过滤器正匹配代表着“可能是”。下图是一个验证关键词“X”是否在前述 Bloom 过滤器中的图例。相应的比特位都被置为 1,所以这个关键词很有可能是匹配的。

SPV) 节点与Bloom 过滤器_第3张图片

若结果为或然正匹配,则表示“可能是”。另一方面,如果我们代入关键词计算后的结果某位为 0,说明该关键词并没有被记录在过滤器里。负匹配的结果不是可能,而是一定。也就是说,负匹配代表着“一定不是”。下图 是一个验证关键词“Y”是否存在于简易 Bloom 过滤器中的图例。图中某个结果字段为 0,该字段一定没有被匹配。

SPV) 节点与Bloom 过滤器_第4张图片

Bloom 过滤器被用来过滤 SPV 节点从对等节点里收到的交易信息。SPV 会建立一个只能和 SPV 节点钱包里的地址匹配的过滤器。随后,SPV 节点会向对等节点发送一条包含需在该连接中使用的过滤器的 filterload 消息。当过滤器建好之后,对等节点将每个交易的输出值代入过滤器中验证。那些正匹配的交易会被传送回 SPV 节点。为回应来自 SPV 节点的getdata 信息,对等节点会发出一条只含有和过滤器匹配的区块的区块头信息,以及与之相匹配的交易的 merkle 树。这一对等节点还会发出一条相匹配的交易的 tx 消息。这个节点能够通过发送一条 filteradd 信息来向它的 Bloom 过滤器增加关键词,也能够发送 filterclear 信息来清除整个过滤器。因为不能直接从过滤器里删除关键词,所以如果某关键词不再需要,节点必须通过清除和增加来替换原有的过滤器。

你可能感兴趣的:(SPV) 节点与Bloom 过滤器)