第 16 章 Sui 对象模型中的 Walrus Blob
Walrus 把大文件留在存储网络里,把可编程状态放在 Sui 上。开发者真正需要掌握的是两层 ID:
blob_id:Walrus 内容标识,用来向 aggregator 读取数据。- Sui 对象 ID:链上对象标识,用来证明某个 Blob 已注册、归属谁、还能保存多久、是否可以被应用引用。
不要把这两者混成一个字段。blob_id 适合做内容寻址,Sui 对象 ID 适合做权限、索引和生命周期管理。
写入后会得到什么
一次正常上传通常包含三个阶段:
- 客户端把原始字节切片、编码,交给 publisher 或 SDK 写入 Walrus。
- Walrus 存储节点返回可用性相关的签名或确认信息。
- Sui 交易注册 Blob 元数据,产生或更新链上对象。
应用层至少要保存下面这些值:
| 字段 | 来源 | 用途 |
|---|---|---|
blob_id | Walrus 写入结果 | 下载、校验、跨系统引用 |
blob_object_id | Sui 交易结果 | Move 合约引用、索引、权限判断 |
network | 配置文件或 CLI profile | 避免把 testnet ID 用到 mainnet |
epoch / end_epoch | 链上 Blob 元数据 | 判断是否仍在存储期内 |
size | 写入请求或链上事件 | 计费、展示、限额 |
object_digest / tx_digest | Sui 交易结果 | 审计和排错 |
生产系统里不要只存 blob_id。如果后续要在 Move 里验证“这个业务对象引用的是一个真实 Walrus Blob”,你还需要链上对象 ID 或由链上事件构建的索引记录。
Blob 是对象,不是普通 URL
HTTP 读取路径看起来像普通下载:
GET https://<aggregator-host>/v1/blobs/<blob_id>
但这个 URL 本身不表达所有权、租期和应用语义。它只说明某个 aggregator 愿意按 blob_id 返回字节。应用里的业务记录应该指向链上对象或自建索引,再把 blob_id 当作读取地址的一部分。
一个常见的业务对象可以这样建模:
Article object
id: 0x...
title: "Walrus 实战"
walrus_blob_object: 0x... # 链上 Blob 对象 ID
walrus_blob_id: "..." # HTTP 读取用
content_hash: 0x... # 可选:业务层哈希
owner: 0x...
如果你的应用允许替换文件,推荐让业务对象保持稳定,把 Walrus 引用字段更新到新 Blob,而不是复用旧 Blob 的含义。Blob 代表一次写入的内容,业务对象代表应用里的实体。
当前网络的包 ID 和系统对象
Walrus 的链上合约和系统对象 ID 会随网络而不同。写 Move、脚本或索引器时必须从当前网络官方配置读取:
- Mainnet:以
mainnet-v1.47.1对应官方配置为准。 - Testnet:以
testnet-v1.47.1对应官方配置为准。 - Devnet:
devnet-v1.48.0是预发布,不要把它的 ID 写进 mainnet/testnet 代码。
不要从教程、截图或旧项目复制包 ID。正确做法是:
walrus --version
walrus info
sui client active-env
sui client object <WALRUS_SYSTEM_OBJECT_ID>
如果你使用 TypeScript SDK,把网络配置集中在一个模块里,不要把包 ID 分散写在页面组件和后端 handler 中。
对象所有权如何影响集成
Sui 对象常见所有权模型会影响 Walrus 集成:
| 所有权 | 适合场景 | 注意事项 |
|---|---|---|
| 地址拥有对象 | 用户上传的文件、个人资料、NFT 附件 | 更新需要用户签名 |
| 共享对象 | 公共索引、应用级注册表 | 并发和 gas 成本更敏感 |
| 不可变对象 | 发布后不再变的元数据 | 适合做审计锚点 |
| 动态字段 | 按 key 管理大量 Blob 引用 | 需要设计分页和清理策略 |
如果业务记录要频繁更新,不要把每个读操作都依赖共享对象交易。读路径应该优先走索引器或缓存,写路径再回到链上结算状态。
最小设计清单
建一个会引用 Walrus 数据的 Sui 应用时,先回答这些问题:
- Blob 写入由谁付费:用户钱包、后端 sponsor,还是应用金库?
- 链上记录保存
blob_id、Blob 对象 ID,还是二者都保存? - 文件过期后业务对象如何表现:隐藏、提示续期,还是允许重新上传?
- 旧 Blob 是否需要保留审计记录?
- 敏感数据是否在上传前加密?
- 索引器落库时是否保存了
network和tx_digest?
最稳妥的默认方案是:链上业务对象保存 Blob 对象 ID、blob_id、大小和业务哈希;后端索引器监听对象变更和事件;读取时通过 aggregator 拉取字节,并用业务哈希或 SDK 校验结果。