Sui开发者速查表
Sui网络开发人员的最佳实践快速参考。
Move
通用
- 阅读关于包升级的文章并编写友好于升级的代码:
- 包是不可变的,因此有错误的包代码可以永远调用。在对象级别添加保护,而不是在包级别。
- 如果将包
P
升级到P'
,依赖于P
的其他包和客户端将继续使用P
,而不会自动更新为P'
。必须显式更新依赖包和客户端代码以指向P'
。 - 期望被依赖包扩展的包可以通过提供所有版本都符合的标准(不变)接口来避免在每次升级时破坏其扩展。查看Wormhole的消息发送示例,通过Wormhole从桥接发送消息。生成消息以发送的扩展包可以使用任何版本的Wormhole包中的
prepare_message
生成MessageTicket
,而用于发送消息的客户端代码必须将该MessageTicket
传递给包的最新版本中的publish_message
。 - 无法删除
public
函数签名,但可以删除或更改public(friend)
函数签名。除非暴露将永远存在的库函数,否则请自由使用public(friend)
或私有可见性。 - 无法删除
struct
类型,添加新字段(尽管可以添加动态字段)或通过升级添加新的abilities。谨慎引入新类型——它们将永远存在!
- 使用
vector
支持的集合(vector
、VecSet
、VecMap
、PriorityQueue
)时要考虑已知的最大大小≤ 1000项。- 对于允许第三方添加、更大的集合以及未知大小的集合,请使用基于动态字段的集合(
Table
、Bag
、ObjectBag
、ObjectTable
、LinkedTable
)。 - Move对象的最大大小为250KB——任何尝试创建更大的对象都将导致中止的交易。确保你的对象没有一个不断增长的
vector
支持的集合。
- 对于允许第三方添加、更大的集合以及未知大小的集合,请使用基于动态字段的集合(
- 如果你的函数
f
需要来自调用者的(例如)SUI的支付,请使用fun f(payment: Coin<SUI>)
而不是fun f(payment: &mut Coin<SUI>, amount: u64)
。这对于调用者更安全——他们知道自己支付了多少,无需信任f
来提取正确的金额。 - 不要过度优化气体使用。Sui计算成本将四舍五入到最接近的gas bucket,因此只有非常 drastica的变化才会有所不同。特别是,如果你的交易已经在最低成本桶中,它将无法更便宜。
- 遵循Move编码约定以保持一致的风格。
可组合性
- 使用
display
标准自定义对象在钱包、应用程序和资源管理器中的显示方式。 - 避免“自我转账”——在可能的情况下,而不是编写
transfer::transfer(obj, tx_context::sender(ctx))
,从当前函数返回obj
。这允许调用者或可编程交易块使用obj
。
测试
- 使用
sui::test_scenario
来模拟多交易、多发送方的测试场景。 - 使用
sui::test_utils
模块以通过assert_eq
获得更好的测试错误消息,通过print
进行调试打印,通过destroy
进行仅用于测试的销毁。 - 使用
sui move test --coverage
来计算测试的代码覆盖信息,使用sui move coverage source --module <name>
来查看未覆盖的行高亮显示为红色。如果可行,将覆盖率推到100%。
应用
- 为了最佳性能和数据一致性,应用程序应该将写入和读取提交到同一个全节点。在TS SDK中,这意味着应用程序应该使用钱包的
signTransactionBlock
API,然后通过对应用程序的全节点调用execute_transactionBlock
来提交事务,而不是使用钱包的signAndExecuteTransactionBlock
API。这确保读取-写入一致性——来自应用程序的全节点的读取将立即反映事务的写入,而不需要等待检查点。 - 为了更低的延迟,如果应用程序需要知道事务已确认但不立即需要看到事务效果或读取事务写入的对象/事件,请使用
executeTransactionBlock
与"showEffects": false
和"showEvents": false
。 - 应用程序应该为频繁读取的数据实现本地缓存,而不是从全节点过度获取。
- 在可能的情况下,使用可编程交易块来组合现有的链上功能,而不是发布新的智能合约代码。可编程交易块允许大规模批处理和异构组合,将已经很低的燃气费用进一步降低。
- 应用程序应该将燃气预算、燃气价格和币选择留给钱包。这使得钱包更具灵活性,同时确保钱包对事务进行干预以确保其不会失败。
签名
- 永远不要为同时触及相同拥有对象的两个并发事务签名。要么使用独立的拥有对象,要么在发送下一个事务之前等待一个事务结束。违反此规则可能导致客户端equivocation,将牵涉到两个事务中的拥有对象锁定直到当前时期结束。
- 任何
sui client
命令(例如sui client publish
、sui client call
)都可以接受--serialize-output
标志,以输出要签名的Base64事务。 - Sui支持多种用于事务签名的签名方案,包括本地多重签名。
zkLogin
- 尽可能地少调用证明服务。设计你的应用程序流程,以便只有在用户即将执行真实交易时才调用证明服务。
- 注意如何缓存临时私钥。将私钥视为高度敏感数据,例如密码。如果(未过期的)临时私钥及其对应的ZK证明泄漏,则攻击者可以窃取用户资产。