feat(sdk): DotNS registry reads + writes in identity - #293
Merged
Conversation
📦 Bundle size impactComparing
Thresholds — 🟡 ≥10% or ≥5.0 KB · 🟠 ≥20% or ≥15.0 KB (bundled). Percentage only applies once the baseline is ≥ 10 KB. Informational — this check never blocks merge. |
valentinfernandez1
self-requested a review
August 19, 2026 15:46
valentinfernandez1
approved these changes
Aug 19, 2026
valentinfernandez1
left a comment
Collaborator
There was a problem hiding this comment.
Just some small nits but over all LGTM
This was referenced Aug 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #301
Part of #303
Part of #286
Description
Implements the DotNS registry surface in
@parity/product-sdk/identity, replacing the exported-but-throwingresolveDotNs/reverseDotNs/isDotNsAvailablestubs. Everything returnsResult<T, DotNsError>; contract addresses default to the deployed set and are all overridable.Reads.
resolveDotNshashes under the deployment's TLD, readsregistry.ownerandregistry.resolver, thenresolver.addressOfonly when the pointer is the forward resolver. Three outcomes:ok(null)unregistered,ok({ name, owner })registered with no forward address record,ok({ name, owner, address })resolves (H160, not SS58).isDotNsAvailableasksregistrarController.available(label)plusPopRules.classifyName, so a governance-reserved label is not reported as free.reverseDotNscallsreverseResolver.nameOf.Writes return prepared calls the caller submits with their own signer.
setDotNsRecordgives aBatchableCall[]:setResolverfirst when the pointer needs moving, thensetAddress.prepareDotNsRegistrationgives the commit call, secret, timing window, and aprepareRegisterCall()thunk for afterminCommitmentAge(register consumes the commitment, so it cannot be built up front). Priced asmax(priceWithoutCheck(label, owner).price, transferFloor(label, payer, owner)), matching whatregistercharges.The TLD is per network, and read from the chain
The part worth reviewing closely. DotNS fixes its TLD when
DotnsProtocolRegistry.initializeruns, with no setter:.paseoon Paseo Asset Hub Next V2,.doton Previewnet, operator-chosen elsewhere. An earlier revision of this branch hardcoded.dot, so on the SDK's own default chain every name read as unregistered with no error anywhere, because the wrong root yields a node the chain has never written to.The SDK now reads
protocolRegistry.tld()once per runtime and derives the node itself, so one read answers the question andtldNode()is only a cross-check. A deployment older thandotnsb4096968has no getter; there the TLD was a compile-time.dot, so an absent getter falls back to.dotwith a warning. Any other failed read is an error, never a guess.Contract addresses are the opposite: CREATE3-deterministic and identical on every network, verified on both. Hence
PASEO_ASSETHUB_DOTNSbecomesDOTNS_ADDRESSES, since the old name implied a per-network address table that does not exist.Behaviour notes for callers
"TldMismatch", not hashed under ours.alice.dotandalice.paseoare separate registrations that may have different owners, and the identity layer cannot link a name across deployments in either direction, so translating silently could return a stranger's address. The label-to-alias binding is chain-local, and from individuality v0.12.0 the personhood context carries the network suffix, so the alias is per-network too.bob.aliceused to becomebob.alice.dot; it is now refused, since telling it apart fromalice.dotwould need a hardcoded list of every network's TLD. A bare single label still works:alicegivesalice.paseo.alice.42is stored asalice42. Resolvealice42.paseo.namehash(name, tld)requires the root, as do the three name helpers. A default correct on one deployment is the defect this branch fixes.isDotNsAvailableandprepareDotNsRegistrationwere never affected by the rooting bug, but now depend on the TLD read for validation, so a protocol-registry read failure fails a call that previously succeeded.minor. New exports:DotNsTld,dotNsTld,DOT_TLD,stripSuffix,isConsistentDotNsTld, and the"TldMismatch"/"InvalidTld"reasons.Verified against live chains
Unit tests could not have caught any of the three defects fixed here, so both deployments were exercised directly:
.paseo.dot, no getterresolveDotNs("dim2<own>"){ name, owner: 0x4eD4A9b9... }{ name, owner: 0x4eD4A9b9... }resolveDotNs("dim2")bareresolveDotNs("dim2<foreign>")err TldMismatcherr TldMismatchresolveDotNs("nosuchname9x")ok(null)ok(null)The refusals point in opposite directions on the two chains, which is what distinguishes a per-network fix from relocated hardcoding.
142 unit tests, up from 83, each change also checked by reintroducing the defect and confirming the suite goes red (17 such checks, all caught). That mattered: the original bug survived three review passes because
dotns-namehash.test.tsvalidatednamehashagainst a reference implementation that reimplemented the same.dotrooting, so the tests could not have failed. The deterministic live values are pinned in tests (the.paseotldNode, thedim2.paseonode, the content and PoP resolver addresses); owners are not, being mutable state.Not covered: no write was submitted on chain; no name with a forward address record was found, so
ok({ name, owner, address })is unit-test-only;reverseDotNsand lite-person names were not exercised live. There is no automated live test, so nothing here detects rot.Linked issues
Closes #301, "isDotNsAvailable() reports every name as available". Fully resolved. Its ask was "until real resolution lands, make it throw or return a typed error", and this lands the real reads instead, and availability now asksregistrarController.available(label)plusPopRules.classifyNamerather than inferring from a zero resolver. That also covers the aside in dotNS registry surface: the default Asset Hub contract addresses have no code on chain #303, which flagged the same resolver-zero inference.Part of #303, not Closes. The issue is "the default Asset Hub contract addresses have no code on chain". The titled defect is gone: the defaults are now the CREATE3 set dotNS registry surface: the default Asset Hub contract addresses have no code on chain #303 itself names (registry 0xf34054fd…,registrar 0x4f06E818…), verified live on Next V2 and Previewnet. But neither of its two asks is implemented: no gateway walk at runtime, and no startup verification againstDotnsProtocolRegistrythat fails loudly on a mismatch. This PR does read one value from that contract at runtime (the TLD), which is the same direction, so it narrows dotNS registry surface: the default Asset Hub contract addresses have no code on chain #303 without answering it. Leaving it open is the tracking.Part of #286, the personhood and individuality tracking issue. This PR is the dotNS implementation behind two of its sub-issues, so the tracker can follow it from here.Not linked, having checked: #302 is a People-chain
Resources.Consumersread, a different surface in the same file and untouched here; #287, #289, #291 are personhood helpers, ring VRF keys and game helpers.Worth noting that #303 independently corroborates the central finding of this PR before it was made: it records
owner(namehash("dim2.paseo"))as owned on Next V2 andowner(namehash("dim2.dot"))as owned on Previewnet, which is the per-network TLD in one line, measured by someone else on different scripts.