解决DApp开发中的链上链下同步问题

本文分析了去中心化应用(DApp)中链上链下状态同步的问题,重点介绍了由于交易生命周期中可能出现的掉单、回滚等情况导致的同步错误。论文提出了两种类型的链上链下同步Bug,并设计了ÐArcher测试框架来有效检测这些Bug。实验结果表明,许多DApp存在此类同步问题,而ÐArcher能有效帮助开发者发现并解决这些问题,从而避免因状态不一致给用户带来不便。

当使用基于区块链的 DApp 服务时,经常会看到一个屏幕显示交易已完成。看到这个,作者不禁想,“当交易有可能被取消时,这么快就通知用户交易已完成真的没问题吗?如果它被取消了会怎么样?”基于区块链的服务会在交易处理的某个阶段指示交易已完成。如果它被取消,他们如何通知用户?

论文 “ÐArcher: Detecting On-Chain-Off-Chain Synchronization Bugs in Decentralized Applications” 讨论了链上链下同步错误,并定义了两种类型的此类错误。通过实验,它展示了在实际的基于以太坊的 DApp 中发生了多少链上链下同步错误。

简介 & 背景

DApp

随着以太坊的出现,它引入了可编程的智能合约,DApp (Decentralized Application,去中心化应用) 服务应运而生。DApp 是在区块链上运行的应用程序,包括像 DeFi 和 CryptoKitties 这样著名的例子。截至 2021 年 4 月,以太坊上有超过 270 万个 DApp。如图 1 所示,DApp 由链上和链下组件组成。链上部分由智能合约组成,可以在区块链上存储数据和更新状态,而链下部分由与用户和中心化服务交互的前端客户端组成。

区块链最终性

区块链的一个特性是最终性(finality)。最终性意味着一旦交易被执行和处理,就不能被撤销。然而,如果区块链中出现分叉,最长链规则将被用来选择最长的链,导致连接到较短链的区块和交易被取消,从而破坏了最终性。随着时间的推移,随着更多区块的添加,区块被取消或撤销的可能性降低。因此,包含你交易的区块之后连接的区块越多,最终性越高,你就越不需要担心你的交易被取消或撤销。每个区块链都有一个保证最终性所需的特定区块数。在比特币中,这个数字是 6 个区块,每个区块平均需要 10 分钟生成,大约一小时后确保最终性。在以太坊中,这个数字也是 6 个区块,每个区块平均需要 15 秒生成,大约 1 分 30 秒后确保最终性。

方法论

交易生命周期

图 2:以太坊交易生命周期

图 2 表示以太坊交易的生命周期。当用户从链下向区块链发送交易时,创建的交易会被添加到交易池中,并进入 pending(待处理)状态,等待被执行。然后它会被包含在一个区块中并被执行。在当前区块之后生成足够的区块后,它会达到 finalized(最终)状态。理想情况下,交易应该顺利地达到最终状态,但在每个阶段,交易都有可能被丢弃或其执行被取消。

在 pending 状态下,交易可能在两种情况下被丢弃:

  1. 如果用户发送重复交易或提出更高的费用以加快处理速度,则之前的交易可以被忽略和丢弃。
  2. 如果矿工的交易池已满,或者矿工恶意丢弃交易以获取其他利益。

执行阶段的 reversed(已撤销)状态可能由于区块链分叉而发生。如果包含交易的区块被取消,则该区块中的交易会被撤销并返回到交易池,将其状态更改为 reversed,在那里它们等待在新区块中执行。即使在 reversed 状态下,交易也可能像在 pending 状态下一样被丢弃。

该论文报告说,对 Etherscan 进行的为期 4 个月的调查显示,以太坊每秒处理 32.5 笔交易,交易处理速度 (TPS) 为每秒 16.4 笔交易,这意味着超过一半的交易没有立即执行。此外,由于分叉造成的链重组大约每 24.43 个区块(约 11.06 分钟)发生一次。平均每小时有 16.69 笔交易恢复到 reversed 状态,这显示了这些事件的重要性。因此,在开发 DApp 时,必须考虑不确定性交易,以避免链上链下同步错误。

链上链下同步错误

当链上和链下状态不一致时,就会发生链上链下同步错误。考虑到前面描述的交易生命周期,即使交易达到 pending 状态但未包含在区块中,也可能被丢弃。同样,在执行交易后,包含它的区块可能会被取消,导致交易被撤销和丢弃,这显示了它的不确定性。然而,DApp 开发者有时不考虑这种不确定性,导致服务提供不正确的信息。链上链下同步错误可能导致链下服务显示不正确的状态,导致用户请求或执行不正确的操作,浪费费用。

该论文将这些定义为链上链下同步错误,并解释了这些错误的两种类型(Type-1,Type-2)。

Type-1 Bug

图 3:Type-1 Bug

图 3 说明了发生 Type-1 bug 的情况。当交易处于 pending 状态时,如果链下状态发生变化,就会出现 Type-1 bug。如果在交易仍在 pending 状态时,链下状态被更新以反映交易已完成,并且随后矿工没有将交易包含在区块中,则可能发生链上链下同步问题。这被定义为 Type-1 bug。

Type-2 bug

图 4:Type-2

图 4 说明了发生 Type-2 bug 的情况。当交易处于执行状态时,如果链下状态发生变化,就会出现 Type-2 bug。即使交易处于执行状态,并且人们可能认为状态不会改变,但如果发生分叉并且未选择包含该交易的区块,则该交易将被撤销和删除。因此,在执行状态期间更改链下状态可能会导致链上链下同步问题,这被定义为 Type-2 bug。

ÐArcher 测试框架

ÐArcher 测试框架采用了一个测试 oracle,旨在有效地检测 bug。

Test Oracle (测试预言):一种软件测试技术,其中使用预定义的真值来比较和确定测试结果是真还是假。

Type-1 Bug 的测试 Oracle

Assertion 1. For each transaction 𝑡, 𝜎(𝑡, Created) ≠ 𝜎(𝑡, Finalized) implies 𝜎(𝑡, Pending) ≠ 𝜎(𝑡, Finalized).

Type-1 bug 表明,当交易 (t) 被添加到交易池时,DApp 不应过早地更改状态,就好像交易已被执行和最终确定一样。断言 1 指出 𝜎(𝑡, 𝑠) 表示当交易 t 处于状态 s 时 DApp 的链下状态。𝜎(𝑡, Created) ≠ 𝜎(𝑡, Finalized) 意味着当创建交易时状态可以更改,但不应更改为最终状态。同样,𝜎(𝑡, Pending) ≠ 𝜎(𝑡, Finalized) 意味着状态可以在 pending 状态下更改,但不应更改为最终状态。因此,如果当交易处于创建或 pending 状态时,链下状态变为最终状态,则表明存在 Type-1 bug。

Type-2 Bug 的测试 Oracle

Assertion 2. For each transaction 𝑡, 𝜎(𝑡, Pending) = 𝜎(𝑡, Reversed).

Type-2 bug 表明,当交易 (t) 处于执行状态时,可以更改链下状态。但是,如果链被重组并且交易更改为 reversed 状态,则链下状态不会更改,这是一个 bug。断言 2 指出,当交易的状态更改为 reversed 时,它应该与 pending 状态相同。违反断言 2 表明存在 Type-2 bug。

Assertion (断言):开发者假定必须始终为真的逻辑表达式。在代码中实现断言并检测任何违规行为都表明存在 bug 或问题。

实现

ÐArcher 结构

上图显示了 ÐArcher 的工作流程。首先,前端浏览器触发 UI 事件以发送交易,然后在受控区块链中执行这些交易。ÐArcher 根据交易的状态更新检查链下状态并检测 bug。在上图中,受控区块链被实现为按 Created-Pending-Executed-Reversed-Executed-Finalized 的顺序控制交易状态。

评估

该论文进行了实验以回答以下三个问题:

  • RQ1 (Bug 检测能力) ÐArcher 能否有效地检测实际 DApp 中的链上链下同步 bug?
  • RQ2 (我们的 Oracles 的有效性) 论文中提出的 oracles 的效果如何?
  • RQ3 (实用性) ÐArcher 对开发者有用吗?

实验环境

对于实验,该论文从 GitHub 中选择了 11 个 DApp 项目,这些项目具有超过 100 颗星,被实现为 Web 应用程序,并使用可以部署到本地受控区块链的智能合约。选择的 DApp 被部署到本地受控区块链以进行测试,并将 ÐArcher 与 Baseline-1 和 Baseline-2 进行了比较。

实验结果 选择的 DApp 被部署到本地受控区块链以进行实验。ÐArcher 的等待时间设置为 15 秒,即以太坊的平均区块创建时间,并且重复测试 10 次以减轻随机性。

TP : True Positives (真阳性)

FP : False Positives (假阳性)

FN : False Negatives (假阴性)

Pre : Precision (精确率)

Rec : Recall (召回率)

Acc : Accuracy (准确率)

RQ1 (Bug 检测能力)

RQ1 考察了 ÐArcher 检测 bug 的有效性。表 2 显示了 ÐArcher、Baseline-1 和 Baseline-2 的实验结果。在 3,134 笔交易中,ÐArcher 检测到 369 个 Type-1 bug 和 1,862 个 Type-2 bug。有 16 个 Type-1 假阳性 (FP),这意味着它们被检测为 Type-1 bug,但实际上并非 Type-1 bug。此外,ÐArcher 未检测到 52 个 Type-1 和 264 个 Type-2 假阴性 (FN),尽管发生了这些 bug。尽管实验中存在一些测量错误的数据,但 ÐArcher 仍然表现出较高的精确率 (99.3%)、召回率 (87.6%) 和准确率 (89.4%),可以有效地检测 DApp 中的链上链下同步 bug。

RQ2 (我们的 Oracles 的有效性)

RQ2 将研究中设计的两个 oracles 的有效性与两个基线进行了比较。Baseline-1 使用 ContractFuzzer,而 Baseline-2 基于 JavaScript 中的运行时错误检测 bug。表 2 显示 Baseline-1 将 7 笔交易检测为假阳性,表明它无法有效地检测链上链下同步 bug。Baseline-2 检测到 257 笔交易,但其总体精确率、召回率和准确率分别为 56.9%、10.1% 和 20.7%,低于 ÐArcher 的性能。因此,与现有 oracles 相比,本文提出的 oracles 在检测链上链下同步 bug 方面效率更高。

RQ3 (实用性)

RQ3 评估了 ÐArcher 对开发者的实用性。ÐArcher 检测到的 bug 报告已与每个 DApp 开发者共享,导致 15 个 bug 中的 6 个得到确认,3 个得到修复。根据开发者反馈,ÐArcher 被认为对于检测链上链下同步 bug 非常有用。

结论

本文定义了链上链下同步问题,并设计和开发了用于检测链上链下同步 bug 的 oracles 和 ÐArcher 框架。使用开发的框架进行的实验表明,许多 DApp 存在链上链下同步 bug,并且提出的 bug 检测框架和 oracles 能够检测到这些 bug。作者指出,开发 DApp 的开发者通常会花费大量时间测试和验证智能合约,但未能考虑交易生命周期。当链上和链下状态不一致时,忽略交易生命周期可能会导致用户产生意想不到的结果并浪费费用。因此,开发者应考虑交易生命周期更新链下状态,以便向用户提供准确的信息。

目前,许多 DApp 在交易位于交易池中或仅被执行时,会通知用户交易处理已完成,而在交易取消后没有任何操作。由于从链下持续检查链上状态具有挑战性,并且实现最终性可能需要时间,因此等到交易最终确定后再通知用户可能并不总是可行的。但是,我认为至少在交易已被执行时通知用户是必要的,因为包含在区块中的交易很可能会保留在更新的链中,从而降低了完全取消的可能性。在不保证交易最终性的区块链上开发 DApp 的开发者需要考虑何时更新链下状态以及如何在交易取消时通知用户。

  • 原文链接: blog.blockmagnates.com/s...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
blockmagnates
blockmagnates
江湖只有他的大名,没有他的介绍。