crate: kinetic-core stage: 2 reading_time: 15 mins depends_on:
- crate::error::NamesError
- crate::constants::TLD_SUFFIX
- crate::types::infrastructure
What Is This?
This document breaks down the domain name validation module in kinetic-core/src/types/names.rs.
It acts as the foundational authority for all .kin domain name registrations on the network.
Because Kinetic operates as a decentralized, permissionless ecosystem, there is no central authority or human-in-the-loop to review domain applications. Instead, the network relies entirely on deterministic, strictly codified rules running simultaneously on every node.
This file acts as the gatekeeper for the naming system, strictly defining what a valid domain name looks like and how it must be formatted before entering the state machine.
Because these rules are baked directly into the core Rust crate, every peer acts identically. Every peer parses incoming string requests in the exact same way. This ensures that the network state remains perfectly synchronized across thousands of nodes. It achieves this consensus without requiring any external or centralized validation services.
The logic within this module operates entirely statelessly. It does not check the blockchain state to see if a name is already owned or registered. Rather, it exclusively checks the syntactic validity of the requested name. It guarantees that no malformed data, hidden characters, or dangerous system names are ever submitted to the blockchain. By handling this at the lowest level, all higher-level smart contracts can trust the data implicitly.
Why Kinetic Needs This
The necessity of this module comes down to three primary pillars of decentralized network design:
1. State Consistency and Consensus Failures
In a decentralized blockchain architecture, network consensus is extremely fragile.
If two nodes disagree on how to interpret a piece of data, the network forks immediately.
Consider a scenario where a user attempts to register the name EXAMPLE.KIN.
Node A might decide to store the name exactly as written, in full uppercase.
Node B, however, might run a normalization pass and convert it to lowercase example.kin.
If a second user then attempts to register example.kin, the nodes will diverge in their validation.
Node A would allow the registration, thinking it is distinct from the uppercase EXAMPLE.KIN.
Node B would reject it, correctly identifying it as a duplicate registration attempt.
This file completely eliminates that class of fatal consensus bugs.
It forces a unified normalization step before any name is ever processed by the chain.
Every peer that imports the kinetic-core crate will yield the exact same byte string.
This guarantees cryptographic determinism across the entire decentralized network.
2. Defending Against Phishing and Homograph Attacks Decentralized networks and Web3 ecosystems are prime targets for scammers and phishers. If the naming system allowed unrestricted unicode characters, attackers would thrive instantly. Attackers could register domains that look visually identical to popular wallet services. For example, they could replace the standard Latin letter ‘a’ with a Cyrillic ‘a’. This Cyrillic letter has a completely different unicode byte value under the hood. However, it renders identically on a user’s screen in most modern web browsers. This is known in the cybersecurity world as a homograph attack. It is a major vector for wallet draining, phishing, and widespread credential theft.
Important
By strictly enforcing the standard DNS “LDH” rule (Letters, Digits, Hyphens), Kinetic stops this dead in its tracks. The system completely strips out any unicode, emojis, or complex international characters. This dramatically reduces the attack surface for visual spoofing against everyday users. Users can trust that what they see on their screen maps uniquely to a single ledger entry.
3. Infrastructure and System Protection
Traditional operating systems, routers, and network stacks rely heavily on reserved domain names.
Names like localhost, test, or invalid are deeply embedded into the fabric of the web.
They exist in DNS resolvers, web browsers, and local routing configurations.
If a malicious actor on Kinetic could register localhost.kin, the results would be disastrous.
They could trick client applications into routing sensitive traffic improperly across the web.
They could force web wallets or node software to talk to external IP addresses instead of local ones.
Kinetic categorizes these globally understood system names as “Category 1” names.
These are public utility names drawn directly from internet standards like RFC 2606 and RFC 6761.
Warning
By hardcoding a permanent blocklist of these Category 1 names, the network remains safe. It immunizes itself against a massive class of routing exploits and DNS rebinding attacks. Furthermore, the network protects its own future internal architecture by reserving “Category 2” names. Names such as
seed,explorer, anddocsare locked down by the protocol. This prevents opportunistic domain squatters from holding core infrastructure hostnames hostage.
How It Works
The lifecycle of domain name processing in Kinetic flows through a strict, multi-stage pipeline. Every user input string must pass through normalization, validation, and reservation checking.
The Normalization Pipeline
Before a name can be judged, it must be comprehensively cleaned and standardized.
This prevents malicious actors from bypassing security checks using weird formatting tricks.
-> See: kinetic-core/src/types/names.rs — Lines 19 to 28
The normalize_name function executes this critical cleaning process step-by-step:
- Lowercase Conversion: First, it calls
.to_lowercase()on the raw input string. This ensures the entire Kinetic naming ecosystem is completely case-insensitive at the protocol level. - Trailing Dot Removal: Next, it enters a
whileloop that continually pops off trailing dot characters (.). In legacy DNS architecture, a trailing dot signifies the absolute root of the internet. Kinetic strips it away to ensure canonical uniqueness. - Suffix Appending: Finally, the function checks if the cleaned string already ends with the official network TLD. If the user only submitted “mywallet”, it automatically appends the
TLD_SUFFIX. This provides a massive UX benefit for frontend developers, allowing them to submit partial names safely.
The Validation Pipeline
The is_valid_apex_name function is the primary and final gatekeeper for the network.
-> See: kinetic-core/src/types/names.rs — Lines 75 to 124
Step 1: The Suffix Requirement
Before any heavy processing occurs, it explicitly checks if the raw lowercase input ends with the TLD_SUFFIX.
If it does not, it immediately throws an InvalidTLD error.
This early exit ensures users cannot accidentally register .com or .eth domains on Kinetic.
Step 2: Total Length Limits The full string is measured against the strict, standard RFC 1035 length limits. The total length of the domain (including the suffix) cannot exceed 253 characters. Additionally, if the string is completely empty after normalization, it is instantly rejected.
Step 3: Label-by-Label Verification
A standard domain name is made up of individual “labels” separated by dots.
The function splits the normalized string by the . character and iterates through each label.
The length of any single label cannot exceed a maximum of 63 characters.
If a label is totally empty (like in the malformed string my..name.kin), it throws a LabelTooLong error.
Step 4: Character Allowlist (LDH)
The function checks every single character residing within the current label.
It heavily enforces the standard LDH rule: Letters, Digits, Hyphens only.
If a character is not an ASCII lowercase letter, an ASCII digit, or a hyphen, it fails immediately.
It throws an InvalidCharacter error, completely blocking emojis, spaces, underscores, and special symbols.
Step 5: Structural Edge Cases Even with allowed characters, their specific placement within the label heavily matters. A label is strictly forbidden from starting with a hyphen. A label is strictly forbidden from ending with a hyphen. Crucially, a label is also absolutely forbidden from starting with a digit. This specific rule prevents names from being confused with raw IP addresses or backend system flags.
Step 6: Apex Enforcement
The Kinetic protocol currently only supports the registration of apex domains.
Users are not permitted to register subdomains directly at the base protocol level.
The validator extracts the apex of the string using the extract_apex_name helper function.
If the normalized name does not perfectly match the extracted apex, it fails.
The user’s request is safely rejected with a NotAnApexName error message.
Step 7: The Reservation Gauntlet
The final step checks the normalized apex against the restricted reservation lists.
It first calls is_reserved_name to check for collisions with Category 1 locked names.
Then, it queries the external infrastructure module for Category 2 locked names.
If the name hits either list, the validation fails and the transaction is aborted.
Extracting the Apex
To facilitate the apex enforcement rule, the system must isolate the base domain.
-> See: kinetic-core/src/types/names.rs — Lines 126 to 137
The extract_apex_name function takes a fully normalized name string.
It splits it into a standard vector of string slices (Vec<&str>).
If this vector has 2 or more segments, it securely isolates the very last two segments.
It joins them back together with a dot character and returns the newly formed string.
If the vector has less than two segments, it simply returns the string exactly as it is.
Key Pieces
TLD Constant
- Name:
TLD - Type:
&str - Location:
kinetic-core/src/types/names.rs— Line 4 - What it does: Defines the absolute primary top-level domain for the network.
- Why it matters: It acts as the central anchor for all domain-related logic in the crate. Hardcoding it here ensures no other module attempts to guess or reinvent the TLD.
PUBLIC_NAMES Constant Array
- Name:
PUBLIC_NAMES - Type:
&[&str] - Location:
kinetic-core/src/types/names.rs— Lines 45 to 59 - What it does: A statically allocated slice of string slices representing Category 1 reserved names.
- Why it matters: These are globally recognized reserved domains defined by RFC 2606 and RFC 6761. Kinetic locks these names on-chain so internal network operations and Tor hidden services are never compromised.
normalize_name Function
#![allow(unused)]
fn main() {
pub fn normalize_name(name: &str) -> String
}
- Name:
normalize_name - Signature:
pub fn normalize_name(name: &str) -> String - Location:
kinetic-core/src/types/names.rs— Lines 19 to 28 - What it does: Sanitizes messy user input into a canonical
.kinformatted string. - Why it matters: It ensures the complex validation logic only ever deals with perfectly clean data. It returns an owned
Stringbecause it often needs to mutate the data by allocating memory to append the suffix.
is_reserved_name Function
#![allow(unused)]
fn main() {
pub fn is_reserved_name(name: &str) -> bool
}
- Name:
is_reserved_name - Signature:
pub fn is_reserved_name(name: &str) -> bool - Location:
kinetic-core/src/types/names.rs— Lines 34 to 40 - What it does: Checks if a given name collides with the
PUBLIC_NAMESarray. - Why it matters: It acts as an incredibly fast check for Category 1 collisions. It iterates through the array, appends the TLD suffix using a format macro dynamically, and checks for a direct match.
is_valid_apex_name Function
#![allow(unused)]
fn main() {
pub fn is_valid_apex_name(name: &str) -> Result<(), crate::error::NamesError>
}
- Name:
is_valid_apex_name - Signature:
pub fn is_valid_apex_name(name: &str) -> Result<(), crate::error::NamesError> - Location:
kinetic-core/src/types/names.rs— Lines 75 to 124 - What it does: The master security gate and final authority for the naming system.
- Why it matters: It deliberately returns a
Resultinstead of a simple boolean. This allows the Kinetic RPC servers to display highly specific error messages likeNamesError::InvalidCharacterinstead of a generic, unhelpful failure message to the end user.
extract_apex_name Function
#![allow(unused)]
fn main() {
pub fn extract_apex_name(name: &str) -> String
}
- Name:
extract_apex_name - Signature:
pub fn extract_apex_name(name: &str) -> String - Location:
kinetic-core/src/types/names.rs— Lines 126 to 137 - What it does: Strips away arbitrary subdomains to return just the base registered apex string.
- Why it matters: When routing a transaction to
api.wallet.kin, the network needs to accurately resolve the true owner ofwallet.kin. This function provides a robust, fast way to find that base domain every time.
Property-Based Testing
- Location:
kinetic-core/src/types/names.rs— Lines 259 to 281 -> SeeRUST_CONCEPTS.mdfor an explanation ofproptest!. Property tests throw thousands of random, malformed strings at the functions to ensure they never trigger a Rust panic.
How This Connects to the Rest of Kinetic
This module serves as an essential foundational primitive sitting near the very bottom of the dependency graph.
FORWARD DEPENDENCY: crate::error::NamesError
The primary validation function relies intimately on the NamesError enum defined elsewhere.
It returns specific variants like NamesError::InvalidCharacter and NamesError::NotAnApexName.
These rich error variants flow upward through the entire application stack.
They eventually get translated into human-readable JSON responses by the RPC API endpoint.
FORWARD DEPENDENCY: crate::constants::TLD_SUFFIX
Rather than hardcoding the raw string ".kin" inside the validation loop, the module imports TLD_SUFFIX.
This is a highly critical architectural decision for the network’s future.
It means developers can easily spin up private testnets that use a different suffix like ".test".
They can accomplish this by changing one single constant, and all validation automatically adapts without rewrites.
CROSS-CRATE: crate::types::infrastructure::is_infrastructure_name
This particular file handles Category 1 (internet-wide public utility) locked names.
However, it explicitly delegates Category 2 names to the infrastructure module.
Category 2 names are highly specific to Kinetic’s own internal architecture and deployment.
By calling out to the infrastructure module, the naming layer maintains a beautifully clean separation of concerns.
Quick Reference
If you are developing a client application or wallet, you must adhere to these absolute rules:
- Canonical Suffix: The name must fundamentally end with the network suffix.
- Case Sensitivity: Names are totally case-insensitive on-chain; they always process as lowercase.
- Maximum Total Length: The complete domain name cannot ever exceed 253 characters.
- Maximum Label Length: Any single dot-separated segment cannot ever exceed 63 characters.
- Minimum Label Length: A segment cannot be completely empty; consecutive dots will fail.
- Allowed Character Set (LDH):
- Lowercase ASCII letters (
athroughz). - ASCII digits (
0through9). - Hyphens (
-).
- Lowercase ASCII letters (
- Positional Rules:
- A label MUST NOT begin with a hyphen.
- A label MUST NOT end with a hyphen.
- A label MUST NOT begin with a digit (e.g.,
1wallet.kinis rejected).
- Subdomain Restriction: You can only register an apex domain. Third-level domains are heavily blocked.
- Reserved Names List: You cannot register any of the following restricted names:
test,example,invalid,localhost,local,onion,arpa,null,none,zero,corp,lan, orinternal.
Open Questions / Things to Revisit
There are several design limitations that the Kinetic engineering team will need to address over time.
1. Lack of Internationalized Domain Names (IDN) The validation pipeline is locked down to standard ASCII characters. This is the absolute safest choice for a decentralized network launch. It entirely avoids the immensely complex landscape of unicode homograph attacks. However, users globally will demand the ability to register names using non-Latin alphabets. To safely support this feature, the validation logic will need to fully integrate Punycode. This will add significant computational complexity and risk to the validation rules.
2. Second-Level TLD Extraction Vulnerability
The extract_apex_name function blindly grabs the last two string segments of the domain.
This works flawlessly right now under a single-level TLD architecture like .kin.
However, if the network ever supports second-level TLDs (like .co.kin or .gov.kin), it will break.
It would incorrectly identify user.co.kin as being the apex co.kin, destroying routing logic.
If hierarchical TLDs are introduced, this function must be replaced by a Public Suffix List parser.
3. Performance of Normalization Allocations
The normalize_name function is called constantly during network routing and block validation.
Currently, it returns a brand new, heap-allocated String every single time it runs.
In a high-throughput scenario processing thousands of transactions per second, this is a severe bottleneck.
It is highly worth investigating whether this can be optimized using Rust’s Cow<'_, str> type.
This Copy-on-Write pointer would gracefully avoid memory allocations when the input is perfectly formatted.
4. Protocol-Level Subdomain Support
Currently, is_valid_apex_name explicitly blocks the base registration of any subdomains.
If a user owns company.kin, they can configure local routing for blog.company.kin on their own node.
However, they cannot trade blog.company.kin as an independent entity on the distributed ledger.
If Kinetic wants to support granular subdomain leasing, a massive secondary validation path is needed.
This new path would deliberately bypass the apex restriction while still strictly enforcing all other rules.
5. The Concept of Registration Expiration
This entire module deals purely with syntactic validity.
It asks a very simple question: “Is this string formatted correctly according to the rules?”
It does not ask, “Is this name currently active, owned, or expired on the blockchain?”
Passing the is_valid_apex_name check only means the string is syntactically allowed to exist.
State-level checks and database lookups are always required before finalizing any registration transaction.
6. Penalizing Malicious Registration Attempts
The validation logic quickly rejects bad names, but it is currently a free operation.
If a malicious actor spams the network with thousands of invalid name registrations, the nodes must process them.
Should the protocol implement a slashing mechanism or a minimum fee just for submitting a name?
This would prevent denial-of-service attacks aimed specifically at the names.rs validation pipeline.