尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
TerminusDID 合约发布历史全解:从核心架构落地到 EIP-712 签名修复的版本演进
云原生后端运维【免费下载链接】TerminusOpen-Source Personal Cloud OS for Always-On Agents项目地址https://gitcode.com/gh_mirrors/terminus2/Terminus点击查看免费下载TerminusDID 是 Olares ID 体系中的链上身份注册合约以 ERC-721 NFT 形式承载去中心化标识符DID并通过标签Tag系统扩展节点元数据。本文以官方发布历史release-history.md为主线逐版本拆解 V2.0.0 到 V2.3.1 的能力演进——从核心架构、无定义标签系统、带类型定义的标签系统到合约结构优化与 EIP-712 签名恢复 Bug 修复并结合同目录下的设计文档与合约接口文档给出可验证的源码级细节。读完本文你将掌握 TerminusDID 各版本间的功能差异、标签系统的完整设计类型、作用域、Tagger、elemPath 寻址以及合约在安全性与 Gas 优化上的取舍逻辑。版本时间线与核心演进脉络官方发布历史以简洁的 Changelog 形式记录了 TerminusDID 合约模块的五个里程碑版本覆盖两条主线标签系统的能力演进V2.1.0 → V2.2.0与合约工程的健壮性优化V2.3.0 → V2.3.1版本主题核心变化V2.0.0DID 模块核心架构在 Terminus DID 中实现 DID 管理模块的核心架构V2.1.0无定义的标签系统引入标签Tag系统但标签尚无类型定义V2.2.0带类型定义的标签系统标签系统升级支持 ABI 类型定义与复杂结构V2.3.0合约结构优化优化合约结构减小核心合约体积V2.3.1签名安全修复EIP-712 签名恢复失败时 Revert而非使用零地址继续执行其中 V2.1.0 与 V2.2.0 之间的定义差异正是理解 TerminusDID 数据模型的关键V2.1.0 只允许给 DID 挂载一个无名无型的标签V2.2.0 之后标签必须先在某个 TName 下定义含名称、ABI 类型、结构体字段名才能被写入值。下面按版本逐一展开。V2.0.0DID 模块核心架构落地V2.0.0 完成了 TerminusDID 合约的核心骨架即DID 管理部分。根据 DID 设计文档该架构由以下几个关键设计构成。DID 即 ERC-721 NFT每个 DID 同时是一个遵循ERC-721标准的 NFT其唯一标识符id由名称的 Keccak-256 哈希计算得到function tokenId(string memory domain) internal pure returns (uint256) { return uint256(keccak256(bytes(domain))); }这意味着注册成功后合约会铸造一枚 NFT 并返回tokenId且该 NFT 天然支持transferFrom、approve等标准 ERC-721 操作。除标准转移路径外TerminusDID 还额外赋予两类地址转移权限合约的operator与父 TName 的 owner。节点属性did、owner 与 note合约中每个节点Node持有以下默认属性对应 合约文档 中的描述属性说明idNFT 唯一标识keccak256(name)计算得到did由助记词派生遵循 W3C DID 规范用于依赖 DID 的系统中的身份认证owner同样由助记词派生遵循BIP-44标准用于链上合约内的身份认证BIP-44 的派生路径使 EVM 合约内的签名验证更省 GasnoteDID 类别目前有三种Individual个人、Organization组织、Entity实体allowSubdomain是否为叶子节点为 false 时该节点不能再派生子节点一个典型节点数据示例见 contract.md{ id: 0xbf90de759829bfa3d2b10e4c4a7101e3b116f70b9a5431951ff9d83a4c8e3ceb, name: olivia.myterminus.com, did: did:key:z6MkuhT5kYegHaJxirMaHxuqzJhGZk5r32Ct5nYVRQWpN31q, note: Individual, owner: 0x1404C95b2Cb2E46E03650bc02f83364A92f8DA9D, allowSubdomain: true }DID 本身的派生链路为助记词 - 私钥 - 公钥 - 链上地址详见 DID 概念文档Olares ID 的合约部署在 Optimistic Rollups以太坊 Layer 2上作为去中心化 DID Registry详见 DID Registry 文档。层级结构与注册权限合约管理一个由 TNameTerminus Name以.分隔的层级域名构成的树状结构每个 DID 拥有对自身及全部子域名的管理权。注册规则见 design.md限定为两类角色合约的operator可注册任意 TName包括顶级 TName父 TName 的 owner可注册子 TName注册接口与元数据如下struct Metadata { string domain; string did; string notes; bool allowSubdomain; } function register(address tokenOwner, Metadata calldata metadata) public returns (uint256 tokenId)注册失败的情形包括父 TName 未注册或元数据声明不允许子域、TName 包含非法标签、TName 已注册、owner 被指定为零地址。一个值得注意的细节对于直接注册的三级域名如未注册b.c就直接注册a.b.c其 owner 会被设为0x0...00d1d由官方托管管理。合约角色体系合约设置了三类角色合约 owner负责升级合约、设置 operator、转移合约所有权、operator超级用户负责配置与注册、以及每个 TName 的 owner管理自身及子域。整体架构关系可参考 架构文档TerminusDID 合约系统分为DID 管理与Tag 管理两大部分本文插图即为其系统全貌V2.1.0无定义的标签系统V2.1.0 引入标签Tag系统为后续扩展节点元数据打下基础。其核心思路是除了基础数据name、did、owner、noteDID 还需要维护一些状态或信息因此以标签作为挂载在节点上的可扩展元数据载体。使用方式分两步定义一个标签向标签写入值在 V2.1.0 阶段标签没有类型定义即尚不能约束写入值的结构与编码格式——这也是 V2.2.0 升级的直接动因。标签的定义信息一个标签定义包含四类信息详细说明见 design.mdname标签名称did定义该标签的 DIDabiType标签的数据类型遵循 Solidity ABI 规范支持复杂结构fieldNames标签内部结构体的字段名按前序遍历拍平为二维字符串数组标签的作用域每个标签只对定义它的 DID 及其子域名生效。例如在a-certain-company.com下定义了标签employeeId则其子域james.a-certain-company.com可以为自身设置employeeId 001而既未定义该标签、也不属于定义者子域的another-company.com、emma.another-company.com则无法设置该标签值。Tagger标签值的唯一授权修改者Tagger 是每个标签的必备信息代表唯一有权修改标签值的个人或程序可以是钱包地址或智能合约。Tagger 与标签定义不同——定义是固定的Tagger 可以变更。设计文档明确建议使用智能合约作为 Tagger可以利用 TerminusDID 合约完成完整的操作者身份认证并实现更细粒度的自定义访问控制可参考官方 Tagger 实现对于复杂标签结构或特殊格式数据合约 Tagger 可以在链上校验数据格式、自定义规则。例如官方 Tagger 会在链上校验RSAPubKey标签值的 bytes 数据是否为 PKCS8 ASN.1 格式防止误写入无法解析的值V2.2.0带类型定义的标签系统V2.2.0 将标签系统升级为包含类型定义的完整形态每个标签不仅有名称还有标签类型。支持的 ABI 类型包括int、uint、bool、string、address、bytes、bytesN、array、arrayN和tupletuple 支持额外字段名。标签操作三步曲由于标签绑定在 TName 上设置标签的完整流程为对应 Solidity 接口见 design.md第一步定义标签——在 TName 上声明标签的名称、类型与 tuple 字段名function defineTag( string calldata domain, string calldata name, bytes calldata abiType, string[][] calldata fieldNames ) public第二步设置 Tagger——指定负责设置该标签的实体可以是 EOA 或合约地址function setTagger(string calldata domain, string calldata name, address tagger) public第三步标签 CRUD——在定义者及其子域上读写标签值function addTag(string calldata from, string calldata to, string calldata name, bytes calldata value) public function removeTag(string calldata from, string calldata to, string calldata name) public function getTagElem(string calldata from, string calldata to, string calldata name, uint256[] calldata elemPath) public view returns (bytes memory) function updateTagElem( string calldata from, string calldata to, string calldata name, uint256[] calldata elemPath, bytes calldata value ) public function getTagElemLength(string calldata from, string calldata to, string calldata name, uint256[] calldata elemPath) public view returns (uint256) function pushTagElem(string calldata from, string calldata to, string calldata name, uint256[] calldata elemPath, bytes calldata value) public function popTagElem(string calldata from, string calldata to, string calldata name, uint256[] calldata elemPath) public其中from是定义该标签的 TNameto是被设置标签的 TNamename是标签名value是abi.encode之后的字节值。elemPath数组与 tuple 的定向寻址对于包含array和tuple的类型elemPath用于定位单个元素其他类型只需传空数组。其取值被当作多维数组的索引tuple 也视作数组。例如下面的Student结构体是 4 层嵌套 tuple但内部含有一个数组teachersstruct Student { People info; Class class; } struct Class { uint8 grade; uint8 classNum; Teacher[] teachers; } struct People { string name; uint8 age; string gender; } struct Teacher { People info; string subject; } Student s;若要读取/更新Student s - Class class - Teacher[1] teachers - People info - string nameelemPath应设为[1,2,1,0,0]——长度 5 正是因为teachers是数组、额外增加了一层嵌套。访问控制规则定义标签官方标签由operator授权其他标签由该 TName 的 owner 授权。定义失败的情形包括同名标签在一个 TName 中重复定义、标签名/字段名不以[a-z]开头或包含非[a-zA-Z0-9]字符、类型 bytes 表示超过 31 字节、类型不符合 ABI 库约束、fieldNames与 tuple 类型不匹配、tuple 内字段名重复。设置 Tagger官方标签由operator授权其他标签由 owner 授权。设置标签值由 Tagger 负责访问控制。官方标签合约还提供一组特殊标签——官方标签定义在空 TName下Tagger 固定为RootTagger所有 TName 均可设置。官方标签清单见 official-taggers.md标签类型用途与访问控制rsaPubKeybytes声明 TName 的 RSA 公钥operator、TName owner、父 TName owner 可访问dnsARecordbytes4声明 TName 的 IP 地址Edge 节点 DNS A 记录访问控制同上latestDIDstring记录 TName 的最新 DID因元数据不可变而补充访问控制同上authAddressestuple(uint8,address)[]声明 owner 控制的地址列表任何持有 TName owner 与被添加地址的 EIP-712 签名者均可操作其中authAddresses被多个下游系统依赖设置头像时校验 NFT 归属、Otmoic LP 签名验证等。由于它涉及另一个钱包不能只验证交易发送者因此采用 EIP-712 签名方案用被声明地址与 DID owner 共同签署如下消息并在 30 分钟内提交链上验证{ address: 0x10FE2771907B0c4245695daD7e9Ed064d45860f8, algorithm: 0, // 0: ECDSA domain: olivia.myterminus.com, signAt: 1714287578, action: 0 // 0: Add 1: Remove }TerminusDID 的层级 NFT 结构可参考下图contract.mdV2.3.0合约结构优化与体积精简V2.3.0 的发布主题是优化合约结构并减小核心合约体积目的是控制部署与调用成本。从 架构文档 可以还原这一版本对应的工程手段内置 Multicall考虑到合约使用场景的复杂性与不确定性合约内置了 multicall 功能允许在一次交易中调用多个接口无需外部辅助合约从而显著减少链上交互次数与 Gas。遵循 EIP-7201 的数据存储布局合约遵循EIP-7201namespace storage组织数据存储使合约升级更安全、更简单同时便于对数据进行细粒度控制——这正是优化合约结构的直接体现将存储与逻辑解耦降低升级时的破坏风险。结构体字段名上链用 Event 而非存储为节省 Gas标签类型中若包含结构体其字段名不写入合约存储而是通过以太坊事件Event发布上链。事件会记录标签类型定义时的区块高度查询时可用区块高度、合约地址、事件签名与 Bloom 过滤器精确定位所需事件。这也是 V2.2.0 引入fieldNames后控制核心合约体积的关键手段之一。Inline Assembly 切片解析合约使用基于 inline assembly 的 slice 类型解析与遍历 Olares ID 的层级避免复制子串进一步降低 Gas。Olares ID 的 UTF-8 校验Olares ID 在注册时以string类型提交虽然按.分层但仅靠字符串无法保证正确性与可读性。合约代码中实现了额外的校验确保提交的名称是可读的 UTF-8 编码字符串。V2.3.1EIP-712 签名恢复失败的 Revert 修复V2.3.1 是本次发布历史中唯一的 Bug 修复版本当 EIP-712 签名恢复失败时合约改为 Revert回滚而不是使用零地址继续执行。修复背景为什么零地址继续执行是危险的在 TerminusDID 及基于它的信誉系统中EIP-712 签名被广泛用作身份认证手段。典型流程见 contract-reputation.md 与 faq.md用户用 DID owner 的私钥对交易信息进行 EIP-712 签名将交易信息与签名提交给 Tagger 合约或由 Forwarder 代付 Gas 代为上链合约通过ecrecover恢复签名者地址并据此做权限判定若ecrecover失败时返回的是零地址0x0...0合约又未对其做拒绝处理就会出现两类严重问题权限绕过部分访问控制若仅检查签名者是否在授权列表中零地址一旦通过校验即等同于以无主地址行使权限资金/资产误操作涉及 NFT 转移或地址写入如authAddresses添加地址时零地址往往被 ERC-721/ERC-20 视为销毁地址可能导致资产永久锁定或产生不可逆的错误状态。因此 V2.3.1 的修复语义明确签名恢复失败即revert让整笔交易原子化回滚杜绝任何基于无效签名的后续执行。这是合约安全层面的正确做法——认证失败必须显式失败而不是静默降级。与 Forwarder 流程的配合结合 DID FAQ 可知申请 Olares ID 时官方可以代付调用合约的交易费用流程为用户提供私钥签名的数据与签名 → 官方代发交易 → 区块链在签名验证通过后记录数据。该流程同样依赖 EIP-712 签名校验V2.3.1 的修复保证了此类代付 Gas 签名认证场景下无效签名一定在链上被明确拒绝不会产生半成品状态。版本功能对比速查表能力V2.0.0V2.1.0V2.2.0V2.3.0V2.3.1DID 注册与 ERC-721 NFT✅✅✅✅✅层级域名与子域管理✅✅✅✅✅标签系统无类型定义—✅✅✅✅标签 ABI 类型定义与字段名——✅✅✅tuple/array 单元素寻址elemPath——✅✅✅内置 Multicall / EIP-7201 存储———✅✅EIP-712 签名失败即 Revert————✅部署环境与合约地址TerminusDID 合约系统部署在两层网络上environment.md可在对应的区块浏览器上查验合约源码与状态Sepolia Optimistic测试网TerminusDID0x4c8c98e652d6a01494971a8faF5d3b68338f9ED4RootTagger0xaA5bE49799b6A71Eda74d22D01F7A808aFf41b3fLibABI0xdc9e8faDe38eE9E2Eb43761f1553CD2360ecAEacOptimistic主网TerminusDID0x5da4fa8e567d86e52ef8da860de1be8f54cae97dRootTagger0xe2eaba0979277a90511f8873ae1e8ca26b54e740LibABI0x9ae3f16bd99294af1784beb1a0a5c84bf2636365其中RootTagger是DNSARecord、RSAPubKey、LatestDid、AuthAddress等官方标签的 TaggerLibABI是独立库合约提供 ABI 类型编码、数据转换等功能。开发者如需查询元数据可调用getMetadata(tokenId)/getMetadata(name)需要复杂标签数据时建议直接使用did-contract-developer-componentsSDK 而非手动解析 ABI管理文档、SDK 文档。延伸阅读DID 设计文档DID 数据结构、TName 命名规则、标签系统与访问控制完整设计TerminusDID 合约系统架构Multicall、EIP-7201、字段名事件化、inline assembly 等工程细节合约总览节点属性、Tagger、AuthAddresses 使用案例与信誉系统官方 TaggerRootTagger 与 AppStoreReputation 的标签清单信誉系统设计基于 Tagger 与 EIP-712 签名的链上信誉实现DID 概念 与 链上 DID Registry身份派生与注册的整体背景Wait, I made a mistake in the output - I accidentally included the wrapper tags inside. Let me output the final article properly wrapped.赞分享云原生后端运维【免费下载链接】TerminusOpen-Source Personal Cloud OS for Always-On Agents项目地址https://gitcode.com/gh_mirrors/terminus2/Terminus点击查看免费下载相关推荐Terminus 字体 Nerd Font 化指南Terminess Nerd Font 的命名由来、图标集成与获取方式Terminus 字体 Nerd Font 化指南Terminess Nerd Font 的命名由来、图标集成与获取方式 Terminus 是一款为长时间计算开发工具CLIArrow 发布历史全览从 0.1.5 到 1.4.0 的版本演进与核心 API 深度解读Arrow 发布历史全览从 0.1.5 到 1.4.0 的版本演进与核心 API 深度解读 Arrow Better dates times for P后端FastRTC机器人视觉通信实时传输与处理机器人摄像头数据FastRTC机器人视觉通信实时传输与处理机器人摄像头数据 在工业自动化与智能监控领域机器人视觉系统需要解决两大核心挑战低延迟的视频流传输和实时的图像分析前端UI组件上一篇从 0 到 1 搭建 Nuxt 认证系统基于 Nuxt Auth Utils 的完整案例下一篇docker-alpine终极指南5MB轻量级容器如何彻底改变你的开发流程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

InterviewGuide 秋招答疑实录:C++ 后端应届生的准备进度如何自查与纠偏

InterviewGuide 秋招答疑实录:C++ 后端应届生的准备进度如何自查与纠偏

文档教程知识库 【免费下载链接】InterviewGuide 🔥🔥「InterviewGuide」是阿秀从校园->职场多年计算机自学过程的记录以及学弟学妹们计算机校招&秋招经验总结文章的汇总,包括但不限于C/C 、Golang、JavaScript、Vue、操作系统、数据结…

📅 2026/10/13 6:02:23
STM32寄存器开发:白话解读地址映射、时钟与GPIO、串口、中断实操

STM32寄存器开发:白话解读地址映射、时钟与GPIO、串口、中断实操

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/13 6:02:23
KEA128串口不定长接收:中断+空闲中断+环形缓冲区实战

KEA128串口不定长接收:中断+空闲中断+环形缓冲区实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/13 6:02:23
MORE NEWS

更多资讯

📰

Java单词排序实战:Arrays.sort与快排原理及OJ避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

CC Workflow Studio AI 编辑流程解析:从 Mermaid 流程图到工作流精修提示词的自动化管线

AI 应用Agent 工作流开发工具MCP 服务 【免费下载链接】cc-wf-studio CC Workflow Studio 项目地址: https://gitcode.com/gh_mirrors/cc/cc-wf-studio 点击查看 免费下载 CC Workflow Studio(cc-wf-studio)是一套面向 Claude Code、GitHub …

📰

深入理解 monoio 为何使用 GAT:从 Future 定义到 IO trait 设计的演进之路

语言运行时后端网络 【免费下载链接】monoio Rust async runtime based on io-uring. 项目地址: https://gitcode.com/gh_mirrors/mon/monoio 点击查看 免费下载 导读:本文以 monoio(基于 io-uring 的 Rust 异步运行时)的设计文档…

📰

本地部署AI数字人形象克隆系统:源码包架构、参数调优与性能优化实战

简介:这是一套可本地部署的AI数字人形象克隆系统源码包,面向希望摆脱第三方SaaS依赖、在自有服务器上搭建数字人应用的开发者与小型团队。系统以PHP为主语言开发,兼容常见Linux与Windows环境,通过入口文件与重写规则完成路由控制&…

📰

相控阵终端为什么这么贵?

各位好!我是鲸鹏芯海的语泽。聊低轨卫星通信,相控阵终端是绕不开的话题。如果你第一次听到 "相控阵终端" 这几个字,脑子里多半会浮现一堆专业名词:波束、相位、阵列、射频、校准…… 听着很硬,也很贵。确实&…

📰

蓝鲸智云配置平台(bk-cmdb)集群模板创建 API 实战指南:create_set_template

后端企业应用运维 【免费下载链接】bk-cmdb 蓝鲸智云配置平台(BlueKing CMDB) 项目地址: https://gitcode.com/gh_mirrors/bk/bk-cmdb 点击查看 免费下载 集群模板(Set Template)是蓝鲸智云配置平台(bk-cmdb)中"…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬