『学概念找员外』比特币网络(二)
如何处理双重支付
由于网络传递有延迟,不同的节点可能会有不同的交易池。当有双重支付攻击的时候,这个现象会变得十分有意思。假设员外想把同一个比特币支付给天宇与死柯侠,于是,员外几乎同时发出两笔交易。有些节点先听到员外→天宇交易,有些则先听到员外→死柯侠交易。当一个节点接收到了这两个交易当中任何一个,它就会把接收到的交易放入交易池中,之后,它听到了另一个交易,看上去像是双重支付交易,这个节点就会把它丢弃掉不再向外传播。结果就是众多的节点会对“哪一个交易应该被纳入区块链”产生分歧。这种情况被称为竞态条件(race condition)。
好在对于比特币来说,这完全不是问题:打包下一个区块的矿工会打破这个僵局,他会决定哪个交易会最终打包进这个区块。如果员外→天宇的交易进入区块,那些听到员外→死柯侠的节点会把员外→死柯侠的交易从交易池里剔除,因为那是一个双重支付;而那些听到员外→天宇的节点也会把这个交易剔除出去,因为这笔交易已经被纳入区块链。因此,一旦这个区块被传播以后,就不再有前面说的分歧了。
由于每个节点默认保留最早接收到的交易,所以节点在网络上的位置就很重要。如果两个矛盾的交易或区块在网络上两个不同地方被发起,它们会同时向整个网络广播,节点先接收到哪个交易取决于它在网络的位置。
当然,这基于一个假设:不管接收到什么信息,每个节点均保留最早接收到的交易。但是比特币网络是一个对等的网络,节点并不被强制要求这么做,任何节点都有权按照其他逻辑行事,并按照所选的逻辑决定到底保留哪个交易、转播哪些交易。
区块的传播与核验
至于区块的传播,即矿工挖到一个矿(打包一个区块),然后将区块加入区块链,这个过程与新交易的传播过程类似,也受同样竞态条件的限制。如果两个有效的区块同时被挖到(也就是有两个矿工同时获得了记账权力时),只有其中一个区块可以进入长期共识链,哪个区块被最终纳入长期共识链取决于其他节点选择在哪个区块上扩展区块链,未被纳入的一个即被丢弃。
核验一个区块要比核验一个交易复杂得多。除了确认区块头部,确定里面的哈希值是在可以接受的范围内,节点还必须确认区块里的每个交易。最后,一个节点往外传播的区块必须是最长的一条区块链上新加入的区块,当然,“最长的区块链”取决于节点对区块链当前状态的认识。只有这样才可以防止区块链分叉。但就像传播交易时一样,节点同样可以执行它自己的逻辑:它可以选择传递无效的区块,也可以选择传递在共识链上更早加入的区块而不是最新加入的区块。这样就会造成一个分叉,不过这种情况是协议可以承受的。