ERC-7529: 合约发现和 eTLD+1 关联
利用 TXT 记录来发现、验证和关联智能合约与 DNS 域的所有者。
Authors | Todd Chapman (@tthebc01), Charlie Sibbach <charlie@cwsoftware.com>, Sean Sing (@seansing) |
---|---|
Created | 2023-09-30 |
Discussion Link | https://ethereum-magicians.org/t/add-eip-dns-over-https-for-contract-discovery-and-etld-1-association/15996 |
Requires | EIP-1191 |
摘要
RFC 8484 中引入的 DNS over HTTPS (DoH) 使得可以直接从 Web 应用程序对 DNS 记录进行防篡改的客户端查询。本提案描述了一个简单的标准,利用 DoH 来获取 TXT 记录(来自传统的 DNS 服务提供商),用于发现和验证智能合约与常见 DNS 域的关联。该标准可用作一种直接的技术,以减轻智能合约作者身份的欺骗,并通过标准 Web 搜索机制增强智能合约的可发现性。
动机
随着主流企业开始更快地采用公共区块链和数字资产技术,越来越需要一种发现/搜索机制(与传统 Web 技术兼容),用于搜索与已知业务域关联的智能合约,并合理保证智能合约确实属于 DNS 域的业务所有者。相对较新的 DoH 的引入和广泛支持意味着可以直接在 Web 应用程序上下文中对 DNS 记录进行防篡改查询,从而利用简单的 TXT 记录作为链上智能合约的指针。在引入 DoH 之前,Web(和移动)应用程序无法直接访问 DNS 记录;相反,它们必须通过可轻松操纵响应结果的受信任的专有服务提供商来中继请求。
根据 Cloudflare 的说法,如今 TXT 记录最常见的两个用例是电子邮件垃圾邮件预防(通过 SPF、DKIM 和 DMARC TXT 记录)和域名所有权验证。此处考虑的链上智能合约发现和验证的用例本质上是类似的。
TXT 指针与适当的智能合约接口(本提案中描述)相结合,产生了一种简单、灵活且强大的机制,用于客户端检测和合理安全地验证与域名所有者关联的链上逻辑和数字资产。例如,稳定币发行者可以利用此标准为最终用户或基于 Web 的最终用户客户端提供一种方法,以确保其钱包正在交互的资产确实是知名 DNS 域的所有者或管理员发行或控制的合约。
示例 1:
用户访问 merchant.com,该网站接受通过 paymentprocessor.com 付款。paymentprocessor.com 背后的企业之前发布了一种稳定币,用于更轻松的跨境支付,并且符合此 ERC。在结账页面上,paymentprocessor.com 以 iframe 组件的形式挂载。如果用户安装了与此标准兼容的浏览器扩展钱包,则该钱包可以检测结账页面上下文中 iframe 的域,发现并验证稳定币与 paymentprocessor.com 的关联,并自动提示以 paymentprocessor.com 的稳定币完成购买。
示例 2:
用户访问 nftmarketplace.io 以从 theirfavoritebrand.com 购买限量版 NFT。市场 Web 应用程序可以利用此 ERC 允许用户按域名搜索,并向用户表明感兴趣的 NFT 确实是与其 theirfavoritebrand.com 相关联的真实资产。
规范
本文档中使用的关键词“必须(MUST)”、“禁止(MUST NOT)”、“需要(REQUIRED)”、“应当(SHALL)”、“不应当(SHALL NOT)”、“应该(SHOULD)”、“不应该(SHOULD NOT)”、“推荐(RECOMMENDED)”、“不推荐(NOT RECOMMENDED)”、“可以(MAY)”和“可选(OPTIONAL)”按照 RFC 2119 和 RFC 8174 中的描述进行解释。
定义:eTLD+1
术语 TLD 代表顶级域名,并且始终是域名中 URL 中最后一个点后面的部分(例如.com
或.net
)。如果只有一个组织可以直接注册 TLD 下的域名,那么可以保证myexample.com
、abc.myexample.com
和def.myexample.com
都属于同一组织。
但是,通常情况并非如此,因为许多 DNS 注册商允许组织注册顶级域名下的域名(例如sussex.ac.uk
和aber.ac.uk
由不同的机构控制)。这些类型的域称为 eTLD(有效顶级域名),表示一个域,在该域下,单个组织可以注册域名。例如,myexample.com
的 eTLD 是.com
,sussex.ac.uk
的 eTLD 是.ac.uk
,因为各个组织可以在.com
和.ac.uk
下获得自己的域名。
因此,eTLD+1 是 eTLD 加上域名中的下一部分。由于 eTLD 根据定义是可以注册的,因此所有具有相同 eTLD+1 的域名都归同一组织所有,这使得它们适合在本提案中用于将智能合约与单个企业或组织实体相关联。
TXT 记录中的合约指针
eTLD+1 域名的所有者必须在其 DNS 设置中创建 TXT 记录,该记录充当指向他们希望与其域关联的所有相关智能合约的指针。
TXT 记录并非旨在(也不允许大多数 DNS 服务器)存储大量数据。每个 DNS 提供商都有其自己的特定于供应商的字符限制。但是,EVM 兼容的地址字符串为 42 个字符,因此大多数 DNS 提供商将允许在单个记录下存储数十个合约地址。此外,允许域具有与同一主机关联的多个 TXT 记录,并且可以在单个 DoH 查询中检索所有重复记录的内容。
指向组织智能合约的 TXT 记录必须遵循以下架构:
HOST
:ERC-7529.<chain_id>._domaincontracts
(其中<chain_id>
替换为链 ID 的十进制表示形式)VALUE
: <地址 1
>,<地址 2
>,…
建议 EVM 地址字符串遵循 ERC-1191,以便浏览器客户端可以在进行 RPC 调用之前校验地址及其目标网络的有效性。
用户的 Web 应用程序可以使用fetch
直接从支持 DoH 的 DNS 注册商处访问 TXT 记录。支持 JSON 格式的 DoH 服务器的示例查询如下所示:
await fetch("https://example-doh-provider.com/dns-query?name=ERC-7529.1._domaincontracts.myexample.com&type=TXT", {
headers: {
Accept: "application/dns-json"
}
})
智能合约与域的关联
任何智能合约都可以实现此 ERC,以提供 TXT 记录中列出的智能合约地址的验证机制。
智能合约只需要存储一个新的成员变量domains
,这是一个从与部署(或密切相关)合约的企业或组织关联的所有 eTLD+1 域字符串的 keccak256 哈希到布尔值的映射。可以使用外部函数addDomain
和removeDomain
写入此成员变量。可以通过checkDomain
函数查询domains
成员变量,该函数接受表示 eTLD+1 的字符串,如果合约已与域关联,则返回 true,否则,返回 false。
最后,当 eTLD+1 域从domains
映射中添加 (AddDomain
) 或删除 (RemoveDomain
) 时,合约可以发出事件。当客户端事先不知道与合约关联的所有域时,这对于确定与合约关联的所有域可能很有用。
{
/// @notice 添加域时发出的可选事件
/// @param domain 与合约关联的 eTLD+1
event AddDomain(string domain);
/// @notice 从合约中删除域时发出的可选事件
/// @param domain 不再与合约关联的 eTLD+1
event RemoveDomain(string domain);
/// @dev 从与此合约关联的 eTLD+1 域的 keccak256 哈希到布尔值的映射
mapping(bytes32 => bool) domains;
/// @notice 一个 getter 函数,它接受一个 eTLD+1 域字符串,如果与合约关联,则返回 true
/// @param domain 表示 eTLD+1 域的字符串
function checkDomain(string calldata domain) external view returns (bool);
/// @notice 一种经过身份验证的方法来添加 eTLD+1 域
/// @param domain 表示与合约关联的 eTLD+1 域的字符串
function addDomain(string calldata domain) external;
/// @notice 一种经过身份验证的方法来删除 eTLD+1 域
/// @param domain 表示不再与合约关联的 eTLD+1 域的字符串
function removeDomain(string calldata domain) external;
}
客户端验证
当客户端检测到 eTLD+1 上列出的兼容 TXT 记录时,它应该循环遍历每个列出的合约地址,并通过适当的 RPC 提供程序断言,当将 eTLD+1 字符串传递给checkDomain
函数时,每个智能合约都返回true
。
或者,如果客户端正在检查实现此 ERC 的合约,则客户端应检查AddDomain
和RemoveDomain
事件,以计算一个或多个 eTLD+1 域是否与合约主动关联。用户客户端应该尝试从所有关联的 eTLD+1 域获取 TXT 记录,以验证其关联或真实性。客户端必须确认每个合约地址都包含在合约的domains
映射指向的 eTLD+1 的 TXT 记录的VALUE
字段中。
理由
在本规范中,TXT 记录HOST
命名方案旨在模仿 DKIM 命名约定。此外,此命名方案使得可以轻松地以编程方式确定任何智能合约是否与给定区块链网络上的域关联。在前面加上ERC-7529
将防止与其他 TXT 记录的命名冲突。<chain_id>
的值只是与智能合约部署的目标区块链网络关联的链 ID 的十进制表示形式(即,以太坊主网为1
,Sepolia 为11155111
)。因此,典型的HOST
可能是:ERC-7529.1._domainContracts
、ERC-7529.11155111._domaincontracts
等。
使用实现此提案的智能合约的用户客户端受到交叉检查两个独立的信息源彼此一致这一事实的保护(即 DNS 和区块链网络)。只要智能合约上的addDomain
和removeDomain
调用经过适当的身份验证(如参考实现中所示),域字段中的值必须由合约的控制器设置。TXT 记录中的合约地址只能由 eTLD+1 域的所有者设置。为了使这两个值对齐,同一组织必须控制这两个资源。
向后兼容性
未发现向后兼容性问题。
参考实现
checkDomain
、addDomain
和removeDomain
的实现是一个简单的练习,但为了完整起见,此处给出了候选实现:
function checkDomain(
string calldata domain
) external view returns (bool) {
return domains[keccak256(abi.encodePacked(domain))];
}
function addDomain(
string memory domain
) external onlyRole(DEFAULT_ADMIN_ROLE) {
domains[keccak256(abi.encodePacked(domain))] = true;
emit AddDomain(domain);
}
function removeDomain(
string memory domain
) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(domains[keccak256(abi.encodePacked(domain))] == true, "ERC7529: eTLD+1 currently not associated with this contract");
domains[keccak256(abi.encodePacked(domain))] = false;
emit RemoveDomain(domain);
}
注意:必须将适当的帐户身份验证应用于addDomain
和removeDomain
,以便只有授权用户才能更新domains
映射。在给定的参考实现中,onlyRole
修饰符用于将调用权限限制为具有DEFAULT_ADMIN_ROLE
的帐户,该帐户可以添加到带有 OpenZeppelin 访问控制抽象类的任何合约。
安全注意事项
由于依赖于传统的 DNS 系统,因此该 ERC 容易受到对此技术的攻击,例如域劫持。此外,智能合约作者有责任确保addDomain
和removeDomain
已正确经过身份验证,否则攻击者可能会将其智能合约与不良域相关联,这只会破坏验证与正确域的关联的能力。
值得注意的是,攻击者要错误地验证合约以对抗域,需要他们同时破坏 DNS 设置和智能合约本身。在这种情况下,攻击者可能还破坏了企业的电子邮件域。
版权
版权及相关权利通过 CC0 放弃。
Citation
Please cite this document as:
Todd Chapman (@tthebc01), Charlie Sibbach <charlie@cwsoftware.com>, Sean Sing (@seansing), "ERC-7529: 合约发现和 eTLD+1 关联 [DRAFT]," Ethereum Improvement Proposals, no. 7529, September 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7529.