NIP-65:中继列表元数据
NIP-65 定义了 kind 10002 事件,用于公布用户偏好的读写中继。这些元数据帮助其他用户和客户端在分布式中继网络中找到你的内容,实现了"发件箱模型"(outbox model),可以分散负载并提高抗审查能力。
结构
中继列表是一个可替换事件(kind 10002),包含用户想要公布的每个中继的 r 标签。该事件会替换同一公钥之前发布的所有中继列表。
{
"id": "a1b2c3d4e5f6...",
"pubkey": "abcd1234...",
"created_at": 1736726400,
"kind": 10002,
"tags": [
["r", "wss://relay.damus.io", "read"],
["r", "wss://nos.lol"],
["r", "wss://relay.nostr.band", "write"]
],
"content": "",
"sig": "sig1234..."
}
每个 r 标签包含一个中继 WebSocket URL 和一个可选标记,表示用户如何与该中继交互。read 标记表示用户从该中继获取事件,因此其他人应该向该中继发布内容以联系该用户。write 标记表示用户向该中继发布内容,因此其他人应该订阅该中继以查看该用户的内容。省略标记表示同时用于读写。
中继列表事件的 content 字段为空。
发件箱模型
NIP-65 实现了一种去中心化的内容分发模式,称为"发件箱模型"。用户不再都向同一批中心化中继发布和读取内容,而是向各自偏好的中继发布,客户端则动态发现每个用户内容的存放位置。
当 Alice 想要查找 Bob 的帖子时,她的客户端首先从任何拥有该事件的中继获取 Bob 的 kind 10002 事件,然后提取 Bob 标记为 write 的中继,因为那些是他发布内容的地方。她的客户端订阅这些中继以获取 Bob 的事件。当 Alice 想给 Bob 发送私信时,她的客户端则查找他的 read 中继并将消息发布到那里。
遵循发件箱模型的客户端会维持与其关注用户 NIP-65 事件中列出的中继的连接。当发现新账号时,它们会动态连接到新的中继。出现在多个关注用户列表中的中继会被优先选择,因为连接到它们可以服务于用户社交图谱的更多部分。
这种架构提高了抗审查能力,因为没有单一中继需要存储或提供所有人的内容。如果一个中继下线或封禁了某个用户,其内容仍可通过其他列出的中继获取。
重要意义
NIP-65 将中继选择从硬编码的客户端默认值转变为用户发布的路由元数据。这使客户端能够适应每个账号实际的发布和阅读习惯,而不是假设所有人都使用相同的中继集。
这也将复杂性转移到了客户端。要用好发件箱模型,客户端需要中继缓存、重试逻辑以及中继列表缺失或过期时的回退行为。该规范改善了可发现性,但并没有消除对良好中继选择启发式算法的需求。
与中继提示的关系
NIP-65 与其他 NIP 中的中继提示互为补充。当你用 ["p", "pubkey", "wss://hint.relay"] 标记某人时,提示告诉客户端在哪里查找该特定引用。NIP-65 提供了权威的、用户自主控制的偏好中继列表,而提示则是嵌入在单个事件中的快捷方式,用于更快的发现。
对于私信,NIP-65 并非全部。公共内容路由使用 kind 10002,但现代私信技术栈通常依赖独立的收件箱元数据,例如 NIP-17 中继列表,这样用户可以将私信路由与公共发布中继分开。
最佳实践
保持中继列表的更新,因为指向已失效中继的过期条目会让你更难被发现。至少包含两到三个中继以实现冗余,这样即使一个中继下线,你的内容仍可通过其他中继访问。
避免列出过多中继。当你列出十到十五个中继时,每个想要获取你内容的客户端都必须连接所有这些中继,这会降低其使用体验并增加整个网络的负载。精心选择三到五个中继的列表比一个给每个关注你的人带来负担的冗长列表更好。
将通用中继与你使用的专用中继混合搭配。例如,你可以列出一个流行的通用中继如 wss://relay.damus.io,一个专注于你所在地理区域的中继,以及一个你参与的特定社区的中继。
主要来源:
提及于:
另请参阅: