CHIP Number | 0009 |
---|---|
Title | Name Service NFT-based Wallet Address Resolution |
Description | A standard for NFTs to provide resolution of a name into a Chia address |
Author | Right Sexy Orc: Keybase @rightsexyorc |
Editor | Dan Perry |
Comments-URI | CHIP-0009 Comments |
Status | Final |
Category | Informational |
Sub-Category | Guideline |
Created | 2022-10-18 |
Requires | 0007 |
Replaces | None |
Superseded-By | None |
This CHIP provides a method for an NFT to indicate a name that can map, or resolve, to a Chia blockchain address, with an optional expiry block number.
Chia blockchain addresses are long and hard for humans to memorize, communicate and transcribe.
Name services such as Domain Name Service (DNS) and Ethereum Name Service (ENS) are examples of methods for solving this problem for IP addresses and Ethereum blockchain addresses.
This proposal benefits the ecosystem by facilitating transaction creation, as well as Chia adoption by a larger number of humans.
Use cases for this address resolution include helping people communicate their payment address to others using their memory when they don't have their address available, and helping people transcribe their address when communicated verbally. It can also reduce error rates when copied and pasted in a computer manually, by making human verification of the transcription easier.
This proposal has already been implemented by Namesdao and our team has received confirmation by name holders of instances where it helped them communicate a payment address to others, so technical feasibility has been demonstrated and there has been some validation of use cases.
No backwards incompatibilities
We looked to leverage existing patterns and designs when we designed this approach.
We looked especially to the Ethereum Name Service, which also uses an NFT approach.
We also looked to integrate with and leverage the existing primitives and design of the Chia blockchain.
A Chia NFT-based approach would leverage the existing infrastructure built throughout the ecosystem as well as existing primitives such as offers. Various wallets already support transfers and display of NFT's, and various NFT and blockchain explorers already support the standard as well. Additionally, various participants in the Chia community already are owners of NFT's and in many cases, have experience transferring or purchasing NFT's.
As a design decision, and to maintain required data on-chain, we decided to embed the name and expiry block into the metadata URI, and also to use DID-backed NFT's.
We considered exploring DID based possibilities, but there is very limited DID adoption beyond DID-backed NFT's, and no Final status CHIP specification at the time of developing this design.
One objection raised was based on the belief that name resolution required loading of offchain metadata, but that is not the case, since the data is in the NFT's URI itself. Thousands of names have been minted using an initial implementation of this standard. The design's reference implementation has been integrated into the chia-crypto-utils developer toolkit, which is a toolkit used by many wallet developers.
Before resolution, the resolver must prepare the name by applying Nameprep algorithm (RFC 3491), with the exception that underscores are permitted in the name. This limits the octet sequence that makes the name to valid unicode, and provides basic normalization so that names that differ only by case or by the presence of invisible characters are treated as the same name. Similar use of Nameprep is currently present in ENS resolvers.
Names are referenced in lowercase. Primary resolution is performed exclusively using the Chia blockchain.
Each Name Service may have a primary dot extension, e.g. ".xch". If there is no dot extension at the end of the name, the name will be interpreted as having the primary extension of the Name Service. For example, if .xch is the primary extension of the Name Service, then _namesdaotime will reference _namesdaotime.xch.
If a wallet app supports more than one Name Service, it may have an internal lookup mapping dot extensions to Name Services.
A Wallet Address-resolving Name on the Chia blockchain is a NFT1 coin minted using the Name Service's DID. A name record for resolving the Name consists of five to six important values:
1. the NFT coin id (provided per NFT1)
2. The name (required)
3. The expiry block, an integer (optional)
4. The Chia blockchain NFT owner address, per the NFT1 specification (provided per NFT1)
5. Minter DID (per NFT1)
6. The dot extension (optional)
A. To extract the Name and Expiry Block from a Name NFT with the Name Service's Minter DID:
1. Get the second-to-last metadata URI.
2. Remove the .json ending
3. Separate the text following the last "/" and split by the last "-" into two fields.
4. URL-decode the first field to obtain the name.
5. The first field may include up to one dot character ("."). If it does, the characters from the dot onward are the dot extension. If it doesn't, the primary
extension for the Name Service is added, e.g. ".xch".
6. The (optional) expiry block is the second field.
B. The Wallet address for the name is the NFT owner address, per the NFT1 specification (CHIP-0005).
Full node and blockchain explorers should resolve names directly from the blockchain using this technique. Note that CHIP-0005 NFT1 Standard requires that the metadata
URIs return valid metadata matching the hash. The name shall consist of lowercase ASCII characters, excluding whitespace and dots (.). Names are case-insensitive.
Punycode should be used to encode emojis and Unicode characters. The name and the dot extension (without the dot) must be valid normalised labels as described in
UTS46 with the options transitional=false
and useSTD3AsciiRules=true
, with the addition that underscore (_) characters are
acceptable.
The name does not have a maximum length, though a particular Name Service may choose to have a maximum length.
Name Services or third-parties may provide secondary name resolution services that may help an application avoid the need to index all names on the blockchain or have a full copy of the blockchain.
Two techniques can be used for verifying secondary name resolver data, depending on the application.
-
The secondary resolver may supply the NFT coin id, so that a full node wallet can look up the NFT coin quickly and verify the name from its own copy of the blockchain without having to index all names locally. This uses the secondary resolver in a trustless way, though it might not resolve all registered names if not all have been added correctly to the secondary resolver.
-
The secondary resolver may return data that is PGP signed with a public key of the name service or third party secondary resolution service provider. This could be useful for a light wallet, and avoid the risk of man-in-the-middle attacks and domain seizures.
A Secondary Resolution Service should publish its API endpoint(s). A service that supports unlimited or very long length Names may need to make a HTTP POST endpoint available for long Names, not only a HTTP GET endpoint. A Secondary Resolution Service should consider potential support for CDN usage and compressed replies, e.g. gzip.
A Wallet Name Secondary Resolution Service shall return the following required fields: name, address, nft_coin_id, created_block, last_transferred_block, meta_uri, uri, expiry_block
The initial value of last_transferred_block shall be the same as created_block, i.e. before its first transfer. The fields with names ending in "block" list the relevant chia block, an integer value. Meta_uri and uri are the corresponding values from the NFT.
- Test resolving unregistered name
- Test resolving expired name
- Test resolving recently transferred name
- Test resolving newly registered name
Implemented by Namesdao
The following Python3 code demonstrates a simplified version of parsing the name and expiry block from a URI value:
import os
from urllib.parse import unquote
uri = "https://storage2.xchstorage.cyou/namesdao/martian-4468758.json"
name_info = os.path.splitext(os.path.basename(uri))[0].split("-")
expiry_block = name_info[-1]
encoded_name = name_info[-2]
name = unquote(encoded_name)
Additional information is available in Namesdao's NDIP-0002.
A compromise of the Namespace's DID would let an attacker issue new Names. Each Name Service must take measures to secure its DID, as must any DID-backed NFT minter. The potential risk of one Name Service per extension is the dependency of users upon one registrar for the names. In the case of centralized registration issuance, there's a risk that the registry may have issues including even a compromise of its registration key, or government seizure and compromise of the service in the case of a centralized service from a doxxed team. In the case of a Name Service that is decentralized based on a SmartCoin system, there are security risks that the code may have bugs. At the same time, in the case of such compromises the community could potentially choose to migrate to a new registrar for the extension, using a snapshot of the namespace prior to the compromise to re-issue names under a new DID.
Note that Unicode characters can potentially be used to confuse users, such as by using a similar name but with an accent symbol over a vowel. If related services display decoded Punycode characters, they may want to also indicate when a Punycode-decoded name includes non-ASCII characters. A Name Service may also wish to indicate this in its metadata and NFT image.
IETF RFC 1034-3.1: Name space specifications and terminology
IETF RFC 3490: Internationalizing Domain Names in Applications (IDNA)
IETF RFC 3491: Nameprep: A Stringprep Profile for Internationalized Domain Names (IDN)
IETF RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1
IETF RFC 2181: Clarifications to the DNS Specification
IETF RFC 1123: Requirements for Internet Hosts -- Application and Support
EIP-137: Ethereum Domain Name Service - Specification
UTS #46: Unicode IDNA Compatibility Processing
Copyright and related rights waived via CC0.