Skip to content

Person's usernames: read from Asset Hub dotNS instead of the People Chain (rebase of #349) - #426

Open
filip-parity wants to merge 26 commits into
mainfrom
filip/349-rebase
Open

Person's usernames: read from Asset Hub dotNS instead of the People Chain (rebase of #349)#426
filip-parity wants to merge 26 commits into
mainfrom
filip/349-rebase

Conversation

@filip-parity

@filip-parity filip-parity commented Aug 17, 2026

Copy link
Copy Markdown

TL;DR

Rebase of #349 ("Person's usernames - read from AH dotNS instead of PC", by @Zebedeusz — kept as the first commit) onto main, with the review fixes on top. Tracks #397; the client half of paritytech/individuality#755 and paritytech/dotns#230.


What the host does after this PR

Usernames come from the dotNS contracts on Asset Hub. host_logic::dotns_gateway holds the resolution steps once, over a two-method transport (storage, view = ReviveApi_call dry-run from the always-mapped VIEW_CALL_ORIGIN); the CLI drives it over plain RPC (dotns_read.rs) and the in-core runtime over one chainHead_v1 follow opened with runtime (runtime/identity.rs). Every session-identity site (pairing_host.rs, sso_pairing.rs) resolves against the Asset Hub genesis.

Resolution: DotnsGateway.DispatcherAddressRootGatewayDispatcher.TARGET()DotnsPopControllerpendingClaims(user) (gateway-minted names not yet settled by claimLabelStore) merged with the user's LabelStore labels via protocolRegistry()get(storeFactory)getLabelStore(user) → paged getLabels. Store labels carry the network TLD (protocolRegistry.tld(), .paseo on paseo-next-v2; .dot where the registry has no tld() view, as on previewnet); it is stripped and subnames are dropped. label_available asks DotnsRegistrar.available for a label's node under that TLD. classify_labels re-dots flat lite labels (alice01alice.01, per StringUtils.isSingleDotLiteLabel) and treats the rest as full names. HOST_CLI_DOTNS_POP_CONTROLLER overrides discovery when needed.

register-name (CLI) registers a full-person username through DotnsGateway.register_name: reads the People-collection ring index, members and root revision at one pinned People block, waits for Asset Hub's members-subscriber to hold that revision, then submits a General (v5) extrinsic authorized by AsDotnsGateway = RegisterFullName { proof, ring_index, revision, signature } (shape asserted from metadata before signing) with RestrictOrigins(true); Link::LiteUsername (default: the account's own lite name from dotNS) or Link::None(chat_key). Labels are validated with the pallet's rules ([a-z]+, ≤32 bytes; lite stem.NN) and checked against the registrar up front. signing-host --reserved-username <label> reserves a full-person name for a newly created auto account, after the same label and registrar checks.

Configuration: every host config carries the Asset Hub genesis — PairingHostConfig/SigningHostConfig, NativeRuntimeConfig/NativeHostRuntimeConfig (uniffi, Swift/Kotlin wrappers), wasm runtimeConfig.assetHub.genesisHash (required), JS types. Presets: paseo-next-v2 and previewnet (own People/Bulletin/Asset Hub and identity backend), documented in SPEC §14.1 and pinned by the genesis-table test; HOST_CLI_IDENTITY_BACKEND_BASE/_TOKEN override the backend. statement_allowance ring/root helpers take a collection identifier (LitePeople wrappers unchanged; PGAS and allowance paths untouched).


Verified

  • CI-equivalent locally: cargo build/test --workspace --all-features (812 tests), wasm32 check, fmt, clippy -D warnings, iOS bindings --check, codegen no drift.
  • Live, previewnet: auto-managed onboarding (host reservation signature → identity backend 202 → name visible through dotNS/Asset Hub → ring onboarding → paired); identity-check resolves it; pairing-host ⇄ signing-host SSO with getUserId resolved in-core from Asset Hub.
  • Live, paseo-next-v2: identity-check cold path; ignored live tests for the RegisterFullName shape and for a settled store (TLD stripped, ~90 labels paged); the ignored preset-genesis test passes for all six roles.
  • Reservation message, Link, proof message, DOTNS_GATEWAY_CONTEXT, RegisterFullName and the label rules match pallets/dotns-gateway on paritytech/individuality main; contract selectors and ABI shapes match paritytech/dotns master.

Review pointers

Each commit message carries the rationale for its change; the first commit is #349 as authored.


Known, outside this PR

  • The paseo-next-v2 identity backend answers POST /usernames with "dotNS gateway is not enabled in this environment", so accounts registered through it cannot get a dotNS-readable username; the CLI says so and points at previewnet.
  • hosts/dotli must send runtimeConfig.assetHub.genesisHash (required by the wasm host config) — companion change in dotli-community.
  • claimLabelStore is user-signed from the user's own funded H160 and stays outside the host; pending claims expire after 7 days (dotns side).
  • No mainnet preset until the deploy (dotns#223).

Zebedeusz and others added 8 commits August 17, 2026 11:28
…eo-assethub address

The documented 0x1c858C… value predates the Paseo Asset Hub Next V2 reset;
the live DotnsPopController is 0xCC9323… (paritytech/dotns DEPLOYMENTS.md,
same drift as paritytech/dotns#221). Discovery is on-chain, so this only
touches the env-override docs.
…inst the live gateway

Review findings on #349 after the rebase, verified against the live
paseo-next-v2 and previewnet Asset Hubs (spec 2000036, identical) and the
dotNS contracts on master.

In-core identity lookup
- Open the identity follow withRuntime=true. chainHead_v1_call is refused on
  a follow opened without runtime, so every ReviveApi_call view failed and no
  in-core session ever resolved a username; only the CLI's plain-RPC path
  worked. Adds a scripted chainHead test that fails on the old value.
- LabelStore labels carry the network TLD (DotnsPopController._writeRecord
  appends protocolRegistry.tld(); ".paseo" on paseo-next-v2), and the
  classifier only stripped ".dot", so a settled "alice01.paseo" became the
  full username "alice01.paseo". resolve_labels now reads tld(), strips it,
  and drops subnames; classify_labels takes bare labels.
- Always merge pendingClaims with the store: a public registration or an
  incoming transfer deploys the store while gateway names stay pending, so
  the store alone hid them. Page the store (append-only ledger shared with
  public names) instead of reading only the first 16 labels.
- Probe TARGET() and pendingClaims first; target()/pendingClaim are the
  legacy fallbacks (the deployed dispatcher and controller only have the
  former). checked_add on chain-supplied ABI lengths.
- Lite stems follow StringUtils.isSingleDotLiteLabel (DNS label + two
  digits), not alphabetic-only.

register-name
- AsDotnsGatewayInfo::RegisterFullName is {proof, ring_index, revision,
  signature} on the live runtime (individuality#1013); the shape assertion
  and the extra encoding lacked revision, so the command failed at the
  metadata check. Read the People-collection root revision at the pinned
  block, wait for Asset Hub's members-subscriber to import it, and encode
  it. Ring/root/roots helpers take the collection identifier; the LitePeople
  wrappers keep their behaviour.
- Refresh the Asset Hub metadata fixture to the live V16 (spec 2000036).
- Fail early when the member key is onboarded but not yet built into a root
  (the sliced members read cannot prove it), and validate the label and
  --link-lite shape before signing.
…sets

- Previewnet has a live Bulletin chain (wss://previewnet.substrate.dev/bulletin,
  genesis 0x2778b1c9…, "Bulletin Local"), which dotli and dotns-sdk already
  use; the preset borrowed paseo's, so the host advertised and routed a
  Bulletin genesis that disagreed with the app's config.
- The live drift test accepts "Individuality" for the People role
  (previewnet's People chain calls itself "Individuality Local"); it now
  passes for all six roles.
- SPEC.md: previewnet endpoint table (pinned by the genesis-table test for
  every preset), register-name section, env/override wording; README:
  register-name, previewnet, HOST_CLI_* env vars.
- Doc comments still describing usernames as People-chain
  Resources.Consumers reads now name the dotNS contracts on Asset Hub
  (regenerated Swift bindings and codegen golden follow).
…warm-path reads

Ignored network tests against paseo-next-v2 Asset Hub: the live
AsDotnsGatewayInfo::RegisterFullName shape (4 fields) the host asserts before
signing, and the full dotNS resolution chain (pallet storage → dispatcher
TARGET() → controller → registry → store factory → LabelStore) for an
account with a settled store, proving the TLD is stripped and paging covers
the store. Same rationale as the PGAS live tests: a fixture is a snapshot.
is_person_label in paritytech/individuality (support/src/labels.rs) accepts
lowercase ASCII letters only, no digits or hyphens; the register-name
pre-check now enforces the same instead of a looser DNS-label rule.
The paseo-next-v2 identity backend answers POST /usernames with
"dotNS gateway is not enabled in this environment" (verified live), and
since usernames are now read only from dotNS on Asset Hub, accounts
registered through such a backend can never resolve one. Say so, and point
at the previewnet preset / HOST_CLI_IDENTITY_BACKEND_BASE.
…already minted

Review on #349 (re-gius) and paritytech/dotns#235: the gateway enqueues a
reservation for a reserved_base_label without asking the registrar, so a
reservation over a registered name can never be claimed and holds the whole
stem's reservation queue for the reservation window. The contract-side guard
lands in dotns; the client asks first so an attestation cannot fail as a
whole (and lose the lite name) once that guard exists.

label_available reads DotnsRegistrar.available(uint256(node)) for the label's
node under the network tldNode(), through the same transport as the username
reads. attest() checks the reserved base name (shape per the pallet's
is_valid_person, then availability); register-name checks its label. Live
test on paseo: a minted name reports unavailable, an unminted one available.
…tNS registries

Previewnet's DotnsProtocolRegistry predates the configurable TLD (dotns
b4096968) and has no tld()/tldNode(); its TLD is ".dot". Username reads
of a settled LabelStore and the registrar availability check therefore
reverted there. network_tld() reads tld() and falls back to ".dot" when the
view reverts; the TLD node is derived locally (namehash) instead of read.
Live: settled-store labels and available() resolve on both paseo-next-v2
(".paseo") and previewnet (".dot"). The live tests take LIVE_ASSET_HUB_WS,
LIVE_MINTED_LABEL and LIVE_TLD to point at another network.
main's #431 introduced PersonhoodCollection and made the ring, root and
subscriber-root helpers take it; the branch's identifier-based
generalisation of the same helpers folds into that API. read_member_ring_index
and read_subscriber_ring_exponent take a PersonhoodCollection; register-name
uses PersonhoodCollection::People. ChainState literals carry restrict_origins.
@filip-parity

filip-parity commented Aug 18, 2026

Copy link
Copy Markdown
Author

Testing — done against the live identity backend and live chains (previewnet and paseo-next-v2), not local nodes.

  • previewnet, IB + full lite flow: CLI onboarding of a fresh identity → host reservation signature → POST /usernames 202 → the name is read back from the dotNS contracts on Asset Hub → ring onboarding → paired (fbrbnkbohovy.18; identity-check resolves it).
  • paseo-next-v2, IB: rejects the dotns payload with "dotNS gateway is not enabled in this environment"; the CLI now surfaces that and points at previewnet. That environment cannot be exercised end to end until the backend enables the gateway.
  • In-core path: pairing-host ⇄ signing-host over SSO, getUserId resolved by the core from Asset Hub → WHOAMI fbrbnkbohovy.18.
  • Chain reads, both networks: cold path (identity-check), warm path on a settled LabelStore (TLD stripped, .paseo and legacy .dot, paging), registrar available pre-flight, live RegisterFullName shape, preset genesis drift for all six roles — the #[ignore]d live tests in truapi-host-cli/tests/live_asset_hub.rs (LIVE_ASSET_HUB_WS, LIVE_MINTED_LABEL, LIVE_TLD select the network).
  • Not exercised: an actual register_name submission — it needs a full person and the test identities are lite-only. The encoding is checked against pallets/dotns-gateway on individuality main and the live V16 metadata instead.

CI (Rust workspace, codegen, iOS bindings/swift, TS, playground, explorer, licenses) is green on the current head; the same suite passes locally.


lovely testing evidence available here

… the reserved name reachable

Repo-conventions review of #426.

- discover_pop_controller reads DotnsGateway.DispatcherAddress and the
  dispatcher's TARGET(); pending claims come from pendingClaims(address).
  The target(), pendingClaim(address) and PopControllerAddress fallbacks,
  and the singular pending-claim decoder, are gone: no deployed network
  answers them (live-probed on paseo-next-v2 and previewnet). The ".dot"
  fallback stays: previewnet's registry has no tld() view.
- is_full_person_label now matches the pallet's is_person_label
  ([a-z]+, at most 32 bytes); the earlier commit changed only the messages.
- signing-host takes --reserved-username for a newly created auto account
  (same conflict rules as --lite-username-prefix), so the reserved-name
  pre-flight added for re-gius' review is reachable; live: a minted name
  and a malformed label are refused before the backend is called.
- Comments describe current behaviour only; availability responses are the
  flat map both identity backends serve; backend token env/mint share one
  cell; MemberRingPosition projects only the fields it reads (covered by
  the projection test); read_member_ring_index_at names the pinned read;
  the scripted identity test asserts the H160 argument.
…at the gateway rejects

Findings of the second five-agent verification pass on #426.

- DotnsTransport::view returns DotnsViewError: a contract revert is an
  answer, a transport or decode failure is not. network_tld() falls back to
  ".dot" only on a revert (a registry without tld(), as on previewnet); any
  other failure is an error, since guessing the TLD would drop every label
  carrying the real one and let label_available approve minted names.
- label_available asks DotnsRegistrar.ownerOf: a minted name is taken
  whoever holds it, the escrow included, because the gateway only mints
  fresh ids. classify_labels skips non-ASCII store labels instead of
  panicking. A malformed DispatcherAddress is an error, not "not deployed".
- register-name refuses up front what the gateway extension rejects: an
  account that already holds a DotnsGateway.AccountAlias, and a lite link the
  account does not own per DotnsGateway.LiteLabelOwner. Labels follow the
  PopRules tiers as well as the pallet rule: registrable full names are six
  to thirty-two lowercase letters, reservable base names six to eight;
  --reserved-username is validated before startup.
- The Asset Hub metadata fixture is main's paseo-next-asset-hub-metadata.scale
  (byte-identical). The settled-store live test proves paging. The scripted
  in-core test asserts the exact view sequence, origin and H160 argument.
- Docs: previewnet is the only preset whose identity backend onboards new
  auto accounts today; register-name output lines; HOST_CLI_SIGNER_MNEMONIC
  scope; availability response shape; SigningHostConfig's Asset Hub genesis
  is a parity field.
Comment thread rust/crates/truapi-server/src/host_logic/dotns_gateway.rs
Comment thread rust/crates/truapi-server/src/runtime/identity.rs Outdated
Comment thread rust/crates/truapi-host-cli/src/attestation.rs Outdated
Comment thread rust/crates/truapi-host-cli/src/dotns_read.rs Outdated
Comment thread rust/crates/truapi-host-cli/src/register_name.rs
SessionUiInfo/SessionInfo carry the identity material from #403 next to the
dotNS username fields; the codegen golden and Swift bindings are regenerated.
… harden the CLI reads

Review of #426 by sphamjoli.

- The in-core dotNS lookup has a 45 s budget for the whole walk (best block,
  discovery, contract views, label pages) and 10 s per step, instead of 10 s
  for everything.
- resolve_labels warns when the last label page read was still full, so a
  name past the paged range shows in the logs rather than as "no username".
- Backend access tokens are cached per backend base, so two backends in one
  process never share a token.
- AssetHubReader errors on AccountAlias / LiteLabelOwner values of the wrong
  length instead of treating them as absent, and resolves the controller
  once per reader.
@filip-parity
filip-parity requested a review from sphamjoli August 18, 2026 13:11
Comment thread rust/crates/truapi-server/src/host_logic/dotns_gateway.rs Outdated
Comment thread rust/crates/truapi-server/src/host_logic/dotns_gateway.rs Outdated
Comment thread rust/crates/truapi-server/src/host_logic/dotns_gateway.rs
…e gateway's rule

Review of #426 by re-gius.

- A pending claim older than the controller's reservationDuration is lapsed
  (claimLabelStore skips it, expirePendingClaim sweeps it), so resolve_labels
  reads reservationDuration() and Timestamp.Now at the pinned block and
  drops such entries instead of reporting them as usernames until swept.
- The gateway reserves through PopRules.reserveBaseNameForPop, which has no
  upper length: a reserved base name is any registrable full-person label
  (letters only, six to thirty-two bytes). --reserved-username and the
  attest pre-flight use that rule.
- classify_labels documents the first-letters-only-label heuristic for the
  full username and the DotnsPopController.usernameNodeOf(address) endpoint
  that should replace it.
@filip-parity
filip-parity requested a review from re-gius August 19, 2026 08:02

@re-gius re-gius left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM on the DotNS side

@filip-parity

Copy link
Copy Markdown
Author

@filvecchiato @pgherveou give some love to this pull request pretty please

@filip-parity
filip-parity enabled auto-merge August 19, 2026 10:35
SigningHostConfig::new takes the Asset Hub genesis; the mobile-host SSO
tests from #433 construct it with one.
@TarikGul
TarikGul self-requested a review August 19, 2026 11:54
let platform = get_optional_object(value, "platform", "runtimeConfig.platform")?;
let people = get_required_object(value, "people", "runtimeConfig.people")?;
let bulletin = get_required_object(value, "bulletin", "runtimeConfig.bulletin")?;
let asset_hub = get_required_object(value, "assetHub", "runtimeConfig.assetHub")?;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes assetHub required and dotli only passes people and bulletin, so make dev and make e2e-dotli break on merge. dotli already has getActiveServicesConfig().assethub.genesis, so it's one line there. Could we land that and bump the submodule in this PR? We've bumped it alongside the change that needed it before (#419, #300, #291). Worth doing here because the dotli E2E job is disabled right now, so CI won't tell anyone — the bump is the only thing protecting it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 097ec3b: dotli passes runtimeConfig.assetHub in paritytech/dotli-community#180 (typed as an intersection so it compiles against the released package too), and hosts/dotli here points at that commit, so make dev / make e2e-dotli keep working with the field required.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 097ec3b: dotli passes runtimeConfig.assetHub in paritytech/dotli-community#180 (typed as an intersection so it compiles against the released package too), and hosts/dotli here points at that commit, so make dev / make e2e-dotli keep working with the field required.

match identity.lite_username {
Some(lite) => {
debug!(%lite, "linking the account's own lite username");
Ok(Link::LiteUsername(lite.into_bytes()))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reproduced: a 40-char stem plus two digits classifies fine and comes back as a 43-byte lite username, which is_dotted_lite_username rejects. We apply that check to --link-lite seven lines up but not to this one, and this goes into the signed ring-VRF message, so it's invalid after we've signed it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 097ec3b: the auto-resolved lite username passes the same is_dotted_lite_username check as an explicit --link-lite before it enters the signed message; an unlinkable one fails with a --chat-key hint.

/// Budget for the whole Asset Hub lookup: best block, controller discovery, the
/// contract walk and the label pages of a large store, well over a dozen
/// round trips on one follow.
const LOOKUP_BUDGET: Duration = Duration::from_secs(45);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a per-attempt budget, not an overall one. It's applied inside the retry loop, so it's 45s times IDENTITY_LOOKUP_MAX_ATTEMPTS with no backoff between attempts, and lookup_and_apply runs twice per session, once for the identity account and once for the root key. That puts the worst case around 270s rather than 45, up from 60 before. install_external_session also holds the activation lock across all of it, and its own doc says product frames can only use the session once that future resolves.

Could this be an overall budget instead? Or install the session first and let refresh_current_session_identity fill the username in afterwards?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 097ec3b: the 45 s budget is overall — it bounds the whole resolution of a session (identity account, root fallback, all retries), each step keeps its 10 s operation timeout, and running out of budget installs the session without a username instead of holding activation.

Ok(output) => {
decode_string(&output).map_err(|err| format!("ProtocolRegistry.tld(): {err}"))
}
Err(DotnsViewError::Reverted(_)) => Ok(TLD_WITHOUT_VIEW.to_string()),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc two lines up says guessing the TLD would drop every label carrying the real one, then this guesses .dot on any revert. On .paseo that drops everything and we report a definitive NoRecord.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 097ec3b: the fallback is verified instead of guessed — on a tld() revert, DotnsRegistry.recordExists(namehash("dot")) must hold, otherwise resolution errors naming the problem. Unit-tested for all four outcomes.


let registry_output = transport
.view(controller, call_no_args("protocolRegistry()"))
.await?;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keep answers apart from failures' change only took in tld() and ownerOf(); the other four views use bare ? and From<DotnsViewError> for String flattens it. Since pendingClaims runs first, a revert there kills the warm path too.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 097ec3b: every view in the walk names its call in errors, and a pendingClaims revert is treated as the controller's answer (warn + read the store) rather than the end of the whole resolution; transport failures still abort.

Comment thread rust/crates/truapi-platform/src/lib.rs Outdated
pub people_chain_genesis_hash: [u8; 32],
/// Bulletin-chain genesis hash used for in-core preimage submission.
pub bulletin_chain_genesis_hash: [u8; 32],
/// Asset Hub genesis hash. Not read by the local-signing paths, which take

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This field is never read, every reader goes through PairingHostConfig, and native hosts only build a SigningHostConfig. So iOS, Android and the app repos get a required-field compile break for something with no effect. Option or a default?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 097ec3b: the field is gone — SigningHostConfig, the native records, the wasm signing-host config and the Swift/Kotlin wrappers no longer carry it, so native hosts have no dead required field. The pairing config keeps it; that is the only reader.

/// Reads the ring index `member` is included in for `collection`, from
/// `Members.Members`, pinned to block `at`. Errors when the member has no
/// record. Errors too when the member is not `Included` yet.
pub async fn read_member_ring_index_at(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second reader of Members.Members, hand-rolled keys plus its own projection, while signing_host/ring_vrf.rs keeps the subxt-typed one. That's the #334 convergence item and this adds an instance. They also disagree — one skips a non-Included member, the other errors.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 097ec3b: TODO(#334) on read_member_ring_index_at naming the subxt-typed reader in signing_host/ring_vrf.rs and the Included-vs-error divergence. Left as a comment per the convergence item.

/// Eth-derived accounts — trailing 12 bytes `0xEE` — are implicitly mapped.
/// They need no on-chain state. Views therefore work from this synthetic
/// account on any network.
pub const VIEW_CALL_ORIGIN: [u8; 32] = {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VIEW_CALL_ORIGIN resolves to address(0), the address Solidity guards reject most. Given a revert reads as an answer here, could we use a non-zero eth-derived origin?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 097ec3b: VIEW_CALL_ORIGIN is [0xEE; 32] — still eth-derived (trailing 0xEE, so implicitly mapped) but with the non-zero address 0xEE…EE, so address(0) guards cannot turn into a false 'reverted' answer. Live views on both networks verified with it.

@TarikGul TarikGul left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 blockers, and a few nits, overall looks great

main's #440/#455 brought their own previewnet preset with the post-wipe
genesis hashes; the branch keeps its per-chain endpoint constants and backend
override, updated to those values. The SPEC/README previewnet sections merge
main's wording with the dotNS onboarding note; the 401 caveat does not apply
here, since the CLI mints the backend token itself.
- hosts/dotli passes runtimeConfig.assetHub (dotli-community#180); the
  submodule points at that commit, so make dev and make e2e-dotli keep
  working with the required field.
- The auto-linked lite username passes the same `name.NN` shape check as an
  explicit --link-lite before it enters the signed ring-VRF message.
- The 45 s lookup budget bounds the whole username resolution of a session
  (identity account, root fallback, every retry); each step keeps its 10 s
  operation timeout, and running out of budget installs the session without
  a username instead of blocking activation.
- The ".dot" TLD fallback is verified instead of guessed: on a tld() revert
  the registry must hold the record for namehash("dot")
  (DotnsRegistry.recordExists), or resolution errors.
- Every dotNS view names its call in errors; a pendingClaims revert is the
  controller's answer (warn, read the store) rather than the end of the
  whole resolution.
- SigningHostConfig carries no Asset Hub genesis: nothing reads it there,
  the pairing config is where it drives the dotNS lookup. The field is gone
  from the native records, the wasm signing-host config, and the Swift and
  Kotlin wrappers, so native hosts do not carry a dead required field.
- VIEW_CALL_ORIGIN maps to a non-zero eth-derived address, since Solidity
  guards commonly reject address(0) and a revert is read as an answer.
- TODO(#334) on the second Members.Members reader.
@filip-parity
filip-parity requested a review from TarikGul August 20, 2026 07:51
Carries the runtime-config contract test for assetHub and the deepmerge-ts
audit pin alongside the assetHub field itself.
@TarikGul

Copy link
Copy Markdown
Member

Feel free to ping me when you need a re-review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants