Monoxide是由王嘉平博士与其他研究人员共同设计的公有链方案,并发表了论文《Monoxide: Scale Out Blockchain with Asynchronized Consensus Zones》。我并没有下载到并阅读这篇论文,不过根据王嘉平博士的《Monoxide原理详解:突破区块链不可能三角的极简架构》一文,已不难领悟其设计精要。理解Monoxide之前,可先思考一下区块链系统的分片设计,及分片架构必然会遇见的两个典型问题。
1、什么是分片:由于单一的、整体式的区块链系统,交易处理速度慢、吞吐量低,因此可考虑将单一系统分割成一定程度上独立的N个分片子系统,以提升整个系统的交易处理速度与吞吐量。
2、如何处理跨分片交易:Alice的账户位于A分片,Bob的账户位于B分片,若Alice需给Bob转账,应如何处理?
3、如何确保分片安全性:若采取PoW共识算法,将挖矿算力分散到N个分片,每个分片的算力只占全网算力的1/N,如何应对恶意算力攻击?
Monoxide采用异步共识组方案:将单一的区块链网络及账本分割成N个形式上独立的共识组,每个共识组拥有独立的账本(链)、P2P网络,分组K的区块只在网络K中进行Gossip广播,各个分组的行为与动作是异步执行的,可以认为每个共识组就是一个分片。Monoxide在Nakamoto或GHOST的基础上,只进行了非常简单、而又极其有效的改进,这是目前其他的很多分片方案所不具备的,这些分片方案的设计过于复杂,不够精妙。
为了处理跨分组交易,Monoxide引入了接力交易(或称之为中继交易):分组A的Alice给分组B的Bob转了X个币,则可先在分组A的区块Y中打包这笔交易,并执行Alice(-X)。接着生成接力交易,包含完备的转账信息,比如区块Y的头部信息,及交易Merkle Tree Path,并将接力交易发送到分组B,分组B的矿工最终(虽然会延迟)会验证接力交易的合法性,并记录到分组B的区块中、执行Bob(+X)。通过将1笔交易转换为2笔交易的方式完成跨组交易,Monoxide称之为交易的「最终原子性」。由于收款方共识组的全节点需要验证接力交易的合法性,因此需要持续接收并存储支付方分组的所有区块头部数据。每笔交易最多可跨越2个分组,随着系统生态的繁荣、分组数量的增大,不跨分组的交易占比逐渐趋零,因此由N个分组构成的系统,和不分组的单一系统相比,全账本数据量增长到约2N倍,交易吞吐量与TPS提高到约N/2倍。
为了确保分组安全性,Monoxide引入了连弩挖矿:矿工节点可以利用一次成功的挖矿运算,同时为多个分组生产区块,多个分组共享全网算力,而不是各个分组独自占用一份算力,避免算力分散并确保分组安全和全网安全的等价性。对于矿工来说,执行连弩挖矿,更需要存储所有分组的账本,矿工必须确保自己正在扩展的各个分组账本不与其他分组账本的数据发生冲突、各个分组账本数据必须是互相融洽的(比如跨分组的Alice(-X)和Bob(+X)),然后才能根据Nakamoto或GHOST继续进行扩展。因此Monoxide虽然对账本进行了形式上的分片和隔离,但实际上矿工节点仍需获取所有分组账本,并构造「全账本」,对于专业的矿池来说,这并不是问题。专业的矿池为了提高算力利用率,必然会同时接入所有的共识组P2P网络,同时加入所有共识组执行连弩挖矿。
连弩挖矿的工作原理:在区块链技术中,一般以Merkle Tree的形式组织多笔交易,但实际上Merkle Tree可被用于组织任何数据条目。在连弩挖矿的设计中,矿工M可以同时生产多个分组的区块,并将这些分组的区块头部用Merkle Tree组织起来,结合Root及其他相关参数进行统一的挖矿计算,一旦找到符合任一分组挖矿难度要求的解,就可以立即将「挖矿结果、Merkle Tree路径、分组区块 」广播到该分组的P2P网络,并继续执行挖矿运算,以求取符合其他分组难度要求的解。不同分组的挖矿难度最终会收敛到同等级别,因为在各个分组区块奖励相同的情况下,算力资源必然优加入挖矿难度低的分组中执行挖矿以获取最高收益,这必然会抹平不同分组的挖矿难度差异。因此连弩挖矿有很大的概率“不连弩”,或许只找到一个有效解即可同时满足所有分组的挖矿难度要求。
Monoxide的可选优化项:在Monoxide系统中,矿工节点大概率会加入所有分组的P2P网络中,并存储所有分组的区块数据。而对于不执行挖矿运算、但需要执行数据验证的的分组全节点来说,也必须加入所有分组网络,以获取其他分组的区块头部数据,否则将无法验证接力交易的合法性,这是不太合理的。可以考虑用N+1的分组方案解决这个问题:额外建立1个公共的P2P网络,用于广播所有分组的区块头部数据,任一分组的全节点只需加入2个网络:自身分组网络与这个公共网络,这就极大地简化了原先的N个分组之间的N*(N-1)/2个双边关系。
对Monoxide的几点改进(或改造)思考
1)Monoxide按照账户地址的前k个比特,划分出2^k个分组。而我认为可以有其他的可选分组方案:让用户自主选择一个共识组,用这个共识组的编号作为前缀修饰自己的地址,比如XYZ.abcdefg,XYZ是分组编号,abcdefg是用户通过公钥计算出的通用地址。整个系统可根据发展情况,逐步增加新的共识组,而不用提前规划好一个固定的共识组数量。这样也有利于钱包商部署自己的全节点,由钱包商APPx生成的地址,可以划归到APPx前缀下,比如XYZ.APPx.abcdefg,类似于每个银行账号都有该银行的固定前缀一样。钱包商APPx将自己的用户全部划归到XYZ共识组下,可更方便地部署运维全节点,更好地为用户提供查询与交易广播服务。
2)Monoxide拥有自己的智能合约编程模型Oxidation,但我不太喜欢这个模型。因此我进行了一些脑洞思考:既然Monoxide采用了异步共识组的分片机制,则可将所用智能合约独立编址,划分到专用的一个或多个特殊共识组中,可称其为「图灵共识组」,可更方便地处理用户与用户之间的转账,以及用户与合约之间的交互。普通共识组可以采用UTXO模型,而图灵组可采用Account-Balance(Key-Value)模型。比如下图中的紫色的ACZ8为图灵共识组,专门负责执行智能合约,每一个用户普通账户除了在自己的共识组中有余额,在图灵共识组中可能也会有余额(因为智能合约在执行过程中会给某些相关账户存款,其额度可能非常小)。因此可以让图灵共识组中的对应余额必须积累到一定数额后清零,然后才能生成接力交易,并广播到该账户所属的普通共识组中去,以显著减少图灵组与其他分组的交互次数。图灵组也可能采用PoS、DPoS、PBFT之类的共识,而不采用PoW,并且最好具备状态最终性,而不是概率最终性,这样更有利于设计和实现高效的DAPP。