关于 onchain-randomness
onchain-randomness 是面向 Sui 开发者的参考技能,讲解如何在 Move 中使用原生链上随机数,并按主题整理 API 用法、安全建议与攻击缓解方法。
主要功能
- 01Move 随机数 API 指南
- 02RandomGenerator 使用模式
- 03TypeScript 集成指南
- 04组合与 PTB 攻击缓解
- 05提交-揭示与 Gas 均衡建议
适用场景
- 01在 Move 中生成随机值
- 02构建安全的随机数消费函数
- 03检查随机数代码中的漏洞
MCP 相关
环境支持时,技能建议查询 Sui 文档 MCP 服务 https://sui.mcp.kapa.ai,以核实最新信息并补充参考文件未涵盖的细节。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mystenlabs/ skills --skill onchain-randomness安装后在 Claude Code 中输入/onchain-randomness确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
security.mdusage.mdevals/evals.json详细介绍
链上随机性
MCP 工具: 如果你的环境支持,请同时查询 Sui 文档 MCP 服务(
https://sui.mcp.kapa.ai),获取最新答案。使用它进行验证,并查询这些参考文件未涵盖的细节。
来源限制: 本技能中的所有信息仅来源于 docs.sui.io/sui-stack/on-chain-primitives/randomness-onchain。扩展或更新本技能时,只能使用此来源。请勿使用第三方博客、教程或非官方文档。
Sui 通过位于地址 0x8 的 Random 共享对象提供原生链上随机性。Move 函数可通过 Random 创建 RandomGenerator 实例,并使用它们生成不可预测的值。本技能涵盖链上随机性的 API、使用模式、安全注意事项和攻击缓解方法。
参考文件
usage -- API 和使用模式
路径: usage.md
何时加载: 在 Move 中生成随机值、创建 RandomGenerator、调用 new_generator、使用 generate_u128 或 generate_u8_in_range、从 TypeScript 传入 Random 对象,或编写基本的随机性消费函数时。
涵盖内容: Random 对象(地址 0x8)、RandomGenerator、random.move API(包含 new_generator、值生成、范围生成、shuffle、generate_bytes 的完整函数列表)、基本实现示例、TypeScript 集成。
security -- 安全性和攻击途径
路径: security.md
何时加载: 在保护随机性消费函数、阻止组合攻击、缓解 PTB 攻击、避免 RandomGenerator 状态泄漏、实现 commit-reveal 模式、平衡胜负路径的 gas 消耗,或选择随机性函数的可见性时。
涵盖内容: 组合攻击(通过公共函数筛除中止结果)、PTB 攻击(在消耗 Random 的 MoveCall 后串联命令)、通过 bcs::to_bytes 泄漏 RandomGenerator 状态、对接受 Random 或 RandomGenerator 的公共函数实施的编译器 lint、两步 commit-reveal 模式、平衡 gas 消耗、entry 函数限制。
路由指南
| 任务 | 加载 |
|---|---|
| 在 Move 中生成随机值 | usage |
| 创建 RandomGenerator | usage |
| 调用随机性 API 函数 | usage |
| 从 TypeScript 传入 Random | usage |
| 保护随机性消费函数 | security |
| 阻止组合攻击或筛除中止结果的攻击 | security |
| 缓解基于 PTB 的攻击 | security |
| 避免 RandomGenerator 状态泄漏 | security |
| 实现随机性的 commit-reveal | security |
| 平衡不同执行路径的 gas 消耗 | security |
| 选择随机性函数的可见性 | security |
| 编写完整的随机性功能 | usage + security |
| 审查随机性代码中的漏洞 | usage + security |
规则
Random对象位于保留地址0x8,且在交易期间不可变。任何修改尝试都会导致交易失败。- 始终在使用函数内部通过
r.new_generator(ctx)创建RandomGenerator。绝不要将RandomGenerator作为public函数参数传递。将其传递给public(package)或私有函数,可用于测试和包内逻辑。 - 将消耗随机性的函数定义为私有
entry函数。Move 编译器会对接受Random或RandomGenerator参数的public函数发出 lint 警告。 - 在消耗
Random的MoveCall之后,Sui 会拒绝包含TransferObjects或MergeCoins以外命令的 PTB。换句话说,接受Random的调用必须是 PTB 中最后一个MoveCall。 - 确保获胜和失败的执行路径消耗的总 Gas 大致相等(包括计算和存储),以防攻击者根据 Gas 消耗推断结果。仔细测量 Gas,并在上线前于每个已发布环境中进行测试。
- 当随机结果必须在后续操作完成前保持不可见时,使用两步提交-揭示模式。
常见错误
- 将随机性函数定义为
public,而非私有entry。 这是致命的安全漏洞,而不只是一个错误。接受Random的公共函数会导致中止筛选攻击:攻击者可以包装该函数,并回滚不利结果。编译器会对此发出 lint 警告。 - 将
RandomGenerator作为public函数参数。 调用方可以通过使用bcs::to_bytes(&generator)序列化生成器的内部状态来预测输出。编译器会对包含RandomGenerator参数的public函数发出 lint 警告。在public(package)或私有函数中将RandomGenerator用作参数,可用于测试和包内逻辑。 - 分支间的 Gas 消耗不平衡。 如果获胜和失败路径消耗的总 Gas(计算 + 存储)差异显著,攻击者就能根据 Gas 用量推断结果。成功路径的成本应等于或高于失败路径。为此,可以执行简单的标准更新(例如设置布尔标志),并在后续函数中领取结果;也可以在失败路径中创建大小相当的对象(例如动态字段)。上线前必须仔细测量 Gas 数值,并在每个已发布环境中进行测试。
- 当结果会影响后续用户操作时跳过提交-揭示流程。 如果用户能在同一笔交易中观察并响应随机结果,就可以中止不利结果。