从Java角度看区块链实践系列3——P2P网络:比特币P2P网络、全节点、SPV节点与Bloom布隆过滤器

比特币网络

比特币网络是一个P2P的网络,网络中不同节点互为对等关系,每个节点可能具有不同的功能。一共分为四个部分:节点路由、区块链数据库、挖矿、钱包服务。

四个功能:节点路由、区块链数据库、挖矿、钱包服务
四个功能:节点路由、区块链数据库、挖矿、钱包服务

 节点路由:主要负责参与验证并传播交易及区块信息,以及发现并维持与对等节点的连接;

区块链数据库:保存一份完整的、最新的区块链数据副本,通过这些数据能够独立自主地校验所有交易,而不需借由任何外部参照;

挖矿:通过运行工作量证明(proof-of-work)算法,以相互竞争的方式创建新的区块;(POW我们将在共识部分详细介绍)

钱包服务:提供密钥对的生成,交易签名,交易广播等等有关钱包的服务;(关于密钥以及签名我们将在签名算法部分详细介绍);

我们通常说的比特币网络,概指运行P2P协议的通讯网络,其实比特币还包括了其他的运行特殊协议的拓展网络。P2P网络上连接着许多矿池服务器以及协议网关,以这样的方式把运行其他协议的节点连接起来,比如stratum协议的矿池网络、早年基于UDP的FIBER中继网络等。

各种节点类型,网关和协议的扩展比特币网络
显示各种节点类型,网关和协议的扩展比特币网络

全节点

这种类型的节点包含了区块网络全部完整的交易数据。一般在区块链的早期,所有的节点都是全节点,并且往往都是由社区搭建维护的。全节点启动后,第一件需要干的事儿,就是完善本地的区块数据,因此,首先它会与上次连接的对等接节点进行交互,并随之发送getblocks请求,以接收最新的区块数据。

这里提一下,有些节点会维护一个交易池(一些优秀的公链项目都会有交易池),交易池的作用是缓存未确认交易,以便用户钱包的节点查询已经接收但还未被确认的、属于该用户钱包的预支付信息。有些节点还会单独维护一个孤立交易池,如果一个交易的输入与某未知的交易有关,如与缺失的父交易相关,也就是父交易还未被打包,该孤立交易就会被暂时储存在孤立交易池中直到父交易的信息到达。

 

全节点同步区块的过程
全节点通过从对等体检索区块同步区块链

SPV轻节点

SPV全称为“简易支付验证节点”——“Simplified Payment Verification”,之所以叫轻节点是因为他不需要下载存储完整区块数据,只需要下载区块头,大小只有完整区块的1/1000,目前截至2020.3.30完整区块数据大小为314.40 GB

现在,我们来思考一个问题,全节点可以根据完整的区块数据验证UTXO是否被花费,那么SPV又该如何进行验证交易?

简单的说,SPV通过交易在链上的深度,而不是高度,来验证交易。

什么是区块链的深度和高度?

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

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

区块在区块链中的位置越深,交易被改变的可能就越小。

举个例子,一个全节点需要检查第300,000号区块的某个交易,它会从300,000开始到创世区块(1号区块)全部链接起来,构建出一个UTXO库,然后再确认该UTXO是否已被花费来验证UTXO的有效性。

相反,SPV则会用该UTXO的信息和它所在区块的Merkle路径之间建立一条链接。然后,SPV节点陷入等待,直到区块高度到达300,006区块,也就是之后又生成了6个区块,也就证明UTXO的有效性,才能被用以花费。根据代理网关协议,当区块被6次确认后也就证明了该交易是不可双重支付的。

SPV会通过请求获取Merkle路径,然后通过证明以及验证区块链中的工作量证明(挖矿验证)来判断交易是不是真实存在

但是,SPV虽然可以证明交易的存在性,却无法证明交易是否是双重支付攻击,因为它没有关于所有交易的记录。

为了预防此类攻击漏洞,SPV需要随机连接多个对等节点,以增加至少与一个可靠节点连接的概率,但这种连接方式意味着SPV节点也容易受到网络分区攻击Sybil女巫攻击。(此篇文章的涉及区块链攻击我们将会在下一篇进行介绍)

绝大多数情况下,具备良好网络连接的SPV是足够安全的,总的来说SPV节点在资源需求、实用性和安全性之间进行了权衡。当然,如果需要确保万无一失的安全性,最可靠的办法还是运行全节点。

下图,SPV节点通过传递getheaders请求来获取区块头,同时SPV节点在此过程中还设置了过滤器。

SPV节点同步区块头
SPV节点同步区块头​​​​​​

由于SPV与对等节点进行getheaders交互,因此又产生了新的隐私风险,SPV通过Bloom布隆过滤器来解决隐私风险问题(我们稍后介绍隐私问题)。

Bloom过滤器

《精通比特币》中这样描述道:Bloom过滤器是一个允许用户描述特定的关键词组合而不必精确表述的基于概率的过滤方法。它能让用户在有效搜索关键词的同时保护他们的隐私。在SPV节点里,这一方法被用来向对等节点发送交易信息查询请求,同时交易地址不会被暴露。

布隆过滤器的工作原理

1、首先我们具有一个长度为N的数组和M个哈希函数,M个哈希函数的结果在1~N之间,数组里的每个元素初始值为0。这里以一个 16位的数组和3个哈希函数进行演示。

Bloom过滤器
Bloom过滤器结构

2、添加关键字的过程,是对关键字分别进行M个哈希的运算,以结果为索引,若索引位置为0,则修改为1,否则不进行更改,设置到数组N中。添加关键字:“A”。

添加关键字:“A”
添加关键字:“A”
添加关键字B
添加关键字:“B”

3、验证关键字是否在过滤器中,则是对关键字分别进行M个哈希的远算结果后,查看数组N中对应的比特位是否都被置位1,若全都为1则关键字存在,否则关键字不存在。接下来我们继续添加关键字:“B”。

验证关键字“X”是否已存在于Bloom过滤器
验证关键字“X”是否已存在于Bloom过滤器

4、基于这种设计,当数组全部被置为0时,Bloom过滤器的误识率就会变得非常的高。尽管如此,却依然不能掩盖Bloom过滤器在空间利用率查询时间方面的优秀,插入数据和查询数据的时间复杂度都是O(M)。Bloom过滤器被比特币用于的SPV节点,在以太坊合约也有应用,比如定位查找日志等。

SPV如何使用的Bloom过滤器?

SPV节点主要通过设置关键字(包括地址、密钥、散列)来告诉Bloom过滤器过滤从其它节点接收到的交易(包括块信息)。接下来我们详细介绍整个过程:

1、SPV节点初始化一个“空”的“过滤器”,如果过滤器为空,将会过滤全部信息;

2、列出SPV钱包中所有的的地址,密钥和散列;

3、将这些信息作为关键字添加到Bloom过滤器中,之后Bloom过滤器将会依据这些关键字过滤交易;

4、SPV节点向对等节点发送filteradd加载Bloom过滤器的请求,随后发送getdata消息以获取所需数据;

5、对等节点针对每笔传入的交易根据Bloom过滤器进行过滤,匹配的内容包括: 交易ID、Bloom可以过滤公钥哈希,脚本,OP_RETURN值,签名中的公钥、智能合同或复杂脚本的任何未来组件(脚本放在签名部分详细论述);

6、对等节点响应getdata请求,内容包括:一个merkleblock消息以及相关Tx交易信息,该消息仅包含与过滤器匹配的块和每个匹配交易的merkle路径(下节论述)的区块头;

7、SPV节点收到响应消息,将会更新本地的UTXO集和钱包余额,随后还会修改Bloom过滤器,之后重复此过程。

SPV隐私问题

SPV为了保证隐私,将不会告知Bloom过滤器完整的地址信息,通常会以部分地址信息作为关键字。除此之外我们还可以通过以下方式保证SPV节点隐私安全:

1、对连接进行加密认证:Tor洋葱网络传输。如果了解暗网的同学可能会很快了解,在这里简单的介绍以下。Tor网络是通过多层代理的方式保证匿名,不可追踪和隐私的随机网络,并提供数据的加密和封装,如果想要追踪发出请求真实服务器就需要层层破解代理服务器,转发的代理服务器越多,破解难度越大;

2、对连接进行加密认证:对等认证和加密。比特币在BIP-150和BIP-151两种比特币改进方案中增加了对P2P认证和加密的支,BIP-150要求在认证之前,两个节点按照BIP-151建立了加密通信,因此我们可以借助这两个提案加强SPV的隐私保护。

总结

这一节我们主要介绍了,比特币P2P网络的概念,之后详细介绍了全节点、SPV节点,全节点存储完整数据,而SPV节点只保存区块头部分区块数据,在一定程度上SPV节点并不是很安全,一般交易所都会2+个全节点,而不会使用单独的节点。最后我们介绍了Bloom过滤器的应用,以及SPV隐私问题的解决方案,通过这些知识你会对区块链“链”的概念有一定的了解。

如果觉得本文有什么不足之处,欢迎评论!我会尽我所能,进行完善 ~

 

参考文献:

《精通比特币第二版》

发布了21 篇原创文章 · 获赞 11 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_38652136/article/details/105198046