Alert Source Discuss
🚧 Stagnant Standards Track: ERC

ERC-2544: ENS 通配符解析

增加了对 ENS 中子域“通配符”解析的支持。

Authors Nick Johnson (@arachnid), 0age (@0age)
Created 2020-02-28
Discussion Link https://ethereum-magicians.org/t/eip-2544-ens-wildcard-resolution
Requires EIP-137

摘要

以太坊名称服务规范 (EIP-137) 建立了一个两步名称解析流程。首先,ENS 客户端对名称执行 namehash 算法,以确定关联的“节点”,并将该节点提供给 ENS 注册表合约以确定解析器。然后,如果在注册表上为该节点设置了解析器,则客户端将相同的节点提供给解析器合约,该合约将返回关联的地址或其他记录。

按照目前的规范,如果未在给定节点的 ENS 注册表上设置解析器,则此过程终止。 此 EIP 通过在未为域设置解析器时添加一个额外的步骤来更改名称解析过程。 此步骤从名称中删除最左侧的标签,导出新片段的节点,并将该节点提供给 ENS 注册表。 如果为该节点找到了解析器,则客户端将原始的完整节点提供给该解析器合约,以导出相关的记录。 重复此步骤,直到找到带有解析器的节点。

此外,本规范定义了一种使用统一的 resolve() 方法来解析名称的新方法,该方法允许更灵活地处理名称解析。

动机

许多应用程序(如钱包提供商、交易所和 dapps)都表示希望通过共享父域上的自定义子域为其用户颁发 ENS 名称。 但是,这样做的成本对于大型用户群而言目前是令人望而却步的,因为必须在 ENS 注册表上为每个子域设置一个不同的记录。

此外,用户在创建帐户后无法立即使用这些子域,因为必须首先提交用于为子域节点分配解析器的交易并在链上进行挖掘。 这增加了在引导新用户时产生的不必要的摩擦,而巧合的是,他们通常会从 ENS 名称提供的可用性改进中受益匪浅。

启用通配符支持允许设计更高级的解析器,这些解析器可以确定性地生成未分配子域的地址和其他记录。 生成的地址可以映射到反事实合约部署地址(即 CREATE2 地址)、指定的“回退”地址或其他方案。 此外,仍然可以将各个解析器分配给任何给定的子域,这将取代使用父解析器的通配符解析。

EIP-2544 的另一个关键动机是以向后兼容的方式启用通配符解析。 它不需要修改当前的 ENS 注册表合约或任何现有的解析器,并继续支持现有的 ENS 记录——传统的 ENS 客户端将无法解析通配符记录。

规范

本文档中的关键词“必须 (MUST)”、“禁止 (MUST NOT)”、“必需 (REQUIRED)”、“应 (SHALL)”、“不应 (SHALL NOT)”、“应该 (SHOULD)”、“不应该 (SHOULD NOT)”、“推荐 (RECOMMENDED)”、“可以 (MAY)”和“可选 (OPTIONAL)”应按照 RFC 2119 中的描述进行解释。

假设:

  • namehash 是 EIP 137 中定义的算法。
  • dnsencode 是用于编码 RFC1035 第 3.1 节中指定的 DNS 名称的过程,但编码名称的总长度没有限制。 空字符串的编码与名称“.”相同,如单个 0 八位字节。
  • parent 是一个从名称中删除第一个标签的函数(例如,parent('foo.eth') = 'eth')。 parent('tld') 定义为空字符串 ‘‘。
  • ens 是当前网络的 ENS 注册表合约。

符合 EIP-2544 的 ENS 解析器可以实现以下函数接口:

interface ExtendedResolver {
    function resolve(bytes calldata name, bytes calldata data) external view returns(bytes);
}

如果解析器实现了此函数,则当使用接口的 ID 0xTBD 调用 supportsInterface() 时,它必须返回 true。

ENS 客户端将使用要解析的 DNS 编码名称和解析器函数的编码 calldata (如 EIP-137 和其他地方所述)调用 resolve ;如果不支持该函数,则该函数必须返回该函数的有效返回数据,或者恢复原状。

符合 EIP-2544 的 ENS 客户端在确定给定名称的解析器时必须执行以下过程:

  1. 设置 currentname = name
  2. 设置 resolver = ens.resolver(namehash(currentname))
  3. 如果 resolver 不是零地址,则停止并返回 resolver
  4. 如果 name 是空名称(’’ 或 ‘.’),则停止并返回 null。
  5. 否则,设置 currentname = parent(currentname) 并转到 2。

如果上述过程返回 null,则名称解析必须以失败告终。 否则,符合 EIP-2544 的 ENS 客户端在解析记录时必须执行以下过程:

  1. calldata 设置为所需解析函数的 ABI 编码调用数据 - 例如,解析 addr 记录时 addr(namehash(name)) 的 ABI 编码。
  2. 设置 supports2544 = resolver.supportsInterface(0xTBD)
  3. 如果 supports2544 为 true,则设置 result = resolver.resolve(dnsencode(name), calldata)
  4. 否则,将 result 设置为使用 calldata 调用 resolver 的结果。
  5. 使用相应解析函数的返回数据 ABI 解码后返回 result(例如,对于 addr(),将 resolver.resolve() 的结果 ABI 解码为 address)。

请注意,在所有情况下,解析函数(addr() 等)和 resolve 函数都提供原始 name而不是在解析的第一阶段中找到的 currentname

伪代码

function getResolver(name) {
    for(let currentname = name; currentname !== ''; currentname = parent(currentname)) {
        const node = namehash(currentname);
        const resolver = ens.resolver(node);
        if(resolver != '0x0000000000000000000000000000000000000000') {
            return resolver;
        }
    }
    return null;
}

function resolve(name, func, ...args) {
    const resolver = getResolver(name);
    if(resolver === null) {
        return null;
    }
    const supports2544 = resolver.supportsInterface('0xTBD');
    let result;
    if(supports2544) {
        const calldata = resolver[func].encodeFunctionCall(namehash(name), ...args);
        result = resolver.resolve(dnsencode(name), calldata);
        return resolver[func].decodeReturnData(result);
    } else {
        return resolver[func](...args);
    }
}

理由

所提出的实现以最大限度地减少对现有系统的影响的方式支持通配符解析。 它还最大程度地重用现有算法和过程,从而减轻了各种 ENS 客户端的作者和维护者的负担。

它还认识到关于 ENS 通配符解析的可取性的现有共识,通过解决关键的可扩展性障碍,从而能够更广泛地采用原始规范。

虽然为解析器引入了可选的 resolve 函数,但采用未散列的名称和用于解析函数的 calldata 会增加实现的复杂性,但它提供了一种让解析器获取纯文本标签并采取相应措施的方法,这使许多与通配符相关的用例成为可能,否则这些用例是不可能的 - 例如,通配符解析器可以将 id.nifty.eth 解析为某个集合中 id 为 id 的 NFT 的所有者。 如果只有 namehash 可用,这是不可能的。 需求更简单的解析器可以继续直接实现解析函数,并完全省略对 resolve 函数的支持。

DNS 线路格式用于编码名称,因为它允许快速且高气体效率地散列名称,以及其他常见操作,例如获取或删除单个标签; 相比之下,点分隔名称需要迭代名称中的每个字符才能找到分隔符。

向后兼容性

符合 EIP-137 的现有 ENS 客户端将无法解析通配符记录并拒绝与之交互,而符合 EIP-2544 的客户端将继续正确解析或拒绝现有的 ENS 记录。 希望为非通配符用例实现新的 resolve 函数的解析器(例如,解析器直接设置在要解析的名称上)应考虑返回给调用各个解析函数的传统客户端的内容,以实现最大的兼容性。

安全注意事项

虽然兼容的 ENS 客户端将继续拒绝解析没有解析器的记录,但仍然存在配置不正确的客户端会引用不正确的解析器,或者在无法找到解析器时不会拒绝与 null 地址交互的风险。

此外,支持完全任意通配符子域解析的解析器将增加由于键入错误而将资金发送给非预期接收者的可能性。 实现此类解析器的应用程序应考虑根据上下文向客户端提供额外的名称验证,或实施支持资金可恢复性的功能。

还有一种可能性是,某些应用程序可能要求未为某些子域设置解析器。 如果要出现问题,父域将需要成功解析给定的子域节点——据作者所知,目前没有应用程序支持此功能或期望子域不应解析为记录。

版权

通过 CC0 放弃版权及相关权利。

Citation

Please cite this document as:

Nick Johnson (@arachnid), 0age (@0age), "ERC-2544: ENS 通配符解析 [DRAFT]," Ethereum Improvement Proposals, no. 2544, February 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2544.