mirror of https://github.com/lukechilds/docs.git
moxiegirl
6 years ago
25 changed files with 1157 additions and 607 deletions
@ -0,0 +1,793 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
|
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<!-- Begin Jekyll SEO tag v2.5.0 --> |
|||
<title>Subdomain Design and Implementation | Blockstack</title> |
|||
<meta name="generator" content="Jekyll v3.5.0" /> |
|||
<meta property="og:title" content="Subdomain Design and Implementation" /> |
|||
<meta name="author" content="Blockstack" /> |
|||
<meta property="og:locale" content="en_US" /> |
|||
<meta name="description" content="Subdomain Design and Implementation" /> |
|||
<meta property="og:description" content="Subdomain Design and Implementation" /> |
|||
<link rel="canonical" href="http://localhost:4000/core/naming/tutorial_subdomains.html" /> |
|||
<meta property="og:url" content="http://localhost:4000/core/naming/tutorial_subdomains.html" /> |
|||
<meta property="og:site_name" content="Blockstack" /> |
|||
<meta property="og:type" content="article" /> |
|||
<meta property="article:published_time" content="2018-08-29T11:40:46-07:00" /> |
|||
<script type="application/ld+json"> |
|||
{"description":"Subdomain Design and Implementation","author":{"@type":"Person","name":"Blockstack"},"@type":"BlogPosting","url":"http://localhost:4000/core/naming/tutorial_subdomains.html","headline":"Subdomain Design and Implementation","dateModified":"2018-08-29T11:40:46-07:00","datePublished":"2018-08-29T11:40:46-07:00","mainEntityOfPage":{"@type":"WebPage","@id":"http://localhost:4000/core/naming/tutorial_subdomains.html"},"@context":"http://schema.org"}</script> |
|||
<!-- End Jekyll SEO tag --> |
|||
|
|||
<!-- <meta property="og:image" content="http://localhost:4000/assets/posts/logo.png"/> --> |
|||
<meta property="og:image" content="/assets/posts/logo.png"/> |
|||
<link rel="stylesheet" href="/assets/css/main.css"> |
|||
<link rel="shortcut icon" type="image/png" href="/assets/img/favicon.png" > |
|||
<link rel="alternate" type="application/rss+xml" title="Blockstack" href="/feed.xml"> |
|||
<script src="/assets/js/main.js"></script> |
|||
|
|||
</head> |
|||
|
|||
|
|||
<body> |
|||
|
|||
<header class="uk-background-secondary"> |
|||
<div data-uk-sticky="sel-target: .uk-navbar-container; cls-active: uk-navbar-sticky" class="uk-sticky uk-sticky-fixed" style="position: fixed; top: 0px; width: 1904px;"> |
|||
<nav class="uk-navbar-container"> |
|||
<div class="uk-container"> |
|||
<div data-uk-navbar> |
|||
<div class="uk-navbar-left"> |
|||
|
|||
<!-- <a class="uk-navbar-item uk-logo" href="/"><img src="http://localhost:4000/assets/posts/logo.png" alt="Docs"></a> --> |
|||
<a class="uk-navbar-item uk-logo" href="/"><img src="/assets/posts/logo.png" alt="Docs"></a> |
|||
|
|||
</div> |
|||
<div class="uk-navbar-right"> |
|||
<ul class="uk-navbar-nav uk-visible@m"> |
|||
|
|||
|
|||
|
|||
|
|||
<li><a href="https://blockstack.org" target="_blank" >Blockstack.org</a></li> |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
<li><a href="https://forum.blockstack.org/" target="_blank" >Forums</a></li> |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
<li><a href="https://github.com/blockstack" target="_blank" >GitHub</a></li> |
|||
|
|||
|
|||
</ul> |
|||
|
|||
|
|||
<div> |
|||
<a class="uk-navbar-toggle" uk-search-icon href="#"></a> |
|||
<div class="uk-drop uk-background-default uk-border-rounded" uk-drop="mode: click; pos: left-center; offset: 0"> |
|||
<form class="uk-search uk-search-navbar uk-width-1-1" onsubmit="return false;"> |
|||
<input id="searchBox" class="uk-search-input" type="search" placeholder="Search..." autofocus> |
|||
</form> |
|||
<ul id="searchBox-results" class="uk-position-absolute uk-width-1-1 uk-list"></ul> |
|||
</div> |
|||
</div> |
|||
<script> |
|||
SimpleJekyllSearch({ |
|||
searchInput: document.getElementById('searchBox'), |
|||
resultsContainer: document.getElementById('searchBox-results'), |
|||
noResultsText: '<li>No results found</li>', |
|||
searchResultTemplate: '<li><a href="{url}">{title}</a></li>', |
|||
json: '/search.json' |
|||
}); |
|||
</script> |
|||
|
|||
|
|||
<a class="uk-navbar-toggle uk-hidden@m" href="#offcanvas" data-uk-navbar-toggle-icon data-uk-toggle></a> |
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
</nav> |
|||
</div> |
|||
</header> |
|||
|
|||
|
|||
|
|||
|
|||
<div class="uk-section"> |
|||
<div class="uk-container"> |
|||
<div class="uk-grid-large" data-uk-grid> |
|||
|
|||
<div class="sidebar-fixed-width uk-visible@m"> |
|||
<div class="sidebar-docs uk-position-fixed"> |
|||
|
|||
<h5>Overview</h5> |
|||
<ul class="uk-nav uk-nav-default doc-nav"> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/naming/introduction.html">Blockstack Naming Service (BNS)</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/naming/architecture.html">Understand the Architecture</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/naming/namespaces.html">Understand Namespaces</a></li> |
|||
|
|||
</ul> |
|||
|
|||
<h5>Tutorials</h5> |
|||
<ul class="uk-nav uk-nav-default doc-nav"> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/naming/tutorial_creation.html">Creating a Namespace</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class="uk-active"><a href="/core/naming/tutorial_subdomains.html">Subdomain Design and Implementation</a></li> |
|||
|
|||
</ul> |
|||
|
|||
<h5>How to use BNS</h5> |
|||
<ul class="uk-nav uk-nav-default doc-nav"> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/naming/pickname.html">Choose a name</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/naming/resolving.html">Resolve a name</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/naming/register.html">Register a name</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/naming/manage.html">Manage BNS Names</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/naming/subdomains.html">BNS Subdomains</a></li> |
|||
|
|||
</ul> |
|||
|
|||
<h5>Other topics</h5> |
|||
<ul class="uk-nav uk-nav-default doc-nav"> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/naming/forks.html">BNS Forks</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/naming/did.html">DID Encoding for Subdomains</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/naming/comparison.html">Naming system feature comparison</a></li> |
|||
|
|||
</ul> |
|||
|
|||
</div> |
|||
</div> |
|||
|
|||
<div class="uk-width-1-1 uk-width-expand@m"> |
|||
|
|||
<article class="uk-article"> |
|||
|
|||
<h1 class="uk-article-title">Subdomain Design and Implementation</h1> |
|||
|
|||
|
|||
|
|||
<div class="uk-article-meta uk-margin-top uk-margin-medium-bottom"> |
|||
|
|||
|
|||
|
|||
<!-- <img class="avatar avatar-small" alt="Blockstack" width="32" height="32" data-proofer-ignore="true" src="https://avatars2.githubusercontent.com/Blockstack?v=3&s=32" srcset="https://avatars2.githubusercontent.com/Blockstack?v=3&s=32 1x, https://avatars2.githubusercontent.com/Blockstack?v=3&s=64 2x, https://avatars2.githubusercontent.com/Blockstack?v=3&s=96 3x, https://avatars2.githubusercontent.com/Blockstack?v=3&s=128 4x" /> --> |
|||
|
|||
|
|||
|
|||
<!-- Written by <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">Blockstack</span></span><br> --> |
|||
|
|||
|
|||
<time datetime="2018-08-29T11:40:46-07:00" itemprop="datePublished"> |
|||
|
|||
<a "target="_blank" href="https://github.com/moxiegirl/docs-new/blob/master/_core/naming/tutorial_subdomains.md" class="btn btn-default githubEditButton" role="button"><span data-uk-icon="icon: pencil; ratio: 1.2"></span> Edit this page on Github</a> |
|||
<span style="font-family:Wingdings">w</span> Aug 29, 2018 |
|||
</time> |
|||
|
|||
</div> |
|||
|
|||
<div class="article-content"> |
|||
|
|||
<p class="no_toc">Subdomains allow us to provide names to end users cheaply (and quickly). This |
|||
tutorial explains you how to create, register, and run a subdomain register, it |
|||
contains the following sections:</p> |
|||
|
|||
<ul id="markdown-toc"> |
|||
<li><a href="#strong-subdomain-ownership" id="markdown-toc-strong-subdomain-ownership">Strong subdomain ownership</a></li> |
|||
<li><a href="#overall-design" id="markdown-toc-overall-design">Overall Design</a></li> |
|||
<li><a href="#zonefile-format" id="markdown-toc-zonefile-format">Zonefile Format</a> <ul> |
|||
<li><a href="#operations-per-zonefile" id="markdown-toc-operations-per-zonefile">Operations per Zonefile</a></li> |
|||
</ul> |
|||
</li> |
|||
<li><a href="#domain-operator-endpoint" id="markdown-toc-domain-operator-endpoint">Domain Operator Endpoint</a> <ul> |
|||
<li><a href="#configuration-and-registration-files" id="markdown-toc-configuration-and-registration-files">Configuration and Registration Files</a></li> |
|||
<li><a href="#register-subdomain" id="markdown-toc-register-subdomain">Register Subdomain</a></li> |
|||
<li><a href="#check-subdomain-registration-status" id="markdown-toc-check-subdomain-registration-status">Check subdomain registration status</a></li> |
|||
<li><a href="#updating-entries" id="markdown-toc-updating-entries">Updating Entries</a></li> |
|||
</ul> |
|||
</li> |
|||
<li><a href="#resolver-behavior" id="markdown-toc-resolver-behavior">Resolver Behavior</a> <ul> |
|||
<li><a href="#supported-core--resolver-endpoints" id="markdown-toc-supported-core--resolver-endpoints">Supported Core / Resolver Endpoints</a></li> |
|||
<li><a href="#subdomain-caching" id="markdown-toc-subdomain-caching">Subdomain Caching</a></li> |
|||
<li><a href="#testing-subdomain-registrar-and-resolution" id="markdown-toc-testing-subdomain-registrar-and-resolution">Testing Subdomain Registrar and Resolution</a></li> |
|||
<li><a href="#running-an-interactive-testing-environment-with-the-subdomain-registrar-service" id="markdown-toc-running-an-interactive-testing-environment-with-the-subdomain-registrar-service">Running an interactive testing environment with the Subdomain Registrar service</a></li> |
|||
</ul> |
|||
</li> |
|||
</ul> |
|||
|
|||
<h2 id="strong-subdomain-ownership">Strong subdomain ownership</h2> |
|||
|
|||
<p>For those who are new to this concept, it’s a model where domains can |
|||
permanently, cryptographically delegate subdomains to particular keys, |
|||
relinquishing their ability to revoke the names or change the name |
|||
resolution details.</p> |
|||
|
|||
<p>These names will be indicated with an <code class="highlighter-rouge">.</code>, e.g., <code class="highlighter-rouge">foo.bar.id</code></p> |
|||
|
|||
<h2 id="overall-design">Overall Design</h2> |
|||
|
|||
<p>We can do this today with a special indexer & resolver endpoint and |
|||
without any changes to the core protocol.</p> |
|||
|
|||
<p>We can do this by having a zone file record for each subdomain <em>i</em> |
|||
containing the following information:</p> |
|||
|
|||
<ol> |
|||
<li>An owner address <em>addr</em></li> |
|||
<li>A sequence number <em>N</em></li> |
|||
<li>A zonefile</li> |
|||
<li>A signature <em>S</em> of the above</li> |
|||
</ol> |
|||
|
|||
<p>The signature <em>S_i</em> must be verifiable with the address in the |
|||
<em>(N-1)</em>th entry for subdomain <em>i</em>.</p> |
|||
|
|||
<h2 id="zonefile-format">Zonefile Format</h2> |
|||
|
|||
<p>For now, the resolver will use an <em>TXT</em> record per subdomain to define |
|||
this information. The entry name will be <code class="highlighter-rouge">$(subdomain)</code>.</p> |
|||
|
|||
<p>We’ll use the format of <a href="https://tools.ietf.org/html/rfc1464">RFC 1464</a> |
|||
for the TXT entry. We’ll have the following strings with identifiers:</p> |
|||
|
|||
<ol> |
|||
<li><strong>parts</strong> : this specifies the number of pieces that the |
|||
zonefile has been chopped into. TXT strings can only be 255 bytes, |
|||
so we chop up the zonefile.</li> |
|||
<li><strong>zf{n}</strong>: part <em>n</em> of the zonefile, base64 encoded</li> |
|||
<li><strong>owner</strong>: the owner address delegated to operate the subdomain</li> |
|||
<li><strong>seqn</strong>: the sequence number</li> |
|||
<li><strong>sig</strong>: signature of the above data.</li> |
|||
</ol> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code>$ORIGIN bar.id |
|||
$TTL 3600 |
|||
pubkey TXT "pubkey:data:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" |
|||
registrar URI 10 1 "bsreg://foo.com:8234" |
|||
aaron TXT "owner=33VvhhSQsYQyCVE2VzG3EHa9gfRCpboqHy" "seqn=0" "parts=1" "zf0=JE9SSUdJTiBhYXJvbgokVFRMIDM2MDAKbWFpbiBVUkkgMSAxICJwdWJrZXk6ZGF0YTowMzAyYWRlNTdlNjNiMzc1NDRmOGQ5Nzk4NjJhNDlkMDBkYmNlMDdmMjkzYmJlYjJhZWNmZTI5OTkxYTg3Mzk4YjgiCg==" |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>The <code class="highlighter-rouge">registrar</code> entry indicates how to contact the registrar service |
|||
for clients of the domain wishing to register or modify their entry.</p> |
|||
|
|||
<h3 id="operations-per-zonefile">Operations per Zonefile</h3> |
|||
|
|||
<p>At 4kb zonefile size, we can only fit around 20 updates per zonefile.</p> |
|||
|
|||
<h2 id="domain-operator-endpoint">Domain Operator Endpoint</h2> |
|||
|
|||
<p>The directory <code class="highlighter-rouge">subdomain_registrar/</code> contains our code for running a |
|||
subdomain registrar. It can be executed by running:</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code>$ blockstack-subdomain-registrar start foo.id |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>Here, <code class="highlighter-rouge">foo.id</code> is the domain for which subdomains will be associated.</p> |
|||
|
|||
<h3 id="configuration-and-registration-files">Configuration and Registration Files</h3> |
|||
|
|||
<p>Configuration of the subdomain registrar is done through <code class="highlighter-rouge">~/.blockstack_subdomains/config.ini</code></p> |
|||
|
|||
<p>The sqlite database which stores the registrations is located alongside the config <code class="highlighter-rouge">~/.blockstack_subdomains/registrar.db</code>.</p> |
|||
|
|||
<p>You can change the location of the config file (and the database), by setting the environment variable <code class="highlighter-rouge">BLOCKSTACK_SUBDOMAIN_CONFIG</code></p> |
|||
|
|||
<h3 id="register-subdomain">Register Subdomain</h3> |
|||
|
|||
<p>Subdomain registrations can be submitted to this endpoint using a REST |
|||
API.</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code>POST /register |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>The schema for registration is:</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="w"> |
|||
</span><span class="err">'type'</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="err">'object',</span><span class="w"> |
|||
</span><span class="err">'properties'</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="err">{</span><span class="w"> |
|||
</span><span class="err">'name'</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="err">{</span><span class="w"> |
|||
</span><span class="err">'type':</span><span class="w"> </span><span class="err">'string',</span><span class="w"> |
|||
</span><span class="err">'pattern':</span><span class="w"> </span><span class="err">'([a-z0-9\-_+]{3,36</span><span class="p">}</span><span class="err">)$'</span><span class="w"> |
|||
</span><span class="err">},</span><span class="w"> |
|||
</span><span class="err">'owner_address'</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
|||
</span><span class="err">'type':</span><span class="w"> </span><span class="err">'string',</span><span class="w"> |
|||
</span><span class="err">'pattern':</span><span class="w"> </span><span class="err">schemas.OP_ADDRESS_PATTERN</span><span class="w"> |
|||
</span><span class="p">}</span><span class="err">,</span><span class="w"> |
|||
</span><span class="err">'zonefile'</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
|||
</span><span class="err">'type'</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="err">'string',</span><span class="w"> |
|||
</span><span class="err">'maxLength'</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="err">blockstack_constants.RPC_MAX_ZONEFILE_LEN</span><span class="w"> |
|||
</span><span class="p">}</span><span class="w"> |
|||
</span><span class="err">},</span><span class="w"> |
|||
</span><span class="err">'required':</span><span class="p">[</span><span class="w"> |
|||
</span><span class="err">'name'</span><span class="p">,</span><span class="w"> </span><span class="err">'owner_address'</span><span class="p">,</span><span class="w"> </span><span class="err">'zonefile'</span><span class="w"> |
|||
</span><span class="p">]</span><span class="err">,</span><span class="w"> |
|||
</span><span class="err">'additionalProperties'</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="err">True</span><span class="w"> |
|||
</span><span class="err">}</span><span class="w"> |
|||
</span></code></pre> |
|||
</div> |
|||
|
|||
<p>The registrar will:</p> |
|||
|
|||
<ol> |
|||
<li>Check if the subdomain <code class="highlighter-rouge">foo</code> exists already on the domain.</li> |
|||
<li>Add the subdomain to the queue.</li> |
|||
</ol> |
|||
|
|||
<p>On success, this returns <code class="highlighter-rouge">202</code> and the message</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"true"</span><span class="p">,</span><span class="w"> </span><span class="nt">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Subdomain registration queued."</span><span class="p">}</span><span class="w"> |
|||
</span></code></pre> |
|||
</div> |
|||
|
|||
<p>When the registrar wakes up to prepare a transaction, it packs the queued |
|||
registrations together and issues an <code class="highlighter-rouge">UPDATE</code>.</p> |
|||
|
|||
<h3 id="check-subdomain-registration-status">Check subdomain registration status</h3> |
|||
|
|||
<p>A user can check on the registration status of their name via querying the |
|||
registrar.</p> |
|||
|
|||
<p>This is an API call:</p> |
|||
<div class="highlighter-rouge"><pre class="highlight"><code>GET /status/{subdomain} |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>The registrar checks if the subdomain has propagated (i.e., the |
|||
registration is completed), in which case the following is returned:</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Subdomain already propagated"</span><span class="p">}</span><span class="w"> |
|||
</span></code></pre> |
|||
</div> |
|||
|
|||
<p>Or, if the subdomain has already been submitted in a transaction:</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Your subdomain was registered in transaction 09a40d6ea362608c68da6e1ebeb3210367abf7aa39ece5fd57fd63d269336399 -- it should propagate on the network once it has 6 confirmations."</span><span class="p">}</span><span class="w"> |
|||
</span></code></pre> |
|||
</div> |
|||
|
|||
<p>If the subdomain still hasn’t been submitted yet:</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Subdomain is queued for update and should be announced within the next few blocks."</span><span class="p">}</span><span class="w"> |
|||
</span></code></pre> |
|||
</div> |
|||
|
|||
<p>If an error occurred trying to submit the <code class="highlighter-rouge">UPDATE</code> transaction, this endpoint will return an error |
|||
message in the <code class="highlighter-rouge">"error"</code> key of a JSON object.</p> |
|||
|
|||
<h3 id="updating-entries">Updating Entries</h3> |
|||
|
|||
<p>The subdomain registrar does not currently support updating subdomain entries.</p> |
|||
|
|||
<h2 id="resolver-behavior">Resolver Behavior</h2> |
|||
|
|||
<p>When a lookup like <code class="highlighter-rouge">foo.bar.id</code> hits the resolver, the resolver will need to:</p> |
|||
|
|||
<ol> |
|||
<li>Lookup the zonefile history of <code class="highlighter-rouge">bar.id</code></li> |
|||
<li>Fetch all these zonefiles and filter by operations on <code class="highlighter-rouge">foo</code></li> |
|||
<li>Verify that all <code class="highlighter-rouge">foo</code> operations are correct</li> |
|||
<li>Return the latest record for foo</li> |
|||
<li>Do a profile lookup for <code class="highlighter-rouge">foo.bar.id</code> by fetching the URLs in the entry. |
|||
<em>Note</em>, this spec does not define a priority order for fetching those URLs.</li> |
|||
</ol> |
|||
|
|||
<h3 id="supported-core--resolver-endpoints">Supported Core / Resolver Endpoints</h3> |
|||
|
|||
<p>Generally, domain endpoints are not aware of subdomains (only endpoints |
|||
aware of subdomains is <code class="highlighter-rouge">/v1/users/<foo.bar.tld></code>, |
|||
<code class="highlighter-rouge">/v1/names/<foo.bar.tld></code>, and <code class="highlighter-rouge">/v1/addresses/bitcoin/<foo.bar.tld></code>) |
|||
The endpoints which <em>are</em> subdomain aware are marked as such in |
|||
[api-specs.md], the cli command <code class="highlighter-rouge">blockstack lookup</code> is subdomain |
|||
aware.</p> |
|||
|
|||
<p>This means that search is <em>not</em> yet supported.</p> |
|||
|
|||
<p>The lookups work just like normal – it returns the user’s |
|||
profile object:</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code>$ curl -H "Authorization: bearer blockstack_integration_test_api_password" -H "Origin: http://localhost:3000" http://localhost:16268/v1/users/bar.foo.id -v -s | python -m json.tool |
|||
* Trying 127.0.0.1... |
|||
* Connected to localhost (127.0.0.1) port 16268 (#0) |
|||
> GET /v1/users/bar.foo.id HTTP/1.1 |
|||
> Host: localhost:16268 |
|||
> User-Agent: curl/7.50.1 |
|||
> Accept: */* |
|||
> Authorization: bearer blockstack_integration_test_api_password |
|||
> Origin: http://localhost:3000 |
|||
> |
|||
* HTTP 1.0, assume close after body |
|||
< HTTP/1.0 200 OK |
|||
< Server: SimpleHTTP/0.6 Python/2.7.12+ |
|||
< Date: Thu, 03 Aug 2017 14:39:16 GMT |
|||
< content-type: application/json |
|||
< Access-Control-Allow-Origin: * |
|||
< |
|||
{ [66 bytes data] |
|||
* Closing connection 0 |
|||
{ |
|||
"bar": { |
|||
"@type": "Person", |
|||
"description": "Lorem Ipsum Bazorem" |
|||
} |
|||
} |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>Name info lookups are also supported (this should enable authenticating logins |
|||
with <code class="highlighter-rouge">blockstack.js</code>, but I will need to double check).</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code>$ curl -H "Authorization: bearer XXXX" -H "Origin: http://localhost:3000" http://localhost:6270/v1/names/created_equal.self_evident_truth.id -s | python -m json.tool |
|||
{ |
|||
"address": "1AYddAnfHbw6bPNvnsQFFrEuUdhMhf2XG9", |
|||
"blockchain": "bitcoin", |
|||
"expire_block": -1, |
|||
"last_txid": "0bacfd5a3e0ec68723d5948d6c1a04ad0de1378c872d45fa2276ebbd7be230f7", |
|||
"satus": "registered_subdomain", |
|||
"zonefile_hash": "48fc1b351ce81cf0a9fd9b4eae7a3f80e93c0451", |
|||
"zonefile_txt": "$ORIGIN created_equal\n$TTL 3600\n_https._tcp URI 10 1 \"https://www.cs.princeton.edu/~ablankst/created_equal.json\"\n_file URI 10 1 \"file:///tmp/created_equal.json\"\n" |
|||
} |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<h3 id="subdomain-caching">Subdomain Caching</h3> |
|||
|
|||
<p>A resolver <em>caches</em> a subdomain’s state by keeping a database of all |
|||
the current subdomain records. This database is automatically updated |
|||
when a new zonefile for a particularly domain is seen by the resolver |
|||
(this is performed lazily).</p> |
|||
|
|||
<h3 id="testing-subdomain-registrar-and-resolution">Testing Subdomain Registrar and Resolution</h3> |
|||
|
|||
<p>You can run a subdomain registrar and resolver with blockstack-core in |
|||
regtest mode as follows:</p> |
|||
|
|||
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="nv">IMAGE</span><span class="o">=</span><span class="k">$(</span>docker run -dt -p 3000:3000 -p 6270:6270 -p 16269:16269 -p 18332:18332 -e <span class="nv">BLOCKSTACK_TEST_CLIENT_RPC_PORT</span><span class="o">=</span>6270 -e <span class="nv">BLOCKSTACK_TEST_CLIENT_BIND</span><span class="o">=</span>0.0.0.0 -e <span class="nv">BLOCKSTACK_TEST_BITCOIND_ALLOWIP</span><span class="o">=</span>172.17.0.0/16 quay.io/blockstack/integrationtests:master blockstack-test-scenario --interactive 2 blockstack_integration_tests.scenarios.browser_env<span class="k">)</span> |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>Once you see <code class="highlighter-rouge">Test finished; doing checks</code> in that container’s logs, the |
|||
registrar has started and is ready to accept requests. (We recommend |
|||
following the docker instructions below for running this test in |
|||
Docker, as it will fetch the source code for the registrar and set the |
|||
correct environment variables for it to run).</p> |
|||
|
|||
<p>Once this environment has started, you can issue a registration request from curl:</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code>curl -X POST -H 'Content-Type: application/json' --data '{"zonefile": "$ORIGIN baz\n$TTL 3600\n_file URI 10 1 \"file:///tmp/baz.profile.json\"\n", "name": "baz", "owner_address": "14x2EMRz1gf16UzGbxZh2c6sJg4A8wcHLD"}' http://localhost:3000/register/ |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>This registers <code class="highlighter-rouge">baz.foo.id</code> – you can check the registrar’s status with</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code>curl http://localhost:3000/status/baz |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>The API endpoints <code class="highlighter-rouge">/v1/users/<foo.bar.tld></code>, |
|||
<code class="highlighter-rouge">/v1/names/<foo.bar.tld></code>, and <code class="highlighter-rouge">/v1/addresses/bitcoin/<foo.bar.tld></code> all work, so if you query the core API, you’ll get a response.</p> |
|||
|
|||
<p>For example:</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code>curl http://localhost:6270/v1/names/baz.foo.id | python -m json.tool |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>Will return:</p> |
|||
<div class="highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="w"> |
|||
</span><span class="nt">"address"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1Nup2UcbVuVoDZeZCtR4vjSkrvTi8toTqc"</span><span class="p">,</span><span class="w"> |
|||
</span><span class="nt">"blockchain"</span><span class="p">:</span><span class="w"> </span><span class="s2">"bitcoin"</span><span class="p">,</span><span class="w"> |
|||
</span><span class="nt">"expire_block"</span><span class="p">:</span><span class="w"> </span><span class="mi">-1</span><span class="p">,</span><span class="w"> |
|||
</span><span class="nt">"last_txid"</span><span class="p">:</span><span class="w"> </span><span class="s2">"43bbcbd8793cdc52f1b0bd2713ed136f4f104a683a9fd5c89911a57a8c4b28b6"</span><span class="p">,</span><span class="w"> |
|||
</span><span class="nt">"satus"</span><span class="p">:</span><span class="w"> </span><span class="s2">"registered_subdomain"</span><span class="p">,</span><span class="w"> |
|||
</span><span class="nt">"zonefile_hash"</span><span class="p">:</span><span class="w"> </span><span class="s2">"e7e3aada18c9ac5189f1c54089e987f58c0fa51e"</span><span class="p">,</span><span class="w"> |
|||
</span><span class="nt">"zonefile_txt"</span><span class="p">:</span><span class="w"> </span><span class="s2">"$ORIGIN bar\n$TTL 3600\n_file URI 10 1 \"file:///tmp/baz.profile.json\"\n"</span><span class="w"> |
|||
</span><span class="p">}</span><span class="w"> |
|||
</span></code></pre> |
|||
</div> |
|||
|
|||
<h3 id="running-an-interactive-testing-environment-with-the-subdomain-registrar-service">Running an interactive testing environment with the Subdomain Registrar service</h3> |
|||
|
|||
<p>Follow the <a href="../integration_tests/README.md">instructions here</a> to download the regtesting Docker image.</p> |
|||
|
|||
<p>Since the subdomain registrar service runs on port 3000, we need to do two things to expose this endpoint to interact with it from the browser:</p> |
|||
<ul> |
|||
<li>Open port 3000 with <code class="highlighter-rouge">-p 3000:3000</code></li> |
|||
</ul> |
|||
|
|||
<p>Here’s the full command you’d run to start the interactive testing scenario:</p> |
|||
|
|||
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="nv">IMAGE</span><span class="o">=</span><span class="k">$(</span>docker run -dt -p 3000:3000 -p 6270:6270 -p 16269:16269 -p 18332:18332 -e <span class="nv">BLOCKSTACK_TEST_CLIENT_RPC_PORT</span><span class="o">=</span>6270 -e <span class="nv">BLOCKSTACK_TEST_CLIENT_BIND</span><span class="o">=</span>0.0.0.0 -e <span class="nv">BLOCKSTACK_TEST_BITCOIND_ALLOWIP</span><span class="o">=</span>172.17.0.0/16 quay.io/blockstack/integrationtests:master blockstack-test-scenario --interactive 2 blockstack_integration_tests.scenarios.browser_env<span class="k">)</span> |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<div class="share uk-text-center"> |
|||
<a href="https://twitter.com/intent/tweet?text=Subdomain Design and Implementation&url=http://localhost:4000/core/naming/tutorial_subdomains.html&via=&related=" rel="nofollow" target="_blank" title="Share on Twitter" onclick="window.open(this.href, 'twitter', 'width=550,height=235');return false;"><span data-uk-icon="icon: twitter; ratio: 1.2"></span></a> |
|||
<a class="uk-margin-small-left" href="https://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Flocalhost%3A4000%2Fcore%2Fnaming%2Ftutorial_subdomains.html" rel="nofollow" target="_blank" title="Share on Facebook" onclick="window.open(this.href, 'facebook-share','width=580,height=296');return false;"><span data-uk-icon="icon: facebook; ratio: 1.2"></span></a> |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
<hr class="uk-margin-medium"> |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
<div class="uk-margin-large-top"> |
|||
<h3>Related Articles</h3> |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
<ul class="uk-list"> |
|||
|
|||
</ul> |
|||
</div> |
|||
|
|||
|
|||
|
|||
</article> |
|||
|
|||
<script> |
|||
// Table of contents scroll to |
|||
UIkit.scroll('#markdown-toc a', { |
|||
duration: 400, |
|||
offset: 120 |
|||
}); |
|||
</script> |
|||
|
|||
</div> |
|||
|
|||
</div> |
|||
</div> |
|||
|
|||
|
|||
<div id="offcanvas" data-uk-offcanvas="flip: true; overlay: true"> |
|||
<div class="uk-offcanvas-bar"> |
|||
|
|||
<button class="uk-offcanvas-close" type="button" data-uk-close></button> |
|||
|
|||
<ul class="uk-nav uk-nav-default"> |
|||
<!-- <li><a class="uk-logo uk-margin-small-bottom" href="/"><img src="http://localhost:4000/assets/posts/logo.png" alt="Docs"></a></li> --> |
|||
<li><a class="uk-logo uk-margin-small-bottom" href="/"><img src="/assets/posts/logo.png" alt="Docs"></a></li> |
|||
|
|||
|
|||
<li><a href="https://blockstack.org" target="_blank" >Blockstack.org</a></li> |
|||
|
|||
|
|||
<li><a href="https://forum.blockstack.org/" target="_blank" >Forums</a></li> |
|||
|
|||
|
|||
<li><a href="https://github.com/blockstack" target="_blank" >GitHub</a></li> |
|||
|
|||
</ul> |
|||
|
|||
<div class="uk-margin-small-top uk-text-center uk-text-muted uk-link-muted"> |
|||
<div data-uk-grid class="uk-child-width-auto uk-grid-small uk-flex-center uk-grid"> |
|||
|
|||
<div class="uk-first-column"> |
|||
<a href="https://twitter.com/" data-uk-icon="icon: twitter" class="uk-icon-link uk-icon" target="_blank"></a> |
|||
</div> |
|||
|
|||
|
|||
<div> |
|||
<a href="https://www.facebook.com/" data-uk-icon="icon: facebook" class="uk-icon-link uk-icon" target="_blank"></a> |
|||
</div> |
|||
|
|||
|
|||
|
|||
|
|||
<div> |
|||
<a href="https://www.instagram.com/" data-uk-icon="icon: instagram" class="uk-icon-link uk-icon" target="_blank"></a> |
|||
</div> |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
<div> |
|||
<a href="https://vimeo.com/" data-uk-icon="icon: vimeo" class="uk-icon-link uk-icon" target="_blank"></a> |
|||
</div> |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
</div> |
|||
|
|||
|
|||
|
|||
<footer class="uk-section uk-text-center uk-text-muted uk-link-muted"> |
|||
<div class="uk-container uk-container-small"> |
|||
|
|||
<div> |
|||
<ul class="uk-subnav uk-flex-center"> |
|||
|
|||
|
|||
|
|||
|
|||
<li><a href="https://blockstack.org" target="_blank" >Blockstack.org</a></li> |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
<li><a href="https://forum.blockstack.org/" target="_blank" >Forums</a></li> |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
<li><a href="https://github.com/blockstack" target="_blank" >GitHub</a></li> |
|||
|
|||
|
|||
</ul> |
|||
</div> |
|||
<div class="uk-margin-medium"> |
|||
<div data-uk-grid class="uk-child-width-auto uk-grid-small uk-flex-center uk-grid"> |
|||
|
|||
<div class="uk-first-column"> |
|||
<a href="https://twitter.com/" data-uk-icon="icon: twitter" class="uk-icon-link uk-icon" target="_blank"></a> |
|||
</div> |
|||
|
|||
|
|||
<div> |
|||
<a href="https://www.facebook.com/" data-uk-icon="icon: facebook" class="uk-icon-link uk-icon" target="_blank"></a> |
|||
</div> |
|||
|
|||
|
|||
|
|||
|
|||
<div> |
|||
<a href="https://www.instagram.com/" data-uk-icon="icon: instagram" class="uk-icon-link uk-icon" target="_blank"></a> |
|||
</div> |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
<div> |
|||
<a href="https://vimeo.com/" data-uk-icon="icon: vimeo" class="uk-icon-link uk-icon" target="_blank"></a> |
|||
</div> |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
</div> |
|||
</div> |
|||
<div class="uk-margin-medium uk-text-small copyright">Blockstack</div> |
|||
|
|||
</div> |
|||
</footer> |
|||
|
|||
|
|||
|
|||
<script type="text/javascript"> |
|||
/* Create a configuration object */ |
|||
var ss360Config = { |
|||
/* Your site id */ |
|||
siteId: 'blockstack', |
|||
/* A CSS selector that points to your search box */ |
|||
searchBox: {selector: '#searchBox'} |
|||
}; |
|||
</script> |
|||
<script src="https://cdn.sitesearch360.com/sitesearch360-v11.min.js" async></script> |
|||
|
|||
|
|||
|
|||
|
|||
</body> |
|||
|
|||
</html> |
@ -1,303 +0,0 @@ |
|||
# Subdomain Design and Implementation |
|||
|
|||
Subdomains allow us to provide names to end users cheaply (and quickly). |
|||
|
|||
## Strong subdomain ownership |
|||
|
|||
For those who are new to this concept, it's a model where domains can |
|||
permanently, cryptographically delegate subdomains to particular keys, |
|||
relinquishing their ability to revoke the names or change the name |
|||
resolution details. |
|||
|
|||
These names will be indicated with an `.`, e.g., `foo.bar.id` |
|||
|
|||
## Overall Design |
|||
|
|||
We can do this today with a special indexer & resolver endpoint and |
|||
without any changes to the core protocol. |
|||
|
|||
We can do this by having a zone file record for each subdomain *i* |
|||
containing the following information: |
|||
|
|||
1. An owner address *addr* |
|||
2. A sequence number *N* |
|||
3. A zonefile |
|||
4. A signature *S* of the above |
|||
|
|||
The signature *S_i* must be verifiable with the address in the |
|||
*(N-1)*th entry for subdomain *i*. |
|||
|
|||
## Zonefile Format |
|||
|
|||
For now, the resolver will use an *TXT* record per subdomain to define |
|||
this information. The entry name will be `$(subdomain)`. |
|||
|
|||
|
|||
We'll use the format of [RFC 1464](https://tools.ietf.org/html/rfc1464) |
|||
for the TXT entry. We'll have the following strings with identifiers: |
|||
|
|||
1. **parts** : this specifies the number of pieces that the |
|||
zonefile has been chopped into. TXT strings can only be 255 bytes, |
|||
so we chop up the zonefile. |
|||
2. **zf{n}**: part *n* of the zonefile, base64 encoded |
|||
3. **owner**: the owner address delegated to operate the subdomain |
|||
4. **seqn**: the sequence number |
|||
5. **sig**: signature of the above data. |
|||
|
|||
``` |
|||
$ORIGIN bar.id |
|||
$TTL 3600 |
|||
pubkey TXT "pubkey:data:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" |
|||
registrar URI 10 1 "bsreg://foo.com:8234" |
|||
aaron TXT "owner=33VvhhSQsYQyCVE2VzG3EHa9gfRCpboqHy" "seqn=0" "parts=1" "zf0=JE9SSUdJTiBhYXJvbgokVFRMIDM2MDAKbWFpbiBVUkkgMSAxICJwdWJrZXk6ZGF0YTowMzAyYWRlNTdlNjNiMzc1NDRmOGQ5Nzk4NjJhNDlkMDBkYmNlMDdmMjkzYmJlYjJhZWNmZTI5OTkxYTg3Mzk4YjgiCg==" |
|||
``` |
|||
|
|||
The `registrar` entry indicates how to contact the registrar service |
|||
for clients of the domain wishing to register or modify their entry. |
|||
|
|||
### Operations per Zonefile |
|||
|
|||
At 4kb zonefile size, we can only fit around 20 updates per zonefile. |
|||
|
|||
## Domain Operator Endpoint |
|||
|
|||
The directory `subdomain_registrar/` contains our code for running a |
|||
subdomain registrar. It can be executed by running: |
|||
|
|||
``` |
|||
$ blockstack-subdomain-registrar start foo.id |
|||
``` |
|||
|
|||
Here, `foo.id` is the domain for which subdomains will be associated. |
|||
|
|||
### Configuration and Registration Files |
|||
|
|||
Configuration of the subdomain registrar is done through `~/.blockstack_subdomains/config.ini` |
|||
|
|||
The sqlite database which stores the registrations is located alongside the config `~/.blockstack_subdomains/registrar.db`. |
|||
|
|||
You can change the location of the config file (and the database), by setting the environment variable `BLOCKSTACK_SUBDOMAIN_CONFIG` |
|||
|
|||
### Register Subdomain |
|||
|
|||
Subdomain registrations can be submitted to this endpoint using a REST |
|||
API. |
|||
|
|||
``` |
|||
POST /register |
|||
``` |
|||
|
|||
The schema for registration is: |
|||
|
|||
``` |
|||
{ |
|||
'type' : 'object', |
|||
'properties' : { |
|||
'name' : { |
|||
'type': 'string', |
|||
'pattern': '([a-z0-9\-_+]{3,36})$' |
|||
}, |
|||
'owner_address' : { |
|||
'type': 'string', |
|||
'pattern': schemas.OP_ADDRESS_PATTERN |
|||
}, |
|||
'zonefile' : { |
|||
'type' : 'string', |
|||
'maxLength' : blockstack_constants.RPC_MAX_ZONEFILE_LEN |
|||
} |
|||
}, |
|||
'required':[ |
|||
'name', 'owner_address', 'zonefile' |
|||
], |
|||
'additionalProperties' : True |
|||
} |
|||
``` |
|||
|
|||
The registrar will: |
|||
|
|||
1. Check if the subdomain `foo` exists already on the domain. |
|||
2. Add the subdomain to the queue. |
|||
|
|||
On success, this returns `202` and the message |
|||
|
|||
``` |
|||
{"status": "true", "message": "Subdomain registration queued."} |
|||
``` |
|||
|
|||
When the registrar wakes up to prepare a transaction, it packs the queued |
|||
registrations together and issues an `UPDATE`. |
|||
|
|||
|
|||
### Check subdomain registration status |
|||
|
|||
A user can check on the registration status of their name via querying the |
|||
registrar. |
|||
|
|||
This is an API call: |
|||
``` |
|||
GET /status/{subdomain} |
|||
``` |
|||
|
|||
The registrar checks if the subdomain has propagated (i.e., the |
|||
registration is completed), in which case the following is returned: |
|||
|
|||
``` |
|||
{"status": "Subdomain already propagated"} |
|||
``` |
|||
|
|||
Or, if the subdomain has already been submitted in a transaction: |
|||
|
|||
``` |
|||
{"status": "Your subdomain was registered in transaction 09a40d6ea362608c68da6e1ebeb3210367abf7aa39ece5fd57fd63d269336399 -- it should propagate on the network once it has 6 confirmations."} |
|||
``` |
|||
|
|||
If the subdomain still hasn't been submitted yet: |
|||
|
|||
``` |
|||
{"status": "Subdomain is queued for update and should be announced within the next few blocks."} |
|||
``` |
|||
|
|||
If an error occurred trying to submit the `UPDATE` transaction, this endpoint will return an error |
|||
message in the `"error"` key of a JSON object. |
|||
|
|||
### Updating Entries |
|||
|
|||
The subdomain registrar does not currently support updating subdomain entries. |
|||
|
|||
## Resolver Behavior |
|||
|
|||
When a lookup like `foo.bar.id` hits the resolver, the resolver will need to: |
|||
|
|||
1. Lookup the zonefile history of `bar.id` |
|||
2. Fetch all these zonefiles and filter by operations on `foo` |
|||
3. Verify that all `foo` operations are correct |
|||
4. Return the latest record for foo |
|||
5. Do a profile lookup for `foo.bar.id` by fetching the URLs in the entry. |
|||
*Note*, this spec does not define a priority order for fetching those URLs. |
|||
|
|||
### Supported Core / Resolver Endpoints |
|||
|
|||
Generally, domain endpoints are not aware of subdomains (only endpoints |
|||
aware of subdomains is `/v1/users/<foo.bar.tld>`, |
|||
`/v1/names/<foo.bar.tld>`, and `/v1/addresses/bitcoin/<foo.bar.tld>`) |
|||
The endpoints which *are* subdomain aware are marked as such in |
|||
[api-specs.md], the cli command `blockstack lookup` is subdomain |
|||
aware. |
|||
|
|||
This means that search is *not* yet supported. |
|||
|
|||
The lookups work just like normal -- it returns the user's |
|||
profile object: |
|||
|
|||
``` |
|||
$ curl -H "Authorization: bearer blockstack_integration_test_api_password" -H "Origin: http://localhost:3000" http://localhost:16268/v1/users/bar.foo.id -v -s | python -m json.tool |
|||
* Trying 127.0.0.1... |
|||
* Connected to localhost (127.0.0.1) port 16268 (#0) |
|||
> GET /v1/users/bar.foo.id HTTP/1.1 |
|||
> Host: localhost:16268 |
|||
> User-Agent: curl/7.50.1 |
|||
> Accept: */* |
|||
> Authorization: bearer blockstack_integration_test_api_password |
|||
> Origin: http://localhost:3000 |
|||
> |
|||
* HTTP 1.0, assume close after body |
|||
< HTTP/1.0 200 OK |
|||
< Server: SimpleHTTP/0.6 Python/2.7.12+ |
|||
< Date: Thu, 03 Aug 2017 14:39:16 GMT |
|||
< content-type: application/json |
|||
< Access-Control-Allow-Origin: * |
|||
< |
|||
{ [66 bytes data] |
|||
* Closing connection 0 |
|||
{ |
|||
"bar": { |
|||
"@type": "Person", |
|||
"description": "Lorem Ipsum Bazorem" |
|||
} |
|||
} |
|||
``` |
|||
|
|||
Name info lookups are also supported (this should enable authenticating logins |
|||
with `blockstack.js`, but I will need to double check). |
|||
|
|||
``` |
|||
$ curl -H "Authorization: bearer XXXX" -H "Origin: http://localhost:3000" http://localhost:6270/v1/names/created_equal.self_evident_truth.id -s | python -m json.tool |
|||
{ |
|||
"address": "1AYddAnfHbw6bPNvnsQFFrEuUdhMhf2XG9", |
|||
"blockchain": "bitcoin", |
|||
"expire_block": -1, |
|||
"last_txid": "0bacfd5a3e0ec68723d5948d6c1a04ad0de1378c872d45fa2276ebbd7be230f7", |
|||
"satus": "registered_subdomain", |
|||
"zonefile_hash": "48fc1b351ce81cf0a9fd9b4eae7a3f80e93c0451", |
|||
"zonefile_txt": "$ORIGIN created_equal\n$TTL 3600\n_https._tcp URI 10 1 \"https://www.cs.princeton.edu/~ablankst/created_equal.json\"\n_file URI 10 1 \"file:///tmp/created_equal.json\"\n" |
|||
} |
|||
``` |
|||
|
|||
### Subdomain Caching |
|||
|
|||
A resolver *caches* a subdomain's state by keeping a database of all |
|||
the current subdomain records. This database is automatically updated |
|||
when a new zonefile for a particularly domain is seen by the resolver |
|||
(this is performed lazily). |
|||
|
|||
### Testing Subdomain Registrar and Resolution |
|||
|
|||
You can run a subdomain registrar and resolver with blockstack-core in |
|||
regtest mode as follows: |
|||
|
|||
```bash |
|||
IMAGE=$(docker run -dt -p 3000:3000 -p 6270:6270 -p 16269:16269 -p 18332:18332 -e BLOCKSTACK_TEST_CLIENT_RPC_PORT=6270 -e BLOCKSTACK_TEST_CLIENT_BIND=0.0.0.0 -e BLOCKSTACK_TEST_BITCOIND_ALLOWIP=172.17.0.0/16 quay.io/blockstack/integrationtests:master blockstack-test-scenario --interactive 2 blockstack_integration_tests.scenarios.browser_env) |
|||
``` |
|||
|
|||
Once you see `Test finished; doing checks` in that container's logs, the |
|||
registrar has started and is ready to accept requests. (We recommend |
|||
following the docker instructions below for running this test in |
|||
Docker, as it will fetch the source code for the registrar and set the |
|||
correct environment variables for it to run). |
|||
|
|||
Once this environment has started, you can issue a registration request from curl: |
|||
|
|||
``` |
|||
curl -X POST -H 'Content-Type: application/json' --data '{"zonefile": "$ORIGIN baz\n$TTL 3600\n_file URI 10 1 \"file:///tmp/baz.profile.json\"\n", "name": "baz", "owner_address": "14x2EMRz1gf16UzGbxZh2c6sJg4A8wcHLD"}' http://localhost:3000/register/ |
|||
``` |
|||
|
|||
This registers `baz.foo.id` -- you can check the registrar's status with |
|||
|
|||
``` |
|||
curl http://localhost:3000/status/baz |
|||
``` |
|||
|
|||
The API endpoints `/v1/users/<foo.bar.tld>`, |
|||
`/v1/names/<foo.bar.tld>`, and `/v1/addresses/bitcoin/<foo.bar.tld>` all work, so if you query the core API, you'll get a response. |
|||
|
|||
For example: |
|||
|
|||
``` |
|||
curl http://localhost:6270/v1/names/baz.foo.id | python -m json.tool |
|||
``` |
|||
|
|||
Will return: |
|||
``` |
|||
{ |
|||
"address": "1Nup2UcbVuVoDZeZCtR4vjSkrvTi8toTqc", |
|||
"blockchain": "bitcoin", |
|||
"expire_block": -1, |
|||
"last_txid": "43bbcbd8793cdc52f1b0bd2713ed136f4f104a683a9fd5c89911a57a8c4b28b6", |
|||
"satus": "registered_subdomain", |
|||
"zonefile_hash": "e7e3aada18c9ac5189f1c54089e987f58c0fa51e", |
|||
"zonefile_txt": "$ORIGIN bar\n$TTL 3600\n_file URI 10 1 \"file:///tmp/baz.profile.json\"\n" |
|||
} |
|||
``` |
|||
|
|||
### Running an interactive testing environment with the Subdomain Registrar service |
|||
|
|||
Follow the [instructions here](../integration_tests/README.md) to download the regtesting Docker image. |
|||
|
|||
Since the subdomain registrar service runs on port 3000, we need to do two things to expose this endpoint to interact with it from the browser: |
|||
- Open port 3000 with `-p 3000:3000` |
|||
|
|||
Here's the full command you'd run to start the interactive testing scenario: |
|||
|
|||
```bash |
|||
IMAGE=$(docker run -dt -p 3000:3000 -p 6270:6270 -p 16269:16269 -p 18332:18332 -e BLOCKSTACK_TEST_CLIENT_RPC_PORT=6270 -e BLOCKSTACK_TEST_CLIENT_BIND=0.0.0.0 -e BLOCKSTACK_TEST_BITCOIND_ALLOWIP=172.17.0.0/16 quay.io/blockstack/integrationtests:master blockstack-test-scenario --interactive 2 blockstack_integration_tests.scenarios.browser_env) |
|||
``` |
Loading…
Reference in new issue