2.3 使用区块链达成没有身份的共识

在这一节里,我们将探讨比特币共识算法的技术细节。回忆一下,我们在前面曾说过,比特币中的每个节点并没有一个稳定的、长期的身份,这一点也是与传统分布式共识算法的不同之处。身份缺失的原因是,在一个点对点网络中,没有一个中央权威机构来发放身份,并保证它们没有制造节点。用技术术语来说,乱造节点就是所谓的“女巫攻击”(sybil attack)现象。女巫就是恶意黑客制造的不同节点,这些节点看起来像是对应不同的身份的人,其实是由一个人在幕后控制。另一个原因是化名制(pseudonymity),也是比特币想达到的一个目标,所以即使可以替所有节点建立唯一真实身份,我们也不想那样做。虽然比特币还是不能保证真正的匿名,一个用户用不同身份做的不同交易还是有办法被最终追踪到,但比特币的特性毕竟没有强迫大家用真实身份来加入。这是比特币的重要特性,也是比特币系统的核心理念。

如果所有节点都有真实身份的话,那么设计上会更加容易。有了真实身份,我们就能够以这样的方式发出协议指令,比如“编号最小的节点开始做某些动作”,在没有真实身份前提下,系统能设计的指令就受到很多限制,但设计真实身份最主要的考虑是安全上的便利。如果节点的身份可以被识别,就不能随便地制造新的节点身份出来。那样的话,我们就可以假设有恶意节点的数量,然后部署安全措施来防范。基于以上原因,缺少真实身份给比特币的共识协议带来很多难点。

我们可以做一个较弱的理论假设来弥补这个先天的不足。假设我们可以在系统里随意选一个节点,一个比较好的比喻是——就如同在彩票站,或是在任何一个难以辨别每个人身份的系统中,我们给每一位顾客发出彩票或是一个识别牌,之后我们就可以开始抽奖,与奖号对应的人就会中奖。现在我们想象一下在比特币的世界里,我们假设也可以做到这一点。我们再假设,这个彩票的印制过程与发放办法是足够聪明的,如果一个黑客想制造出许多女巫节点来,最后所有这些节点也只能拿到一张彩票。也就是说,这个黑客无法通过制造假的节点来增强他的力量。如果你觉得我们做的假设太多了,请不要担心,我们在以后会消除这些假设,并在后文会详细说明,在比特币系统中,与这些假设相对应的性质是如何实现的。

隐性共识

对随意节点选择的假设可以让“隐性共识”(inplicit consensus)成为可能。我们的共识协议有多个回合,每个回合都对应着区块链里的一个块。在每一个回合里,一个随机节点会被选中,然后这个节点可以提议这个链的下一个区块。这时没有共识算法,也没有任何投票过程来决定哪个区块会被选中,随机被选中的节点会直接决定区块链的下一个区块,但万一这个节点是恶意的呢?针对这个问题,还是有应对办法的,解决方法就是隐性共识。其他节点可以通过隐性地接受或是拒绝前面这个被随机选择出来的节点。如果接受,它们会在这个块之后接龙下去;如果拒绝,它们忽略这个新的区块,而是选择前一曾经接受的区块,来继续接龙下去。大家还记得,每一块都记录着前一块的哈希值。这就是节点选择在哪一块来继续接龙的技术处理方式:比特币共识算法(简化版)。

这个算法的简化假设是,可以随意选择一个节点,这些节点都不会受到女巫攻击的影响。

1.新的交易被广播到所有节点上。

2.每个节点都将新的交易放进一个区块。

3.在每个回合,一个随机的节点可以广播它的区块。

4.其他节点可以选择接受这个区块,前提是如果区块里的交易都是正当的(有真的签名)。

5.节点们可以把以上区块的哈希值放进自己的区块里,以此来表示它们对那个新区块的认可。

我们现在一起来研究一下为什么这样一个共识算法是有效的。为此,我们假设有一个叫爱丽丝的黑客,她想要破坏这个共识过程。

窃取比特币

爱丽丝能够窃取属于另一个用户,不受她控制的地址里的比特币吗?答案是否定的。即使这一轮是由爱丽丝提议区块链上的下一个区块,她也不可能窃取别人的比特币。这么做的话,爱丽丝需要发起一笔有效的交易来花掉这个比特币。这就要求爱丽丝伪造比特币拥有者的签名,然而如果数字签名机制是安全的,她是无法办到的。只要背后的密码学基础是牢靠的,她就无法轻易窃取比特币。

拒绝服务攻击

让我们来考虑另一种攻击。假设爱丽丝不喜欢叫鲍勃的某个用户,爱丽丝可以决定她不把鲍勃发起的任何交易放进她所提议的区块里。换言之,她拒绝提供服务给鲍勃。尽管这是爱丽丝可以开展的有效的攻击,但幸好这不过是个小问题。如果鲍勃的交易没有被放进爱丽丝所提议的下一个区块,鲍勃只要等到下一个诚实节点发起区块的时候,他的交易记录就会被放进这个区块里。所以这其实也不算是一个有效的攻击。

双重支付攻击

爱丽丝也可能会发起一个双重支付攻击。要理解爱丽丝如何发起这种攻击,我们可以假设爱丽丝是鲍勃开的网店或网站的一名顾客。鲍勃提供一些比特币付费的在线服务,比如软件下载。双重支付攻击是这样的:爱丽丝在鲍勃的网站选中一件商品并加入购物车中,此时服务器要求付款。然后,爱丽丝在她的地址上向鲍勃的地址发起了一笔比特币交易,并向整个网络广播这笔交易。我们假设由某个诚实节点来制造下一个区块,并把这笔交易放进这个区块中。因此,现在就有了一个由诚实节点发起,包含代表爱丽丝向商家鲍勃支付这笔交易在内的区块了。

我们还记得一个交易就是一个数据结构,里面有爱丽丝的数字签名,一个付给鲍勃的公钥(地址)的指令和一个哈希值。这个哈希值代表了一个指针,指向先前的一笔交易的输出,即爱丽丝之前收到并于现在消费比特币。这个指针必须指向一个已被共识链上的某个之前的区块所认可的交易。

顺便说一下,有两种容易混淆的不同类型的哈希指针。一种是在区块内用来表示接在之前哪个区块后面的哈希指针;另一种是在交易里的一个或多个,用来指向之前交易里说明比特币来源的哈希指针。

我们回到爱丽丝如何发起双重支付攻击这个问题。最新的一个区块由一个诚实节点产生,其中包含爱丽丝下载软件向鲍勃付费的交易记录。当看到这笔交易被放入区块链后,鲍勃认为爱丽丝已经向他付款,便允许爱丽丝下载软件。假设在下一个回合被随机选中的节点恰巧被爱丽丝所控制。现在因为爱丽丝可以提议下一个区块,她可以选择忽略掉前面那个包含她支付给鲍勃的那笔交易的区块,而产生一个包含指向之前区块指针的区块。不仅这样,在这个区块里,爱丽丝可以放进一笔交易,把她付给鲍勃的币转到一个被她所控制地址里去。这就是一个经典的双重支付攻击。因为这两个交易用的是同一个币,只有一个交易可以被放进区块链。所以如果爱丽丝成功地把币转到她控制的地址,那个她付币给鲍勃的交易记录将变得无效,因为它将不会被放进区块链里。这一过程详见图2.2。

图2.2 双重支付攻击

注:爱丽丝创建了两笔交易:一笔是她付给鲍勃比特币的交易,另一笔是她将这笔比特币重复支付到她控制的另一个地址。因为这两笔交易用相同的比特币支付,所以只有一笔会被放进区块链。图中的箭头表示一个区块链接到前一个区块的指针,通过在前一个区块自己的内容中包含了一个哈希值进行了扩展。CA代表爱丽丝拥有的币。

那我们如何知道这个双重支付攻击是否能成功呢?这取决于最后哪个区块会被纳入长期的共识链,是爱丽丝转给鲍勃的区块,还是爱丽丝转给爱丽丝自己的区块。是什么决定了哪一个区块被纳入呢?诚实节点会遵守在最长有效分支后面延展这一规则,那到底在哪个分支后面延展呢?并没有明确的答案!目前来看,这两条分支长度一样,它们的区别是仅在于最后一个区块,并且这两个区块都是有效的。选择下一个区块的节点可以决定建立在其中一个区块上。这个选择就决定了双重支付攻击的成功与否。

微妙之处在于:从道德角度考虑,这两个分支截然不同,一个是包含付给鲍勃交易的区块,一个是包含爱丽丝把这些币双重支付给她自己地址交易的区块。但这个区别仅仅建立在我们知道爱丽丝先支付给鲍勃再试图双重支付这个故事的基础上。但从技术角度来看,这两笔交易完全一致,且都有效。节点没有办法分辨出哪一个是道义上合理合法的交易。

实践中,节点往往用延展它们在点对点网络里最早听到的区块这种启发式的方法。但这不是一个无懈可击的法则。在一些情况下,因为网络延迟,很可能它们先听到的区块实际上是后被创造出来的。所以下一个提议节点至少是有可能选择在那个包含双重支付的区块上延展。爱丽丝甚至还可以贿赂下一个提议节点来加大这个可能性。不管出于什么原因,如果下一个节点真的接受了这个双重支付的区块,那么这条链将比包含支付给鲍勃交易的那条链更长。基于此,下一个诚实节点就有可能去延展这条链,因为它更长。随着这个过程继续,这条包含双重支付的链会更有可能成为长期共识链的一部分。相反,那个包含爱丽丝支付给鲍勃交易区块的链会被网络完全遗忘,成为一个孤块(orphan block)。

我们现在从商家鲍勃的立场重新考虑整个情况。理解鲍勃如何保护自己不受双重支付攻击是理解比特币安全措施的重要的一部分。当爱丽丝广播她向鲍勃支付的交易时,鲍勃也在网上听着,鲍勃在下一区块被创建之前就能听到这笔交易。如果鲍勃比我们前面描述的更加草率的话,他可以在网上完成检查程序,并允许爱丽丝此时下载软件。这叫作零验证交易(zero confirmation transaction)。这将导致一个比前面所说的更加基础的双重支付攻击。前面所述情况,为了实现双重支付攻击,我们需要假设一个恶意黑客控制了发起下一个区块的节点。但如果鲍勃允许爱丽丝在没有收到区块链一条确认信息的情况下就下载软件,那么爱丽丝可以立刻广播一条双重支付交易,一个诚实节点就有可能把这个交易放进下一区块,而不是支付给鲍勃的那笔交易。见图2.3。

图2.3 从鲍勃立场来看双重支付

注:这是一个从商家鲍勃的立场来看爱丽丝做的双重支付尝试。为了保护自己免受双重支付攻击,鲍勃应当等爱丽丝向他支付的交易被区块链包含进去,并且多等几次确认。

另一方面,一个谨慎的商家甚至在看到交易被包含在一个区块后仍然不会允许爱丽丝下载软件,而是继续等待。如果鲍勃看到爱丽丝成功发起了双重支付的攻击,他会意识到那个含有爱丽丝向他支付的交易的区块有可能已经被丢弃。他应该放弃这个交易,不让爱丽丝下载软件。如果在尝试双重支付的情况下,恰巧下几个节点还是建立在爱丽丝向鲍勃支付交易的区块上,那鲍勃就相信这笔交易会被纳入长期共识链。

总而言之,一个交易得到的确认越多,它被纳入长期共识链的概率就越大。如前文所述,诚实节点总是选择延展最长的共识链。因为长链增长更多,那条含有双重支付的短链追上长链的概率会变得越来越小。在只有一小撮恶意节点的情况下,这个结论尤其正确。因为短链要想赶上,这些恶意节点需要被一直连续选中。

事实证明,双重支付攻击成功的概率将随着确认的数目的增加而指数级降低。所以,如果你感兴趣的交易已经收到k个确认,双重支付攻击交易被纳入长期共识链的概率以关于k的一个函数指数级下降。在比特币生态系统里,最常见的方法是等6个确认。并不是6这个数字有什么特殊意义,只不过,这样在你等待的时间与确认你所感兴趣的交易被纳入长期共识链之间做了很好的平衡如后文总结时所说,并没有一个固定的数字,但6是个常用的数目。——译者注

总结起来,防止不正当交易完全是用密码学的方法。但这些方法被共识所加强,意思是一个节点如果想放进一个密码学上不正当的交易,这个交易不会被纳入长期共识链的唯一原因是绝大多数的节点是诚实的,不会把一个不正当交易放进区块链。另外,防止双重支付攻击完全依赖于共识,密码学不起任何作用。从密码角度来看,这两个交易都是正当有效的。但共识可以能决定哪个被放进长期共识链。最后,你无法百分之百保证你感兴趣的交易被放进了长期共识链。但指数级概率保证了不错的结果,6笔交易过后,实质上你没有犯错的可能了。