新年伊始,CSDN 以“让区块链回归技术和应用的本质”为宗旨撰写《区块链开发者报告》包含技术扫描、公链选择指南,以及公链与应用开发实战 3 个部分。
其中公链与应用开发实战部分,Qtum 量子链中国区技术负责人——钟文斌,撰写了《公链设计与开发实践和开发细节》部分,讲述了 Qtum 量子链基本特性、设计初衷,以及在Qtum量子链项目中所运用技术的详细介绍,本文为上篇,包含以下部分:
背景介绍
Qtum 量子链的基本特性
账户抽象层 ― UTXO 和比特币脚本如何支持智能合约?
PoS 共识机制
公链设计与开发细节揭秘
作者:钟文斌
2018 年被称为“公链元年”,各种形形色色的公链如雨后春笋,一时间几乎所有项目都在开发各种各具特色的公链。Qtum 量子链作为国内最早的一批公链之一,在 2017 年 9 月上线了其主干网络,其全球全节点数仅次于以太坊和比特币,成为全球第三大去中心化区块链网络。
Qtum 兼容比特币和以太坊这两大生态,可以说集合了主流公链开发的所有技术,并且在此基础上提出并实现了多项技术创新。本文以 Qtum 为例,介绍了公链设计和开发需要注意的诸多细节,供所有公链开发者参考。
Qtum 是首个建立在 UTXO 模型之上,采用 PoS 共识机制和去中心化治理模式,且兼容多虚拟机的智能合约平台和价值传输网络。
为了读者有直观理解,先罗列 Qtum 区块链网络的的基本特性和参数 :
底层模型 :UTXO(Unspent Transaction Output)
区块大小 :2 MB
平均区块间隔 :144 秒
共识机制 :PoS(Proof-of-Stake,权益证明机制)
链上理论最大 TPS : 70~100 笔交易 / 秒
初始发行量 :100,000,000 QTUM
当前挖矿奖励 :4 QTUM,每四年减半
挖矿奖励总额 :约 7,884,000 QTUM(作为区块生产者奖励)
基础代码框架 :比特币 Bitcoin core
支持智能合约,支持 EVM,x86VM 等多虚拟机
支持去中心化链上治理机制
这些特性和参数的确定并非一时兴起,而是 Qtum 创始团队在综合考虑公链生态的现状、应用场景、技术可行性以及未来发展方向等因素之后确定的。在正式开始介绍各部分设计前,不妨先回顾一下 Qtum 设计初衷,有助于理解后续的许多实现细节。
Qtum 量子链的想法诞生于 2016 年,当时的比特币网络已经稳定运行了近 8 年,期间比特币账本从未出过一笔错账,足以看出比特币 UTXO,PoW 等设计的优越性。当时大部分项目都是对比特币的简单修改,本质上还是中本聪最初设计的雏形。然而比特币的美中不足之处在于其非图灵完备的脚本,无法支持真正意义上的智能合约。
Qtum 创始团队最初始的想法很简单 :让比特币支持智能合约。
然而,为什么团队创造了一条新的公链,并且具有如此多与比特币完全不同的特性呢?主要出于以下几点考虑 :
1. 出于安全性、稳定性、匿名性和可扩展性等方面考虑,选择 UTXO 模型,而不是账户模型 ;
2. 比特币的升级需要 Core 团队和比特币社区的共识,如此重大的升级几乎不可行,因此需要一条新公链 ;
3. 支持智能合约需要虚拟机,EVM 具有良好的生态,首先兼容
4. 不重复造轮子,并保持和比特币及以太坊两大社区的兼容性,复用比特币和以太坊部分代码
5. EVM 有其固有的缺点,因此 Qtum 也在自主研发更具兼容性的 x86 虚拟机
6. 同一条链上支持多种虚拟机,需要设计可扩展的账户抽象层
7. PoW 共识的缺陷,兼顾去中心化,因此采用 PoS 作为共识机制
8. 已有的区块链项目都缺乏有效的链上治理模式,需要设计一套去中心化治理机制。
简而言之,Qtum = UTXO+PoS+ 智能合约 + 多虚拟机兼容 + 去中心化治理,这与开篇提到的 :“Qtum 是首个建立在 UTXO 模型之上,采用 PoS 共识机制和去中心化治理模式,且兼容多虚拟机的智能合约平台和价值传输网络”完全吻合。上述设计涉及到较多技术实现细节,接下来我们详细解释。
01
账户抽象层 : UTXO 和比特币脚本如何支持智能合约?
UTXO v.s. 账户模型UTXO(Unspent Transaction Output,未花费的交易输出)是比特币采用的底层账本模型。而以太坊则采用了账户模型。对于普通人来说,后者相对好理解,就是从一个地址到另一个地址,一笔 ETH 的传输,类似银行账户。
而比特币交易则相对复杂,它是由若干 input和 output 组成的,每个 output 包含特定”锁定脚本”,该脚本规定了该 output 的花费规则,提供符合规则的”解锁脚本“即可花费该 output,作为下一笔交易的 input。而尚未被花费的 output 就是 UTXO。比特币网络上的交易都是由 input 和 output 串联起来的。
UTXO 的优点在于 :
• 安全性:解决双花问题的逻辑和处理方式都及其简单,且支持原生多重签名
• 匿名性:多入多出的交易,钱包可生成任意多个地址,每次生成新的找零地址
• 可扩展性:可并行处理,生成离线交易无需像以太坊一样维护 nonce
• 轻钱包:SPV,支持轻钱包去中心化验证交易的合法性,特别适合移动设备
• 兼容性:兼容诸如闪电网络,跨链原子交换,隐私交易等其他基于 UTXO 的项目所采用的技术
UTXO 虽然有诸多优点,但当时基于 UTXO 模型的各种项目的底层脚本语言都是非图灵完备的,并且与以太坊虚拟机所采用的账户模型无法兼容。
为此 Qtum 开发账户抽象层(Account Abstraction Layer, AAL),实现 UTXO 模型与账户模型的适配。这种分层设计实现了底层账本和上层智能合约的完全解耦,也使 Qtum 后续兼容多种虚拟机(EVM,x86,WASM 等)成为可能。
AAL 要实现的工作其实很简单:UTXO 模型 <-> 账户模型。
由于篇幅有限,本文只对其基本原理和遇到的问题做简要解释,感兴趣的读者可以进一步阅读《深度解析 Qtum 量子链账户抽象层》,文章从代码层面对 AAL 进行了详细剖析 .扩展比特币脚本 ― UTXO 模型 -> 账户模型比特币的 UTXO 模型采用了一套非图灵完备的脚本语言,该脚本自带的操作码并不支持合约交易。Qtum 在比特币脚本的基础上增加了 3 个操作码 :
1. OP_CREATE :创建智能合约
2. OP_CALL :调用智能合约 ( 向合约发送 QTUM)
3. OP_SPEND :花费智能合约中的 QTUM在产生新区块时,除了对交易脚本做常规的检查外,还需要检查是否包含上述的操作码。OP_CREATE 用于向 EVM 传递合约字节码。OP_CALL 将 data、gasPrice、gasLimit、VMversion 等运行智能合约所需的关键参数通过交易脚本发送,最终传递到 EVM 中。OP_SEND 则用于合约执行结果的 UTXO 转换,稍后解释。通过引入上述三个脚本,Qtum 的 UTXO 模型具备了识别和处理智能合约相关交易的能力。
02
从 UTXO 获取的合约如何在 EVM 中运行?
合约的执行会引起状态改变,对于合约的状态,Qtum 沿用了 EVM 的定义,所以能兼容所有的符合 EVM 规范的智能合约。从上述 OP_CREATE 或 OP_CALL 提取出合约交易参数之后,即可构建运行环境。合约的运行过程基本采用了 EVM 的引擎,为使其与 Qtum 区块链进行正常交互,Qtum 完成了以下工作(这里只截取部分),供公链开发者参考 :
1. 针对每个独立交易构建运行环境,最大限度的把不同交易的合约执行过程隔离开,避免合约执行过程中的交叉影响
2. 实现 EVM 的永久存储,当区块成为孤块或断开时,可以实现状态的回滚
3. 实 现 EVM 和 Qtum 区 块 链 间 的 接 口, 使 EVM 能够获取诸如 BLOCKHASH,COINBASE,DIFFICULTY,BLOCKNUMBER,GASLIMIT 等区块基本信息 4. 实现已部署在链上的合约间的相互调用
5. 实现合约地址获取自身余额的功能
6. 为 EVM 生成 debug 信息,方便调试智能合约
7. 重新设定各操作码的 gas 价格,因为 QTUM 和 ETH 的价格差异较大,且 EVM 的 gas模型设计略不合理,因此需要重新优化
8. 支持自毁操作码,使合约可以自毁
9. ……
感兴趣的读者可以阅读《Qtum 设计文档》获取更多设计方面的细节。在解决了上述问题之后,从 Qtum 交易传入的智能合约代码即可在 EVM 中成功运行了。该实现理论上适用于所有基于 UTXO 的项目。运行的结果会引起状态改变,这时需要使用上述的 OP_SPEND 用于花费合约中的余额,上面已经提到,无论是比特币还是 Qtum,都是通过私钥”解锁“ UTXO 脚本来花费 UTXO余额的,而 EVM 的执行涉及不同账户之间的转账,所以需要通过 OP_SPEND 实现这些转账到 UTXO 模型交易的转换,最终转化为 Qtum 标准交易脚本(对比特币交易脚本不熟悉的读者建议阅读《Mastering Bitcoin》)。
03
账户抽象层的安全性
上述的 UTXO 和账户模型的互相转换虽然实现了 Qtum 区块链与 EVM 的交互,但 AAL也引入了一个安全问题。由于合约地址本身也是一个 Qtum 的合法地址,并且底层都是UTXO 模型,这就意味着一个合约可以拥有多个 UTXO。这本身没有问题,但却给攻击者提供了 DoS 攻击的可能性。攻击者可以通过给合约发送多个小额的 UTXO,然后一次性用 OP_SPEND 花费大量 UTXO,从而导致区块大小超过限制,新区块无法被接收,使得网络无法产生新的区块。这是 UTXO 与 智能合约相结合所带来的必然问题。Qtum 的解决方案是在共识层面做优化,规定合约地址只能拥有一个 UTXO。每次合约运行结束时,都会将原来的 UTXO 和新加入的 UTXO 进行合并,从而保证合约地址始终只有一个 UTXO。
Qtum 称之为“Condensing transaction”。为了保证合约状态以及 UTXO 的共识,Qtum 的区块头除了包含与比特币相同的字段外,还需要额外加入 hashStateRoot 以及 hashUTXORoot 两个字段,感兴趣的读者可以阅读Qtum 的源码。账户抽象层带来的好处比特币的 UTXO 模型相较于以太坊的账户模型有诸多优越性,以太坊有一套图灵完备的语言,可以实现比较复杂的智能合约逻辑。两者都有强大的生态作为支撑,并且聚集了区块链行业最优秀的开发者。
Qtum 选择不重复造轮子,而是在比特币和以太坊的基础上开发了账户抽象层 AAL,打通了两个原本分离的生态。这一设计带来的好处包括 :
1. 获得与比特币一致的稳定底层基础设施(UTXO);
2. 兼容比特币后续所有包括性能上和安全性上的升级;(目前已同步升级到 0.16 版本,正在适配 0.17)
3. 兼容现有智能合约生态,以太坊上的智能合约可以零成本迁移 ;(QRC-20,QRC-721等均兼容)
4. 比特币和以太坊的开发者自动成为 Qtum 的开发者 ;
5. 兼容所有基于比特币和以太坊虚拟机的技术,比如闪电网络,雷电网络,plasma,加密隐私,原子交换,分片等等 ;
6. 兼容以太坊上所有智能合约开发工具(当然有些需要做 RPC 的适配,Qtum 已经实现了这样的适配),降低开发者学习成本。
04
小结
Qtum 首创的账户抽象层 AAL 实现了 UTXO 模型到账户模型的适配,从技术层面打通了比特币和以太坊生态,并未后续兼容多种虚拟机(如 x86,WASM)提供了可能,其设计思想和实现细节值得公链开发者参考。
说到共识机制,我们首先从字面上回顾一下什么叫“区块链”,所谓区块实际上是一段时间内交易的集合,每个区块都有一个指向上一区块的哈希指针,从而组成了一条链。所以简单来说区块链就是一个不可篡改的分布式数据库,那为什么需要挖矿呢? 这里以 PoW 挖矿为例。
首先,区块链主要分为 :公有链、私有链和联盟链。它们的核心区别在于记账权,公有链是去中心化的,赋予网络上的每个节点记账的权力,而私有链和联盟链的记账节点为少数几个指定节点。
只有公有链才需要挖矿,其目的在于 :
1. 安全性:依靠区块奖励和手续费激励节点记账,去中心化地维护区块链网络的安全性
2. 随机性:保证选出的记账节点的随机性,否则固定的记账节点很容易被 DoS 攻击,出现单点故障
3. 代币分发 :挖矿也是一个代币分发的过程,从而把币随机地分发出去,而不是只在少数人手中
整个比特币的精髓就在于它的激励机制,但 PoW 共识机制也并非没有问题,比如 :
• 加入网络的门槛较高,当前需要花费很多钱买矿机才能成为比特币的全节点进行挖矿,普通设备几乎没有机会 ;
• 越来越趋性中心化,大部分的挖矿所得被少数几个大矿池占据 ;
• 能源消耗巨大,矿机耗电甚至超过某些小国的耗电量(当然这些电量支撑起这么大的网络并不算多,但我们应该寻找更好的方式替代)。基于这些问题,2012 年时 Sunny King 提出 PoS(Proof-of-Stake,权益证明机制),其原理这里不做赘述,感兴趣的读者可以参考这篇文章。简单来说,只要用户持有该网络的Token,就可以参与记账。另外,代币持有人作为利益相关者也更有动力维护网络的安全。PoS 机制同样也能达到比特币的随机性、安全性和代币分发等功能,而且相比于 PoW 来说显得更加去中心化(前提是代币初始分发足够分散)。中本聪在设计 PoW 共识机制时并 没有想到会有矿机的出现从而使得比特币越来越中心化,而 PoS 的挖矿根本不需要使用矿机,只需要一台普通电脑、树莓派就可以参与。
除此之外还有几种共识机制比如 DPoS(代理权益机制)选出一些代理人来进行记账。pBFT,dBFT 等则是改进后的拜占庭容错机制解决方案。这几个共识机制虽然效率较高,但都比较中心化的,容易导致一些中心化的问题。对于计算节点比较少的网络,甚至一个节点挂掉都有可能导致整个网络瘫痪,但这些在比特币或者 Qtum 上都没有发生过。
Qtum 项目出于去中心化程度和能源消耗方面的考虑,选择采用 PoS 共识机制。
01
关于 PoS 的误解
关于 PoS 共识机制,大多数人的理解还停留在其最原始的版本,即 PoS1.0。实际上 PoS 共识机制已经经历过 3 次大的迭代 :
• PoS1.0 :依赖“币龄”,长期不在线,双花问题等 ;
• PoS2.0 :移除“币龄”,增强安全性 ;
• PoS3.0 :针对“short-range”攻击,采用区块时间和交易时间确认 UTXO 的“年龄”。
“币龄”这个概念其实早就从共识机制中移除,现在的 PoS3.0 系统已经可以解决很多初始版本遇到的安全性问题,甚至在抵抗 51% 攻击上比 PoW 系统更具优势。
02
PoS + 智能合约带来的问题
Qtum 没有直接采用 PoS3.0,不是因为共识机制本身有问题,而是由于 PoS 和智能合约的结合可能带来潜在的攻击可能。攻击者可以通过支付比较昂贵的 gas 发起一系列“垃圾合约”。虽然这将消耗很多的 gas,但由于矿工可以获得交易中的 gas 作为奖励,只要攻击者的合约设计得当,就能保证其他节点无法正常处理该交易,而攻击者则可利用先验知识成为区块的生产者,从而将攻击成本全部收回,实现零成本的 DoS 攻击。
但是为何现有用 PoS 共识机制的区块链项目就不会有这个问题,因为它们大部分只支持非图灵完备的脚本语言,无法支持上述的“垃圾合约”(实际上需要循环操作)。但是在Qtum 上既支持 PoS,又支持智能合约,使上述攻击成为可能。
Qtum 的解决方案是 :通过和其他节点分享收益并将收益延迟化,增加攻击的成本。Qtum 在 PoS3.0 的基础上修改激励返还机制,实现了 MPoS(Mutualized Proof-of-Stake)。
MPoS 的基本原理 :每个区块奖励由 10 个矿工平分,其余奖励延迟 500 区块。即 1/10 区块奖励立刻获得,其余 9/10 奖励在 500 个区块之后连续 9 个块中获得。挖矿奖励 = 区块所得 + 手续费 + 运行智能合约 gas 费用。这个简单改进在不改变 PoS3.0 的核心逻辑的前提下,使攻击者无法预测获得区块奖励的多少,也无法立即获得区块奖励,从而极大提高了发动上述“垃圾合约”攻击的成本(仅存在理论可能性,实际操作中完全无法实现)。
03
PoS 的实现细节
Qtum 的底层代码源于比特币,其采用的是 PoW 共识机制。如何将 PoS 应用到其中,并进一步实现 MPoS 呢?Qtum 团队做了以下实现,供公链开发者参考 ,实现 PoS 区块验证和挖矿功能,具体细节如下 :
• 同时支持 PoW 和 PoS 区块,因为在初始阶段需采用 PoW 生成初始代币,在一定高度后变为纯 PoS
• 每个区块的 stake modifier 都会发生改变
• coinage(币龄)不能改变 PoS 哈希值
• 交易费不会作为共识规则
• 需要最近的 500 个区块用于验证 PoS,这里区块不宜太多,否则数据量太大难以处理
• 没有币龄概念,只需要币达到一定的确认数(如 500 个区块)就可以进行 PoS 挖矿
• 增加 PoS 相关的共识参数:区块签名,区块类型(PoW 还是 PoS),前一个 stake 位置,以及 staking 交易创建时间等
• 区块出 coinbase 交易外(实际上 coinbase 交易已经没有实际作用),还需要增加coinstake 交易,用于生成和分配区块奖励
• 接收区块时要检查区块头,因为处理 PoS 区块时,需要处理重复哈希和孤块问题
• Staker 只需要才成功发现 stake 后才继续处理交易,否则将导致交易被多次处理,特别是对于合约交易,多次处理可能会浪费大量时间,这点与 PoW 区块的交易处理略有不同
• 由于 AAL 引入了智能合约,PoS 区块的交易不仅需要估计交易本身自带的 sigop 的大小,还需要考虑由于智能合约产生的“condensing 交易”所引入的额外交易,否则将导致有可能生成超过区块大小限制的交易,影响系统安全性。
关于 MPoS 的实现细节包括 :
• 发送给 MPoS staker 的区块奖励必须来自于 staking 区块 • stake 交易必须包含至少 10 个输出(outputs),1 个给区块创建者,9 个给 MPoS staker
• stake 交易的第 1 个 10 个 outputs 是共识相关的,必须准确地按照 MPoS staker 挖矿的区块高度正确地排列,且创建者为第一个 output
• stake 交易可以包含额外的 outputs,例如,将一个大的 staking UTXO 分成多个 UTXO,input 也可以包含多个输入,比如讲零散的 UTXO 自动合并成较大的 UTXO。在第 10个 output 后,对于 output 不应该有任何特殊的共识规则,只要交易的 output 值不会41超过输入值 + 区块奖励 + 费用
• 前 500 个 PoS 区块不使用 MPoS,因此区块的创建者获得全部的奖励,不需要使用前面的规则
04
小结
Qtum 是首个采用纯 PoS 共识机制的智能合约平台,并解决了其潜在的安全隐患。公链开发者在采用新的共识规则时应该首要考虑不同的技术组合带来的安全性问题,不能完全照搬照套。