***(王玮)Corda共识机制的深入分析

2017-05-24 Corda共识机制的深入分析 - Corda需要共识机制吗?
作者:王玮,中关村20周年突出贡献奖”获得者,北京微志科技有限公司创始人

2017-01-20 王玮 无链之链:R3 Corda带来的新视角(一):基本概念与模型 | 首发于《程序员》杂志,版权归其所有。
2017-03-15 王玮 Corda需要共识机制吗?(一)
2017-04-03 王玮 Corda需要共识机制吗?(二)
2017-05-24 Corda需要共识机制吗?(三)


摘要

2017-03-15 王玮 Corda需要共识机制吗?(一)

我在上一篇文章《无链之链:Corda带来的新视角》当中,留下了一个最主要的问题(也许是两个):

Corda需要共识机制吗?
如果需要,这个共识机制应该是什么样子的?

这个问题我相信很多人都会关心:

  • 一方面notary这种近乎信任中介的模式,为什么还需要共识机制呢?
  • 另一方面R3又一直宣称Corda也是有共识机制的,这不能不让人产生困惑。

前一段听到R3的企业产品部门负责人Mike Ward简介Corda的时候,受到相关概念的启发,又重新开始考虑这个问题,并且有了一些新的想法。

本文首先详细介绍一下基于notary的交易验证机制,而后解释一下STXO的概念以及其对系统实现的影响,最后再针对Corda到底需不需要共识机制进行分析,并给出笔者建议的一种共识机制实现方式的建议。


1. Notary模式回顾与分析

2017-03-15 王玮 Corda需要共识机制吗?(一)

本节实际上是针对Corda的notary机制进行详细讲解,毕竟“无链之链”这篇综述性的文章,并不能全面描述notary运行机制。考虑到notary是Corda至关重要的特点之一,同时也为了后面进一步讨论共识机制,对notary模式的关键要点和流程进行详细介绍还是有必要的。

Notary的基本运行方式

Corda基于notary进行交易确认的模式,可以简单地这样理解:

一个notary记录了通过他确认的所有交易的输入、输出状态,新来一个交易的时候,只需要对所有(成功的)历史交易的输入项进行一个直接的查询,就能知道新交易的所有输入项中任何一个是否以前被使用过。只要所有输入项都没有被使用过,也就是不会发生双花,整个交易(在输入项这个维度上)就是合法的。

另一方面,Notary机制的要点之一,就是允许系统中存在多个这样的角色,从而能够让相互之间不做交易的人使用不同的notary作为公证人。例如:Alice和Bob做交易,使用notary N1,Carol和Dave做交易,使用notary N2。这样的设计才使得notary这个概念有意义,如果整个Corda网络都必须采用同一个notary的话,几乎就退化成为了一个星形结构(哪怕notary本身是一个大型的分布式网络,逻辑上仍然是一个整体),中心化网络的一切弊病都会回来了,也就没必要发明notary这个“新词“了。

Corda的发明者们提出:通过上面这两个机制,Corda实现了隐私局部化、高性能、高可靠性等关键特性。因此可以说这两点是Corda的notary机制的核心特性,缺一不可。

多个Notary的问题

首先设想一个场景:

Alice从Bob那里获得了10元钱,要通过一个交易把这十元钱的资产转移给Dave的时候,这个交易应该通过哪个notary来确认呢?

如果Corda对于notary确认交易的机制没有其他规定的话,N1、N2都能对这个交易做确认:根据我们前面对notary机制的简单解释,如果这笔资产没有在之前转移给别人,那么N1、N2当然都不可能在自身的数据库中查到使用过的记录,因此都会认为这个10元钱的资产状态是有效的。真的这么简单吗,怎么隐约感觉会有点什么问题呢?

我们来考虑第二个场景:

Alice想要实现“双花”攻击,也就是把这笔资产同时转给Carol、Dave,他会怎么做?此时如果他选择N1来做这两笔交易确认的话,N1作为验证者,无论是采用任何同步、串行等机制,一定会实现根据历史状态查出这个资产已经转移过一次的信息,从而拒绝这两笔交易中还未成功的那个,这是notary模式的应有之义。

因此,对Alice而言,很显然应该选择将这两笔交易分别发送给N1、N2进行确认,期望有可能进行攻击。可以想见,如果系统没有特殊机制应对这种情况,而是任由N1、N2通过简单的历史状态查询方式来对这笔资产的有效性进行验证,由于查不到被使用过的记录,一定都认为它是有效的,结果就发生了“双花”。因此,系统必须设计一套机制来保证这两个交易至少有一个不能成功。

什么样的机制呢?

我们先来看看Corda关于notary进行状态确认的原则

  • 状态必须是基于notary的,也就是每个状态会有一个notary“字段”,表明这个状态当前“基于”哪个notary。
  • 一个合法交易的所有输入必须基于同一个notary。

先来看第一条:由于每个状态都有一个notary属性,因此一个notary是能够判断这个状态是不是“属于”自己的。有了这个信息,上面问题中所说的交易对于N1、N2来说就不是完全等同的,如果我们能够根据这个信息设定一个机制来防止双花,就能解决这个问题了。

很显然,我们只能要求那个发现待验证交易的一个输入项对应的notary不是自己的时候做出反应(在这个例子中是N2),他可以有两个选择:

  • 选择一是验证失败,本质上就是拒绝验证那些包含notary属性不等于自己的状态的交易,因为这笔资产的状态对应的notary一定是N1。
  • 另一选择是他可以在验证这个交易的时候根据该状态的notary属性向“原”notary(也就是N1)来发出请求,针对这个状态进行验证。这两个方案看起来应该都能满足防双花的需求,但稍微想一下就知道,方案二需要引入很复杂的机制才能实现,这个留给读者自行验证。

毫无疑问,Corda选择了前一个方案,就是直接拒绝。

Notary变更

上面的方案解决了一个问题,就是跨notary的“双花”,但是故事并没有结束。

我们考虑第三个场景:

Alice从Bob和Carol那里分别收到10块钱,其中与Bob的交易是N1确认的,与Carol的交易是N2确认的。他要把这20块钱给Dave,需要怎么做呢?

  • 我们先说合理的做法:他应该发起一笔与Dave的交易,以两个10块钱的资产作为输入,形成一个20块钱的输出,这也是UTXO模型的标准做法。但是根据上面的讨论,我们会发现一个问题:这笔交易无论是发给N1确认还是N2确认,都应该会遭到拒绝——这也就是上述关于状态验证的两个原则中的第二条所规定的含义——如果不拒绝,就无法杜绝Alice把其中一个十块钱通过另一个notary进行双花的风险。
  • 当然,我们可以有另一种做法,就是要求Alice创建两个交易,每个交易只有一个输入项,然后分别交给当初生成他们的交易所对应的notary来确认。这样做是没问题的,但是如果系统只允许这一种方案,就意味着Corda系统中的UTXO永远不能“合并”,本质上Corda系统会被notary划分成一个个永远无法互相通讯的子网,每个子网中都有所有那些需要互相交易的参与方。大家可以脑补一下这种景象,notary+UTXO模型的“弊端”被“平方级”放大,应该属于系统设计不良的范畴。

因此,只剩下一种可能性了:

Corda必须提供一个可以把一笔资产/一个状态/一个UTXO在不同notary之间转移的手段。

读过“无链之链”这篇综述文章的读者应该还记得,Corda专门设计了一种交易类型——notary变更交易,用于将一个状态在两个notary之间转移。

同时,Corda也内置了一个“Notary变更流程”的实现——NotaryChangeFlow,这个flow接收两个参数:originalState, newNotary,主要完成以下工作:

  • 创建一个交易(类型显然是notary变更交易),以变更前的状态作为输入,产生一个变更后的新状态作为输出
  • 获得这个状态的所有可能消费者的签名(其实就是这个状态的拥有者,目前我还没看到Corda当中支持一个状态有多个拥有者的设计,严格说这也不符合UTXO模型。不过不排除考虑可撤销的状态算是有两个可能消费者的情况?总之这是笔者的理解)
  • 从状态的原notary那里获取签名
  • 完成该交易并将结果发送给参与方(也就是上面所说的所有可能消费者/拥有者),这样原旧状态的拥有者就拥有新状态了

简单地说,一个状态进行notary变更,就是状态的拥有者通过该状态的当前notary跟自己做了一个交易,这个交易的输出状态与输入状态之间只有一个变化,就是notary从旧的变成了新的。这样做显然有一个好处,就是旧的状态也符合系统的规则

在交易完成之后就无效了,从而至少在旧notary的覆盖范围内防止通过notary变更实现双花。

有了这套机制,我们先回过头来看第二个场景——因为我们要保证这个新机制不能产生新的双花攻击的机会:

Alice想要把一笔(已经转移给Dave的)资产转移给Carol,如果他使用N1来验证:此时N1会因为该资产已经转移而拒绝;如果他使用N2来验证,要么因为notary不同而被拒绝,要么必须首先进行notary变更。而根据notary变更流程,他同样要跟N1做一个交易把资产的notary变成N2,N1仍然能知道这个状态已经在此之前交易过了,所以会拒绝这个变更交易,从而仍然能够防止双花。

现在来看第三个场景:

Alice只要执行过一次notary变更交易,无论是把从Bob那里收到的10块钱变更到N2上,还是把从Carol那里收到的10块钱变更到N1上,就可以在对应的notary上验证这个新构造的、有两个输入和一个输出的交易,从而实现转账。同时,后续无论通过什么方式进行双花攻击,也都能被拒绝,读者可以自行验证。

小结

简单地说,Corda基于notary进行交易确认方式,在系统只有一个notary的情况下,通过对历史交易记录进行查询的方式就可以实现。一旦系统中有多个notary,并且出现“跨”notary的交易活动,防止双花的的职责当然就涉及多个notary之间的“协同”。

Corda结合交易场景,采用了一个比较标准的方式,就是不在交易过程中让多个notary互动,而是在交易之前必须把交易所需要的所有输入状态指定到验证该交易的notary上,避免一个状态可以在两个notary上进行验证的情况,从而实现了防止双花。为此,Corda不仅设置了一种notary变更的交易类型,还内置了变更流程,使得这些功能成为系统框架的一部分。


2. 为什么要共识

Corda需要共识机制吗?(二)

理解了notary的交易确认机制,会不会产生一个感觉:挺完美的嘛——半信任中介方式,加上各种规则的严防死守,感觉把双花攻击都杜绝了啊,还需要共识机制吗?在给出这个问题的答案之前,我们先兜个圈子,介绍一些更基本的概念,不仅对后续讨论Corda的共识机制有帮助,也有利于更深入地理解去中心化数据库的一些关键概念。

只许州官放火,不许百姓点灯

首先我们探讨notary模式下节点间的信任关系:notary是两个交易者之间的第三方,这是与交易者不同的一种角色,因此Corda系统节点间的信任关系相对于比特币的节点间关系要复杂得多,无法做到全都是相互不信任的对等节点那么简单的模型。

注:当然,比特币其实也会有全功能节点和SPV的关系,但性质上跟notary和交易节点的关系还是有本质差别的

我们可以用一张图来表示Corda系统中节点间信任关系的模型(暂时排除了Oracle等其他角色的节点,因为对共识这个主题不产生实质性影响):

***(王玮)Corda共识机制的深入分析_第1张图片

我们逐个看一下不同角色之间的几种信任关系:

  • 黑色连线的“互不信任”,是所有交易系统的固有特征,也是区块链/类区块链系统要解决的问题,这方面Corda与其他类型的系统没有区别
  • 红色连线的“信任”,是基于notary的机制“强加”给我们的,是Corda区别于普通区块链的根本特点。当然, 这种信任也不是无条件的,各种密码学手段、联盟机制也会有所控制。不过,毕竟这成为了Corda模式的前提之一,因此对这种信任关系的讨论超出了本文的范围,只能作为讨论的前提
  • 蓝色连线的“不信任”,则是本文第一部分所讨论并解决的问题,也就是通过notary机制来防止双花,从而使得“互不信任”的交易双方通过notary可以进行交易
  • 最后剩下的就是notary之间的黄色连线,也是一种“互不信任”的关系,也就是是R3一直强调的,notary可以是一些mutually distrusting的节点,这应该也是现实世界的特点。如果系统无法处理这个互不信任的关系,则会导致文章第一部分所说的情况:整个网络被notary划分成若干相互隔绝的子网,Corda这套体系恐怕也就没什么意义了。因此,系统必须有机制能够让这些notary在一起“合作”,相信读者已经能够猜出来:解决这个问题的,就是本文的主题——共识机制。

简单地总结一下:Corda系统中,强制引入了交易者对notary的信任关系,除此之外都是与其他区块链系统类似的,只是因为多了一种角色而更加复杂。听起来有点“只许州官放火,不许百姓点灯”的意味——你必须信任notary,而notary不信任你,并且它们之间也不互相信任。没办法,这种模式的根本特点就是这样,不得不说是所有讨论的一个略显遗憾的前提。不过,从后面共识机制的讨论可以看到,对于一个体系而言,这个模式还是有一定价值的,至少可以防止风险的扩散。

UTXO vs. STXO

本文一开头说到:“听到R3的企业产品部门负责人Mike Ward简介Corda的时候,受到相关概念的启发”,这个相关概念,就是指STXO(Spent Transaction Object)

STXO这个概念并不新鲜,但是Mike Ward说:“Notary就是STXO的database”,这就有些与众不同了。我想大部分人都能感受到,采用交易对象(“TXO”)模型的系统,如比特币、Corda,一般人都只针对UTXO这个概念进行讨论,STXO则基本上是个附属品——经常和UTXO成对出现,但默认不需要解释。STXO DB这个提法,更是鲜见——不仅在其他UTXO模型的区块链系统中没有看到过,在R3 Corda其他相关文档中也从未出现。

很明显,对于“TXO”模型的系统,下面这个等式成立:

TXO = STXO + UTXO
也就是说,TXO是一个全集,STXO和UTXO则互为“补集”。

针对这种关系,有一个很容易推导出的结论:

当你能访问整个TXO集合的时候,用UTXO还是用STXO来判断一个交易对象的状态是等价的——你想知道一个交易对象是否UTXO,可以在UTXO的集合中进行搜索,能搜到则是UTXO,搜不到就不是;反过来也可以在STXO集合中搜索,搜到了就不是UTXO,搜不到就是。

理论上听起来没毛病,实践中我们先看一下比特币是怎么做的:

比特币(0.8版以上)的数据中,有一个chainstate目录,其下放的就是UTXO数据库。这是个levelDB数据库,比特币的全功能节点需要对它进行维护:在确认一个区块时,首先要检索所有交易的输入项,如果发现没有对应的UTXO,应该要拒绝

确认区块的时候,要把所有交易的输入项在这个数据库中删除,并且把输出项插入。由此可见,这是比特币交易确认的过程中非常重要的一步,融合在比特币交易确认的复杂流程中,这个处理的正确性决定了确保数据准确以实现防止双花的能力,是比特币节点的重要功能之一。

比特币的这个实现模式有很合理的原因:

随着交易的不断进行,越来越多的对象被“花掉”,因此:

  • STXO是一个有历史积累的集合,数量只增不减,越积越多。
  • UTXO则有增有减——虽然比特币可以分解,但除非所有交易都是一进多出,否则增减总量相对还是有匹配的,这样可以保证UTXO的增长速度没有那么快。

既然如此,作为交易验证过程中必须查询的数据,显然选择数据量小的那部分是合理的,虽然需要不断增删,付出一定维护一致性的代价,总还是好过每一次查询时间越来越长的问题。总之,这是个系统设计的取舍问题,而非原理上的区别

全局 vs. 局部

那么,对于notary模式的系统而言,是不是应该采用与比特币相同的模式呢,即:

随时记录/更新UTXO的信息,验证交易的时候查询一个对象是否UTXO?

我们先给出答案,也就是上面提到的:

notary是STXO数据库——它是通过保存/查询STXO来实现相关功能的。

在论证这个方案的合理性之前,又要谈谈概念了:

notary的数据是“局部”的,每个notary只掌握经过自己公证的交易,这也是Corda“信息部分可见”特性的根本保障。

所以,严格来说UTXO和STXO这两个概念对于notary而言,存在局部性和全局性双重含义

  • 从局部看,UTXO表示“没有在我这里花过”,而STXO则表示“在我这里花过”;
  • 从全局看,UTXO表示“在整个Corda网络中没有花过”,而STXO则表示“在整个Corda网络中花过”。

这样一对比就很明显了:

  • 在我这里花过,则在整个Corda网络中花过;
  • 没在我这里花过,不代表没在别处花过。

反过来,

  • 要在整个网络中没花过,必须在所有notary那里都没花过;
  • 而在整个网络中花过,只需要在任何一个notary那里花过就可以了。

因此:某种意义上说,STXO的概念是绝对的,无范围限制的,而UTXO的概念是相对的,局部的

从实践的角度,我们首先看单一notary的情况:

  • 对于单个notary而言,他可以保存所有“经过”他公证的交易记录,从而拥有一切他处理过的交易的TXO记录,因此对于一个notary二样,UTXO和STXO仍然是补集关系,采用保存哪一种的方式来实现双花检测,从实现的角度看都是没问题的。也就是说,虽然概念上STXO比UTXO更具有绝对性,但实践上却因为两者都被限定在一个局部,因而用哪一类对象做判定依据仍然是等价的
  • 再看多个notary,并且出现对象notary变更的情况(如果没有notary变更,任何交易对象的状态变化仍然被永久限定在某个notary局部,等同于单notary)。根据前面的介绍,notary变更是交易者将一个对象通过当前notary跟自己做一个交易,形成一个新的UTXO,其notary是新notary;原对象则变成了STXO。

此时,新的UTXO是针对新notary的,对于系统中其他notary而言,没有什么意义——由于UTXO概念的局部性,这个新的UTXO对象在他们那里“既非UTXO,也非STXO”。原对象的STXO是针对原notary的,但是由于STXO的全局性,其实对于整个Corda网络而言,这应该都是一个STXO

讨论到这里,我们可以给出本文最重要的结论:

对于一个基于notary机制的系统而言,当有多个notary可能会关心一个TXO的状态时,STXO是对所有notary都有意义的,UTXO则只对未来会处理到他的notary才有意义

共识

说完了所有这些概念,终于可以讲讲共识了。为了简化讨论,我们只设想一个场景:不管出于什么原因,比如程序bug、网络通讯故障、甚至notary蓄意欺骗等等,一个对象的当前notary对它执行了两次notary变更,分别将其notary属性变更为notary A、notary B,如果系统可以允许这种情况的发生,不就出现了双花吗?

这也印证了上面讨论过的前提——notary之间相互应该是不信任的,对变更notary这件事,由于涉及一个对象可以在其他notary那里进行交易的问题,因此必须有机制保证一个对象变更两次notary的行为受到阻止。唯一的办法显然就是notary变更必须要所有notary节点都达成共识——这也就是Corda系统中需要共识机制的根本原因,相信读者非常容易理解和证明。

那么,从实践角度而言,系统的“notary们”需要针对什么达成共识,又如何达成共识呢?相信真正理解了前面几个概念的读者,已经有个大概的思路了:

由于对象状态的判断要作为全系统notary达成一致的结论,就应该使用全系统一致的概念来进行处理,而根据前面的结论,STXO自然是应该使用的概念。因此,notary作为STXO DB的模式,就自然而然地成为共识机制的解决方案了。具体设计和实现方面的建议,我们就放到下一节再讲。

小结

本节主要是一些概念的深入讨论,首先是信任关系问题:基于notary的系统,信任关系要复杂一些,notary之间互不信任,应该是共识机制存在的大前提。其次,UTXO和STXO在信息全局可见的系统中互为补集,因此实践中使用哪个作为防止双花的依据都是可以的,只需要根据系统设计的优化方案来考虑。

然而,对于notary模式的系统而言,UTXO和STXO在局部和全局的意义是不同的,这将导致无论从概念上还是实践上,使用STXO作为交易确认的依据更具有一致性,不过这一特点只在发生notary变更的情况下才会体现出来。综合上述三点,就可以推导出Corda的共识机制会基于什么样的设计来实现,也就notary作为STXO DB的模式。

此外,作为本节的结束,我顺便提一个有意思的问题供读者思考:

基于TXO模式的系统,共识是针对TXO的状态的(不管是UTXO还是STXO),那基于账户模型的系统,共识机制是针对什么的呢,或者说应该是怎样一个模式呢?


3. 共识机制设计方案

Corda系统应该针对发生notary变更的对象(STXO)达成共识,这是本文第二部分通过理论推导得出的结论,但并没有给出具体的共识方案。在这里,我们首先从实践的角度把这个共识机制的合理性再论述一次,也就自然而然地推导出共识机制的具体实现模式了。

为什么无法针对UTXO达成共识

我们首先来看基于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的共识

针对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”,那么各个节点就通过这个共识拒绝了这个交易,他们自身不需要做额外的动作,而发布变更消息的节点,也不应该为这个交易提供确认。

上述共识机制可以用下图表示:

***(王玮)Corda共识机制的深入分析_第2张图片

若干要点

至此,我们就讲完了针对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变更流程中设计更多的环节以确保防止双花攻击,但是这与共识机制的处理流程是无关的。

最后,笔者要进行一个“剧透”——本系列文章还有第四部分,在第四部分我们要对共识机制的具体技术实现给出描述,并且还要给出一个令人“惊讶”的事实和相应的解释,敬请期待。

你可能感兴趣的:(***(王玮)Corda共识机制的深入分析)