8.8 简易支付验证 (Simplified Payment Verification (SPV) )节点
并非所有的节点都有能力储存完整的区块链。许多比特币客户端被设计成运行在空间和功率受限的设备上,如智能电话、平板电脑、嵌入式系统等。对于这样的设备,通过简化的支付验证(SPV)的方式可以使它们在不必存储完整区块链的情况下进行工作。这种类型的客端被称为SPV客户端或轻量级客户端。随着比特币的使用热潮,SPV节点逐渐变成比特币节点(尤其是比特币钱包)所采用的最常见的形式。
SPV节点只需下载区块头,而不用下载包含在每个区块中的交易信息。由此产生的不含交易信息的区块链,大小只有完整区块链的1/1000。SPV节点不能构建所有可用于消费的UTXO的全貌,这是由于它们并不知道网络上所有交易的完整信息。SPV节点验证交易时所使用的方法略有不同,这个方法需依赖对等节点“按需”提供区块链相关部分的局部视图。
打个比方来说,每个全节点就像是一个在陌生城市里的游客,他带着一张包含每条街道、每个地址的详细地图。相比之 下,SPV节点就像是这名陌生城市里的游客只知道一条主干道的名字,通过随机询问该城市的陌生人来获取分段道路指示。虽然两种游客都可以通过实地考察来验证一条街是否存在,但没有地图的游客不知道每个小巷中有哪些街道,也不知道附近还有什么其他街道。没有地图的游客在“教堂街23号”的前面,并不知道这个城市里是否还有其他若干条“教堂街 23号”,也不知道面前的这个是否是要找的那个。对他来说,最好的方式就是向足够多的人问路,并且希望其中一部分人不是要试图抢劫他。
简易支付验证是通过参考交易在区块链中的深度,而不是高度,来验证它们。一个拥有完整区块链的节点会构造一条验证链,这条链是由沿着区块链按时间倒序一直追溯到创世区块的数千区块及交易组成。而一个SPV节点会验证所有区块的链(但不是所有的交易),并且把区块链和有关交易链接起来。
例如,一个全节点要检查第300,000号区块中的某个交易,它会把从该区块开始一直回溯到创世区块的300,000个区块全部都链接起来,并建立一个完整的UTXO数据库,通过确认该UTXO是否还未被支付来证实交易的有效性。SPV节点则不能验证UTXO是否还未被支付。相反地,SPV节点会在该交易信息和它所在区块之间用merkle路径(见“ 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节点是足够安全的,它在资源需求、实用性和安全性之间维持恰当的平衡。当然,如果要保证万无一失的安全性,最可靠的方法还是运行完整区块链的节点。
提示 完整的区块链节点是通过检查整个链中在它之下的数千个区块来保证这个UTXO没有被支付,从而验证交易。而 SPV节点是通过检查在其上面的区块将它压在下面的深度来验证交易。
SPV节点使用的是一条getheaders消息,而不是getblocks消息来获得区块头。发出响应的对等节点将用一条headers 消息发送多达2000个区块头。这一过程和全节点获取所有区块的过程没什么区别。SPV节点还在与对等节点的连接上设置了过滤器,用以过滤从对等节点发来的未来区块和交易数据流。任何目标交易都是通过一条getdata的请求来读取的。对等节点生成一条包含交易信息的tx消息作为响应。区块头的同步过程如图8-7所示。
图8-7SPV节点同步区块头
由于SPV节点需要读取特定交易从而选择性地验证交易,这样就又产生了隐私风险。与全区块链节点收集每一个区块内的全部交易所不同的是,SPV节点对特定数据的请求可能无意中透露了钱包里的地址信息。例如,监控网络的第三方可以跟踪某个SPV节点上的钱包所请求的全部交易信息,并且利用这些交易信息把比特币地址和钱包的用户关联起来,从而损害了用户的隐私。
在引入SPV节点/轻量级节点后不久,比特币开发人员就添加了一个新功能:Bloom过滤器,用以解决SPV节点的隐私风 险问题。Bloom过滤器通过一个采用概率而不是固定模式的过滤机制,允许SPV节点只接收交易信息的子集,同时不会精确泄露哪些是它们感兴趣的地址。
在引入SPV /轻量级节点后不久,比特币开发人员添加了一个名为bloom过滤器的功能来解决SPV节点的隐私风险。 Bloom过滤器允许SPV节点接收交易的一个子集,通过使用概率而不是固定模式的过滤机制无需精确地揭示他们感兴趣的地址。