/
StarcoinNameService 设计原型

目标

在 Starcoin 上结合 Move 面向资源特性设计出可以实现的、易用的去中心化域名服务

设计思路

一、域名规范

域名应使用 UTF-8 编码,域名的位数应大于 3 位,同时小于 50 位

SNS 将使用固定长度的256位 Hash 存储和解析,可以由域名派生 Hash,并保留层次结构,使用 与 ENS 类似的 Namehash 的方式。

在 namehash 处理前,需要 UTS-46 对名称进行规范化处理。

确保大写和小写的域名等效,并且禁止使用无效字符。

在注册和解析前必须将域名做 UTS-46 处理,才可以使得注册和解析结果统一

UTS-46 规范化

用于 UTS-46 规范化处理可以使用 Js idna-uts46-hx 进行处理

1import uts46 from 'idna-uts46-hx' 2 3console.log(uts46.toAscii('TEST.stc',{useStd3ASCII:true,transitional:false})) 4console.log(uts46.toUnicode('你好STARCOIN.stc',{useStd3ASCII:true,transitional:false})) 5 6//输出 7//test.stc 8//你好starcoin.stc

Namehash 处理

Namehash 的处理是将域名用 . 分割为数块,再将其 Hash 处理

如:“foo.stc” → 分为 foostc ,先计算 0x0000000000000000000000000000000000000000000000000000000000000000 的 hash 再加上 stc 的 hash 再加上 foo 的 hash,最后再进行 hash 处理

1namehash([]) = 0x0000000000000000000000000000000000000000000000000000000000000000 2namehash([label, …]) = keccak256(namehash(…), keccak256(label))

Python 示例

1def namehash(name): 2 if name == '': 3 return '\0' * 32 4 else: 5 label, _, remainder = name.partition('.') 6 return sha3(namehash(remainder) + sha3(label))

Move 示例

1#[test] 2 fun test_hash(){ 3 use StarcoinFramework::Hash; 4 use StarcoinFramework::Vector; 5 6 let node = Vector::empty<u8>(); 7 let i = 0; 8 while(i < 32){ 9 Vector::push_back(&mut node, 0); 10 i = i + 1; 11 }; 12 Vector::append(&mut node ,Hash::keccak_256(b"eth")); 13 node = Hash::keccak_256(node); 14 Vector::append(&mut node ,Hash::keccak_256(b"foo")); 15 node = Hash::keccak_256(node); 16 assert!(node == x"de9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f",1301); 17 }

二、注册表/解析器

当域名被注册,在合约中需要记录这个域名的状态(是否过期,NFT ID)

由于 Move 语言特性,域名有多种实现思路:

在以太坊中的 NFT 可以通过修改 owner 转移所有权,在域名过期后通过 owner 的修改即可转移所有权,但是 Move 中的 NFT 存放在 NFTGallery 中,用户可以将其转移,此时 SNS 合约对 域名 失去了控制,不能将其回收后重新发放给后续此域名注册人,如果 NFT 转移至 NFT 交易市场中,也会存在同样问题,SNS 合约失去了控制

  1. SNS 合约掌握完全控制,可以控制域名的回收。采用合约自定义的 DomainGallery 保存域名 NFT ,并设置 SBT型 NFT 作为域名的 “使用槽“,一个用户只能同时安装一个域名,这个域名带有正向和反向解析。缺点:不能在钱包中显示(解决方案后续讨论),不能使用通用的 NFT 交易市场,需要 SNS 合约实现交易市场功能

  2. SNS 合约不掌控,失效域名不回收。采用通用 NFTGallery 保存,也设置 SBT 型 NFT 作为 “使用槽”,优点是可以在钱包中展示,失效的域名可以由所有者 Burn 可以奖励 Token (注册时除注册费外还需质押一定价值的 Token) 缺点:NFT 域名失效后需要交易市场进行处理(下架、禁止上架、提示失效等),一直保存在 NFTGallery 中。

1) 合约完全控制

每个账户下使用 DomainGallery 保存域名

1struct DomainGallery has key, store{ 2 DomainsName : vector<u8>, 3 Domains : Table::Table<vector<u8>, NFT::NFT<SNSMetaData, SNSBody>> 4}

域名在 放入 SBT ”使用槽“ 时、新建子域名时增加解析记录

ResolverDetails 中保存的 owner 标识当前的 NFT 拥有者,如果域名为子域名该项为 None

mainDomain 保存主域名的 Namehash ,如果域名为主域名该项为 None

1struct Resolvers has key, store{ 2 list : Table::Table<vector<u8>, ResolverDetails> 3} 4 5struct ResolverDetails has store, drop{ 6 owner : Option::Option<address>, 7 mainDomain : Option::Option<vector<u8>> 8}

2) 合约不控制 NFT 的回收

主域名在注册时需要记录过期时间、NFT id

当域名失效后,被他人注册后,注册表中的记录应为最新的 NFT id、过期时间

1struct Registry has key, store{ 2 list : Table::Table<vector<u8>, ResolverDetails> 3} 4 5struct RegistryDetails has store, drop{ 6 Expiration_time : u64, 7 id : u64 8}

域名在 放入 SBT ”使用槽“ 时、新建子域名时增加解析记录

ResolverDetails 中保存的 owner 标识当前的 NFT 拥有者,如果域名为子域名该项为 None

mainDomain 保存主域名的 Namehash ,如果域名为主域名该项为 None

1struct Resolvers has key, store{ 2 list : Table::Table<vector<u8>, ResolverDetails> 3} 4 5struct ResolverDetails has store, drop{ 6 owner : Option::Option<address>, 7 mainDomain : Option::Option<vector<u8>> 8}

三、域名 NFT 结构

需要解析多种地址,包括 STC 地址、ETH 地址、BTC地址、IPFS 等

各种地址用 Table< u8,vector<u8>> 来表示

同时需要支持子域名

1struct SNSMetaData has drop, copy, store { 2 domain_name : vector<u8>, 3 controller : address, 4 create_time : u64, 5 expiration_time : u64, 6} 7 8struct SNSBody has store{ 9 domain : Domain, 10 subDomains : SubDomains 11} 12 13struct Domain has store { 14 stc_address : address, 15 contents : vector<u8>, 16 content : Table::Table<u8, vector<u8>> 17} 18 19struct SubDomains has store{ 20 subDomainsName : vector<u8>, 21 subDomains : Table::Table<vector<u8>, SubDomain> 22} 23 24struct SubDomain has store{ 25 stc_address : address, 26 contents : vector<u8>, 27 content : Table::Table<u8, vector<u8>> 28}