Skip to content

TEP: 81 - TON DNS 标准

  • TEP: 81
  • 标题: TON DNS 标准
  • 状态: 活跃
  • 类型: 合约接口
  • 作者: EmelyanenkoK, Tolya
  • 创建日期: 2022年6月25日
  • 取代: -
  • 被取代: -

摘要

TON DNS 是一个服务,用于将人类可读的域名(例如 test.tonmysite.temp.ton)转换为 TON 智能合约地址、TON 网络中运行的服务所使用的 ADNL 地址(例如 TON 网站)等。

动机

虽然任何人原则上都可以使用 TON 区块链实现这样的服务,但有一个预定义的服务和众所周知的接口是很有用的,以便在应用程序或服务需要将人类可读的标识符转换为地址时默认使用。

指南

有用的链接

  1. 参考 DNS 智能合约
  2. DNS 拍卖 (源代码)
  3. ton.org 文档
  4. Tolya 关于 TON DNS 的回答 (俄文) - 1, 2, 3

规范

域名

TON DNS 使用熟悉的域名格式,由 UTF-8 编码的字符串 最多 126 字节 组成,不同部分用点(".")分隔。

域名中不允许使用范围 0..32(空字符、控制代码和空格)内的字节。

例如,test.tonmysite.temp.ton 是有效的 TON DNS 域名。

技术上,TON 域名是区分大小写的,但 TON 应用程序和服务在执行 TON DNS 查找之前会将所有域名转换为小写,以实现不区分大小写的效果,因此注册不小写的域名没有意义。

注意,特定的智能合约实现可能在创建子域时施加额外的名称限制(例如,为了避免类似字符以防止钓鱼)。但 dnsresolve get-method 必须支持上述格式的域名。

域名的内部表示

在内部,TON DNS 将域名转换如下。首先,域名被分割成由点字符 . 分隔的组件。然后在每个组件后附加空字符,并将所有组件按逆序连接。例如,google.com 变为 com\0google\0

一级域名

目前,只有以 .ton 结尾的域名被视为有效的 TON DNS 域名。

这在未来可能会改变。然而,定义与互联网中已有的一级域名(如 .com.to)相同的一级域名是个坏主意,因为这可能会导致注册一个 TON 域名 google.com,部署一个 TON 网站,在其其他看似无害的 TON 网站中创建一个隐蔽链接,并从毫无戒心的访问者那里窃取 google.com 的 cookies。

解析 TON DNS 域名

根 DNS

首先,通过检查最近主链状态中的配置参数 #4 的值来定位 根 DNS 智能合约。该参数包含主链中根 DNS 智能合约的 256 位地址。

dnsresolve

Get-method

然后为根 DNS 智能合约调用一个特殊的 get-method dnsresolve,带有两个参数:

  • 第一个参数是一个包含待解析域名内部表示的 CellSlice,其数据位数为 8n,其中 n 是内部表示的字节长度(最多 127 字节)。
  • 第二个参数是一个无符号的 256 位整数,包含所需的 category。通常,category 是字符串的 sha256 哈希值。如果 category 为零,则请求所有类别。

Get-method 结果

Get-method 返回两个值:

  • 第一个是 8m,表示已解析的内部表示域名前缀的长度(以位为单位),0 < m <= n
  • 第二个是包含所需域名和类别的 TON DNS 记录的 Cell,或者是一个包含 256 位无符号整数键(类别)和值等于相应 TON DNS 记录序列化结果的 Dictionary

未解析

如果该 get-method 失败,则 TON DNS 查找不成功。

如果根 DNS 智能合约无法解析该域名,即如果没有非空前缀是智能合约已知的有效域名,则返回 (0, null)

换句话说,m = 0 意味着 TON DNS 查找未找到所需域名的数据。在这种情况下,TON DNS 查找也不成功。

已解析

如果 m = n,则结果的第二个组件要么是包含所需域名和类别的有效 TON DNS 记录的 Cell,要么是 Null,如果该域名没有此类别的 TON DNS 记录。

无论哪种情况,解析过程都会停止,并反序列化获得的 TON DNS 记录,以获取所需的信息(如记录的类型及其参数,如智能合约地址或 ADNL 地址)。

部分解析

最后,如果 m < n,则查找到目前为止是成功的,但只有部分结果可用于原始内部表示域名前缀的 m 字节。

DNS 智能合约返回的前缀是所有已知前缀中最长的。例如,尝试在根 DNS 智能合约中查找 mysite.test.ton(即内部表示中的 ton\0test\0mysite\0)可能返回 8m=72,对应于前缀 ton\0test\0,即通常域名表示中的子域 test.ton

在这种情况下,dnsresolve() 返回类别 sha256("dns_next_resolver") 的值,无论客户端最初请求的类别是什么。按惯例,类别 sha256("dns_next_resolver") 包含类型为 dns_next_resolver 的 TON DNS 记录,包含下一个解析器智能合约的地址(可以驻留在其他工作链中,如基础链)。

如果确实如此,解析过程继续运行下一个解析器的 get-method dnsresolve,域名的内部表示仅包含其尚未解析的部分(如果我们查找 ton\0test\0mysite\0,并且根 DNS 智能合约找到前缀 ton\0test\0,则下一个 dnsresolve 将以 mysite\0 作为第一个参数调用)。

然后,下一个解析器智能合约报告错误或缺少所需域名或其前缀的任何记录,或者获得最终结果,或者返回另一个前缀和下一个解析器智能合约。在后一种情况下,过程以相同方式继续,直到解析完所有原始域名。

请求开头的空字符

请求开头的空字符 \0 表示“自身”。

调用 dnsresolve 方法时带有一个空字符 \0(人类可读形式中的 ".")和类别是正确的。

在这种情况下,DNS 智能合约可以从其 DNS 记录中返回请求的类别。

示例:

dnsresolve("ton\0test\0mysite\0", 1) 在根 DNS 智能合约上调用。

结果是 8m=64,对应于前缀 ton\0test,以及 dns_next_resolver 记录。

dnsresolve("\0mysite\0", 1) 在从 dns_next_resolver 记录中获得的 DNS 智能合约上调用。

结果是 8m=56,对应于前缀 \0mysite,以及 dns_next_resolver 记录。

dnsresolve("\0", 1) 在从 dns_next_resolver 记录中获得的 DNS 智能合约上调用。

结果是 8m=8,对应于 \0 和包含类别 1 的 DNS 记录的 Cell。

在非根 DNS 智能合约上调用 dnsresolve

与在根 DNS 智能合约上调用 dnsresolve 相同,但初始请求必须以空字符开头,以便所有类型的实现都能返回正确的结果。

示例:dnsresolve("\0test\0mysite\0")

注意,这仅对初始请求要求,不适用于递归期间。

DNS 智能合约

实现 TON DNS 标准的智能合约必须包含一个 dnsresolve get-method,按上述方式工作。

DNS 记录

标准类别:

类别 sha256("dns_next_resolver") - DNS 下一个解析器,包含下一个 DNS 解析器的智能合约地址,采用 dns_next_resolver 方案;

类别 sha256("wallet") - TON 钱包,包含智能合约地址,采用 dns_smc_address 方案;

类别 sha256("site") - TON 网站,包含 ADNL 地址,采用 dns_adnl_address 方案;

DNS 记录值的 TL-B 方案:

proto_http#4854 = Protocol;
proto_list_nil$0 = ProtoList;

proto_list_next$1 head:Protocol tail:ProtoList = ProtoList;



cap_is_wallet#2177 = SmcCapability;

cap_list_nil$0 = SmcCapList;
cap_list_next$1 head:SmcCapability tail:SmcCapList = SmcCapList;

dns_smc_address#9fd3 smc_addr:MsgAddressInt flags:(### 8) { flags <= 1 }
  cap_list:flags . 0?SmcCapList = DNSRecord;
dns_next_resolver#ba93 resolver:MsgAddressInt = DNSRecord;
dns_adnl_address#ad01 adnl_addr:bits256 flags:(### 8) { flags <= 1 }
  proto_list:flags . 0?ProtoList = DNSRecord;
dns_storage_address#7473 bag_id:bits256 = DNSRecord;

_ (HashmapE 256 ^DNSRecord) = DNS_RecordSet;

缺点

理由和替代方案

为什么域名如此昂贵?

如果没有最低价格,可能会用几万 TON 买下所有 4 个字母的域名(26^4 = ~457000)。因此,最低价格取决于域名的长度。还需要注意的是,几个月后,所有域名的最低价格将降至 100 TON。

为什么 DNS 拍卖会销毁币?

如果我们不从 DNS 拍卖中销毁币,那么我们需要将钱发送给谁?

为什么只允许 ASCII 域名?

如果我们支持 UTF-8,可能会创建看起来相同但实际上是不同域名的域名(例如 example.ton 和 ехаmрlе.ton)。

为什么有子域解析器?

可以在自定义解析器合约中实现任何子域逻辑。

为什么域名不是永久购买的?

有可能访问拥有域名的钱包的权限会丢失,因此域名将永久丢失。在 TON DNS 中,需要每年通过向合约发送至少 0.005 TON(消息处理的最低 TON 数量)来延长域名。

先前的工作

  1. EIP-137

未解决的问题

未来的可能性

  1. 实现私有(加密)字段

变更日志

  • 2023年12月20日 - 删除了未使用的功能:

    cap_method_seqno#5371 = SmcCapability;
    cap_method_pubkey#71f4 = SmcCapability;
    cap_name#ff name:Text = SmcCapability;