共识不只是 PoW 或 PoS:先分清谁能参与,再看怎样达成一致

只知道一条链用了工作量证明(PoW)或权益证明(PoS),还不足以知道它怎样达成共识,更不足以判断它是否适合一个应用。
我在 2021 年的一串讨论里提出过这个区分:限制一个人靠大量身份获得影响力,和让一群参与者对结果达成一致,是不同的问题。讨论后来延伸到了攻击门槛和所谓的区块链“不可能三角”。这些问题值得放在一起讲,因为它们有同一个陷阱:用一个熟悉的标签,代替对实际机制的理解。
把 PoW、PoS 当作一类链的简称,日常交流并没有什么问题。可是一旦开始比较安全性、解释最终性,或者选择应用的底层系统,就需要把这个简称拆开。Ethereum 自己的开发者文档也明确区分了抗女巫机制与完整共识协议。[1]
一个人开一万个账号,算一万票吗?
假设一个没有准入限制的网络要投票。如果每个账号算一票,我不需要说服其他人,只需要再创建一万个账号。这些账号各有名字,甚至各有一对可以正常签名的密钥,但背后可能仍是同一个控制者。
这就是 Sybil attack(女巫攻击)的基本问题。John Douceur 在 2002 年的论文《The Sybil Attack》中讨论了一个实体表现为多个身份时,分布式系统的冗余与信任假设如何失效。[2]
抗女巫机制限制的,是廉价复制身份带来的影响力。它不一定禁止创建新身份,更不等于证明“每个账号背后都有一个不同的真人”。
在 PoW 中,挖矿影响力与计算工作有关。把同样的算力拆成更多名字,不会凭空得到更多总算力。PoS 把参与权重与按协议投入或质押的资产权重联系起来;单纯把同一份权益换几个名字,也不应凭空放大总权重。具体怎么选择提议者、怎么计算投票,以及违规时怎么处理,还要继续看那条链的协议。[1]
这也解释了为什么 DID 不能自动解决女巫攻击。签名能帮助验证某个操作是否由对应密钥授权;它没有自动证明这个控制者只拥有一个身份。如果应用需要“一人一次”的投票,还需要额外的资格与唯一性规则。DID 是什么和“谁能获得多少投票权”,是相连但不同的知识点。
现在,即使我们已经解决了参与权重的问题,还有一个麻烦:两个各自满足其他要求、却花费了同一份资金的交易,先接受哪一个?有些参与者先看到了交易甲,另一些先看到了交易乙。告诉他们谁有资格投票,还没有告诉他们怎样结束这场分歧。
有资格说话之后,还要有决定规则
可以用几项具体问题拆开一套链协议。这个拆法用于理解职责,不表示实现一定有几层可以任意替换的插件。
| 要解决的问题 | 需要看的规则 |
|---|---|
| 什么更新可以接受? | 签名、余额或尚未花费的交易输出、执行结果等有效性检查 |
| 谁能参与,影响力怎么算? | 准入、抗女巫与权重规则 |
| 谁提出下一次更新? | 提议者选择及其时间安排 |
| 看到了不同的历史怎么办? | 分支选择或相应的投票协议 |
| 什么时候可以依赖结果? | 确认与最终性条件,以及网络和故障假设 |
Bitcoin 是一个很好的例子。“最长链获胜”是常见的解释,但更准确的说法是:节点在符合自身验证规则的候选链中,选择累计工作量最大的链。这里的“最长”不能简单理解为区块个数最多,更不能理解为只要工作量足够大,无效交易也会被接受。[3]
PoW 在这里承担的作用也不止一项。它使出块机会与算力相关,并让节点能够比较候选历史所累积的工作量。所以把 PoW 说成“只负责随机选一个人”,仍然省略了关键部分。这个抽签也不是按账号数量平均抽签。
反过来,分支选择规则本身同样不是完整的共识协议。没有有效性规则,我们甚至不知道哪些链有资格拿来比较;没有相应的网络与算力假设,也不能仅凭选链规则就许诺交易不会回退。[3]
最终性可以理解为:在协议假设成立时,已经确认的结果不会再被另一段冲突历史替换。Bitcoin 所说的确认则通常是在等待更多工作量累积后,降低历史被替换的风险。
Ethereum 的例子能进一步说明这个区分。Gasper 把 LMD-GHOST 分支选择与 Casper FFG 最终性机制结合起来:前者帮助确定当前跟随哪个分支,后者让特定检查点(协议选定的区块位置)获得更强的确认保证。名字很长,不需要先背下来;需要记住的是,“使用 PoS”没有替我们回答所有这些问题。[4]
还有一个容易漏掉的区别:出现两个候选分支,不等于已经有两个互相冲突的最终结果。系统可以暂时意见不一致,同时仍按协议保证不把冲突结果都最终确认。应用真正关心的,通常是自己正在依赖哪一级保证。
51% 和 2/3,不能这样比大小
讨论链的安全性时,最容易产生误会的数字大概就是这两个。
Bitcoin 所说的多数算力攻击,讨论的是攻击者对竞争历史的影响。它不等于攻击者拥有了所有人的私钥,也不等于能够让遵守原有验证规则的节点接受任意凭空造出的资金。少数算力也并非绝不可能造成重组,即节点改为接受另一段历史,原先接受的交易可能被撤回;风险与攻击者算力和后续累积的确认有关。[3]
BFT(拜占庭容错)则是一类在参与者可能撒谎、发冲突消息或不响应时仍寻求正确结果的协议。不能只看到“三分之二签名才提交”,就推导出“必须攻破三分之二才会出问题”。
先分清两个目标:安全性(safety)要求正确参与者不最终接受冲突结果;活性(liveness)要求系统在规定条件下仍能继续处理请求。停止确认和确认了错误的冲突历史,是不同故障。
用四个共同维护系统的节点作一个小例子:假设确认需要三票。任意两个三票集合至少重叠两个成员;如果最多只有一个坏成员,交集中就至少有一个诚实成员。协议限制诚实成员为互相冲突的结果提供支持,才能帮助排除冲突确认。这里“三票才能确认”不表示可以容忍三个坏成员。达到协议确认要求的一组参与者叫作法定集合(quorum)。这个例子解释的是集合交集,不能代替 实用拜占庭容错协议(PBFT)的完整消息流程证明。[5]
经典 PBFT 把这个关系推广为 n = 3f + 1:用这么多个副本(共同维护服务的节点),容忍最多 f 个拜占庭故障,相应法定集合为 2f + 1。它的活性还要求网络最终能让消息及时送达,不能在消息永远被阻断时仍保证进展。[5]
在权益加权协议中,还要把“几个节点”换成“多少投票权”。一万个验证者名称,不一定意味着一万个独立控制者。
以 Ethereum 的 Gasper 为例,阻止最终化和制造冲突最终结果,要分别分析。在验证者集合和投票权重固定的模型下,两个冲突结果都获得所需的确认,会暴露至少三分之一投票权违反可罚没规则,即质押资产可因此被扣除。这也不表示持有三分之一就能在任何网络条件下完成这种攻击。[6]
真实协议还处理权重随时间变化的情况。例如长期分裂时,inactivity leak 会逐渐降低各分支眼中未参与投票者的权重;Ethereum 文档讨论了由此让两支最终化、需要社会协调恢复的情形。因此,固定权重下的交集推理不能不加条件地推广到任意长度的网络分区。[7]
因此,比较前最好把句子补全:攻击者控制的是算力、投票权益,还是准入成员?我们讨论的是阻止进展、重组未最终确认的历史,还是违反最终性?网络允许多长的延迟,系统如何恢复?
如果这些条件不同,66.67% > 51% 并不能证明某个系统更安全。对应用而言,哪一种故障会发生、发生后能看到什么证据、恢复需要谁参与,往往比一个孤立的百分比更有用。
“不可能三角”也需要写出前提
同样的习惯适用于去中心化、安全性和可扩展性。
CAP 是针对明确模型的结果。网络分区,是部分节点彼此无法通信;这里的一致性要求读写表现得像操作同一份有先后顺序的数据,而可用性要求非故障节点收到的请求最终得到响应。Gilbert 和 Lynch 的论文讨论的是网络分区条件下,原子一致性与特定可用性要求不能同时保证。这里的术语有严格定义;它不是“任何系统的三个好处只能选两个”的通用模板。[8]
区块链“不可能三角”的三个词,和 CAP 的三个条件不是一回事。即便大家使用同一个词,“去中心化”也可能在指独立运营者的数量、普通人验证系统的成本,或决策权的分布。换了定义,再拿同一个三角形比较,就很容易把条件换掉了。
分片的直观思路是把工作分摊到不同部分,而不让每个节点重复处理全部工作。Vitalik 在 2021 年讨论分片的文章中,把这个三难困境限定在使用简单技术的情形,并解释分片如何尝试改变限制,同时说明新增的成本和假设。这个例子不是在说分片没有代价,而是在提醒我们:架构本身会改变设计空间。[9]
这也不能反过来推出“没有任何理论限制”,或者“某条新链已经解决所有问题”。针对明确模型,研究者可以提出下界和不可能性结果;新的方案也需要说明自己保留了哪些假设、改变了哪些约束。一个工程上的概括,和一个适用范围清楚的定理,应该分别阅读。
对 ArcBlock 来说,这样的区分有很实际的意义。我们从应用出发组织系统,而应用需要理解的远不止底层链采用哪个缩写。比如身份与权限由什么证明、一次交易什么时候可依赖、跨链操作在哪一侧最终结算,都需要分别回答。ArcBlock 的链与应用和 DID 与区块链可以接着读,但这些设计选择本身并不是“普遍比另一条链更安全”的证明。
“更早”或“更新”也是标签。一个协议较早出现并获得广泛采用,也不能单独证明每个技术选择都是最优;一个设计比较新,同样不能单独证明它更适用。把问题拆到这一层,才有可能认真讨论不同链的区别,而不是让读者在 PoW、PoS、BFT 几个标签之间选阵营。
读一条链的介绍时,不妨多追问一句:它告诉我的,是谁能参与,还是大家怎样决定同一段历史?如果只回答了前一半,共识这件事还没有讲完。
参考