mirror of https://github.com/lukechilds/docs.git
moxiegirl
6 years ago
19 changed files with 1736 additions and 46 deletions
@ -0,0 +1,589 @@ |
|||
<!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>How Atlas Works | Blockstack</title> |
|||
<meta name="generator" content="Jekyll v3.8.3" /> |
|||
<meta property="og:title" content="How Atlas Works" /> |
|||
<meta name="author" content="Blockstack" /> |
|||
<meta property="og:locale" content="en_US" /> |
|||
<meta name="description" content="How Atlas Works" /> |
|||
<meta property="og:description" content="How Atlas Works" /> |
|||
<link rel="canonical" href="https://zbabystack.netlify.com/core/auth/howitworks.html" /> |
|||
<meta property="og:url" content="https://zbabystack.netlify.com/core/auth/howitworks.html" /> |
|||
<meta property="og:site_name" content="Blockstack" /> |
|||
<meta property="og:type" content="article" /> |
|||
<meta property="article:published_time" content="2018-08-29T18:50:59-07:00" /> |
|||
<script type="application/ld+json"> |
|||
{"description":"How Atlas Works","author":{"@type":"Person","name":"Blockstack"},"@type":"BlogPosting","url":"https://zbabystack.netlify.com/core/auth/howitworks.html","headline":"How Atlas Works","dateModified":"2018-08-29T18:50:59-07:00","datePublished":"2018-08-29T18:50:59-07:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://zbabystack.netlify.com/core/auth/howitworks.html"},"@context":"http://schema.org"}</script> |
|||
<!-- End Jekyll SEO tag --> |
|||
|
|||
<!-- <meta property="og:image" content="https://zbabystack.netlify.com/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="https://zbabystack.netlify.com/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"> |
|||
<!-- --> |
|||
|
|||
|
|||
<ul class="uk-nav uk-nav-default doc-nav"> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/auth/overview.html">Overview of the Atlas network</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class="uk-active"><a href="/core/auth/howitworks.html">How Atlas Works</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/auth/howtouse.html">How to Use the Atlas Network</a></li> |
|||
|
|||
</ul> |
|||
|
|||
<!-- --> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="uk-width-1-1 uk-width-expand@m"> |
|||
|
|||
<article class="uk-article"> |
|||
|
|||
<h1 class="uk-article-title">How Atlas Works</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-29T18:50:59-07:00" itemprop="datePublished"> |
|||
|
|||
<a "target="_blank" href="https://github.com/moxiegirl/docs-new/blob/master/_core/auth/howitworks.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">Atlas was designed to overcome the structural weaknesses inherent to all |
|||
distributed hash tables. In particular, it uses an unstructured peer network to |
|||
maximize resilience against network link failure, and it uses the underlying |
|||
blockchain (through BNS) to rate-limit chunk announcements.</p> |
|||
|
|||
<p>This section contains the following sections:</p> |
|||
|
|||
<ul id="markdown-toc"> |
|||
<li><a href="#peer-selection" id="markdown-toc-peer-selection">Peer Selection</a></li> |
|||
<li><a href="#comparison-to-dhts" id="markdown-toc-comparison-to-dhts">Comparison to DHTs</a> <ul> |
|||
<li><a href="#chunk-censorship" id="markdown-toc-chunk-censorship">Chunk Censorship</a></li> |
|||
<li><a href="#neighbor-censorship" id="markdown-toc-neighbor-censorship">Neighbor Censorship</a></li> |
|||
</ul> |
|||
</li> |
|||
<li><a href="#chunk-propagation" id="markdown-toc-chunk-propagation">Chunk Propagation</a></li> |
|||
<li><a href="#querying-chunk-inventories" id="markdown-toc-querying-chunk-inventories">Querying Chunk Inventories</a></li> |
|||
</ul> |
|||
|
|||
<h2 id="peer-selection">Peer Selection</h2> |
|||
|
|||
<p>Atlas peers self-organize into an unstructured peer-to-peer network. |
|||
The Atlas peer network is a <a href="https://en.wikipedia.org/wiki/Random_regular_graph">random K-regular |
|||
graph</a>. Each node maintains |
|||
<em>K</em> neighbors chosen at random from the set of Atlas peers.</p> |
|||
|
|||
<p>Atlas nodes select peers by carrying out an unbiased random walk of the peer |
|||
graph. When “visiting” a node <em>N</em>, it will ask for <em>N</em>’s neighbors and then |
|||
“step” to one of them with a probability dependent on <em>N</em>’s out-degree and the |
|||
neighbor’s in-degree.</p> |
|||
|
|||
<p>The sampling algorithm is based on the Metropolis-Hastings (MH) random graph walk |
|||
algorithm, but with a couple key differences. In particular, the algorithm |
|||
attempts to calculate an unbiased peer graph sample that accounts for the fact |
|||
that most nodes will be short-lived or unreliable, while a few persistent nodes |
|||
will remain online for long periods of time. The sampling algorithm accounts |
|||
for this with the following tweaks:</p> |
|||
|
|||
<ul> |
|||
<li> |
|||
<p>If the neighbors of the visited node <em>N</em> are all unresponsive, the random |
|||
walk resets to a randomly-chosen known neighbor. There is no back-tracking on |
|||
the peer graph in this case.</p> |
|||
</li> |
|||
<li> |
|||
<p>The transition probability from <em>N</em> to a live neighbor is <em>NOT</em> <code class="highlighter-rouge">min(1, |
|||
degree(neighbor)/degree(N))</code> like it is in the vanilla MH algorithm. Instead, |
|||
the transition probability discourages backtracking to the previous neighbor <em>N_prev</em>, |
|||
but in a way that still guarantees that the sampling will remain unbiased.</p> |
|||
</li> |
|||
<li> |
|||
<p>A peer does not report its entire neighbor set when queried, |
|||
but only reports a random subset of peers that have met a minimium health threshold.</p> |
|||
</li> |
|||
<li> |
|||
<p>A new neighbor is only selected if it belongs to the same <a href="blockstack_naming_service.md#bns-forks">BNS |
|||
fork-set</a> (i.e. it reports |
|||
as having a recent valid consensus hash).</p> |
|||
</li> |
|||
</ul> |
|||
|
|||
<p>The algorithm was adapted from the work from <a href="https://arxiv.org/pdf/1204.4140.pdf">Lee, Xu, and |
|||
Eun</a> in the proceedings of |
|||
ACM SIGMETRICS 2012.</p> |
|||
|
|||
<h2 id="comparison-to-dhts">Comparison to DHTs</h2> |
|||
|
|||
<p>The reason Atlas uses an unstructured random peer network |
|||
instead of a <a href="https://en.wikipedia.org/wiki/Distributed_hash_table">distributed hash table</a> |
|||
(DHT) is that DHTs are susceptbile to Sybil attacks. An adaptive adversary can |
|||
insert malicious nodes into the DHT in order to stop victims from |
|||
resolving chunks or finding honest neighbors.</p> |
|||
|
|||
<h3 id="chunk-censorship">Chunk Censorship</h3> |
|||
|
|||
<p>In a DHT, an attacker can censor a chunk by inserting nodes into the peers’ routing tables |
|||
such that the attacker takes control over all of the chunk’s hash buckets. |
|||
It can do so at any point in time after the chunk was first stored, |
|||
because only the peers who maintain the chunk’s hash bucket have to store it. |
|||
This is a <em>fundamental</em> problem with structured overlay networks |
|||
that perform request routing based on content hash—they give the attacker |
|||
insight as to the path(s) the queries take through the peer graph, and thus |
|||
reduce the number of paths the attacker must disrupt in order to censor the |
|||
chunk.</p> |
|||
|
|||
<p>Atlas uses an unstructured overlay network combined with a 100% chunk |
|||
replication strategy in order to maximize |
|||
the amount of work an adversary has to do to censor a chunk. |
|||
In Atlas, all peers replicate a chunk, and the paths the chunk take through the |
|||
network are <em>independent</em> of the content and <em>randomized</em> by the software |
|||
(so the paths cannot be predicted in advance). The attacker’s only |
|||
recourse is to quickly identify the nodes that can serve the chunk and partition them from |
|||
the rest of the network in order to carry out a censorship attack. |
|||
This requires them to have visibility into the vast majority of network links in |
|||
the Atlas network (which is extremely difficult to do, because in practice Atlas |
|||
peers maintain knowledge of up to 65536 neighbors and only report 10 random peers |
|||
when asked).</p> |
|||
|
|||
<h3 id="neighbor-censorship">Neighbor Censorship</h3> |
|||
|
|||
<p>Another problem with DHTs is that their overlay |
|||
network structure is determined by preferential attachment. Not every peer that |
|||
contacts a given DHT node has an equal chance of becoming its neighbor. |
|||
The node will instead rank a set of peers as being more or less ideal |
|||
for being neighbors. In DHTs, the degree of preference a node exhibits to |
|||
another node is usually a function of the node’s self-given node identifier |
|||
(e.g. a node might want to select neighbors based on proximity in the key |
|||
space).</p> |
|||
|
|||
<p>The preferential attachment property means that an adaptive adversary can game the node’s |
|||
neighbor selection algorithm by inserting malicious nodes that do not |
|||
forward routing or lookup requests. The attacker does not even have to eclipse |
|||
the victim node—the victim node will simply prefer to talk to the attacker’s unhelpful nodes |
|||
instead of helpful honest nodes. In doing so, the attacker can prevent honest peers from discovering each |
|||
other and each other’s chunks.</p> |
|||
|
|||
<p>Atlas’s neighbor selection strategy does not exhibit preferential attachment |
|||
based on any self-reported node properties. A |
|||
node is selected as a neighbor only if it is reached through an unbiased random graph |
|||
walk, and if it responds to queries correctly. |
|||
In doing so, an attacker is forced to completely eclipse a set of nodes |
|||
in order to cut them off from the rest of the network.</p> |
|||
|
|||
<h2 id="chunk-propagation">Chunk Propagation</h2> |
|||
|
|||
<p>Atlas nodes maintain an <em>inventory</em> of chunks that are known to exist. Each |
|||
node independently calculates the chunk inventory from its BNS database. |
|||
Because the history of name operations in BNS is linearized, each node can |
|||
construct a linearized sub-history of name operations that can set chunk |
|||
hashes as their name state. This gives them a linearized sequence of chunks, |
|||
and every Atlas peer will independently arrive at the same sequence by reading |
|||
the same blockchain.</p> |
|||
|
|||
<p>Atlas peers keep track of which chunks are present and which are absent. They |
|||
each construct an <em>inventory vector</em> of chunks <em>V</em> such that <em>V[i]</em> is set to 1 |
|||
if the node has the chunk whose hash is in the <em>i</em>th position in the chunk |
|||
sequence (and set to 0 if it is absent).</p> |
|||
|
|||
<p>Atlas peers exchange their inventory vectors with their neighbors in order to |
|||
find out which chunks they each have. Atlas nodes download chunks from |
|||
neighbors in rarest-first order in order to prioritize data replication for the |
|||
chunks that are currently most at-risk for disappearing due to node failure.</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code> Name operation | chunk hashes | chunk data | Inventory |
|||
history | as name state | | vector |
|||
|
|||
+-------------------+ |
|||
| NAME_PREORDER | |
|||
+-------------------+----------------+ |
|||
| NAME_REGISTRATION | chunk hash | "0123abcde..." 1 |
|||
+-------------------+----------------+ |
|||
| NAME_UPDATE | chunk hash | (null) 0 |
|||
+-------------------+----------------+ |
|||
| NAME_TRANSFER | |
|||
+-------------------+ |
|||
| NAME_PREORDER | |
|||
+-------------------+----------------+ |
|||
| NAME_IMPORT | chunk hash | "4567fabcd..." 1 |
|||
+-------------------+----------------+ |
|||
| NAME_TRANSFER | |
|||
+-------------------| |
|||
. . . |
|||
|
|||
|
|||
Figure 2: Relationship between Atlas node chunk inventory and BNS name state. |
|||
Some name operations announce name state in the blockchain, which Atlas |
|||
interprets as a chunk hash. The Atlas node builds up a vector of which chunks |
|||
it has and which ones it does not, and announces it to other Atlas peers so |
|||
they can fetch chunks they are missing. In this example, the node's |
|||
inventory vector is [1, 0, 1], since the 0th and 2nd chunks are present |
|||
but the 1st chunk is missing. |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<h2 id="querying-chunk-inventories">Querying Chunk Inventories</h2> |
|||
|
|||
<p>Developers can query a node’s inventory vector as follows:</p> |
|||
|
|||
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="o">>>></span> <span class="kn">import</span> <span class="nn">blockstack</span> |
|||
<span class="o">>>></span> <span class="n">result</span> <span class="o">=</span> <span class="n">blockstack</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">get_zonefile_inventory</span><span class="p">(</span><span class="s">"https://node.blockstack.org:6263"</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">524288</span><span class="p">)</span> |
|||
<span class="o">>>></span> <span class="k">print</span> <span class="nb">len</span><span class="p">(</span><span class="n">result</span><span class="p">[</span><span class="s">'inv'</span><span class="p">])</span> |
|||
<span class="mi">11278</span> |
|||
<span class="o">>>></span> |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>The variable <code class="highlighter-rouge">result['inv']</code> here is a big-endian bit vector, where the <em>i</em>th |
|||
bit is set to 1 if the <em>i</em>th chunk in the chunk sequence is present. The bit at |
|||
<code class="highlighter-rouge">i=0</code> (the earliest chunk) refers to the leftmost bit.</p> |
|||
|
|||
<p>A sample program that inspects a set of Atlas nodes’ inventory vectors and determines |
|||
which ones are missing which chunks can be found |
|||
<a href="https://github.com/blockstack/atlas/blob/master/atlas/atlas-test">here</a>.</p> |
|||
|
|||
<div class="share uk-text-center"> |
|||
<a href="https://twitter.com/intent/tweet?text=How Atlas Works&url=https://zbabystack.netlify.com/core/auth/howitworks.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=https%3A%2F%2Fzbabystack.netlify.com%2Fcore%2Fauth%2Fhowitworks.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="https://zbabystack.netlify.com/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> |
@ -0,0 +1,523 @@ |
|||
<!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>How to Use the Atlas Network | Blockstack</title> |
|||
<meta name="generator" content="Jekyll v3.8.3" /> |
|||
<meta property="og:title" content="How to Use the Atlas Network" /> |
|||
<meta name="author" content="Blockstack" /> |
|||
<meta property="og:locale" content="en_US" /> |
|||
<meta name="description" content="How to Use the Atlas Network" /> |
|||
<meta property="og:description" content="How to Use the Atlas Network" /> |
|||
<link rel="canonical" href="https://zbabystack.netlify.com/core/auth/howtouse.html" /> |
|||
<meta property="og:url" content="https://zbabystack.netlify.com/core/auth/howtouse.html" /> |
|||
<meta property="og:site_name" content="Blockstack" /> |
|||
<meta property="og:type" content="article" /> |
|||
<meta property="article:published_time" content="2018-08-29T18:50:59-07:00" /> |
|||
<script type="application/ld+json"> |
|||
{"description":"How to Use the Atlas Network","author":{"@type":"Person","name":"Blockstack"},"@type":"BlogPosting","url":"https://zbabystack.netlify.com/core/auth/howtouse.html","headline":"How to Use the Atlas Network","dateModified":"2018-08-29T18:50:59-07:00","datePublished":"2018-08-29T18:50:59-07:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://zbabystack.netlify.com/core/auth/howtouse.html"},"@context":"http://schema.org"}</script> |
|||
<!-- End Jekyll SEO tag --> |
|||
|
|||
<!-- <meta property="og:image" content="https://zbabystack.netlify.com/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="https://zbabystack.netlify.com/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"> |
|||
<!-- --> |
|||
|
|||
|
|||
<ul class="uk-nav uk-nav-default doc-nav"> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/auth/overview.html">Overview of the Atlas network</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/auth/howitworks.html">How Atlas Works</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class="uk-active"><a href="/core/auth/howtouse.html">How to Use the Atlas Network</a></li> |
|||
|
|||
</ul> |
|||
|
|||
<!-- --> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="uk-width-1-1 uk-width-expand@m"> |
|||
|
|||
<article class="uk-article"> |
|||
|
|||
<h1 class="uk-article-title">How to Use the Atlas Network</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-29T18:50:59-07:00" itemprop="datePublished"> |
|||
|
|||
<a "target="_blank" href="https://github.com/moxiegirl/docs-new/blob/master/_core/auth/howtouse.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">This section teaches you how to use the Atlas network, it contains the |
|||
following sections:</p> |
|||
|
|||
<ul id="markdown-toc"> |
|||
<li><a href="#the-api" id="markdown-toc-the-api">The API</a></li> |
|||
<li><a href="#looking-up-chunks" id="markdown-toc-looking-up-chunks">Looking up Chunks</a></li> |
|||
<li><a href="#adding-a-new-chunk" id="markdown-toc-adding-a-new-chunk">Adding a New Chunk</a></li> |
|||
<li><a href="#propagating-chunks" id="markdown-toc-propagating-chunks">Propagating Chunks</a></li> |
|||
</ul> |
|||
|
|||
<h2 id="the-api">The API</h2> |
|||
|
|||
<p>While the Blockstack software stack expects that Atlas-hosted data is made up of |
|||
DNS zone files, Atlas itself does not enforce this (nor does it care about the |
|||
format of its chunks). It is designed as a general-purpose chunk store. |
|||
Nevertheless, the ubiquitous use of Atlas to store data as DNS zone files has |
|||
had an influence on its API design—fields and method names frequently allude |
|||
to zone files and zone file hashes. This is intentional.</p> |
|||
|
|||
<p>The <a href="https://core.blockstack.org">public BNS API endpoint</a> does not support |
|||
resolving Atlas chunks that do not encode Gaia routing information or subdomain |
|||
information. To directly interact with Atlas, developers will need to install |
|||
<a href="https://github.com/blockstack/blockstack-core">Blockstack Core</a> and use its |
|||
Python client libraries for these examples.</p> |
|||
|
|||
<h2 id="looking-up-chunks">Looking up Chunks</h2> |
|||
|
|||
<p>All Atlas chunks are addressed by the RIPEMD160 hash of the SHA256 hash of the |
|||
chunk data. A client can query up to 100 chunks in one RPC call.</p> |
|||
|
|||
<p>A client can look up a chunk with the <code class="highlighter-rouge">get_zonefiles()</code> method. If successful, |
|||
the returned payload will be a <code class="highlighter-rouge">dict</code> with a <code class="highlighter-rouge">zonefiles</code> key that maps the chunk |
|||
hashes to their respective data.</p> |
|||
|
|||
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="o">>>></span> <span class="kn">import</span> <span class="nn">blockstack</span> |
|||
<span class="o">>>></span> <span class="n">data</span> <span class="o">=</span> <span class="n">blockstack</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">get_zonefiles</span><span class="p">(</span><span class="s">'https://node.blockstack.org:6263'</span><span class="p">,</span> <span class="p">[</span><span class="s">'1b89a685f4c4ea245ce9433d0b29166c22175ab4'</span><span class="p">])</span> |
|||
<span class="o">>>></span> <span class="k">print</span> <span class="n">data</span><span class="p">[</span><span class="s">'zonefiles'</span><span class="p">][</span><span class="s">'1b89a685f4c4ea245ce9433d0b29166c22175ab4'</span><span class="p">]</span> |
|||
<span class="err">$</span><span class="n">ORIGIN</span> <span class="n">duckduckgo_tor</span><span class="o">.</span><span class="nb">id</span> |
|||
<span class="err">$</span><span class="n">TTL</span> <span class="mi">3600</span> |
|||
<span class="n">tor</span> <span class="n">TXT</span> <span class="s">"3g2upl4pq6kufc4m.onion"</span> |
|||
|
|||
<span class="o">>>></span> |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>(This particular chunk happens to be associated with the BNS name |
|||
<code class="highlighter-rouge">duckduckgo_tor.id</code>).</p> |
|||
|
|||
<h2 id="adding-a-new-chunk">Adding a New Chunk</h2> |
|||
|
|||
<p>The only way to add a chunk to Atlas is to do so through an on-chain name in |
|||
BNS. Adding a new chunk is a two-step process:</p> |
|||
|
|||
<ul> |
|||
<li>The name owner announces the chunk hash as a name’s state |
|||
via a <code class="highlighter-rouge">NAME_REGISTRATION</code>, <code class="highlighter-rouge">NAME_UPDATE</code>, <code class="highlighter-rouge">NAME_RENEWAL</code>, or <code class="highlighter-rouge">NAME_IMPORT</code> transaction.</li> |
|||
<li>Once the transaction is confirmed and processed by BNS, the name owner |
|||
broadcasts the matching zone file.</li> |
|||
</ul> |
|||
|
|||
<p>Setting a name’s state to be the hash of a chunk is beyond the scope of this |
|||
document, since it needs to be done through a BNS client. |
|||
See the relevant documentation for |
|||
<a href="https://github.com/blockstack/blockstack.js">blockstack.js</a> and the <a href="https://github.com/blockstack/blockstack-browser">Blockstack |
|||
Browser</a> for doing this.</p> |
|||
|
|||
<p>Once the name operation is confirmed, you can announce the data to the |
|||
Atlas network. You can do so with the Python client as follows:</p> |
|||
|
|||
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="o">>>></span> <span class="kn">import</span> <span class="nn">blockstack</span> |
|||
<span class="o">>>></span> <span class="kn">import</span> <span class="nn">base64</span> |
|||
<span class="o">>>></span> <span class="n">data</span> <span class="o">=</span> <span class="s">"..."</span> <span class="c"># this is the chunk data you will announce</span> |
|||
<span class="o">>>></span> <span class="n">data_b64</span> <span class="o">=</span> <span class="n">base64</span><span class="o">.</span><span class="n">b64encode</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> |
|||
<span class="o">>>></span> <span class="n">result</span> <span class="o">=</span> <span class="n">blockstack</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">put_zonefiles</span><span class="p">(</span><span class="s">'https://node.blockstack.org:6263'</span><span class="p">,</span> <span class="p">[</span><span class="n">data_b64</span><span class="p">])</span> |
|||
<span class="o">>>></span> <span class="k">assert</span> <span class="n">result</span><span class="p">[</span><span class="s">'saved'</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span> |
|||
<span class="o">>>></span> |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>At most five chunks can be announced in one RPC call. |
|||
Note that the data must be base64-encoded before it can be announced.</p> |
|||
|
|||
<p>When the <code class="highlighter-rouge">put_zonefiles()</code> method succeeds, it returns a <code class="highlighter-rouge">dict</code> with a list |
|||
under the <code class="highlighter-rouge">saved</code> key. Here, <code class="highlighter-rouge">result['saved'][i]</code> will be 1 if the <code class="highlighter-rouge">i</code>th |
|||
chunk given to <code class="highlighter-rouge">put_zonefiles()</code> was saved by the node, and 0 if not. |
|||
The node will not save a chunk if it is too big, or if it has not yet processed |
|||
the name operation that contained the chunk’s hash.</p> |
|||
|
|||
<p>The <code class="highlighter-rouge">put_zonefiles()</code> method is idempotent.</p> |
|||
|
|||
<h2 id="propagating-chunks">Propagating Chunks</h2> |
|||
|
|||
<p>Atlas peers will each store a copy of the chunks you announce. In the |
|||
background, they will asynchronously announce to one another which chunks they |
|||
have available, and replicate them to one another in a rarest-first order (much |
|||
like how BitTorrent works). Eventually, every Atlas peer will receive the |
|||
chunk.</p> |
|||
|
|||
<p>However, developers can accelerate this process by eagerly propagating chunks. |
|||
To do so, they can ask an Atlas peer for its immediate neighbors in the Atlas |
|||
peer graph, and replicate the chunk to each of them as well.</p> |
|||
|
|||
<p>For example, this code will replicate the chunk to not only |
|||
<code class="highlighter-rouge">https://node.blockstack.org:6263</code>, but also to its immediate neighbors.</p> |
|||
|
|||
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="o">>>></span> <span class="kn">import</span> <span class="nn">blockstack</span> |
|||
<span class="o">>>></span> <span class="kn">import</span> <span class="nn">base64</span> |
|||
<span class="o">>>></span> <span class="n">data</span> <span class="o">=</span> <span class="s">"..."</span> <span class="c"># this is the chunk you will replicate widely</span> |
|||
<span class="o">>>></span> <span class="n">data_b64</span> <span class="o">=</span> <span class="n">base64</span><span class="o">.</span><span class="n">b64encode</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> |
|||
<span class="o">>>></span> |
|||
<span class="o">>>></span> <span class="n">result</span> <span class="o">=</span> <span class="n">blockstack</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">get_atlas_peers</span><span class="p">(</span><span class="s">'https://node.blockstack.org:6263'</span><span class="p">)</span> |
|||
<span class="o">>>></span> <span class="n">neighbors</span> <span class="o">=</span> <span class="n">result</span><span class="p">[</span><span class="s">'peers'</span><span class="p">]</span> |
|||
<span class="o">>>></span> <span class="k">print</span> <span class="s">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">neighbors</span><span class="p">)</span> |
|||
<span class="mf">13.65</span><span class="o">.</span><span class="mf">207.163</span><span class="p">:</span><span class="mi">6264</span><span class="p">,</span> <span class="mf">52.225</span><span class="o">.</span><span class="mf">128.191</span><span class="p">:</span><span class="mi">6264</span><span class="p">,</span> <span class="n">node</span><span class="o">.</span><span class="n">blockstack</span><span class="o">.</span><span class="n">org</span><span class="p">:</span><span class="mi">6264</span><span class="p">,</span> <span class="mf">23.102</span><span class="o">.</span><span class="mf">162.7</span><span class="p">:</span><span class="mi">6264</span><span class="p">,</span> <span class="mf">52.167</span><span class="o">.</span><span class="mf">230.235</span><span class="p">:</span><span class="mi">6264</span><span class="p">,</span> <span class="mf">23.102</span><span class="o">.</span><span class="mf">162.124</span><span class="p">:</span><span class="mi">6264</span><span class="p">,</span> <span class="mf">52.151</span><span class="o">.</span><span class="mf">59.26</span><span class="p">:</span><span class="mi">6264</span><span class="p">,</span> <span class="mf">13.92</span><span class="o">.</span><span class="mf">134.106</span><span class="p">:</span><span class="mi">6264</span> |
|||
<span class="o">>>></span> |
|||
<span class="o">>>></span> <span class="k">for</span> <span class="n">neighbor</span> <span class="ow">in</span> <span class="n">neighbors</span><span class="p">:</span> |
|||
<span class="o">...</span> <span class="n">result</span> <span class="o">=</span> <span class="n">blockstack</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">put_zonefiles</span><span class="p">(</span><span class="n">neighbor</span><span class="p">,</span> <span class="p">[</span><span class="n">data_b64</span><span class="p">])</span> |
|||
<span class="o">...</span> <span class="k">assert</span> <span class="n">result</span><span class="p">[</span><span class="s">'saved'</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span> |
|||
<span class="o">...</span> |
|||
<span class="o">>>></span> |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>This is not strictly necessary, but it does help accelerate chunk replication |
|||
and makes it less likely that a chunk will get lost due to individual node |
|||
failures.</p> |
|||
|
|||
<div class="share uk-text-center"> |
|||
<a href="https://twitter.com/intent/tweet?text=How to Use the Atlas Network&url=https://zbabystack.netlify.com/core/auth/howtouse.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=https%3A%2F%2Fzbabystack.netlify.com%2Fcore%2Fauth%2Fhowtouse.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="https://zbabystack.netlify.com/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> |
@ -0,0 +1,578 @@ |
|||
<!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>Overview of the Atlas network | Blockstack</title> |
|||
<meta name="generator" content="Jekyll v3.8.3" /> |
|||
<meta property="og:title" content="Overview of the Atlas network" /> |
|||
<meta name="author" content="Blockstack" /> |
|||
<meta property="og:locale" content="en_US" /> |
|||
<meta name="description" content="Overview of the Atlas network" /> |
|||
<meta property="og:description" content="Overview of the Atlas network" /> |
|||
<link rel="canonical" href="https://zbabystack.netlify.com/core/auth/overview.html" /> |
|||
<meta property="og:url" content="https://zbabystack.netlify.com/core/auth/overview.html" /> |
|||
<meta property="og:site_name" content="Blockstack" /> |
|||
<meta property="og:type" content="article" /> |
|||
<meta property="article:published_time" content="2018-08-29T18:50:59-07:00" /> |
|||
<script type="application/ld+json"> |
|||
{"description":"Overview of the Atlas network","author":{"@type":"Person","name":"Blockstack"},"@type":"BlogPosting","url":"https://zbabystack.netlify.com/core/auth/overview.html","headline":"Overview of the Atlas network","dateModified":"2018-08-29T18:50:59-07:00","datePublished":"2018-08-29T18:50:59-07:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://zbabystack.netlify.com/core/auth/overview.html"},"@context":"http://schema.org"}</script> |
|||
<!-- End Jekyll SEO tag --> |
|||
|
|||
<!-- <meta property="og:image" content="https://zbabystack.netlify.com/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="https://zbabystack.netlify.com/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"> |
|||
<!-- --> |
|||
|
|||
|
|||
<ul class="uk-nav uk-nav-default doc-nav"> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class="uk-active"><a href="/core/auth/overview.html">Overview of the Atlas network</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/auth/howitworks.html">How Atlas Works</a></li> |
|||
|
|||
|
|||
<!-- --> |
|||
|
|||
<li class=""><a href="/core/auth/howtouse.html">How to Use the Atlas Network</a></li> |
|||
|
|||
</ul> |
|||
|
|||
<!-- --> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="uk-width-1-1 uk-width-expand@m"> |
|||
|
|||
<article class="uk-article"> |
|||
|
|||
<h1 class="uk-article-title">Overview of the Atlas network</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-29T18:50:59-07:00" itemprop="datePublished"> |
|||
|
|||
<a "target="_blank" href="https://github.com/moxiegirl/docs-new/blob/master/_core/auth/overview.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">This document describes the Atlas network, a peer-to-peer content-addressed |
|||
storage system whose chunks’ hashes are announced on a public blockchain. Atlas |
|||
allows users and developers to <strong>permanently store</strong> chunks of data that are |
|||
<strong>replicated across every peer.</strong> As long as at least one Atlas peer is online, |
|||
all chunks are available to clients.</p> |
|||
|
|||
<p>This document is aimed at developers and technical users. The following |
|||
concepts are discussed:</p> |
|||
|
|||
<ul id="markdown-toc"> |
|||
<li><a href="#architecture" id="markdown-toc-architecture">Architecture</a></li> |
|||
<li><a href="#motivation" id="markdown-toc-motivation">Motivation</a></li> |
|||
<li><a href="#feature-comparison" id="markdown-toc-feature-comparison">Feature Comparison</a></li> |
|||
</ul> |
|||
|
|||
<p>The reader of this document is expected to be familiar with the <a href="blockstack_naming_service.md">Blockstack |
|||
Naming Service</a> (BNS), as well as Blockstack’s |
|||
storage system <a href="https://github.com/blockstack/gaia">Gaia</a>. We advise the reader |
|||
to familiarize themselves with both systems before approaching this document.</p> |
|||
|
|||
<h2 id="architecture">Architecture</h2> |
|||
|
|||
<p>Atlas is designed to integrate with BNS in order to allow users to |
|||
store name state off-chain, encoded as a DNS zone file. |
|||
The overwhelmingly-common use-cases in Blockstack are:</p> |
|||
|
|||
<ul> |
|||
<li>Storing a name’s routing information for its owners’ <a href="https://github.com/blockstack/gaia">Gaia</a> |
|||
datastores.</li> |
|||
<li>Storing BNS subdomain transactions and associated state.</li> |
|||
</ul> |
|||
|
|||
<p>Atlas is a middleware system in Blockstack. Most developers do not |
|||
interact with it directly. BNS clients like the |
|||
<a href="https://github.com/blockstack/blockstack-browser">Blockstack Browser</a> |
|||
automatically generate zone files for the names they register, and automatically |
|||
propagate them to the Atlas network. BNS API endpoints, including our |
|||
<a href="https://core.blockstack.org">public endpoint</a> and the |
|||
<a href="https://github.com/blockstack/blockstack.js">blockstack.js</a> library, |
|||
will automatically fetch zone files from Atlas when they need to look |
|||
up data in Gaia (such as profiles and app data).</p> |
|||
|
|||
<div class="highlighter-rouge"><pre class="highlight"><code> +--------------+ +---------------+ +----------------+ |
|||
clients | Blockstack | | blockstack.js | | BNS API module | |
|||
| Browser | | | | | |
|||
+--------------+ +---------------+ +----------------+ |
|||
^ ^ ^ ^ ^ ^ |
|||
| | | | | | |
|||
| | | | | | |
|||
V | V | V | |
|||
+----------+ | +----------+ | +----------+ | |
|||
Gaia | Gaia hub | | | Gaia hub | | | Gaia hub | | |
|||
+----------+ | +----------+ | +----------+ | |
|||
| | | |
|||
| | | |
|||
V V V |
|||
+---------------------------------------------------------------+ |
|||
Atlas | Atlas Peer Network | |
|||
+----------+------+----------+-----+----------+------+----------+ |
|||
BNS | BNS node | | BNS node | | BNS node | | BNS node | |
|||
+----------+ +----------+ +----------+ +----------+ |
|||
^ ^ ^ ^ |
|||
| (indexing | | | |
|||
| blockchain) | | | |
|||
+---------------------------------------------------------------+ |
|||
Blockchain | Blockchain Peer Network | |
|||
+---------------------------------------------------------------+ |
|||
|
|||
|
|||
Figure 1: Location of Atlas in the Blockstack architecture. Each BNS node |
|||
implements an Atlas peer. An Atlas peer treats a name state value in BNS as |
|||
the hash of a DNS zone file. Atlas peers exchange zone files with one another |
|||
until they each have a full replica of all known zone files. Clients can look |
|||
up zone files for names using the name's stat value as a zone file hash. Clients |
|||
can broadcast zone files to the network if they match a previously-announced |
|||
hash. In practice, zone files store URLs to a name owner's Gaia hubs, thereby |
|||
allowing Blockstack apps to read and write data in Gaia. |
|||
</code></pre> |
|||
</div> |
|||
|
|||
<p>Nevertheless, Atlas is a general-purpose content-addressed storage |
|||
system that advanced developers can use to <strong>host data in an immutable |
|||
and durable manner.</strong> Beyond its default use-case in Blockstack, |
|||
Atlas is ideal for tasks like:</p> |
|||
|
|||
<ul> |
|||
<li>Announcing PGP public keys under a human-readable name</li> |
|||
<li>Storing package hashes for a software release</li> |
|||
<li>Securely deploying shell scripts to remote VMs</li> |
|||
<li>Binding human-readable names to Tor .onion addresses |
|||
(<a href="https://github.com/blockstack-packages/blockstack-tor">example</a>)</li> |
|||
</ul> |
|||
|
|||
<h2 id="motivation">Motivation</h2> |
|||
|
|||
<p>Atlas was designed to augment BNS. BNS allows each name to store a small |
|||
amount of state—on the order of 20 bytes. The size is so small because the |
|||
state must be recorded to a public blockchain, where the cost per byte is |
|||
high and the blockchain protocol limits the size of transactions.</p> |
|||
|
|||
<p>To compensate for this, we developed an off-chain storage system allows BNS |
|||
names to bind and store a large amount of state to each name in a way that |
|||
<em>preserves the security properties of having written that state to the |
|||
blockchain</em>. Instead of storing 20 bytes of data on the blockchain, a BNS name |
|||
owner would store the <em>cryptograhpic hash</em> of its state, and then store the actual state |
|||
Atlas. This decouples the name’s state size from the blockchain.</p> |
|||
|
|||
<p>The reference implementation of Atlas currently allows up to 40kb of state to be |
|||
bound to a BNS name, instead of a measly 20 bytes. The 40kb of data is |
|||
replicated to each BNS node, where it is stored forever.</p> |
|||
|
|||
<h2 id="feature-comparison">Feature Comparison</h2> |
|||
|
|||
<p>Atlas is not the only peer-to-peer content-addressible chunk store in existance. The following |
|||
feature table describes Atlas in relation to other popular chunk stores.</p> |
|||
|
|||
<table> |
|||
<thead> |
|||
<tr> |
|||
<th><strong>Features</strong></th> |
|||
<th>Atlas</th> |
|||
<th>BitTorrent</th> |
|||
<th><a href="https://datproject.org/">DAT</a></th> |
|||
<th><a href="https://ipfs.io">IPFS</a></th> |
|||
<th><a href="https://github.com/ethersphere/swarm">Swarm</a></th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr> |
|||
<td>Each peer stores all chunks</td> |
|||
<td>X</td> |
|||
<td>X</td> |
|||
<td> </td> |
|||
<td> </td> |
|||
<td> </td> |
|||
</tr> |
|||
<tr> |
|||
<td>Replicas are permanent [1]</td> |
|||
<td>X</td> |
|||
<td>X</td> |
|||
<td>X</td> |
|||
<td> </td> |
|||
<td> </td> |
|||
</tr> |
|||
<tr> |
|||
<td>Replicas are free</td> |
|||
<td> </td> |
|||
<td>X</td> |
|||
<td>X</td> |
|||
<td>X</td> |
|||
<td> </td> |
|||
</tr> |
|||
<tr> |
|||
<td>Sybil-resistant chunk discovery</td> |
|||
<td>X</td> |
|||
<td>X</td> |
|||
<td> </td> |
|||
<td> </td> |
|||
<td>X</td> |
|||
</tr> |
|||
<tr> |
|||
<td>Sybil-resistant peer discovery</td> |
|||
<td>X</td> |
|||
<td> </td> |
|||
<td> </td> |
|||
<td> </td> |
|||
<td> </td> |
|||
</tr> |
|||
<tr> |
|||
<td>Fixed chunk size</td> |
|||
<td>X</td> |
|||
<td> </td> |
|||
<td>X</td> |
|||
<td>X</td> |
|||
<td>X</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
|
|||
<p>[1] Here, “permanent” means that once a peer has data, they will never evict it |
|||
as part of the protocol.</p> |
|||
|
|||
<div class="share uk-text-center"> |
|||
<a href="https://twitter.com/intent/tweet?text=Overview of the Atlas network&url=https://zbabystack.netlify.com/core/auth/overview.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=https%3A%2F%2Fzbabystack.netlify.com%2Fcore%2Fauth%2Foverview.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="https://zbabystack.netlify.com/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> |
Loading…
Reference in new issue