Docs · The main road
Delegate your TLD once. Change everything after that for free.
Handshake is a root zone. It stores delegation, not content — so a name you own cannot carry a website, a mailbox or a social handle until some nameserver answers for it. Point yours at ours with one on-chain update and every record afterwards is an ordinary DNS edit: instant, unlimited, and costing nothing.
Why it can't be done the old way
The chain stores exactly seven record types — NS,
DS, GLUE4, GLUE6,
SYNTH4, SYNTH6 and TXT. There is
no A, no MX, no CNAME. That is not
a gap in the design; a root zone's job is to delegate.
It is also why you do not want to keep your records on-chain even where you could. Every change is a transaction with a fee, and it does not reach other people's resolvers until the name tree commits — up to about six hours later. Delegation moves that cost to exactly one transaction, once.
The one on-chain step
You publish a resource on your name containing two NS records and nothing else:
{"records": [
{"type": "NS", "ns": "ns1.hns.one."},
{"type": "NS", "ns": "ns2.hns.one."}
]}
Trailing dots as shown. No GLUE4 or GLUE6 —
ns1.hns.one is an ordinary ICANN hostname, so it is out of
bailiwick and resolvers look its address up the normal way. You never
need our IP address to delegate.
Publish the records
In whichever wallet
holds the name — Bob Wallet, an hsd wallet, or your
registrar's record editor. It is an UPDATE covenant.
Wait for the tree
One block (~10 minutes) to confirm, then up to ~6 hours — 36 blocks — before the wider network sees it. An external resolver still showing the old delegation during that window has not failed.
Claim it at the panel
https://app.hns.one/names/. Only the name's holder can set NS on-chain, so the delegation itself is the proof of ownership — there is nothing else for us to check, and we never ask for a key.
If you drive hsd directly
The wallet HTTP API, which is what our own tooling calls:
curl -X POST http://127.0.0.1:12039/wallet/<id>/update \
-H 'content-type: application/json' \
-d '{"name":"yourname",
"data":{"records":[{"type":"NS","ns":"ns1.hns.one."},
{"type":"NS","ns":"ns2.hns.one."}]},
"broadcast":true}'
The equivalent RPC is sendupdate [NAME, RESOURCE]. Either
one spends coin and needs your wallet unlocked.
It is not a merge. If your name already carries a TXT
pointer or a DS record and you send only the two NS
records, those are gone — which for a DS means every
validating resolver starts failing closed on your name. Read the
current resource first, keep what you need, and send the union.
Our own bulk tooling does this by construction and refuses to touch a
name carrying a DS anchor it cannot sign for.
What it costs
| Item | Cost | How we know |
|---|---|---|
The one UPDATE transaction |
~0.03 HNS | ~308 vbytes at hsd's default 100,000 doo/kB. Measured on a real mainnet update: 30,900 doos |
| Every DNS change afterwards | Free | Ordinary zone edits; nothing touches the chain |
| Publishing and re-publishing a site | Free | Control-key publishes are not billed |
| Time to confirm | ~10 minutes | One block |
| Time to be visible everywhere | up to ~6 hours | 36-block tree interval |
Exactly what we can and cannot do once you delegate
- We answer every query at and under your nameThat is
what delegation means.
yourname,www.yourname,alice.yourname— all of it arrives at our nameservers, and your name resolves if and only if we are up. - We can repoint your nameWe hold the zone. Nothing in the protocol stops an operator from changing where a name points. That is the trust you are extending, and it is the honest reason to keep a second operator in your NS set.
- We cannot tamper with your published contentA published site is named by its own hash. We can change which hash your name points at — visibly, in a record you can read — but we cannot alter the bytes behind a hash without the hash changing.
- We cannot touch your name on-chainWe never hold your key. Transfers, renewals and the delegation itself all need it, and the panel has no route that could ask for it.
- We cannot change your apex NS or DSThose live on-chain. The DNS editor refuses them for everyone, including us, with the message that they are changed in your wallet.
What you can edit, and where
The editor is at https://app.hns.one/dns/, with a JSON
API at /api/dns/records, /api/dns/mutate and
/api/dns/pointer. The user-settable types are exactly the
set our nameserver can serve and our signer can sign:
A AAAA CNAME TXT
MX SRV TLSA CAA
NS, and DS only alongside NS.
Limits: 20 records per owner name, 100 per label subtree, owner names ≤ 200 characters, values ≤ 1000 bytes. Addresses must be public unicast — private, CGNAT, loopback and documentation ranges are refused, because "point it at an IP" means one the internet can reach.
Some names are managed by a flow rather than by hand and are shown
read-only: _hns.* and _atproto.*,
OPENPGPKEY and SMIMEA anywhere (those belong
to the mail encryption flow and are an operator-run step, not something
the account panel can do today), and
_443._tcp* TLSA in zones where DANE is enabled
— there, the pin is rewritten on every certificate rollover and a manual
edit would be silently overwritten.
You can also delegate a label under your own name to someone else's
nameservers. Our server answers with a proper referral, and if you supply
a DS alongside the NS we sign it, so the
handoff stays secure.
DNSSEC: who signs what
Delegation makes your name resolve. A DS record makes the
answers provable. The two halves are deliberately split, because only
one of them can be done by someone holding your key.
| Step | Who does it | Detail |
|---|---|---|
| Generate the zone key | HNS.ONE | One ECDSAP256SHA256 key (algorithm 13) per zone, flags 257, kept on the operator machine at mode 0600 |
| Sign the zone | HNS.ONE | RRSIG, DNSKEY and NSEC written to a pre-signed zone file; signatures are valid for 30 days and are re-signed |
| Serve signed answers | HNS.ONE | Our nameserver answers the DO path from that file |
Publish the DS on-chain |
You | We give you the keytag, algorithm, digest type and digest; only the name's holder can commit it |
The record you publish looks like this, alongside your NS records in the same resource:
{"type": "DS", "keyTag": 64223, "algorithm": 13,
"digestType": 2, "digest": "9ebe72e3f4b8...."}
There is one combined signing key per zone, not a KSK/ZSK pair. It is published with the SEP bit set and signs every RRset directly.
A DS on-chain for a key nobody can sign with is worse
than no DNSSEC at all: a validating resolver can prove the answer
should be signed, finds it is not, and returns SERVFAIL. Your name goes
dark for exactly the resolvers that check.
So: delegate first, confirm we are answering, then publish the DS we give you. If you are moving away, remove the DS before you move the NS.
The signatures are verified by the same code that produces them. That
catches implementation mistakes but not a shared misreading of the
spec — both sides would make the same one. Independent validation
(ldns-verify-zone, delv) has not been run
against these zones. Treat the DNSSEC path as unvalidated until it
has.
Signatures also expire on a 30-day cycle and must be regenerated. If that ever lapses, a signed zone fails closed — every name under it stops resolving for validating resolvers.
Verify it landed
Ask our nameserver directly, before and after:
# the delegation, straight from the chain
hsd-cli --api-key="$HSD_NODE_API_KEY" rpc getnameresource '"yourname"'
# what we actually answer for it
dig @ns1.hns.one yourname NS
dig @ns1.hns.one yourname SOA
dig @ns1.hns.one +dnssec yourname DNSKEY
A working delegation answers NOERROR with our two NS
records and a SOA whose primary is ns1.hns.one. Expect exactly the
two NS records and no glue.
Leaving
There is no lock-in mechanism, because there is nothing to lock: we never held your key, and the delegation you published is the only thing pointing the name at us.
Remove the DS first
Publish an updated
resource without the DS record, and wait for the tree to
commit. Skipping this leaves an anchor your new operator cannot sign
for, and validating resolvers fail closed.
Repoint the NS
One more
UPDATE, same cost, naming your own nameservers or another
operator's.
Copy your records across
Read them from
the DNS editor or
GET /api/dns/records and recreate them wherever you are
going.
You can read every record we serve for your name through the editor or the records API, but there is no "download my zone" button and nothing emits a BIND zone file. Moving out today means copying records across by hand or by script. That is a gap, not a policy.
We also do not block or detect-and-stall a departure: when a name stops delegating to us our tooling notices and warns that we are still answering only until resolvers' caches expire.
Honest status
Delegation is not self-service and cannot be. The on-chain update needs your key, which we will never hold, so there is no "delegate" button and no API endpoint that could do it for you. The panel's job starts after the update lands.
Both nameservers are one machine. ns1.hns.one and
ns2.hns.one both resolve to 198.44.116.200. Add a second
operator to your NS set if the name matters.
Every name we serve today is one of our own. The code path for an owner delegating their own TLD to us is implemented and tested, and the detection runs on both planes — but we have no third-party name live on it yet. You would be first.
Zone signing runs on the operator machine, not the edge. A record change made on the public plane serves immediately on the unsigned path and becomes visible to validating resolvers only after the operator drains the signing queue. The queue drainer for tenant publishes is not implemented yet — see Publishing.