Skip to content

Latest commit

 

History

History
719 lines (546 loc) · 29.6 KB

File metadata and controls

719 lines (546 loc) · 29.6 KB

AIP-0009: Avian Name System v2 (ANS)

AIP:     0009
Title:   Avian Name System v2 (ANS)
Author:  Avian Network Developers
Status:  Draft
Type:    Standards Track
Created: 2026-05-25
Supersedes: AIP-0004

Abstract

This proposal defines Avian Name System v2 (ANS), a human-readable naming and identity layer built on top of Avian's existing asset infrastructure. ANS allows users, creators, and collections to register a short .avn name that resolves to an Avian address and optional off-chain metadata. Names are registered by creating an Avian asset whose name ends with the .AVN suffix (e.g. ARTIST.AVN). Resolution semantics, wire-format details, consensus enforcement, and new RPC methods are specified below.


Motivation

Avian addresses are 34-character alphanumeric strings that are opaque to human users. Several independent actors on mainnet have already begun registering .AVN-suffixed assets as informal identity markers (e.g. BTC.AVN created at block 1 160 822, Oct 2022), demonstrating organic demand for a naming convention.

ANS v1 stored an ANS record in a free-form field on any asset. A chain scan of all 1 880 mainnet assets in May 2026 confirmed zero assets carry an ANS record, leaving no backward-compatibility obligation for the record format while preserving the serialisation skeleton.

ANS v2 replaces the v1 design with one that:

  • reuses the existing asset registration mechanism for name ownership and transfer;
  • piggybacks on already-deployed on-chain assets such as BTC.AVN;
  • replaces the IP/DNS record type with a cross-chain address (XADDR) type stored on sub-assets (e.g. BOB.AVN/BTC);
  • fixes activation to use BIP9 miner signaling rather than a wall-clock timestamp;
  • adds resolveavn, whoisavn, getansdata, and myansnames RPCs for first-class name resolution.

Specification

1. Name Format

An ANS name has the form:

<label>.avn

where:

Component Rule
<label> 1–27 characters; [a-zA-Z0-9]; case-insensitive — the node normalises to uppercase to form the on-chain asset name
.avn suffix literal, case-insensitive for user input

The 27-character limit on the label derives from the global MAX_NAME_LENGTH = 31 asset name limit: the .AVN suffix consumes 4 characters, leaving 27 for the label. Label input is case-insensitive; btc.avn, BTC.avn, and BTC.AVN all resolve to the same on-chain asset BTC.AVN. Hyphens are not permitted because the existing root name character set ([A-Z0-9._]) does not include them; supporting hyphens would require a separate consensus validation path and is deferred to a future AIP.

The corresponding on-chain asset name is the uppercased form: <LABEL>.AVN. The owner-token asset name is <LABEL>.AVN!.

Examples:

User input On-chain asset Owner token
btc.avn BTC.AVN BTC.AVN!
artist.avn ARTIST.AVN ARTIST.AVN!
myalbum.avn MYALBUM.AVN MYALBUM.AVN!

Names are case-insensitive: BTC.AVN and btc.avn refer to the same name.

2. Name Registration

A name is registered by creating a standard Avian asset whose name matches <LABEL>.AVN. No additional transaction format is required. The existing 500 AVN asset creation fee acts as the anti-spam mechanism.

At creation time the issuer may attach an ANS resolution record by setting nHasANS = 1 and populating strANSID with an ANS ID (see §3). If no ANS record is set at creation, the name still exists and resolves via the owner-token fallback (see §4).

2.1 Label Validation (consensus)

Nodes MUST reject any asset creation transaction where the asset name ends in .AVN but the <LABEL> portion fails the character rules in §1. This prevents malformed names entering the UTXO set.

3. ANS Record Format (strANSID)

When nHasANS == 1 the strANSID field contains an ANS ID string with the following structure:

ANS<type_nibble><data>
Field Length Description
ANS 3 bytes Fixed magic prefix
<type_nibble> 1 byte (hex char) Record type (see §3.1)
<data> variable Type-dependent payload

Maximum total length: 512 bytes (expanded from 90 bytes to accommodate inline thumbnail images in PROFILE records; ANS has been active on testnet only, so no mainnet migration is required. The original 90-byte limit was raised from ANS v1's 40 bytes to accommodate bech32 and post-quantum addresses).

3.1 Record Types

Type nibble Name Payload Max payload
0 ADDR Any valid Avian address (legacy, bech32, bech32m, PQ) 86 bytes
1 XADDR Cross-chain external address stored on a sub-asset (see §3.3) 508 bytes
2 PROFILE CBOR map (RFC 8949) encoding compact identity fields (see §3.4) 508 bytes

Type 1 (IP/DNS A record) defined in ANS v1 is superseded; nibble 1 is reassigned to XADDR. The type byte space 3f is reserved for future AIPs.

3.2 ADDR Record

The ADDR record maps the name to a specific Avian address independently of who holds the owner token. This is useful for wallets that rotate key pairs while keeping the same name pointed at a stable payment address.

All current Avian address formats are supported:

Address type Format Network Approx. length
Legacy P2PKH Base58Check (R...) mainnet + testnet 34 chars
SegWit v0 P2WPKH Bech32 (avn1q...) mainnet + testnet ~43 chars
Post-quantum ML-DSA-44 (witness v2) Bech32m (avn1z...) testnet only ~63 chars

Taproot (segwit v1 / P2TR / bech32m avn1p...) is NEVER_ACTIVE on all Avian networks and is therefore not listed. If taproot is activated in a future release, its bech32m addresses will be valid ADDR payloads without any ANS protocol change, since the 90-byte limit accommodates them.

strANSID = "ANS0" + <avian_address>

Examples:

ANS0RHwoNwr7iucfVDtgcsw4vkoMMqpcx2PmKv          (legacy P2PKH)
ANS0avn1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4  (bech32 P2WPKH)

3.3 XADDR Record

The XADDR record maps an ANS name to an address on an external (non-Avian) blockchain. It is carried on a sub-asset of the .AVN name, not on the root name itself. The sub-asset name encodes the target chain:

<LABEL>.AVN/<COIN>

where <COIN> is the ticker of the target chain, normalised to uppercase (e.g. BTC, ETH, SOL). The sub-asset name uniquely identifies both the ANS name and the target chain; no two sub-assets can share the same name (enforced by existing asset consensus rules).

strANSID = "ANS1" + <external_address>
Field Rule
<external_address> The address on the target chain, encoded as a UTF-8 string. Avian nodes do not validate the format — the receiving application is responsible for address validation.

Maximum payload: 508 bytes (512-byte total strANSID limit minus the 4-byte ANS1 prefix).

Examples:

ANS1bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx   (BOB.AVN/BTC — Bitcoin bech32)
ANS10x71C7656EC7ab88b098defB751B7401B5f6d8976F   (BOB.AVN/ETH — Ethereum hex)
ANS1So11111111111111111111111111111111111111112     (BOB.AVN/SOL — Solana base58)

3.4 PROFILE Record

The PROFILE record encodes a compact identity profile as a CBOR map (RFC 8949). After the four-byte ANS2 prefix, the remaining bytes of strANSID are raw binary CBOR — not hex- or base64-encoded. Resolvers decode the bytes directly.

Integer map keys minimise payload size:

Key Field CBOR type Max length Notes
0 addr tstr 86 bytes Payment address (any valid Avian format); overrides owner‑token fallback
1 name tstr 32 bytes Human-readable display name
2 avatar tstr or bstr 64 bytes (tstr) / 480 bytes (bstr) tstr: ipfs://… CID or https:// URL; bstr: inline thumbnail image (see below)
3 url tstr 64 bytes Website URL

Encoding rules:

  • At least one key MUST be present.
  • Unknown integer keys MUST be silently ignored (forward compatibility).
  • Non-integer keys MUST cause the record to be treated as malformed.
  • String values MUST be valid UTF-8.
  • Total CBOR payload MUST NOT exceed 508 bytes.
  • Indefinite-length encoding and CBOR tags MUST be rejected.

Inline avatar images (key 2 as bstr): Resolvers distinguish a URL reference from an inline image by the CBOR major type of the value: major type 3 (tstr) is a URL/CID; major type 2 (bstr) is raw image bytes. The image format is detected from the leading magic bytes — no format prefix byte is needed:

Format Magic bytes (hex) Notes
PNG 89 50 4e 47 0d 0a 1a 0a lossless; good for logos/icons
WebP 52 49 46 46 ?? ?? ?? ?? 57 45 42 50 lossy or lossless; smallest at thumbnail sizes
JPEG ff d8 ff lossy; widely supported

Recommended dimensions: ≤ 32 × 32 pixels. Wallets SHOULD prefer WebP for the smallest on-chain footprint. Resolvers MUST NOT render images larger than 128 × 128 pixels from an inline bstr to prevent resource exhaustion.

strANSID = "ANS2" + <raw CBOR bytes>

Example — display name only ({1: "Satoshi"}):

CBOR (hex): a1 01 67 53 61 74 6f 73 68 69      (10 bytes)
strANSID:   "ANS2" + those 10 bytes             (14 bytes total)

Example — payment address + display name ({0: "RHwoNwr7…", 1: "Satoshi"}):

CBOR (hex): a2 00 78 22 52 48 77 6f 4e 77 72 37 69 75 63 66
            56 44 74 67 63 73 77 34 76 6b 6f 4d 4d 71 70 63
            78 32 50 6d 4b 76 01 67 53 61 74 6f 73 68 69
            (47 bytes)
strANSID:   "ANS2" + those 47 bytes             (51 bytes total)

4. Resolution Algorithm

4.1 Avian address resolution

Given a name <label>.avn, a resolver MUST follow these steps:

  1. Compute the on-chain asset name N = uppercase(<label>) + ".AVN".
  2. Look up asset N in the asset database. If not found → NXNAME (name not registered).
  3. If the asset has nHasANS == 1: a. Decode strANSID. b. If type is ADDR and the address is valid → return that address. c. If type is PROFILE, decode the CBOR map:
    • If key 0 (addr) is present and valid → return that address.
    • Otherwise → fall through to step 4. d. If decoding fails → fall through to step 4.
  4. Owner-token fallback: find the current UTXO holder of N! (the owner token). Return the address holding N!.

The fallback in step 4 means that names registered before ANS v2 activation (such as BTC.AVN) are automatically resolvable without any migration transaction.

4.2 Cross-chain (XADDR) resolution

Given a name <label>.avn and a coin ticker <coin>:

  1. Compute the sub-asset name S = uppercase(<label>) + ".AVN/" + uppercase(<coin>).
  2. Look up asset S in the asset database. If not found → NXCHAIN (no record for that chain).
  3. If the sub-asset has nHasANS == 1 and type is XADDR → return the external address.
  4. Otherwise → NXCHAIN.

No fallback exists for cross-chain resolution. An XADDR record must be explicitly set on the sub-asset by the name owner.

5. Metadata

ANS v2 supports a two-tier metadata model. The tiers are independent and complementary; either or both MAY be present on any .AVN asset.

5.1 Tier 1 — Compact on-chain records (CBOR)

Core identity fields are stored directly in strANSID using the PROFILE record type (type nibble 2, defined in §3.4). The encoding is CBOR (RFC 8949): self-describing, binary, typically 30–50 % smaller than JSON, and already used by IPFS (DAG-CBOR) ensuring tooling compatibility. Using small integer map keys, a profile containing a display name, payment address, and avatar URL fits comfortably within the existing 86-byte payload budget.

Tier 1 records are always available — they live entirely on-chain and require no external services to resolve. Wallets and resolvers SHOULD use Tier 1 for fast lookups (primary address, display name).

5.2 Tier 2 — Extended off-chain profile (IPFS)

If the .AVN asset was created with nHasIPFS == 1, the strIPFSHash field MAY contain an IPFS CIDv0 or CIDv1 pointing to a JSON document describing the full identity:

{
  "name": "Satoshi",
  "bio": "Creator of Bitcoin",
  "avatar": "ipfs://Qm...",
  "website": "https://example.com",
  "social": {
    "twitter": "@satoshi"
  }
}

This document is advisory only and carries no consensus weight. Clients SHOULD validate the CID against the document hash before rendering.

The strIPFSHash CID is an on-chain commitment: it is a cryptographic hash of the document, so the content is permanently bound to the asset and independently verifiable without trust. Tier 2 is suited to rich or frequently-changing data that would not fit in the 86-byte strANSID budget.

IPFS availability: the CID approach requires the content to be pinned on at least one IPFS node to remain accessible. Operators and wallet developers SHOULD use a pinning service or run a local IPFS node to ensure metadata remains reachable. A Tier 2 fetch failure MUST NOT prevent resolution of Tier 1 records.

5.3 Precedence

When both tiers are present, Tier 1 (on-chain CBOR) takes precedence for fields that appear in both. Resolvers SHOULD surface Tier 1 data immediately and fetch Tier 2 data asynchronously.

Sub-assets of a .AVN asset (e.g. BOB.AVN/BTC) are independent Avian assets. When a sub-asset carries an XADDR record (§3.3), it participates in ANS cross-chain resolution: the component after / identifies the target chain, and the XADDR payload is the external address. Sub-assets without an XADDR record are not part of the ANS protocol and MAY be used for other purposes by tooling.

6. Uniqueness

Name uniqueness is enforced for free by the Avian asset layer: no two assets can share the same name. Creating BTC.AVN a second time is rejected by existing consensus rules.

7. Name Transfer and Update

  • Transfer: Send the <LABEL>.AVN! owner token to a new address. After the next block the owner-token fallback resolves to the new holder.
  • Update resolution address: Reissue the <LABEL>.AVN asset with updated strANSID (if the asset was created as reissuable). Wallets SHOULD create .AVN assets as reissuable (nReissuable = 1) to allow future updates.
  • Freeze: Reissue with nReissuable = 0 to permanently lock the resolution record.

8. Activation

ANS v2 uses BIP9 miner signaling for on-chain, decentralised activation. Miners signal readiness by setting a dedicated bit in the block nVersion field. Once 75 % of blocks in a 2016-block retarget window signal readiness, the deployment locks in and activates after one further retarget period.

The deployment is registered as DEPLOYMENT_ANS_V2 in the DeploymentPos enum with the following parameters:

Parameter Value
bit TBD (first unused bit)
nStartTime TBD
nTimeout nStartTime + 1 year
period 2016
threshold 1512 (75 % — reduced from Bitcoin default of 95 % to account for Avian's smaller mining pool)
min_activation_height TBD
// params.h — add to DeploymentPos enum
DEPLOYMENT_ANS_V2,

// chainparams.cpp
consensus.vDeployments[Consensus::DEPLOYMENT_ANS_V2].bit                   = X;    // TBD
consensus.vDeployments[Consensus::DEPLOYMENT_ANS_V2].nStartTime            = <TBD>;
consensus.vDeployments[Consensus::DEPLOYMENT_ANS_V2].nTimeout              = <TBD>;
consensus.vDeployments[Consensus::DEPLOYMENT_ANS_V2].period                = 2016;
consensus.vDeployments[Consensus::DEPLOYMENT_ANS_V2].threshold             = 1512;
consensus.vDeployments[Consensus::DEPLOYMENT_ANS_V2].min_activation_height = <TBD>;

This replaces the wall-clock timestamp approach used by ANS v1, which was never activated on any network (UPGRADE_AVIAN_NAME_SYSTEM remained at its default nTimestamp = UINT32_MAX, disabling the feature entirely). BIP9 signaling is deterministic: the activation point is determined entirely by miner behaviour recorded in block headers — no developer needs to hardcode a block height.

Before activation nodes MUST NOT enforce §2.1 label validation or §3 record format. After activation nodes MUST enforce §2.1 and §3.

Pre-existing .AVN assets created before activation are valid name registrations; the ANS record field (strANSID) is ignored until activation.

Read-only RPCs (getansdata, resolveavn, whoisavn, myansnames) are not gated on activation. They operate on whatever ANS-capable assets exist in the database, enabling lookups on mainnet assets such as BTC.AVN without waiting for BIP9 lock-in. Only transaction-creating operations (asset issuance and reissuance with ANS records) enforce the activation gate.

9. New and Modified RPC

All ANS RPCs are grouped under the "avian name system" help category.

9.1 resolveavn (updated)

resolveavn "<name>" ( "<coin>" )

Resolves an ANS name.  Without a coin argument, resolves to an Avian address.
With a coin argument, resolves to the address on the specified chain.

Arguments:
  1. name   (string, required)  The ANS name to resolve, e.g. "btc.avn"
  2. coin   (string, optional)  Target chain ticker, e.g. "BTC" or "ETH"

Result (Avian resolution, no coin):
{
  "name":         (string)  Canonical form of the requested name
  "address":      (string)  Resolved Avian address
  "asset":        (string)  On-chain asset name (e.g. "BTC.AVN")
  "record_type":  (string)  "ADDR", "PROFILE", or "owner_token_fallback"
  "display_name": (string, optional)  Display name from PROFILE record (key 1)
  "avatar":       (string, optional)  Avatar CID/URL from PROFILE record (key 2)
  "url":          (string, optional)  Website URL from PROFILE record (key 3)
  "has_metadata": (bool)    true if an IPFS metadata document is attached
  "ipfs_hash":    (string, optional)  IPFS CID of the metadata document
}

Result (cross-chain resolution, with coin):
{
  "name":         (string)  Canonical form of the requested name
  "coin":         (string)  Requested chain ticker (uppercase)
  "address":      (string)  Address on the target chain
  "asset":        (string)  Sub-asset holding the XADDR record (e.g. "BOB.AVN/BTC")
  "record_type":  "XADDR"
}

Returns null if the name is not registered.  Returns null with coin if no XADDR record
exists for that chain.

9.2 getansdata (new)

getansdata "<asset>"

Returns the raw ANS record attached to an asset.

Arguments:
  1. asset  (string, required)  The asset name (e.g. "BTC.AVN" or "BOB.AVN/BTC")

Result:
{
  "asset":        (string)  The asset name
  "has_ans":      (bool)    Whether the asset has an ANS record
  "type":         (string, optional)  "ADDR", "XADDR", or "PROFILE"
  "address":      (string, optional)  For ADDR/XADDR: the encoded address
  "display_name": (string, optional)  For PROFILE: display name (key 1)
  "avatar":       (string, optional)  For PROFILE: avatar CID/URL or "<inline image>" (key 2)
  "url":          (string, optional)  For PROFILE: website URL (key 3)
  "ans_id":       (string)  Raw strANSID value
}

9.3 whoisavn (new)

whoisavn "<address>"

Reverse-lookup: finds all ANS names associated with the given Avian address.

Arguments:
  1. address  (string, required)  The Avian address to query

Result:
{
  "address":       (string)  The queried address
  "owner_of":      (array)   ANS names for which this address holds the owner token
  "registered_as": (array)   ANS names whose ADDR or PROFILE record resolves to this address
}

9.4 myansnames (new, wallet RPC)

myansnames

Lists all ANS names owned by addresses in this wallet.

Result:
[
  {
    "name":         (string)  The ANS name (e.g. "BOB.AVN")
    "type":         (string)  Record type ("ADDR", "XADDR", "PROFILE", or "none")
    "address":      (string, optional)  Payment address from ADDR or PROFILE record
    "display_name": (string, optional)  Display name from PROFILE record
    "cross_chain":  (array)   Cross-chain addresses from XADDR sub-assets
    [
      {
        "coin":    (string)  Chain ticker (e.g. "BTC")
        "address": (string)  Address on the target chain
        "asset":   (string)  Sub-asset name (e.g. "BOB.AVN/BTC")
      },
      ...
    ]
  },
  ...
]

9.5 ansencode / ansdecode (new, utility)

ansencode <type> <data>
ansdecode "<ans_id>"

Helper RPCs for constructing and inspecting strANSID strings. ansencode takes a record type (ADDR, XADDR, or PROFILE) and the appropriate data, and returns the encoded strANSID. ansdecode takes a raw strANSID string and returns the parsed fields. Neither RPC touches the chain; both work regardless of activation state.

9.6 listassets and getassetdata (updated)

Both RPCs already expose has_ans and ans_id fields as of ANS v2 (added in v5.0.0). No further changes are required.

9.7 issueasset (updated)

The existing issueasset RPC accepts optional ans_type and ans_data parameters. ANS v2 adds validation that, when the asset name ends in .AVN, the label satisfies §1.


Rationale

Why .AVN-named assets instead of an arbitrary-asset ANS field?

Using the asset name as the name identifier gives several properties for free:

  • Uniqueness — enforced by existing consensus with no new index.
  • Ownership — the owner token IS the deed to the name.
  • Transferability — normal asset transfer semantics.
  • Organic compatibility — assets like BTC.AVN already on mainnet are immediately resolvable without migration.

The v1 design (any asset carries an ANS field with a free-form name) required a separate uniqueness index, complex validation, and none of the existing assets could benefit from it.

Why remove the IP/DNS type?

DNS A records require full nodes to operate authoritative DNS servers, introduce off-chain infrastructure dependencies, and can become stale. No mainnet asset ever used this type. Name-to-IP mapping is better served by existing DNS infrastructure pointing to off-chain metadata retrieved via the IPFS CID.

Why BIP9 miner signaling?

The v1 IsUpgradeActive() implementation calls GetTime() (the node's wall-clock), which is not consensus-safe: two nodes with different system clocks can disagree on whether the upgrade is active for the same block. The correct fix would be to use pindex->GetMedianTimePast() (the median timestamp of the last 11 blocks), which is derived entirely from on-chain data and is used by many chains (Zcash, Horizen, and others) for timestamp-based activation.

ANS v2 goes one step further and uses BIP9 miner signaling instead of a fixed timestamp. BIP9 has additional advantages over a fixed timestamp:

  • Demonstrated support — activation requires miners to explicitly signal readiness, reducing the risk of activating before the network has upgraded.
  • Automatic lock-in — once the threshold is reached, the activation height is determined by the chain itself, with no developer needing to hardcode a value.
  • Existing infrastructure — Avian already has vDeployments and the BIP9 state machine; ANS v2 reuses it at no extra implementation cost.

The threshold is reduced from the Bitcoin default of 95 % to 75 % to account for Avian's smaller and less active mining pool.

Why XADDR sub-assets instead of an additional PROFILE key?

Cross-chain addresses are stored on sub-assets (<LABEL>.AVN/<COIN>) rather than as extra keys in the PROFILE CBOR map. This approach has several advantages:

  • Native asset ownership — Each <LABEL>.AVN/<COIN> sub-asset can be independently transferred. A user can hold BOB.AVN (their Avian identity) while delegating control of BOB.AVN/BTC (their Bitcoin cross-chain record) to a separate key.
  • Unlimited chains — Any number of chains can be registered without changing the CBOR schema. Adding Solana support is just issuing BOB.AVN/SOL; no protocol change needed.
  • No size pressure on PROFILE — PROFILE records target 30–100 bytes for on-chain identity. Adding one cross-chain address (~50 bytes) per supported chain would rapidly exhaust the 508-byte budget for users active on many chains.
  • Optional — Cross-chain support is fully opt-in; ANS names resolve to an Avian address without any sub-assets.

Backwards Compatibility

  • Wire format: CNewAsset serialisation is unchanged. The nHasANS and strANSID fields remain. Type nibble 1 is reassigned from IP (ANS v1, never used on any network) to XADDR.
  • Existing ANS v1 records: Zero assets carry nHasANS = 1 on mainnet (confirmed scan, May 2026), so no migration or special-casing is needed.
  • Existing .AVN assets: Automatically resolvable via the owner-token fallback. No transaction required from current holders.
  • Old nodes: Nodes that have not upgraded will not enforce §2.1 label validation. They will accept .AVN assets with invalid labels. This is a soft-fork enforcement point and must reach sufficient node adoption before the activation height.

Test Vectors

Label validation

Input Valid Reason
btc yes
BTC yes normalised to BTC
mywallet yes
MyWallet yes normalised to MYWALLET
a yes (1 char)
abcdefghijklmnopqrstuvwxyz1 yes (27 chars) exactly at limit
abcdefghijklmnopqrstuvwxyz12 no 28 chars, exceeds max 27
my-wallet no hyphens not permitted
has space no spaces not permitted

ANS ID encoding

Type Input address/data Encoded strANSID
ADDR RHwoNwr7iucfVDtgcsw4vkoMMqpcx2PmKv (legacy) ANS0RHwoNwr7iucfVDtgcsw4vkoMMqpcx2PmKv
ADDR avn1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 (bech32) ANS0avn1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
XADDR bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx (BTC bech32, on BOB.AVN/BTC) ANS1bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx
XADDR 0x71C7656EC7ab88b098defB751B7401B5f6d8976F (ETH hex, on BOB.AVN/ETH) ANS10x71C7656EC7ab88b098defB751B7401B5f6d8976F

PROFILE record (CBOR) encoding

Fields CBOR map CBOR hex strANSID bytes
display name only {1: "Satoshi"} a1 01 67 53 61 74 6f 73 68 69 14
name + address {0: "RHwoNwr7…", 1: "Satoshi"} a2 00 78 22 52 48 77 6f … 01 67 53 61 74 6f 73 68 69 51

Resolution

Given BTC.AVN asset exists, nHasANS = 0, owner token BTC.AVN! held at RCyhEoC9y4kyPpkm4v8eWWjbAtGKUHrtWa:

resolveavn "btc.avn"
→ { "address": "RCyhEoC9y4kyPpkm4v8eWWjbAtGKUHrtWa", "record_type": "owner_token_fallback", ... }

Given ARTIST.AVN asset exists, nHasANS = 1, strANSID = "ANS0RHwoNwr7iucfVDtgcsw4vkoMMqpcx2PmKv":

resolveavn "artist.avn"
→ { "address": "RHwoNwr7iucfVDtgcsw4vkoMMqpcx2PmKv", "record_type": "ADDR", ... }

Given BOB.AVN/BTC sub-asset exists, nHasANS = 1, strANSID = "ANS1bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx":

resolveavn "bob.avn" "BTC"
→ { "address": "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx", "record_type": "XADDR", "coin": "BTC", "asset": "BOB.AVN/BTC" }

Given BOB.AVN exists but no BOB.AVN/XMR sub-asset:

resolveavn "bob.avn" "XMR"
→ null

Reverse lookup

Given BTC.AVN! owner token is held at RCyhEoC9y4kyPpkm4v8eWWjbAtGKUHrtWa:

whoisavn "RCyhEoC9y4kyPpkm4v8eWWjbAtGKUHrtWa"
→ { "address": "...", "owner_of": ["BTC.AVN"], "registered_as": [] }

Implementation Notes

  1. A new LevelDB index ans_name → asset_name (keyed on the lowercased label) is recommended for O(1) name lookup in resolveavn. Without it, resolveavn must call GetAssetMetaData directly, which is still O(1) via the existing asset-name index.
  2. Add DEPLOYMENT_ANS_V2 to the DeploymentPos enum in params.h and register the deployment parameters in chainparams.cpp (see §8). The UPGRADE_AVIAN_NAME_SYSTEM entry in vUpgrades should be removed.
  3. IsAvianNameSystemDeployed(const CBlockIndex* pindexPrev) in assets.cpp should call VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_ANS_V2, versionbitscache) == ThresholdState::ACTIVE rather than checking a wall-clock timestamp.
  4. The CAvianNameSystemID class in ans.h/ans.cpp replaces Type::IP with Type::XADDR (nibble 1). The associated IPToHex/HexToIP helpers are removed. The XADDR constructor stores the external address as a plain string in the existing strAddr field.
  5. For cross-chain lookups, resolveavn constructs the sub-asset name as uppercase(label) + ".AVN/" + uppercase(coin) and calls ReadAssetData directly — O(1) via the existing asset-name index. No additional index is required.
  6. whoisavn performs two independent scans: AddressDir(address) (plus the dirty-cache overlay in passetsCache) to find owner-token UTXOs for the owner_of field; and a full AssetDir("*", ...) scan filtered by .AVN suffix for the registered_as field. The latter is O(N assets) and is acceptable for the current mainnet asset count (~1 900); a dedicated reverse index may be warranted if the asset count grows significantly.
  7. For PROFILE (type 2) records, use a minimal CBOR decoder (RFC 8949). Only definite-length major types 0 (uint), 2 (bstr), 3 (tstr), and 5 (map) need be supported. Indefinite-length encodings and tagged values (0xc00xdb) MUST cause the record to be treated as malformed. Unknown integer keys MUST be silently skipped.

Copyright

This document is placed in the public domain.