Sui CLI 中新增的 — verify-compatibility 标志使得包升级的调试工作变得更加简便。这个新标志在 PR “启用包升级兼容性检查 #20342” 中有详细介绍,它为在应用程序升级过程中可能出现的错误提供了更多的环境信息。在本地仿真中使用此标志运行应用程序,可以帮助你在不消耗 SUI 的情况下捕捉错误并完善代码。
升级简介
Sui 提供了合约升级的功能。在创建一个“包”时,你将获得一个升级能力(cap),允许你对合约进行升级。你可以选择存储这个对象便于以后使用,或者在发布时将合约标记为不可变。一旦你确认包已经稳定,并且不再需要进一步的升级,就可以通过丢弃升级能力(cap)来使包变得不可变。这确保了合约不再发生变化,从而增加了用户的信任。
如果你选择存储你的升级能力(cap),你可以选择以下几种“策略”进行升级,按严格程度从低到高排列:
- 兼容:允许添加新类型和函数,改变非公开接口和函数体,更新依赖。
- 增量:与兼容策略相同,但现有声明将变得不可变。
- 仅依赖:只允许升级依赖项。
关于常量和约束的几项注意事项,可以在 Sui 文档的 Custom Upgrade Policies 部分了解更多关于每种策略类型的规则。
本地验证
大多数开发者希望能够修复他们合约中的问题,因此会选择“兼容”策略。然而,如果你尝试发布一个不兼容的升级,使用 — verify-compatibility 标志时会遇到错误。以下 CLI 示例中显示了这些错误消息。如果不使用该标志,失败的交易将不会提供任何环境信息,这使得调试更加困难。
// removing a struct from a package
error[Compatibility E01001]: missing public declaration
┌─ UpgradeErrors.move:4:18
│
4 │ module upgrades::upgrades {
│ ^^^^^^^ struct 'MyStruct' is missing
│
= Structs are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade.
= Add missing struct 'MyStruct' back to the module 'upgrades'.
更改函数的签名或公共类型的内容将导致错误,错误会指明签名如何被修改以及需要做什么更改才能修复你的包。
注意:结构体必须是公开的,这使得它们实际上是不可变的。
// removing a field from a struct
error[Compatibility E01002]: type mismatch
┌─ UpgradeErrors.move:34:19
│
34 │ public struct MyStruct {
│ ^^^^^^^^^^^ Incorrect number of fields: expected
│ 2, found 1
│
= Structs are part of a module's public interface and cannot be removed or changed during an upgrade.
= Restore the original struct's fields for struct 'MyStruct' including the ordering.
增量策略对于那些希望确保现有功能不发生变化,同时仍然在其包内提供迁移路径的开发者来说非常有用。迁移通常是通过将旧类型替换为使用新发布函数的新类型来实现的。增量策略通过不允许更改现有函数体来增加限制。
error[Compatibility E03001]: function signature mismatch
┌─ UpgradeErrors.move:18:31
│
18 │ fun my_func(): u32 { // changed to u32
│ ^^^ Unexpected return type 'u32', expected 'u64'
│
= Functions cannot be removed or changed during an 'additive' or 'dependency only' upgrade.
= Restore the original function's return type for function 'my_func'.
仅依赖策略是最严格的选择,它仍然允许升级。它适用于那些已经彻底审核过自己包的开发者,只希望更新合约依赖的包。添加任何新类型或功能都将受到限制。
error[Compatibility E01010]: new declaration
┌─ UpgradeErrors.move:4:18
│
4 │ module upgrades::upgrades {
│ ^^^^^^^^ New unexpected enum 'MyEnum'.
│
= Enums cannot be added during a 'dependency only' upgrade.
= Remove the enum 'MyEnum' from its module.
不可变合约仍然是一个很好的选择,尤其是在你有足够时间对包及其依赖项进行全面审核,或计划通过发布新的包来弃用之前的合约。在这种情况下,错误不会受到影响,通常会显示为对象错误。
Could not find upgrade capability at 0x123
这些更改比之前提供的链上错误有了显著的改进。如果不使用 — verify-compatibility 标志,你将体验到旧有的行为,即返回失败交易,但没有关于问题发生位置的任何环境信息。
Error executing transaction '2Ve6boZzub62kK7BYMcGCvu3mtnUtDQExFVAwWea8FxN': PackageUpgradeError { upgrade_error: IncompatibleUpgrade } in command 1
Sui 1.42 版本引入了升级错误标志,我们期待社区在我们推出此功能时提供反馈,以确保其稳定性。目前这是一个可选功能。如果你有任何建议或问题,请通过 Discord 或 GitHub 提交问题联系我们。
关于Sui Network
Sui是基于第一原理重新设计和构建而成的L1公有链,旨在为创作者和开发者提供能够承载Web3中下一个十亿用户的开发平台。Sui上的应用基于Move智能合约语言,并具有水平可扩展性,让开发者能够快速且低成本支持广泛的应用开发。获取更多信息:https://linktr.ee/sui_apac