Документация по TON DNS

05.03.2020
категория: Инструкции

Цель этого документа — дать краткое введение в TON DNS, сервис для перевода понятных человеку доменных имен (таких как test.ton илиmysite.temp.ton) в адреса смарт-контрактов TON, адреса ADNL, используемые службами, работающими в сети TON (например, узлами TON) и т. д.

1. Доменные имена

TON DNS использует читабельные доменные имена, состоящие из строки в кодировке UTF-8 длиной до 126 байт, с несколькими секциями доменного имени, разделенными точками (.). Нулевые символы (то есть нулевые байты) и в целом, байты в диапазоне 0..32 не допускаются в доменных именах. Например, test.ton иmysite.temp.ton являются допустимыми доменами TON DNS.
Основное отличие от обычных доменных имен состоит в том, что домены TON DNS чувствительны к регистру; при желании можно преобразовать все домены в нижний регистр перед выполнением поиска TON DNS, чтобы получить нечувствительность к регистру.

В настоящее время только домены, оканчивающиеся на .ton, распознаются как допустимые домены TON DNS. Это может измениться в будущем. Однако обратите внимание, что будет плохой идеей определять домены первого уровня совпадающими с доменами первого уровня, уже существующими в Интернете, такими как .com или.to. Потому что в таком случае можно зарегистрировать
TON-домен google.com, развернуть там сайт TON, создать скрытую ссылку на страницу этого сайта TON со своего другого сайта TON, выглядящего безобидно, и украсть cookie-файлы google.com у ничего не подозревающих посетителей.

TON DNS преобразует доменные имена следующим образом. Во-первых, доменное имя разбивается на компоненты, разделенные символами точки .. Затем к каждому компоненту добавляются нулевые символы, и все компоненты объединяются в обратном порядке. Например, google.com становитсяcom\0google\0.

2. Преобразование доменов TON DNS

Домен TON DNS преобразуется следующим образом. Во-первых, корневой смарт-контракт DNS определяется путем проверки значения параметра конфигурации #4 в последнем состоянии мастер-цепочки. Этот параметр содержит 256-битный адрес корневого смарт-контракта DNS внутри мастер-цепочки.

Затем для корневого смарт-контракта DNS вызывается специальный get-метод dnsresolve (id метода 123660) с двумя параметрами. Первый параметр — это CellSlice с *8n* битами данных, содержащими внутреннее представление запрашиваемого домена, где *n* — длина внутреннего представления в байтах (не более 127). Второй параметр — это 16-разрядное целое число со знаком, содержащее обязательную *категорию*. Если категория равна нулю, то запрашиваются все категории.

Если get-метод завершится неудачно, то поиск TON DNS будет неудачным. В противном случае get-метод возвращает два значения. Первый — *8m*, длина префикса внутреннего представления запрашиваемого домена (в битах), 0 <m <= n. Второй — это ячейка с записью TON DNS для требуемого домена в требуемой категории или корневой словарь с 16-разрядными целочисленными ключами (категориями) со знаком и значениями, равными сериализации соответствующих записей TON DNS. Если домен не дает отклика с корневым смарт-контрактом DNS, то есть, если непустой префикс не является действующим доменом, то возвращается (0, null). Другими словами, m = 0 означает, что поиск TON DNS не нашел данных для требуемого домена. В этом случае поиск TON DNS также не будет успешным.

Если m = n, то вторым компонентом результата является либо ячейка с допустимой записью TON DNS для требуемого домена и категории, либо значение Null, если для этого домена с этой категорией нет записи TON DNS. В любом случае процесс разрешения останавливается, и полученная таким образом запись TON DNS десериализуется и запрашивается информация (например, тип записи и ее параметры, такие как адрес смарт-контракта или адрес ADNL).

Наконец, если m < n, то поиск успешен, но для префикса m-byte исходного внутреннего представления домена доступен только частичный результат. Возвращается самый длинный из всех таких префиксов, известных смарт-контракту DNS. Например, попытка поиска mysite.test.ton (то естьton\0test\0mysite\0 во внутреннем представлении) в корневом смарт-контракте DNS может вернуть 8m = 72, что соответствует префиксу ton\0test\0, то есть поддомен «test.ton» в обычном доменном представлении. В этом случае dnsresolve() возвращает значение для категории -1 для этого префикса независимо от категории, первоначально запрошенной клиентом.

Обусловлено, что категория -1 обычно содержит запись TON DNS типа *dns_next_resolver*, содержащую адрес следующего смарт-контракта резолвера (распознавателя), который может находиться в любой другой рабочей цепочке, например в базовой цепочке. Если это действительно так, процесс разрешения продолжается, выполняя get-метод dnsresolve для следующего резолвера с внутренним представлением доменного имени, содержащим только его часть, до сих пор не преобразованную (если мы искали ton\0test\0mysite\0 и префикс ton\0test\0 был найден в корневом смарт-контракте DNS, то следующий dnsresolve будет вызываться с mysite\0 в качестве первого аргумента).

Затем, либо смарт-контракт следующего резолвера сообщает об ошибке или об отсутствии каких-либо записей для требуемого домена / любого из его префиксов, либо получается окончательный результат, либо возвращается другой префикс и смарт-контракт следующего резолвера. В последнем случае процесс продолжается таким же образом, пока не будет преобразован весь исходный домен.

3. Использование LiteClient и TonLib для преобразования доменов TON DNS

Вышеуказанный процесс может быть вызван автоматически с помощью TON LiteClient или TONLib. Например, можно вызвать команду dnsresolve test.ton 1 в LiteClient, чтобы преобразовать «test.ton» с категорией 1 и получить следующий результат:

> dnsresolve test.ton
...
Result for domain 'test.ton' category 1
raw data: x{AD011B3CBBE404F47FFEF92D0D7894C5C6F215F677732A49E544F16D1E75643D46AB00}

category #1 : (dns_adnl_address adnl_addr:x1B3CBBE404F47FFEF92D0D7894C5C6F215F677732A49E544F16D1E75643D46AB flags:0)
	adnl address 1B3CBBE404F47FFEF92D0D7894C5C6F215F677732A49E544F16D1E75643D46AB = UNTZO7EAT2H77XZFUGXRFGFY3ZBL5TXOMVETZKE6FWR45LEHVDKXAUY

В этом случае запись TON DNS для «test.ton» представляет собой запись dns_adnl_address, содержащую адрес ADNL UNTZO7EAT2H77XZFUGXRFGFY3ZBL5TXOMVETZKE6FWR45LEHVDKXAUY

В качестве альтернативы можно вызвать tonlib-cli и ввести следующую команду:

> dns resolve root test.ton 1
Redirect resolver
...
Done
  test.ton 1 ADNL:untzo7eat2h77xzfugxrfgfy3zbl5txomvetzke6fwr45lehvdkxauy

Это более компактное представление того же результата.

Наконец, если использовать прокси-сервер RLDP-HTTP в клиентском режиме для доступа к TON-сайтам из браузера, как описано в Инструкции по созданию TON Sites, автоматически запускается преобразователь TONLib для преобразования всех доменов, введенных конечным пользователем, так что HTTP-запрос к http://test.ton/testnet/last автоматически перенаправляется на ADNL-адрес untzo7eat2h77xzfugxrfgfy3zbl5txomvetzke6fwr45lehvdkxauy через RLDP.

4. Регистрация новых доменов

Предположим, что у вас есть новый TON сайт с недавно сгенерированным адресом ADNL, например, vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3. Безусловно, конечный пользователь может набрать http://vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3.adnl/, чтобы зайти на ваш TON сайт из браузера с помощью прокси-сервера RLDP-HTTP в режиме клиента, но это не очень удобно. Вместо этого вы можете зарегистрировать новый домен, скажем, mysite.temp.ton с записью dns_adnl_address в категории 1, содержащей адрес ADNL vcq … 25f3 вашего сайта TON. Тогда пользователь сможет получить доступ к вашему сайту, просто набрав mysite.temp.ton в браузере.

Как правило, обычно необходимо связаться с владельцем домена более высокого уровня и попросить его добавить запись для вашего субдомена в смарт-контракт его DNS-резолвера. Тем не менее, TestNet блокчейна TON имеет специальный преобразователь для temp.ton, который позволяет любому автоматически регистрировать любые субдомены temp.ton, которые еще не заняты, при условии, что по этому смарт-контракту выплачивается небольшая плата (в тестовых Граммах). В нашем случае сначала нужно узнать адрес этого смарт-контракта, например, с помощью Lite Client:

> dnsresolve temp.ton -1
...
category #-1 : (dns_next_resolver
  resolver:(addr_std
    anycast:nothing workchain_id:0 address:x190BD756F6C0E7948DC26CB47968323177FB20344F8F9A50918CAF87ECB34B79))
	next resolver 0:190BD756F6C0E7948DC26CB47968323177FB20344F8F9A50918CAF87ECB34B79 = EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN

Мы видим, что адрес этого автоматического DNS смарт-контракта — EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN. Мы можем запустить несколько методов get, чтобы вычислить требуемую цену для регистрации субдомена и узнать период, за который субдомен будет зарегистрирован:

> runmethod EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN getstdperiod
...
arguments:  [ 67418 ] 
result:  [ 700000 ] 
remote result (not to be trusted):  [ 700000 ] 
> runmethod EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN getppr
...
arguments:  [ 109522 ] 
result:  [ 100000000 ] 
remote result (not to be trusted):  [ 100000000 ] 

Мы видим, что субдомены регистрируются в течение 700000 секунд (около восьми дней), и что цена регистрации составляет 100000000ng = 0,1 тестового Грамма на домен, плюс цена за каждый бит и ячейку хранимых данных, которые можно узнать с помощью get-методов getppb иgetppc.

Теперь мы хотим, чтобы этот смарт-контракт зарегистрировал наш поддомен. Чтобы сделать это, мы должны создать специальное сообщение из своего кошелька для автоматического DNS смарт-контракта. Предположим, что у нас есть кошелек my_new_wallet с адресомkQABzslAMKOVwkSkkWfelS1pYSDOSyTcgn0yY_loQvyo_ZgI. Затем мы запускаем следующий скрипт Fift (из подкаталога crypto/smartcont исходного дерева):

fift -s auto-dns.fif <auto-dns-smc-addr> add <my-subdomain> <expire-time> owner <my-wallet-addr> cat 1 adnl <my-site-adnl-address>

Например:

$ fift -s auto-dns.fif EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN add 'mysite' 700000 owner kQABzslAMKOVwkSkkWfelS1pYSDOSyTcgn0yY_loQvyo_ZgI cat 1 adnl vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3
Automatic DNS smart contract address = 0:190bd756f6c0e7948dc26cb47968323177fb20344f8f9a50918caf87ecb34b79 
kQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLef5H
Action: add mysite 1583865040 
Operation code: 0x72656764 
Value: x{2_}
 x{BC000C_}
  x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00}
 x{BFFFF4_}
  x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_}

Internal message body is: x{726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A1_}
 x{2_}
  x{BC000C_}
   x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00}
  x{BFFFF4_}
   x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_}

B5EE9C7241010601007800012F726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A10102012002030105BC000C040105BFFFF4050046AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD0000499FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01070E6337D
Query_id is 6799642071046147647 = 0x5E5D2E700481CE3F 
(Saved to file dns-msg-body.boc)

Мы видим, что тело сообщения для этого запроса было создано и сохранено в файле dns-msg-body.boc. Теперь вам нужно отправить платеж с вашего кошелька kQAB..ZgI на автоматический смарт-контракт EQA..UXN вместе с телом сообщения из файла dns-msg-body.boc, чтобы автоматический смарт-контракт знал, что Вы хотите это сделать. Если ваш кошелек был создан с помощью new-wallet.fif, вы можете просто использовать аргумент командной строки-B для wallet.fif при выполнении этой передачи:

$ fift -s wallet.fif my_new_wallet EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN 1 1.7 -B dns-msg-body.boc
Source wallet address = 0:01cec94030a395c244a49167de952d696120ce4b24dc827d3263f96842fca8fd 
kQABzslAMKOVwkSkkWfelS1pYSDOSyTcgn0yY_loQvyo_ZgI
Loading private key from file my_new_wallet.pk
Transferring GR$1.7 to account kQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLef5H = 0:190bd756f6c0e7948dc26cb47968323177fb20344f8f9a50918caf87ecb34b79 seqno=0x1 bounce=-1 
Body of transfer message is x{726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A1_}
 x{2_}
  x{BC000C_}
   x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00}
  x{BFFFF4_}
   x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_}

signing message: x{0000000103}
 x{62000C85EBAB7B6073CA46E1365A3CB41918BBFD901A27C7CD2848C657C3F659A5BCA32A9F880000000000000000000000000000726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A1_}
  x{2_}
   x{BC000C_}
    x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00}
   x{BFFFF4_}
    x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_}

resulting external message: x{8800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA050E3817FC01F564AECE810B8077D72E3EE15C81392E8B4AE9CDD0D6575821481C996AE8FFBABA0513F131E10E27C006C6544E99D71E0A6AACF7D02C677342B040000000081C_}
 x{62000C85EBAB7B6073CA46E1365A3CB41918BBFD901A27C7CD2848C657C3F659A5BCA32A9F880000000000000000000000000000726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A1_}
  x{2_}
   x{BC000C_}
    x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00}
   x{BFFFF4_}
    x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_}

B5EE9C72410207010001170001CF8800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA050E3817FC01F564AECE810B8077D72E3EE15C81392E8B4AE9CDD0D6575821481C996AE8FFBABA0513F131E10E27C006C6544E99D71E0A6AACF7D02C677342B040000000081C01019762000C85EBAB7B6073CA46E1365A3CB41918BBFD901A27C7CD2848C657C3F659A5BCA32A9F880000000000000000000000000000726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A10202012003040105BC000C050105BFFFF4060046AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD0000499FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01031E3A74C
(Saved to file wallet-query.boc)

Вы должны заменить «1» на правильный порядковый номер вашего кошелька. После того, как вы получите подписанное входящее сообщение в wallet-query.boc, адресованное вашему кошельку и дающее указание передать 1,7 тестовых Граммов в автоматический смарт-контракт вместе с описанием вашего нового домена, который нужно зарегистрировать, вы можете загрузить это сообщение с помощью LiteClient, набрав:

> sendfile wallet-query.boc 
[ 1][t 1][!testnode]	sending query from file wallet-query.boc
[ 3][t 1][!query]	external message status is 1

Если все работает правильно, вам придут некоторые изменения из автоматического смарт-контракта в сообщении-подтверждении (плата будет взиматься только за хранение вашего субдомена, за обработку смарт-контракта и отправку сообщений, а остаток будет возвращен), и ваш новый домен будет зарегистрирован:

> last
...
> dnsresolve mysite.temp.ton 1
...
Result for domain 'mysite.temp.ton' category 1
category #1 : (dns_adnl_address adnl_addr:x45061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD flags:0)
	adnl address 45061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD = vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3

Вы можете изменить или продлить этот домен практически таким же образом, сначала создав запрос в файле dns-msg-body.boc с помощьюauto-dns.fif, используя такие действия, как update или prolong, а затем встроить этот запрос в сообщение из вашего кошелька в автоматический DNS смарт-контракт, используяwallet.fif или аналогичный скрипт с аргументом командной строки -B dns-msg-body.boc.

Все новости о криптовалюте Toncoin и блокчейн-платформе TON в нашем Телеграм канале Новости TON.
9732