{"description":"Blockstack Naming Service (BNS)","author":{"@type":"Person","name":"Blockstack"},"@type":"BlogPosting","url":"https://zbabystack.netlify.com/core/naming/introduction.html","headline":"Blockstack Naming Service (BNS)","dateModified":"2018-08-30T13:25:56-07:00","datePublished":"2018-08-30T13:25:56-07:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://zbabystack.netlify.com/core/naming/introduction.html"},"@context":"http://schema.org"}</script>
repository is the reference implementation of the Blockstack Naming Service.</p>
<h1id="introduction">Introduction</h1>
<p>The Blockstack Naming Service (BNS) is a network system that binds names
to off-chain state without relying on any central points of control.
It does so by embedding a log of its control-plane messages within a public blockchain, like Bitcoin.</p>
<p>Each BNS peer determines the state of each name by indexing these specially-crafted
transactions. In doing so, each peer independently calculates the same global
name state.</p>
<p>Names in BNS have three properties:</p>
<ul>
<li><strong>Names are globally unique.</strong> The protocol does not allow name collisions, and all
well-behaved nodes resolve a given name to the same state.</li>
<li><strong>Names are human-meaningful.</strong> Each name is chosen by its creator.</li>
<li><strong>Names are strongly-owned.</strong> Only the name’s owner can change the state it
resolves to. Specifically, a name is owned by one or more ECDSA private keys.</li>
</ul>
<p>Internally, a BNS node implements a replicated name database. Each BNS node keeps itself
synchronized to all of the other ones in the world, so queries on one BNS node
will be the same on other nodes. BNS nodes allow a name’s owner to bind
up to 40Kb of off-chain state to their name, which will be replicated to all
BNS nodes via the <ahref="atlas_network.md">Atlas network</a>.</p>
<p>BNS nodes extract the name database log from an underlying blockchain (Blockstack
Core currently uses Bitcoin, and had used Namecoin in the past).
BNS uses the blockchain to establish a shared “ground truth” for the system: as long as
two nodes have the same view of the blockchain, then they will build up the same
database.</p>
<p>The biggest consequence for developers is that in BNS, reading name state is
fast and cheap but writing name state is slow and expensive. This is because
registering and modifying names requires one or more transactions to be sent to
the underlying blockchain, and BNS nodes will not process them until they are
sufficiently confirmed. Users and developers need to acquire and spend
the requisite cryptocurrency (i.e. Bitcoin) to send BNS transactions.</p>
<h1id="motivation">Motivation</h1>
<p>We rely on naming systems in everyday life, and they play a critical
role in many different applications. For example, when you look up a
friend on social media, you are using the platform’s naming service to resolve
their name to their profile. When you look up a website, you are using the
Domain Name Service to
resolve the hostname to its host’s IP address. When you check out a Git branch, you
are using your Git client to resolve the branch name to a commit hash.
When you look up someone’s PGP key on a keyserver, you are resolving
their key ID to their public key.</p>
<p>What kinds of things do we want to be true about names? In BNS, names are
globally unique, names are human-meaningful, and names are strongly-owned.
However, if you look at these examples, you’ll see that each of them only
guarantees <em>two</em> of these properties. This limits how useful they can be.</p>
<ul>
<li>In DNS and social media, names are globally unique and human-readable, but not
strongly-owned. The system operator has the
final say as to what each names resolves to.
<ul>
<li><strong>Problem</strong>: Clients must trust the system to make the right
choice in what a given name resolves to. This includes trusting that
no one but the system administrators can make these changes.</li>
</ul>
</li>
<li>In Git, branch names are human-meaningful
and strongly-owned, but not globally unique. Two different Git nodes may resolve the same
branch name to different unrelated repository states.
<ul>
<li><strong>Problem</strong>: Since names can refer to conflicting state, developers
have to figure out some other mechanism to resolve ambiguities. In Git’s
case, the user has to manually intervene.</li>
</ul>
</li>
<li>In PGP, names are key IDs. They are
are globally unique and cryptographically owned, but not human-readable. PGP
key IDs are derived from the keys they reference.
<ul>
<li><strong>Problem</strong>: These names are difficult for most users to
remember since they do not carry semantic information relating to their use in the system.</li>
</ul>
</li>
</ul>
<p>BNS names have all three properties, and none of these problems. This makes it a
powerful tool for building all kinds of network applications. With BNS, we
can do the following and more:</p>
<ul>
<li>Build domain name services where hostnames can’t be hijacked.</li>
<li>Build social media platforms where user names can’t be stolen by phishers.</li>
<li>Build version control systems where repository branches do not conflict.</li>
<li>Build public-key infrastructure where it’s easy for users to discover and
remember each other’s keys.</li>
</ul>
<h1id="how-to-use-bns">How to Use BNS</h1>
<p>BNS names are organized into a global name hierarchy. There are three different
layers in this hierarchy related to naming:</p>
<ul>
<li>
<p><strong>Namespaces</strong>. These are the top-level names in the hierarchy. An analogy
to BNS namespaces are DNS top-level domains. Existing BNS namespaces include
<codeclass="highlighter-rouge">.id</code>, <codeclass="highlighter-rouge">.podcast</code>, and <codeclass="highlighter-rouge">.helloworld</code>. All other names belong to exactly one
namespace. Anyone can create a namespace, but in order for the namespace
to be persisted, it must be <em>launched</em> so that anyone can register names in it.
Namespaces are not owned by their creators.</p>
</li>
<li>
<p><strong>BNS names</strong>. These are names whose records are stored directly on the
blockchain. The ownership and state of these names are controlled by sending
blockchain transactions. Example names include <codeclass="highlighter-rouge">verified.podcast</code> and
<codeclass="highlighter-rouge">muneeb.id</code>. Anyone can create a BNS name, as long as the namespace that
contains it exists already. The state for BNS names is usually stored in the <ahref="atlas_network.md">Atlas
network</a>.</p>
</li>
<li>
<p><strong>BNS subdomains</strong>. These are names whose records are stored off-chain,
but are collectively anchored to the blockchain. The ownership and state for
these names lives within the <ahref="atlas_network.md">Atlas network</a>. While BNS
subdomains are owned by separate private keys, a BNS name owner must
broadcast their subdomain state. Example subdomains include <codeclass="highlighter-rouge">jude.personal.id</code>
and <codeclass="highlighter-rouge">podsaveamerica.verified.podcast</code>. Unlike BNS namespaces and names, the
state of BNS subdomains is <em>not</em> part of the blockchain consensus rules.</p>
</li>
</ul>
<p>A feature comparison matrix summarizing the similarities and differences
between these name objects is presented below:</p>
<table>
<thead>
<tr>
<th>Feature</th>
<th><strong>Namespaces</strong></th>
<th><strong>BNS names</strong></th>
<th><strong>BNS Subdomains</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Globally unique</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Human-meaningful</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Owned by a private key</td>
<td></td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Anyone can create</td>
<td>X</td>
<td>X</td>
<td>[1]</td>
</tr>
<tr>
<td>Owner can update</td>
<td></td>
<td>X</td>
<td>[1]</td>
</tr>
<tr>
<td>State hosted on-chain</td>
<td>X</td>
<td>X</td>
<td></td>
</tr>
<tr>
<td>State hosted off-chain</td>
<td></td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Behavior controlled by consensus rules</td>
<td>X</td>
<td>X</td>
<td></td>
</tr>
<tr>
<td>May have an expiration date</td>
<td></td>
<td>X</td>
<td></td>
</tr>
</tbody>
</table>
<p>[1] Requires the cooperation of a BNS name owner to broadcast its transactions</p>
<h3id="creating-a-namespace">Creating a Namespace</h3>
<p>There are four steps to creating a namespace:</p>
<ol>
<li>
<p><strong>Send a <codeclass="highlighter-rouge">NAMESPACE_PREORDER</code> transaction</strong> (<ahref="https://www.blocktrail.com/BTC/tx/5f00b8e609821edd6f3369ee4ee86e03ea34b890e242236cdb66ef6c9c6a1b28">live example</a>).
This is the first step. This registers the <em>salted hash</em> of the namespace with BNS nodes, and burns the
requisite amount of cryptocurrency. In addition, it proves to the
BNS nodes that user has honored the BNS consensus rules by including
a recent <em>consensus hash</em> in the transaction
(see the section on <ahref="#bns-forks">BNS forks</a> for details).</p>
</li>
<li>
<p><strong>Send a <codeclass="highlighter-rouge">NAMESPACE_REVEAL</code> transaction</strong> (<ahref="https://www.blocktrail.com/BTC/tx/ab54b1c1dd5332dc86b24ca2f88b8ca0068485edf0c322416d104c5b84133a32">live example</a>).
This is the second step. This reveals the salt and the namespace ID (pairing it with its
<codeclass="highlighter-rouge">NAMESPACE_PREORDER</code>), it reveals how long names last in this namespace before
they expire or must be renewed, and it sets a <em>price function</em> for the namespace
that determines how cheap or expensive names its will be. The price function takes
a name in this namespace as input, and outputs the amount of cryptocurrency the
name will cost (i.e. by examining how long the name is, and whether or not it
has any vowels or non-alphabet characters). The namespace creator
has the option to collect name registration fees for the first year of the
namespace’s existence by setting a <em>namespace creator address</em>.</p>
</li>
<li>
<p><strong>Seed the namespace with <codeclass="highlighter-rouge">NAME_IMPORT</code> transactions</strong> (<ahref="https://www.blocktrail.com/BTC/tx/c698ac4b4a61c90b2c93dababde867dea359f971e2efcf415c37c9a4d9c4f312">live example</a>).
Once the namespace has been revealed, the user has the option to populate it with a set of
names. Each imported name is given both an owner and some off-chain state.
This step is optional—namespace creators are not required to import names.</p>
</li>
<li>
<p><strong>Send a <codeclass="highlighter-rouge">NAMESPACE_READY</code> transaction</strong> (<ahref="https://www.blocktrail.com/BTC/tx/2bf9a97e3081886f96c4def36d99a677059fafdbd6bdb6d626c0608a1e286032">live example</a>).
This is the final step of the process. It <em>launches</em> the namespace, which makes it available to the
public. Once a namespace is ready, anyone can register a name in it if they
pay the appropriate amount of cryptocurrency (according to the price funtion
revealed in step 2).</p>
</li>
</ol>
<p>The reason for the <codeclass="highlighter-rouge">NAMESPACE_PREORDER/NAMESPACE_REVEAL</code> pairing is to prevent
frontrunning. The BNS consensus rules require a <codeclass="highlighter-rouge">NAMESPACE_REVEAL</code> to be
paired with a previous <codeclass="highlighter-rouge">NAMESPACE_PREORDER</code> sent within the past 24 hours.
If it did not do this, then a malicious actor could watch the blockchain network
and race a victim to claim a namespace.</p>
<p>Namespaces are created on a first-come first-serve basis. If two people try to
create the same namespace, the one that successfully confirms both the
<codeclass="highlighter-rouge">NAMESPACE_PREORDER</code> and <codeclass="highlighter-rouge">NAMESPACE_REVEAL</code> wins. The fee burned in the
<codeclass="highlighter-rouge">NAMESPACE_PREORDER</code> is spent either way.</p>
<p>Once the user issues the <codeclass="highlighter-rouge">NAMESPACE_PREORDER</code> and <codeclass="highlighter-rouge">NAMESPACE_REVEAL</code>, they have
1 year before they must send the <codeclass="highlighter-rouge">NAMESPACE_READY</code> transaction. If they do not
do this, then the namespace they created disappears (along with all the names
they imported).</p>
<p>Developers wanting to create their own namespaces should read the <ahref="namespace_creation.md">namespace
creation</a> document. It is highly recommended that
developers follow this tutorial closely, given the large amount of
cryptocurrency at stake.</p>
<h3id="using-namespaces">Using Namespaces</h3>
<p>The intention is that each application can create its own BNS
namespace for its own purposes. Applications can use namespaces for things like:</p>
<ul>
<li>Giving users a SSO system, where each user registers their public key under a
username. Blockstack applications do this with names in the <codeclass="highlighter-rouge">.id</code> namespace,
for example.</li>
<li>Providing a subscription service, where each name is a 3rd party that provides
a service for users to subscribe to. For example, names in
<codeclass="highlighter-rouge">.podcast</code> point to podcasts that users of the
<ahref="https://dotpodcast.co">DotPodcast</a> app can subscribe to.</li>
<li>Implementing software licenses, where each name corresponds to an access key.
Unlike conventional access keys, access keys implemented as names
can be sold and traded independently. The licensing fee (paid as a name
registration) would be set by the developer and sent to a developer-controlled
blockchain address.</li>
</ul>
<p>Names within a namespace can serve any purpose the developer wants. The ability
to collect registration fees for 1 year after creating the namespace not only
gives developers the incentive to get users to participate in the app, but also
gives them a way to measure economic activity.</p>
<p>Developers can query individual namespaces and look up names within them using
the BNS API. The API offers routes to do the following:</p>
<h4id="list-all-namespaces-in-existence-reference">List all namespaces in existence (<ahref="https://core.blockstack.org/#namespace-operations-get-all-namespaces">reference</a>).</h4>
<h4id="list-all-names-within-a-namespace-reference">List all names within a namespace (<ahref="https://core.blockstack.org/#namespace-operations-get-all-namespaces">reference</a>)</h4>
<h4id="get-the-cost-to-register-a-namespace-reference">Get the Cost to Register a Namespace (<ahref="https://core.blockstack.org/#price-checks-get-namespace-price">reference</a>)</h4>
<p>If you want to register a namespace, please see the <ahref="namespace_creation.md">namespace creation tutorial</a>.</p>
<h4id="getting-the-current-consensus-hash-reference">Getting the Current Consensus Hash (<ahref="https://core.blockstack.org/#blockchain-operations-get-consensus-hash">reference</a>)</h4>
<p>In practice, the zone file hash is the <codeclass="highlighter-rouge">RIPEMD160</code> hash of the <codeclass="highlighter-rouge">SHA256</code> hash of
the zone file, and the public key is the <codeclass="highlighter-rouge">base58check</code>-encoded <codeclass="highlighter-rouge">RIPEMD160</code> hash
of the double-<codeclass="highlighter-rouge">SHA256</code> hash of the ECDSA public key (i.e. a Bitcoin address).</p>
<p>The BNS consensus rules ensure that
a BNS name can only be registered if it is not already taken, and that only the
user who owns the name’s private key can change its public key hash or zone file
hash. This means that a name’s public key and zone file can be stored anywhere,
since they can be authenticated using the hashes discovered by indexing the
blockchain under the BNS consensus rules.</p>
<p>BNS nodes implement a decentralized storage system for zone files called the
<ahref="atlas_network.md">Atlas network</a>. In this system, BNS nodes eagerly replicate
all the zone files they know about to one another, so that eventually every BNS
node has a full replica of all zone files.</p>
<p>The public keys for names are stored off-chain in <ahref="https://github.com/blockstack/gaia">Gaia</a>.
The user controls where their public keys are hosted using the zone file
contents (if they are hosted online anywhere at all).</p>
<p>Developers can query this table via the BNS API. The API offers routes
to do the following:</p>
<h4id="look-up-a-names-public-key-and-zone-file-reference">Look up a name’s public key and zone file (<ahref="https://core.blockstack.org/#name-querying-get-name-info">reference</a>)</h4>
<p>Note that the <codeclass="highlighter-rouge">zonefile</code> field is given with the off-chain data that hashes
to the <codeclass="highlighter-rouge">zonefile_hash</code> field.</p>
<h4id="list-all-names-the-node-knows-about-reference">List all names the node knows about (<ahref="https://core.blockstack.org/#name-querying-get-all-names">reference</a>)</h4>
<p>Each page returns 100 names. While no specific ordering is mandated by the
protocol, the reference implementation orders names by their order of creation
in the blockchain.</p>
<h4id="look-up-the-history-of-states-a-name-was-in-reference">Look up the history of states a name was in (<ahref="https://core.blockstack.org/#name-querying-name-history">reference</a>)</h4>
<p>All of the above information is extracted from the blockchain. Each top-level
field encodes the states the name transitioned to at the given block height (e.g.
445838, 445851, 445873, adn 445884). At each block height, the name’s zone file
hashes are returned in the order they were discovered in the blockchain.</p>
<p>Each name state contains a lot of ancillary data that is used internally by
other API calls and client libraries. The relevant fields for this document’s
scope are:</p>
<ul>
<li><codeclass="highlighter-rouge">address</code>: This is the base58check-encoded public key hash.</li>
<li><codeclass="highlighter-rouge">name</code>: This is the name queried.</li>
<li><codeclass="highlighter-rouge">value_hash</code>: This is the zone file hash.</li>
<li><codeclass="highlighter-rouge">opcode</code>: This is the type of transaction that was processed.</li>
<li><codeclass="highlighter-rouge">txid</code>: This is the transaction ID in the underlying blockchain.</li>
</ul>
<p>The name’s <em>entire</em> history is returned. This includes the history of the name
under its previous owner, if the name expired and was reregistered.</p>
<h4id="look-up-the-list-of-names-owned-by-a-given-public-key-hash-reference">Look up the list of names owned by a given public key hash (<ahref="https://core.blockstack.org/#name-querying-get-names-owned-by-address">reference</a>)</h4>
<p>Registering a BNS name costs cryptocurrency. This cost comes from two sources:</p>
<ul>
<li>
<p><strong>Transaction fees:</strong> These are the fees imposed by the cost of storing the
transaction data to the blockchain itself. They are independent of BNS, since
all of the blockchain’s users are competing to have their transactions included
in the next block. The blockchain’s miners receive the transaction fee.</p>
</li>
<li>
<p><strong>Registration fees:</strong> Each BNS namespace imposes an <em>additional</em> fee on how
much a name costs. The registration fee is sent to the namespace creator
during the first year that a namespace exists, and is sent to a burn address
afterwards. The registration fee is different for each name and is
determined by the namespace itself, but can be queried in advance by the user.</p>
</li>
</ul>
<p>Registering a name takes two transactions. They are:</p>
<ul>
<li>
<p><strong><codeclass="highlighter-rouge">NAME_PREORDER</code> transaction</strong>: This is the first transaction to be sent.
It tells all BNS nodes the <em>salted hash</em> of the BNS name, and it pays the
registration fee to the namespace owner’s designated address (or the burn
address). In addition, it proves to the BNS nodes that the client knows about
the current state of the system by including a recent <em>consensus hash</em>
in the transaction (see the section on <ahref="#bns-forks">BNS forks</a> for details).</p>
</li>
<li>
<p><strong><codeclass="highlighter-rouge">NAME_REGISTRATION</code> transaction</strong>: This is the second transaction to be
sent. It reveals the salt and the name to all BNS nodes, and assigns the name
an initial public key hash and zone file hash</p>
</li>
</ul>
<p>The reason this process takes two transactions is to prevent front-running.
The BNS consensus rules stipulate that a name can only be registered if its
matching preorder transaction was sent in the last 24 hours. Because a name
must be preordered before it is registered, someone watching the blockchain’s
peer network cannot race a victim to claim the name they were trying to
register (i.e. the attacker would have needed to send a <codeclass="highlighter-rouge">NAME_PREORDER</code>
transaction first, and would have had to have sent it no more than 24 hours
ago).</p>
<p>Registering a name on top of the Bitcoin blockchain takes 1-2 hours. This is
because you need to wait for the <codeclass="highlighter-rouge">NAME_PREORDER</code> transaction to be sufficiently
confirmed before sending the <codeclass="highlighter-rouge">NAME_REGISTRATION</code> transaction. The BNS nodes
only register the name once both transactions have at least 6 confirmations
(which itself usually takes about an hour).</p>
<p>Names are registered on a first-come first-serve basis.
If two different people try to register the same name at the same time, the
person who completes the two-step process <em>earliest</em> will receive the name. The
other person’s <codeclass="highlighter-rouge">NAME_REGISTRATION</code> transaction will be ignored, since it will
not be considered valid at this point. The registration fee paid by the
<codeclass="highlighter-rouge">NAME_PREORDER</code> will be lost. However, this situation is rare in practice—
as of early 2018, we only know of one confirmed instance in the system’s 3+ years
of operation.</p>
<p>Fully-qualified names can be between 3 and 37 characters long, and consist of
the characters <codeclass="highlighter-rouge">a-z</code>, <codeclass="highlighter-rouge">0-9</code>, <codeclass="highlighter-rouge">+</code>, <codeclass="highlighter-rouge">-</code>, <codeclass="highlighter-rouge">_</code>, and <codeclass="highlighter-rouge">.</code>. This is to prevent
<p>Note the use of <codeclass="highlighter-rouge">jq -r</code> to select the <codeclass="highlighter-rouge">"name_price"</code> field. This API
endpoint may return other ancilliary data regarding transaction fee estimation,
but this is the only field guaranteed by this specification to be present.</p>
<h4id="getting-the-current-consensus-hash-reference-1">Getting the Current Consensus Hash (<ahref="https://core.blockstack.org/#blockchain-operations-get-consensus-hash">reference</a>)</h4>
<td>This changes the name’s public key hash. In addition, the current owner has the option to atomically clear the name’s zone file hash (so the new owner won’t “receive” the zone file).</td>
<p>Depending in the namespace rules, a name can expire. For example, names in the
<codeclass="highlighter-rouge">.id</code> namespace expire after 2 years. You need to send a <codeclass="highlighter-rouge">NAME_RENEWAL</code> every
so often to keep your name.</p>
<p>A <codeclass="highlighter-rouge">NAME_RENEWAL</code> costs both transaction fees and registration fees. You will
pay the registration cost of your name to the namespace’s designated burn address when you
renew it. You can find this fee using the <codeclass="highlighter-rouge">/v1/prices/names/{name}</code> endpoint.</p>
<p>When a name expires, it enters a month-long “grace period” (5000 blocks). It
will stop resolving in the grace period, and all of the above operations will
cease to be honored by the BNS consensus rules. You may, however, send a
<codeclass="highlighter-rouge">NAME_RENEWAL</code> during this grace period to preserve your name.</p>
<p>If your name is in a namespace where names do not expire, then you never need to
use this transaction.</p>
<p>When you send a <codeclass="highlighter-rouge">NAME_RENEWAL</code>, you have the option of also setting a new public
key hash and a new zone file hash. See the <ahref="wire-format.md">transaction format</a>
document for details on how to construct this transaction.</p>
<h2id="bns-subdomains">BNS Subdomains</h2>
<p>BNS names are strongly-owned because the owner of its private key can generate
valid transactions that update its zone file hash and owner. However, this comes at the
cost of requiring a name owner to pay for the underlying transaction in the
blockchain. Moreover, this approach limits the rate of BNS name registrations
and operations to the underlying blockchain’s transaction bandwidth.</p>
<p>BNS overcomes this with subdomains. A <strong>BNS subdomain</strong> is a type of BNS name whose state
and owner are stored outside of the blockchain, but whose existence and
operation history are anchored to the
blockchain. In the example table in the <ahref="#resolving-bns-names">Resolving BNS
Names</a> section, the names <codeclass="highlighter-rouge">cicero.res_publica.id</code> and
<codeclass="highlighter-rouge">podsaveamerica.verified.podcast</code> are subdomains.</p>
<p>Like their on-chain counterparts, subdomains are globally
unique, strongly-owned, and human-readable. BNS gives them their own name state
and public keys.</p>
<p>Unlike on-chain names, subdomains can be created and managed
cheaply, because they are broadcast to the
BNS network in batches. A single blockchain transaction can send up to 120
subdomain operations.</p>
<p>This is achieved by storing subdomain records in the <ahref="atlas_network.md">Atlas Network</a>.
An on-chain name owner broadcasts subdomain operations by encoding them as
<codeclass="highlighter-rouge">TXT</code> records within a DNS zone file. To broadcast the zone file,
the name owner sets the new zone file hash with a <codeclass="highlighter-rouge">NAME_UPDATE</code> transaction and
replicates the zone file via Atlas. This, in turn, replicates all subdomain
operations it contains, and anchors the set of subdomain operations to
an on-chain transaction. The BNS node’s consensus rules ensure that only
valid subdomain operations from <em>valid</em><codeclass="highlighter-rouge">NAME_UPDATE</code> transactions will ever be
stored.</p>
<p>For example, the name <codeclass="highlighter-rouge">verified.podcast</code> once wrote the zone file hash <codeclass="highlighter-rouge">247121450ca0e9af45e85a82e61cd525cd7ba023</code>,
<spanclass="s2">"zonefile_txt"</span>: <spanclass="s2">"</span><spanclass="nv">$ORIGIN</span><spanclass="s2"> 1yeardaily</span><spanclass="se">\n</span><spanclass="nv">$TTL</span><spanclass="s2"> 3600</span><spanclass="se">\n</span><spanclass="s2">_http._tcp URI 10 1 </span><spanclass="se">\"</span><spanclass="s2">https://ph.dotpodcast.co/1yeardaily/head.json</span><spanclass="se">\"\n</span><spanclass="s2">"</span>
<spanclass="o">}</span>
</code></pre>
</div>
<p>This information was extracted from the <codeclass="highlighter-rouge">1yeardaily</code><codeclass="highlighter-rouge">TXT</code> resource record in the zone
file for <codeclass="highlighter-rouge">verified.podcast</code>.</p>
<p>Developers interact with subdomains the same way they interact with names.
Using the BNS API, a developer can:</p>
<h4id="look-up-a-subdomains-public-key-and-zone-file-reference">Look up a subdomain’s public key and zone file (<ahref="https://core.blockstack.org/#name-querying-get-name-info">reference</a>)</h4>
<spanclass="s2">"zonefile_txt"</span>: <spanclass="s2">"</span><spanclass="nv">$ORIGIN</span><spanclass="s2"> aaron.personal.id</span><spanclass="se">\n</span><spanclass="nv">$TTL</span><spanclass="s2"> 3600</span><spanclass="se">\n</span><spanclass="s2">_https._tcp URI 10 1 </span><spanclass="se">\"</span><spanclass="s2">https://gaia.blockstack.org/hub/1PwztPFd1s2STMv4Ntq6UPBdYgHSBr5pdF/profile.json</span><spanclass="se">\"\n</span><spanclass="s2">"</span>
<spanclass="o">}</span>
</code></pre>
</div>
<h4id="look-up-a-subdomains-transaction-history-reference">Look up a subdomain’s transaction history (<ahref="https://core.blockstack.org/#name-querying-name-history">reference</a>)</h4>
<h4id="look-up-the-list-of-names-and-subdomains-owned-by-a-given-public-key-hash-reference">Look up the list of names and subdomains owned by a given public key hash (<ahref="https://core.blockstack.org/#name-querying-get-names-owned-by-address">reference</a>)</h4>
<li><codeclass="highlighter-rouge"><spanclass="p">{</span><spanclass="err">address</span><spanclass="p">}</span></code> is an on-chain public key hash (e.g. a Bitcoin address).</li>
<li><codeclass="highlighter-rouge"><spanclass="p">{</span><spanclass="err">index</span><spanclass="p">}</span></code> refers to the <codeclass="highlighter-rouge">nth</code> name this address created.</li>
</ul>
<p>For example, the DID for <codeclass="highlighter-rouge">personal.id</code> is
<codeclass="highlighter-rouge">did:stack:v0:1dARRtzHPAFRNE7Yup2Md9w18XEQAtLiV-0</code>, because the name
<codeclass="highlighter-rouge">personal.id</code> was the first-ever name created by
<p>As another example, the DID for <codeclass="highlighter-rouge">jude.id</code> is <codeclass="highlighter-rouge">did:stack:v0:16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg-1</code>.
Here, the address <codeclass="highlighter-rouge">16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg</code> had created one earlier
name in history prior to this one (which happens to be <codeclass="highlighter-rouge">abcdefgh123456.id</code>).</p>
<p>The purpose of a DID is to provide an eternal identifier for a public key.
The public key may change, but the DID will not.</p>
<p>Blockstack Core implements a DID method of its own
in order to be compatible with other systems that use DIDs for public key resolution.
In order for a DID to be resolvable, all of the following must be true for a
name:</p>
<ul>
<li>The name must exist</li>
<li>The name’s zone file hash must be the hash of a well-formed DNS zone file</li>
<li>The DNS zone file must be present in the BNS <ahref="atlas_network.md">Atlas Network</a></li>
<li>The DNS zone file must contain a <codeclass="highlighter-rouge">URI</code> resource record that points to a signed
JSON Web Token</li>
<li>The public key that signed the JSON Web Token (and is included with it) must
hash to the address that owns the name</li>
</ul>
<p>Not all names will have DIDs that resolve to public keys. However, names created by the <ahref="https://github.com/blockstack/blockstack-browser">Blockstack
Browser</a> will have DIDs that
do.</p>
<p>Developers can programmatically resolve DIDs via the Python API:</p>
<h3id="did-encoding-for-subdomains">DID Encoding for Subdomains</h3>
<p>Every name and subdomain in BNS has a DID. The encoding is slightly different
for subdomains, so the software can determine which code-path to take.</p>
<ul>
<li>
<p>For on-chain BNS names, the <codeclass="highlighter-rouge"><spanclass="p">{</span><spanclass="err">address</span><spanclass="p">}</span></code> is the same as the Bitcoin address
that owns the name. Currently, both version byte 0 and version byte 5
addresses are supported (i.e. addresses starting with <codeclass="highlighter-rouge">1</code> or <codeclass="highlighter-rouge">3</code>, meaning <codeclass="highlighter-rouge">p2pkh</code> and
<p>For off-chain BNS subdomains, the <codeclass="highlighter-rouge"><spanclass="p">{</span><spanclass="err">address</span><spanclass="p">}</span></code> has version byte 63 for
subdomains owned by a single private key, and version byte 50 for subdomains
owned by a m-of-n set of private keys. That is, subdomain DID addresses start
with <codeclass="highlighter-rouge">S</code> or <codeclass="highlighter-rouge">M</code>, respectively.</p>
</li>
</ul>
<p>The <codeclass="highlighter-rouge"><spanclass="p">{</span><spanclass="err">index</span><spanclass="p">}</span></code> field for a subdomain’s DID is distinct from the <codeclass="highlighter-rouge"><spanclass="p">{</span><spanclass="err">index</span><spanclass="p">}</span></code> field
for a BNS name’s DID, even if the same created both names and subdomains.
For example, the name <codeclass="highlighter-rouge">abcdefgh123456.id</code> has the DID <codeclass="highlighter-rouge">did:stack:v0:16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg-0</code>,
because it was the first name created by <codeclass="highlighter-rouge">16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg</code>.
However, <codeclass="highlighter-rouge">16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg</code><em>also</em> created <codeclass="highlighter-rouge">jude.statism.id</code>
as its first subdomain name. The DID for <codeclass="highlighter-rouge">jude.statism.id</code> is
<codeclass="highlighter-rouge">did:stack:v0:SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i-0</code>. Note that the address
<codeclass="highlighter-rouge">SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i</code> encodes the same public key hash as the address
<codeclass="highlighter-rouge">16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg</code> (the only difference between these two
strings is that the first is base58check-encoded with version byte 0, and the
second is encoded with version byte 63).</p>
<p>You can see this play out in practice with the following code snippit:</p>