区块链系列:重塑经济与世界+数字货币到信用社会+解码区块链全球应用与投资案例
上QQ阅读APP看书,第一时间看更新

第三章
区块链进阶本章《简单支付验证》部分由海滨完成,《侧链》部分由申屠青春完成,《闪电网络》部分由潘志彪完成。

一、简单支付验证(SPV)

简单支付验证(Simplified Payment Verification,简称SPV)是一种无须维护完整的区块链信息,只需要保存所有的区块头部信息即可进行支付验证的技术。该技术可以大大节省区块链支付验证用户的存储空间,减轻用户存储负担,降低区块链未来交易量剧增而给用户带来的压力。以比特币系统为例,节点只需保存所有区块头信息,即可进行交易支付验证。节点虽然不能独立验证交易,但能够从区块链其他节点获取交易验证的必要信息,从而完成交易支付验证,同时还可以得到整个区块链网络对交易的确认数。

要理解SPV的概念,首先需要理解如下两类概念的区别。

一是SPV与轻钱包(或瘦客户端)的区别。轻钱包指的是节点本地只保存与其自身相关的交易数据(尤其是可支配交易数据),但并不保存完整区块链信息的技术。SPV的目标是验证某个支付是否真实存在,并得到了多少个确认。比如爱丽丝(Alice)收到来自鲍伯(Bob)的一个通知,鲍伯声称已经从其账户中汇款一定数额的钱给了爱丽丝。如何快速验证该支付的真实性,是SPV的工作目标。轻钱包或瘦客户端的目标不仅是支付验证,而且是用于管理节点自身的资产收入、支付等信息。比如爱丽丝使用轻钱包或瘦客户端管理自身在区块链的收入信息、支出信息,在本地只保存与爱丽丝自身相关的交易数据,尤其是可支配交易数据。轻钱包与SPV的最大区别是,轻钱包节点仍需下载每个新区块的全部数据并进行解析,获取并本地存储与自身相关的交易数据,只是无须在本地保存全部数据而已。而SPV节点不需要下载新区块的全部数据,只需要保存区块头部信息即可。虽然轻钱包或瘦客户端中部分借鉴了SPV的理念,但和SPV是完全不同的。

二是区块链支付验证与区块链交易验证的区别。SPV指的是区块链支付验证,而不是区块链交易验证。这两种验证方式存在很大的区别。区块链交易验证的过程比较复杂,包括账户余额验证、双重支付判断等,通常由保存区块链完整信息的区块链验证节点来完成。而支付验证的过程比较简单,只是判断该笔支付交易是否已经得到了区块链节点共识验证,并得到了多少的确认数即可。还是以比特币系统为例,用户爱丽丝收到来自鲍伯的通知,鲍伯声称已经从其账户中汇款一定数额的钱给爱丽丝。爱丽丝进行交易验证的过程如下:首先,爱丽丝遍历完整的区块链账本,在区块链账本的交易中保存了鲍伯的历史交易信息(包括鲍伯的汇款账户、鲍伯的签名、历史收款人的地址以及汇款金额信息等),查询鲍伯的账户,就可以判断鲍伯提供的账户是否有足够的余额,如果余额不足则交易验证失败;其次,爱丽丝要根据区块链账本判断鲍伯是否已经支出了这个账户上的钱给别人,即是否存在双重支付问题,如果存在则交易验证失败;最后,判断鲍伯是否拥有其提供账户的支配权,如果判断失败则交易验证失败。而如果爱丽丝只是进行支付验证,则过程简单得多:通过SPV,爱丽丝可以进行支付快速验证,即检查此项支付交易是否已经被收录存储于区块链中,并得到了多少个确认数,就可以判断支付验证的合法性。详细的技术原理如下。

(一)SPV的技术原理

在区块链中,区块信息主要包括区块大小、区块头、交易数量和交易信息四部分内容。其中,区块头大小为固定字节,比如比特币中区块头的大小始终为80字节。区块头中一般包括如下信息:前一区块(也称父区块)的哈希值、区块中交易默克尔树的根哈希值、时间戳等。以比特币为例,其区块头的数据结构如表3-1所示。

表3-1 区块头的数据结构

通过区块的哈希值,可以识别出区块链中的对应区块。区块前后有序链接,每一个区块都可以通过其区块头的“前一区块的哈希值”字段引用前一区块。这样把每个区块均链接到各自前一区块的哈希值序列就创建了一条一直可以追溯到第一个区块(创世区块)的链条。前一区块的哈希值,可以确保区块链所记录的交易次序。默克尔树的根哈希值则可以确保收录到区块中的所有交易的真实性。

区块链节点利用SPV对支付进行验证的工作原理如下:

①计算待验证支付的交易哈希值;

②节点从区块链网络上获取并存储最长链的所有区块头至本地;

③节点从区块链获取待验证支付对应的默克尔树哈希认证路径;

④根据哈希认证路径,计算默克尔树的根哈希值,将计算结果与本地区块头中的默克尔树的根哈希值进行比较,定位到包含待验证支付的区块;

⑤验证该区块的区块头是否已经包含在已知最长链中,如果包含则证明支付真实有效;

⑥根据该区块头所处的位置,确定该支付已经得到的确认数量。

上述方法可以减轻用户的负担。以比特币为例,无论未来的交易量多大,区块头的大小始终只有80字节,按照每小时6个的区块生成速度,每年产出52560个区块。当只保存区块头时,每年新增存储需求约为4兆字节,100年后累计的存储需求仅为400兆字节,即使用户使用的是最低端的设备,正常情况下也完全能够负载。

SPV的工作原理中,最为关键和复杂的是步骤③,节点从区块链获取待验证支付对应的默克尔树哈希认证路径的过程。例如,一个区块链节点想要知道其钱包中某个比特币地址即将到达的某笔支付,该节点会在节点间的通信链接上建立起布鲁姆过滤器,限制只接受含有目标比特币地址的交易。当节点探测到某交易符合布鲁姆过滤器的要求时,将以默克尔区块消息的形式发送该区块。默克尔区块消息包含区块头和一条连接目标交易与默克尔树根的默克尔哈希认证路径。默克尔树哈希认证路径是验证待验证支付是否存在于默克尔树的关键条件,该认证路径由默克尔树所有路径中节点的哈希值共同构成,自下而上进行哈希计算。节点能够使用该路径找到与该交易相关的区块,进而验证对应区块中该交易的有无。如图3-1所示为根据交易A、B、C、D、E、F、G、H生成的默克尔树。这是一棵自下而上通过哈希运算生成的二叉树。叶子节点为交易信息的哈希值,叶子节点两两进行哈希运算得到其父节点,继续此过程,直至生成默克尔树根节点。需要注意的是,如果存在单个叶子节点无法匹配成对,则用复制的方法构成完整的二叉树,比如图3-2中交易H不存在,则可以将交易G的哈希值M(G)复制一份替代M(H),从而完成二叉树的生成过程。

图3-1 交易默克尔树结构示意图

图3-2 默克尔树哈希认证路径示意图

假设待验证交易为E,则交易E的默克尔树哈希认证路径为图3-2虚线框所示的M(F)、M(GH)和M(ABCD)。通过该哈希认证路径,即可以通过哈希计算找到一条链接交易E与默克尔树根的完整路径。

(二)SPV的功能扩展

虽然SPV可以高效地进行支付验证,但对于节点当前状态(账户余额、账户信息甚至合约状态等)均无法给出证明。SPV能否扩展并更进一步呢?以太坊对SPV的功能进行了扩展:每一个区块头,并非只包含一棵默克尔树,而是包含了三棵默克尔树,分别对应了三种对象——默克尔交易树、默克尔收据树和默克尔状态树。其中默克尔收据树和默克尔状态树是比特币等现有区块链系统没有的。默克尔收据树是由展示每一笔交易影响的数据条构成的默克尔树。而在默克尔状态树中,则保存账户信息、账户余额等信息。三棵默克尔树的功能分工如下。

①默克尔交易树:保存交易信息,用于验证交易是否真实包含于区块链中。

②默克尔收据树:保存某个地址的历史事件实例,比如一个交易是否成功执行、一个众筹合约是否完成了目标等。

③默克尔状态树:保存了账户名称、账户余额等信息。

基于上述三棵树,以太坊不仅可以实现SPV的支付验证,而且可以快速验证账户是否存在、了解账户余额甚至快速判断交易是否执行成功等信息,实现了良好的SPV扩展。

(三)SPV面临的问题

SPV面临的第一个是问题是SPV节点与区块链系统去中心化程度似乎存在一定的矛盾。随着SPV节点数量的增多,那么区块链参与完整验证的节点数量就会减少。然而,SPV却不能完全独立构成区块链。由于SPV节点没有存储完整的区块链信息,SPV的实现离不开存储区块链完整信息的节点或系统的辅助。

SPV面临的第二个问题是交易可锻性攻击交易可锻性(transaction malleability)攻击,又称交易延展性攻击。攻击者侦听比特币P2P网络中的交易,利用交易签名算法的特征修改原交易中的input签名,生成拥有一样input和output的新交易,然后广播到网络中形成双重支付。这样,原来的交易将有一定的概率不能被确认,造成不可预料的后果。。由于SPV实现中一个关键步骤是根据支付哈希值定位其在区块中的位置,而该过程可能遭遇交易可锻性攻击。比如比特币系统中,交易可锻性攻击体现在交易ID(账号)可被伪造,而交易ID可被伪造的原因是比特币签名算法不够完善。以比特币为例,交易可锻性攻击的过程如下:在比特币的交易中,第三方交易系统会将交易发送方、接受方、交易金额等数据作为一个交易发送到比特币网络中,发送之前会对这条交易信息进行加密和签名,接着根据生成的签名最终获得一个哈希值,这个哈希值作为交易ID返回给提现的用户。一次交易请求过后,用户接收到的仅有一个交易ID,根据这个交易ID可以查看交易是否成功。当交易发送到比特币网络中后,网络中的各个节点会根据之前生成的签名来验证交易的真实性。问题就出在签名算法上:椭圆曲线数字签名ECDSA这个算法的一个问题是,修改签名的某个字节能够使签名依然校验成功,这样伪造签名之后交易依然能够成功进行。由于交易ID是根据签名生成的,而伪造之后的签名会生成一个完全不同的交易ID,第三方判断到两个ID不同便会确定当前交易失败,而事实上交易已经成功了。这时如果用户发现交易提示失败,可以再次发起交易,第三方交易系统一看之前交易确实失败了,那就会再进行一次交易。这时用户的比特币钱包里就会多收到一份比特币,也就造成了第三方交易平台资金损失。交易的可锻性体现在虽然交易签名被“锻造过”(即修改伪造过),但最终的交易依然有效。上述攻击对于SPV是有效的,因为在交易可锻性攻击场景中,伪造的交易和正常的交易都在区块链网络中,如果伪造的交易先被处理,那么攻击就成功。从而,SPV支付在区块链中的位置定位过程可能无法完成或出现错误,最终影响支付验证的进程和准确性。

有人提出可以通过改进SPV的工作流程来提升攻击防范的有效性,比如不再仅根据哈希值来判断支付的状态,而是使用双因素或者多因素验证,包括账户余额、支付信息追踪等来综合判断支付是否真正成功,但这会增加SPV的复杂度。如何更加有效地解决SPV面临的问题还值得进一步研究。