Skip to content

cyber.domain_contract.md

Alexander Nazarov edited this page Mar 13, 2019 · 2 revisions

Смарт-контракт cyber.domain

Назначение cyber.domain

Cмарт-контракт cyber.domain обеспечивает создание и обработку доменных имен, создание или удаление привязки доменных имен к аккаунтам, создание имен пользователей с привязкой к аккаунту, смену владельцев доменных имен, а также покупку доменных имен на аукционе.

В состав смарт-контракта cyber.domain входят:

  • группа экшен-операций, используемых для покупки доменного имени на аукционе, в том числе: checkwin, biddomain, biddmrefund, newdomain и declarenames;
  • группа внутренних доменных экшен-операций, в том числе: passdomain, linkdomain, unlinkdomain и newusername. Код данных экшен-операций находится в ядре, но их вызов происходит через смарт-контракт;
  • объявления используемых в транзакциях имен.

Требования, предъявляемые к доменным именам

Доменные имена в CyberWay формируются в соответствии с правилами и процедурами Domain Name System (DNS). К структуре доменных имен предъявляются следующие требования:

  • общее количество символов в доменном имени не должно превышать 253 шт.;
  • доменное имя состоит из отдельных частей, разделенных символом «точка»;
  • наличие нахождения рядом двух символов «точка» недопустимо;
  • количество символов в отдельной части доменного имени не должно превышать 63 шт.;
  • допустимыми символами в доменном имени являются буквенно-цифровые, а также символ «дефис»;
  • наличие прописных букв в доменном имени недопустимо;
  • символ «дефис» не должен находиться в начале или конце любой части доменного имени;
  • самая правая часть доменного имени должна содержать хотя бы один буквенный символ. Наличие в ней только цифровых символов недопустимо.

Аукцион доменных имен в смарт-контракте

Экшен-операции checkwin, biddomain, biddmrefund и newdomain используются для покупки доменного имени на аукционе. Процедура покупки доменного имени на аукционе выполняется аналогично процедуре покупки имени аккаунта. В процедуре действуют следующие правила:

  • ставки на покупку любого доменного имени принимаются на аукционе в любой момент;
  • по самой крупной ставке определяется единственное доменное имя, которое может быть выкуплено в настоящий момент;
  • доменное имя считается выкупленным на аукционе, если были выполнены следующие условия:
    • после трансфера ставки на данное доменное имя прошло не более суток;
    • с момента предыдущего выкупа любого доменного имени прошло не менее суток;
  • количество выкупленных доменных имен на аукционе в течение суток должно быть не более одного;
  • по завершении аукциона победителю трансфер не возвращается. Победитель может воспользоваться следующими возможностями:
    • создать самостоятельно доменное имя с использованием операции newdomain и стать его владельцем;
    • владелец доменного имени может создать от него поддоменные имена добавлением к нему слева символа «точка» и части имени (например, владелец домена golos.io может создавать поддомены api.golos.io, ws.golos.io и т.д. Следует заметить, что в отличие от аккаунтов в cyberway, где имена формируются добавлением частей справа, от cyber могут быть образованы cyber.msig, cyber.domain). При этом допускается только прямое наследование доменных имен (например, если владелец создал домен для второго уровня, то создание домена для третьего уровня будет недопустимым).

Примечания:

  • В EOSIO имеются экшен-операции, прописанных непосредственно в ядре. У этой группы экшен-операций часть логики выполняется в ядре, а часть — в смарт-контракте (например, у newaccount создание самого account, обработка данных памяти и выделение ресурсов bandwidth выполняется в ядре). Такое разделение логики дает возможность гибко задавать дополнительные ограничения и обработку без изменения кода ядра, то есть обходиться без проведения хардфорка, ограничиваясь изменениями смарт-контракта. (В дальнейшем необходимо окончательно определиться с местом объявления таких экшен-операций).
  • Экшен-операции смарт-контракта cyber.domain изначально предназначались для распределения доменных имен на основе аукциона. Впоследствии эта группа экшен-операций была дополнена другими, в том числе обеспечивающими такие функции: создание домена, передача домена, привязка/отвязка домена, объявление использованных имен в транзакциях, создание имени пользователя.

Экшен-операция checkwin

Экшен-операция checkwin используется для контроля появления владельца (победителя) доменного имени на аукционе. Данная операция не требует специального вызова и вызывается автоматически с определенной периодичностью.

Экшен-операция checkwin имеет следующий вид:

[[eosio::action]] void checkwin();  

Данная операция не имеет входных параметров. Для ее вызова требуются права контракта cyber.domain.

Экшен-операция biddomain

Экшен-операция biddomain позволяет аккаунту делать ставки на аукционе для покупки доменного имени. Данная операция имеет следующий вид:

[[eosio::action]] void biddomain(
    name bidder,
    domain_name name,
    asset bid
);  

Параметры:
bidder — имя аккаунта, делающего ставку на аукционе на покупку доменного имени;
name — доменное имя (строковое значение в соответствии с требованиями), на которое делается ставка. ;
bid — значение в виде структуры, задающее ставку.

Для выполнение данной экшен-операции требуется, чтобы аккаунт смарт-контракта cyber.domain был наделен правами аккаунта bidder. В случае, если на аукционе появляется ставка с большим значением, осуществляется возврат ставки аккаунту bidder. Возврат выполняется автоматически внутренним вызовом biddmrefund из biddomain.

Экшен-операция biddmrefund

Экшен-операция biddmrefund используется для возврата с аукциона ставки на покупку доменного имени в случае, если для того же доменного имени была сделана ставка с бо́льшим значением. Данная операция имеет вид:

[[eosio::action]] void biddmrefund(
    name bidder,
    domain_name name
);  

Параметры:
bidder — имя аккаунта, которому делается возврат средств с аукциона;
name — доменное имя, на покупку которого была сделана ставка.

В случае возникновения нестандартной ситуации (появление сбоя в сети или ошибки в работе узла) возможен вызов biddmrefund отдельно от вызова biddomain (нестандартный вызов biddmrefund).

Экшен-операция newdomain

Экшен-операция newdomain используется для создания нового доменного имени. Данная операция имеет следующий вид:

[[eosio::action]] void newdomain(
    eosio::name creator,
    domain_name name
);

Параметры:
creator — имя аккаунта, создающего доменное имя;
name — создаваемое доменное имя.

Экшен-операция newdomain может быть выполнена в следующих вариантах:

  • создание доменного имени системным аккаунтом cyber.domain;
  • создание собственного доменного имени победителем аукциона доменных имен;
  • создание суб-доменного имени владельцем прямого родительского домена.

Аккаунт смарт-контракта cyber.domain должен быть привилегированным или иметь разрешения на перевод средств с cyber.namesaccount (в случае возврата средств). По завершении выполнения данной экшен-операции аккаунт creator становится владельцем созданного доменного имени.

Объявления используемых в транзакции имен

Для определения имени пользователя только одного доменного имени недостаточно. Имя пользователя привязывается к аккаунту-владельцу и аккаунту-области (обычно это смарт-контракт) и имеет вид структуры имя@домен. Доменная часть определяет область. В разных областях могут существовать аккаунты с одинаковыми именами. Имеются несколько синтаксисов, поддерживаемых данные username, которые позволяют текстовому представлению имени пользователя сопоставить имя аккаунта.

Ограничения, введенные на значение username
К структуре имени пользователя предъявляются следующие требования:

  • общее количество символов в имени пользователя не должно превышать 32 шт.;
  • имя пользователя может состоять из отдельных частей, разделенных символом «точка»;
  • наличие нахождения рядом двух символов «точка» недопустимо;
  • допустимыми символами в имени пользователя являются буквенно-цифровые, а также символ «дефис»;
  • наличие прописных букв в имени пользователя недопустимо;
  • символ «дефис» не может находиться в начале или в конце имени пользователя.

Объявление declarenames

Объявление declarenames используется для передачи списка структур с информацией об использованных в транзакциях доменных именах (или именах пользователей) и соответствующих им аккаунтам.

[[eosio::action]] void declarenames(
    vector<name_info> domains
);

Параметр:
domains — массив описаний, каждое описание представляет собой структуру name_info.

Объявление declarenames может быть выполнена любым аккаунтом.

Объявление newusername

Объявление newusername используется для создания имени пользователя. При создании имени пользователя используются три поля — creator, owner, name. Объявление newusername имеет следующий вид:

[[eosio::action]] void newusername(
    name creator,
    name owner,
    username name
); 

Параметры:
creator — имя аккаунта, в области которого создается имя пользователя;
owner— имя аккаунта, являющимся владельцем имени пользователя;
name — текстовое представление имени пользователя.

Объявлению newusername передаются списки структур с информацией об использованных именах и соответствующих им аккаунтам. Объявление newusername может быть создано любым аккаунтом.

Выполнение операции newusername транзакция должна быть подписана аккаунтом creator.

Объявление passdomain

Объявление passdomain используется для передачи доменного имени от одного аккаунта другому (для смены владельца доменного имени). Объявление passdomain имеет следующий вид:

[[eosio::action]] void passdomain(
    name from,
    name to,
    domain_name name
); 

Параметры:
from — имя аккаунта, от которого передается доменное имя и который является его владельцем;
to — имя аккаунта, которому передается доменное имя и который будет является его владельцем;
name — строковое представление передаваемого доменного имени.

Для выполнения операции в транзакции требуется подпись аккаунта from — владельца доменного имени.

Объявление linkdomain

Объявление linkdomain используется для привязки доменного имени к имени аккаунта. Объявление linkdomain имеет следующий вид:

[[eosio::action]] void linkdomain(
    name owner,
    name to,
    domain_name name
);

Параметры:
owner — имя аккаунта, от которого удаляется привязка доменного имени и который был его владельцем;
to — имя аккаунта, к которому добавляется привязка доменного имени и который становится его владельцем;
name — строковое представление доменного имени.

Объявление unlinkdomain

Объявление unlinkdomain используется для удаления привязки доменного имени от имени аккаунта. Объявление unlinkdomain имеет следующий вид:

[[eosio::action]] void unlinkdomain(
    name owner,
    domain_name name
);

Параметры:
owner — имя аккаунта, от которого удаляется привязка доменного имени и который был его владельцем;
name — строковое представление доменного имени.

Пример использования объявлений linkdomain и unlinkdomain
Пусть аккаунту, который имеет контракт, присвоено трудно запоминаемое имя ajhgsd23qw.

Для устранения этого недостатка данный аккаунт, используя linkdomain, привязывает доменное имя helloworld к своему контракту.

Пользователям легче запомнить домен @helloworld и отправлять трансфер на это имя, в отличие от трансфера на имя аккаунта ajhgsd23qw. Доменное имя @helloworld будет разрешаться в ajhgsd23qw и в транзакции будет добавлено экшен-операция declarenames с указанием использованных доменных имен.

Для прекращения использования доменного имени @helloworld аккаунт должен вызвать экшен-операцию unlinkdomain. После этого доменное имя @helloworld не будет разрешаться в ajhgsd23qw и, следовательно, отправка трансфера на него будет невозможна.

Аккаунт ajhgsd23qw в своем окружении может также создать себе имя пользователя, например, admin. В этом случае имя admin@@helloworld будет разрешаться в имя ajhgsd23qw. При добавлении доменного имени можно использовать admin@helloworld.

Описание структуры name_info

Структура name_info используется для проверки наличия всех элементов в момент их применения, а также наличия связи доменного имени с указанным аккаунтом. Объявление name_info имеет следующий вид:

struct name_info {
    domain_name domain;
    name account;
    vector<username> users;
};

Параметры:
domain — доменное имя;
account — имя аккаунта, соответствующее доменному имени;
users — список имен пользователей доменного имени.

Объявление declarenames принимает на вход массив структур. Количество принимаемых структур не должно быть нулевым. При попытке отправления пустого массива возникает ошибка.

Для имен пользователей отсутствуют соответствия, так как имя пользователя, в отличие от доменного имени, в течение всего времени не меняет свой аккаунт.

Вводятся следующие дополнительные ограничения:

  • структуры должны быть отсортированы по доменному имени, то есть имена доменов должны располагаться по возрастанию. Исключение составляет для доменного имени, являющегося пустой строкой. Это возможно, когда имя пользователя указывается не на доменном имени, а явно в смарт-контракте. В этом случае сортировка должна быть выполнена по имени аккаунта по полю .account;
  • доменное имя не должно содержать два одинаковых значения .domain, за исключением пустых значений (“”);
  • поле .account в доменном имени не должно содержать пустое значение.

Примечания

  • Вместе с declarenames для внутреннего использования могут присутствовать короткие имена аккаунтов, заменяемые реальные имена аккаунтов. Преобразование внутренних коротких имен в реальные имена аккаунтов выполняется на уровне эксплорера.
  • В настоящей реализации нет проверки, что указанные в declarenames аккаунты существуют в других экшен-операциях. Реализация проверки затруднена, так как непосредственно процесс проверки требует большие ресурсы, затрачиваемые на чтение файла формата ABI и десериализацию действия. Риск отсутствия такой проверки — добавление отправителем транзакции больше информации, чем ее необходимо для проверки. В результате ему нужно будет дополнительно заплатить за излишне используемые ресурсы bandwidth.
  • В настоящей реализации отсутствует информация о позициях используемых доменовских или пользовательских именах.Транзакция может содержать действие с несколькими именами аккаунтов в качестве аргументов, например, someaction( name 1, name 2, name 3, name 4, name 5). В случае, если пользователь отправит действие вида someaction( acc1, one@golos, two@golos, acc1, three@golos) и оно разрешится на том же аккаунте (someaction(acc1, acc1, acc1, acc1, acc3)) , то declarenames будет содержать только используемые имена пользователей или доменные имена. При этом нельзя определить позиции, на которых были использованы имена пользователей, например:
declarenames([{
    domain:"golos",
    account:N(acc1),
    users:["one","two","three"]
}])
  • Реализована поддержка имен вида username@@account (наличие символов «@@» в имени означает, что правая часть — не доменное имя, а имя аккаунта). Например, если транзакция разрешает имена вида alice@@token, bob@@token, admin@@golos.io, то объявление declarenames будет содержать следующие аргументы:
declarenames([
    {domain:"", account:N(golos.io), users:["admin"]},
    {domain:"", account:N(token), users:["alice","bob"]}
])