IOHK官网博客:针对 Plutus validators基于属性的基本测试

image
原文来自IOHK Victor Cacciari Miraldo, 由卡尔达诺大使陈哲Anson翻译

如何使用“cooked-validators”库编写链下代码并免费获得基于属性的测试

我们最近从 Tweag 的智能合约验证和审计团队负责人 Victor Miraldo 那里听到了关于在去中心化金融 (DeFi) 世界中出于安全原因进行验证的重要性。 Victor 是 Haskell 和形式化方法工程师,致力于通过工具和流程确保去中心化应用程序 (DApps) 的安全性和正确性。在这篇博文中,他概述了编写和部署 DApp 是不够的,以及为什么每个开发人员都应该针对一系列不良行为者彻底测试所有链上代码和 Plutus 脚本。为此,他介绍了一个现成的工具库,用于与 Plutus 验证器脚本进行交互——称为cooked-validators,由 Tweag 开发。这个库帮助实现最内层的链下代码,负责生成和提交交易。通过使用这个库,您可以在交易级别免费获得基于属性的测试。

让我们听听 Victor 对使用他们的软件库的看法。

介绍

交易级测试使我们能够向验证器脚本提交任意交易并评估它们的行为。这个过程不同于使用定义的端点作为合约链下代码的一部分来测试整个智能合约。毕竟,该链下代码旨在与链上代码无缝协作,并将具有自己的内在安全性和安全性检查。此方法适用于正常操作,但在测试设置中,它通常会保护链上验证器脚本免受格式错误甚至恶意输入的影响。因此,对于交易级别的测试,我们希望绕过清理链下代码并锤击链上脚本,就像攻击者手工制作的链下基础设施可能带来的一样。作为与 Web 服务的类比,除了客户端用户界面允许的那些请求之外,您通常希望通过向其发送任意请求来测试您的服务器。

熟验证器库使您能够编写负责生成和提交交易的链下代码,并在交易级别使用相同的代码来执行和测试您的合约。这使得为链上编写测试变得更加容易,这些测试可以检测一些坏事是否会发生。

关于 ‘cooked-validators’ 库

使用cooked-validators 构建你的合约与你已经习惯的使用Contract monad 并没有太大的不同。假设您遵循了拆分合约的教程,直到并包括“定义验证器脚本”部分。最后,你有一个 splitValidator 函数来执行该合约的链上部分。如果您没有按照教程进行操作,则 splitValidator 合约会锁定一定数量的资金,这些资金只能通过在两个先前指定的参与方之间拆分资金来解锁。

现在,要与该合约本身进行交互,我们需要编写链下代码,它会生成必要的交易并将其发送到区块链。我们不会直接在 Contract monad 中执行此操作,而是依赖于cooked-validators 库。 lockFunds 交易可以这样写:
1646021012(1)

这与我们直接在 Contract monad 中编写的 lockFunds 非常相似。不同之处在于这里我们使用了任意的 MonadBlockChain monad。这种技术使我们能够将相同的 lockFunds 用于两个目的:

  1. 生成交易,因为 Contract monad 是 MonadBlockChain 的一个实例,并且
  2. 使用cooked-validators 工具为链上验证者编写测试。

假设我们还定义了 unlockFunds 交易(要使用的代码),以便熟化验证器将与 Contract monad 无缝交互。事实上,我们可以像教程中一样定义端点函数:
1646021055(1)

测试合约
因为我们已经使用熟验证器定义了链下代码的第一层(生成并提交原始交易),所以我们可以使用其测试基础设施来测试链上验证器。是否可以解锁已锁定资金的基本测试可能如下所示:
1646021087(1)

在这里,as 组合器仅在测试代码时起作用,它使我们能够以与许多用户相同的方式与我们的合约进行交互。
函数 unlockPossible1 是一个单元测试,用于检查是否有好事发生。我们可以很容易地测试没有发生不好的事情:
1646021117(1)

我们还可以将这些测试用作基于属性的测试。在这种情况下,正在测试的属性是拆分的两个接收者中的任何一个始终可以解锁:
1646021138(1)

此外,如果我们的一项测试失败,我们将收到导致测试失败的交易的可读摘要。以下是一个更复杂的验证者测试失败的前三笔交易的摘录:
1646021198(1)


显示给开发人员的跟踪包含调试问题所需的所有信息,并尝试以可读的方式呈现信息。
除了基于属性的测试之外,cooked-validators 还提供了根据某些功能修改跟踪中的事务的能力。这可以以许多不同的方式模拟攻击。例如,编写一个测试,例如:
1646021263(1)

这将导致cooked-validators 尝试执行两个测试,这两个测试都应该失败,如下所示:

1.根据doAttack修改lockFunds sd交易,然后提交;然后提交未经修改的 unlockFunds 或
2.提交lockFunds sd;然后根据doAttack修改并提交unlockFunds。

某处组合器的细节可能会有点复杂,因此我们将在此处省略它。有一篇单独的博客文章为感兴趣的人提供了 Tweag 博客上的技术细节。

相关的代码库和结论

尽管 Plutus 已经通过其 ContractModel 类支持一种基于属性的合约端点测试形式,但它不提供交易级测试。在 Tweag,交易级测试对我们来说非常重要。在审计 Plutus 合约时,我们需要能够像攻击者一样行事并修改交易以研究验证者将如何反应。
通过使用熟验证器开发您的链下代码,您将能够测试您的链上代码的许多安全性和正确性属性,这可以大大增加您对代码正确性的信心。这可以在审计期间节省时间和金钱。事实上,Tweag 审计的第一步是使用成熟的验证器编写交易生成代码,然后能够自由地与我们客户的基础设施进行交互。

原文链接:Simple property-based tests for Plutus validators - IOHK Blog