查看原文
其他

sUDT 和 Anyone-Can-Pay 的合约升级啦

sUDT Nervos 中文社区 2023-01-05


最新版本的 sUDT 和 Anyone-Can-Pay (ACP)lock 智能合约已部署至 Nervos CKB 主网,并由 Trail of Bits 完成审计,其完整的审计报告如下:
  • https://github.com/trailofbits/publications/blob/master/reviews/NervosSUDT.pdf




大家可能已经在 Neuron(0.33.2 或更高版本)、比特派钱包(5.0.009 或更高版本)看到了关于 ACP 智能合约要求升级的通知。上一版本 ACP lock 合约中的资产是完全安全的,用户可以在钱包内将其资产迁移到新的 ACP lock 合约中。

对于开发者来说,他们只需要用新的代码哈希[1]来解析 ACP 短地址[2],必要时为用户引入一个方便的入口来迁移他们的资产。


Trail of Bits 的审计合作



自 2020 年 10 月以来,我们对 sUDT[3] 以及 Anyon-Can-Pay[4] lock 智能合约进行了几轮安全审计。Trail of Bits[5] 的安全专家们在智能合约安全审计方面做得非常好,帮助我们发现了运行中存在的几个问题。虽然大多数问题不影响最终的结果,但其中有两个漏洞很突出,我们对此打了补丁,并发布了一个新版本的 Anyone-Can-Pay 智能合约。

在内部,我们已经仔细讨论并解决了审计报告中提及的每一个问题。


基于 Docker 智能合约在构建过程依赖于 PATH 中的 moleculec


这个问题已经在这次提交的 commit[6] 中解决了。幸运的是,这并不影响最终的二进制文件。我们的构建过程中虽然有 checkings[7] 步骤,确保构建二进制文件中的正确性以及唯一性,但这个 commit 仍然有助于我们完善流程,让我们在未来构建更安全的智能合约。


智能合约使用未更新的 ckb-c-stdlib 依赖项


对我们来说,这更像是在 CKB 上智能合约开发的一个设计选择。

目前智能合约都是静态链接的,这意味着一个智能合约必须在自己的二进制文件中打包所有的依赖库,一旦智能合约在主网上发布,它所有的依赖库将被固定,我们没有办法在不更新二进制文件的情况下改变这些库。由于这种设计,每个部署的智能合约将被锁定在一个特定版本的 ckb-c-stdlib 库中,
即使我们在未来增加了新的功能,我们也不能轻易升级到新版本的 ckb-c-stdlib,二进制的稳定性以及可重复的构建,是 CKB 非常重要的基础。

但这并不意味着我们没有意识到这个问题,我们采取的策略是,我们把特定版本的 ckb-c-stdlib 库作为智能合约的一部分,当库中暴露出一些漏洞时,我们会发布一个安全补丁,并同时更新二进制文件。这样,可以确保即使开发者使用的是较旧的库时,他们仍然可以在链上正常操作。

这个问题的另一个潜在解决方案是 Nervos 基金会正在开发的
CKB 动态链接技术,一旦动态链接技术成熟,我们就可以动态链接 CKB-VM 中的依赖库。这样,当发现库中有漏洞时,我们可以只升级特定的库,而链上的二进制文件可以保持不变。


GCC 从 9.2 版本到 10.2 版本对某些 memcmp 用例进行了错误编译


这更像是一个信息说明,大约在 Trail of Bits 做安全审计的同一时间段,我们发现了一个 GCC 的 bug,它可能会影响 CKB 上许多智能合约的 secp256k1[8] 库。因此,我们向 Trail of Bits 的安全专家咨询了这个问题,结果发现,CKB 中使用的 GCC 版本没有受到这个问题的影响,所以我们无需采取进一步的行动。不过,我们还是会对这个问题保持密切关注,以防出现其他问题。


sbrk 的实现没有在失败时设置 errno


这的确是我们代码中的一个问题,因为我们没有像标准的 sbrk 调用那样设置 errno,不过这并不会影响智能合约的使用,因为到目前为止,CKB 上的智能合约都没有使用 mallocs,因此不会发出 sbrk 调用。不过,我们计划很快修复这个问题,并发布一个不包含这个 bug 的 CKB RISC-V 工具链的新版本。


未初始化的变量被读取


这是必须修复的两个漏洞之一,漏洞的修复可见:
  • https://github.com/nervosnetwork/ckb-production-scripts/commit/8cbe3dbe66c14c7aba6208c4833a4bd6048c34ec



未定义 CKB-Only Cells 的行为


这是另一个必须修复的漏洞,漏洞的修复可见:
  • https://github.com/nervosnetwork/ckb-production-scripts/commit/8cbe3dbe66c14c7aba6208c4833a4bd6048c34ec



在 Anyone-Can-Pay 智能合约中的重复逻辑


这是我们在构建智能合约时忽略的一个问题,虽然它本身谈不上是一个漏洞,但我们也把它和前面两个漏洞一起修复了,漏洞的修复可见:
  • https://github.com/nervosnetwork/ckb-production-scripts/commit/8cbe3dbe66c14c7aba6208c4833a4bd6048c34ec



mbedtls 库是在非生产环境下构建的


这个问题被发现是因为在包含 sUDT 和 ACP lock 两个智能合约的仓库里有 RSA 相关的代码。但正如审计报告所指出的,RSA 智能合约当时还在开发中,没有进入生产状态。非常感谢 Trail of Bits 指出了这一点,我们已经在代码中解决了这个问题。这里还想强调的是,RSA 智能合约将有一轮单独的安全审计,只有安全审计通过之后,我们才会建议在生产环境下使用 RSA 智能合约。


nervosnetwork/riscv-newlib 700 个 commits 过期


和上面的 ckb-c-stdlib 库说明相似,这也是由于 CKB 智能合约设计造成的。由于可重复构建的考虑,我们不能在智能合约发布后就简单地升级智能合约中的依赖项。因此在 Nervos,我们正在执行一种不同的做法:我们将以更慢的速度升级 RISC-V 工具链。现在我们提供的 RISC-V 工具链已经过仔细的测试,可以确定其中出现错误或漏洞的可能性很小。

我们确实计划将工具链升级到较新版本的 GCC 以及 newlib 库,但这需要时间以及各方面的仔细测试,另外,当旧版本的工具链出现漏洞时,我们将给工具链打上补丁,并将受影响的智能合约也升级到新版本。


在未来升级智能合约




智能合约的可升级性是非常重要的,我们希望能不影响用户有一个顺滑的升级路径。虽然这一次我们不得不让每个受影响的用户手动升级到较新的版本,但在未来我们将尽量减少这样的麻烦。考虑到这一点,我们计划为 CKB 核心团队部署的智能合约引入可升级功能(Cell Capacity 由 Nervos 基金会提供),智能合约可升级的工作方式如下所示:

  • 当智能合约首次部署在 CKB 上时,将有一个名为 Type ID 的特殊机制,这样每个智能合约都可以获得一个独特的名字。其中存在一个多签锁,被 Cell 用来控制智能合约,而这个多签锁目前由 CKB 核心团队和 Nervos 基金会组成的系统合约升级委员会来维护。多签的设置是 3/5,也就是说只要 5 个中的 3 个提供签名,智能合约就可以升级。
  • 在使用智能合约时,开发者不应直接使用数据哈希,而应利用 Type ID技术。
  • 当一个漏洞被发现时,智能合约包含的 Cell 可以被委员会解锁,并升级至漏洞修复的新版本,而通过 Type ID[9] 引用智能合约的用户,无需任何手动操作,就可以使用新版本,这样一来漏洞就可以得到顺滑处理。
  • 在一段时间后,当委员会足够有把握认为智能合约安全时, 委员会可以通过 Cell 的多签锁升级为全零锁来最终确定智能合约 ,而这之后没有人能够改变它,这个升级过程可以在未来通过社区治理进一步去中心化,通过用治理锁取代多签锁,智能合约包含的 Cell 只能在某些特定治理结果下被解锁。
  • 此外,如果用户不希望锁被委员会或治理自动升级,他仍然可以选择使用代码哈希的 sUDT 和 ACP lock,而不是哈希 Type,它不会受到任何升级的影响,而且没有人可以改变合约,它将继续使用创建 Cell 时指定的代码,而不是升级后的新代码。

我们希望将这两种选择留给用户,从而平衡用户无感漏洞修复「Code is Law」理念之间的冲突,同时实现更顺滑的用户体验和一个去中心化的未来。




Ref:

[1] https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-system-script-list/0024-ckb-system-script-list.md#anyone_can_pay
[2] https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0021-ckb-address-format/0021-ckb-address-format.md#short-payload-format
[3] https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0025-simple-udt/0025-simple-udt.md
[4] https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0026-anyone-can-pay/0026-anyone-can-pay.md
[5] https://www.trailofbits.com/
[6] https://github.com/nervosnetwork/ckb-production-scripts/commit/690f8dd645c5c3e329a1cbda83e1c0879c952907
[7] https://github.com/nervosnetwork/ckb-production-scripts/blob/master/build.rs#L15-L28
[8] https://github.com/bitcoin/bitcoin/issues/20005
[9] https://xuejie.space/2020_02_03_introduction_to_ckb_script_programming_type_id/




更多精彩内容
👇欢迎关注👇


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存