今天分享的这篇论文介绍了基于区块链的分布式应用程序中,链下(用户在DApp中看到的)与链上(区块链上)状态不一致的问题。
背景与简介
基于区块链的DApp(分布式应用程序)存在线上线下同步的问题。由于区块链的交易天然是有较大延迟的,比如最常见的比特币平均每10分钟生成一个区块。此外区块链可能会出现分叉,因此为了确保交易不被反转,通常交易需要被多个区块确认后,才会被认为最终不会被改变。在比特币区块链上,默认交易被6个区块确认(交易所在区块后又生成了5个新的合法区块)后,该交易会被最终确认(不会再被反转)。因此比特币区块链上确认一笔交易大概需要60分钟。类似的,以太坊区块链确认一笔交易大概需要90秒。
如果DApp开发者在开发DApp时对同步问题处理不当,就会给用户造成困扰,甚至给用户带来大的经济损失。实际上,很多DApp开发者都不会完全同步DApp与区块链上的状态。这可能是由于开发者疏忽或该问题不那么重要,也可能是为了平衡DApp的性能。
典型的DApp由链上智能合约与链下的应用程序构成(如下图所示)。
链下部分负责与用户进行交互以及其它一些程序逻辑,链上部分通过区块链上的智能合约自动管理。链下部分通过rpc请求或者远程 API调用来访问区块链。
同步问题
区块链上一般交易的生命周期如下图所示。
各个状态含义如下:
- 已经创建:用户已创建交易,但尚未广播到区块链网络
- 等待收入区块:交易已被广播到区块链网络,进入到交易池中,但尚未被已生成区块包含
- 被区块收入并执行:交易已被某个区块收入,并且此区块已经被广播到了整个区块链网络,但是此状态的交易仍有可能被区块链上出现的分叉反转
- 被反转:交易虽然被某个区块包含了,但是由于分叉的出现,导致交易所在链最终没有能成为主链(而主链上由于某种原因未包含此交易),导致交易被反转
- 被最终确认:交易被认为“永久”存在于区块链上
关于状态转移的一些解释:
- 等待中的交易有可能被丢弃,比如出现了双花问题,导致交易不再有效
- 被反转的交易可能会被丢弃(原因同上),也有可能被再次加入到区块中,从而进入到被区块收入并执行状态
现网检测
论文中,作者们通过Etherscan对以太坊上的交易进行了长达4个月的监测,发现:以太坊上每秒收到的交易数大概为32.5,而最终被区块链确认的仅有约16.4。可以看出大约有一半的交易都由于某些原因未被包含在区块链中。此外他们还发现,区块链的分叉重组大概每11.06分钟发生一次,其中每次大约有16.69笔交易的状态会变为被反转状态。
根据观测可知,开发DApp时,开发人员有必要考虑DApp的同步问题。
同步错误分类
文中提出了两类不同步类型,分别称之为I 类错误与II类错误。
I 类错误
I 类错误如下图所示。
该错误发生于交易已经被广播到区块链网络,但是没有被任何区块包含的情况下。在此情况下,如果DApp将应用的链下状态变为交易已经处理完成,此类错误 (I类)就会出现。我们将处于等待收入状态下的交易状态的不一致性定义为 I类错误。
II类错误
II 类错误如下图所示。
II 类错误发生在交易已经被某个区块包含之后,但是尚未被最终确认的情况下。此时如果DApp将应用的链下状态变为交易已处理完成状态,此类错误就会出现。我们将处于被区块收入并执行状态下的交易状态的不一致性定义为 II类错误。
检测方法
断言
文中使用断言来判断错误是否发生。定义函数$\sigma$为从链上状态到链下状态的映射。那么我们通过以下两个断言来判断是否出错。一旦断言被触发,我们认为错误发生了。
函数$\sigma(tx, status)$表示交易tx 在链上的状态为status状态时,DApp 中显示的状态。即:
断言一
断言一用于判断I类错误。
断言一:对于每笔交易$t$,$\sigma (t, 已创建) \ne \sigma(t, 已完成) \wedge \sigma(t, 待收入区块) \ne \sigma(t, 已完成)$
断言一指出:交易在已创建或者待收入区块状态时 DApp 显示的状态不能与 DApp 中指示交易已完成的状态一样。
断言二
断言二用于判断II类错误。
断言二:对于每笔交易$t$,$\sigma(t, 等待收入区块) = \sigma(t, 被反转)$
断言二指出如果交易被反转,DApp应当将所显示状态修改为与交易等待收入区块状态一致状态显示。
DArcher
本文提出一个测试框架DArcher用于检测状态不一致错误。DArcher工作流如下图所示。
前端浏览器用于通过远程请求触发DApp中的交易事件。状态分析器在交易的链上状态改变时读取交易状态,并同时读取链下状态,最终分析生成报告。
实验分析
数据集
论文选取了11个DApp作为测试对象,这11个DApp均为在github上均获取超过100颗星的智能合约项目。
由于不同的DApp的线下状态的实现、存储方式不一样,所以无法使用统一的方法来获取DApp的链下状态。作者通过人工分析的方式来找到状态对应的存储位置,以供分析器读取。此过程由两个不同的研究人员分别完成以防止出错。
由于测试环境中,区块链是受控的,DApp的链上状态可以直接获取。
所选取的DApp如下表所示。
应用 | 功能 |
---|---|
AgroChain | 农业供应链 |
Augur | 预测市场 |
DemocracyEarth | DAOs管理 |
ETH Hot Wallet | 钱包 |
Ethereum Voting Dapp | 投票 |
Giveth | 慈善捐赠 |
Heiswap | 匿名转账 |
MetaMask | 钱包 |
Multisender | 一对多转账 |
PublicVotes | 投票 |
TodoList Dapp | 代办事项列表 |
实验环境
文中使用Crawljax作为前端测试工具。此外研究者们在以太坊客户端 Geth 的基础上实现了用于实验的可控区块链。在此区块链中,研究者们可以控制交易的生命周期按照设计好的状态进行。为了测试,研究者们将智能合约部署于本地的区块链中,以方便与DApp进行交互。
结果分析
结果那肯定很好啊,没啥好分析的,文中给出了一张表,不过看不出太多有用信息,直接贴在下面了。对比的baseline-i, baseline-ii 感觉没什么对比价值,感兴趣的可参考原论文。
文中测出的一些Bugs(15个)被反馈给了开发者,其中有6个已经被确认,并且有3个已被修复。
存在问题
- 无法确保实验中所用链下状态的准确性,这种不准确性可能由读取的时间间隔(可控变量)引起,也可能由于对DApp分析不够引起
- DApp可能不单依赖单个智能合约来判断状态,所以我们前面的断言本身可能并不正确
- 应用 DArcher 的另外一个问题是:每测试一个DApp都需要手动去适配获取链下状态的方法,十分麻烦
引用
[1] Zhang, Wuqi, et al. "ÐArcher: detecting on-chain-off-chain synchronization bugs in decentralized applications."Proceedings of the 29th ACM Joint Meeting on European Software Engineering Conference and Symposium on the Foundations of Software Engineering. 2021.
更多推荐