ERC-7857: 具有私有元数据的 AI 代理 NFT
AI 代理 NFT,支持安全地管理具有可验证数据传输的私有元数据
Authors | Ming Wu (@sparkmiw), Jason Zeng (@zenghbo), Wei Wu (@Wilbert957), Michael Heinrich (@michaelomg) |
---|---|
Created | 2025-01-02 |
Discussion Link | https://ethereum-magicians.org/t/erc-7857-an-nft-standard-for-ai-agents-with-private-metadata/22391 |
摘要
一种专门为 AI 代理设计的 NFT 标准接口,其中元数据表示代理功能并需要隐私保护。与侧重于静态元数据的传统 NFT 标准不同,此标准引入了可验证数据所有权和安全传输的机制。通过为不同的验证方法(例如,可信执行环境 (TEE)、零知识证明 (ZKP))定义统一的接口,它可以安全地管理有价值的代理元数据(如模型、内存和字符定义),同时保持机密性和可验证性。
动机
随着 AI 模型智能的不断提高,代理已成为自动化有意义的日常任务的强大工具。代理与区块链技术的集成已被认为是加密行业中的一个主要叙事,许多项目都允许用户创建代理。然而,一个关键的缺失部分是代理所有权的去中心化管理。
AI 代理具有固有的非同质化属性,这使得它们成为 NFT 表示的天然候选对象:
- 每个代理都是独一无二的,具有自己的模型、内存和角色
- 代理体现明确的所有权,代表着巨大的计算投资和知识产权
- 代理具有定义其能力的私有元数据(例如,神经网络模型、内存、角色定义)
然而,当前的 NFT 标准(如 ERC-721)不足以将 AI 代理表示为数字资产。虽然 NFT 可以建立数字项目的所有权,但使用它们来表示 AI 代理会带来独特的挑战。关键问题在于元数据传输机制。与元数据通常是静态且可公开访问的传统 NFT 不同,AI 代理的元数据(构成代理本身):
- 具有内在价值,通常是转移的主要目的
- 需要加密存储以保护知识产权
- 在所有权变更时需要隐私保护和可验证的传输机制
例如,在转移代理 NFT 时,我们需要确保:
- 加密元数据(代理的模型、内存、角色等)的实际传输是可验证的
- 新所有者可以安全地访问构成代理的元数据
- 代理的执行环境可以验证所有权并加载适当的元数据
本 EIP 引入了一个具有私有元数据的 NFT 标准,该标准通过隐私保护验证机制解决这些要求,从而实现有价值的代理数据的安全所有权和传输,同时保持机密性和可验证性。该标准将作为新兴代理生态系统的基础,允许平台以去中心化的方式提供可验证的代理所有权和安全的元数据管理。
规范
EIP 定义了三个关键接口:主 NFT 接口、元数据接口和数据验证接口。
数据验证系统
验证系统由两个核心组件组成,它们协同工作以确保安全的数据操作:
- 链上验证器(数据验证接口)
- 实现为智能合约
- 验证通过合约调用提交的证明
- 返回结构化的验证结果
- 可以使用不同的验证机制(TEE/ZKP)实现
- 链下证明器
- 为所有权和可用性声明生成证明
- 与加密数据和密钥一起使用
- 实现方式因验证机制而异:
- 基于 TEE:在可信硬件中生成证明
- 基于 ZKP:创建加密零知识证明
该系统支持两种类型的证明:
- 所有权证明
- 由有权访问原始数据的 Prover 生成
- 证明知道所声明的 dataHashes 的原像
- 通过 verifyOwnership() 在链上验证
- 转移有效性证明
- 由 Prover 为数据传输生成
- 证明:
- 了解原始数据(原像)
- 正确解密和重新加密数据
- 安全的密钥传输(使用接收方的公钥来加密新密钥)
- 存储中的数据可用性(使用接收方的签名来确认数据在存储中可用)
- 通过
verifyTransferValidity()
在链上验证
所有权验证是可选的,因为当薄荷的 token 被转移或克隆时,可用性验证中会再次检查所有权验证。安全总比后悔好,所以我们建议对铸造和更新进行所有权验证。
不同的验证机制具有不同的功能:
- 基于 TEE 的实现
- Prover 在可信硬件中运行
- 可以安全地处理私钥
- 支持直接数据重新加密
- 验证器检查 TEE 证明
- 基于 ZKP 的实现
- Prover 生成加密证明
- 无法处理多方私钥
- Prover 知道重新加密密钥
- 下次更新时需要额外的重新加密,否则新的更新仍然对 Prover 可见
数据验证接口
/// @notice 所有权证明验证的输出
struct OwnershipProofOutput {
bytes32[] dataHashes;
bool isValid;
}
/// @notice 转移有效性证明验证的输出
struct TransferValidityProofOutput {
bytes32[] oldDataHashes;
bytes32[] newDataHashes;
bytes pubKey;
bytes sealedKey;
bool isValid;
}
/// @notice 验证数据的所有权
/// @param _proof 由配套证明系统生成的证明
/// @return 验证结果和已验证的数据哈希
function verifyOwnership(
bytes calldata _proof
) external view returns (OwnershipProofOutput memory);
/// @notice 验证数据传输的有效性
/// @param _proof 由配套证明系统生成的证明
/// @return 验证结果和传输详细信息
function verifyTransferValidity(
bytes calldata _proof
) external view returns (TransferValidityProofOutput memory);
元数据接口
/// @dev 当数据更新时发出此事件
event Updated(
uint256 indexed _tokenId,
bytes32[] _oldDataHashes,
bytes32[] _newDataHashes
);
/// @notice 获取 NFT 集合的名称
function name() external view returns (string memory);
/// @notice 获取 NFT 集合的符号
function symbol() external view returns (string memory);
/// @notice 获取特定 token 的元数据 URI
function tokenURI(uint256 tokenId) external view returns (string memory);
/// @notice 更新数据
/// @param _tokenId 要更新的 token
/// @param _proofs 更新的数据所有权的证明
function update(
uint256 _tokenId,
bytes[] calldata _proofs
) external;
/// @notice 获取 token 的数据哈希
/// @param _tokenId token 标识符
/// @return token 的当前数据哈希
function dataHashesOf(uint256 _tokenId) public view returns (bytes32[] memory);
/// @notice 获取 token 的数据描述
/// @param _tokenId token 标识符
/// @return token 的当前数据描述
function dataDescriptionsOf(uint256 _tokenId) public view returns (string[] memory);
主 NFT 接口
/// @dev 当铸造新的功能性 NFT 时发出此事件
event Minted(
uint256 indexed _tokenId,
address indexed _creator,
bytes32[] _dataHashes,
string[] _dataDescriptions
);
/// @dev 当授权用户使用数据时发出此事件
event AuthorizedUsage(
uint256 indexed _tokenId,
address indexed _user
);
/// @dev 当数据随所有权一起转移时发出此事件
event Transferred(
uint256 _tokenId,
address indexed _from,
address indexed _to
);
/// @dev 当数据被克隆时发出此事件
event Cloned(
uint256 indexed _tokenId,
uint256 indexed _newTokenId,
address _from,
address _to
);
/// @dev 当发布密封密钥时发出此事件
event PublishedSealedKey(
address indexed _to,
uint256 indexed _tokenId,
bytes _sealedKey
);
/// @notice 此 NFT 使用的验证器接口
/// @return 验证器合约的地址
function verifier() external view returns (IDataVerifier);
/// @notice 使用数据所有权证明来薄荷新的 NFT
/// @param _proofs 数据所有权的证明
/// @param _dataDescriptions 数据的描述
/// @return _tokenId 新铸造的 token 的 ID
function mint(bytes[] calldata _proofs, string[] calldata _dataDescriptions)
external
payable
returns (uint256 _tokenId);
/// @notice 转移完整数据(完整意味着数据和所有权)
/// @param _to 将数据转移到的地址
/// @param _tokenId 要转移数据的 token
/// @param _proofs _to 可用的数据证明
function transfer(
address _to,
uint256 _tokenId,
bytes[] calldata _proofs
) external;
/// @notice 克隆数据(克隆仅表示数据,不表示所有权)
/// @param _to 将数据克隆到的地址
/// @param _tokenId 要克隆数据的 token
/// @param _proofs _to 可用的数据证明
/// @return _newTokenId 新克隆的 token 的 ID
function clone(
address _to,
uint256 _tokenId,
bytes[] calldata _proofs
) external payable returns (uint256 _newTokenId);
/// @notice 转移具有所有权的公共数据
/// @param _to 将数据转移到的地址
/// @param _tokenId 要转移数据的 token
function transferPublic(
address _to,
uint256 _tokenId
) external;
/// @notice 克隆公共数据
/// @param _to 要将数据克隆到的地址
/// @param _tokenId 要克隆数据的 token
/// @return _newTokenId 新克隆的 token 的 ID
function clonePublic(
address _to,
uint256 _tokenId
) external payable returns (uint256 _newTokenId);
/// @notice 将授权用户添加到群组
/// @param _tokenId 要添加到群组的 token
function authorizeUsage(
uint256 _tokenId,
address _user
) external;
/// @notice 获取 token 所有者
/// @param _tokenId token 标识符
/// @return token 的当前所有者
function ownerOf(uint256 _tokenId) external view returns (address);
/// @notice 获取 token 的授权用户
/// @param _tokenId token 标识符
/// @return token 的当前授权用户
function authorizedUsersOf(uint256 _tokenId) external view returns (address[] memory);
原理
本标准中的设计选择受到以下几个关键要求的推动:
- 验证抽象:该标准将验证逻辑分离到一个专用接口(
IDataVerifier
)中,允许不同的验证机制(TEE、ZKP)以可互换的方式实现和使用。验证器应支持两种类型的证明:- 所有权证明 通过证明知道生成所声明的 dataHashes 的原像来验证证明者是否拥有原始数据
- 转移有效性证明 通过证明以下内容来验证安全数据完整性和可用性:了解原始数据(oldDataHashes 的原像);能够使用 oldKey 解密并使用 newKey 重新加密;使用接收者的公钥安全传输 newKey;与 newDataHashes 匹配的新加密数据的完整性;以及由接收者对
oldDataHashes
和newDataHashes
的签名确认的数据可用性
-
数据保护:该标准使用数据哈希和加密密钥来确保有价值的 NFT 数据保持受到保护,同时仍可进行完整性和可用性验证
- 灵活的数据管理:支持三种不同的数据操作:
- 完全转移,其中数据和所有权转移给新所有者
- 数据克隆,其中数据被克隆到新的 token,但所有权不转移
- 数据使用授权,其中数据被授权由特定用户使用,但所有权不转移,并且用户仍然无法访问数据。这需要一个环境来秘密地验证用户并处理来自授权用户的请求,我们称之为“密封执行器”
- 密封执行器:虽然密封执行器未定义且超出本标准的范围,但它是本标准工作的关键组件。密封执行器是一个可以验证用户并秘密处理来自授权用户的请求的环境。密封执行器应通过 tokenId 获取授权组,并使用授权组中的公钥验证用户的签名。如果验证成功,执行器将处理请求并将结果返回给用户,并且密封执行器可以通过受信任方(在允许的情况下)、TEE 或 FHE 来实现
向后兼容性
本 EIP 不继承现有的 NFT 标准,以保持其对功能性数据管理的关注。但是,如果需要传统的 NFT 兼容性,则实现可以选择额外实现 ERC-721。
参考实现
有关参考实现,请参阅 0G Labs 的 0G 代理 NFT 实现(可在 0glabs GitHub 存储库 0g-agent-nft
中找到)。
安全考虑事项
- 证明验证
- 实现必须仔细验证证明中的所有断言
- 必须防止重放攻击
- 不同的验证系统有其自身的安全考虑,以及关于密钥管理的不同功能:TEE 可以安全地处理来自多方的私钥,从而实现直接数据重新加密。但是,由于其加密性质,ZKP 无法处理来自多方的私钥。因此,重新加密密钥也来自证明者(即发送者),因此通过转移或克隆获得的 token 必须在其下次更新期间进行重新加密,否则新的更新仍然对以前的所有者可见。密钥处理能力的这种差异会影响在以后使用期间如何管理数据转换
- 数据隐私
- 只有哈希和密封密钥存储在链上,实际的功能数据必须安全地存储和传输到链下
- 密钥管理对于安全数据访问至关重要
- TEE 验证系统可以支持接收者的私钥,但 ZKP 验证系统不能。因此,当使用 ZKP 时,从其他人转移或克隆的 token 应在下次更新时重新加密,否则新的更新仍然对以前的所有者可见
- 访问控制和状态管理
- 仅限于 token 所有者的操作
- 所有数据操作必须保持完整性和可用性
- 关键状态更改(密封密钥、所有权、权限)必须是原子的且可验证的
- 密封执行器
- 虽然超出了本标准的范围,但密封执行器对于安全操作至关重要
- 密封执行器通过针对每个 tokenId 的授权公钥验证用户签名,从而在安全环境中验证用户并处理请求
- 密封执行器可以通过受信任方(在允许的情况下)、可信执行环境 (TEE) 或完全同态加密 (FHE) 来实现
- 确保安全的请求处理和结果交付
版权
版权和相关权利通过 CC0 豁免。
Citation
Please cite this document as:
Ming Wu (@sparkmiw), Jason Zeng (@zenghbo), Wei Wu (@Wilbert957), Michael Heinrich (@michaelomg), "ERC-7857: 具有私有元数据的 AI 代理 NFT [DRAFT]," Ethereum Improvement Proposals, no. 7857, January 2025. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7857.