A TLD is a root identity you own as a singleton. Names live under it. Both are Chialisp covenants a node enforces — no server is asked for permission. names.cat is the auction house and front end, SageX is the wallet, and Nalanda is the pricing profile that decides what a name costs.
This page is the honest version. It keeps enforced by consensus, enforced by our server, and not built in three separate columns — because those three get conflated in every project, and the difference is the entire reason to do this on a chain.
Chialisp covenants. A node refuses a spend that breaks them. All are checked through
brun; the time-and-announcement rules are additionally checked through the
real mempool — the only thing that proves a condition is enforced rather than
merely emitted.
| Puzzle | Mod hash | What it guarantees |
|---|---|---|
namid_tld | 0x4f36d34a… | A root identity. Name, DID and data root ride every generation. lock is monotonic — it can only tighten. |
namid_tld_clawback | 0x1e0e8dab… | Roots get a two-day window on every owner change. |
nalanda_sld | 0xa836f4b3… | A name under a root. PARENT_LAUNCHER is re-curried into every child, so a name can never be re-pointed at another root. |
nalanda_sld_clawback | 0xa1567458… | Names now get the window roots already had. rotate/transfer park the new key; finalize is permissionless after 9216 blocks; cancel is owner-only with no time bound. |
namid_tld_lease | 0xee5b6682… | The lease. Renewal is permissionless — payment is the authorization. close cannot fire early. Live coin: leasetest, testnet11 block 4457033. |
namid_tld_lease_height | 0xc5414464… | The same covenant in blocks (YEAR_BLOCKS = 1683072). Exists because a lease expiry in seconds cannot be compared to a price curve in height. |
nalanda_namespace_registry | 0x64ff1c84… | Namespace pricing as consensus state: register / renew / reopen / rollover / swap_price. |
nalanda_sld_commit | 0x038bcb21… | Commit-reveal. A commit and its reveal cannot land in the same block. |
nalanda_price | 0x414aaf8d… | The curve: length factor, digit factor, VRGDA-lite demand, decaying premium. |
namid_tld_vault | 0x23344fc0… | Passkey (secp256r1) custody with recovery keys. |
Every hash above was recompiled from source when this page was generated and matched what the status document claims. A mod hash that drifts from its source is a museum exhibit, not a pin.
The namespace registry work was mostly about refusing to believe the buyer. Each defence exists because the obvious version of the puzzle would have accepted a number the buyer supplied.
Price depends on length and digits, so the spend reveals the name and the puzzle
measures it itself — strlen plus a byte scan. The caller never states a length.
The premium halves daily, so a later height is cheaper. A claimed height is
sandwiched between ASSERT_HEIGHT_ABSOLUTE now and
ASSERT_BEFORE_HEIGHT_ABSOLUTE now+SLACK: too early and the spend does not
exist yet, too late and it has expired.
PRICE_PUZZLE_HASH pins the curried program, not the mod. The same
nalanda_price mod with PREMIUM_START = 0 gives every name away
and shares its mod hash exactly — so a mod-hash pin would have pinned nothing.
reopen accepts no t0. It rebuilds the lapsed lease's own puzzle
hash from our namespace launcher and the revealed name, then demands that coin's
announcement — rather than accepting either as an argument.
Being explicit about this is the point. Everything on the right is real and tested — and none of it would survive a dishonest registry.
close cannot fire earlyapps/namid)DATA_ROOT) is on chain; the content is served by us and must be checked
against the root by the clientchain_lock.py and
chain_profile.py verify against the chain and report unproven
rather than guessingtld_mailbox is durable, proof-gated and sealed;
the relay carries signalling. Delivery is ours.Running right now, on testnet11.
| Surface | State | Detail |
|---|---|---|
| names.cat | HTTP 200 | /api/health reports 46 names on testnet11. Auction house and web front end. |
| SageX | shipping | Desktop, web and browser extension. Two-phase build → approve → sign. The extension never sees a seed. |
| coturn | verified | TURN relay for name-to-name calls, confirmed with a real allocation — STUN alone cannot cross symmetric NAT. |
| On chain | partial | soultest.nm, didit.nm, leasetest, and 46 registry names —
but only 2 of the 46 are genuinely minted roots. The rest are registry rows awaiting mint. |
The next real milestone is taking money for a name on testnet11, end to end: commit → wait → reveal → pay escrow → register → mint the name coin → lease it. Every piece exists and is tested in isolation. None of it has run as one flow against a live chain.
apps/namid still computes one in Python. Until they are the same number,
the chain is not actually pricing anything.registered;
nothing yet creates the nalanda_sld coin bound to that announcement.
This is the gap that matters most — see the payer binding below.namid_tld_lease to heights everywhere, or declare the seconds lease
legacy. Two flavours is right for now; only one should be issued.In one place, so it cannot be skimmed past.
nalanda_sld_commit announces payer_ph, but nothing in any puzzle can
force the coin that issues the name to assert that announcement. A minting driver
that ignores it reopens the whole front-running hole downstream of a perfectly correct
commitment. This is the one that would actually lose someone a name.
Opening a commit needs no signature — deliberately, so a lost key cannot strand one — so
anyone can copy an opening out of the mempool and spend that coin in their own bundle.
They cannot take the name, but they invalidate the committer's bundle. One fee to attack;
COMMIT_MIN_BLOCKS to recover.
The coin is on chain and somebody funded it. Hiding that needs a different construction than a hash.
MIN_SALT checks length, not entropyThirty-two zero bytes pass. It removes the common footgun, not a determined caller.
namid_tld generations are in circulationPre-lock (0x0a17a0b2…, what soultest.nm carries) and
current (0x4f36d34a…). tld_classify.py knows both and reports
which. Any new reader must do the same, or it misreports half the chain.
PROFILE = "NAL" is a claim, not a proofAny puzzle can curry three bytes, and swap_price can legitimately re-point the
pricing module while the label stays put. chain_profile.py reports
profile_claimed, profile_verified and profile_honest
separately and never collapses them.
Nothing on this page asks to be taken on trust. From the repo root:
# The covenants — 22 suites, brun plus real-mempool gates cd primitives/all-kinds-of-nft/puzzles/ownership-lock for t in test_*.py; do python3 "$t"; done # The registry — 1007 pass, 12 skip cd apps/NalandaX/registry-Backend-artefacts && python3 -m pytest tests/ -q # The four implementations of the price must agree with the vectors bash scripts/nalanda-parity.sh # needs `npm install` in sagex-wallet first # Nothing secret is committed bash scripts/secret-scan-repo.sh
They need .mj_data/registry.json — the registry's live store, which is runtime
state and deliberately untracked. A fresh clone has none, so those tests skip with a reason
naming exactly what is missing. They are not muted: point the tree at a populated store
and they run and pass. Verified in both directions when this repo was split out.
The names.cat deploy scripts used to hold absolute paths into the old w3us-v1
monorepo. That path still exists on this machine, so they did not fail — they built a
deployment bundle out of the old tree. They now resolve the repo root via
/.namid-root and exit non-zero if the marker is missing. If you add a deploy
script, do the same: an absolute path to another checkout is a silent-wrong-source hazard,
not an error.
Where everything lives.