4、DID与区块链:主流公链上的DID实现
好,咱们进入正题。前面聊了DID的规范、文档结构,那这些东西到底存哪儿?怎么保证它不被篡改?答案就是——链上锚定。
说白了,DID的核心价值就是「去中心化」。你想想看,如果DID文档存在某个中心服务器上,那跟传统账号有啥区别?所以,我们需要把DID的「根」锚定到区块链上。今天我就带大家看看,在以太坊、Polygon、Solana这三条主流公链上,DID是怎么落地的。
4.1 为什么需要链上锚定?
先回答一个基础问题:为什么非得把DID跟区块链绑在一起?
我个人习惯把DID比作「数字身份证的根」。这个根必须满足三个条件:
- 不可篡改——谁也不能偷偷改你的身份信息
- 全球可验证——任何人在任何地方都能查到这个根
- 无单点故障——没有哪个公司能关掉你的身份
区块链天然满足这三点。所以,DID的「锚定」操作,就是把DID文档的哈希、或者关键控制权信息,写到链上的一笔交易里。嗯,这里要注意:不是把整个DID文档存上链,那样太贵了。我们只存一个「指纹」——哈希值。
核心原则:链上存证明,链下存数据。
DID文档本身存在IPFS或中心化存储里,链上只存文档的哈希和DID Controller的公钥信息。
4.2 以太坊上的DID实现
以太坊是DID生态最成熟的公链。ERC-1056(以太坊DID方法)是事实标准。我在项目中用过好几次,说实话,它的设计很巧妙。
4.2.1 ERC-1056 核心机制
ERC-1056不依赖智能合约存储DID文档,而是利用以太坊账户本身。每个以太坊地址天然就是一个DID:did:ethr:0x1234...。
为什么可以这样?因为以太坊地址本身就带有公钥信息。你只要用私钥签个名,就能证明你是这个DID的拥有者。
具体实现上,ERC-1056用了一个轻量级的注册合约,只记录三件事:
- DID所有者的变更历史
- 委托控制人的公钥
- DID文档的哈希值
来看一个实际的解析流程:
// 使用 ethers.js 解析 did:ethr
import { EthrDID } from 'ethr-did'
import { Resolver } from 'did-resolver'
import { getResolver } from 'ethr-did-resolver'
// 配置以太坊网络
const providerConfig = {
rpcUrl: 'https://mainnet.infura.io/v3/YOUR_PROJECT_ID',
registry: '0xdca7ef03e98e0dc2b855be647c39abe984fcf21b' // ERC-1056主网合约
}
// 创建解析器
const resolver = new Resolver(getResolver(providerConfig))
// 解析DID
async function resolveDID(did) {
const doc = await resolver.resolve(did)
console.log('DID文档:', JSON.stringify(doc, null, 2))
return doc
}
// 调用示例
resolveDID('did:ethr:0x1234567890abcdef...')
我曾经在一个供应链金融项目里用过这套方案。当时有个坑:以太坊主网交易费太贵了,每次更新DID文档哈希要花几十美元。后来我们改用了Polygon,成本直接降到几分钱。
小技巧:在以太坊上,如果你只是验证身份(不更新文档),完全不需要花Gas。因为验证只需要检查链上已有的记录,是只读操作。
4.3 Polygon上的DID实现
Polygon作为以太坊的侧链,兼容EVM,所以ERC-1056可以直接部署上去。但Polygon有自己的特色——Polygon ID。
4.3.1 Polygon ID 的独特设计
Polygon ID不只是简单的DID注册,它集成了零知识证明(ZKP)。这意味着你可以「证明你拥有某个属性,而不暴露属性本身」。比如,证明你年龄大于18岁,但不用告诉对方你具体几岁。
Polygon上的DID格式是:did:polygonid:polygon:mumbai:2qD...xyz
它的链上锚定逻辑是这样的:
- 用户生成一个身份钱包(包含公钥和私钥)
- 身份哈希被提交到Polygon上的智能合约
- 用户用私钥签发可验证凭证(VC)
- 验证者通过链上合约验证凭证的有效性
来看一个实际的状态发布代码:
// Polygon ID 状态发布示例(简化版)
const { Identity } = require('@polygonid/js-sdk')
async function publishState() {
// 创建身份
const identity = new Identity()
await identity.create()
// 生成状态信息
const state = identity.getState()
// 发布到链上(需要Gas)
const tx = await identity.publishStateToPolygon(
'0x...合约地址',
state
)
console.log('状态已发布,交易哈希:', tx.hash)
}
// 验证凭证
async function verifyCredential(credential) {
const isValid = await identity.verifyCredential(credential)
console.log('凭证有效:', isValid)
}
说实话,Polygon ID的ZK方案确实牛,但学习曲线有点陡。我刚开始搞的时候,被那个「Merkle Tree证明」绕晕了好几天。后来发现,其实你不需要完全理解ZK的数学原理,只要会用SDK就行。
避坑指南:我曾经在生产环境遇到过一个问题——Polygon的RPC节点偶尔会超时,导致状态发布失败。解决方案是:在代码里加重试机制,并且使用多个RPC端点做负载均衡。
4.4 Solana上的DID实现
Solana跟以太坊完全不同。它用的是历史证明(PoH)加权益证明(PoS),交易速度快、费用极低。Solana上的DID标准是 did:sol。
4.4.1 Solana DID 的账户模型
Solana没有智能合约存储DID,而是利用它的「账户模型」。每个Solana账户都可以存储数据,DID文档就存在账户的「数据区」里。
DID格式:did:sol:9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin
解析流程跟以太坊不太一样:
// Solana DID 解析示例
import { Connection, PublicKey } from '@solana/web3.js'
import { SolDID } from '@solana/did'
const connection = new Connection('https://api.mainnet-beta.solana.com')
async function resolveSolDID(did) {
// 从DID中提取公钥
const pubkey = new PublicKey(did.split(':')[2])
// 读取账户数据
const accountInfo = await connection.getAccountInfo(pubkey)
if (!accountInfo) {
throw new Error('DID账户不存在')
}
// 解析DID文档
const didDoc = SolDID.parse(accountInfo.data)
return didDoc
}
// 创建新的DID
async function createSolDID() {
const did = await SolDID.create(connection)
console.log('新DID:', did.toString())
return did
}
Solana最大的优势是快。我在一个游戏项目里用过,用户注册DID几乎秒确认,费用不到0.00001 SOL。但缺点也很明显——Solana网络偶尔会「卡住」(我记得2022年就宕机过好几次),这时候DID解析也会受影响。
4.5 三条公链的对比
我整理了一个表格,方便你对比选择:
| 特性 | 以太坊 (ERC-1056) | Polygon (Polygon ID) | Solana (did:sol) |
|---|---|---|---|
| 交易费用 | 高($5-$50) | 低($0.01-$0.1) | 极低(<$0.001) |
| 确认时间 | 12-15秒 | 2-3秒 | 0.4-1秒 |
| 隐私保护 | 基础(无ZK) | 强(内置ZK) | 基础(无ZK) |
| 生态成熟度 | 最成熟 | 中等 | 早期 |
| 开发难度 | 低(文档多) | 中(ZK有门槛) | 中(Solana独特) |
| 适用场景 | 高价值身份 | 隐私敏感应用 | 高频低价值场景 |
4.6 链上解析的通用流程
不管用哪条链,DID解析的流程都差不多。我画个逻辑图给你:
- 输入DID:比如
did:ethr:0x... - 解析DID方法:提取
ethr部分,找到对应的解析器 - 读取链上数据:调用对应链的RPC,获取DID文档哈希和控制人信息
- 验证签名:检查返回的数据是否由DID Controller签名
- 返回DID文档:组装成标准的DID文档格式
这里有个关键点:解析器必须信任它连接的RPC节点。如果RPC节点作恶,返回假数据,那解析结果就是错的。所以,我建议在生产环境里,自己运行一个全节点,或者用多个RPC做交叉验证。
核心总结:
- 以太坊:稳定、成熟,适合高价值身份场景
- Polygon:成本低、有ZK隐私保护,适合合规应用
- Solana:极快、极便宜,适合高频交互场景
- 选哪条链,取决于你的业务需求、预算和隐私要求
好了,这一章的内容就到这儿。下一章我们会深入DID文档的详细结构,包括怎么用JSON-LD做扩展、怎么添加服务端点。到时候我会拿一个真实的DID文档拆开给你看,保证你一看就懂。