IDotnsPopController

Git Source

Inherits: IDotnsController

Title: IDotnsPopController

Interface for the dedicated PoP controller that issues device names and personhood names on behalf of the dotNS gateway pallet.

Deliberately disjoint from @custom:contract IDotnsRegistrarController. The two controllers coexist on @custom:contract DotnsRegistrar via its multi-controller affordance and neither imports the other. A personhood name collides through the registrar's ERC721 availability check (first-to-mint wins); a device name is not a token, so it collides through

Notes:

  • function: IDotnsRegistry.recordExists at its stem-under-container node (@custom:reverts DeviceNameAlreadyIssued). Reservation queuing for reservedLabel mirrors its live head into PopRules, so a queued base name also blocks the public commit-reveal flow, which reads that slot when it prices a name. Label formats: Device names (the label of @custom:function issueDeviceName and the deviceLabel of a LinkKind.DeviceName link) are a stem of lowercase ASCII letters, a separator, then exactly two digits (e.g. joseph.42) per @custom:function StringUtils.isDeviceLabel. The stem is stricter than a DNS label because the name a person chooses is restricted to letters; a stem short enough to be governance-reserved is rejected by classification, not by the shape. The label is stored in the form the gateway sends, which is the canonical form of the name, so nothing here normalises it. Personhood names (the label of @custom:function issuePersonhoodName and the optional reservedLabel of @custom:function issueDeviceNameWithReservation) are lowercase ASCII letters only, per @custom:function StringUtils.isPersonhoodLabel (e.g. alice). That is the same rule a device-name stem follows and is stricter than a DNS label: no hyphens and no interior digits, because a personhood name is also a name a person chose. A separator marks a device name and is rejected everywhere else, so only the gateway can create a dotted name; a digit suffix on its own is not exclusive, since a public label may carry one directly. Cross-flow priority on the base name is arbitrated by

  • function: IPopRules.reserveBaseNameForPop.

  • security-contact: admin@parity.io

Functions

issueDeviceNameWithReservation

Issues a device name to the supplied user and optionally enqueues a reservation for a personhood name they intend to claim later.

Callable only under a Root origin (otherwise @custom:reverts NotRoot). The issuance validates the stem.NN shape and requires the label to classify outside the governance-reserved tier (otherwise @custom:reverts InvalidDeviceLabel), and rejects a supplied chat key whose length is neither zero nor CHAT_KEY_LENGTH (otherwise @custom:reverts InvalidChatKey). On a warm-path mint (user already has a LabelStore) it @custom:emits DeviceNameIssued and @custom:emits NameRegistered; on a cold-path mint it @custom:emits DeviceNameIssued and

Notes:

  • emits: PendingClaimStashed, with @custom:emits NameRegistered deferred to

  • function: settlePendingClaims when the claim settles. The reservation only runs when reservedLabel is non-empty: it requires a letters-only personhood label (otherwise @custom:reverts InvalidPersonhoodLabel) with no owner on the registrar (otherwise @custom:reverts PersonhoodNameUnavailable), since a name that already has an owner could never be claimed. This validation runs before both the issuance and any queue mutation, so an already-registered reservedLabel aborts the whole call and the candidate receives no device name either; callers should validate the reserved label before attesting rather than relying on this revert. It then advances the head past expired entries (@custom:emits ReservationExpired for each one), removes the user from any prior queue position (@custom:emits ReservationRelinquished) so a single user holds at most one live reservation across all labels, and enqueues a fresh entry (@custom:emits ReservationQueued). The enqueue rejects with @custom:reverts AlreadyReserved when the user already holds a reservation that was not cleared by the prior removal and with @custom:reverts QueueFull when the per-label queue has reached MAX_RESERVATION_QUEUE. Cross-chain callers pass the ABI-encoded tuple as the call's payload, which Solidity decodes directly.

  • struct: DeviceNameIssuanceWithReservation.

function issueDeviceNameWithReservation(DeviceNameIssuanceWithReservation calldata params)
    external;

Parameters

NameTypeDescription
paramsDeviceNameIssuanceWithReservationIssuance and reservation request; see

reservePersonhoodName

Enqueues only a personhood-name reservation for a user.

Callable only under a Root origin (otherwise @custom:reverts NotRoot). This is the second step of the split gateway flow: @custom:function issueDeviceName issues the device name first, then this function reserves the personhood name in a separate transaction so proof-size stays below per-call limits. Reverts with @custom:reverts InvalidPersonhoodLabel when the label is empty, is not lowercase ASCII letters (so a hyphen or any digit rejects it), or is governance-reserved, and with @custom:reverts PersonhoodNameUnavailable when the label already has an owner on the registrar and so could never be claimed. Moving the user out of a prior queue @custom:emits ReservationRelinquished. The caller remains agnostic about backend batching; it simply exposes a small retryable primitive.

function reservePersonhoodName(PersonhoodNameReservation calldata params) external;

Parameters

NameTypeDescription
paramsPersonhoodNameReservationReservation request; see @custom:struct PersonhoodNameReservation.

issueDeviceName

Issues a device name to the supplied user without touching the reservation queue.

Callable only under a Root origin (otherwise @custom:reverts NotRoot). The supplied label must satisfy the stem.NN shape and must classify outside the governance-reserved tier (otherwise @custom:reverts InvalidDeviceLabel); a supplied chat key whose length is neither zero nor CHAT_KEY_LENGTH reverts

Notes:

  • reverts: InvalidChatKey before mint and resolver writes run. A device name that has already been issued reverts @custom:reverts DeviceNameAlreadyIssued. On a warm-path mint

  • emits: DeviceNameIssued and @custom:emits NameRegistered. On a cold-path mint @custom:emits DeviceNameIssued and @custom:emits PendingClaimStashed, with

  • emits: NameRegistered deferred to @custom:function settlePendingClaims when the claim settles. Cross-chain callers pass the ABI-encoded issuance tuple as the call's payload, which Solidity decodes directly.

function issueDeviceName(DeviceNameIssuance calldata params) external;

Parameters

NameTypeDescription
paramsDeviceNameIssuanceIssuance request; see @custom:struct DeviceNameIssuance.

isPopIssued

Whether this controller issued label as a PoP identity.

Keyed by text, so it answers about a name rather than about a node. A device name is issued as a subname (joseph beneath its numeric container 42) and a personhood name as a second-level name, so a caller holding a node must check that the node is the one label resolves to under those rules before reading this answer as being about what it holds; node identity is what names the object. Set at mint and never cleared, so it is unaffected by a name later becoming transferable; the soulbound flag is a transfer rule and cannot stand in for it.

function isPopIssued(string calldata label) external view returns (bool issued);

Parameters

NameTypeDescription
labelstringBare label without the TLD, for example joseph.42.

Returns

NameTypeDescription
issuedboolTrue when this controller issued label.

issuePersonhoodName

Issues a personhood name to the supplied user.

Callable only under a Root origin (otherwise @custom:reverts NotRoot). The label must be a letters-only personhood label (otherwise @custom:reverts InvalidPersonhoodLabel), and must not classify as governance-reserved or as a device-name shape (otherwise

Notes:

  • reverts: InvalidPersonhoodLabel). The gateway also defers to PopRules as the single cross-flow authority: when PopRules carries a live base-name slot held by another user (this controller's prior queue head, or a sibling controller's write), the call reverts

  • reverts: NotHolder before any queue mutation. Two orthogonal axes drive the state machine. The reservation axis treats the user as claiming if and only if they hold the live head-of-queue reservation on the label: a claim wipes the entire queue (@custom:emits ReservationEvicted for every other waiter), releases the PopRules slot, and

  • emits: ReservationClaimed; a non-claim drops any pending entry the user holds (@custom:emits ReservationRelinquished). Either way the issuance

  • emits: PersonhoodNameIssued. Advancing the queue head past expired entries

  • emits: ReservationExpired for each one. The chat-key axis selects whether a fresh key is persisted on the resolver or the new entry inherits its key from a prior device name. The fresh-key branch rejects a chat key whose length is neither zero nor CHAT_KEY_LENGTH (otherwise @custom:reverts InvalidChatKey). The DeviceName branch validates the device name's stem.NN shape (otherwise @custom:reverts InvalidDeviceLabel), requires the registrant to own the device name in the registry (otherwise

  • reverts: DeviceNameNotOwned), reads its chat key from the resolver and copies it across; if the device name carries no chat key the inherited value is empty and the personhood name's chat-key write is silently skipped (the DeviceNameLinked event still fires). @custom:emits DeviceNameLinked alongside the issuance event. On a warm-path mint the event order is @custom:emits NameRegistered first (from the inner mint), then

  • emits: PersonhoodNameIssued, then @custom:emits DeviceNameLinked when applicable. On a cold-path mint @custom:emits PendingClaimStashed replaces the initial

  • emits: NameRegistered; the deferred @custom:emits NameRegistered fires later from

  • function: settlePendingClaims. Cross-chain callers pass the ABI-encoded issuance tuple as the call's payload, which Solidity decodes directly.

function issuePersonhoodName(PersonhoodNameIssuance calldata params) external;

Parameters

NameTypeDescription
paramsPersonhoodNameIssuanceIssuance request; see @custom:struct PersonhoodNameIssuance.

expireReservation

Permissionlessly removes expired entries from the head of a reservation queue.

Permissionless on purpose: anyone (typically a UI or a bot) can poke a stale queue so the next live head takes over without waiting for the next gateway call. Validates label as a letters-only personhood label (otherwise @custom:reverts InvalidPersonhoodLabel) and @custom:emits ReservationExpired for every expired entry reaped from the head. A label carrying a digit or a hyphen is not a personhood label and

Note: reverts: InvalidPersonhoodLabel, as does a device name, since a separator is not one either. Only a letters-only label reaches the queue, and one that was never reserved resolves to an empty queue so the call is a no-op.

function expireReservation(string calldata label) external;

Parameters

NameTypeDescription
labelstringPersonhood name whose queue is reaped.

relinquishReservation

Lets the caller voluntarily drop their own active reservation.

Reverts with @custom:reverts NoActiveReservation when the caller holds no live reservation. On success the caller's entry is removed from its queue and

Note: emits: ReservationRelinquished is emitted; if the removed entry was the queue head, head advancement may additionally @custom:emits ReservationExpired for any stale entries reaped behind it.

function relinquishReservation() external;

isReservedForClaim

Returns whether a label currently has a live reservation at the queue head.

Validates label as a letters-only personhood label (otherwise

Note: reverts: InvalidPersonhoodLabel) before inspecting the queue.

function isReservedForClaim(string calldata label)
    external
    view
    returns (bool reserved, address holder);

Parameters

NameTypeDescription
labelstringPersonhood name whose queue is inspected.

setReservationDuration

Updates the reservation duration used to decide when queue entries expire.

Owner-gated (otherwise @custom:reverts OwnableUnauthorizedAccount); emits

Note: emits: ReservationDurationSet on success.

function setReservationDuration(uint64 duration) external;

reservationMeta

Returns the queue metadata (head, tail) for labelhash.

Read-only accessor over the per-label reservation queue. head == tail means the queue is empty; active entries occupy [head, tail). Exposed on the interface because invariant tests and off-chain consumers use it to enumerate live queue state without scanning storage.

function reservationMeta(bytes32 labelhash) external view returns (uint64 head, uint64 tail);

Parameters

NameTypeDescription
labelhashbytes32Keccak-256 of the personhood name whose queue is being read.

Returns

NameTypeDescription
headuint64Index of the live queue head.
tailuint64Index one past the last queued entry.

reservationEntry

Returns the queue entry at index for labelhash.

Sparse storage: a zero entryOwner means the slot was relinquished, expired and reaped, or never written. Callers pair this with @custom:function reservationMeta to walk the live window [head, tail).

function reservationEntry(
    bytes32 labelhash,
    uint64 index
)
    external
    view
    returns (address entryOwner, uint64 joinedAt);

Parameters

NameTypeDescription
labelhashbytes32Keccak-256 of the personhood name whose queue is being read.
indexuint64Queue index to look up.

Returns

NameTypeDescription
entryOwneraddressOwner of the slot (zero if empty/relinquished).
joinedAtuint64Timestamp the entry was enqueued (only meaningful when entryOwner != address(0)).

userReservation

Returns user's current reservation pointer.

A zero labelhash on the returned struct means the user holds no reservation; index is meaningful only when labelhash is non-zero.

function userReservation(address user)
    external
    view
    returns (UserReservation memory reservation);

Parameters

NameTypeDescription
useraddressAccount whose reservation pointer is being read.

Returns

NameTypeDescription
reservationUserReservationPer-user reservation pointer; see @custom:struct UserReservation.

reservedLabelOf

Returns the personhood name a reservation queue is keyed under.

Reverse lookup from the bytes32 queue key to its label string, so a consumer that observed a queue by labelhash (for example from a reservation event) can recover the human-readable label without holding its preimage. Returns an empty string when no reservation was ever enqueued under labelhash.

function reservedLabelOf(bytes32 labelhash) external view returns (string memory label);

Parameters

NameTypeDescription
labelhashbytes32Keccak-256 of the personhood name.

Returns

NameTypeDescription
labelstringThe personhood name, or empty when unknown.

reservationDuration

Returns the window, in seconds, after which a reservation-queue entry lapses.

Governance-configurable via @custom:function setReservationDuration. Pending claims do not lapse.

function reservationDuration() external view returns (uint64 duration);

Returns

NameTypeDescription
durationuint64Reservation duration in seconds.

settlePendingClaims

Settles up to limit of a user's pending claims, writing each stashed label into the user's LabelStore and deploying that store when the user has none yet.

Permissionless: any caller may settle any user's claims and bears the full cost, including the LabelStore storage deposit, which is charged to the transaction signer. Settlement is never destructive: the name is already minted, so this only completes the deferred label write. Each settled entry is removed from the queue and the user leaves the pending-claim enumeration set once their queue empties. At most limit entries are processed so a large queue cannot exceed the block gas limit; moreRemaining reports whether entries are left for a follow-up call, and a limit of zero settles nothing. Writes are idempotent on an already-locked store slot, so a claim whose label was independently written settles harmlessly. Emits

Note: emits: PendingClaimSettled and @custom:emits NameRegistered per settled entry, with settledBy set to the caller so a third-party settlement is distinguishable from a self-settlement.

function settlePendingClaims(
    address user,
    uint256 limit
)
    external
    returns (uint256 settledCount, bool moreRemaining);

Parameters

NameTypeDescription
useraddressAccount whose pending claims are settled.
limituint256Maximum number of entries to settle in this call.

Returns

NameTypeDescription
settledCountuint256Number of entries settled.
moreRemainingboolWhether the user still holds unsettled entries.

claimLabelStore

Settles the caller's own pending claims into their LabelStore.

Convenience for a user settling their own store: equivalent to

Notes:

  • function: settlePendingClaims with msg.sender and a bounded batch. The caller deploys and pays for their store on the first write. Settles at most one bounded batch so the call cannot exceed the block gas limit; moreRemaining reports whether the caller still holds unsettled entries, in which case they call again. Emits the same

  • emits: PendingClaimSettled and @custom:emits NameRegistered as

  • function: settlePendingClaims.

function claimLabelStore() external returns (bool moreRemaining);

Returns

NameTypeDescription
moreRemainingboolWhether the caller still holds unsettled entries.

pendingClaims

Returns a paginated slice of a user's pending claims in queue order.

An empty array means the user has no pending claims at offset. Each entry carries its mintedAt, and every entry stays settleable whatever its age. An offset past the end returns an empty array rather than reverting, and a page holds at most DotnsConstants.MAX_PAGE_SIZE entries.

function pendingClaims(
    address user,
    uint256 offset,
    uint256 limit
)
    external
    view
    returns (PendingClaim[] memory claims);

Parameters

NameTypeDescription
useraddressAccount whose pending claims are read.
offsetuint256Start index into the queue.
limituint256Maximum entries to return.

Returns

NameTypeDescription
claimsPendingClaim[]Page of the user's pending claims; see @custom:struct PendingClaim.

pendingClaimCountOf

Returns the number of pending claims currently staged for user.

function pendingClaimCountOf(address user) external view returns (uint256 count);

Parameters

NameTypeDescription
useraddressAccount whose pending claims are counted.

Returns

NameTypeDescription
countuint256Number of staged pending claims.

pendingClaimUserCount

Returns the number of users with at least one live pending claim.

Exact live count, not an all-time tally: fully settled users are removed from the enumeration set so off-chain consumers can page through every stalled user without filtering.

function pendingClaimUserCount() external view returns (uint256 count);

Returns

NameTypeDescription
countuint256Number of users currently holding a pending claim.

pendingClaimUsers

Returns a paginated slice of users with at least one live pending claim.

Pair with @custom:function pendingClaims to read each user's stashed entries. Ordering is not chronological; callers MUST NOT assume mintedAt is monotonic across the slice. Returns an empty array when offset is past the live count, and a page holds at most DotnsConstants.MAX_PAGE_SIZE entries.

function pendingClaimUsers(
    uint256 offset,
    uint256 limit
)
    external
    view
    returns (address[] memory users);

Parameters

NameTypeDescription
offsetuint256Start index.
limituint256Maximum entries to return.

Returns

NameTypeDescription
usersaddress[]Slice of users currently holding a pending claim.

Events

DeviceNameIssued

Emitted when the gateway pallet issues a device name.

event DeviceNameIssued(bytes32 indexed labelhash, address indexed user, string label);

PersonhoodNameIssued

Emitted when the gateway pallet issues a personhood name.

Fires whether or not the user held a reservation for it; a claim of the live reservation also @custom:emits ReservationClaimed.

event PersonhoodNameIssued(bytes32 indexed labelhash, address indexed user, string label);

ReservationQueued

Emitted when a reservation entry is added to the queue for a personhood name.

event ReservationQueued(
    bytes32 indexed reservedLabelhash, address indexed user, uint64 position
);

Parameters

NameTypeDescription
reservedLabelhashbytes32
useraddress
positionuint64Position in the queue at the time of joining (0 = active holder).

ReservationExpired

Emitted when a reservation entry is removed due to expiry.

event ReservationExpired(bytes32 indexed reservedLabelhash, address indexed user);

ReservationRelinquished

Emitted when a user's own reservation entry is dropped: an explicit relinquish, a standalone personhood-name issuance, or a re-reservation that moves the user to another queue.

event ReservationRelinquished(bytes32 indexed reservedLabelhash, address indexed user);

ReservationClaimed

Emitted when the holder of a queue's live head claims the reserved name.

event ReservationClaimed(bytes32 indexed reservedLabelhash, address indexed user);

ReservationEvicted

Emitted for each waiter removed from a queue when its head is claimed.

event ReservationEvicted(bytes32 indexed reservedLabelhash, address indexed user);

DeviceNameLinked

Emitted when a personhood name is linked to a device name.

event DeviceNameLinked(bytes32 indexed personhoodLabelhash, bytes32 indexed deviceLabelhash);

ReservationDurationSet

Emitted when the reservation duration is updated.

event ReservationDurationSet(uint64 duration);

NameRegistered

Emitted when a name is successfully registered via the PoP controller.

event NameRegistered(
    string indexed label, bytes32 indexed labelhash, address indexed owner, address store
);

Parameters

NameTypeDescription
labelstring
labelhashbytes32
owneraddress
storeaddressThe Store instance used to persist the immutable registration record.

PendingClaimStashed

Emitted when a gateway-path mint defers its LabelStore write into the pending-claim mapping because the user has no store yet.

event PendingClaimStashed(address indexed user, bytes32 indexed labelhash, string label);

PendingClaimSettled

Emitted when a pending claim is written into a LabelStore.

Fires once per settled entry from @custom:function settlePendingClaims. settledBy is the caller: it equals user for a self-settlement and is any other address for a third-party settlement, so consumers can tell the two apart from the log alone.

event PendingClaimSettled(
    address indexed user, bytes32 indexed labelhash, address store, address indexed settledBy
);

Parameters

NameTypeDescription
useraddressAccount the settled name belongs to.
labelhashbytes32Labelhash of the settled name.
storeaddressThe LabelStore the label was written into.
settledByaddressCaller that performed and paid for the settlement.

ReservationHeadAdvanced

Emitted when a reservation queue's head transitions to a new user, either via expiry of the prior head or via the explicit relinquish path.

event ReservationHeadAdvanced(bytes32 indexed labelhash, address indexed newHead);

Parameters

NameTypeDescription
labelhashbytes32Personhood-name hash whose queue head changed.
newHeadaddressAddress now holding the head slot.

Errors

NotRoot

Thrown when a gated entrypoint is reached without a Root origin.

Carries no caller parameter: a Root origin has no account to report, and reading msg.sender under one traps.

error NotRoot();

InvalidDeviceLabel

Thrown when a supplied device name does not match stem.NN, or its stem is governance-reserved.

error InvalidDeviceLabel();

InvalidPersonhoodLabel

Thrown when a supplied personhood name is not lowercase ASCII letters only, or classifies outside what the gateway may issue or reserve.

error InvalidPersonhoodLabel();

PersonhoodNameUnavailable

Thrown when a personhood name to reserve already has an owner on the registrar, so the queued reservation could never be claimed.

error PersonhoodNameUnavailable();

DeviceNameAlreadyIssued

Thrown when a device name is issued again while its subname already exists.

A device name is issued once; re-issuing it would rehome the identity to a new owner and overwrite its records, so an existing subname is rejected rather than reassigned.

error DeviceNameAlreadyIssued();

InvalidChatKey

Thrown when a supplied chat key is non-empty and not exactly 65 bytes long.

Mirrors the resolver's InvalidChatKeyLength so the controller surfaces a controller-local error before the mint runs.

error InvalidChatKey(uint256 length);

Parameters

NameTypeDescription
lengthuint256Caller-supplied chat key length, in bytes.

NoActiveReservation

Thrown when a user tries to claim or relinquish a reservation that they do not hold.

error NoActiveReservation(address user);

QueueFull

Thrown when a reservation queue has reached its capacity.

error QueueFull(bytes32 labelhash);

AlreadyReserved

Thrown when attempting to enqueue a user who already has an active reservation.

error AlreadyReserved(address user, bytes32 labelhash);

NotHolder

Thrown when someone tries to issue a personhood name standalone while another user holds the live head-of-queue reservation for it.

error NotHolder(address user, bytes32 labelhash);

DeviceNameNotOwned

Thrown when a device link names a device name the registrant does not own.

Prevents identity hijack by ensuring the registrant of the personhood name actually holds the device name whose chat key is being inherited.

error DeviceNameNotOwned(address user, bytes32 deviceLabelhash);

Parameters

NameTypeDescription
useraddressRegistrant supplied by the gateway.
deviceLabelhashbytes32Device name whose ownership did not match.

ReservationDurationTooLow

Thrown when @custom:function setReservationDuration is called with a value below the protocol minimum.

error ReservationDurationTooLow(uint64 duration);

Parameters

NameTypeDescription
durationuint64Caller-supplied duration, in seconds.

Structs

Tagged union selecting the chat-key source for a personhood-name issuance.

struct Link {
    LinkKind kind;
    string deviceLabel;
    bytes chatKey;
}

Properties

NameTypeDescription
kindLinkKind
deviceLabelstringDevice name stem.NN (only read when kind == DeviceName).
chatKeybytesChat key bytes (only read when kind == None).

UserReservation

Per-user reservation pointer: which queue the user sits in and where.

struct UserReservation {
    bytes32 labelhash;
    uint64 index;
}

Properties

NameTypeDescription
labelhashbytes32Non-zero when the user holds a live reservation; zero otherwise.
indexuint64Monotonic queue index, meaningful only when labelhash is non-zero.

ReservationEntry

Reservation queue entry: a user and the timestamp they joined the queue.

Packs into a single storage slot (20 + 8 bytes).

struct ReservationEntry {
    address owner;
    uint64 joinedAt;
}

ReservationQueueMeta

Metadata describing the occupied range of a reservation queue.

Uses monotonically increasing indices. Active entries occupy [head, tail); length = tail - head. Slots past head are deleted as the head advances so garbage never accumulates.

struct ReservationQueueMeta {
    uint64 head;
    uint64 tail;
}

PendingClaim

Deferred per-user binding of a freshly minted name to its LabelStore.

Recorded by the gateway path when the user has no LabelStore. The binding later settles via @custom:function settlePendingClaims, which deploys the store from a signed origin and writes the stashed label. PoP-resolver records (chat key, device link) are persisted eagerly at mint time on @custom:contract IDotnsPopResolver, not at settlement, so the resolver carries the full identity record regardless of whether the user has settled their Store. A user accumulates one entry per deferred name: the Root gateway path cannot deploy a LabelStore (contract creation is forbidden from the Root origin), so it keeps stashing entries until a signed-origin @custom:function settlePendingClaims deploys the store and settles the entries. Entries never lapse and can be settled at any time.

struct PendingClaim {
    string label;
    uint64 mintedAt;
}

Properties

NameTypeDescription
labelstringBare label without the TLD, which is appended at settlement time. A device name carries its separator, so this is not always a single DNS label.
mintedAtuint64Timestamp of the originating mint.

DeviceNameIssuance

Device-name issuance payload.

Single struct so the gateway can ABI-encode one tuple as the cross-chain payload and the contract decodes it directly out of msg.data. All fields are required; chatKey may be empty bytes to skip the resolver write.

struct DeviceNameIssuance {
    string label;
    address user;
    bytes chatKey;
}

Properties

NameTypeDescription
labelstringDevice name stem.NN being issued.
useraddressBeneficiary account on this chain.
chatKeybytesChat-key bytes persisted on the PoP resolver. Empty leaves the slot unset.

DeviceNameIssuanceWithReservation

Device-name issuance combined with an optional personhood-name reservation.

Composition of a @custom:struct DeviceNameIssuance and a reservation slot, so internal helpers consume the issuance via params.issuance without unpacking. The issuance always runs; the reservation only runs when reservedLabel is non-empty.

struct DeviceNameIssuanceWithReservation {
    DeviceNameIssuance issuance;
    string reservedLabel;
}

Properties

NameTypeDescription
issuanceDeviceNameIssuanceDevice-name issuance request; see DeviceNameIssuance.
reservedLabelstringPersonhood name to enqueue for a later claim. Empty string skips the reservation.

PersonhoodNameReservation

Personhood-name reservation payload.

The reservation-only primitive. Device-name issuance is handled by

Notes:

  • function: issueDeviceName, and LabelStore settlement by

  • function: settlePendingClaims.

struct PersonhoodNameReservation {
    address user;
    string label;
}

Properties

NameTypeDescription
useraddressBeneficiary account that will hold the reservation.
labelstringPersonhood name to enqueue for a later claim.

PersonhoodNameIssuance

Personhood-name issuance payload.

struct PersonhoodNameIssuance {
    string label;
    address user;
    Link link;
}

Properties

NameTypeDescription
labelstringPersonhood name being issued.
useraddressBeneficiary account on this chain.
linkLinkChat-key source for the new entry; see @custom:struct Link.

Enums

LinkKind

Discriminant for the Link union supplied to issuePersonhoodName.

Selects the chat-key source for the personhood name. Orthogonal to whether the issuance is a claim or standalone; that is derived from on-chain reservation state. None means the caller supplies a fresh chat key in link.chatKey. DeviceName means the personhood name is linked to a prior device name (link.deviceLabel) and inherits its chat key. The member order is part of the ABI: the gateway pallet encodes DeviceName as 1.

enum LinkKind {
    None,
    DeviceName
}