王玮(玮哥)
渡鸦区块链专栏作者
点击回顾
Corda需要共识机制吗?(一)
Corda需要共识机制吗?(二)
Corda系统应该针对发生notary变更的对象(STXO)达成共识,这是本文第二部分通过理论推导得出的结论,但并没有给出具体的共识方案。在这里,我们首先从实践的角度把这个共识机制的合理性再论述一次,也就自然而然地推导出共识机制的具体实现模式了。
我们首先来看基于UTXO的共识模式(其实这个名字不精确,严格意义上说应该叫交易阶段共识,后面我们会详细讨论到),也就是典型的区块链系统的共识模式:当你要使用或花掉一个UTXO的时候,各个节点要确认这个UTXO没有被花过,因此要查询UTXO数据库,找到这个对象,才能确认交易。验证节点都同意交易成立,交易(或者交易所属的区块)就被记录在链上,成为了“事实”。
很显然,UTXO共识模式对基于notary的、非广播式的系统是不适用的:以Corda为例,一个状态如果没有在若干notary之间发生转移,那么其当前notary就可以确认他是否以前被使用过,不需要其他notary的参与。
另一方面,由于系统的交易是不广播的,系统中的其他notary对这个对象的存在一无所知,也就是文章第二部分提到过的的:对系统中其他notary而言,这个对象既不是UTXO,也不是STXO,所以其他notary也无法参与这个交易过程。
反过来,对于发生过notary变更的对象,基于UTXO的共识模式也有问题:要实现基于UTXO的交易合法性检查,意味着要让所有notary知道变更之后的对象在交易发生时仍然是一个UTXO,也就是说让每个notary都把变更后的UTXO记录在案,用于交易发生时的判断依据。
简单来说,这样做确实是可以的,对于防止这个新的UTXO被双花,是有效的,读者可以自行验证。然而,由于广播的是notary变更产生的新UTXO,而那个经过notary变更已经失效的STXO的信息却不被其他notary所知,这样就无法避免文章第二部分所说的,由于各种技术的或者蓄意欺诈的原因,而使得这个对象再次通过变更notary的方式,在其他notary那里生成新的UTXO,从而实现双花——关键点在于,刚刚广播的那个UTXO是上一次notary变更生成的对象,而双花攻击者通过二次notary变更生成的UTXO和上次变更生成的UTXO确实不是同一个对象,所以任何节点都无法通过UTXO的记录判断这个双花。
简单说,无论从有效性还是必要性的角度,针对UTXO达成共识在Corda模式的系统中都是没有意义的。
针对STXO达成共识,也就是说系统中所有的notary都知道某个对象是STXO,后续交易确认时可以作为依据。很显然,对于没有发生过notary变更的对象,他的所有历史信息都在某一个notary那里记录,让系统中的其他notary知道他什么时候变成STXO仍然没意义,因此我们可以只针对发生notary变更的情况来讨论共识的流程:
广播,当一个对象发生notary变更的时候,该对象的当前notary应该把这件事广播通知系统中的所有其他notary,告诉他们“某个对象发生了notary变更,因此他已经变成了STXO,另外会新生成一个UTXO”。其他notary收到这个广播,应该做一系列的处理:
查询,按照交易规则,查询自己的STXO库,看看这个对象是不是在自己这里以前发生过交易,已经是STXO了。注意,我们前面提到过的,在Corda这样的系统中,一个notary对自身STXO数据库的查询结果,只能反映一个对象在当前notary见证过的交易范围内是不是STXO,而在整个系统中是不是STXO,就要靠下面一个动作——“共识”——来完成了。
共识,每个notary能够返回的结果无非三种可能性:查到/没查到/没反馈,看到这里,大家应该会心一笑了,这就是共识机制派上用场的地方:不是所有节点都一定会反馈同一个结果(包括有些节点因为不在线而没有反馈),因此必须要有合适的机制来解决整个系统对“这个对象是不是STXO”最终达成一致的问题,这就是典型的分布式共识场景。
实现共识的技术手段,Corda并没有具体规定,根据官方的说法,Corda并不拒绝采用任何有效的共识机制,听起来有点类似Fabric支持可插拔的共识模型,总之我们应该认为共识可以达成。具体的实现技术,我们将在下一节进行讨论。
确认,如果共识的结论是这个对象目前不是STXO,因此可以交易,则系统中的各个notary就可以接受这个交易,并且将该对象记录到自己的STXO数据库中,使其成为已经交易的状态,从而杜绝这个对象未来可能的双花。而后,发布这个变更消息的notary,也应当根据这个共识的结果,最终确认这个变更交易,产生新的UTXO。这样一来,notary变更交易就正式完成了。反过来,如果共识的结论是“这个对象以前就是STXO”,那么各个节点就通过这个共识拒绝了这个交易,他们自身不需要做额外的动作,而发布变更消息的节点,也不应该为这个交易提供确认。
上述共识机制可以用下图表示:
(点击查看大图更清晰)
至此,我们就讲完了针对notary变更的共识机制的基本流程,下面通过几个问题来讨论/总结一下这个共识机制有什么特点:
总体效率
很明显,本文介绍的共识机制是“notary变更共识”,也就是说凡是不涉及notary变更的交易,仍然是由交易双方通过notary直接确认的,不需要在多个notary之间达成共识。只有这样,考虑到notary变更的概率,Corda系统的性能才能大幅度超越每笔交易都需要共识的区块链模式,这也是“多中心化”存在的意义。
共识保障
既然是共识机制,必然要满足达成共识所需要的各种条件,这一点与其他系统的共识机制是一样的,例如:如果采用PBFT方式,则必须有2f+1个以上的节点是可信的并且在线;如果是采用类似比特币的机制,则要考虑软分叉之后的恢复等。
这里笔者只想强调一点,就是在类似Corda这种系统中,必须使用类似PBFT的“强”共识机制,不能允许“分叉”情况的出现。这是因为系统中没有“区块链”这样的全局数据结构,一旦允许分叉,很难设计有效的机制进行恢复,或者说恢复机制一定会导致系统引入非常复杂的处理流程。当然,这个保障在联盟链的系统中应该是比较容易实现的,现有联盟链也基本上都是采用强共识机制。
恶意notary
抛开细节不说,Corda引入notary这种新角色,在共识机制中还有没有其他影响呢?
我想最基本的就是要看看恶意notary与区块链系统中一般的恶意节点之间有什么差异,例如:notary变更交易根本不发出广播要求达成共识,或者共识过程拒绝了此次变更而notary仍然去完成变更交易。
这种情况是普通区块链系统不会出现的,也就是恶意notary的特殊之处。解决的办法也很简单,只需要在规定notary变更交易,必须有“目标”notary的参与即可。具体参与方式可以有多种,最简单的就是这种交易应该让目标notary也参与验证,这样他就能获得这个交易的全部信息,从而知道输入(STXO)的信息和输出(UTXO)的全部信息。
未来,当新的UTXO到自己这里来交易时,可以查询STXO在全网的状态,看看是否达成了共识,从而实现对恶意notary的防范,并且仍然保持了只有notary变更交易才需要共识的模式。
除了上述要点之外,笔者提个“小问题”:共识过程中,如果有一个notary发现需要共识的对象在他这里被使用过,从而拒绝这个共识,而其他notary由于认定该对象未被使用过而同意,则最后这个对象会被认定为未使用过,根据共识的定义,这个对象“未被使用过”的共识仍然能够达成。可是如果这个对象“真的”在这个反对的notary那里使用过怎么办呢?系统不是出现错误了吗?在notary这种模式下,是不是该有个什么一票否决机制?这些问题,就留给读者去思考吧。
小结
本节给出了基于notary模式的系统的一种特殊的共识机制——notary变更交易的共识,建立在这样一个前提下:notary模式的系统中普通类型的交易既不需要,也不可能通过共识来进行确认。
这种共识机制本身是标准的,也就是说原则可以采用任何一种一致的共识算法,但是从实践的角度看,由于没有区块链模型的数据结构,必须采用类似PBFT的强共识机制才有意义,否则必然要为解决分叉问题涉及大量额外的处理流程。
此外,为了进一步防止恶意notary的攻击,需要在notary变更流程中设计更多的环节以确保防止双花攻击,但是这与共识机制的处理流程是无关的。
最后,笔者要进行一个“剧透”——本系列文章还有第四部分,在第四部分我们要对共识机制的具体技术实现给出描述,并且还要给出一个令人“惊讶”的事实和相应的解释,敬请期待。
作者简介: 王玮
“中关村20周年突出贡献奖”获得者
北京微志科技有限公司创始人
渡鸦区块链专栏作者
在金融IT领域从业近20年,主持过世界上最大的基于开放平台和分布式技术的银行账务系统的设计与开发,曾任国家“核高基”国产化中间件应用示范项目副组长等。目前从事区块链技术在金融等领域应用的研究、开发和推广工作。同时还是中国人民大学信息学院工程硕士企业导师、华夏基石e洞察管理杂志专栏作家。
本文为渡鸦原创专家专栏,转载请联系后台授权。
加入渡鸦
(全职∕实习生):[email protected]