空岛飞行
来日再见
写了 2 篇文章
百度开源的区块链项目:XuperChain,一个支持智能合约并行执行的系统
发表于 2019-08-06 10:57:17
大家可能知道百度在ALL IN AI,但实际上百度在区块链领域也发力不小,这篇文章就是关于百度的区块链系统Xuperchain的,我们来看看大公司会给区块链技术带来什么新变化吧。这篇文章介绍了一种自UTXO改进的模式,它通过追踪合约的输出结果来确定变量的改变,从而实现了合约的并行执行,改变了以往合约只能顺次执行的状况。
橙皮书的好朋友王渊命老师(@jolestar)也在自己微博上点评过百度这个项目的一些设计亮点,作为引子,也许能让读者更好了解Xuperchain的设计,这里摘录一下老王原微博的评论:

百度开源了一个区块链项目,xuperchain。今天下了源码看了一下,它的一些设计挺有意思。 

以太坊为了支持在链上执行合约,把 UTXO 改成了 Account 模式。因为区块链执行合约时,会先加载合约的最新状态,然后执行,更新状态,用户发起交易的时候没法知道自己的交易执行后合约的最终状态是什么,很难用 UTXO 模式追踪,所以以太坊用了 Account + Global State Trie 来追踪。

而 xuperchain 设计了一种通过 UTXO 追踪链上合约状态的办法。它的交易有两种 input,一种追踪资产,另外一种 input 追踪合约中 key-value 的变化。比如图一中,counter 合约第一次调用,所以 input 的 refTxid 为空。图二中第二次调用的时候,input 的 key counter 就引用了上一个交易。

这种方式带来的困难是客户端怎么知道合约要变更哪些 key?如何构造交易?所以它提供了一种预执行的方法,客户端先调用接口通过节点预执行一下合约,拿到输入输出,再构造交易,提交给链上。

另外一个问题是交易的冲突,比如同时有两个交易一起调用 increase counter,如果 input 引用的是同一个交易,就发生冲突了。所以它并不是按合约状态整体追踪,而是按 key 追踪,这样可以减少冲突的概率。这个机制其实有点像数据库里的乐观锁。 当然这种设计的好处是把链的状态拆分成 key-value 的版本变化追踪,就可以去除 Global State Trie 的构建以及追踪成本,对性能应该有好处。

另外一个影响是智能合约虚拟机的设计。它的智能合约虚拟机的上下文(context),后面对接一个多版本的 key-value 数据库,合约执行时,通过 GetObject/PutObject 的调用就可以追踪到合约变更了哪些 key ,以及 value 的最新状态,合约实际上变成了验证交易的工具,如果信任区块数据,链上的最终合约状态可以直接通过交易构造出来,而无需重复执行合约。(图三是它的 counter 合约的 go 版本的例子)

它的合约支持 wasm,当前支持了两个语言,一个是 c++,另外一个是 golang。golang 的 wasm 当前还不支持 export 方法给外部调用,只能直接从 main 开始运行,所以它用了一个 driver 模式,main 方法中通过反射来调用具体的方法。当然,golang 的 wasm 文件太大的问题还没解,那个 counter 合约编译出来得 5M 多,但如果是联盟链的场景下,应该也还能接受吧。

感兴趣的也可以看看,当然,现在文档还不是太完备,会有些坑。github.com/xuperchain/xuperunion

以下为翻译原文。

如今,区块链技术不仅被用作加密货币交易,它在更广阔的领域也扮演了重要角色,比如证据保存和商品追踪。但是,现存的区块链表现的很糟糕,不能满足商业需求,因为他们的智能合约只能顺次执行。我们创建了一个全新的,支持智能合约并行执行和验证的区块链系统。

1.介绍

中本聪于2009年发明了比特币[1],世界上第一个成功的大规模区块链应用。2014年,Vitalik Buterin创立了以太坊[2]。与比特币相较,以太坊支持智能合约,允许开发者使用基于区块链的solidity语言开发应用。2015年,linux基金会推出了 Hyperledger[3],允许开发者使用流行的编程语言比如Go语言开发智能合约。百度起初也是基于以太坊开发区块链应用,但是我们发现以太坊并不能满足我们商业上的需求。究其根本,以太坊上的智能合约全部都是顺次执行,顺次验证的。对一个单一节点来说,只有CPU的一个单核被利用起来了。在这篇论文中,我们提出了一种新型的区块链数据模型:XuperModel。基于XuperModel,我们的区块链系统XuperChain能够利用多核计算来执行和验证智能合约。

2.智能合约的性能问题

在以太坊[2]中,矿工首先从交易池中取得一组有序交易,然后在一系列交易中执行智能合约,最后将它们打包进区块。验证节点接收到区块后也需要按之前矿工打包的顺序依次执行交易,保证验证节点与矿工节点最终状态一致。

显然,智能合约的串联执行模式限制了区块链系统性能的提升,因为串联执行模式没有办法充分发挥多核CPU的运算能力。

Hyperledger Fabric[3]提出了一种解决途径,智能合约首先在多个代言节点上预执行用以获得读写集以及代言节点的签名。然后,排序节点将交易排序并打包到链上。这种方法的优势是一部分交易完全能够并行执行,但是它也有一些缺陷:未确认交易的输出并不是立即可见的,而且新交易只有被确认才能可读。这就导致了在合约调用和数据更新之间存在延迟。

3.XuperChain让智能合约并行执行 


3.1架构概览

XuperChain主要是由虚拟机层,数据桥接层和模型层组成。虚拟机层解释合约的字节码,我们现在支持solidity和webassembly。桥接层处理合约代码的系统调用,比如Get,Put,Iterator等。模型层处理事务提交,回滚和数据查询。

整个处理过程是这个样子的。一阶段:首先,客户端触发智能合约的预执行,智能合约的字节码被虚拟机解析并执行,并且像Get,Set这样的系统调用在执行过程中被桥接层截获,桥接层记录下执行过程中的读写集,最后将它们返回客户端。二阶段:用户将读写集与交易组合起来,附上TA的签名,然后将它们提交给模型层。模型层会验证读取集中的变量是否与本地状态匹配,最后将写入集中的变量值更新到状态数据库中。

3.2XuperModel

为了描述读写集,我们需要定义一种叫做XuperModel的新交易模式。这种模式是比特币UTXO模式的升级。在比特币UTXO模式里,每一笔交易的输入都需要参照之前一笔交易的输出来证明资金的来源。相似的,在XuperModel中,每一笔交易读取的数据需要参照上一笔交易写入的数据。在XuperModel中,一笔交易的输入就是智能合约执行中使用的数据,它来自另一笔交易的输出。一笔交易的输出会被记录到交易数据库中,等待被未来交易的智能合约引用。

我们来进一步解释一下:如果存在这样两笔交易,tx1和tx2,tx1将变量a赋值为1,tx2将变量b赋值为2。然后存在一个tx3,tx3能够调用一个智能合约交换两个变量的值,最后输出结果为a=2,b=1。所以tx3的输入将会指向tx1和tx2,因为a,b之前的值是被tx1和tx2指定的。

3.3 XuperModel的智能缓存

为了在运行期间为合约获取读写集,每个合约在预执行时都会被提供一个智能缓存。这个缓存对状态数据库来说是只读的,它还能生成读写集和智能合约预执行的结果。同时,它也能被用作合约验证。这个缓存由四部分组成,一个写入集实例,一个读取集实例,一个状态数据库引用和一个渗透标记(penetration flag)用以确定查询是否可以渗透到数据库中。 

当预执行合约时,渗透标记被设为true,桥接器会根据状态数据库中可被读取的数据生成一个缓存,桥接器将查询的数据存储到缓存中的读取集中。合约也能写入数据,被写入的数据会存放在缓存的写入集中。预执行之后,读写集能够被一同取得然后返回到客户端。

当验证合约时,渗透标志被设为false,验证节点会根据交易的读写集初始化一个新缓存实例。这个节点将会再次执行合约,但是合约只能在准备好的读取集中读取数据。相似的,写入数据只能在缓存实例的写入集中起作用。

我们来进一步解释一下,以一个调用合约为例。Xuperchain用发起一个交易的方式调用合约。当合约预执行时,智能缓存是以三层存储对象的形式被生成的。假设合约调用一个Get方法,获取变量的名字叫parameter,缓存首先会在它的写入集中读取相关数据,如果没有找到,就在读取集中寻找,如果还是没有找到,最后在数据库中寻找并且在读取集中记录下变量的名称和版本。当验证合约时,缓存以双层存储对象的形式生成。假设验证的合约调用一个Get方法,缓存会首先读取写入集中最新的数据,如果没有找到,就在读取集中寻找。

3.4交易冲突处理

像我们之前提到的,智能缓存能够提取智能合约预执行时生成的读写集,这是交易信息的很重要的一部分。在XuperChain中,一个读写集由读取集和写入集组成。读取集是由tuples:{variable,data version}组成,它反映了合同运行时读取的变量状态;写入集是 tuples: {variable name, data value},它代表了合约执行之后状态数据库的改变。

数据版本是tuple: {RefTxid, RefOffset},它记录了上一个修改变量的交易的ID和交易输出的偏移量。交易的ID是该交易所有字段的sha256摘要。在Hyperledger Fabric中数据版本也是一个tuple,但是它的结构是{BlockHeight,TxNumber},所以Fabric不支持未确认交易输出的立即可见。

当一个节点接收到交易后,它首先根据交易附带的读写集创建一个临时的缓存,用它来验证智能合约执行结果是否正确。通过检查后,它会验证读写集中变量的版本是否与本地状态数据库中的记录一致,如果不一致,它会拒绝这笔交易。值得注意的是,XuperChain需要为所有写入集中的变量在读取集中对应地赋予版本数据。如果变量之前没有数值,版本的位置需要留空。此外,如果本地未确认交易的读写集与区块中已确认的交易产生冲突,未确认的交易将会回滚。回滚操作会将写入集中的变量恢复回以前版本的读取集中的值。

3.5智能合约的并行预执行

由于XuperModel上面提到的特性——智能缓存和标记版本的数据,我们能够并行地执行智能合约。桥接层会为每个合约生成一个新的内容,包括一个标准缓存的实例,这个实例只在预执行期间是合法的。在预执行期间的读写操作只会对这个缓存产生影响,所以(智能合约)的预执行都是彼此独立的。因为智能合约的预执行是一个彼此互不影响的过程,所以合约能够被并行执行。

上图解释了合约是如何并行执行的。假设合约1,合约2和合约3是同时被执行的。通过XuperBridge三个缓存实例被初始化。缓存在合约执行期间记录读写集并将其返回给用户。

3.6智能合约的并行验证

当合约预执行时,客户端的用户会从XuperChain节点那里得到读写集。用户可以在本地将带有读写集的完整交易与签名组装起来然后提交给XuperChain。XuperChain节点会验证合约。验证过程如下图所示。

合约验证主要包括一下三步:

步骤一:XuperBridge会初始化一个新的上下文(context),然后根据交易提交的读写集生成上下文中的缓存。如果一个在读取集中特定版本的数据没有在本地状态数据库中找到,这表明数据已经被其他合约优先修改了,缓存的初始化会失败,合约也会失败。

步骤二:节点会再次执行合约以验证写入集是否与交易中的写入集一致。 

步骤三:如果一致,这笔交易会被确认,否则返回失败。

冲突的合约会在步骤一失效。因为每个合约的验证过程是分别发生在各自的缓存中的,不同合约的验证过程是彼此独立的,所以步骤二中合约的验证能够并行。在步骤三中,我们需要再次检查读取集中变量的版本是否合法。

3.7局限

通过上面提到的XuperModel,我们的系统能够让合约并行执行,并且未确认合约的输出也能立即可见。但是,这个模式仍然存在一些局限。首先,在合约执行期间对状态数据库的每一访问都会记录在读取集中,所以如果一个用户在合约调用期间访问了太多数据,会导致读取集过大。更重要的是,该模型对存储的要求很高,需要进一步优化。

4.结论

这篇论文提出了一种能够使智能合约并行执行的新型区块链架构,它将将智能合约的执行分成两个不同的阶段:预执行和验证。它通过一种改进自UTXO[1]模式的新数据模式XuperModel,解决了并行环境中交易的冲突问题。现在,有许多关于如何提升智能合约性能的学术研究。其中一些从底层存储引擎[4]开始,其中一些使用STM技术[5]来并行化合同执行。我们基于读写集的方法更具确定性且易于实现。在业内,Hyperledger Fabric[3]也提出了一种基于读写集的新模式。Fabric模式最主要的一个缺点是数据版本与区块高度关联,所以未确认交易的输出不能立即可用。结论是,我们相信XuperChain引入的架构对探索智能合约的并行执行是有意义的。未来我们将会努力打破这个模式的局限,提升它的性能。 

5.参考文献

[1] Satoshi Nakamoto, Bitcoin: A Peer-to-Peer Electronic Cash System, 2008.

[2] Ethereum White Paper. A Next Generation Smart Contract & Decentralized Application Platform,available:https://github.com/ethereum/wiki/wiki/White-Paper, November 12, 2015. 

[3] Fabric docs. available: https://github.com/hyperledger/fabric/blob/release-1.4/docs/source/whatis.md, 2015. 

[4] S. Wang, T. T. A . Dinh, Q. Lin, Z. Xie, M. Zhang, Q. Cai, G. Chen, B.C. Ooi and P. Ruan: An Efficient Storage Engine for Blockchain and Forkable Applications. PVLDB 11(10): 1137–1150

[5] T. Dickerson, P. Gazzillo, M. Herlihy, and E. Koskinen. Adding concurrency to smart contracts. In PODC, 2017.

原文地址:https://medium.com/@ccnusjy/xuperchain-a-blockchain-system-that-supports-smart-contracts-parallelization-23849be3260


空岛飞行 查看主页
来日再见
写了 2 篇文章

评论

this comment section is using the amazing decentralized database engine - Gun.db

推荐阅读

a16z女合伙人 Vs. 诺奖经济学家(中)--怀疑者对加密币的观点
预言家周报#18:这台计算机就像一个美好的小镇
预言家周报#14:我们想复制一个44年前的俱乐部
浅谈dApp的设计模式
看看预测市场的前世今生,区块链改变了什么?
从一场逝去的社会实验说起:“邪教”是如何建设社群的?