# Terminology

New terminology (beyond the [official ENS glossary](https://docs.ens.domains/terminology)) has been needed in the course of building ENSNode. The following should be understood as a draft that is open to community feedback. Each definition below aims to maximize alignment with the official ENS glossary where possible, and reduce instances where a piece of terminology may have multiple meanings in the context of the protocol.

## ENS Name Resolution Fundamentals

Understanding how ENS names are processed and displayed requires precise terminology around name components and their various states. The following sections build from basic name resolution concepts to the specific classification and encoding systems used in ENSNode.

### name, node, namehash

A **name** is a human-readable string like `"vitalik.eth"` composed of **labels**. A **name** may or may not be _normalized_.

> **Normalization** is process of canonicalizing a name before running it through the Namehash algorithm. [source](https://docs.ens.domains/resolution/names#normalize)

The [`namehash`](https://docs.ens.domains/resolution/names#namehash) function computes a UUID 32-byte hash of a given **name**. If the name provided to `namehash` is not _normalized_ then the resulting **node** is considered _invalid_.

> The node is a hex-encoded 32-byte value that is derived from the name using the namehash algorithm defined in ENSIP-1. [source](https://docs.ens.domains/resolution/names#namehash)

For the _normalized_ name `vitalik.eth`, its **node** is `0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835`.

https://docs.ens.domains/resolution/names#namehash

## Label Processing and Classification

ENSNode must process labels from various onchain and offchain sources, each potentially in different states of normalization and availability. This section defines the core label processing concepts.

### Labels, LabelHashes, labelhash function

A **Label** is a human-readable string used as a segment of a **name** — i.e. `vitalik` and `eth` are the **Labels** of `vitalik.eth`. Labels are arbitrary unicode strings and may or may not be: _normalized_ or _unnormalized_, _known_ or _unknown_.

In the ENSv1 `Registry` contract, only the **name**'s **node** is registered on-chain. Because of this there is no guarantee that a registered **node** is composed of _normalized_ Labels or that those Labels are _known_. That is, when observing the `Registry` in isolation, the human-readable **Labels** that make up a **name** are not available (either on-chain or off-chain). That said, in many cases the **Labels** that make up a name can be made **known**: human-readable **Labels** can be emitted by contracts (i.e. the `ETHRegistrarController` or the `NameWrapper`), and in other cases the human-readable **Label** for a given **LabelHash** can be determined via rainbow table lookups (via [ENSRainbow](/docs/services/ensrainbow)) and other strategies.

#### Rendering _Unknown_ Labels

When rendering a **name**, one must take care to differentiate between an _unknown_ **Label** (only identifiable by its 32-byte **LabelHash**) and a _known_ **Label** potentially composed of hex characters. To do so, the _unknown_ **Label**'s **LabelHash** is _encoded_ as `[{LabelHash}]`. Examples are likely helpful:

- `vitalik.eth` — a _normalized_ **name** w/ _normalized_ & _known_ Labels
- `[731f7025b488151de311c24abc1f27f02940bde412246fbdb3dea0d4f0663b22].eth` — a **name** composed of two Labels
1. an _unknown_ Label (of unknown _normalization_): `0x731f7025b488151de311c24abc1f27f02940bde412246fbdb3dea0d4f0663b22`
2. a _normalized_, _known_ Label: `eth`
- `731f7025b488151de311c24abc1f27f02940bde412246fbdb3dea0d4f0663b22.eth` — a _normalized_ **name** composed of two Labels
1. a _normalized_, _known_ Label (that just so happens to be a set of 64 literal hex characters): `731f7025b488151de311c24abc1f27f02940bde412246fbdb3dea0d4f0663b22`
2. a _normalized_, _known_ Label: `eth`

### LabelHash, labelhash function

In this terminology reference, we say that the **LabelHash** of a **Label** is the result of calling the **`labelhash` function** with that **Label** as input. For the complete technical definition, see the [ENSRainbow Glossary](/docs/services/ensrainbow/concepts/glossary#labelhash).

That is, `0xaf2caa1c2ca1d027f1ac823b529d0a67cd144264b2789fa2ea4d63a67c7103cc` is the **LabelHash** of `vitalik`, which is the result of calling the **`labelhash` function** like so:

```ts title="example.ts"
import { labelhashInterpretedLabel, asInterpretedLabel } from "enssdk";
const labelHash = labelhashInterpretedLabel(asInterpretedLabel("vitalik"));
```

:::caution[LabelHash Terminology Outside of this Reference]
Outside of this terminology reference & ENSNode, the word 'labelhash' may refer to either the function or the result of the function.
:::

## Name and Label State Classifications

As ENSNode processes ENS data from multiple sources, labels and names exist in various states depending on normalization and data availability. These classifications are essential for proper display and validation.

### ENS name normalization standard

The **ENS name normalization standard** is defined by [ENSIP-15: Name Normalization](https://docs.ens.domains/ensip/15/).

### ENS Normalize

We define **ENS Normalize** as a specific implementation of the **ENS name normalization standard** associated with a versioned release of the [`@adraffy/ens-normalize` package](https://www.npmjs.com/package/@adraffy/ens-normalize) to NPM.

It is important to note that the logic in this package changes across time with new releases. Therefore, labels / names that were unnormalized when using version X of this package may become normalized when using version X+N of this package. Generally such logic changes are based on [updates to the Unicode standard](https://www.unicode.org/versions/#schedule), such as how Unicode tends to officially release a set of new emojis each year.

The ENSIndexer Config API provides details of the specific **ENS Normalize** release being used. It is also important for apps building on ENSNode to match their **ENS Normalize** version with the version of the **ENS Normalize** package used by ENSIndexer. If ENS normalization implementations are not equivalent, the guarantees ENSNode provides for **Interpreted Labels** and **Interpreted Names** may not be met. For example, if ENSNode is using a more recent version of **ENS Normalize** than an app building on ENSNode, the app may receive an Interpreted Label / Interpreted Name from ENSNode that is not formatted as an encoded labelhash (because it is normalized in version X+N of **ENS Normalize**) but the app might consider that to be an unnormalized label / name because the app is still using version X of **ENS Normalize**.

### Normalized Label

A **Normalized Label** is a **Label** that has been processed through the **ENS Normalize** and represents the canonical form of that label. The normalization process ensures consistent representation and prevents homograph attacks.

### Unnormalized Label

An **Unnormalized Label** is a **Label** that has not been processed through the **ENS Normalize**, or one that would change if processed through normalization.

### Unknown Label

An **Unknown Label** is a **Label** for which the human-readable string is not available, and only the **LabelHash** is known. These labels are displayed using the **Encoded LabelHash** format: `[{LabelHash}]`.

### Normalized Name

A **Normalized Name** is a **name** composed entirely of **Normalized Labels**. This represents the canonical form of a name that can be safely processed through the `namehash` function to produce a valid **node**.

### Unnormalized Name

An **Unnormalized Name** is a **name** that contains one or more **Unnormalized Labels**, meaning it has not been fully processed through the **ENS Normalize**.

## Display Encoding Formats

When human-readable names or labels are unavailable, ENSNode uses specific encoding formats for consistent display. These formats ensure users can distinguish between actual hex content and placeholder representations.

### Encoded LabelHash

An **Encoded LabelHash** is a **LabelHash** that has been formatted for display when the corresponding **Label** is _unknown_. The encoding format wraps the hex representation of the **LabelHash** in square brackets: `[{LabelHash}]`.

For example, if a **LabelHash** is `0x731f7025b488151de311c24abc1f27f02940bde412246fbdb3dea0d4f0663b22`, its **Encoded LabelHash** representation would be `[731f7025b488151de311c24abc1f27f02940bde412246fbdb3dea0d4f0663b22]`.

### Encoded NameHash

An **Encoded NameHash** is a **NameHash** that has been formatted for display when the corresponding **Name** is _unknown_ or not human-readable. The encoding format wraps the hex representation of the **NameHash** in square brackets: `[{NameHash}]`.

For example, if a **NameHash** is `0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835`, its **Encoded NameHash** representation would be `[ee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835]`.

## Data Processing Pipeline

ENSNode's indexing pipeline transforms raw blockchain data into user-friendly formats. This requires distinguishing between literal onchain data and the interpreted forms used in applications.

When processing ENS data, it's important to distinguish between the literal data read from blockchain sources and the interpreted form used in applications:

### Literal Label

A **Literal Label** is the raw label data as it exists in onchain storage or event data, before any processing or interpretation. This represents the exact bytes or string as emitted by contracts.

### Interpreted Label

An **Interpreted Label** is a **Label** that is either:

- (if normalized): a normalized **Literal Label**
- (if not normalized or **Unknown**): an **Encoded LabelHash**

Apps building on ENSNode should take special note to align their implementation of **ENS Normalize** with the **ENS Normalize** used by the ENSNode they use. The **ENS Normalize** version used by each ENSNode can be referenced in the ENSIndexer Config API.

### Beautified Label

A **Beautified Label** is a **Label** produced from an **Interpreted Label** for presentation in a UI. It is either:

- an **Encoded LabelHash**, preserved verbatim from the source **Interpreted Label**, or
- a label produced by passing a normalized label through [ENSIP-15](https://docs.ens.domains/ensip/15) beautification, which is guaranteed to be normalizable back to the original normalized label but is itself NOT necessarily normalized (e.g. `"♾"` → `"♾️"`).

Because the beautified form is not guaranteed to be normalized, a **Beautified Label** is NOT an **Interpreted Label** and MUST NOT be used as a lookup key, or anywhere else that expects an **Interpreted Label**.

### Literal Name

A **Literal Name** is a Name exclusively composed of 0 or more **Literal Labels**.

### Interpreted Name

An **Interpreted Name** is a Name exclusively composed of 0 or more **Interpreted Labels**.

### Beautified Name

A **Beautified Name** is a Name produced from an **Interpreted Name** for presentation in a UI, where each label is either:

- an **Encoded LabelHash**, preserved verbatim from the source **Interpreted Name**, or
- a label produced by passing a normalized label through [ENSIP-15](https://docs.ens.domains/ensip/15) beautification, which is guaranteed to be normalizable back to the original normalized label but is itself NOT necessarily normalized (e.g. `"♾"` → `"♾️"`).

Because the beautified form is not guaranteed to be normalized, a **Beautified Name** is NOT an **Interpreted Name** and MUST NOT be used as a navigation target, lookup key, or anywhere else that expects an **Interpreted Name**.

### Resolvable Name

A **Resolvable Name** is a Name that can be used as input to ENS Forward Resolution. It contains only literal label segments (normalized or unnormalized), and each label is at most 255 bytes due to the [DNS Encoding](https://docs.ens.domains/resolution/names/#dns-encoding) standard.

:::danger[Interpreted Name !== Resolvable Name]
Because Forward Resolution does not support **Encoded LabelHashes**, an **Interpreted Name** containing an **Encoded LabelHash** is NOT a **Resolvable Name**: it can be used to traverse the Unigraph, but the records for that name cannot be resolved.
:::

## Subgraph Indexability & Label/Name Interpretation

### Subgraph-Indexable Labels / Subgraph-Unindexable Labels

The legacy ENS Subgraph specifies that **Unknown Labels** and labels containing certain UTF-8 characters are "invalid". We refer to this concept as `subgraph-indexable` and `subgraph-unindexable`.

A **Literal Label** is `subgraph-unindexable` if it:

- is an **Unknown Label**, or
- contains any of the following prohibited UTF-8 characters.

The `subgraph-unindexable` UTF-8 characters are:

1. `\0` (null byte) - PostgreSQL does not allow storing this character in text fields
2. `.` (period) - Conflicts with ENS label separator logic
3. `[` (left square bracket) - Conflicts with "unknown label" representations
4. `]` (right square bracket) - Conflicts with "unknown label" representations

A `subgraph-indexable` **Literal Label** is a **Known Literal Label** that does NOT contain any of the prohibited UTF-8 characters.

### Subgraph Interpreted Label

A **Subgraph Interpreted Label** is a **Label** that is either:

- (if `subgraph-indexable`): a **Literal Label** guaranteed to not contain any of the `subgraph-unindexable` UTF-8 characters, or
- (if `subgraph-unindexable`): an Encoded LabelHash.

### Subgraph Interpreted Name

A **Subgraph Interpreted Name** is a name exclusively composed of 0 or more **Subgraph Interpreted Labels**.

## ENS Data Models: Nametable, Namegraph, Unigraph

ENSv1 and ENSv2 use fundamentally different onchain data models, and ENSNode unifies them into a single one. These three terms name those models precisely.

### Nametable

A **Nametable** is the native onchain data model of ENSv1: a flat mapping from each name's **node** (namehash) to its onchain state, rather than a connected graph of Registries and Domains. Each ENSv1 datasource is its own Nametable — e.g. Ethnames (the mainnet ENS Registry), Basenames, Lineanames, and 3DNS.

### Namegraph

A **Namegraph** is the native onchain data model of ENSv2: it represents names as a graph of `Registry → Domain → Registry → Domain → …` rather than as a flat Nametable. A Namegraph may be cyclic, and an unbounded number of _disjoint_ Namegraphs can exist. There is no single global Namegraph — prefer "a Namegraph" or "the Namegraphs" over "the Namegraph".

### Unigraph

The **Unigraph** is the entire collection of ENSv1 Nametables and ENSv2 Namegraphs combined into a **single unified data model** using ENS Resolution semantics, indexed into [ENSDb](/docs/services/ensdb) by [ENSIndexer](/docs/services/ensindexer)'s `unigraph` plugin. Within the Unigraph, ENSv1 Nametables are represented in namegraph shape via virtual Registries (`ENSv1VirtualRegistry`), so navigating the Unigraph looks identical regardless of whether the underlying entity is ENSv1 or ENSv2.

## Core Protocol Extension Concepts

The following concepts extend the core ENS protocol to handle multichain and off-chain scenarios that arise in modern ENS usage.

### Subregistry

A **Subregistry** is any data structure outside of the [Registry](https://docs.ens.domains/terminology#registry) that manages supplemental state for a set of [subnames](https://docs.ens.domains/terminology#subname-subdomain). Each [name](https://docs.ens.domains/terminology#name) has the potential for association with at least 1 subregistry (through the [Name Wrapper](https://docs.ens.domains/terminology#name-wrapper)) and may optionally be associated with multiple subregistries. When a name is associated with multiple subregistries, this means that the full state of a name must be combined across the Registry and each associated subregistry. For example, the state of all direct subnames of .eth is distributed across the Registry and two subregistries: the BaseRegistrar and the Name Wrapper. The ENS protocol does not currently define standards for subregistries: subregistries currently exist outside the scope of ENS protocol standards. For example, subregistries could live on L1, on L2s, or offchain (in a database or even in a Google Sheet). The ENS protocol currently provides no standardized mechanism to discover subregistries or to interact with subregistries.

Some specific implementations of subregistries include:

- The [BaseRegistrar](https://github.com/ensdomains/ens-contracts/blob/staging/contracts/ethregistrar/BaseRegistrarImplementation.sol) that holds supplemental state for direct subnames of .eth. This includes state for ERC721 NFTs and expiry times.
- The [NameWrapper](https://docs.ens.domains/terminology#name-wrapper), which serves as a subregistry for the entire ENS root (all ENS names). This includes state for ERC1155 NFTs, expiry times, and fuses.
  - Note how direct subnames of .eth are an example of multiple subregistries potentially holding supplemental state for a name outside the Registry.
- The contracts on Base that manage supplemental state for direct subnames of [base.eth](https://www.base.org/names).
- The contracts on Linea that manage supplemental state for direct subnames of [linea.eth](https://names.linea.build/).
- The contracts on Base / Optimism that manage supplemental state for DNS names managed by [3DNS](https://3dns.box/).
- The offchain databases that manage supplemental state for direct subnames of [uni.eth](https://blog.uniswap.org/introducing-uni-eth-your-unique-web3-username).
- The offchain databases that manage supplemental state for direct subnames of [cb.id](https://help.coinbase.com/en/wallet/managing-account/coinbase-ens-support).
- DNS nameservers for (essentially) all DNS names. Since ENS is a superset of DNS, (essentially) any DNS name is an ENS name. Therefore, whenever supplemental state associated with a DNS name is updated in a DNS nameserver, a subregistry is being updated.

### Subregistrar

A **Subregistrar** is any system that is a [Registrar](https://docs.ens.domains/terminology#registrar) or that writes to a subregistry.

This definition expands the definition of Registrar to include cases such as:

- The [ETHRegistrarController](https://github.com/ensdomains/ens-contracts/blob/staging/contracts/ethregistrar/ETHRegistrarController.sol) that writes to BaseRegistrar (the owner of the "eth" TLD). Note how the definition of "Registrar" in the official ENS glossary only includes contracts that are pointed to by the owner field of the Registry. Therefore, the BaseRegistrar is a Registrar (and a Subregistry), while the ETHRegistrarController is a Subregistrar.
- The contracts on Base that write to the Subregistry for direct subnames of base.eth. These contracts live on Base, therefore they cannot meet the definition of Registrar because they can't be set as the owner in the Registry on Ethereum mainnet.
- The offchain systems that write to the offchain databases associated with direct subnames of uni.eth and cb.id.
- Any NFT marketplace that supports the exchange of an NFT representing ownership of an ENS name. Each time a NFT is exchanged, state about that NFT must be updated within a related subregistry. Therefore the marketplace enabling that trade is a Subregistrar.
- Any DNS registrar, as ENS is a superset of DNS.

### Shadow Registry

A **Shadow Registry** is a Subregistry meeting ALL of the following constraints:

1. Not the Registry;
2. Implemented as a smart contract exposing the same interface as the Registry;
3. Used as part of the source of truth for a CCIP-Read Gateway Server for ENSIP-10 (wildcard resolution) powered subnames.

A specific implementation of a Shadow Registry can be found in [this contract](https://github.com/base-org/basenames/blob/v1.0.4/src/L2/Registry.sol) storing a subset of the state of base.eth subnames on Base.